diff -Nru meson-1.0.1/PKG-INFO meson-1.2.1/PKG-INFO --- meson-1.0.1/PKG-INFO 2023-02-23 22:09:18.121258300 +0000 +++ meson-1.2.1/PKG-INFO 2023-08-07 22:56:08.500238000 +0000 @@ -1,11 +1,12 @@ Metadata-Version: 2.1 Name: meson -Version: 1.0.1 +Version: 1.2.1 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 +Project-URL: Source, https://github.com/mesonbuild/meson Keywords: meson,mesonbuild,build system,cmake Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console diff -Nru meson-1.0.1/cross/armclang-linux.txt meson-1.2.1/cross/armclang-linux.txt --- meson-1.0.1/cross/armclang-linux.txt 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/cross/armclang-linux.txt 2023-08-07 22:54:24.000000000 +0000 @@ -17,15 +17,12 @@ [binaries] # we could set exe_wrapper = qemu-arm-static but to test the case # when cross compiled binaries can't be run we don't do that -c = '/opt/arm/developmentstudio-2019.0/sw/ARMCompiler6.12/bin/armclang' +c = ['/opt/arm/developmentstudio-2019.0/sw/ARMCompiler6.12/bin/armclang', '--target=aarch64-arm-none-eabi'] #c = '/opt/arm/developmentstudio-2019.0/sw/ARMCompiler5.06u6/bin/armcc' #cpp = '/usr/bin/arm-linux-gnueabihf-g++' ar = '/opt/arm/developmentstudio-2019.0/sw/ARMCompiler6.12/bin/armar' #strip = '/usr/arm-linux-gnueabihf/bin/strip' -#pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' - -[built-in options] -c_args = ['--target=aarch64-arm-none-eabi'] +#pkg-config = '/usr/bin/arm-linux-gnueabihf-pkg-config' [host_machine] system = 'baremetal' diff -Nru meson-1.0.1/cross/armclang.txt meson-1.2.1/cross/armclang.txt --- meson-1.0.1/cross/armclang.txt 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/cross/armclang.txt 2023-05-23 15:20:02.000000000 +0000 @@ -2,16 +2,16 @@ # to the environment(PATH) variable, so that Meson can find # the armclang, armlink and armar while building. [binaries] -c = 'armclang' -cpp = 'armclang' +c = ['armclang', '--target=arm-arm-none-eabi'] +cpp = ['armclang', '--target=arm-arm-none-eabi'] ar = 'armar' strip = 'armar' [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'] -cpp_args = ['--target=arm-arm-none-eabi', '-mcpu=cortex-m0plus'] +c_args = ['-mcpu=cortex-m0plus'] +cpp_args = ['-mcpu=cortex-m0plus'] [host_machine] system = 'bare metal' # Update with your system name - bare metal/OS. diff -Nru meson-1.0.1/cross/ccomp-armv7a.txt meson-1.2.1/cross/ccomp-armv7a.txt --- meson-1.0.1/cross/ccomp-armv7a.txt 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/cross/ccomp-armv7a.txt 2023-05-23 15:20:02.000000000 +0000 @@ -1,10 +1,10 @@ [binaries] -c = 'ccomp' +c = ['ccomp', '-target', 'armv7a-eabi'] ar = 'ccomp' strip = 'strip' [built-in options] -c_args = ['-target', 'armv7a-eabi', '-fall'] +c_args = ['-fall'] [host_machine] system = 'bare metal' # Update with your system name - bare metal/OS. diff -Nru meson-1.0.1/cross/iphone.txt meson-1.2.1/cross/iphone.txt --- meson-1.0.1/cross/iphone.txt 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/cross/iphone.txt 2023-06-28 14:48:20.000000000 +0000 @@ -1,22 +1,22 @@ # This is a cross compilation file from OSX Yosemite to iPhone # Apple keeps changing the location and names of files so -# these might not work for you. Use the googels and xcrun. +# these might not work for you. Use the googles and xcrun. [binaries] -c = 'clang' -cpp = 'clang++' -objc = 'clang' -objcpp = 'clang++' +c = ['clang', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] +cpp = ['clang++', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] +objc = ['clang', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] +objcpp = ['clang++', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] 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'] +c_args = ['-miphoneos-version-min=11.0'] +cpp_args = ['-miphoneos-version-min=11.0'] +c_link_args = ['-miphoneos-version-min=11.0'] +cpp_link_args = ['-miphoneos-version-min=11.0'] +objc_args = ['-miphoneos-version-min=11.0'] +objcpp_args = ['-miphoneos-version-min=11.0'] [properties] root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer' @@ -25,6 +25,8 @@ [host_machine] system = 'darwin' +subsystem = 'ios' +kernel = 'xnu' cpu_family = 'aarch64' cpu = 'aarch64' endian = 'little' diff -Nru meson-1.0.1/cross/linux-mingw-w64-32bit.txt meson-1.2.1/cross/linux-mingw-w64-32bit.txt --- meson-1.0.1/cross/linux-mingw-w64-32bit.txt 2021-04-01 21:13:00.000000000 +0000 +++ meson-1.2.1/cross/linux-mingw-w64-32bit.txt 2023-08-07 22:54:24.000000000 +0000 @@ -4,7 +4,7 @@ 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' +pkg-config = '/usr/bin/i686-w64-mingw32-pkg-config' windres = '/usr/bin/i686-w64-mingw32-windres' exe_wrapper = 'wine' ld = '/usr/bin/i686-w64-mingw32-ld' diff -Nru meson-1.0.1/cross/linux-mingw-w64-64bit.txt meson-1.2.1/cross/linux-mingw-w64-64bit.txt --- meson-1.0.1/cross/linux-mingw-w64-64bit.txt 2021-04-01 21:13:00.000000000 +0000 +++ meson-1.2.1/cross/linux-mingw-w64-64bit.txt 2023-08-07 22:54:24.000000000 +0000 @@ -4,9 +4,9 @@ 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' +pkg-config = '/usr/bin/x86_64-w64-mingw32-pkg-config' windres = '/usr/bin/x86_64-w64-mingw32-windres' -exe_wrapper = 'wine64' +exe_wrapper = 'wine' cmake = '/usr/bin/cmake' [properties] diff -Nru meson-1.0.1/cross/metrowerks-arm.txt meson-1.2.1/cross/metrowerks-arm.txt --- meson-1.0.1/cross/metrowerks-arm.txt 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/cross/metrowerks-arm.txt 2023-05-30 15:42:56.000000000 +0000 @@ -0,0 +1,28 @@ +# This file assumes that the path to your Metrowerks Embedded ARM +# toolchain is added to the environment(PATH) variable, so that +# Meson can find the binaries while building. + +# You should also do one of the following to ensure Meson can +# locate the .lcf linker script: +# - Add the cross directory to PATH as well +# - Edit c_link_args and cpp_link_args with the full +# path to the .lcf file on your machine + +[binaries] +c = 'mwccarm' +c_ld = 'mwldarm' +cpp = 'mwccarm' +cpp_ld = 'mwldarm' +ar = 'mwldarm' +as = 'mwasmarm' + +[built-in options] +c_args = ['-lang', 'c99', '-D_NITRO', '-nosyspath'] +c_link_args = 'metrowerks.lcf' +cpp_args = ['-lang', 'c++', '-D_NITRO', '-nosyspath'] +cpp_link_args = 'metrowerks.lcf' + +[host_machine] +system = 'bare metal' +cpu_family = 'arm' +endian = 'little' \ No newline at end of file diff -Nru meson-1.0.1/cross/metrowerks-eppc.txt meson-1.2.1/cross/metrowerks-eppc.txt --- meson-1.0.1/cross/metrowerks-eppc.txt 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/cross/metrowerks-eppc.txt 2023-05-30 15:42:56.000000000 +0000 @@ -0,0 +1,28 @@ +# This file assumes that the path to your Metrowerks toolchain +# of choice is added to the environment(PATH) variable, so that +# Meson can find the binaries while building. + +# You should also do one of the following to ensure Meson can +# locate the .lcf linker script: +# - Add the cross directory to PATH as well +# - Edit c_link_args and cpp_link_args with the full +# path to the lcf file on your machine + +[binaries] +c = 'mwcceppc' +c_ld = 'mwldeppc' +cpp = 'mwcceppc' +cpp_ld = 'mwldeppc' +ar = 'mwldeppc' +as = 'mwasmeppc' + +[built-in options] +c_args = ['-lang', 'c99', '-nosyspath'] +c_link_args = 'metrowerks.lcf' +cpp_args = ['-lang', 'c++', '-nosyspath'] +cpp_link_args = 'metrowerks.lcf' + +[host_machine] +system = 'bare metal' +cpu_family = 'ppc' +endian = 'little' \ No newline at end of file diff -Nru meson-1.0.1/cross/metrowerks.lcf meson-1.2.1/cross/metrowerks.lcf --- meson-1.0.1/cross/metrowerks.lcf 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/cross/metrowerks.lcf 2023-05-30 15:42:56.000000000 +0000 @@ -0,0 +1,18 @@ +# General-purpose linker script for Metrowerks toolchains. +# This script will link a blank application. Its only purpose +# is to allow the toolchains to run Meson tests. To link an +# actual application, you need to write your own fine-tuned lcf. + +MEMORY { + TEST (RWX) : ORIGIN=0, LENGTH=0 +} + +SECTIONS { + .TEST:{ + * (.text) + * (.data) + * (.rodata) + * (.bss) + __startup=.; + } > TEST +} \ No newline at end of file diff -Nru meson-1.0.1/cross/none.txt meson-1.2.1/cross/none.txt --- meson-1.0.1/cross/none.txt 2022-08-13 08:48:38.000000000 +0000 +++ meson-1.2.1/cross/none.txt 2023-08-07 22:54:24.000000000 +0000 @@ -15,5 +15,5 @@ objc = ['false'] objcpp = ['false'] ar = ['false'] -pkgconfig = ['false'] +pkg-config = ['false'] cmake = ['false'] diff -Nru meson-1.0.1/cross/tvos.txt meson-1.2.1/cross/tvos.txt --- meson-1.0.1/cross/tvos.txt 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/cross/tvos.txt 2023-06-28 14:48:20.000000000 +0000 @@ -1,18 +1,18 @@ # This is a cross compilation file from OSX Yosemite to Apple tvOS # Apple keeps changing the location and names of files so -# these might not work for you. Use the googels and xcrun. +# these might not work for you. Use the googles and xcrun. [binaries] -c = 'clang' -cpp = 'clang++' +c = ['clang', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk'] +cpp = ['clang++', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk'] ar = 'ar' strip = 'strip' [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'] +c_args = ['-mtvos-version-min=12.0'] +cpp_args = ['-mtvos-version-min=12.0'] +c_link_args = ['-mtvos-version-min=12.0'] +cpp_link_args = ['-mtvos-version-min=12.0'] [properties] root = '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer' @@ -22,6 +22,8 @@ [host_machine] system = 'darwin' +subsystem = 'tvos' +kernel = 'xnu' cpu_family = 'arm' cpu = 'arm64' endian = 'little' diff -Nru meson-1.0.1/cross/ubuntu-armhf.txt meson-1.2.1/cross/ubuntu-armhf.txt --- meson-1.0.1/cross/ubuntu-armhf.txt 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/cross/ubuntu-armhf.txt 2023-08-07 22:54:24.000000000 +0000 @@ -1,12 +1,12 @@ [binaries] # we could set exe_wrapper = qemu-arm-static but to test the case # when cross compiled binaries can't be run we don't do that -c = '/usr/bin/arm-linux-gnueabihf-gcc' -cpp = '/usr/bin/arm-linux-gnueabihf-g++' +c = ['/usr/bin/arm-linux-gnueabihf-gcc'] +cpp = ['/usr/bin/arm-linux-gnueabihf-g++'] rust = ['rustc', '--target', 'arm-unknown-linux-gnueabihf', '-C', 'linker=/usr/bin/arm-linux-gnueabihf-gcc-7'] ar = '/usr/arm-linux-gnueabihf/bin/ar' strip = '/usr/arm-linux-gnueabihf/bin/strip' -pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' +pkg-config = '/usr/bin/arm-linux-gnueabihf-pkg-config' ld = '/usr/bin/arm-linux/gnueabihf-ld' [built-in options] diff -Nru meson-1.0.1/data/shell-completions/zsh/_meson meson-1.2.1/data/shell-completions/zsh/_meson --- meson-1.0.1/data/shell-completions/zsh/_meson 2022-06-19 19:10:06.000000000 +0000 +++ meson-1.2.1/data/shell-completions/zsh/_meson 2023-05-23 15:20:02.000000000 +0000 @@ -74,7 +74,7 @@ 'configure:configure a project' 'dist:generate release archive' 'init:create a new project' -'install:install one more more targets' +'install:install one or more targets' 'introspect:query project properties' 'setup:set up a build directory' 'test:run tests' @@ -180,7 +180,7 @@ '--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' + '--gdb-path=[program to run for gdb (can be wrapper or compatible program)]:program:_path_commands' '--list[list available tests]' '(--wrapper --wrap)'{'--wrapper=','--wrap='}'[wrapper to run tests with]:wrapper program:_path_commands' "$__meson_cd" @@ -391,7 +391,7 @@ "$__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"' + '(-l --load-average)'{'-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)]' diff -Nru meson-1.0.1/data/syntax-highlighting/vim/ftdetect/meson.vim meson-1.2.1/data/syntax-highlighting/vim/ftdetect/meson.vim --- meson-1.0.1/data/syntax-highlighting/vim/ftdetect/meson.vim 2020-08-15 16:27:05.000000000 +0000 +++ meson-1.2.1/data/syntax-highlighting/vim/ftdetect/meson.vim 2023-05-23 15:20:02.000000000 +0000 @@ -1,3 +1,4 @@ au BufNewFile,BufRead meson.build set filetype=meson +au BufNewFile,BufRead meson.options set filetype=meson au BufNewFile,BufRead meson_options.txt set filetype=meson au BufNewFile,BufRead *.wrap set filetype=dosini diff -Nru meson-1.0.1/data/syntax-highlighting/vim/syntax/meson.vim meson-1.2.1/data/syntax-highlighting/vim/syntax/meson.vim --- meson-1.0.1/data/syntax-highlighting/vim/syntax/meson.vim 2022-06-19 19:10:06.000000000 +0000 +++ meson-1.2.1/data/syntax-highlighting/vim/syntax/meson.vim 2023-05-23 15:20:02.000000000 +0000 @@ -150,7 +150,7 @@ hi def link mesonNumber Number hi def link mesonBuiltin Function hi def link mesonBoolean Boolean -if exists("meson_space_error_higlight") +if exists("meson_space_error_highlight") hi def link mesonSpaceError Error endif diff -Nru meson-1.0.1/debian/changelog meson-1.2.1/debian/changelog --- meson-1.0.1/debian/changelog 2023-03-15 07:27:04.000000000 +0000 +++ meson-1.2.1/debian/changelog 2023-11-30 23:51:48.000000000 +0000 @@ -1,21 +1,88 @@ -meson (1.0.1-5ubuntu1) lunar; urgency=low +meson (1.2.1-3~kisak1~l) lunar; urgency=low - * Merge from Debian unstable. Remaining changes: - - skip test failing due to newer asan version + * Disable tests + * Fudge unnessicary test dependency - -- Gianfranco Costamagna Wed, 15 Mar 2023 08:27:04 +0100 + -- kisak Thu, 30 Nov 2023 18:51:48 -0500 -meson (1.0.1-5) unstable; urgency=medium +meson (1.2.1-3) unstable; urgency=medium - * Fix incorrect usage of fgetc/fputc. Closes: #1032168. + * Remove build dep to GTK 2 things. Closes: #1049376. - -- Jussi Pakkanen Sat, 11 Mar 2023 23:06:44 +0200 + -- Jussi Pakkanen Tue, 22 Aug 2023 18:00:48 +0300 + +meson (1.2.1-2) unstable; urgency=medium + + * Add debian/clean. Closes: #1045515. + + -- Jussi Pakkanen Mon, 14 Aug 2023 19:58:17 +0300 + +meson (1.2.1-1) unstable; urgency=medium + + * New upstream release. Closes: #1041454. + * Remove dep on gtk-sharp. Closes: #1041653. + + -- Jussi Pakkanen Tue, 08 Aug 2023 02:05:26 +0300 + +meson (1.2.0-1) unstable; urgency=medium + + * New upstream release. + + -- Jussi Pakkanen Sun, 16 Jul 2023 23:59:13 +0300 + +meson (1.2.0~rc3-1) experimental; urgency=medium + + * New upstream release. + + -- Jussi Pakkanen Tue, 11 Jul 2023 22:09:18 +0300 + +meson (1.2.0~rc2-1) experimental; urgency=medium + + * New upstream release. + + -- Jussi Pakkanen Wed, 05 Jul 2023 23:56:53 +0300 + +meson (1.2.0~rc1-1) experimental; urgency=medium + + * New upstream release. -meson (1.0.1-4ubuntu1) lunar; urgency=medium + -- Jussi Pakkanen Wed, 28 Jun 2023 17:53:10 +0300 - * Upload to Ubuntu with a skip of a failing test, due to newer asan version +meson (1.1.1-2) unstable; urgency=medium - -- Gianfranco Costamagna Thu, 09 Mar 2023 10:34:19 +0100 + * Reupload to unstable. + + -- Jussi Pakkanen Sun, 18 Jun 2023 19:27:41 +0300 + +meson (1.1.1-1) experimental; urgency=medium + + * New upstream release. + + -- Jussi Pakkanen Thu, 25 May 2023 21:38:39 +0300 + +meson (1.1.0-1) experimental; urgency=medium + + * New upstream release. + + -- Jussi Pakkanen Mon, 10 Apr 2023 18:41:34 +0300 + +meson (1.1.0~rc2-1) experimental; urgency=medium + + * New upstream release. + + -- Jussi Pakkanen Sun, 02 Apr 2023 22:03:53 +0300 + +meson (1.0.1-6) experimental; urgency=medium + + * CPU detection fix from Helmut Grohne. Closes: #1033579. + + -- Jussi Pakkanen Tue, 28 Mar 2023 00:18:29 +0300 + +meson (1.0.1-5) unstable; urgency=medium + + * Fix incorrect usage of fgetc/fputc. Closes: #1032168. + + -- Jussi Pakkanen Sat, 11 Mar 2023 23:06:44 +0200 meson (1.0.1-4) unstable; urgency=medium diff -Nru meson-1.0.1/debian/clean meson-1.2.1/debian/clean --- meson-1.0.1/debian/clean 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/debian/clean 2023-11-30 23:48:39.000000000 +0000 @@ -0,0 +1,2 @@ +meson.egg-info/ +meson-test-run.xml diff -Nru meson-1.0.1/debian/control meson-1.2.1/debian/control --- meson-1.0.1/debian/control 2022-09-14 22:16:45.000000000 +0000 +++ meson-1.2.1/debian/control 2023-11-30 23:51:48.000000000 +0000 @@ -2,12 +2,12 @@ Maintainer: Jussi Pakkanen Section: devel Priority: optional -Standards-Version: 4.6.1 +Standards-Version: 4.6.2 Homepage: https://mesonbuild.com X-Python3-Version: >= 3.7 Rules-Requires-Root: no Build-Depends: debhelper-compat (= 13), - python3:any (>= 3.5), + python3:any (>= 3.7), dh-exec, dh-python, python3-setuptools, @@ -43,7 +43,6 @@ bison , mono-mcs , mono-devel , - libwxgtk3.2-dev , python3-gi , gtk-doc-tools , # Rust is not needed to build Meson, only to run a part of its test @@ -73,9 +72,6 @@ libvulkan-dev , libpcap-dev , libcups2-dev , - gtk-sharp2 , - gtk-sharp2-gapi , - libglib2.0-cil-dev , libwmf-dev , git , mercurial , diff -Nru meson-1.0.1/debian/debcrossgen meson-1.2.1/debian/debcrossgen --- meson-1.0.1/debian/debcrossgen 2023-02-26 23:45:36.000000000 +0000 +++ meson-1.2.1/debian/debcrossgen 2023-11-30 23:48:39.000000000 +0000 @@ -71,7 +71,9 @@ write_args_line(ofile, 'cpp_link_args', cpp_link_args) cpu_family_map = dict(mips64el="mips64", - i686='x86') + i686='x86', + powerpc64le='ppc64', + ) cpu_map = dict(armhf="arm7hlf", mips64el="mips64", powerpc64le="ppc64", diff -Nru meson-1.0.1/debian/patches/3-debian-sysconfig-layout.patch meson-1.2.1/debian/patches/3-debian-sysconfig-layout.patch --- meson-1.0.1/debian/patches/3-debian-sysconfig-layout.patch 2022-12-29 22:19:40.000000000 +0000 +++ meson-1.2.1/debian/patches/3-debian-sysconfig-layout.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -From 9cea9e351d20d58f447b06baa7bb9a3f5cc40ea4 Mon Sep 17 00:00:00 2001 -From: Stefano Rivera -Date: Mon, 19 Dec 2022 19:56:32 -0400 -Subject: [PATCH] Update the Debian Python path detection for setuptools >= 60 - -Debian now (since Python 3.10.2-6) adds the deb_system scheme to -sysconfig. Newer distutils (such as bundled with setuptools >= 60) adds -fetch schemes from sysconfig, rather than duplicating the sysconfig -schemes statically in distutils.command.install. - -This change broke meson's deb_system check. - -This patch replaces that mechanism (for newer Debian releases) with -explicit scheme selection, which is far simpler. -But it also retains the old mechanism, for older Debian releases that -require it (Debian <= 11). - -Fixes: #8739 (for python module, and makes similar minimal changes to the python3 module) - -Fixes: https://bugs.debian.org/1026312 - -Forwarded: https://github.com/mesonbuild/meson/pull/11211 ---- - mesonbuild/modules/python.py | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - -diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py -index f74d10e4c..68632af2d 100644 ---- a/mesonbuild/modules/python.py -+++ b/mesonbuild/modules/python.py -@@ -363,15 +363,23 @@ def get_distutils_paths(scheme=None, prefix=None): - # 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. -+# Until version 3.10.2-6, Debian only patched distutils, not sysconfig. - - if 'deb_system' in distutils.command.install.INSTALL_SCHEMES: -+ # Debian systems before setuptools-bundled distutils was used by default - paths = get_distutils_paths(scheme='deb_system') - install_paths = get_distutils_paths(scheme='deb_system', prefix='') - else: -- paths = sysconfig.get_paths() -+ if 'deb_system' in sysconfig.get_scheme_names(): -+ # Use Debian's custom deb_system scheme (with our prefix) -+ scheme = 'deb_system' -+ elif sys.version_info >= (3, 10): -+ scheme = sysconfig.get_default_scheme() -+ else: -+ scheme = sysconfig._get_default_scheme() -+ paths = sysconfig.get_paths(scheme=scheme) - empty_vars = {'base': '', 'platbase': '', 'installed_base': ''} -- install_paths = sysconfig.get_paths(vars=empty_vars) -+ install_paths = sysconfig.get_paths(vars=empty_vars, scheme=scheme) - - def links_against_libpython(): - from distutils.core import Distribution, Extension --- -2.35.1 - diff -Nru meson-1.0.1/debian/patches/5-fputc.patch meson-1.2.1/debian/patches/5-fputc.patch --- meson-1.0.1/debian/patches/5-fputc.patch 2023-03-15 07:27:00.000000000 +0000 +++ meson-1.2.1/debian/patches/5-fputc.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -diff --git a/test cases/common/105 generatorcustom/gen.c b/test cases/common/105 generatorcustom/gen.c -index 59518c0ef..964ae7e9c 100644 ---- a/test cases/common/105 generatorcustom/gen.c -+++ b/test cases/common/105 generatorcustom/gen.c -@@ -22,9 +22,17 @@ int main(int argc, const char ** argv) { - fprintf(output, "#pragma once\n"); - fprintf(output, "#define "); - -- char c; -+ int bytes_copied = 0; -+ int c; - while((c = fgetc(input)) != EOF) { -- fputc(c, output); -+ if(fputc(c, output) == EOF) { -+ fprintf(stderr, "Writing to output file failed.\n"); -+ return 1; -+ } -+ if(++bytes_copied > 10000) { -+ fprintf(stderr, "File copy stuck in an eternal loop!\n"); -+ return 1; -+ } - } - fputc('\n', output); - diff -Nru meson-1.0.1/debian/patches/series meson-1.2.1/debian/patches/series --- meson-1.0.1/debian/patches/series 2023-03-15 07:26:38.000000000 +0000 +++ meson-1.2.1/debian/patches/series 2023-11-30 23:48:39.000000000 +0000 @@ -1,5 +1,2 @@ 1-disable-openmpi.patch 2-disable-rootdir-test.patch -3-debian-sysconfig-layout.patch -5-fputc.patch -skip-failing-test-in-ubuntu.patch diff -Nru meson-1.0.1/debian/patches/skip-failing-test-in-ubuntu.patch meson-1.2.1/debian/patches/skip-failing-test-in-ubuntu.patch --- meson-1.0.1/debian/patches/skip-failing-test-in-ubuntu.patch 2023-03-09 09:34:12.000000000 +0000 +++ meson-1.2.1/debian/patches/skip-failing-test-in-ubuntu.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -Description: New asan from gcc-13 is failing the test. This looks more - a toolchain change rather than a bug in meson. -Author: Gianfranco Costamagna -Last-Update: 2023-03-09 - ---- meson-1.0.1.orig/unittests/linuxliketests.py -+++ meson-1.0.1/unittests/linuxliketests.py -@@ -355,6 +355,8 @@ class LinuxlikeTests(BasePlatformTests): - - @skip_if_not_base_option('b_sanitize') - def test_generate_gir_with_address_sanitizer(self): -+ if is_linux(): -+ raise SkipTest('skipped on Ubuntu with sanitizer from gcc 13.') - if is_cygwin(): - raise SkipTest('asan not available on Cygwin') - if is_openbsd(): diff -Nru meson-1.0.1/debian/rules meson-1.2.1/debian/rules --- meson-1.0.1/debian/rules 2021-02-14 12:58:40.000000000 +0000 +++ meson-1.2.1/debian/rules 2023-11-30 23:50:38.000000000 +0000 @@ -1,5 +1,8 @@ #!/usr/bin/make -f +# PPA cheat: disable tests +export DEB_BUILD_OPTIONS=nocheck + # Print all logging info to stdout so it # shows up in build logs. export MESON_PRINT_TEST_OUTPUT=1 diff -Nru meson-1.0.1/debian/source/include-binaries meson-1.2.1/debian/source/include-binaries --- meson-1.0.1/debian/source/include-binaries 2023-03-09 09:32:28.000000000 +0000 +++ meson-1.2.1/debian/source/include-binaries 1970-01-01 00:00:00.000000000 +0000 @@ -1,207 +0,0 @@ -__pycache__/run_tests.cpython-310.pyc -__pycache__/run_unittests.cpython-310-pytest-6.2.5.pyc -dist/meson-1.0.1-py3.10.egg -mesonbuild/__pycache__/__init__.cpython-310.pyc -mesonbuild/__pycache__/_pathlib.cpython-310.pyc -mesonbuild/__pycache__/arglist.cpython-310.pyc -mesonbuild/__pycache__/build.cpython-310.pyc -mesonbuild/__pycache__/coredata.cpython-310.pyc -mesonbuild/__pycache__/depfile.cpython-310.pyc -mesonbuild/__pycache__/envconfig.cpython-310.pyc -mesonbuild/__pycache__/environment.cpython-310.pyc -mesonbuild/__pycache__/mcompile.cpython-310.pyc -mesonbuild/__pycache__/mconf.cpython-310.pyc -mesonbuild/__pycache__/mdevenv.cpython-310.pyc -mesonbuild/__pycache__/mdist.cpython-310.pyc -mesonbuild/__pycache__/mesondata.cpython-310.pyc -mesonbuild/__pycache__/mesonlib.cpython-310.pyc -mesonbuild/__pycache__/mesonmain.cpython-310.pyc -mesonbuild/__pycache__/minit.cpython-310.pyc -mesonbuild/__pycache__/minstall.cpython-310.pyc -mesonbuild/__pycache__/mintro.cpython-310.pyc -mesonbuild/__pycache__/mlog.cpython-310.pyc -mesonbuild/__pycache__/mparser.cpython-310.pyc -mesonbuild/__pycache__/msetup.cpython-310.pyc -mesonbuild/__pycache__/msubprojects.cpython-310.pyc -mesonbuild/__pycache__/mtest.cpython-310.pyc -mesonbuild/__pycache__/munstable_coredata.cpython-310.pyc -mesonbuild/__pycache__/optinterpreter.cpython-310.pyc -mesonbuild/__pycache__/programs.cpython-310.pyc -mesonbuild/__pycache__/rewriter.cpython-310.pyc -mesonbuild/ast/__pycache__/__init__.cpython-310.pyc -mesonbuild/ast/__pycache__/interpreter.cpython-310.pyc -mesonbuild/ast/__pycache__/introspection.cpython-310.pyc -mesonbuild/ast/__pycache__/postprocess.cpython-310.pyc -mesonbuild/ast/__pycache__/printer.cpython-310.pyc -mesonbuild/ast/__pycache__/visitor.cpython-310.pyc -mesonbuild/backend/__pycache__/__init__.cpython-310.pyc -mesonbuild/backend/__pycache__/backends.cpython-310.pyc -mesonbuild/backend/__pycache__/ninjabackend.cpython-310.pyc -mesonbuild/cmake/__pycache__/__init__.cpython-310.pyc -mesonbuild/cmake/__pycache__/common.cpython-310.pyc -mesonbuild/cmake/__pycache__/executor.cpython-310.pyc -mesonbuild/cmake/__pycache__/fileapi.cpython-310.pyc -mesonbuild/cmake/__pycache__/generator.cpython-310.pyc -mesonbuild/cmake/__pycache__/interpreter.cpython-310.pyc -mesonbuild/cmake/__pycache__/toolchain.cpython-310.pyc -mesonbuild/cmake/__pycache__/traceparser.cpython-310.pyc -mesonbuild/cmake/__pycache__/tracetargets.cpython-310.pyc -mesonbuild/compilers/__pycache__/__init__.cpython-310.pyc -mesonbuild/compilers/__pycache__/asm.cpython-310.pyc -mesonbuild/compilers/__pycache__/c.cpython-310.pyc -mesonbuild/compilers/__pycache__/c_function_attributes.cpython-310.pyc -mesonbuild/compilers/__pycache__/compilers.cpython-310.pyc -mesonbuild/compilers/__pycache__/cpp.cpython-310.pyc -mesonbuild/compilers/__pycache__/cs.cpython-310.pyc -mesonbuild/compilers/__pycache__/cuda.cpython-310.pyc -mesonbuild/compilers/__pycache__/cython.cpython-310.pyc -mesonbuild/compilers/__pycache__/d.cpython-310.pyc -mesonbuild/compilers/__pycache__/detect.cpython-310.pyc -mesonbuild/compilers/__pycache__/fortran.cpython-310.pyc -mesonbuild/compilers/__pycache__/java.cpython-310.pyc -mesonbuild/compilers/__pycache__/objc.cpython-310.pyc -mesonbuild/compilers/__pycache__/objcpp.cpython-310.pyc -mesonbuild/compilers/__pycache__/rust.cpython-310.pyc -mesonbuild/compilers/__pycache__/swift.cpython-310.pyc -mesonbuild/compilers/__pycache__/vala.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/__init__.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/arm.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/ccrx.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/clang.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/clike.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/compcert.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/elbrus.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/emscripten.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/gnu.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/intel.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/islinker.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/pgi.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/ti.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/visualstudio.cpython-310.pyc -mesonbuild/compilers/mixins/__pycache__/xc16.cpython-310.pyc -mesonbuild/dependencies/__pycache__/__init__.cpython-310.pyc -mesonbuild/dependencies/__pycache__/base.cpython-310.pyc -mesonbuild/dependencies/__pycache__/boost.cpython-310.pyc -mesonbuild/dependencies/__pycache__/cmake.cpython-310.pyc -mesonbuild/dependencies/__pycache__/coarrays.cpython-310.pyc -mesonbuild/dependencies/__pycache__/configtool.cpython-310.pyc -mesonbuild/dependencies/__pycache__/cuda.cpython-310.pyc -mesonbuild/dependencies/__pycache__/detect.cpython-310.pyc -mesonbuild/dependencies/__pycache__/dev.cpython-310.pyc -mesonbuild/dependencies/__pycache__/dub.cpython-310.pyc -mesonbuild/dependencies/__pycache__/factory.cpython-310.pyc -mesonbuild/dependencies/__pycache__/framework.cpython-310.pyc -mesonbuild/dependencies/__pycache__/hdf5.cpython-310.pyc -mesonbuild/dependencies/__pycache__/misc.cpython-310.pyc -mesonbuild/dependencies/__pycache__/mpi.cpython-310.pyc -mesonbuild/dependencies/__pycache__/pkgconfig.cpython-310.pyc -mesonbuild/dependencies/__pycache__/platform.cpython-310.pyc -mesonbuild/dependencies/__pycache__/qt.cpython-310.pyc -mesonbuild/dependencies/__pycache__/scalapack.cpython-310.pyc -mesonbuild/dependencies/__pycache__/ui.cpython-310.pyc -mesonbuild/dependencies/data/__pycache__/__init__.cpython-310.pyc -mesonbuild/interpreter/__pycache__/__init__.cpython-310.pyc -mesonbuild/interpreter/__pycache__/compiler.cpython-310.pyc -mesonbuild/interpreter/__pycache__/dependencyfallbacks.cpython-310.pyc -mesonbuild/interpreter/__pycache__/interpreter.cpython-310.pyc -mesonbuild/interpreter/__pycache__/interpreterobjects.cpython-310.pyc -mesonbuild/interpreter/__pycache__/mesonmain.cpython-310.pyc -mesonbuild/interpreter/__pycache__/type_checking.cpython-310.pyc -mesonbuild/interpreter/primitives/__pycache__/__init__.cpython-310.pyc -mesonbuild/interpreter/primitives/__pycache__/array.cpython-310.pyc -mesonbuild/interpreter/primitives/__pycache__/boolean.cpython-310.pyc -mesonbuild/interpreter/primitives/__pycache__/dict.cpython-310.pyc -mesonbuild/interpreter/primitives/__pycache__/integer.cpython-310.pyc -mesonbuild/interpreter/primitives/__pycache__/range.cpython-310.pyc -mesonbuild/interpreter/primitives/__pycache__/string.cpython-310.pyc -mesonbuild/interpreterbase/__pycache__/__init__.cpython-310.pyc -mesonbuild/interpreterbase/__pycache__/_unholder.cpython-310.pyc -mesonbuild/interpreterbase/__pycache__/baseobjects.cpython-310.pyc -mesonbuild/interpreterbase/__pycache__/decorators.cpython-310.pyc -mesonbuild/interpreterbase/__pycache__/disabler.cpython-310.pyc -mesonbuild/interpreterbase/__pycache__/exceptions.cpython-310.pyc -mesonbuild/interpreterbase/__pycache__/helpers.cpython-310.pyc -mesonbuild/interpreterbase/__pycache__/interpreterbase.cpython-310.pyc -mesonbuild/interpreterbase/__pycache__/operator.cpython-310.pyc -mesonbuild/linkers/__pycache__/__init__.cpython-310.pyc -mesonbuild/linkers/__pycache__/detect.cpython-310.pyc -mesonbuild/linkers/__pycache__/linkers.cpython-310.pyc -mesonbuild/modules/__pycache__/__init__.cpython-310.pyc -mesonbuild/modules/__pycache__/cmake.cpython-310.pyc -mesonbuild/modules/__pycache__/dlang.cpython-310.pyc -mesonbuild/modules/__pycache__/external_project.cpython-310.pyc -mesonbuild/modules/__pycache__/fs.cpython-310.pyc -mesonbuild/modules/__pycache__/gnome.cpython-310.pyc -mesonbuild/modules/__pycache__/i18n.cpython-310.pyc -mesonbuild/modules/__pycache__/icestorm.cpython-310.pyc -mesonbuild/modules/__pycache__/java.cpython-310.pyc -mesonbuild/modules/__pycache__/keyval.cpython-310.pyc -mesonbuild/modules/__pycache__/modtest.cpython-310.pyc -mesonbuild/modules/__pycache__/pkgconfig.cpython-310.pyc -mesonbuild/modules/__pycache__/python.cpython-310.pyc -mesonbuild/modules/__pycache__/python3.cpython-310.pyc -mesonbuild/modules/__pycache__/qt.cpython-310.pyc -mesonbuild/modules/__pycache__/qt5.cpython-310.pyc -mesonbuild/modules/__pycache__/qt6.cpython-310.pyc -mesonbuild/modules/__pycache__/simd.cpython-310.pyc -mesonbuild/modules/__pycache__/sourceset.cpython-310.pyc -mesonbuild/modules/__pycache__/wayland.cpython-310.pyc -mesonbuild/scripts/__pycache__/__init__.cpython-310.pyc -mesonbuild/scripts/__pycache__/cleantrees.cpython-310.pyc -mesonbuild/scripts/__pycache__/cmake_run_ctgt.cpython-310.pyc -mesonbuild/scripts/__pycache__/copy.cpython-310.pyc -mesonbuild/scripts/__pycache__/depfixer.cpython-310.pyc -mesonbuild/scripts/__pycache__/depscan.cpython-310.pyc -mesonbuild/scripts/__pycache__/env2mfile.cpython-310.pyc -mesonbuild/scripts/__pycache__/externalproject.cpython-310.pyc -mesonbuild/scripts/__pycache__/gettext.cpython-310.pyc -mesonbuild/scripts/__pycache__/meson_exe.cpython-310.pyc -mesonbuild/scripts/__pycache__/msgfmthelper.cpython-310.pyc -mesonbuild/scripts/__pycache__/symbolextractor.cpython-310.pyc -mesonbuild/scripts/__pycache__/test_loaded_modules.cpython-310.pyc -mesonbuild/scripts/__pycache__/uninstall.cpython-310.pyc -mesonbuild/scripts/__pycache__/vcstagger.cpython-310.pyc -mesonbuild/templates/__pycache__/__init__.cpython-310.pyc -mesonbuild/templates/__pycache__/cpptemplates.cpython-310.pyc -mesonbuild/templates/__pycache__/cstemplates.cpython-310.pyc -mesonbuild/templates/__pycache__/ctemplates.cpython-310.pyc -mesonbuild/templates/__pycache__/cudatemplates.cpython-310.pyc -mesonbuild/templates/__pycache__/dlangtemplates.cpython-310.pyc -mesonbuild/templates/__pycache__/fortrantemplates.cpython-310.pyc -mesonbuild/templates/__pycache__/javatemplates.cpython-310.pyc -mesonbuild/templates/__pycache__/mesontemplates.cpython-310.pyc -mesonbuild/templates/__pycache__/objcpptemplates.cpython-310.pyc -mesonbuild/templates/__pycache__/objctemplates.cpython-310.pyc -mesonbuild/templates/__pycache__/rusttemplates.cpython-310.pyc -mesonbuild/templates/__pycache__/samplefactory.cpython-310.pyc -mesonbuild/templates/__pycache__/sampleimpl.cpython-310.pyc -mesonbuild/templates/__pycache__/valatemplates.cpython-310.pyc -mesonbuild/utils/__pycache__/__init__.cpython-310.pyc -mesonbuild/utils/__pycache__/core.cpython-310.pyc -mesonbuild/utils/__pycache__/platform.cpython-310.pyc -mesonbuild/utils/__pycache__/posix.cpython-310.pyc -mesonbuild/utils/__pycache__/universal.cpython-310.pyc -mesonbuild/utils/__pycache__/vsenv.cpython-310.pyc -mesonbuild/wrap/__pycache__/__init__.cpython-310.pyc -mesonbuild/wrap/__pycache__/wrap.cpython-310.pyc -mesonbuild/wrap/__pycache__/wraptool.cpython-310.pyc -test cases/python/1 basic/gluon/__pycache__/__init__.cpython-310.pyc -test cases/python/1 basic/gluon/__pycache__/gluonator.cpython-310.pyc -test cases/python3/1 basic/gluon/__pycache__/__init__.cpython-310.pyc -test cases/python3/1 basic/gluon/__pycache__/gluonator.cpython-310.pyc -unittests/__pycache__/allplatformstests.cpython-310.pyc -unittests/__pycache__/baseplatformtests.cpython-310.pyc -unittests/__pycache__/darwintests.cpython-310.pyc -unittests/__pycache__/datatests.cpython-310.pyc -unittests/__pycache__/failuretests.cpython-310.pyc -unittests/__pycache__/helpers.cpython-310.pyc -unittests/__pycache__/internaltests.cpython-310.pyc -unittests/__pycache__/linuxcrosstests.cpython-310.pyc -unittests/__pycache__/linuxliketests.cpython-310.pyc -unittests/__pycache__/machinefiletests.cpython-310.pyc -unittests/__pycache__/platformagnostictests.cpython-310.pyc -unittests/__pycache__/pythontests.cpython-310.pyc -unittests/__pycache__/rewritetests.cpython-310.pyc -unittests/__pycache__/subprojectscommandtests.cpython-310.pyc -unittests/__pycache__/taptests.cpython-310.pyc -unittests/__pycache__/windowstests.cpython-310.pyc Binary files /tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/dist/meson-1.0.1-py3.10.egg and /tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/dist/meson-1.0.1-py3.10.egg differ diff -Nru meson-1.0.1/man/meson.1 meson-1.2.1/man/meson.1 --- meson-1.0.1/man/meson.1 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/man/meson.1 2023-08-07 22:54:34.000000000 +0000 @@ -1,4 +1,4 @@ -.TH MESON "1" "February 2023" "meson 1.0.1" "User Commands" +.TH MESON "1" "August 2023" "meson 1.2.1" "User Commands" .SH NAME meson - a high productivity build system .SH DESCRIPTION @@ -105,7 +105,7 @@ print the source files of the given target .TP \fB\-\-buildsystem\-files\fR -print all files that make up the build system (meson.build, meson_options.txt etc) +print all files that make up the build system (meson.build, meson.options, meson_options.txt etc) .TP \fB\-\-tests\fR print all unit tests diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/manual tests/12 wrap mirror/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/manual tests/12 wrap mirror/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/manual tests/12 wrap mirror/meson.build" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/manual tests/12 wrap mirror/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,4 +1,4 @@ project('downloader') -# this test will timeout, showing that a subdomain isn't caught as masquarading url +# this test will timeout, showing that a subdomain isn't caught as masquerading url subproject('zlib') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/manual tests/3 git wrap/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/manual tests/3 git wrap/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/manual tests/3 git wrap/meson.build" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/manual tests/3 git wrap/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,4 +1,4 @@ -project('git outcheckker', 'c') +project('git outchecker', 'c') sp = subproject('samplesubproject') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/manual tests/4 standalone binaries/readme.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/manual tests/4 standalone binaries/readme.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/manual tests/4 standalone binaries/readme.txt" 2021-11-02 19:58:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/manual tests/4 standalone binaries/readme.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -1,5 +1,5 @@ This directory shows how you can build redistributable binaries. On -OSX this menans building an app bundle and a .dmg installer. On Linux +OSX this means building an app bundle and a .dmg installer. On Linux it means building an archive that bundles its dependencies. On Windows it means building an .exe installer. diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/manual tests/6 hg wrap/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/manual tests/6 hg wrap/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/manual tests/6 hg wrap/meson.build" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/manual tests/6 hg wrap/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,4 +1,4 @@ -project('Mercurial outcheckker', 'c') +project('Mercurial outchecker', 'c') sp = subproject('samplesubproject') diff -Nru meson-1.0.1/meson.egg-info/PKG-INFO meson-1.2.1/meson.egg-info/PKG-INFO --- meson-1.0.1/meson.egg-info/PKG-INFO 2023-02-23 22:09:15.000000000 +0000 +++ meson-1.2.1/meson.egg-info/PKG-INFO 2023-08-07 22:56:03.000000000 +0000 @@ -1,11 +1,12 @@ Metadata-Version: 2.1 Name: meson -Version: 1.0.1 +Version: 1.2.1 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 +Project-URL: Source, https://github.com/mesonbuild/meson Keywords: meson,mesonbuild,build system,cmake Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console diff -Nru meson-1.0.1/meson.egg-info/SOURCES.txt meson-1.2.1/meson.egg-info/SOURCES.txt --- meson-1.0.1/meson.egg-info/SOURCES.txt 2023-02-23 22:09:15.000000000 +0000 +++ meson-1.2.1/meson.egg-info/SOURCES.txt 2023-08-07 22:56:03.000000000 +0000 @@ -23,6 +23,9 @@ cross/linux-mingw-w64-32bit.txt cross/linux-mingw-w64-64bit.json cross/linux-mingw-w64-64bit.txt +cross/metrowerks-arm.txt +cross/metrowerks-eppc.txt +cross/metrowerks.lcf cross/msp430.txt cross/none.txt cross/ownstdlib.txt @@ -141,6 +144,7 @@ mesonbuild/backend/__init__.py mesonbuild/backend/backends.py mesonbuild/backend/ninjabackend.py +mesonbuild/backend/nonebackend.py mesonbuild/backend/vs2010backend.py mesonbuild/backend/vs2012backend.py mesonbuild/backend/vs2013backend.py @@ -149,6 +153,12 @@ mesonbuild/backend/vs2019backend.py mesonbuild/backend/vs2022backend.py mesonbuild/backend/xcodebackend.py +mesonbuild/cargo/__init__.py +mesonbuild/cargo/builder.py +mesonbuild/cargo/cfg.py +mesonbuild/cargo/interpreter.py +mesonbuild/cargo/manifest.py +mesonbuild/cargo/version.py mesonbuild/cmake/__init__.py mesonbuild/cmake/common.py mesonbuild/cmake/executor.py @@ -189,6 +199,7 @@ mesonbuild/compilers/mixins/gnu.py mesonbuild/compilers/mixins/intel.py mesonbuild/compilers/mixins/islinker.py +mesonbuild/compilers/mixins/metrowerks.py mesonbuild/compilers/mixins/pgi.py mesonbuild/compilers/mixins/ti.py mesonbuild/compilers/mixins/visualstudio.py @@ -210,6 +221,7 @@ mesonbuild/dependencies/mpi.py mesonbuild/dependencies/pkgconfig.py mesonbuild/dependencies/platform.py +mesonbuild/dependencies/python.py mesonbuild/dependencies/qt.py mesonbuild/dependencies/scalapack.py mesonbuild/dependencies/ui.py @@ -242,6 +254,7 @@ mesonbuild/interpreterbase/interpreterbase.py mesonbuild/interpreterbase/operator.py mesonbuild/linkers/__init__.py +mesonbuild/linkers/base.py mesonbuild/linkers/detect.py mesonbuild/linkers/linkers.py mesonbuild/modules/__init__.py @@ -289,6 +302,8 @@ mesonbuild/scripts/itstool.py mesonbuild/scripts/meson_exe.py mesonbuild/scripts/msgfmthelper.py +mesonbuild/scripts/pycompile.py +mesonbuild/scripts/python_info.py mesonbuild/scripts/regen_checker.py mesonbuild/scripts/run_tool.py mesonbuild/scripts/scanbuild.py @@ -448,6 +463,9 @@ 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/26 cmake package prefix dir/cmakePackagePrefixDirConfig.cmake.in +test cases/cmake/26 cmake package prefix dir/meson.build +test cases/cmake/26 cmake package prefix dir/test.json 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 @@ -705,6 +723,8 @@ 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/inc3/meson.build +test cases/common/130 include order/inc3/prefer-build-dir-over-src-dir.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 @@ -724,6 +744,7 @@ 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/132 get define/test.json 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 @@ -1127,10 +1148,10 @@ 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/195 generator in subdir/com/mesonbuild/tooldir/genprog.py 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 @@ -1302,10 +1323,10 @@ 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/227 very long command line/codegen.py +test cases/common/227 very long command line/main.c +test cases/common/227 very long command line/meson.build +test cases/common/227 very long command 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 @@ -1338,9 +1359,9 @@ 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/235 invalid standard overridden to valid/main.c +test cases/common/235 invalid standard overridden to valid/meson.build +test cases/common/235 invalid standard overridden 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 @@ -1447,6 +1468,7 @@ test cases/common/259 preprocess/bar.c test cases/common/259 preprocess/foo.c test cases/common/259 preprocess/foo.h +test cases/common/259 preprocess/math.c test cases/common/259 preprocess/meson.build test cases/common/259 preprocess/src/file.map.in test cases/common/259 preprocess/src/meson.build @@ -1455,6 +1477,19 @@ 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/260 declare_dependency objects/bar.c +test cases/common/260 declare_dependency objects/foo.c +test cases/common/260 declare_dependency objects/meson.build +test cases/common/260 declare_dependency objects/prog.c +test cases/common/261 testcase clause/meson.build +test cases/common/261 testcase clause/test.json +test cases/common/262 generator chain/data.txt +test cases/common/262 generator chain/meson.build +test cases/common/262 generator chain/stage1.py +test cases/common/262 generator chain/stage2.py +test cases/common/263 default_options dict/lib.c +test cases/common/263 default_options dict/meson.build +test cases/common/263 default_options dict/meson_options.txt test cases/common/27 multiline string/meson.build test cases/common/28 try compile/invalid.c test cases/common/28 try compile/meson.build @@ -1475,6 +1510,7 @@ 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/test.json 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 @@ -1495,6 +1531,7 @@ test cases/common/4 shared/meson.build test cases/common/40 options/meson.build test cases/common/40 options/meson_options.txt +test cases/common/40 options/test.json 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 @@ -1504,11 +1541,14 @@ 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/mylicense.txt 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/sublicense1.txt +test cases/common/42 subproject/subprojects/sublib/sublicense2.txt 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 @@ -1527,6 +1567,9 @@ 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/44 pkgconfig-gen/dependencies/test2.c +test cases/common/44 pkgconfig-gen/inc1/inc1.h +test cases/common/44 pkgconfig-gen/inc2/inc2.h 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 @@ -1639,6 +1682,9 @@ 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/sub3/data/data.txt +test cases/common/59 install subdir/sub3/data/excluded.txt +test cases/common/59 install subdir/sub3/data/excluded/excluded.txt 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 @@ -1837,6 +1883,7 @@ 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/subsubsub.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 @@ -1849,6 +1896,8 @@ 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/98 subproject subdir/subprojects/subsubsub-1.0/.meson-subproject-wrap-hash.txt +test cases/common/98 subproject subdir/subprojects/subsubsub-1.0/meson.build test cases/common/99 postconf/meson.build test cases/common/99 postconf/postconf.py test cases/common/99 postconf/prog.c @@ -2160,6 +2209,10 @@ test cases/failing/129 generator host binary/test.json test cases/failing/13 array arithmetic/meson.build test cases/failing/13 array arithmetic/test.json +test cases/failing/130 invalid ast/meson.build +test cases/failing/130 invalid ast/test.json +test cases/failing/131 invalid project function/meson.build +test cases/failing/131 invalid project function/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 @@ -2369,9 +2422,9 @@ test cases/failing/74 link with shared module on osx/module.c test cases/failing/74 link with shared module on osx/prog.c test cases/failing/74 link with shared module on osx/test.json -test cases/failing/75 non ascii in ascii encoded configure file/config9.h.in -test cases/failing/75 non ascii in ascii encoded configure file/meson.build -test cases/failing/75 non ascii in ascii encoded configure file/test.json +test cases/failing/75 non-ascii in ascii encoded configure file/config9.h.in +test cases/failing/75 non-ascii in ascii encoded configure file/meson.build +test cases/failing/75 non-ascii in ascii encoded configure file/test.json test cases/failing/76 subproj dependency not-found and required/meson.build test cases/failing/76 subproj dependency not-found and required/test.json test cases/failing/77 unfound run/meson.build @@ -2391,8 +2444,8 @@ test cases/failing/81 threads dependency with version/test.json test cases/failing/82 gtest dependency with version/meson.build test cases/failing/82 gtest dependency with version/test.json -test cases/failing/83 dub libray/meson.build -test cases/failing/83 dub libray/test.json +test cases/failing/83 dub library/meson.build +test cases/failing/83 dub library/test.json test cases/failing/84 dub executable/meson.build test cases/failing/84 dub executable/test.json test cases/failing/85 dub compiler/meson.build @@ -2491,6 +2544,12 @@ 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/22 extract_objects/bar.f90 +test cases/fortran/22 extract_objects/foo1.f90 +test cases/fortran/22 extract_objects/foo2.f90 +test cases/fortran/22 extract_objects/meson.build +test cases/fortran/23 preprocess/main.f90 +test cases/fortran/23 preprocess/meson.build 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 @@ -2983,6 +3042,9 @@ test cases/nasm/1 configure file/meson.build test cases/nasm/2 asm language/hello.asm test cases/nasm/2 asm language/meson.build +test cases/nasm/3 nasm only/dummy.asm +test cases/nasm/3 nasm only/dummy.def +test cases/nasm/3 nasm only/meson.build test cases/native/1 trivial/meson.build test cases/native/1 trivial/trivial.c test cases/native/2 global arg/meson.build @@ -3075,11 +3137,14 @@ test cases/python/1 basic/subdir/subprog.py test cases/python/2 extmodule/blaster.py.in test cases/python/2 extmodule/meson.build +test cases/python/2 extmodule/meson_options.txt 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/2 extmodule/subinst/printer.py +test cases/python/2 extmodule/subinst/submod/printer.py test cases/python/3 cython/cytest.py test cases/python/3 cython/meson.build test cases/python/3 cython/libdir/cstorer.pxd @@ -3107,6 +3172,7 @@ test cases/python/7 install path/structured/alpha/three.py test cases/python/7 install path/structured/alpha/two.py test cases/python/7 install path/structured/beta/one.py +test cases/python/7 install path/target/meson.build test cases/python/8 different python versions/blaster.py test cases/python/8 different python versions/meson.build test cases/python/8 different python versions/meson_options.txt @@ -3238,6 +3304,11 @@ test cases/rust/2 sharedlib/stuff.rs test cases/rust/2 sharedlib/test.json test cases/rust/2 sharedlib/value.c +test cases/rust/20 rust and cpp/lib.cpp +test cases/rust/20 rust and cpp/lib.hpp +test cases/rust/20 rust and cpp/main.rs +test cases/rust/20 rust and cpp/meson.build +test cases/rust/20 rust and cpp/test.json test cases/rust/3 staticlib/meson.build test cases/rust/3 staticlib/other.rs test cases/rust/3 staticlib/prog.rs @@ -3250,6 +3321,7 @@ test cases/rust/4 polyglot/test.json test cases/rust/5 polyglot static/clib.c test cases/rust/5 polyglot static/meson.build +test cases/rust/5 polyglot static/overflow_size_checks.py test cases/rust/5 polyglot static/prog.c test cases/rust/5 polyglot static/stuff.rs test cases/rust/5 polyglot static/test.json @@ -3264,9 +3336,11 @@ 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/helper.rs 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/rust/9 unit tests/test3.rs test cases/swift/1 exe/main.swift test cases/swift/1 exe/meson.build test cases/swift/2 multifile/libfile.swift @@ -3307,37 +3381,53 @@ 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 relative find program/foo.py -test cases/unit/100 relative find program/meson.build -test cases/unit/100 relative find program/subdir/meson.build -test cases/unit/101 rlib linkage/lib2.rs -test cases/unit/101 rlib linkage/main.rs -test cases/unit/101 rlib linkage/meson.build -test cases/unit/102 python without pkgconfig/meson.build -test cases/unit/103 strip/lib.c -test cases/unit/103 strip/meson.build -test cases/unit/104 debug function/meson.build -test cases/unit/105 pkgconfig relocatable with absolute path/meson.build -test cases/unit/106 subproject symlink/cp.py -test cases/unit/106 subproject symlink/main.c -test cases/unit/106 subproject symlink/meson.build -test cases/unit/106 subproject symlink/symlinked_subproject/meson.build -test cases/unit/106 subproject symlink/symlinked_subproject/src.c -test cases/unit/106 subproject symlink/symlinked_subproject/datadir/datafile -test cases/unit/106 subproject symlink/symlinked_subproject/datadir/meson.build -test cases/unit/107 new subproject on reconfigure/meson.build -test cases/unit/107 new subproject on reconfigure/meson_options.txt -test cases/unit/107 new subproject on reconfigure/subprojects/foo/foo.c -test cases/unit/107 new subproject on reconfigure/subprojects/foo/meson.build -test cases/unit/108 configure same noop/meson.build -test cases/unit/108 configure same noop/meson_options.txt -test cases/unit/109 freeze/freeze.c -test cases/unit/109 freeze/meson.build +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/104 strip/lib.c +test cases/unit/104 strip/meson.build +test cases/unit/105 debug function/meson.build +test cases/unit/106 pkgconfig relocatable with absolute path/meson.build +test cases/unit/107 subproject symlink/cp.py +test cases/unit/107 subproject symlink/main.c +test cases/unit/107 subproject symlink/meson.build +test cases/unit/107 subproject symlink/symlinked_subproject/meson.build +test cases/unit/107 subproject symlink/symlinked_subproject/src.c +test cases/unit/107 subproject symlink/symlinked_subproject/datadir/datafile +test cases/unit/107 subproject symlink/symlinked_subproject/datadir/meson.build +test cases/unit/108 new subproject on reconfigure/meson.build +test cases/unit/108 new subproject on reconfigure/meson_options.txt +test cases/unit/108 new subproject on reconfigure/subprojects/foo/foo.c +test cases/unit/108 new subproject on reconfigure/subprojects/foo/meson.build +test cases/unit/109 configure same noop/meson.build +test cases/unit/109 configure same noop/meson_options.txt 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 -test cases/unit/110 classpath/meson.build -test cases/unit/110 classpath/com/mesonbuild/Simple.java +test cases/unit/110 freeze/freeze.c +test cases/unit/110 freeze/meson.build +test cases/unit/110 replace unencodable xml chars/meson.build +test cases/unit/110 replace unencodable xml chars/script.py +test cases/unit/111 classpath/meson.build +test cases/unit/111 classpath/com/mesonbuild/Simple.java +test cases/unit/112 list build options/meson.build +test cases/unit/112 list build options/meson_options.txt +test cases/unit/113 complex link cases/main.c +test cases/unit/113 complex link cases/meson.build +test cases/unit/113 complex link cases/s1.c +test cases/unit/113 complex link cases/s2.c +test cases/unit/113 complex link cases/s3.c +test cases/unit/114 empty project/expected_mods.json +test cases/unit/114 empty project/meson.build +test cases/unit/115 genvslite/main.cpp +test cases/unit/115 genvslite/meson.build test cases/unit/12 promote/meson.build test cases/unit/12 promote/subprojects/s1/meson.build test cases/unit/12 promote/subprojects/s1/s1.c @@ -3468,6 +3558,7 @@ test cases/unit/38 pkgconfig format/somelib.c test cases/unit/38 pkgconfig format/someret.c test cases/unit/39 external, internal library rpath/built library/bar.c +test cases/unit/39 external, internal library rpath/built library/foo.py test cases/unit/39 external, internal library rpath/built library/meson.build test cases/unit/39 external, internal library rpath/built library/meson_options.txt test cases/unit/39 external, internal library rpath/built library/prog.c @@ -3756,62 +3847,65 @@ test cases/unit/90 devenv/test-devenv.py test cases/unit/90 devenv/subprojects/sub/foo.c test cases/unit/90 devenv/subprojects/sub/meson.build -test cases/unit/91 install skip subprojects/foo.c -test cases/unit/91 install skip subprojects/foo.dat -test cases/unit/91 install skip subprojects/foo.h -test cases/unit/91 install skip subprojects/meson.build -test cases/unit/91 install skip subprojects/foo/foofile -test cases/unit/91 install skip subprojects/subprojects/bar/bar.c -test cases/unit/91 install skip subprojects/subprojects/bar/bar.dat -test cases/unit/91 install skip subprojects/subprojects/bar/bar.h -test cases/unit/91 install skip subprojects/subprojects/bar/meson.build -test cases/unit/91 install skip subprojects/subprojects/bar/bar/barfile -test cases/unit/92 new subproject in configured project/meson.build -test cases/unit/92 new subproject in configured project/meson_options.txt -test cases/unit/92 new subproject in configured project/subprojects/sub/foo.c -test cases/unit/92 new subproject in configured project/subprojects/sub/meson.build -test cases/unit/93 clangformat/.clang-format -test cases/unit/93 clangformat/.clang-format-ignore -test cases/unit/93 clangformat/.clang-format-include -test cases/unit/93 clangformat/meson.build -test cases/unit/93 clangformat/not-included/badformat.cpp -test cases/unit/93 clangformat/src/badformat.c -test cases/unit/93 clangformat/src/badformat.cpp -test cases/unit/94 custominc/helper.c -test cases/unit/94 custominc/meson.build -test cases/unit/94 custominc/prog.c -test cases/unit/94 custominc/prog2.c -test cases/unit/94 custominc/easytogrepfor/genh.py -test cases/unit/94 custominc/easytogrepfor/meson.build -test cases/unit/95 implicit force fallback/meson.build -test cases/unit/95 implicit force fallback/subprojects/something/meson.build -test cases/unit/96 compiler.links file arg/meson.build -test cases/unit/96 compiler.links file arg/test.c -test cases/unit/97 link full name/.gitignore -test cases/unit/97 link full name/libtestprovider/meson.build -test cases/unit/97 link full name/libtestprovider/provider.c -test cases/unit/97 link full name/proguser/meson.build -test cases/unit/97 link full name/proguser/receiver.c -test cases/unit/98 install all targets/bar-custom.txt -test cases/unit/98 install all targets/bar-devel.h -test cases/unit/98 install all targets/bar-notag.txt -test cases/unit/98 install all targets/foo.in -test cases/unit/98 install all targets/foo1-devel.h -test cases/unit/98 install all targets/lib.c -test cases/unit/98 install all targets/main.c -test cases/unit/98 install all targets/meson.build -test cases/unit/98 install all targets/script.py -test cases/unit/98 install all targets/custom_files/data.txt -test cases/unit/98 install all targets/subdir/bar2-devel.h -test cases/unit/98 install all targets/subdir/foo2.in -test cases/unit/98 install all targets/subdir/foo3-devel.h -test cases/unit/98 install all targets/subdir/lib.c -test cases/unit/98 install all targets/subdir/main.c -test cases/unit/98 install all targets/subdir/meson.build -test cases/unit/98 install all targets/subdir/script.py -test cases/unit/99 custom target name/file.txt.in -test cases/unit/99 custom target name/meson.build -test cases/unit/99 custom target name/subdir/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/excludes/excluded.txt +test cases/unit/99 install all targets/excludes/installed.txt +test cases/unit/99 install all targets/excludes/excluded/placeholder.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/unit/99 install all targets/subprojects/subproject/aaa.txt +test cases/unit/99 install all targets/subprojects/subproject/bbb.txt +test cases/unit/99 install all targets/subprojects/subproject/meson.build test cases/vala/1 basic/meson.build test cases/vala/1 basic/prog.vala test cases/vala/10 mixed sources/meson.build @@ -3952,6 +4046,12 @@ test cases/warning/7 module without unstable/test.json test cases/warning/8 target with no sources/meson.build test cases/warning/8 target with no sources/test.json +test cases/warning/9 meson.options/meson.build +test cases/warning/9 meson.options/meson.options +test cases/warning/9 meson.options/test.json +test cases/warning/9 meson.options/subprojects/no-warn/meson.build +test cases/warning/9 meson.options/subprojects/no-warn/meson.options +test cases/warning/9 meson.options/subprojects/no-warn/meson_options.txt test cases/wasm/1 basic/hello.c test cases/wasm/1 basic/hello.cpp test cases/wasm/1 basic/hello.html @@ -4086,6 +4186,7 @@ tools/run_with_cov.py unittests/allplatformstests.py unittests/baseplatformtests.py +unittests/cargotests.py unittests/darwintests.py unittests/datatests.py unittests/failuretests.py diff -Nru meson-1.0.1/mesonbuild/arglist.py meson-1.2.1/mesonbuild/arglist.py --- meson-1.0.1/mesonbuild/arglist.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/arglist.py 2023-06-28 14:48:20.000000000 +0000 @@ -22,7 +22,7 @@ import typing as T if T.TYPE_CHECKING: - from .linkers import StaticLinker + from .linkers.linkers import StaticLinker from .compilers import Compiler # execinfo is a compiler lib on BSD @@ -198,13 +198,13 @@ """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 + 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: + # defined by what comes _after_ it. Thus deduping this: # -D FOO -D BAR # would yield either # -D FOO BAR diff -Nru meson-1.0.1/mesonbuild/ast/interpreter.py meson-1.2.1/mesonbuild/ast/interpreter.py --- meson-1.0.1/mesonbuild/ast/interpreter.py 2022-10-24 19:25:24.000000000 +0000 +++ meson-1.2.1/mesonbuild/ast/interpreter.py 2023-05-23 15:20:02.000000000 +0000 @@ -352,7 +352,7 @@ return None # Loop detected id_loop_detect += [node.ast_id] - # Try to evealuate the value of the node + # Try to evaluate the value of the node if isinstance(node, IdNode): result = quick_resolve(node) @@ -421,7 +421,7 @@ else: args = [args_raw] - flattend_args = [] # type: T.List[TYPE_nvar] + flattened_args = [] # type: T.List[TYPE_nvar] # Resolve the contents of args for i in args: @@ -430,18 +430,18 @@ if resolved is not None: if not isinstance(resolved, list): resolved = [resolved] - flattend_args += resolved + flattened_args += resolved elif isinstance(i, (str, bool, int, float)) or include_unknown_args: - flattend_args += [i] - return flattend_args + flattened_args += [i] + return flattened_args def flatten_kwargs(self, kwargs: T.Dict[str, TYPE_nvar], include_unknown_args: bool = False) -> T.Dict[str, TYPE_nvar]: - flattend_kwargs = {} + flattened_kwargs = {} for key, val in kwargs.items(): if isinstance(val, BaseNode): resolved = self.resolve_node(val, include_unknown_args) if resolved is not None: - flattend_kwargs[key] = resolved + flattened_kwargs[key] = resolved elif isinstance(val, (str, bool, int, float)) or include_unknown_args: - flattend_kwargs[key] = val - return flattend_kwargs + flattened_kwargs[key] = val + return flattened_kwargs diff -Nru meson-1.0.1/mesonbuild/ast/introspection.py meson-1.2.1/mesonbuild/ast/introspection.py --- meson-1.0.1/mesonbuild/ast/introspection.py 2023-02-01 21:43:18.000000000 +0000 +++ meson-1.2.1/mesonbuild/ast/introspection.py 2023-07-05 15:40:06.000000000 +0000 @@ -76,7 +76,6 @@ self.environment = env 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 = {OptionKey('backend'): self.backend} self.project_data = {} # type: T.Dict[str, T.Any] @@ -113,9 +112,12 @@ proj_vers = 'undefined' self.project_data = {'descriptive_name': proj_name, 'version': proj_vers} - if os.path.exists(self.option_file): + optfile = os.path.join(self.source_root, self.subdir, 'meson.options') + if not os.path.exists(optfile): + optfile = os.path.join(self.source_root, self.subdir, 'meson_options.txt') + if os.path.exists(optfile): oi = optinterpreter.OptionInterpreter(self.subproject) - oi.process(self.option_file) + oi.process(optfile) self.coredata.update_project_options(oi.options) def_opts = self.flatten_args(kwargs.get('default_options', [])) @@ -179,7 +181,7 @@ lang = lang.lower() if lang not in self.coredata.compilers[for_machine]: try: - comp = detect_compiler_for(self.environment, lang, for_machine) + comp = detect_compiler_for(self.environment, lang, for_machine, True) except mesonlib.MesonException: # do we even care about introspecting this language? if required: @@ -261,9 +263,9 @@ # 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))] + elementary_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: + if elementary_nodes: res += [curr] return res @@ -278,10 +280,10 @@ objects = [] # type: T.List[T.Any] empty_sources = [] # type: T.List[T.Any] # Passing the unresolved sources list causes errors + kwargs_reduced['_allow_no_sources'] = True target = targetclass(name, self.subdir, self.subproject, for_machine, empty_sources, [], objects, self.environment, self.coredata.compilers[for_machine], kwargs_reduced) - target.process_compilers() - target.process_compilers_late([]) + target.process_compilers_late() new_target = { 'name': target.get_basename(), diff -Nru meson-1.0.1/mesonbuild/ast/postprocess.py meson-1.2.1/mesonbuild/ast/postprocess.py --- meson-1.0.1/mesonbuild/ast/postprocess.py 2022-10-24 19:25:13.000000000 +0000 +++ meson-1.2.1/mesonbuild/ast/postprocess.py 2023-05-23 15:20:02.000000000 +0000 @@ -16,7 +16,7 @@ # or an interpreter-based tool from __future__ import annotations -from . import AstVisitor +from .visitor import AstVisitor import typing as T if T.TYPE_CHECKING: diff -Nru meson-1.0.1/mesonbuild/ast/printer.py meson-1.2.1/mesonbuild/ast/printer.py --- meson-1.0.1/mesonbuild/ast/printer.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/ast/printer.py 2023-05-23 15:20:02.000000000 +0000 @@ -17,7 +17,7 @@ from __future__ import annotations from .. import mparser -from . import AstVisitor +from .visitor import AstVisitor import re import typing as T diff -Nru meson-1.0.1/mesonbuild/backend/backends.py meson-1.2.1/mesonbuild/backend/backends.py --- meson-1.0.1/mesonbuild/backend/backends.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/backend/backends.py 2023-08-07 22:54:34.000000000 +0000 @@ -46,7 +46,7 @@ from ..compilers import Compiler from ..environment import Environment from ..interpreter import Interpreter, Test - from ..linkers import StaticLinker + from ..linkers.linkers import StaticLinker from ..mesonlib import FileMode, FileOrString from typing_extensions import TypedDict @@ -251,6 +251,16 @@ elif backend == 'xcode': from . import xcodebackend return xcodebackend.XCodeBackend(build, interpreter) + elif backend == 'none': + from . import nonebackend + return nonebackend.NoneBackend(build, interpreter) + return None + + +def get_genvslite_backend(genvsname: str, build: T.Optional[build.Build] = None, interpreter: T.Optional['Interpreter'] = None) -> T.Optional['Backend']: + if genvsname == 'vs2022': + from . import vs2022backend + return vs2022backend.Vs2022Backend(build, interpreter, gen_lite = True) return None # This class contains the basic functionality that is needed by all backends. @@ -258,6 +268,7 @@ class Backend: environment: T.Optional['Environment'] + name = '' def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional['Interpreter']): # Make it possible to construct a dummy backend @@ -269,7 +280,6 @@ self.interpreter = interpreter self.environment = build.environment 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(), @@ -277,14 +287,22 @@ self.src_to_build = mesonlib.relpath(self.environment.get_build_dir(), self.environment.get_source_dir()) - def generate(self) -> None: + # If requested via 'capture = True', returns captured compile args per + # target (e.g. captured_args[target]) that can be used later, for example, + # to populate things like intellisense fields in generated visual studio + # projects (as is the case when using '--genvslite'). + # + # 'vslite_ctx' is only provided when + # we expect this backend setup/generation to make use of previously captured + # compile args (as is the case when using '--genvslite'). + def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: raise RuntimeError(f'generate is not implemented in {type(self).__name__}') def get_target_filename(self, t: T.Union[build.Target, build.CustomTargetIndex], *, warn_multi_output: bool = True) -> str: if isinstance(t, build.CustomTarget): 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.') + f'Using the first one. Consider using `{t.name}[0]`.') filename = t.get_outputs()[0] elif isinstance(t, build.CustomTargetIndex): filename = t.get_outputs()[0] @@ -496,7 +514,8 @@ feed: T.Optional[bool] = None, env: T.Optional[build.EnvironmentVariables] = None, tag: T.Optional[str] = None, - verbose: bool = False) -> 'ExecutableSerialisation': + verbose: bool = False, + installdir_map: T.Optional[T.Dict[str, str]] = None) -> '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 @@ -557,7 +576,7 @@ workdir = workdir or self.environment.get_build_dir() return ExecutableSerialisation(exe_cmd + cmd_args, env, exe_wrapper, workdir, - extra_paths, capture, feed, tag, verbose) + extra_paths, capture, feed, tag, verbose, installdir_map) 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]], @@ -630,7 +649,7 @@ if isinstance(exe, (programs.ExternalProgram, build.BuildTarget, build.CustomTarget)): - basename = exe.name + basename = os.path.basename(exe.name) elif isinstance(exe, mesonlib.File): basename = os.path.basename(exe.fname) else: @@ -733,8 +752,10 @@ @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() + srcdir = self.environment.get_source_dir() + for dep in target.external_deps: - if not isinstance(dep, (dependencies.ExternalLibrary, dependencies.PkgConfigDependency)): + if dep.type_name not in {'library', 'pkgconfig'}: continue for libpath in dep.link_args: # For all link args that are absolute paths to a library file, add RPATH args @@ -748,11 +769,18 @@ 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']: + # emulate rpaths by setting PATH + # .dll is there for mingw gcc + 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:] + + try: + commonpath = os.path.commonpath((libdir, srcdir)) + except ValueError: # when paths are on different drives on Windows + commonpath = '' + + if commonpath == srcdir: + rel_to_src = libdir[len(srcdir) + 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: @@ -830,6 +858,8 @@ def _determine_ext_objs(self, extobj: 'build.ExtractedObjects', proj_dir_to_build_root: str) -> T.List[str]: result: T.List[str] = [] + targetdir = self.get_target_private_dir(extobj.target) + # Merge sources and generated sources raw_sources = list(extobj.srclist) for gensrc in extobj.genlist: @@ -846,12 +876,18 @@ elif self.environment.is_object(s): result.append(s.relative_name()) + # MSVC generate an object file for PCH + if extobj.pch: + for lang, pch in extobj.target.pch.items(): + compiler = extobj.target.compilers[lang] + if compiler.get_argument_syntax() == 'msvc': + objname = self.get_msvc_pch_objname(lang, pch) + result.append(os.path.join(proj_dir_to_build_root, targetdir, objname)) + # extobj could contain only objects and no sources if not sources: return result - targetdir = self.get_target_private_dir(extobj.target) - # 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. @@ -886,6 +922,12 @@ args += compiler.get_pch_use_args(pchpath, p[0]) return includeargs + args + def get_msvc_pch_objname(self, lang: str, pch: T.List[str]) -> str: + if len(pch) == 1: + # Same name as in create_msvc_pch_implementation() below. + return f'meson_pch-{lang}.obj' + return os.path.splitext(pch[1])[0] + '.obj' + 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. @@ -903,6 +945,12 @@ mesonlib.replace_if_different(pch_file, pch_file_tmp) return pch_rel_to_build + def target_uses_pch(self, target: build.BuildTarget) -> bool: + try: + return T.cast('bool', target.get_option(OptionKey('b_pch'))) + except KeyError: + return False + @staticmethod def escape_extra_args(args: T.List[str]) -> T.List[str]: # all backslashes in defines are doubly-escaped @@ -993,7 +1041,8 @@ continue if compiler.language == 'vala': - if isinstance(dep, dependencies.PkgConfigDependency): + if dep.type_name == 'pkgconfig': + assert isinstance(dep, dependencies.ExternalDependency) if dep.name == 'glib-2.0' and dep.version_reqs is not None: for req in dep.version_reqs: if req.startswith(('>=', '==')): @@ -1049,6 +1098,57 @@ paths.update(cc.get_library_dirs(self.environment)) return list(paths) + @classmethod + @lru_cache(maxsize=None) + def extract_dll_paths(cls, target: build.BuildTarget) -> T.Set[str]: + """Find paths to all DLLs needed for a given target, since + we link against import libs, and we don't know the actual + path of the DLLs. + + 1. If there are DLLs in the same directory than the .lib dir, use it + 2. If there is a sibbling directory named 'bin' with DLLs in it, use it + """ + results = set() + for dep in target.external_deps: + + if dep.type_name == 'pkgconfig': + # If by chance pkg-config knows the bin dir... + bindir = dep.get_pkgconfig_variable('bindir', [], default='') + if bindir: + results.add(bindir) + + for link_arg in dep.link_args: + if link_arg.startswith(('-l', '-L')): + link_arg = link_arg[2:] + p = Path(link_arg) + if not p.is_absolute(): + continue + + try: + p = p.resolve(strict=True) + except FileNotFoundError: + continue + + for _ in p.parent.glob('*.dll'): + # path contains dlls + results.add(str(p.parent)) + break + + else: + if p.is_file(): + p = p.parent + # Heuristic: replace *last* occurence of '/lib' + binpath = Path('/bin'.join(p.as_posix().rsplit('/lib', maxsplit=1))) + for _ in binpath.glob('*.dll'): + results.add(str(binpath)) + break + + for i in chain(target.link_targets, target.link_whole_targets): + if isinstance(i, build.BuildTarget): + results.update(cls.extract_dll_paths(i)) + + return results + 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]: @@ -1063,8 +1163,8 @@ if isinstance(target, build.BuildTarget): prospectives.update(target.get_transitive_link_deps()) # External deps - 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))) + result.update(self.extract_dll_paths(target)) + for bdep in extra_bdeps: prospectives.add(bdep) if isinstance(bdep, build.BuildTarget): @@ -1115,6 +1215,11 @@ if isinstance(exe, build.CustomTarget): extra_bdeps = list(exe.get_transitive_build_target_deps()) extra_paths = self.determine_windows_extra_paths(exe, extra_bdeps) + for a in t.cmd_args: + if isinstance(a, build.BuildTarget): + for p in self.determine_windows_extra_paths(a, []): + if p not in extra_paths: + extra_paths.append(p) else: extra_paths = [] @@ -1127,8 +1232,6 @@ 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)) @@ -1187,11 +1290,19 @@ return outputs def generate_depmf_install(self, d: InstallData) -> None: - if self.build.dep_manifest_name is None: - return + depmf_path = self.build.dep_manifest_name + if depmf_path is None: + option_dir = self.environment.coredata.get_option(OptionKey('licensedir')) + assert isinstance(option_dir, str), 'for mypy' + if option_dir: + depmf_path = os.path.join(option_dir, 'depmf.json') + else: + 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) - out_name = os.path.join('{prefix}', self.build.dep_manifest_name) + ofilename = os.path.join(self.environment.get_prefix(), depmf_path) + odirname = os.path.join(self.environment.get_prefix(), os.path.dirname(depmf_path)) + out_name = os.path.join('{prefix}', depmf_path) + out_dir = os.path.join('{prefix}', os.path.dirname(depmf_path)) 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: @@ -1199,6 +1310,12 @@ # Copy file from, to, and with mode unchanged d.data.append(InstallDataBase(ifilename, ofilename, out_name, None, '', tag='devel', data_type='depmf')) + for m in self.build.dep_manifest.values(): + for ifilename, name in m.license_files: + ofilename = os.path.join(odirname, name.relative_name()) + out_name = os.path.join(out_dir, name.relative_name()) + d.data.append(InstallDataBase(ifilename, ofilename, out_name, None, + m.subproject, tag='devel', data_type='depmf')) def get_regen_filelist(self) -> T.List[str]: '''List of all files whose alteration means that the build @@ -1494,7 +1611,6 @@ mlog.log(f'Running postconf script {name!r}') run_exe(s, env) - @lru_cache(maxsize=1) def create_install_data(self) -> InstallData: strip_bin = self.environment.lookup_binary_entry(MachineChoice.HOST, 'strip') if strip_bin is None: diff -Nru meson-1.0.1/mesonbuild/backend/ninjabackend.py meson-1.2.1/mesonbuild/backend/ninjabackend.py --- meson-1.0.1/mesonbuild/backend/ninjabackend.py 2023-02-23 22:07:04.000000000 +0000 +++ meson-1.2.1/mesonbuild/backend/ninjabackend.py 2023-08-07 22:54:34.000000000 +0000 @@ -30,16 +30,15 @@ from . import backends from .. import modules -from ..modules import gnome from .. import environment, mesonlib from .. import build from .. import mlog from .. import compilers from ..arglist import CompilerArgs from ..compilers import Compiler -from ..linkers import ArLinker, RSPFileSyntax +from ..linkers import ArLikeLinker, RSPFileSyntax from ..mesonlib import ( - File, LibType, MachineChoice, MesonException, OrderedSet, PerMachine, + File, LibType, MachineChoice, MesonBugException, MesonException, OrderedSet, PerMachine, ProgressBar, quote_arg ) from ..mesonlib import get_compiler_for_source, has_path_sep, OptionKey @@ -50,12 +49,13 @@ from typing_extensions import Literal from .._typing import ImmutableListProtocol - from ..build import ExtractedObjects + from ..build import ExtractedObjects, LibTypes from ..interpreter import Interpreter - from ..linkers import DynamicLinker, StaticLinker + from ..linkers.linkers import DynamicLinker, StaticLinker from ..compilers.cs import CsCompiler from ..compilers.fortran import FortranCompiler + CommandArgOrStr = T.List[T.Union['NinjaCommandArg', str]] RUST_EDITIONS = Literal['2015', '2018', '2021'] @@ -64,20 +64,20 @@ 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): +def cmd_quote(arg: str) -> str: # 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) + arg = re.sub(r'(\\*)"', lambda m: '\\' * (len(m.group(1)) * 2 + 1) + '"', arg) # any terminal backslashes likewise need doubling - s = re.sub(r'(\\*)$', lambda m: '\\' * (len(m.group(1)) * 2), s) + arg = re.sub(r'(\\*)$', lambda m: '\\' * (len(m.group(1)) * 2), arg) # and double quote - s = f'"{s}"' + arg = f'"{arg}"' - return s + return arg -def gcc_rsp_quote(s): +def gcc_rsp_quote(s: str) -> str: # see: the function buildargv() in libiberty # # this differs from sh-quoting in that a backslash *always* escapes the @@ -99,7 +99,7 @@ rmfile_prefix = ['rm', '-f', '{}', '&&'] -def get_rsp_threshold(): +def get_rsp_threshold() -> int: '''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.''' @@ -114,7 +114,7 @@ # single argument; see MAX_ARG_STRLEN limit = 131072 # Be conservative - limit = limit / 2 + limit = limit // 2 return int(os.environ.get('MESON_RSP_THRESHOLD', limit)) # a conservative estimate of the command-line length limit @@ -129,7 +129,7 @@ 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: +def ninja_quote(text: str, is_build_line: bool = False) -> str: if is_build_line: quote_re = NINJA_QUOTE_BUILD_PAT else: @@ -159,22 +159,22 @@ none = 3 class NinjaCommandArg: - def __init__(self, s, quoting = Quoting.both): + def __init__(self, s: str, quoting: Quoting = Quoting.both) -> None: self.s = s self.quoting = quoting - def __str__(self): + def __str__(self) -> str: return self.s @staticmethod - def list(l, q): + def list(l: str, q: Quoting) -> T.List[NinjaCommandArg]: return [NinjaCommandArg(i, q) for i in l] +@dataclass class NinjaComment: - def __init__(self, comment): - self.comment = comment + comment: str - def write(self, outfile): + def write(self, outfile: T.TextIO) -> None: for l in self.comment.split('\n'): outfile.write('# ') outfile.write(l) @@ -182,11 +182,12 @@ outfile.write('\n') class NinjaRule: - def __init__(self, rule, command, args, description, - rspable = False, deps = None, depfile = None, extra = None, + def __init__(self, rule: str, command: CommandArgOrStr, args: CommandArgOrStr, + description: str, rspable: bool = False, deps: T.Optional[str] = None, + depfile: T.Optional[str] = None, extra: T.Optional[str] = None, rspfile_quote_style: RSPFileSyntax = RSPFileSyntax.GCC): - def strToCommandArg(c): + def strToCommandArg(c: T.Union[NinjaCommandArg, str]) -> NinjaCommandArg: if isinstance(c, NinjaCommandArg): return c @@ -209,8 +210,8 @@ return NinjaCommandArg(c) self.name = rule - self.command = [strToCommandArg(c) for c in command] # includes args which never go into a rspfile - self.args = [strToCommandArg(a) for a in args] # args which will go into a rspfile, if used + self.command: T.List[NinjaCommandArg] = [strToCommandArg(c) for c in command] # includes args which never go into a rspfile + self.args: T.List[NinjaCommandArg] = [strToCommandArg(a) for a in args] # args which will go into a rspfile, if used self.description = description self.deps = deps # depstyle 'gcc' or 'msvc' self.depfile = depfile @@ -235,7 +236,7 @@ # fallthrough return ninja_quote(qf(str(x))) - def write(self, outfile): + def write(self, outfile: T.TextIO) -> None: if self.rspfile_quote_style is RSPFileSyntax.MSVC: rspfile_quote_func = cmd_quote else: @@ -380,7 +381,8 @@ if len(self.deps) > 0: 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 sorted(self.orderdeps)]) + orderdeps = [str(x) for x in self.orderdeps] + line += ' || ' + ' '.join([ninja_quote(x, True) for x in sorted(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 @@ -487,6 +489,7 @@ self.introspection_data = {} self.created_llvm_ir_rule = PerMachine(False, False) self.rust_crates: T.Dict[str, RustCrate] = {} + self.implicit_meson_outs = [] def create_phony_target(self, all_outputs, dummy_outfile, rulename, phony_infilename, implicit_outs=None): ''' @@ -545,7 +548,7 @@ # We want to match 'Note: including file: ' in the line # '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:\'. + # number of colons. Match up to the drive name 'd:\'. # 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. @@ -572,9 +575,13 @@ raise MesonException(f'Could not determine vs dep dependency prefix string. output: {stderr} {stdout}') - def generate(self): + def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: + if vslite_ctx: + # We don't yet have a use case where we'd expect to make use of this, + # so no harm in catching and reporting something unexpected. + raise MesonBugException('We do not expect the ninja backend to be given a valid \'vslite_ctx\'') ninja = environment.detect_ninja_command_and_version(log=True) - if self.build.need_vsenv: + if self.environment.coredata.get_option(OptionKey('vsenv')): builddir = Path(self.environment.get_build_dir()) try: # For prettier printing, reduce to a relative path. If @@ -611,6 +618,14 @@ self.build_elements = [] self.generate_phony() self.add_build_comment(NinjaComment('Build rules for targets')) + + # Optionally capture compile args per target, for later use (i.e. VisStudio project's NMake intellisense include dirs, defines, and compile options). + if capture: + captured_compile_args_per_target = {} + for target in self.build.get_targets().values(): + if isinstance(target, build.BuildTarget): + captured_compile_args_per_target[target.get_id()] = self.generate_common_compile_args_per_src_type(target) + for t in ProgressBar(self.build.get_targets().values(), desc='Generating targets'): self.generate_target(t) self.add_build_comment(NinjaComment('Test rules')) @@ -649,6 +664,9 @@ self.generate_compdb() self.generate_rust_project_json() + if capture: + return captured_compile_args_per_target + def generate_rust_project_json(self) -> None: """Generate a rust-analyzer compatible rust-project.json file.""" if not self.rust_crates: @@ -746,11 +764,12 @@ return False return True - def create_target_source_introspection(self, target: build.Target, comp: compilers.Compiler, parameters, sources, generated_sources): + def create_target_source_introspection(self, target: build.Target, comp: compilers.Compiler, parameters, sources, generated_sources, + unity_sources: T.Optional[T.List[mesonlib.FileOrString]] = None): ''' Adds the source file introspection information for a language of a target - Internal introspection storage formart: + Internal introspection storage format: self.introspection_data = { '': { : { @@ -781,16 +800,40 @@ 'parameters': parameters, 'sources': [], 'generated_sources': [], + 'unity_sources': [], } tgt[id_hash] = src_block - # Make source files absolute - sources = [x.absolute_path(self.source_dir, self.build_dir) if isinstance(x, File) else os.path.normpath(os.path.join(self.build_dir, x)) - for x in sources] - generated_sources = [x.absolute_path(self.source_dir, self.build_dir) if isinstance(x, File) else os.path.normpath(os.path.join(self.build_dir, x)) - for x in generated_sources] - # Add the source files - src_block['sources'] += sources - src_block['generated_sources'] += generated_sources + + def compute_path(file: mesonlib.FileOrString) -> str: + """ Make source files absolute """ + if isinstance(file, File): + return file.absolute_path(self.source_dir, self.build_dir) + return os.path.normpath(os.path.join(self.build_dir, file)) + + src_block['sources'].extend(compute_path(x) for x in sources) + src_block['generated_sources'].extend(compute_path(x) for x in generated_sources) + if unity_sources: + src_block['unity_sources'].extend(compute_path(x) for x in unity_sources) + + def create_target_linker_introspection(self, target: build.Target, linker: T.Union[Compiler, StaticLinker], parameters): + tid = target.get_id() + tgt = self.introspection_data[tid] + lnk_hash = tuple(parameters) + lnk_block = tgt.get(lnk_hash, None) + if lnk_block is None: + if isinstance(parameters, CompilerArgs): + parameters = parameters.to_native(copy=True) + + if isinstance(linker, Compiler): + linkers = linker.get_linker_exelist() + else: + linkers = linker.get_exelist() + + lnk_block = { + 'linker': linkers, + 'parameters': parameters, + } + tgt[lnk_hash] = lnk_block def generate_target(self, target): try: @@ -830,7 +873,11 @@ self.generate_swift_target(target) return - # Pre-existing target C/C++ sources to be built; dict of full path to + # CompileTarget compiles all its sources and does not do a final link. + # This is, for example, a preprocessor. + is_compile_target = isinstance(target, build.CompileTarget) + + # Preexisting 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] @@ -839,7 +886,7 @@ 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++ + # a language that is handled below, such as C or C++ transpiled_sources: T.List[str] if 'vala' in target.compilers: @@ -879,7 +926,7 @@ mlog.log(mlog.red('FIXME'), msg) # Get a list of all generated headers that will be needed while building - # this target's sources (generated sources and pre-existing sources). + # this target's sources (generated sources and preexisting sources). # This will be set as dependencies of all the target's sources. At the # same time, also deal with generated sources that need to be compiled. generated_source_files = [] @@ -896,6 +943,8 @@ obj_list.append(rel_src) elif self.environment.is_library(rel_src) or modules.is_module_library(rel_src): pass + elif is_compile_target: + generated_source_files.append(raw_src) else: # Assume anything not specifically a source file is a header. This is because # people generate files with weird suffixes (.inc, .fh) that they then include @@ -921,7 +970,7 @@ if s.split('.')[-1] in compilers.lang_suffixes['d']: d_generated_deps.append(o) - use_pch = self.environment.coredata.options.get(OptionKey('b_pch')) + use_pch = self.target_uses_pch(target) if use_pch and target.has_pch(): pch_objects = self.generate_pch(target, header_deps=header_deps) else: @@ -931,7 +980,7 @@ obj_targets = [t for t in od if t.uses_fortran()] obj_list.extend(o) - fortran_order_deps = [self.get_target_filename(t) for t in obj_targets] + fortran_order_deps = [File(True, *os.path.split(self.get_target_filename(t))) for t in obj_targets] fortran_inc_args: T.List[str] = [] if target.uses_fortran(): fortran_inc_args = mesonlib.listify([target.compilers['fortran'].get_include_args( @@ -964,9 +1013,9 @@ 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 + # Generate compile targets for all the preexisting sources for this target for src in target_sources.values(): - if not self.environment.is_header(src): + if not self.environment.is_header(src) or is_compile_target: if self.environment.is_llvm_ir(src): o, s = self.generate_llvm_ir_compile(target, src) obj_list.append(o) @@ -985,11 +1034,11 @@ if is_unity: for src in self.generate_unity_files(target, unity_src): o, s = self.generate_single_compile(target, src, True, unity_deps + header_deps + d_generated_deps, - fortran_order_deps, fortran_inc_args) + fortran_order_deps, fortran_inc_args, unity_src) obj_list.append(o) compiled_sources.append(s) source2object[s] = o - if isinstance(target, build.CompileTarget): + if is_compile_target: # Skip the link stage for this special type of target return linker, stdlib_args = self.determine_linker_and_stdlib_args(target) @@ -1000,6 +1049,11 @@ 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, fortran_order_deps) self.add_build(elem) + #In AIX, we archive shared libraries. If the instance is a shared library, we add a command to archive the shared library + #object and create the build element. + if isinstance(target, build.SharedLibrary) and self.environment.machines[target.for_machine].is_aix(): + elem = NinjaBuildElement(self.all_outputs, linker.get_archive_name(outname), 'AIX_LINKER', [outname]) + 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'): @@ -1014,7 +1068,7 @@ 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 + cppversion = target.get_option(OptionKey('std', machine=target.for_machine, lang='cpp')) if cppversion not in ('latest', 'c++latest', 'vc++latest'): return False if not mesonlib.current_vs_supports_modules(): @@ -1024,7 +1078,7 @@ return True def generate_dependency_scan_target(self, target, compiled_sources, source2object, generated_source_files: T.List[mesonlib.File], - object_deps: T.List[str]) -> None: + object_deps: T.List['mesonlib.FileOrString']) -> None: if not self.should_use_dyndeps_for_target(target): return depscan_file = self.get_dep_scan_file_for(target) @@ -1035,8 +1089,8 @@ 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 + # Dump the sources as a json list. This avoids potential problems where + # the number of sources passed to depscan exceeds the limit imposed by # the OS. with open(json_abs, 'w', encoding='utf-8') as f: json.dump(scan_sources, f) @@ -1267,7 +1321,9 @@ ['--internal', 'regenerate', self.environment.get_source_dir(), - self.environment.get_build_dir()] + # Ninja always runs from the build_dir. This includes cases where the user moved the + # build directory and invalidated most references. Make sure it still regenerates. + '.'] self.add_rule(NinjaRule('REGENERATE_BUILD', c, [], 'Regenerating build files.', @@ -1294,7 +1350,7 @@ 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}") + mlog.warning(f"build statement for {build.outfilenames} references nonexistent rule {build.rulename}") def write_rules(self, outfile): for b in self.build_elements: @@ -1505,7 +1561,7 @@ 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. + Handles both preexisting and generated sources. Returns a tuple (vala, vapi, others) each of which is a dictionary with the keys being the path to the file (relative to the build directory) @@ -1515,7 +1571,7 @@ vapi: T.MutableMapping[str, File] = OrderedDict() others: T.MutableMapping[str, File] = OrderedDict() othersgen: T.MutableMapping[str, File] = OrderedDict() - # Split pre-existing sources + # Split preexisting 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 @@ -1606,7 +1662,7 @@ valac_outputs.append(vala_c_file) args = self.generate_basic_compiler_args(target, valac) - args += valac.get_colorout_args(self.environment.coredata.options.get(OptionKey('b_colorout')).value) + args += valac.get_colorout_args(target.get_option(OptionKey('b_colorout'))) # 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). @@ -1650,7 +1706,7 @@ target.install_dir[3] = os.path.join(self.environment.get_datadir(), 'gir-1.0') # Detect gresources and add --gresources arguments for each for gensrc in other_src[1].values(): - if isinstance(gensrc, gnome.GResourceTarget): + if isinstance(gensrc, modules.GResourceTarget): gres_xml, = self.get_custom_target_sources(gensrc) args += ['--gresources=' + gres_xml] extra_args = [] @@ -1778,8 +1834,8 @@ return orderdeps, first_file def _add_rust_project_entry(self, name: str, main_rust_file: str, args: CompilerArgs, - from_subproject: bool, is_proc_macro: bool, - output: str, deps: T.List[RustDep]) -> None: + from_subproject: bool, proc_macro_dylib_path: T.Optional[str], + deps: T.List[RustDep]) -> None: raw_edition: T.Optional[str] = mesonlib.first(reversed(args), lambda x: x.startswith('--edition')) edition: RUST_EDITIONS = '2015' if not raw_edition else raw_edition.split('=')[-1] @@ -1799,12 +1855,18 @@ deps, cfg, is_workspace_member=not from_subproject, - is_proc_macro=is_proc_macro, - proc_macro_dylib_path=output if is_proc_macro else None, + is_proc_macro=proc_macro_dylib_path is not None, + proc_macro_dylib_path=proc_macro_dylib_path, ) self.rust_crates[name] = crate + def _get_rust_dependency_name(self, target: build.BuildTarget, dependency: LibTypes) -> str: + # Convert crate names with dashes to underscores by default like + # cargo does as dashes can't be used as parts of identifiers + # in Rust + return target.rust_dependency_map.get(dependency.name, dependency.name).replace('-', '_') + def generate_rust_target(self, target: build.BuildTarget) -> None: rustc = target.compilers['rust'] # Rust compiler takes only the main file as input and @@ -1892,8 +1954,8 @@ args.extend(rustc.get_linker_always_args()) args += self.generate_basic_compiler_args(target, rustc, False) - # Rustc replaces - with _. spaces are not allowed, so we replace them with underscores - args += ['--crate-name', target.name.replace('-', '_').replace(' ', '_')] + # Rustc replaces - with _. spaces or dots are not allowed, so we replace them with underscores + args += ['--crate-name', target.name.replace('-', '_').replace(' ', '_').replace('.', '_')] depfile = os.path.join(target.subdir, target.name + '.d') args += ['--emit', f'dep-info={depfile}', '--emit', 'link'] args += target.get_extra_args('rust') @@ -1901,16 +1963,69 @@ args += output linkdirs = mesonlib.OrderedSet() external_deps = target.external_deps.copy() + + # Have we already injected msvc-crt args? + # + # If we don't have A C, C++, or Fortran compiler that is + # VisualStudioLike treat this as if we've already injected them + # + # We handle this here rather than in the rust compiler because in + # general we don't want to link rust targets to a non-default crt. + # However, because of the way that MSCRTs work you can only link to one + # per target, so if A links to the debug one, and B links to the normal + # one you can't link A and B. Rust is hardcoded to the default one, + # so if we compile C/C++ code and link against a non-default MSCRT then + # linking will fail. We can work around this by injecting MSCRT link + # arguments early in the rustc command line + # https://github.com/rust-lang/rust/issues/39016 + crt_args_injected = not any(x is not None and x.get_argument_syntax() == 'msvc' for x in + (self.environment.coredata.compilers[target.for_machine].get(l) + for l in ['c', 'cpp', 'fortran'])) + + crt_link_args: T.List[str] = [] + try: + buildtype = target.get_option(OptionKey('buildtype')) + crt = target.get_option(OptionKey('b_vscrt')) + is_debug = buildtype == 'debug' + + if crt == 'from_buildtype': + crt = 'mdd' if is_debug else 'md' + elif crt == 'static_from_buildtype': + crt = 'mtd' if is_debug else 'mt' + + if crt == 'mdd': + crt_link_args = ['-l', 'static=msvcrtd'] + elif crt == 'md': + # this is the default, no need to inject anything + crt_args_injected = True + elif crt == 'mtd': + crt_link_args = ['-l', 'static=libcmtd'] + elif crt == 'mt': + crt_link_args = ['-l', 'static=libcmt'] + + except KeyError: + crt_args_injected = True + # TODO: we likely need to use verbatim to handle name_prefix and name_suffix for d in target.link_targets: linkdirs.add(d.subdir) - if d.uses_rust(): + # staticlib and cdylib provide a plain C ABI, i.e. contain no Rust + # metadata. As such they should be treated like any other external + # link target + if d.uses_rust() and d.rust_crate_type not in ['staticlib', 'cdylib']: # 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))] - project_deps.append(RustDep(d.name, self.rust_crates[d.name].order)) - elif d.typename == 'static library': + d_name = self._get_rust_dependency_name(target, d) + args += ['--extern', '{}={}'.format(d_name, os.path.join(d.subdir, d.filename))] + project_deps.append(RustDep(d_name, self.rust_crates[d.name].order)) + continue + + if not crt_args_injected and not {'c', 'cpp', 'fortran'}.isdisjoint(d.compilers): + args += crt_link_args + crt_args_injected = True + + if isinstance(d, build.StaticLibrary): # 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. @@ -1928,7 +2043,7 @@ # before that it would treat linking two static libraries as # whole-archive linking. However, to make this work we have to disable # bundling, which can't be done until 1.63.0… So for 1.61–1.62 we just - # have to hope that the default cases of +whole-archive are sufficent. + # have to hope that the default cases of +whole-archive are sufficient. # See: https://github.com/rust-lang/rust/issues/99429 if mesonlib.version_compare(rustc.version, '>= 1.63.0'): whole_archive = ':+whole-archive,-bundle' @@ -1946,9 +2061,14 @@ # 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))] - project_deps.append(RustDep(d.name, self.rust_crates[d.name].order)) - else: + d_name = self._get_rust_dependency_name(target, d) + args += ['--extern', '{}={}'.format(d_name, os.path.join(d.subdir, d.filename))] + project_deps.append(RustDep(d_name, self.rust_crates[d.name].order)) + else: + if not crt_args_injected and not {'c', 'cpp', 'fortran'}.isdisjoint(d.compilers): + crt_args_injected = True + crt_args_injected = True + if rustc.linker.id in {'link', 'lld-link'}: if verbatim: # If we can use the verbatim modifier, then everything is great @@ -1974,6 +2094,9 @@ external_deps.extend(d.external_deps) for e in external_deps: for a in e.get_link_args(): + if a in rustc.native_static_libs: + # Exclude link args that rustc already add by default + continue if a.endswith(('.dll', '.so', '.dylib')): dir_, lib = os.path.split(a) linkdirs.add(dir_) @@ -1990,13 +2113,24 @@ if d == '': d = '.' args += ['-L', d] - has_shared_deps = any(isinstance(dep, build.SharedLibrary) for dep in target.get_dependencies()) - if isinstance(target, build.SharedLibrary) or has_shared_deps: + + # Because of the way rustc links, this must come after any potential + # library need to link with their stdlibs (C++ and Fortran, for example) + args.extend(target.get_used_stdlib_args('rust')) + + target_deps = target.get_dependencies() + has_shared_deps = any(isinstance(dep, build.SharedLibrary) for dep in target_deps) + has_rust_shared_deps = any(dep.uses_rust() + and dep.rust_crate_type == 'dylib' + for dep in target_deps) + + if cratetype in {'dylib', 'proc-macro'} or has_rust_shared_deps: # add prefer-dynamic if any of the Rust libraries we link - # against are dynamic, otherwise we'll end up with - # multiple implementations of crates + # against are dynamic or this is a dynamic library itself, + # otherwise we'll end up with multiple implementations of libstd. args += ['-C', 'prefer-dynamic'] + if isinstance(target, build.SharedLibrary) or has_shared_deps: # build the usual rpath arguments as well... # Set runtime-paths so we can run executables without needing to set @@ -2021,10 +2155,16 @@ for rpath_arg in rpath_args: args += ['-C', 'link-arg=' + rpath_arg + ':' + os.path.join(rustc.get_sysroot(), 'lib')] - self._add_rust_project_entry(target.name, main_rust_file, args, bool(target.subproject), - #XXX: There is a fix for this pending - getattr(target, 'rust_crate_type', '') == 'procmacro', - output, project_deps) + proc_macro_dylib_path = None + if getattr(target, 'rust_crate_type', '') == 'proc-macro': + proc_macro_dylib_path = os.path.abspath(os.path.join(target.subdir, target.get_filename())) + + self._add_rust_project_entry(target.name, + os.path.abspath(os.path.join(self.environment.build_dir, main_rust_file)), + args, + bool(target.subproject), + proc_macro_dylib_path, + project_deps) compiler_name = self.compiler_to_rule_name(rustc) element = NinjaBuildElement(self.all_outputs, target_name, compiler_name, main_rust_file) @@ -2209,7 +2349,7 @@ # them out to fix this properly on Windows. See: # https://github.com/mesonbuild/meson/issues/1517 # https://github.com/mesonbuild/meson/issues/1526 - if isinstance(static_linker, ArLinker) and not mesonlib.is_windows(): + if isinstance(static_linker, ArLikeLinker) and not mesonlib.is_windows(): # `ar` has no options to overwrite archives. It always appends, # which is never what we want. Delete an existing library first if # it exists. https://github.com/mesonbuild/meson/issues/1355 @@ -2244,6 +2384,13 @@ options = self._rsp_options(compiler) self.add_rule(NinjaRule(rule, command, args, description, **options, extra=pool)) + if self.environment.machines[for_machine].is_aix(): + rule = 'AIX_LINKER{}'.format(self.get_rule_suffix(for_machine)) + description = 'Archiving AIX shared library' + cmdlist = compiler.get_command_to_archive_shlib() + args = [] + options = {} + self.add_rule(NinjaRule(rule, cmdlist, args, description, **options, extra=None)) args = self.environment.get_build_command() + \ ['--internal', @@ -2369,8 +2516,12 @@ self.generate_cython_compile_rules(compiler) return crstr = self.get_rule_suffix(compiler.for_machine) + options = self._rsp_options(compiler) if langname == 'fortran': self.generate_fortran_dep_hack(crstr) + # gfortran does not update the modification time of *.mod files, therefore restat is needed. + # See also: https://github.com/ninja-build/ninja/pull/2275 + options['extra'] = 'restat = 1' rule = self.compiler_to_rule_name(compiler) depargs = NinjaCommandArg.list(compiler.get_dependency_gen_args('$out', '$DEPFILE'), Quoting.none) command = compiler.get_exelist() @@ -2382,7 +2533,6 @@ else: deps = 'gcc' depfile = '$DEPFILE' - options = self._rsp_options(compiler) self.add_rule(NinjaRule(rule, command, args, description, **options, deps=deps, depfile=depfile)) @@ -2396,7 +2546,12 @@ output = [] else: output = NinjaCommandArg.list(compiler.get_output_args('$out'), Quoting.none) - command = compiler.get_exelist() + ['$ARGS'] + depargs + output + compiler.get_compile_only_args() + ['$in'] + + if 'mwcc' in compiler.id: + output[0].s = '-precompile' + command = compiler.get_exelist() + ['$ARGS'] + depargs + output + ['$in'] # '-c' must be removed + else: + command = compiler.get_exelist() + ['$ARGS'] + depargs + output + compiler.get_compile_only_args() + ['$in'] description = 'Precompiling header $in' if compiler.get_argument_syntax() == 'msvc': deps = 'msvc' @@ -2454,6 +2609,9 @@ return args def generate_genlist_for_target(self, genlist: build.GeneratedList, target: build.BuildTarget) -> None: + for x in genlist.depends: + if isinstance(x, build.GeneratedList): + self.generate_genlist_for_target(x, target) generator = genlist.get_generator() subdir = genlist.subdir exe = generator.get_exe() @@ -2465,7 +2623,7 @@ sole_output = os.path.join(self.get_target_private_dir(target), outfilelist[i]) else: sole_output = f'{curfile}' - infilename = curfile.rel_to_builddir(self.build_to_src) + infilename = curfile.rel_to_builddir(self.build_to_src, self.get_target_private_dir(target)) base_args = generator.get_arglist(infilename) outfiles = genlist.get_outputs_for(curfile) outfiles = [os.path.join(self.get_target_private_dir(target), of) for of in outfiles] @@ -2501,10 +2659,10 @@ what = f'{sole_output!r}' else: # since there are multiple outputs, we log the source that caused the rebuild - what = f'from {sole_output!r}.' + what = f'from {sole_output!r}' if reason: reason = f' (wrapped by meson {reason})' - elem.add_item('DESC', f'Generating {what}{reason}.') + elem.add_item('DESC', f'Generating {what}{reason}') if isinstance(exe, build.BuildTarget): elem.add_dep(self.get_target_filename(exe)) @@ -2593,7 +2751,7 @@ # inside it. This can be either the final PDB (for, say, # foo.exe) or an object pdb (for foo.obj). If the former, then # each compilation step locks the pdb file for writing, which - # is a bottleneck and object files from one target can not be + # is a bottleneck and object files from one target cannot be # used in a different target. The latter seems to be the # sensible one (and what Unix does) but there is a catch. If # you try to use precompiled headers MSVC will error out @@ -2615,7 +2773,7 @@ # has pdb file called foo.pdb. So will a static library # foo.lib, which clobbers both foo.pdb _and_ the dll file's # export library called foo.lib (by default, currently we name - # them libfoo.a to avoidt this issue). You can give the files + # them libfoo.a to avoid this issue). You can give the files # unique names such as foo_exe.pdb but VC also generates a # bunch of other files which take their names from the target # basename (i.e. "foo") and stomp on each other. @@ -2779,10 +2937,39 @@ commands += compiler.get_include_args(self.get_target_private_dir(target), False) return commands + # Returns a dictionary, mapping from each compiler src type (e.g. 'c', 'cpp', etc.) to a list of compiler arg strings + # used for that respective src type. + # Currently used for the purpose of populating VisualStudio intellisense fields but possibly useful in other scenarios. + def generate_common_compile_args_per_src_type(self, target: build.BuildTarget) -> dict[str, list[str]]: + src_type_to_args = {} + + use_pch = self.target_uses_pch(target) + + for src_type_str in target.compilers.keys(): + compiler = target.compilers[src_type_str] + 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 use_pch and 'mw' not in compiler.id: + commands += self.get_pch_include_args(compiler, target) + + commands += self._generate_single_compile_target_args(target, compiler, is_generated=False) + + # Metrowerks compilers require PCH include args to come after intraprocedural analysis args + if use_pch and 'mw' in compiler.id: + commands += self.get_pch_include_args(compiler, target) + + commands = commands.compiler.compiler_args(commands) + + src_type_to_args[src_type_str] = commands.to_native() + return src_type_to_args + def generate_single_compile(self, target: build.BuildTarget, src, is_generated=False, header_deps=None, - order_deps: T.Optional[T.List[str]] = None, - extra_args: T.Optional[T.List[str]] = None) -> None: + order_deps: T.Optional[T.List['mesonlib.FileOrString']] = None, + extra_args: T.Optional[T.List[str]] = None, + unity_sources: T.Optional[T.List[mesonlib.FileOrString]] = None) -> None: """ Compiles C/C++, ObjC/ObjC++, Fortran, and D sources """ @@ -2797,17 +2984,23 @@ # 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': + use_pch = self.target_uses_pch(target) and is_generated != 'pch' + if use_pch and 'mw' not in compiler.id: commands += self.get_pch_include_args(compiler, target) commands += self._generate_single_compile_target_args(target, compiler, is_generated) + + # Metrowerks compilers require PCH include args to come after intraprocedural analysis args + if use_pch and 'mw' in compiler.id: + commands += self.get_pch_include_args(compiler, target) + commands = commands.compiler.compiler_args(commands) # Create introspection information if is_generated is False: - self.create_target_source_introspection(target, compiler, commands, [src], []) + self.create_target_source_introspection(target, compiler, commands, [src], [], unity_sources) else: - self.create_target_source_introspection(target, compiler, commands, [], [src]) + self.create_target_source_introspection(target, compiler, commands, [], [src], unity_sources) build_dir = self.environment.get_build_dir() if isinstance(src, File): @@ -2830,7 +3023,7 @@ commands += self.get_compile_debugfile_args(compiler, target, rel_obj) # PCH handling - if self.environment.coredata.options.get(OptionKey('b_pch')): + if self.target_uses_pch(target): pchlist = target.get_pch(compiler.language) else: pchlist = [] @@ -2898,6 +3091,8 @@ def add_dependency_scanner_entries_to_element(self, target, compiler, element, src): if not self.should_use_dyndeps_for_target(target): return + if isinstance(target, build.CompileTarget): + return extension = os.path.splitext(src.fname)[1][1:] if extension != 'C': extension = extension.lower() @@ -2973,6 +3168,13 @@ dep = dst + '.' + compiler.get_depfile_suffix() return commands, dep, dst, [] # Gcc does not create an object file during pch generation. + def generate_mwcc_pch_command(self, target, compiler, pch): + commands = self._generate_single_compile(target, compiler) + dst = os.path.join(self.get_target_private_dir(target), + os.path.basename(pch) + '.' + compiler.get_pch_suffix()) + dep = os.path.splitext(dst)[0] + '.' + compiler.get_depfile_suffix() + return commands, dep, dst, [] # mwcc compilers do not create an object file during pch generation. + def generate_pch(self, target, header_deps=None): header_deps = header_deps if header_deps is not None else [] pch_objects = [] @@ -2991,13 +3193,17 @@ elif compiler.id == 'intel': # Intel generates on target generation continue + elif 'mwcc' in compiler.id: + src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0]) + (commands, dep, dst, objs) = self.generate_mwcc_pch_command(target, compiler, pch[0]) + extradep = None else: src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0]) (commands, dep, dst, objs) = self.generate_gcc_pch_command(target, compiler, pch[0]) extradep = None pch_objects += objs rulename = self.compiler_to_pch_rule_name(compiler) - elem = NinjaBuildElement(self.all_outputs, dst, rulename, src) + elem = NinjaBuildElement(self.all_outputs, objs + [dst], rulename, src) if extradep is not None: elem.add_dep(extradep) self.add_header_deps(target, elem, header_deps) @@ -3039,8 +3245,7 @@ commands += linker.get_pie_link_args() elif isinstance(target, build.SharedLibrary): if isinstance(target, build.SharedModule): - options = self.environment.coredata.options - commands += linker.get_std_shared_module_link_args(options) + commands += linker.get_std_shared_module_link_args(target.get_options()) else: commands += linker.get_std_shared_lib_link_args() # All shared libraries are PIC @@ -3114,7 +3319,7 @@ def guess_external_link_dependencies(self, linker, target, commands, internal): # Ideally the linker would generate dependency information that could be used. # But that has 2 problems: - # * currently ld can not create dependency information in a way that ninja can use: + # * currently ld cannot create dependency information in a way that ninja can use: # https://sourceware.org/bugzilla/show_bug.cgi?id=22843 # * Meson optimizes libraries from the same build using the symbol extractor. # Just letting ninja use ld generated dependencies would undo this optimization. @@ -3285,6 +3490,11 @@ else: dependencies = target.get_dependencies() internal = self.build_target_link_arguments(linker, dependencies) + #In AIX since shared libraries are archived the dependencies must + #depend on .a file with the .so and not directly on the .so file. + if self.environment.machines[target.for_machine].is_aix(): + for i, val in enumerate(internal): + internal[i] = linker.get_archive_name(val) commands += internal # Only non-static built targets need link args and link dependencies if not isinstance(target, build.StaticLibrary): @@ -3317,7 +3527,7 @@ # # 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) + commands += linker.get_option_link_args(target.get_options()) dep_targets = [] dep_targets.extend(self.guess_external_link_dependencies(linker, target, commands, internal)) @@ -3333,6 +3543,7 @@ 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) + self.create_target_linker_introspection(target, linker, commands) return elem def get_dependency_filename(self, t): @@ -3348,17 +3559,20 @@ def generate_shlib_aliases(self, target, outdir): for alias, to, tag in target.get_aliases(): - aliasfile = os.path.join(self.environment.get_build_dir(), outdir, alias) + aliasfile = os.path.join(outdir, alias) + abs_aliasfile = os.path.join(self.environment.get_build_dir(), outdir, alias) try: - os.remove(aliasfile) + os.remove(abs_aliasfile) except Exception: pass try: - os.symlink(to, aliasfile) + os.symlink(to, abs_aliasfile) except NotImplementedError: mlog.debug("Library versioning disabled because symlinks are not supported.") except OSError: mlog.debug("Library versioning disabled because we do not have symlink creation privileges.") + else: + self.implicit_meson_outs.append(aliasfile) def generate_custom_target_clean(self, trees: T.List[str]) -> str: e = self.create_phony_target(self.all_outputs, 'clean-ctlist', 'CUSTOM_COMMAND', 'PHONY') @@ -3484,6 +3698,11 @@ for t in deps.values(): # Add the first output of each target to the 'all' target so that # they are all built + #Add archive file if shared library in AIX for build all. + if isinstance(t, build.SharedLibrary): + if self.environment.machines[t.for_machine].is_aix(): + linker, stdlib_args = self.determine_linker_and_stdlib_args(t) + t.get_outputs()[0] = linker.get_archive_name(t.get_outputs()[0]) targetlist.append(os.path.join(self.get_target_dir(t), t.get_outputs()[0])) elem = NinjaBuildElement(self.all_outputs, targ, 'phony', targetlist) @@ -3520,6 +3739,12 @@ elem.add_item('pool', 'console') self.add_build(elem) + # If these files used to be explicitly created, they need to appear on the build graph somehow, + # otherwise cleandead deletes them. See https://github.com/ninja-build/ninja/issues/2299 + if self.implicit_meson_outs: + elem = NinjaBuildElement(self.all_outputs, 'meson-implicit-outs', 'phony', self.implicit_meson_outs) + self.add_build(elem) + elem = NinjaBuildElement(self.all_outputs, 'reconfigure', 'REGENERATE_BUILD', 'PHONY') elem.add_item('pool', 'console') self.add_build(elem) @@ -3528,13 +3753,11 @@ self.add_build(elem) 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: + data = self.introspection_data.get(target_id) + if not data: return super().get_introspection_data(target_id, target) - result = [] - for i in self.introspection_data[target_id].values(): - result += [i] - return result + return list(data.values()) def _scan_fortran_file_deps(src: Path, srcdir: Path, dirname: Path, tdeps, compiler) -> T.List[str]: diff -Nru meson-1.0.1/mesonbuild/backend/nonebackend.py meson-1.2.1/mesonbuild/backend/nonebackend.py --- meson-1.0.1/mesonbuild/backend/nonebackend.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/mesonbuild/backend/nonebackend.py 2023-07-05 15:40:06.000000000 +0000 @@ -0,0 +1,39 @@ +# Copyright 2022 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 __future__ import annotations + +import typing as T + +from .backends import Backend +from .. import mlog +from ..mesonlib import MesonBugException + + +class NoneBackend(Backend): + + name = 'none' + + def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: + # Check for (currently) unexpected capture arg use cases - + if capture: + raise MesonBugException('We do not expect the none backend to generate with \'capture = True\'') + if vslite_ctx: + raise MesonBugException('We do not expect the none backend to be given a valid \'vslite_ctx\'') + + if self.build.get_targets(): + raise MesonBugException('None backend cannot generate target rules, but should have failed earlier.') + mlog.log('Generating simple install-only backend') + self.serialize_tests() + self.create_install_data_files() diff -Nru meson-1.0.1/mesonbuild/backend/vs2010backend.py meson-1.2.1/mesonbuild/backend/vs2010backend.py --- meson-1.0.1/mesonbuild/backend/vs2010backend.py 2023-02-01 21:43:18.000000000 +0000 +++ meson-1.2.1/mesonbuild/backend/vs2010backend.py 2023-08-07 22:54:34.000000000 +0000 @@ -22,20 +22,24 @@ import typing as T from pathlib import Path, PurePath import re +from collections import Counter from . import backends from .. import build -from .. import dependencies from .. import mlog from .. import compilers +from .. import mesonlib from ..mesonlib import ( - File, MesonException, replace_if_different, OptionKey, version_compare, MachineChoice + File, MesonBugException, MesonException, replace_if_different, OptionKey, version_compare, MachineChoice ) from ..environment import Environment, build_filename +from .. import coredata if T.TYPE_CHECKING: + from ..arglist import CompilerArgs from ..interpreter import Interpreter + Project = T.Tuple[str, Path, str, MachineChoice] def autodetect_vs_version(build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]) -> backends.Backend: vs_version = os.getenv('VisualStudioVersion', None) @@ -72,7 +76,7 @@ 'Please specify the exact backend to use.'.format(vs_version, vs_install_dir)) -def split_o_flags_args(args): +def split_o_flags_args(args: T.List[str]) -> T.List[str]: """ Splits any /O args and returns them. Does not take care of flags overriding previous ones. Skips non-O flag arguments. @@ -93,17 +97,58 @@ o_flags += ['/O' + f for f in flags] return o_flags - -def generate_guid_from_path(path, path_type): +def generate_guid_from_path(path, path_type) -> str: return str(uuid.uuid5(uuid.NAMESPACE_URL, 'meson-vs-' + path_type + ':' + str(path))).upper() def detect_microsoft_gdk(platform: str) -> bool: return re.match(r'Gaming\.(Desktop|Xbox.XboxOne|Xbox.Scarlett)\.x64', platform, re.IGNORECASE) +def filtered_src_langs_generator(sources: T.List[str]): + for src in sources: + ext = src.split('.')[-1] + if compilers.compilers.is_source_suffix(ext): + yield compilers.compilers.SUFFIX_TO_LANG[ext] + +# Returns the source language (i.e. a key from 'lang_suffixes') of the most frequent source language in the given +# list of sources. +# We choose the most frequent language as 'primary' because it means the most sources in a target/project can +# simply refer to the project's shared intellisense define and include fields, rather than have to fill out their +# own duplicate full set of defines/includes/opts intellisense fields. All of which helps keep the vcxproj file +# size down. +def get_primary_source_lang(target_sources: T.List[File], custom_sources: T.List[str]) -> T.Optional[str]: + lang_counts = Counter([compilers.compilers.SUFFIX_TO_LANG[src.suffix] for src in target_sources if compilers.compilers.is_source_suffix(src.suffix)]) + lang_counts += Counter(filtered_src_langs_generator(custom_sources)) + most_common_lang_list = lang_counts.most_common(1) + # It may be possible that we have a target with no actual src files of interest (e.g. a generator target), + # leaving us with an empty list, which we should handle - + return most_common_lang_list[0][0] if most_common_lang_list else None + +# Returns a dictionary (by [src type][build type]) that contains a tuple of - +# (pre-processor defines, include paths, additional compiler options) +# fields to use to fill in the respective intellisense fields of sources that can't simply +# reference and re-use the shared 'primary' language intellisense fields of the vcxproj. +def get_non_primary_lang_intellisense_fields(vslite_ctx: dict, + target_id: str, + primary_src_lang: str) -> T.Dict[str, T.Dict[str, T.Tuple[str, str, str]]]: + defs_paths_opts_per_lang_and_buildtype = {} + for buildtype in coredata.get_genvs_default_buildtype_list(): + captured_build_args = vslite_ctx[buildtype][target_id] # Results in a 'Src types to compile args' dict + non_primary_build_args_per_src_lang = [(lang, build_args) for lang, build_args in captured_build_args.items() if lang != primary_src_lang] # Only need to individually populate intellisense fields for sources of non-primary types. + for src_lang, args_list in non_primary_build_args_per_src_lang: + if src_lang not in defs_paths_opts_per_lang_and_buildtype: + defs_paths_opts_per_lang_and_buildtype[src_lang] = {} + defs = Vs2010Backend.extract_nmake_preprocessor_defs(args_list) + paths = Vs2010Backend.extract_nmake_include_paths(args_list) + opts = Vs2010Backend.extract_intellisense_additional_compiler_options(args_list) + defs_paths_opts_per_lang_and_buildtype[src_lang][buildtype] = (defs, paths, opts) + return defs_paths_opts_per_lang_and_buildtype + class Vs2010Backend(backends.Backend): - def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]): + + name = 'vs2010' + + def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Interpreter], gen_lite: bool = False): 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' @@ -112,74 +157,87 @@ self.windows_target_platform_version = None self.subdirs = {} self.handled_target_deps = {} + self.gen_lite = gen_lite # Synonymous with generating the simpler makefile-style multi-config projects that invoke 'meson compile' builds, avoiding native MSBuild complications def get_target_private_dir(self, target): return os.path.join(self.get_target_dir(target), target.get_id()) + def generate_genlist_for_target(self, genlist: T.Union[build.GeneratedList, build.CustomTarget, build.CustomTargetIndex], target: build.BuildTarget, parent_node: ET.Element, generator_output_files: T.List[str], custom_target_include_dirs: T.List[str], custom_target_output_files: T.List[str]) -> None: + if isinstance(genlist, build.GeneratedList): + for x in genlist.depends: + self.generate_genlist_for_target(x, target, parent_node, [], [], []) + target_private_dir = self.relpath(self.get_target_private_dir(target), self.get_target_dir(target)) + down = self.target_to_build_root(target) + if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)): + for i in genlist.get_outputs(): + # Path to the generated source from the current vcxproj dir via the build root + ipath = os.path.join(down, self.get_target_dir(genlist), i) + custom_target_output_files.append(ipath) + idir = self.relpath(self.get_target_dir(genlist), self.get_target_dir(target)) + if idir not in custom_target_include_dirs: + custom_target_include_dirs.append(idir) + else: + generator = genlist.get_generator() + exe = generator.get_exe() + infilelist = genlist.get_inputs() + outfilelist = genlist.get_outputs() + source_dir = os.path.join(down, self.build_to_src, genlist.subdir) + idgroup = ET.SubElement(parent_node, 'ItemGroup') + samelen = len(infilelist) == len(outfilelist) + for i, curfile in enumerate(infilelist): + if samelen: + sole_output = os.path.join(target_private_dir, outfilelist[i]) + else: + sole_output = '' + infilename = os.path.join(down, curfile.rel_to_builddir(self.build_to_src, target_private_dir)) + deps = self.get_custom_target_depend_files(genlist, True) + base_args = generator.get_arglist(infilename) + outfiles_rel = genlist.get_outputs_for(curfile) + outfiles = [os.path.join(target_private_dir, of) for of in outfiles_rel] + generator_output_files += outfiles + args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output) + for x in base_args] + args = self.replace_outputs(args, target_private_dir, outfiles_rel) + args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()) + .replace("@BUILD_DIR@", target_private_dir) + for x in args] + args = [x.replace("@CURRENT_SOURCE_DIR@", source_dir) for x in args] + args = [x.replace("@SOURCE_ROOT@", self.environment.get_source_dir()) + .replace("@BUILD_ROOT@", self.environment.get_build_dir()) + for x in args] + args = [x.replace('\\', '/') for x in args] + # 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( + exe, + self.replace_extra_args(args, genlist), + workdir=tdir_abs, + capture=outfiles[0] if generator.capture else None, + force_serialize=True + ) + deps = cmd[-1:] + deps + abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) + os.makedirs(abs_pdir, exist_ok=True) + cbs = ET.SubElement(idgroup, 'CustomBuild', Include=infilename) + ET.SubElement(cbs, 'Command').text = ' '.join(self.quote_arguments(cmd)) + ET.SubElement(cbs, 'Outputs').text = ';'.join(outfiles) + ET.SubElement(cbs, 'AdditionalInputs').text = ';'.join(deps) + def generate_custom_generator_commands(self, target, parent_node): generator_output_files = [] custom_target_include_dirs = [] custom_target_output_files = [] - target_private_dir = self.relpath(self.get_target_private_dir(target), self.get_target_dir(target)) - down = self.target_to_build_root(target) for genlist in target.get_generated_sources(): - if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)): - for i in genlist.get_outputs(): - # Path to the generated source from the current vcxproj dir via the build root - ipath = os.path.join(down, self.get_target_dir(genlist), i) - custom_target_output_files.append(ipath) - idir = self.relpath(self.get_target_dir(genlist), self.get_target_dir(target)) - if idir not in custom_target_include_dirs: - custom_target_include_dirs.append(idir) - else: - generator = genlist.get_generator() - exe = generator.get_exe() - infilelist = genlist.get_inputs() - outfilelist = genlist.get_outputs() - source_dir = os.path.join(down, self.build_to_src, genlist.subdir) - idgroup = ET.SubElement(parent_node, 'ItemGroup') - for i, curfile in enumerate(infilelist): - if len(infilelist) == len(outfilelist): - sole_output = os.path.join(target_private_dir, outfilelist[i]) - else: - sole_output = '' - 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) - outfiles_rel = genlist.get_outputs_for(curfile) - outfiles = [os.path.join(target_private_dir, of) for of in outfiles_rel] - generator_output_files += outfiles - args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output) - for x in base_args] - args = self.replace_outputs(args, target_private_dir, outfiles_rel) - args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()) - .replace("@BUILD_DIR@", target_private_dir) - for x in args] - args = [x.replace("@CURRENT_SOURCE_DIR@", source_dir) for x in args] - args = [x.replace("@SOURCE_ROOT@", self.environment.get_source_dir()) - .replace("@BUILD_ROOT@", self.environment.get_build_dir()) - for x in args] - args = [x.replace('\\', '/') for x in args] - # 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( - exe, - self.replace_extra_args(args, genlist), - workdir=tdir_abs, - capture=outfiles[0] if generator.capture else None, - force_serialize=True - ) - deps = cmd[-1:] + deps - abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) - os.makedirs(abs_pdir, exist_ok=True) - cbs = ET.SubElement(idgroup, 'CustomBuild', Include=infilename) - ET.SubElement(cbs, 'Command').text = ' '.join(self.quote_arguments(cmd)) - ET.SubElement(cbs, 'Outputs').text = ';'.join(outfiles) - ET.SubElement(cbs, 'AdditionalInputs').text = ';'.join(deps) + self.generate_genlist_for_target(genlist, target, parent_node, generator_output_files, custom_target_include_dirs, custom_target_output_files) return generator_output_files, custom_target_output_files, custom_target_include_dirs - def generate(self): + def generate(self, + capture: bool = False, + vslite_ctx: dict = None) -> T.Optional[dict]: + # Check for (currently) unexpected capture arg use cases - + if capture: + raise MesonBugException('We do not expect any vs backend to generate with \'capture = True\'') target_machine = self.interpreter.builtin['target_machine'].cpu_family_method(None, None) if target_machine in {'64', 'x86_64'}: # amd64 or x86_64 @@ -228,10 +286,10 @@ 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')) - self.gen_installproj('RUN_INSTALL', os.path.join(self.environment.get_build_dir(), 'RUN_INSTALL.vcxproj')) - self.gen_regenproj('REGEN', os.path.join(self.environment.get_build_dir(), 'REGEN.vcxproj')) + projlist = self.generate_projects(vslite_ctx) + self.gen_testproj() + self.gen_installproj() + self.gen_regenproj() self.generate_solution(sln_filename, projlist) self.generate_regen_info() Vs2010Backend.touch_regen_timestamp(self.environment.get_build_dir()) @@ -341,7 +399,7 @@ ret.update(all_deps) return ret - def generate_solution_dirs(self, ofile, parents): + def generate_solution_dirs(self, ofile: str, parents: T.Sequence[Path]) -> None: prj_templ = 'Project("{%s}") = "%s", "%s", "{%s}"\n' iterpaths = reversed(parents) # Skip first path @@ -361,7 +419,7 @@ ofile.write(prj_line) ofile.write('EndProject\n') - def generate_solution(self, sln_filename, projlist): + def generate_solution(self, sln_filename: str, projlist: T.List[Project]) -> None: default_projlist = self.get_build_by_default_targets() default_projlist.update(self.get_testlike_targets()) sln_filename_tmp = sln_filename + '~' @@ -372,8 +430,7 @@ 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_option(OptionKey('layout')) == 'mirror': + if self.environment.coredata.get_option(OptionKey('layout')) == 'mirror': self.generate_solution_dirs(ofile, prj[1].parents) target = self.build.targets[prj[0]] lang = 'default' @@ -399,8 +456,14 @@ self.environment.coredata.test_guid) ofile.write(test_line) ofile.write('EndProject\n') + if self.gen_lite: # REGEN is replaced by the lighter-weight RECONFIGURE utility, for now. See comment in 'gen_regenproj' + regen_proj_name = 'RECONFIGURE' + regen_proj_fname = 'RECONFIGURE.vcxproj' + else: + regen_proj_name = 'REGEN' + regen_proj_fname = 'REGEN.vcxproj' regen_line = prj_templ % (self.environment.coredata.lang_guids['default'], - 'REGEN', 'REGEN.vcxproj', + regen_proj_name, regen_proj_fname, self.environment.coredata.regen_guid) ofile.write(regen_line) ofile.write('EndProject\n') @@ -412,18 +475,23 @@ ofile.write('Global\n') ofile.write('\tGlobalSection(SolutionConfigurationPlatforms) = ' 'preSolution\n') - ofile.write('\t\t%s|%s = %s|%s\n' % - (self.buildtype, self.platform, self.buildtype, - self.platform)) + multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() if self.gen_lite else [self.buildtype] + for buildtype in multi_config_buildtype_list: + ofile.write('\t\t%s|%s = %s|%s\n' % + (buildtype, self.platform, buildtype, + self.platform)) ofile.write('\tEndGlobalSection\n') ofile.write('\tGlobalSection(ProjectConfigurationPlatforms) = ' 'postSolution\n') - ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % - (self.environment.coredata.regen_guid, self.buildtype, - self.platform, self.buildtype, self.platform)) - ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' % - (self.environment.coredata.regen_guid, self.buildtype, - self.platform, self.buildtype, self.platform)) + # REGEN project (multi-)configurations + for buildtype in multi_config_buildtype_list: + ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % + (self.environment.coredata.regen_guid, buildtype, + self.platform, buildtype, self.platform)) + if not self.gen_lite: # With a 'genvslite'-generated solution, the regen (i.e. reconfigure) utility is only intended to run when the user explicitly builds this proj. + ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' % + (self.environment.coredata.regen_guid, buildtype, + self.platform, buildtype, self.platform)) # Create the solution configuration for p in projlist: if p[3] is MachineChoice.BUILD: @@ -431,21 +499,31 @@ else: config_platform = self.platform # Add to the list of projects in this solution + for buildtype in multi_config_buildtype_list: + ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % + (p[2], buildtype, self.platform, + buildtype, config_platform)) + # If we're building the solution with Visual Studio's build system, enable building of buildable + # projects. However, if we're building with meson (via --genvslite), then, since each project's + # 'build' action just ends up doing the same 'meson compile ...' we don't want the 'solution build' + # repeatedly going off and doing the same 'meson compile ...' multiple times over, so we just + # leave it up to the user to select or build just one project. + # FIXME: Would be slightly nicer if we could enable building of just one top level target/project, + # but not sure how to identify that. + if not self.gen_lite and \ + p[0] in default_projlist and \ + not isinstance(self.build.targets[p[0]], build.RunTarget): + ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' % + (p[2], buildtype, self.platform, + buildtype, config_platform)) + # RUN_TESTS and RUN_INSTALL project (multi-)configurations + for buildtype in multi_config_buildtype_list: ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % - (p[2], 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, 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)) - ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % - (self.environment.coredata.install_guid, self.buildtype, - self.platform, self.buildtype, self.platform)) + (self.environment.coredata.test_guid, buildtype, + self.platform, buildtype, self.platform)) + ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % + (self.environment.coredata.install_guid, buildtype, + self.platform, buildtype, self.platform)) ofile.write('\tEndGlobalSection\n') ofile.write('\tGlobalSection(SolutionProperties) = preSolution\n') ofile.write('\t\tHideSolutionNode = FALSE\n') @@ -463,9 +541,9 @@ ofile.write('EndGlobal\n') replace_if_different(sln_filename, sln_filename_tmp) - def generate_projects(self): + def generate_projects(self, vslite_ctx: dict = None) -> T.List[Project]: startup_project = self.environment.coredata.options[OptionKey('backend_startup_project')].value - projlist = [] + projlist: T.List[Project] = [] startup_idx = 0 for (i, (name, target)) in enumerate(self.build.targets.items()): if startup_project and startup_project == target.get_basename(): @@ -480,8 +558,9 @@ relname = target_dir / fname 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, target.for_machine)) + generated = self.gen_vcxproj(target, str(projfile_path), proj_uuid, vslite_ctx) + if generated: + projlist.append((name, relname, proj_uuid, target.for_machine)) # Put the startup project first in the project list if startup_idx: @@ -521,7 +600,7 @@ def quote_arguments(self, arr): return ['"%s"' % i for i in arr] - def add_project_reference(self, root, include, projid, link_outputs=False): + def add_project_reference(self, root: ET.Element, include: str, projid: str, link_outputs: bool = False) -> None: ig = ET.SubElement(root, 'ItemGroup') pref = ET.SubElement(ig, 'ProjectReference', Include=include) ET.SubElement(pref, 'Project').text = '{%s}' % projid @@ -531,7 +610,7 @@ # objects and .lib files manually. ET.SubElement(pref, 'LinkLibraryDependencies').text = 'false' - def add_target_deps(self, root, target): + def add_target_deps(self, root: ET.Element, target): target_dict = {target.get_id(): target} for dep in self.get_target_deps(target_dict).values(): if dep.get_id() in self.handled_target_deps[target.get_id()]: @@ -542,12 +621,17 @@ tid = self.environment.coredata.target_guids[dep.get_id()] self.add_project_reference(root, vcxproj, tid) + def create_basic_project_filters(self) -> ET.Element: + root = ET.Element('Project', {'ToolsVersion': '4.0', + 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) + return root + def create_basic_project(self, target_name, *, temp_dir, guid, conftype='Utility', target_ext=None, - target_platform=None): + target_platform=None) -> T.Tuple[ET.Element, ET.Element]: root = ET.Element('Project', {'DefaultTargets': "Build", 'ToolsVersion': '4.0', 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) @@ -555,12 +639,13 @@ confitems = ET.SubElement(root, 'ItemGroup', {'Label': 'ProjectConfigurations'}) if not target_platform: target_platform = self.platform - prjconf = ET.SubElement(confitems, 'ProjectConfiguration', - {'Include': self.buildtype + '|' + target_platform}) - p = ET.SubElement(prjconf, 'Configuration') - p.text = self.buildtype - pl = ET.SubElement(prjconf, 'Platform') - pl.text = target_platform + + multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() if self.gen_lite else [self.buildtype] + for buildtype in multi_config_buildtype_list: + prjconf = ET.SubElement(confitems, 'ProjectConfiguration', + {'Include': buildtype + '|' + target_platform}) + ET.SubElement(prjconf, 'Configuration').text = buildtype + ET.SubElement(prjconf, 'Platform').text = target_platform # Globals globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals') @@ -568,50 +653,56 @@ 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 = target_platform - pname = ET.SubElement(globalgroup, 'ProjectName') - 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 + # Configuration type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration') 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) + # This must come AFTER the '' element; importing before the 'PlatformToolset' elt + # gets set leads to msbuild failures reporting - + # "The build tools for v142 (Platform Toolset = 'v142') cannot be found. ... please install v142 build tools." + # This is extremely unhelpful and misleading since the v14x build tools ARE installed. 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 = temp_dir + '\\' + if not self.gen_lite: # Plenty of elements aren't necessary for 'makefile'-style project that just redirects to meson builds + # 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 = target_platform + pname = ET.SubElement(globalgroup, 'ProjectName') + 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(type_config, 'CharacterSet').text = 'MultiByte' + # Fixme: wasn't here before for gen_vcxproj() + ET.SubElement(type_config, 'UseOfMfc').text = 'false' + + # 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 = temp_dir + '\\' - tname = ET.SubElement(direlem, 'TargetName') - tname.text = target_name + tname = ET.SubElement(direlem, 'TargetName') + tname.text = target_name - if target_ext: - ET.SubElement(direlem, 'TargetExt').text = target_ext + if target_ext: + ET.SubElement(direlem, 'TargetExt').text = target_ext return (root, type_config) - def gen_run_target_vcxproj(self, target, ofname, guid): + def gen_run_target_vcxproj(self, target: build.RunTarget, ofname: str, guid: str) -> None: (root, type_config) = self.create_basic_project(target.name, temp_dir=target.get_id(), guid=guid) @@ -641,7 +732,7 @@ self.add_target_deps(root, target) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) - def gen_custom_target_vcxproj(self, target, ofname, guid): + def gen_custom_target_vcxproj(self, target: build.CustomTarget, ofname: str, guid: str) -> None: if target.for_machine is MachineChoice.BUILD: platform = self.build_platform else: @@ -681,7 +772,7 @@ self.add_target_deps(root, target) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) - def gen_compile_target_vcxproj(self, target, ofname, guid): + def gen_compile_target_vcxproj(self, target: build.CompileTarget, ofname: str, guid: str) -> None: if target.for_machine is MachineChoice.BUILD: platform = self.build_platform else: @@ -765,6 +856,36 @@ args.append(self.escape_additional_option(arg)) ET.SubElement(parent_node, "AdditionalOptions").text = ' '.join(args) + # Set up each project's source file ('CLCompile') element with appropriate preprocessor, include dir, and compile option values for correct intellisense. + def add_project_nmake_defs_incs_and_opts(self, parent_node, src: str, defs_paths_opts_per_lang_and_buildtype: dict, platform: str): + # For compactness, sources whose type matches the primary src type (i.e. most frequent in the set of source types used in the target/project, + # according to the 'captured_build_args' map), can simply reference the preprocessor definitions, include dirs, and compile option NMake fields of + # the project itself. + # However, if a src is of a non-primary type, it could have totally different defs/dirs/options so we're going to have to fill in the full, verbose + # set of values for these fields, which needs to be fully expanded per build type / configuration. + # + # FIXME: Suppose a project contains .cpp and .c src files with different compile defs/dirs/options, while also having .h files, some of which + # are included by .cpp sources and others included by .c sources: How do we know whether the .h source should be using the .cpp or .c src + # defs/dirs/options? Might it also be possible for a .h header to be shared between .cpp and .c sources? If so, I don't see how we can + # correctly configure these intellisense fields. + # For now, all sources/headers that fail to find their extension's language in the '...nmake_defs_paths_opts...' map will just adopt the project + # defs/dirs/opts that are set for the nominal 'primary' src type. + ext = src.split('.')[-1] + lang = compilers.compilers.SUFFIX_TO_LANG.get(ext, None) + if lang in defs_paths_opts_per_lang_and_buildtype.keys(): + # This is a non-primary src type for which can't simply reference the project's nmake fields; + # we must laboriously fill in the fields for all buildtypes. + for buildtype in coredata.get_genvs_default_buildtype_list(): + (defs, paths, opts) = defs_paths_opts_per_lang_and_buildtype[lang][buildtype] + condition = f'\'$(Configuration)|$(Platform)\'==\'{buildtype}|{platform}\'' + ET.SubElement(parent_node, 'PreprocessorDefinitions', Condition=condition).text = defs + ET.SubElement(parent_node, 'AdditionalIncludeDirectories', Condition=condition).text = paths + ET.SubElement(parent_node, 'AdditionalOptions', Condition=condition).text = opts + else: # Can't find bespoke nmake defs/dirs/opts fields for this extention, so just reference the project's fields + ET.SubElement(parent_node, 'PreprocessorDefinitions').text = '$(NMakePreprocessorDefinitions)' + ET.SubElement(parent_node, 'AdditionalIncludeDirectories').text = '$(NMakeIncludeSearchPath)' + ET.SubElement(parent_node, 'AdditionalOptions').text = '$(AdditionalOptions)' + def add_preprocessor_defines(self, lang, parent_node, file_defines): defines = [] for define in file_defines[lang]: @@ -791,7 +912,7 @@ return @staticmethod - def escape_preprocessor_define(define): + def escape_preprocessor_define(define: str) -> str: # See: https://msdn.microsoft.com/en-us/library/bb383819.aspx table = str.maketrans({'%': '%25', '$': '%24', '@': '%40', "'": '%27', ';': '%3B', '?': '%3F', '*': '%2A', @@ -802,7 +923,7 @@ return define.translate(table) @staticmethod - def escape_additional_option(option): + def escape_additional_option(option: str) -> str: # See: https://msdn.microsoft.com/en-us/library/bb383819.aspx table = str.maketrans({'%': '%25', '$': '%24', '@': '%40', "'": '%27', ';': '%3B', '?': '%3F', '*': '%2A', ' ': '%20'}) @@ -816,6 +937,39 @@ return f'"{option}"' @staticmethod + def add_filter_info(list_filters_path, filter_group, sub_element, file_path, forced_filter_name=None, down=''): + filter_inc_cl = ET.SubElement(filter_group, sub_element, Include=file_path) + + # Force the subdir + if forced_filter_name: + filter_path = forced_filter_name + else: + # Create a subdir following the placement if on the same drive + filter_path = Path(file_path).resolve().parent + if Path(file_path).drive == Path(down).drive: + filter_path = Path(os.path.relpath(str(filter_path), down)).as_posix().replace('../', '').replace('..', '') + else: + return # No filter needed + + # Needed to have non posix path + filter_path = filter_path.replace('/', '\\') + + if filter_path and filter_path != '.': + # Remove ending backslash + filter_path = filter_path.rstrip('\\') + # Create a hierarchical level of directories + list_path = filter_path.split('\\') + new_filter_path = '' + for path in list_path: + if new_filter_path: + new_filter_path = new_filter_path + '\\' + path + else: + new_filter_path = path + list_filters_path.add(new_filter_path) + # Create a new filter node for the current file added + ET.SubElement(filter_inc_cl, 'Filter').text = filter_path + + @staticmethod def split_link_args(args): """ Split a list of link arguments into three lists: @@ -860,154 +1014,18 @@ return c raise MesonException('Could not find a C or C++ compiler. MSVC can only build C/C++ projects.') - def _prettyprint_vcxproj_xml(self, tree, ofname): + def _prettyprint_vcxproj_xml(self, tree: ET.ElementTree, ofname: str) -> None: ofname_tmp = ofname + '~' tree.write(ofname_tmp, encoding='utf-8', xml_declaration=True) - # ElementTree can not do prettyprinting so do it manually + # ElementTree cannot do pretty-printing, so do it manually doc = xml.dom.minidom.parse(ofname_tmp) with open(ofname_tmp, 'w', encoding='utf-8') as of: of.write(doc.toprettyxml()) replace_if_different(ofname, ofname_tmp) - def gen_vcxproj(self, target, ofname, guid): - mlog.debug(f'Generating vcxproj {target.name}.') - subsystem = 'Windows' - self.handled_target_deps[target.get_id()] = [] - if isinstance(target, build.Executable): - conftype = 'Application' - 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' - 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) - elif isinstance(target, build.CompileTarget): - return self.gen_compile_target_vcxproj(target, ofname, guid) - else: - 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 - proj_to_src_root = os.path.join(down, self.build_to_src) - # Prefix to use to access the source tree's subdir from the vcxproj dir - proj_to_src_dir = os.path.join(proj_to_src_root, self.get_target_dir(target)) - (sources, headers, objects, languages) = self.split_sources(target.sources) - if target.is_unity: - sources = self.generate_unity_files(target, sources) - compiler = self._get_cl_compiler(target) - 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.options[OptionKey('b_vscrt')] - target_name = target.name - 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 - ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'Default' - # Incremental linking increases code size - if '/INCREMENTAL:NO' in buildtype_link_args: - ET.SubElement(type_config, 'LinkIncremental').text = 'false' - - # Build information - compiles = ET.SubElement(root, 'ItemDefinitionGroup') - clconf = ET.SubElement(compiles, 'ClCompile') - # CRT type; debug or release - if vscrt_type.value == 'from_buildtype': - 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' - ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebugDLL' - elif vscrt_type.value == 'mt': - # FIXME, wrong - ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' - ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreaded' - elif vscrt_type.value == 'mtd': - # FIXME, wrong - 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 = 'MultiThreadedDLL' - # Sanitizers - if '/fsanitize=address' in build_args: - ET.SubElement(type_config, 'EnableASAN').text = 'true' - # Debug format - 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 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 - + # Returns: (target_args,file_args), (target_defines,file_defines), (target_inc_dirs,file_inc_dirs) + def get_args_defines_and_inc_dirs(self, target, compiler, generated_files_include_dirs, proj_to_src_root, proj_to_src_dir, build_args): # Arguments, include dirs, defines for all files in the current target target_args = [] target_defines = [] @@ -1017,7 +1035,7 @@ # # file_args is also later split out into defines and include_dirs in # case someone passed those in there - file_args = {l: c.compiler_args() for l, c in target.compilers.items()} + file_args: T.Dict[str, CompilerArgs] = {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 @@ -1041,8 +1059,7 @@ # 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 l in file_args.keys(): - opts = self.environment.coredata.options[OptionKey('args', machine=target.for_machine, lang=l)] - file_args[l] += opts.value + file_args[l] += target.get_option(OptionKey('args', machine=target.for_machine, lang=l)) 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). @@ -1068,8 +1085,9 @@ for i in reversed(d.get_incdirs()): curdir = os.path.join(d.get_curdir(), i) try: - args.append('-I' + self.relpath(curdir, target.subdir)) # build dir + # Add source subdir first so that the build subdir overrides it args.append('-I' + os.path.join(proj_to_src_root, curdir)) # src dir + args.append('-I' + self.relpath(curdir, target.subdir)) # build dir except ValueError: # Include is on different drive args.append('-I' + os.path.normpath(curdir)) @@ -1123,9 +1141,7 @@ for d in reversed(target.get_external_deps()): # Cflags required by external deps might have UNIX-specific flags, # so filter them out if needed - if isinstance(d, dependencies.OpenMPDependency): - ET.SubElement(clconf, 'OpenMPSupport').text = 'true' - else: + if d.name != 'openmp': d_compile_args = compiler.unix_args_to_native(d.get_compile_args()) for arg in d_compile_args: if arg.startswith(('-D', '/D')): @@ -1142,9 +1158,263 @@ else: target_args.append(arg) - languages += gen_langs if '/Gw' in build_args: target_args.append('/Gw') + + return (target_args, file_args), (target_defines, file_defines), (target_inc_dirs, file_inc_dirs) + + @staticmethod + def get_build_args(compiler, buildtype: str, optimization_level: str, debug: bool, sanitize: str) -> T.List[str]: + build_args = compiler.get_buildtype_args(buildtype) + build_args += compiler.get_optimization_args(optimization_level) + build_args += compiler.get_debug_args(debug) + build_args += compiler.sanitizer_compile_args(sanitize) + + return build_args + + #Convert a list of compile arguments from - + # [ '-I..\\some\\dir\\include', '-I../../some/other/dir', '/MDd', '/W2', '/std:c++17', '/Od', '/Zi', '-DSOME_DEF=1', '-DANOTHER_DEF=someval', ...] + #to - + # 'SOME_DEF=1;ANOTHER_DEF=someval;' + #which is the format required by the visual studio project's NMakePreprocessorDefinitions field. + @staticmethod + def extract_nmake_preprocessor_defs(captured_build_args: list[str]) -> str: + defs = '' + for arg in captured_build_args: + if arg.startswith(('-D', '/D')): + defs += arg[2:] + ';' + return defs + + #Convert a list of compile arguments from - + # [ '-I..\\some\\dir\\include', '-I../../some/other/dir', '/MDd', '/W2', '/std:c++17', '/Od', '/Zi', '-DSOME_DEF=1', '-DANOTHER_DEF=someval', ...] + #to - + # '..\\some\\dir\\include;../../some/other/dir;' + #which is the format required by the visual studio project's NMakePreprocessorDefinitions field. + @staticmethod + def extract_nmake_include_paths(captured_build_args: list[str]) -> str: + paths = '' + for arg in captured_build_args: + if arg.startswith(('-I', '/I')): + paths += arg[2:] + ';' + return paths + + #Convert a list of compile arguments from - + # [ '-I..\\some\\dir\\include', '-I../../some/other/dir', '/MDd', '/W2', '/std:c++17', '/Od', '/Zi', '-DSOME_DEF=1', '-DANOTHER_DEF=someval', ...] + #to - + # '/MDd;/W2;/std:c++17;/Od/Zi' + #which is the format required by the visual studio project's NMakePreprocessorDefinitions field. + @staticmethod + def extract_intellisense_additional_compiler_options(captured_build_args: list[str]) -> str: + additional_opts = '' + for arg in captured_build_args: + if (not arg.startswith(('-D', '/D', '-I', '/I'))) and arg.startswith(('-', '/')): + additional_opts += arg + ';' + return additional_opts + + @staticmethod + def get_nmake_base_meson_command_and_exe_search_paths() -> T.Tuple[str, str]: + meson_cmd_list = mesonlib.get_meson_command() + assert (len(meson_cmd_list) == 1) or (len(meson_cmd_list) == 2) + # We expect get_meson_command() to either be of the form - + # 1: ['path/to/meson.exe'] + # or - + # 2: ['path/to/python.exe', 'and/path/to/meson.py'] + # so we'd like to ensure our makefile-style project invokes the same meson executable or python src as this instance. + exe_search_paths = os.path.dirname(meson_cmd_list[0]) + nmake_base_meson_command = os.path.basename(meson_cmd_list[0]) + if len(meson_cmd_list) != 1: + # We expect to be dealing with case '2', shown above. + # With Windows, it's also possible that we get a path to the second element of meson_cmd_list that contains spaces + # (e.g. 'and/path to/meson.py'). So, because this will end up directly in the makefile/NMake command lines, we'd + # better always enclose it in quotes. Only strictly necessary for paths with spaces but no harm for paths without - + nmake_base_meson_command += ' \"' + meson_cmd_list[1] + '\"' + exe_search_paths += ';' + os.path.dirname(meson_cmd_list[1]) + + # Additionally, in some cases, we appear to have to add 'C:\Windows\system32;C:\Windows' to the 'Path' environment (via the + # ExecutablePath element), without which, the 'meson compile ...' (NMakeBuildCommandLine) command can fail (failure to find + # stdio.h and similar), so something is quietly switching some critical build behaviour based on the presence of these in + # the 'Path'. + # Not sure if this ultimately comes down to some 'find and guess' hidden behaviours within meson or within MSVC tools, but + # I guess some projects may implicitly rely on this behaviour. + # Things would be cleaner, more robust, repeatable, and portable if meson (and msvc tools) replaced all this kind of + # find/guess behaviour with the requirement that things just be explicitly specified by the user. + # An example of this can be seen with - + # 1: Download https://github.com/facebook/zstd source + # 2: cd to the 'zstd-dev\build\meson' dir + # 3: meson setup -Dbin_programs=true -Dbin_contrib=true --genvslite vs2022 builddir_vslite + # 4: Open the generated 'builddir_vslite_vs\zstd.sln' and build through a project, which should explicitly add the above to + # the project's 'Executable Directories' paths and build successfully. + # 5: Remove 'C:\Windows\system32;C:\Windows;' from the same project's 'Executable Directories' paths and rebuild. + # This should now fail. + # It feels uncomfortable to do this but what better alternative is there (and might this introduce new problems)? - + exe_search_paths += ';C:\\Windows\\system32;C:\\Windows' + # A meson project that explicitly specifies compiler/linker tools and sdk/include paths is not going to have any problems + # with this addition. + + return (nmake_base_meson_command, exe_search_paths) + + def add_gen_lite_makefile_vcxproj_elements(self, + root: ET.Element, + platform: str, + target_ext: str, + vslite_ctx: dict, + target, + proj_to_build_root: str, + primary_src_lang: T.Optional[str]) -> None: + ET.SubElement(root, 'ImportGroup', Label='ExtensionSettings') + ET.SubElement(root, 'ImportGroup', Label='Shared') + prop_sheets_grp = ET.SubElement(root, 'ImportGroup', Label='PropertySheets') + ET.SubElement(prop_sheets_grp, 'Import', {'Project': r'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props', + 'Condition': r"exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')", + 'Label': 'LocalAppDataPlatform' + }) + ET.SubElement(root, 'PropertyGroup', Label='UserMacros') + + (nmake_base_meson_command, exe_search_paths) = Vs2010Backend.get_nmake_base_meson_command_and_exe_search_paths() + + # Relative path from this .vcxproj to the directory containing the set of '..._[debug/debugoptimized/release]' setup meson build dirs. + proj_to_multiconfigured_builds_parent_dir = os.path.join(proj_to_build_root, '..') + + # Conditional property groups per configuration (buildtype). E.g. - + # + multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() + for buildtype in multi_config_buildtype_list: + per_config_prop_group = ET.SubElement(root, 'PropertyGroup', Condition=f'\'$(Configuration)|$(Platform)\'==\'{buildtype}|{platform}\'') + (_, build_dir_tail) = os.path.split(self.src_to_build) + meson_build_dir_for_buildtype = build_dir_tail[:-2] + buildtype # Get the buildtype suffixed 'builddir_[debug/release/etc]' from 'builddir_vs', for example. + proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype)) + ET.SubElement(per_config_prop_group, 'OutDir').text = f'{proj_to_build_dir_for_buildtype}\\' + ET.SubElement(per_config_prop_group, 'IntDir').text = f'{proj_to_build_dir_for_buildtype}\\' + ET.SubElement(per_config_prop_group, 'NMakeBuildCommandLine').text = f'{nmake_base_meson_command} compile -C "{proj_to_build_dir_for_buildtype}"' + ET.SubElement(per_config_prop_group, 'NMakeOutput').text = f'$(OutDir){target.name}{target_ext}' + captured_build_args = vslite_ctx[buildtype][target.get_id()] + # 'captured_build_args' is a dictionary, mapping from each src file type to a list of compile args to use for that type. + # Usually, there's just one but we could have multiple src types. However, since there's only one field for the makefile + # project's NMake... preprocessor/include intellisense fields, we'll just use the first src type we have to fill in + # these fields. Then, any src files in this VS project that aren't of this first src type will then need to override + # its intellisense fields instead of simply referencing the values in the project. + ET.SubElement(per_config_prop_group, 'NMakeReBuildCommandLine').text = f'{nmake_base_meson_command} compile -C "{proj_to_build_dir_for_buildtype}" --clean && {nmake_base_meson_command} compile -C "{proj_to_build_dir_for_buildtype}"' + ET.SubElement(per_config_prop_group, 'NMakeCleanCommandLine').text = f'{nmake_base_meson_command} compile -C "{proj_to_build_dir_for_buildtype}" --clean' + # Need to set the 'ExecutablePath' element for the above NMake... commands to be able to invoke the meson command. + ET.SubElement(per_config_prop_group, 'ExecutablePath').text = exe_search_paths + # We may not have any src files and so won't have a primary src language. In which case, we've nothing to fill in for this target's intellisense fields - + if primary_src_lang: + primary_src_type_build_args = captured_build_args[primary_src_lang] + ET.SubElement(per_config_prop_group, 'NMakePreprocessorDefinitions').text = Vs2010Backend.extract_nmake_preprocessor_defs(primary_src_type_build_args) + ET.SubElement(per_config_prop_group, 'NMakeIncludeSearchPath').text = Vs2010Backend.extract_nmake_include_paths(primary_src_type_build_args) + ET.SubElement(per_config_prop_group, 'AdditionalOptions').text = Vs2010Backend.extract_intellisense_additional_compiler_options(primary_src_type_build_args) + + # Unless we explicitly specify the following empty path elements, the project is assigned a load of nasty defaults that fill these + # with values like - + # $(VC_IncludePath);$(WindowsSDK_IncludePath); + # which are all based on the current install environment (a recipe for non-reproducibility problems), not the paths that will be used by + # the actual meson compile jobs. Although these elements look like they're only for MSBuild operations, they're not needed with our simple, + # lite/makefile-style projects so let's just remove them in case they do get used/confused by intellisense. + ET.SubElement(per_config_prop_group, 'IncludePath') + ET.SubElement(per_config_prop_group, 'ExternalIncludePath') + ET.SubElement(per_config_prop_group, 'ReferencePath') + ET.SubElement(per_config_prop_group, 'LibraryPath') + ET.SubElement(per_config_prop_group, 'LibraryWPath') + ET.SubElement(per_config_prop_group, 'SourcePath') + ET.SubElement(per_config_prop_group, 'ExcludePath') + + def add_non_makefile_vcxproj_elements( + self, + root: ET.Element, + type_config: ET.Element, + target, + platform: str, + subsystem, + build_args, + target_args, + target_defines, + target_inc_dirs, + file_args + ) -> None: + compiler = self._get_cl_compiler(target) + buildtype_link_args = compiler.get_buildtype_linker_args(self.buildtype) + + # Prefix to use to access the build root from the vcxproj dir + down = self.target_to_build_root(target) + + # FIXME: Should the following 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 + ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'Default' + # Incremental linking increases code size + if '/INCREMENTAL:NO' in buildtype_link_args: + ET.SubElement(type_config, 'LinkIncremental').text = 'false' + + # Build information + compiles = ET.SubElement(root, 'ItemDefinitionGroup') + clconf = ET.SubElement(compiles, 'ClCompile') + if True in ((dep.name == 'openmp') for dep in target.get_external_deps()): + ET.SubElement(clconf, 'OpenMPSupport').text = 'true' + # CRT type; debug or release + vscrt_type = target.get_option(OptionKey('b_vscrt')) + if vscrt_type == 'from_buildtype': + 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 == '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 == 'mdd': + ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' + ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebugDLL' + elif vscrt_type == 'mt': + # FIXME, wrong + ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' + ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreaded' + elif vscrt_type == 'mtd': + # FIXME, wrong + 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 = 'MultiThreadedDLL' + # Sanitizers + if '/fsanitize=address' in build_args: + ET.SubElement(type_config, 'EnableASAN').text = 'true' + # Debug format + 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 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 = target.get_option(OptionKey('eh', machine=target.for_machine, lang='cpp')) + if eh == 'a': + ET.SubElement(clconf, 'ExceptionHandling').text = 'Async' + elif eh == 's': + ET.SubElement(clconf, 'ExceptionHandling').text = 'SyncCThrow' + elif eh == 'none': + ET.SubElement(clconf, 'ExceptionHandling').text = 'false' + else: # 'sc' or 'default' + ET.SubElement(clconf, 'ExceptionHandling').text = 'Sync' + if len(target_args) > 0: target_args.append('%(AdditionalOptions)') ET.SubElement(clconf, "AdditionalOptions").text = ' '.join(target_args) @@ -1153,7 +1423,7 @@ ET.SubElement(clconf, 'PreprocessorDefinitions').text = ';'.join(target_defines) ET.SubElement(clconf, 'FunctionLevelLinking').text = 'true' # Warning level - warning_level = target.get_option(OptionKey('warning_level')) + warning_level = T.cast('str', target.get_option(OptionKey('warning_level'))) ET.SubElement(clconf, 'WarningLevel').text = 'Level' + str(1 + int(warning_level)) if target.get_option(OptionKey('werror')): ET.SubElement(clconf, 'TreatWarningAsError').text = 'true' @@ -1181,25 +1451,6 @@ 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.options.get(OptionKey('b_pch')): - for lang in ['c', 'cpp']: - pch = target.get_pch(lang) - if not pch: - continue - if compiler.id == 'msvc': - if len(pch) == 1: - # Auto generate PCH. - src = os.path.join(down, self.create_msvc_pch_implementation(target, lang, pch[0])) - pch_header_dir = os.path.dirname(os.path.join(proj_to_src_dir, pch[0])) - else: - src = os.path.join(proj_to_src_dir, pch[1]) - pch_header_dir = None - pch_sources[lang] = [pch[0], src, lang, pch_header_dir] - else: - # 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] resourcecompile = ET.SubElement(compiles, 'ResourceCompile') ET.SubElement(resourcecompile, 'PreprocessorDefinitions') @@ -1218,8 +1469,7 @@ ET.SubElement(link, 'GenerateDebugInformation').text = 'false' if not isinstance(target, build.StaticLibrary): if isinstance(target, build.SharedModule): - options = self.environment.coredata.options - extra_link_args += compiler.get_std_shared_module_link_args(options) + extra_link_args += compiler.get_std_shared_module_link_args(target.get_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) # Add link args added using add_global_link_arguments() @@ -1236,15 +1486,15 @@ for dep in target.get_external_deps(): # Extend without reordering or de-dup to preserve `-L -l` sets # https://github.com/mesonbuild/meson/issues/1718 - if isinstance(dep, dependencies.OpenMPDependency): - ET.SubElement(clconf, 'OpenMPSuppport').text = 'true' + if dep.name == 'openmp': + ET.SubElement(clconf, 'OpenMPSupport').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): - ET.SubElement(clconf, 'OpenMPSuppport').text = 'true' + if dep.name == 'openmp': + ET.SubElement(clconf, 'OpenMPSupport').text = 'true' else: extra_link_args.extend_direct(dep.get_link_args()) # Add link args for c_* or cpp_* build options. Currently this only @@ -1252,7 +1502,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.options) + extra_link_args += compiler.get_option_link_args(target.get_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 @@ -1307,12 +1557,6 @@ additional_links.append(linkname) for lib in self.get_custom_target_provided_libraries(target): additional_links.append(self.relpath(lib, self.get_target_dir(target))) - additional_objects = [] - for o in self.flatten_object_list(target, down)[0]: - assert isinstance(o, str) - additional_objects.append(o) - for o in custom_objs: - additional_objects.append(o) if len(extra_link_args) > 0: extra_link_args.append('%(AdditionalOptions)') @@ -1338,7 +1582,7 @@ ET.SubElement(link, 'ModuleDefinitionFile').text = relpath if self.debug: pdb = ET.SubElement(link, 'ProgramDataBaseFileName') - pdb.text = f'$(OutDir){target_name}.pdb' + pdb.text = f'$(OutDir){target.name}.pdb' targetmachine = ET.SubElement(link, 'TargetMachine') if target.for_machine is MachineChoice.BUILD: targetplatform = platform.lower() @@ -1359,9 +1603,119 @@ # /nologo ET.SubElement(link, 'SuppressStartupBanner').text = 'true' # /release - if not self.environment.coredata.get_option(OptionKey('debug')): + if not target.get_option(OptionKey('debug')): ET.SubElement(link, 'SetChecksum').text = 'true' + # Visual studio doesn't simply allow the src files of a project to be added with the 'Condition=...' attribute, + # to allow us to point to the different debug/debugoptimized/release sets of generated src files for each of + # the solution's configurations. Similarly, 'ItemGroup' also doesn't support 'Condition'. So, without knowing + # a better (simple) alternative, for now, we'll repoint these generated sources (which will be incorrectly + # pointing to non-existent files under our '[builddir]_vs' directory) to the appropriate location under one of + # our buildtype build directores (e.g. '[builddir]_debug'). + # This will at least allow the user to open the files of generated sources listed in the solution explorer, + # once a build/compile has generated these sources. + # + # This modifies the paths in 'gen_files' in place, as opposed to returning a new list of modified paths. + def relocate_generated_file_paths_to_concrete_build_dir(self, gen_files: T.List[str], target: T.Union[build.Target, build.CustomTargetIndex]) -> None: + (_, build_dir_tail) = os.path.split(self.src_to_build) + meson_build_dir_for_buildtype = build_dir_tail[:-2] + coredata.get_genvs_default_buildtype_list()[0] # Get the first buildtype suffixed dir (i.e. '[builddir]_debug') from '[builddir]_vs' + # Relative path from this .vcxproj to the directory containing the set of '..._[debug/debugoptimized/release]' setup meson build dirs. + proj_to_build_root = self.target_to_build_root(target) + proj_to_multiconfigured_builds_parent_dir = os.path.join(proj_to_build_root, '..') + proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype)) + relocate_to_concrete_builddir_target = os.path.normpath(os.path.join(proj_to_build_dir_for_buildtype, self.get_target_dir(target))) + for idx, file_path in enumerate(gen_files): + gen_files[idx] = os.path.normpath(os.path.join(relocate_to_concrete_builddir_target, file_path)) + + # Returns bool indicating whether the .vcxproj has been generated. + # Under some circumstances, it's unnecessary to create some .vcxprojs, so, when generating the .sln, + # we need to respect that not all targets will have generated a project. + def gen_vcxproj(self, target: build.BuildTarget, ofname: str, guid: str, vslite_ctx: dict = None) -> bool: + mlog.debug(f'Generating vcxproj {target.name}.') + subsystem = 'Windows' + self.handled_target_deps[target.get_id()] = [] + + if self.gen_lite: + if not isinstance(target, build.BuildTarget): + # Since we're going to delegate all building to the one true meson build command, we don't need + # to generate .vcxprojs for targets that don't add any source files or just perform custom build + # commands. These are targets of types CustomTarget or RunTarget. So let's just skip generating + # these otherwise insubstantial non-BuildTarget targets. + return False + conftype = 'Makefile' + elif isinstance(target, build.Executable): + conftype = 'Application' + 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' + elif isinstance(target, build.CustomTarget): + self.gen_custom_target_vcxproj(target, ofname, guid) + return True + elif isinstance(target, build.RunTarget): + self.gen_run_target_vcxproj(target, ofname, guid) + return True + elif isinstance(target, build.CompileTarget): + self.gen_compile_target_vcxproj(target, ofname, guid) + return True + else: + raise MesonException(f'Unknown target type for {target.get_basename()}') + + (sources, headers, objects, _languages) = self.split_sources(target.sources) + if target.is_unity: + sources = self.generate_unity_files(target, sources) + 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) + + # vcxproj.filters file + root_filter = self.create_basic_project_filters() + + 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 + + compiler = self._get_cl_compiler(target) + build_args = Vs2010Backend.get_build_args(compiler, self.buildtype, self.optimization, self.debug, self.sanitize) + + assert isinstance(target, (build.Executable, build.SharedLibrary, build.StaticLibrary, build.SharedModule)), 'for mypy' + # Prefix to use to access the build root from the vcxproj dir + proj_to_build_root = self.target_to_build_root(target) + # Prefix to use to access the source tree's root from the vcxproj dir + proj_to_src_root = os.path.join(proj_to_build_root, self.build_to_src) + # Prefix to use to access the source tree's subdir from the vcxproj dir + proj_to_src_dir = os.path.join(proj_to_src_root, self.get_target_dir(target)) + + (target_args, file_args), (target_defines, file_defines), (target_inc_dirs, file_inc_dirs) = self.get_args_defines_and_inc_dirs( + target, compiler, generated_files_include_dirs, proj_to_src_root, proj_to_src_dir, build_args) + + if self.gen_lite: + assert vslite_ctx is not None + primary_src_lang = get_primary_source_lang(target.sources, custom_src) + self.add_gen_lite_makefile_vcxproj_elements(root, platform, tfilename[1], vslite_ctx, target, proj_to_build_root, primary_src_lang) + else: + self.add_non_makefile_vcxproj_elements(root, type_config, target, platform, subsystem, build_args, target_args, target_defines, target_inc_dirs, file_args) + meson_file_group = ET.SubElement(root, 'ItemGroup') ET.SubElement(meson_file_group, 'None', Include=os.path.join(proj_to_src_dir, build_filename)) @@ -1375,71 +1729,144 @@ else: return False + pch_sources = {} + if self.target_uses_pch(target): + for lang in ['c', 'cpp']: + pch = target.get_pch(lang) + if not pch: + continue + if compiler.id == 'msvc': + if len(pch) == 1: + # Auto generate PCH. + src = os.path.join(proj_to_build_root, self.create_msvc_pch_implementation(target, lang, pch[0])) + pch_header_dir = os.path.dirname(os.path.join(proj_to_src_dir, pch[0])) + else: + src = os.path.join(proj_to_src_dir, pch[1]) + pch_header_dir = None + pch_sources[lang] = [pch[0], src, lang, pch_header_dir] + else: + # 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] + + list_filters_path = set() + previous_includes = [] if len(headers) + len(gen_hdrs) + len(target.extra_files) + len(pch_sources) > 0: + if self.gen_lite and gen_hdrs: + # Although we're constructing our .vcxproj under our '..._vs' directory, we want to reference generated files + # in our concrete build directories (e.g. '..._debug'), where generated files will exist after building. + self.relocate_generated_file_paths_to_concrete_build_dir(gen_hdrs, target) + + # Filter information + filter_group_include = ET.SubElement(root_filter, 'ItemGroup') + inc_hdrs = ET.SubElement(root, 'ItemGroup') for h in headers: - relpath = os.path.join(down, h.rel_to_builddir(self.build_to_src)) + relpath = os.path.join(proj_to_build_root, h.rel_to_builddir(self.build_to_src)) if path_normalize_add(relpath, previous_includes): + self.add_filter_info(list_filters_path, filter_group_include, 'ClInclude', relpath, h.subdir) ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath) for h in gen_hdrs: if path_normalize_add(h, previous_includes): + self.add_filter_info(list_filters_path, filter_group_include, 'ClInclude', h) ET.SubElement(inc_hdrs, 'CLInclude', Include=h) for h in target.extra_files: - relpath = os.path.join(down, h.rel_to_builddir(self.build_to_src)) + relpath = os.path.join(proj_to_build_root, h.rel_to_builddir(self.build_to_src)) if path_normalize_add(relpath, previous_includes): + self.add_filter_info(list_filters_path, filter_group_include, 'ClInclude', relpath, h.subdir) ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath) for headers in pch_sources.values(): path = os.path.join(proj_to_src_dir, headers[0]) if path_normalize_add(path, previous_includes): + self.add_filter_info(list_filters_path, filter_group_include, 'ClInclude', path, 'pch') ET.SubElement(inc_hdrs, 'CLInclude', Include=path) previous_sources = [] if len(sources) + len(gen_src) + len(pch_sources) > 0: + if self.gen_lite: + # Get data to fill in intellisense fields for sources that can't reference the project-wide values + defs_paths_opts_per_lang_and_buildtype = get_non_primary_lang_intellisense_fields( + vslite_ctx, + target.get_id(), + primary_src_lang) + if gen_src: + # Although we're constructing our .vcxproj under our '..._vs' directory, we want to reference generated files + # in our concrete build directories (e.g. '..._debug'), where generated files will exist after building. + self.relocate_generated_file_paths_to_concrete_build_dir(gen_src, target) + + # Filter information + filter_group_compile = ET.SubElement(root_filter, 'ItemGroup') + inc_src = ET.SubElement(root, 'ItemGroup') for s in sources: - relpath = os.path.join(down, s.rel_to_builddir(self.build_to_src)) + relpath = os.path.join(proj_to_build_root, s.rel_to_builddir(self.build_to_src)) if path_normalize_add(relpath, previous_sources): + self.add_filter_info(list_filters_path, filter_group_compile, 'CLCompile', relpath, s.subdir) inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath) - lang = Vs2010Backend.lang_from_source_file(s) - self.add_pch(pch_sources, lang, inc_cl) - 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) + if self.gen_lite: + self.add_project_nmake_defs_incs_and_opts(inc_cl, relpath, defs_paths_opts_per_lang_and_buildtype, platform) + else: + lang = Vs2010Backend.lang_from_source_file(s) + self.add_pch(pch_sources, lang, inc_cl) + 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) for s in gen_src: if path_normalize_add(s, previous_sources): + self.add_filter_info(list_filters_path, filter_group_compile, 'CLCompile', s) inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=s) - lang = Vs2010Backend.lang_from_source_file(s) - self.add_pch(pch_sources, lang, inc_cl) - 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) + if self.gen_lite: + self.add_project_nmake_defs_incs_and_opts(inc_cl, s, defs_paths_opts_per_lang_and_buildtype, platform) + else: + lang = Vs2010Backend.lang_from_source_file(s) + self.add_pch(pch_sources, lang, inc_cl) + 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, headers in pch_sources.items(): impl = headers[1] if impl and path_normalize_add(impl, previous_sources): + self.add_filter_info(list_filters_path, filter_group_compile, 'CLCompile', impl, 'pch') inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=impl) self.create_pch(pch_sources, lang, inc_cl) - self.add_additional_options(lang, inc_cl, file_args) - self.add_preprocessor_defines(lang, inc_cl, file_defines) - pch_header_dir = pch_sources[lang][3] - if pch_header_dir: - inc_dirs = copy.deepcopy(file_inc_dirs) - inc_dirs[lang] = [pch_header_dir] + inc_dirs[lang] + if self.gen_lite: + self.add_project_nmake_defs_incs_and_opts(inc_cl, impl, defs_paths_opts_per_lang_and_buildtype, platform) 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? + self.add_additional_options(lang, inc_cl, file_args) + self.add_preprocessor_defines(lang, inc_cl, file_defines) + pch_header_dir = pch_sources[lang][3] + if pch_header_dir: + inc_dirs = copy.deepcopy(file_inc_dirs) + inc_dirs[lang] = [pch_header_dir] + inc_dirs[lang] + 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 here too? + + # Filter information + filter_group = ET.SubElement(root_filter, 'ItemGroup') + for filter_dir in list_filters_path: + filter = ET.SubElement(filter_group, 'Filter', Include=filter_dir) + ET.SubElement(filter, 'UniqueIdentifier').text = '{' + str(uuid.uuid4()) + '}' + + additional_objects = [] + for o in self.flatten_object_list(target, proj_to_build_root)[0]: + assert isinstance(o, str) + additional_objects.append(o) + for o in custom_objs: + additional_objects.append(o) previous_objects = [] if self.has_objects(objects, additional_objects, gen_objs): inc_objs = ET.SubElement(root, 'ItemGroup') for s in objects: - relpath = os.path.join(down, s.rel_to_builddir(self.build_to_src)) + relpath = os.path.join(proj_to_build_root, s.rel_to_builddir(self.build_to_src)) if path_normalize_add(relpath, previous_objects): ET.SubElement(inc_objs, 'Object', Include=relpath) for s in additional_objects: @@ -1449,84 +1876,197 @@ ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') self.add_regen_dependency(root) - self.add_target_deps(root, target) + if not self.gen_lite: + # Injecting further target dependencies into this vcxproj implies and forces a Visual Studio BUILD dependency, + # which we don't want when using 'genvslite'. A gen_lite build as little involvement with the visual studio's + # build system as possible. + self.add_target_deps(root, target) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) + self._prettyprint_vcxproj_xml(ET.ElementTree(root_filter), ofname + '.filters') + return True + + def gen_regenproj(self): + # To fully adapt the REGEN work for a 'genvslite' solution, to check timestamps, settings, and regenerate the + # '[builddir]_vs' solution/vcxprojs, as well as regenerating the accompanying buildtype-suffixed ninja build + # directories (from which we need to first collect correct, updated preprocessor defs and compiler options in + # order to fill in the regenerated solution's intellisense settings) would require some non-trivial intrusion + # into the 'meson --internal regencheck ./meson-private' execution path (and perhaps also the '--internal + # regenerate' and even 'meson setup --reconfigure' code). So, for now, we'll instead give the user a simpler + # 'reconfigure' utility project that just runs 'meson setup --reconfigure [builddir]_[buildtype] [srcdir]' on + # each of the ninja build dirs. + # + # FIXME: That will keep the building and compiling correctly configured but obviously won't update the + # solution and vcxprojs, which may allow solution src files and intellisense options to go out-of-date; the + # user would still have to manually 'meson setup --genvslite [vsxxxx] [builddir] [srcdir]' to fully regenerate + # a complete and correct solution. + if self.gen_lite: + project_name = 'RECONFIGURE' + ofname = os.path.join(self.environment.get_build_dir(), 'RECONFIGURE.vcxproj') + conftype = 'Makefile' + # I find the REGEN project doesn't work; it fails to invoke the appropriate - + # python meson.py --internal regencheck builddir\meson-private + # command, despite the fact that manually running such a command in a shell runs just fine. + # Running/building the regen project produces the error - + # ...Microsoft.CppBuild.targets(460,5): error MSB8020: The build tools for ClangCL (Platform Toolset = 'ClangCL') cannot be found. To build using the ClangCL build tools, please install ... + # Not sure why but a simple makefile-style project that executes the full '...regencheck...' command actually works (and seems a little simpler). + # Although I've limited this change to only happen under '--genvslite', perhaps ... + # FIXME : Should all utility projects use the simpler and less problematic makefile-style project? + else: + project_name = 'REGEN' + ofname = os.path.join(self.environment.get_build_dir(), 'REGEN.vcxproj') + conftype = 'Utility' - def gen_regenproj(self, project_name, ofname): guid = self.environment.coredata.regen_guid (root, type_config) = self.create_basic_project(project_name, temp_dir='regen-temp', - guid=guid) + guid=guid, + conftype=conftype + ) + + if self.gen_lite: + (nmake_base_meson_command, exe_search_paths) = Vs2010Backend.get_nmake_base_meson_command_and_exe_search_paths() + all_configs_prop_group = ET.SubElement(root, 'PropertyGroup') + + # Multi-line command to reconfigure all buildtype-suffixed build dirs + multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() + (_, build_dir_tail) = os.path.split(self.src_to_build) + proj_to_multiconfigured_builds_parent_dir = '..' # We know this RECONFIGURE.vcxproj will always be in the '[buildir]_vs' dir. + proj_to_src_dir = self.build_to_src + reconfigure_all_cmd = '' + for buildtype in multi_config_buildtype_list: + meson_build_dir_for_buildtype = build_dir_tail[:-2] + buildtype # Get the buildtype suffixed 'builddir_[debug/release/etc]' from 'builddir_vs', for example. + proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype)) + reconfigure_all_cmd += f'{nmake_base_meson_command} setup --reconfigure "{proj_to_build_dir_for_buildtype}" "{proj_to_src_dir}"\n' + ET.SubElement(all_configs_prop_group, 'NMakeBuildCommandLine').text = reconfigure_all_cmd + ET.SubElement(all_configs_prop_group, 'NMakeReBuildCommandLine').text = reconfigure_all_cmd + ET.SubElement(all_configs_prop_group, 'NMakeCleanCommandLine').text = '' - action = ET.SubElement(root, 'ItemDefinitionGroup') - midl = ET.SubElement(action, 'Midl') - ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)' - ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)' - ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h' - ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb' - ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c' - ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c' - regen_command = self.environment.get_build_command() + ['--internal', 'regencheck'] - cmd_templ = '''call %s > NUL + #Need to set the 'ExecutablePath' element for the above NMake... commands to be able to execute + ET.SubElement(all_configs_prop_group, 'ExecutablePath').text = exe_search_paths + else: + action = ET.SubElement(root, 'ItemDefinitionGroup') + midl = ET.SubElement(action, 'Midl') + ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)' + ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)' + ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h' + ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb' + ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c' + ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c' + regen_command = self.environment.get_build_command() + ['--internal', 'regencheck'] + cmd_templ = '''call %s > NUL "%s" "%s"''' - regen_command = cmd_templ % \ - (self.get_vcvars_command(), '" "'.join(regen_command), self.environment.get_scratch_dir()) - self.add_custom_build(root, 'regen', regen_command, deps=self.get_regen_filelist(), - outputs=[Vs2010Backend.get_regen_stampfile(self.environment.get_build_dir())], - msg='Checking whether solution needs to be regenerated.') + regen_command = cmd_templ % \ + (self.get_vcvars_command(), '" "'.join(regen_command), self.environment.get_scratch_dir()) + self.add_custom_build(root, 'regen', regen_command, deps=self.get_regen_filelist(), + outputs=[Vs2010Backend.get_regen_stampfile(self.environment.get_build_dir())], + msg='Checking whether solution needs to be regenerated.') + ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') ET.SubElement(root, 'ImportGroup', Label='ExtensionTargets') self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) - def gen_testproj(self, target_name, ofname): + def gen_testproj(self): + project_name = 'RUN_TESTS' + ofname = os.path.join(self.environment.get_build_dir(), f'{project_name}.vcxproj') guid = self.environment.coredata.test_guid - (root, type_config) = self.create_basic_project(target_name, - temp_dir='test-temp', - guid=guid) + if self.gen_lite: + (root, type_config) = self.create_basic_project(project_name, + temp_dir='install-temp', + guid=guid, + conftype='Makefile' + ) + (nmake_base_meson_command, exe_search_paths) = Vs2010Backend.get_nmake_base_meson_command_and_exe_search_paths() + multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() + (_, build_dir_tail) = os.path.split(self.src_to_build) + proj_to_multiconfigured_builds_parent_dir = '..' # We know this .vcxproj will always be in the '[buildir]_vs' dir. + # Add appropriate 'test' commands for the 'build' action of this project, for all buildtypes + for buildtype in multi_config_buildtype_list: + meson_build_dir_for_buildtype = build_dir_tail[:-2] + buildtype # Get the buildtype suffixed 'builddir_[debug/release/etc]' from 'builddir_vs', for example. + proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype)) + test_cmd = f'{nmake_base_meson_command} test -C "{proj_to_build_dir_for_buildtype}" --no-rebuild' + if not self.environment.coredata.get_option(OptionKey('stdsplit')): + test_cmd += ' --no-stdsplit' + if self.environment.coredata.get_option(OptionKey('errorlogs')): + test_cmd += ' --print-errorlogs' + condition = f'\'$(Configuration)|$(Platform)\'==\'{buildtype}|{self.platform}\'' + prop_group = ET.SubElement(root, 'PropertyGroup', Condition=condition) + ET.SubElement(prop_group, 'NMakeBuildCommandLine').text = test_cmd + #Need to set the 'ExecutablePath' element for the NMake... commands to be able to execute + ET.SubElement(prop_group, 'ExecutablePath').text = exe_search_paths + else: + (root, type_config) = self.create_basic_project(project_name, + temp_dir='test-temp', + guid=guid) + + action = ET.SubElement(root, 'ItemDefinitionGroup') + midl = ET.SubElement(action, 'Midl') + ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)' + ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)' + ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h' + ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb' + ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c' + 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_option(OptionKey('stdsplit')): + test_command += ['--no-stdsplit'] + 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))) - action = ET.SubElement(root, 'ItemDefinitionGroup') - midl = ET.SubElement(action, 'Midl') - ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)' - ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)' - ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h' - ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb' - ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c' - 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_option(OptionKey('stdsplit')): - test_command += ['--no-stdsplit'] - 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))) ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') self.add_regen_dependency(root) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) - def gen_installproj(self, target_name, ofname): - self.create_install_data_files() - + def gen_installproj(self): + project_name = 'RUN_INSTALL' + ofname = os.path.join(self.environment.get_build_dir(), f'{project_name}.vcxproj') guid = self.environment.coredata.install_guid - (root, type_config) = self.create_basic_project(target_name, - temp_dir='install-temp', - guid=guid) + if self.gen_lite: + (root, type_config) = self.create_basic_project(project_name, + temp_dir='install-temp', + guid=guid, + conftype='Makefile' + ) + (nmake_base_meson_command, exe_search_paths) = Vs2010Backend.get_nmake_base_meson_command_and_exe_search_paths() + multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() + (_, build_dir_tail) = os.path.split(self.src_to_build) + proj_to_multiconfigured_builds_parent_dir = '..' # We know this .vcxproj will always be in the '[buildir]_vs' dir. + # Add appropriate 'install' commands for the 'build' action of this project, for all buildtypes + for buildtype in multi_config_buildtype_list: + meson_build_dir_for_buildtype = build_dir_tail[:-2] + buildtype # Get the buildtype suffixed 'builddir_[debug/release/etc]' from 'builddir_vs', for example. + proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype)) + install_cmd = f'{nmake_base_meson_command} install -C "{proj_to_build_dir_for_buildtype}" --no-rebuild' + condition = f'\'$(Configuration)|$(Platform)\'==\'{buildtype}|{self.platform}\'' + prop_group = ET.SubElement(root, 'PropertyGroup', Condition=condition) + ET.SubElement(prop_group, 'NMakeBuildCommandLine').text = install_cmd + #Need to set the 'ExecutablePath' element for the NMake... commands to be able to execute + ET.SubElement(prop_group, 'ExecutablePath').text = exe_search_paths + else: + self.create_install_data_files() + + (root, type_config) = self.create_basic_project(project_name, + temp_dir='install-temp', + guid=guid) + + action = ET.SubElement(root, 'ItemDefinitionGroup') + midl = ET.SubElement(action, 'Midl') + ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)' + ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)' + ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h' + ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb' + ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c' + ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c' + install_command = self.environment.get_build_command() + ['install', '--no-rebuild'] + self.add_custom_build(root, 'run_install', '"%s"' % ('" "'.join(install_command))) - action = ET.SubElement(root, 'ItemDefinitionGroup') - midl = ET.SubElement(action, 'Midl') - ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)' - ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)' - ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h' - ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb' - ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c' - ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c' - install_command = self.environment.get_build_command() + ['install', '--no-rebuild'] - self.add_custom_build(root, 'run_install', '"%s"' % ('" "'.join(install_command))) ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') 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, verify_files=True): + def add_custom_build(self, node: ET.Element, rulename: str, command: str, deps: T.Optional[T.List[str]] = None, + outputs: T.Optional[T.List[str]] = None, msg: T.Optional[str] = None, verify_files: bool = True) -> None: igroup = ET.SubElement(node, 'ItemGroup') rulefile = os.path.join(self.environment.get_scratch_dir(), rulename + '.rule') if not os.path.exists(rulefile): @@ -1556,20 +2096,23 @@ ET.SubElement(custombuild, 'AdditionalInputs').text = ';'.join(deps) @staticmethod - def nonexistent_file(prefix): + def nonexistent_file(prefix: str) -> str: i = 0 file = prefix while os.path.exists(file): file = '%s%d' % (prefix, i) return file - def generate_debug_information(self, link): + def generate_debug_information(self, link: ET.Element) -> None: # valid values for vs2015 is 'false', 'true', 'DebugFastLink' ET.SubElement(link, 'GenerateDebugInformation').text = 'true' - 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 add_regen_dependency(self, root: ET.Element) -> None: + # For now, with 'genvslite' solutions, REGEN is replaced by the lighter-weight RECONFIGURE utility that is + # no longer a forced build dependency. See comment in 'gen_regenproj' + if not self.gen_lite: + 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): + def generate_lang_standard_info(self, file_args: T.Dict[str, CompilerArgs], clconf: ET.Element) -> None: pass diff -Nru meson-1.0.1/mesonbuild/backend/vs2012backend.py meson-1.2.1/mesonbuild/backend/vs2012backend.py --- meson-1.0.1/mesonbuild/backend/vs2012backend.py 2022-06-19 19:10:14.000000000 +0000 +++ meson-1.2.1/mesonbuild/backend/vs2012backend.py 2023-05-23 15:20:02.000000000 +0000 @@ -23,9 +23,11 @@ from ..interpreter import Interpreter class Vs2012Backend(Vs2010Backend): + + name = 'vs2012' + 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' diff -Nru meson-1.0.1/mesonbuild/backend/vs2013backend.py meson-1.2.1/mesonbuild/backend/vs2013backend.py --- meson-1.0.1/mesonbuild/backend/vs2013backend.py 2022-06-19 19:10:14.000000000 +0000 +++ meson-1.2.1/mesonbuild/backend/vs2013backend.py 2023-05-23 15:20:02.000000000 +0000 @@ -22,9 +22,11 @@ from ..interpreter import Interpreter class Vs2013Backend(Vs2010Backend): + + name = 'vs2013' + 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' diff -Nru meson-1.0.1/mesonbuild/backend/vs2015backend.py meson-1.2.1/mesonbuild/backend/vs2015backend.py --- meson-1.0.1/mesonbuild/backend/vs2015backend.py 2022-06-19 19:10:14.000000000 +0000 +++ meson-1.2.1/mesonbuild/backend/vs2015backend.py 2023-05-23 15:20:02.000000000 +0000 @@ -23,9 +23,11 @@ from ..interpreter import Interpreter class Vs2015Backend(Vs2010Backend): + + name = 'vs2015' + 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' diff -Nru meson-1.0.1/mesonbuild/backend/vs2017backend.py meson-1.2.1/mesonbuild/backend/vs2017backend.py --- meson-1.0.1/mesonbuild/backend/vs2017backend.py 2022-06-19 19:10:14.000000000 +0000 +++ meson-1.2.1/mesonbuild/backend/vs2017backend.py 2023-05-23 15:20:02.000000000 +0000 @@ -26,9 +26,11 @@ class Vs2017Backend(Vs2010Backend): + + name = 'vs2017' + 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' diff -Nru meson-1.0.1/mesonbuild/backend/vs2019backend.py meson-1.2.1/mesonbuild/backend/vs2019backend.py --- meson-1.0.1/mesonbuild/backend/vs2019backend.py 2022-06-19 19:10:14.000000000 +0000 +++ meson-1.2.1/mesonbuild/backend/vs2019backend.py 2023-05-23 15:20:02.000000000 +0000 @@ -25,9 +25,11 @@ class Vs2019Backend(Vs2010Backend): + + name = 'vs2019' + 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: diff -Nru meson-1.0.1/mesonbuild/backend/vs2022backend.py meson-1.2.1/mesonbuild/backend/vs2022backend.py --- meson-1.0.1/mesonbuild/backend/vs2022backend.py 2022-06-19 19:10:14.000000000 +0000 +++ meson-1.2.1/mesonbuild/backend/vs2022backend.py 2023-06-28 14:48:20.000000000 +0000 @@ -25,9 +25,11 @@ class Vs2022Backend(Vs2010Backend): - def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]): - super().__init__(build, interpreter) - self.name = 'vs2022' + + name = 'vs2022' + + def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter], gen_lite: bool = False): + super().__init__(build, interpreter, gen_lite=gen_lite) self.sln_file_version = '12.00' self.sln_version_comment = 'Version 17' if self.environment is not None: diff -Nru meson-1.0.1/mesonbuild/backend/xcodebackend.py meson-1.2.1/mesonbuild/backend/xcodebackend.py --- meson-1.0.1/mesonbuild/backend/xcodebackend.py 2023-02-01 21:43:18.000000000 +0000 +++ meson-1.2.1/mesonbuild/backend/xcodebackend.py 2023-08-07 22:54:34.000000000 +0000 @@ -21,7 +21,7 @@ from .. import dependencies from .. import mesonlib from .. import mlog -from ..mesonlib import MesonException, OptionKey +from ..mesonlib import MesonBugException, MesonException, OptionKey if T.TYPE_CHECKING: from ..interpreter import Interpreter @@ -65,26 +65,21 @@ class FileTreeEntry: - def __init__(self): + def __init__(self) -> None: self.subdirs = {} self.targets = [] -class PbxItem: - def __init__(self, value, comment = ''): - self.value = value - self.comment = comment - class PbxArray: - def __init__(self): + def __init__(self) -> None: self.items = [] - def add_item(self, item, comment=''): + def add_item(self, item: T.Union[PbxArrayItem, str], comment: str = '') -> None: if isinstance(item, PbxArrayItem): self.items.append(item) else: self.items.append(PbxArrayItem(item, comment)) - def write(self, ofile, indent_level): + def write(self, ofile: T.TextIO, indent_level: int) -> None: ofile.write('(\n') indent_level += 1 for i in self.items: @@ -96,7 +91,7 @@ ofile.write(indent_level*INDENT + ');\n') class PbxArrayItem: - def __init__(self, value, comment = ''): + def __init__(self, value: str, comment: str = ''): self.value = value if comment: if '/*' in comment: @@ -107,16 +102,16 @@ self.comment = comment class PbxComment: - def __init__(self, text): + def __init__(self, text: str): assert isinstance(text, str) assert '/*' not in text self.text = f'/* {text} */' - def write(self, ofile, indent_level): + def write(self, ofile: T.TextIO, indent_level: int) -> None: ofile.write(f'\n{self.text}\n') class PbxDictItem: - def __init__(self, key, value, comment = ''): + def __init__(self, key: str, value: T.Union[PbxArray, PbxDict, str, int], comment: str = ''): self.key = key self.value = value if comment: @@ -128,13 +123,13 @@ self.comment = comment class PbxDict: - def __init__(self): + def __init__(self) -> None: # 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=''): + def add_item(self, key: str, value: T.Union[PbxArray, PbxDict, str, int], comment: str = '') -> None: assert key not in self.keys item = PbxDictItem(key, value, comment) self.keys.add(key) @@ -143,14 +138,11 @@ 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 add_comment(self, comment: PbxComment) -> None: + assert isinstance(comment, PbxComment) + self.items.append(comment) - def write(self, ofile, indent_level): + def write(self, ofile: T.TextIO, indent_level: int) -> None: ofile.write('{\n') indent_level += 1 for i in self.items: @@ -191,11 +183,13 @@ ofile.write(';\n') class XCodeBackend(backends.Backend): + + name = 'xcode' + 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.buildtype = T.cast('str', self.environment.coredata.get_option(OptionKey('buildtype'))) self.project_conflist = self.gen_id() self.maingroup_id = self.gen_id() self.all_id = self.gen_id() @@ -228,11 +222,11 @@ top_level_dict.write(ofile, 0) os.replace(tmpname, ofilename) - def gen_id(self): + def gen_id(self) -> str: return str(uuid.uuid4()).upper().replace('-', '')[:24] def get_target_dir(self, target): - dirname = os.path.join(target.get_subdir(), self.environment.coredata.get_option(OptionKey('buildtype'))) + dirname = os.path.join(target.get_subdir(), T.cast('str', self.environment.coredata.get_option(OptionKey('buildtype')))) #os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) return dirname @@ -260,7 +254,12 @@ obj_path = f'{project}.build/{buildtype}/{tname}.build/Objects-normal/{arch}/{stem}.o' return obj_path - def generate(self): + def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: + # Check for (currently) unexpected capture arg use cases - + if capture: + raise MesonBugException('We do not expect the xcode backend to generate with \'capture = True\'') + if vslite_ctx: + raise MesonBugException('We do not expect the xcode backend to be given a valid \'vslite_ctx\'') 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() @@ -342,7 +341,7 @@ xcodetype = 'sourcecode.unknown' return xcodetype - def generate_filemap(self): + def generate_filemap(self) -> None: self.filemap = {} # Key is source file relative to src root. self.target_filemap = {} for name, t in self.build_targets.items(): @@ -356,10 +355,10 @@ self.filemap[o] = self.gen_id() self.target_filemap[name] = self.gen_id() - def generate_buildstylemap(self): + def generate_buildstylemap(self) -> None: self.buildstylemap = {self.buildtype: self.gen_id()} - def generate_build_phase_map(self): + def generate_build_phase_map(self) -> None: for tname, t in self.build_targets.items(): # generate id for our own target-name t.buildphasemap = {} @@ -369,7 +368,7 @@ t.buildphasemap['Resources'] = self.gen_id() t.buildphasemap['Sources'] = self.gen_id() - def generate_build_configuration_map(self): + def generate_build_configuration_map(self) -> None: self.buildconfmap = {} for t in self.build_targets: bconfs = {self.buildtype: self.gen_id()} @@ -378,28 +377,28 @@ bconfs = {self.buildtype: self.gen_id()} self.buildconfmap[t] = bconfs - def generate_project_configurations_map(self): + def generate_project_configurations_map(self) -> None: self.project_configurations = {self.buildtype: self.gen_id()} - def generate_buildall_configurations_map(self): + def generate_buildall_configurations_map(self) -> None: self.buildall_configurations = {self.buildtype: self.gen_id()} - def generate_test_configurations_map(self): + def generate_test_configurations_map(self) -> None: self.test_configurations = {self.buildtype: self.gen_id()} - def generate_build_configurationlist_map(self): + def generate_build_configurationlist_map(self) -> None: self.buildconflistmap = {} 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): + def generate_native_target_map(self) -> None: self.native_targets = {} for t in self.build_targets: self.native_targets[t] = self.gen_id() - def generate_custom_target_map(self): + def generate_custom_target_map(self) -> None: self.shell_targets = {} self.custom_target_output_buildfile = {} self.custom_target_output_fileref = {} @@ -412,7 +411,7 @@ self.custom_target_output_buildfile[o] = self.gen_id() self.custom_target_output_fileref[o] = self.gen_id() - def generate_generator_target_map(self): + def generate_generator_target_map(self) -> None: # Generator objects do not have natural unique ids # so use a counter. self.generator_fileref_ids = {} @@ -452,7 +451,7 @@ self.generator_buildfile_ids[k] = buildfile_ids self.generator_fileref_ids[k] = fileref_ids - def generate_native_frameworks_map(self): + def generate_native_frameworks_map(self) -> None: self.native_frameworks = {} self.native_frameworks_fileref = {} for t in self.build_targets.values(): @@ -462,7 +461,7 @@ self.native_frameworks[f] = self.gen_id() self.native_frameworks_fileref[f] = self.gen_id() - def generate_target_dependency_map(self): + def generate_target_dependency_map(self) -> None: self.target_dependency_map = {} for tname, t in self.build_targets.items(): for target in t.link_targets: @@ -479,7 +478,7 @@ assert k not in self.target_dependency_map self.target_dependency_map[k] = self.gen_id() - def generate_pbxdep_map(self): + def generate_pbxdep_map(self) -> None: self.pbx_dep_map = {} self.pbx_custom_dep_map = {} for t in self.build_targets: @@ -487,12 +486,12 @@ for t in self.custom_targets: self.pbx_custom_dep_map[t] = self.gen_id() - def generate_containerproxy_map(self): + def generate_containerproxy_map(self) -> None: self.containerproxy_map = {} for t in self.build_targets: self.containerproxy_map[t] = self.gen_id() - def generate_target_file_maps(self): + def generate_target_file_maps(self) -> None: self.generate_target_file_maps_impl(self.build_targets) self.generate_target_file_maps_impl(self.custom_targets) @@ -526,13 +525,13 @@ else: raise RuntimeError('Unknown input type ' + str(o)) - def generate_build_file_maps(self): + def generate_build_file_maps(self) -> None: 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): + def generate_source_phase_map(self) -> None: self.source_phase = {} for t in self.build_targets: self.source_phase[t] = self.gen_id() @@ -1023,6 +1022,7 @@ 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'), os.path.join(current_subdir, 'meson_options.txt')] for bf in potentials: i = self.fileref_ids.get(bf, None) @@ -1495,8 +1495,7 @@ else: raise RuntimeError(o) if isinstance(target, build.SharedModule): - options = self.environment.coredata.options - ldargs += linker.get_std_shared_module_link_args(options) + ldargs += linker.get_std_shared_module_link_args(target.get_options()) elif isinstance(target, build.SharedLibrary): ldargs += linker.get_std_shared_lib_link_args() ldstr = ' '.join(ldargs) @@ -1532,7 +1531,7 @@ # 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 + # Xcode cannot 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' @@ -1637,7 +1636,7 @@ quoted_args.append(a) settings_dict.add_item(f'OTHER_{langname}FLAGS', '"' + ' '.join(quoted_args) + '"') - def generate_xc_configurationList(self, objects_dict): + def generate_xc_configurationList(self, objects_dict: PbxDict) -> None: # FIXME: sort items conf_dict = PbxDict() objects_dict.add_item(self.project_conflist, conf_dict, f'Build configuration list for PBXProject "{self.build.project_name}"') @@ -1706,7 +1705,7 @@ t_dict.add_item('defaultConfigurationIsVisible', 0) t_dict.add_item('defaultConfigurationName', self.buildtype) - def generate_prefix(self, pbxdict): + def generate_prefix(self, pbxdict: PbxDict) -> PbxDict: pbxdict.add_item('archiveVersion', '1') pbxdict.add_item('classes', PbxDict()) pbxdict.add_item('objectVersion', '46') @@ -1715,5 +1714,5 @@ return objects_dict - def generate_suffix(self, pbxdict): + def generate_suffix(self, pbxdict: PbxDict) -> None: pbxdict.add_item('rootObject', self.project_uid, 'Project object') diff -Nru meson-1.0.1/mesonbuild/build.py meson-1.2.1/mesonbuild/build.py --- meson-1.0.1/mesonbuild/build.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/build.py 2023-08-07 22:54:34.000000000 +0000 @@ -14,9 +14,9 @@ from __future__ import annotations from collections import defaultdict, OrderedDict -from dataclasses import dataclass, field +from dataclasses import dataclass, field, InitVar from functools import lru_cache -import copy +import abc import hashlib import itertools, pathlib import os @@ -25,7 +25,7 @@ import textwrap import typing as T - +from . import coredata from . import environment from . import dependencies from . import mlog @@ -51,7 +51,7 @@ from .compilers import Compiler from .interpreter.interpreter import Test, SourceOutputs, Interpreter from .interpreterbase import SubProject - from .linkers import StaticLinker + from .linkers.linkers import StaticLinker from .mesonlib import FileMode, FileOrString from .modules import ModuleState from .mparser import BaseNode @@ -60,6 +60,7 @@ GeneratedTypes = T.Union['CustomTarget', 'CustomTargetIndex', 'GeneratedList'] LibTypes = T.Union['SharedLibrary', 'StaticLibrary', 'CustomTarget', 'CustomTargetIndex'] BuildTargetTypes = T.Union['BuildTarget', 'CustomTarget', 'CustomTargetIndex'] + ObjectTypes = T.Union[str, 'File', 'ExtractedObjects', 'GeneratedTypes'] pch_kwargs = {'c_pch', 'cpp_pch'} @@ -72,7 +73,7 @@ } vala_kwargs = {'vala_header', 'vala_gir', 'vala_vapi'} -rust_kwargs = {'rust_crate_type'} +rust_kwargs = {'rust_crate_type', 'rust_dependency_map'} cs_kwargs = {'resources', 'cs_args'} buildtarget_kwargs = { @@ -216,11 +217,14 @@ class DepManifest: version: str license: T.List[str] + license_files: T.List[T.Tuple[str, File]] + subproject: str def to_json(self) -> T.Dict[str, T.Union[str, T.List[str]]]: return { 'version': self.version, 'license': self.license, + 'license_files': [l[1].relative_name() for l in self.license_files], } @@ -231,6 +235,7 @@ """ def __init__(self, environment: environment.Environment): + self.version = coredata.version self.project_name = 'name of master project' self.project_version = None self.environment = environment @@ -268,7 +273,6 @@ 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() @@ -408,6 +412,7 @@ genlist: T.List['GeneratedTypes'] = field(default_factory=list) objlist: T.List[T.Union[str, 'File', 'ExtractedObjects']] = field(default_factory=list) recursive: bool = True + pch: bool = False def __post_init__(self) -> None: if self.target.is_unity: @@ -447,7 +452,7 @@ for comp, srcs in extracted_cmpsrcs.items(): if set(srcs) != set(cmpsrcs[comp]): - raise MesonException('Single object files can not be extracted ' + raise MesonException('Single object files cannot be extracted ' 'in Unity builds. You can only extract all ' 'the object files for each compiler at once.') @@ -502,9 +507,7 @@ @dataclass(eq=False) -class Target(HoldableObject): - - # TODO: should Target be an abc.ABCMeta? +class Target(HoldableObject, metaclass=abc.ABCMeta): name: str subdir: str @@ -512,21 +515,33 @@ build_by_default: bool for_machine: MachineChoice environment: environment.Environment + install: bool = False + build_always_stale: bool = False + extra_files: T.List[File] = field(default_factory=list) + override_options: InitVar[T.Optional[T.Dict[OptionKey, str]]] = None - def __post_init__(self) -> None: + @abc.abstractproperty + def typename(self) -> str: + pass + + @abc.abstractmethod + def type_suffix(self) -> str: + pass + + def __post_init__(self, overrides: T.Optional[T.Dict[OptionKey, str]]) -> None: + if overrides: + ovr = {k.evolve(machine=self.for_machine) if k.lang else k: v + for k, v in overrides.items()} + else: + ovr = {} + self.options = OptionOverrideProxy(ovr, self.environment.coredata.options, self.subproject) + # XXX: this should happen in the interpreter if has_path_sep(self.name): # Fix failing test 53 when this becomes an error. mlog.warning(textwrap.dedent(f'''\ Target "{self.name}" has a path separator in its name. This is not supported, it can cause unexpected failures and will become - a hard error in the future. - ''')) - self.install = False - self.build_always_stale = False - self.options = OptionOverrideProxy({}, self.environment.coredata.options, self.subproject) - self.extra_files = [] # type: T.List[File] - if not hasattr(self, 'typename'): - raise RuntimeError(f'Target type is not set for target class "{type(self).__name__}". This is a bug') + a hard error in the future.''')) # dataclass comparators? def __lt__(self, other: object) -> bool: @@ -587,7 +602,7 @@ return self.typename @staticmethod - def _get_id_hash(target_id): + def _get_id_hash(target_id: str) -> str: # We don't really need cryptographic security here. # Small-digest hash function with unlikely collision is good enough. h = hashlib.sha256() @@ -683,13 +698,31 @@ install_dir: T.List[T.Union[str, Literal[False]]] - def __init__(self, name: str, subdir: str, subproject: SubProject, for_machine: MachineChoice, - sources: T.List['SourceOutputs'], structured_sources: T.Optional[StructuredSources], - objects, environment: environment.Environment, compilers: T.Dict[str, 'Compiler'], kwargs): - super().__init__(name, subdir, subproject, True, for_machine, environment) + # This set contains all the languages a linker can link natively + # without extra flags. For instance, nvcc (cuda) can link C++ + # without injecting -lc++/-lstdc++, see + # https://github.com/mesonbuild/meson/issues/10570 + _MASK_LANGS: T.FrozenSet[T.Tuple[str, str]] = frozenset([ + # (language, linker) + ('cpp', 'cuda'), + ]) + + def __init__( + self, + name: str, + subdir: str, + subproject: SubProject, + for_machine: MachineChoice, + sources: T.List['SourceOutputs'], + structured_sources: T.Optional[StructuredSources], + objects: T.List[ObjectTypes], + environment: environment.Environment, + compilers: T.Dict[str, 'Compiler'], + kwargs): + super().__init__(name, subdir, subproject, True, for_machine, environment, install=kwargs.get('install', False)) self.all_compilers = compilers self.compilers = OrderedDict() # type: OrderedDict[str, Compiler] - self.objects: T.List[T.Union[str, 'File', 'ExtractedObjects']] = [] + self.objects: T.List[ObjectTypes] = [] self.structured_sources = structured_sources self.external_deps: T.List[dependencies.Dependency] = [] self.include_dirs: T.List['IncludeDirs'] = [] @@ -704,11 +737,11 @@ # The list of all files outputted by this target. Useful in cases such # as Vala which generates .vapi and .h besides the compiled output. self.outputs = [self.filename] - self.need_install = False 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.extra_files: T.List[File] = [] self.d_features = defaultdict(list) self.pic = False self.pie = False @@ -716,15 +749,30 @@ 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 + # 1. Preexisting objects provided by the user with the `objects:` kwarg # 2. Compiled objects created by and extracted from another target self.process_objectlist(objects) self.process_kwargs(kwargs) - self.check_unknown_kwargs(kwargs) - if not any([self.sources, self.generated, self.objects, self.link_whole_targets, self.structured_sources]): + self.missing_languages = self.process_compilers() + + # self.link_targets and self.link_whole_targets contains libraries from + # dependencies (see add_deps()). They have not been processed yet because + # we have to call process_compilers() first and we need to process libraries + # from link_with and link_whole first. + # See https://github.com/mesonbuild/meson/pull/11957#issuecomment-1629243208. + link_targets = extract_as_list(kwargs, 'link_with') + self.link_targets + link_whole_targets = extract_as_list(kwargs, 'link_whole') + self.link_whole_targets + self.link_targets.clear() + self.link_whole_targets.clear() + self.link(link_targets) + self.link_whole(link_whole_targets) + + if not any([self.sources, self.generated, self.objects, self.link_whole_targets, self.structured_sources, + kwargs.pop('_allow_no_sources', False)]): mlog.warning(f'Build target {name} has no sources. ' 'This was never supposed to be allowed but did because of a bug, ' 'support will be removed in a future release of Meson') + self.check_unknown_kwargs(kwargs) self.validate_install() self.check_module_linking() @@ -736,6 +784,10 @@ raise MesonException('cannot mix structured sources and unstructured sources') if self.structured_sources and 'rust' not in self.compilers: raise MesonException('structured sources are only supported in Rust targets') + if self.uses_rust(): + # relocation-model=pic is rustc's default and Meson does not + # currently have a way to disable PIC. + self.pic = True def __repr__(self): repr_str = "<{0} {1}: {2}>" @@ -750,7 +802,7 @@ return unity_opt == 'on' or (unity_opt == 'subprojects' and self.subproject != '') def validate_install(self): - if self.for_machine is MachineChoice.BUILD and self.need_install: + if self.for_machine is MachineChoice.BUILD and self.install: if self.environment.is_cross_build(): raise InvalidArguments('Tried to install a target for the build machine in a cross build.') else: @@ -774,12 +826,11 @@ for s in objects: 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 ' + \ - 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) + elif isinstance(s, (CustomTarget, CustomTargetIndex, GeneratedList)): + non_objects = [o for o in s.get_outputs() if not is_object(o)] + if non_objects: + raise InvalidArguments(f'Generated file {non_objects[0]} in the \'objects\' kwarg is not an object.') + self.generated.append(s) else: raise InvalidArguments(f'Bad object of type {type(s).__name__!r} in target {self.name!r}.') @@ -787,8 +838,8 @@ """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. + 1. Preexisting source files in the source tree (static) + 2. Preexisting 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) """ @@ -810,14 +861,14 @@ removed = True return removed - def process_compilers_late(self, extra_languages: T.List[str]): + def process_compilers_late(self): """Processes additional compilers after kwargs have been evaluated. This can add extra compilers that might be required by keyword arguments, such as link_with or dependencies. It will also try to guess which compiler to use if one hasn't been selected already. """ - for lang in extra_languages: + for lang in self.missing_languages: self.compilers[lang] = self.all_compilers[lang] # did user override clink_langs for this target? @@ -860,7 +911,7 @@ missing_languages: T.List[str] = [] if not any([self.sources, self.generated, self.objects, self.structured_sources]): return missing_languages - # Pre-existing sources + # Preexisting sources sources: T.List['FileOrString'] = list(self.sources) generated = self.generated.copy() @@ -963,18 +1014,6 @@ 'Link_depends arguments must be strings, Files, ' 'or a Custom Target, or lists thereof.') - def get_original_kwargs(self): - return self.kwargs - - def copy_kwargs(self, kwargs): - self.kwargs = copy.copy(kwargs) - for k, v in self.kwargs.items(): - if isinstance(v, list): - self.kwargs[k] = listify(v, flatten=True) - for t in ['dependencies', 'link_with', 'include_directories', 'sources']: - if t in self.kwargs: - self.kwargs[t] = listify(self.kwargs[t], flatten=True) - def extract_objects(self, srclist: T.List[T.Union['FileOrString', 'GeneratedTypes']]) -> ExtractedObjects: sources_set = set(self.sources) generated_set = set(self.generated) @@ -1002,7 +1041,7 @@ def extract_all_objects(self, recursive: bool = True) -> ExtractedObjects: return ExtractedObjects(self, self.sources, self.generated, self.objects, - recursive) + recursive, pch=True) def get_all_link_deps(self) -> ImmutableListProtocol[BuildTargetTypes]: return self.get_transitive_link_deps() @@ -1048,23 +1087,7 @@ def process_kwargs(self, kwargs): self.process_kwargs_base(kwargs) - self.copy_kwargs(kwargs) - kwargs.get('modules', []) - self.need_install = kwargs.get('install', self.need_install) - llist = extract_as_list(kwargs, 'link_with') - for linktarget in llist: - if isinstance(linktarget, dependencies.ExternalLibrary): - 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) + self.original_kwargs = kwargs for lang in all_languages: lang_args = extract_as_list(kwargs, f'{lang}_args') @@ -1144,10 +1167,12 @@ extra_files = extract_as_list(kwargs, 'extra_files') for i in extra_files: assert isinstance(i, File) + if i in self.extra_files: + continue trial = os.path.join(self.environment.get_source_dir(), i.subdir, i.fname) if not os.path.isfile(trial): raise InvalidArguments(f'Tried to add non-existing extra file {i}.') - self.extra_files = extra_files + self.extra_files.append(i) self.install_rpath: str = kwargs.get('install_rpath', '') if not isinstance(self.install_rpath, str): raise InvalidArguments('Install_rpath is not a string.') @@ -1212,6 +1237,13 @@ if self.gnu_symbol_visibility not in permitted: raise InvalidArguments('GNU symbol visibility arg {} not one of: {}'.format(self.gnu_symbol_visibility, ', '.join(permitted))) + rust_dependency_map = kwargs.get('rust_dependency_map', {}) + if not isinstance(rust_dependency_map, dict): + raise InvalidArguments(f'Invalid rust_dependency_map "{rust_dependency_map}": must be a dictionary.') + if any(not isinstance(v, str) for v in rust_dependency_map.values()): + raise InvalidArguments(f'Invalid rust_dependency_map "{rust_dependency_map}": must be a dictionary with string values.') + self.rust_dependency_map = rust_dependency_map + 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: @@ -1246,17 +1278,36 @@ def get_extra_args(self, language): return self.extra_args.get(language, []) - def get_dependencies(self, exclude=None): - transitive_deps = [] - if exclude is None: - exclude = [] + @lru_cache(maxsize=None) + def get_dependencies(self) -> OrderedSet[Target]: + # Get all targets needed for linking. This includes all link_with and + # link_whole targets, and also all dependencies of static libraries + # recursively. The algorithm here is closely related to what we do in + # get_internal_static_libraries(): Installed static libraries include + # objects from all their dependencies already. + result: OrderedSet[Target] = OrderedSet() for t in itertools.chain(self.link_targets, self.link_whole_targets): - if t in transitive_deps or t in exclude: + if t not in result: + result.add(t) + if isinstance(t, StaticLibrary): + t.get_dependencies_recurse(result) + return result + + def get_dependencies_recurse(self, result: OrderedSet[Target], include_internals: bool = True) -> None: + # self is always a static library because we don't need to pull dependencies + # of shared libraries. If self is installed (not internal) it already + # include objects extracted from all its internal dependencies so we can + # skip them. + include_internals = include_internals and self.is_internal() + for t in self.link_targets: + if t in result: continue - transitive_deps.append(t) + if include_internals or not t.is_internal(): + result.add(t) if isinstance(t, StaticLibrary): - transitive_deps += t.get_dependencies(transitive_deps + exclude) - return transitive_deps + t.get_dependencies_recurse(result, include_internals) + for t in self.link_whole_targets: + t.get_dependencies_recurse(result, include_internals) def get_source_subdir(self): return self.subdir @@ -1271,7 +1322,7 @@ return self.generated def should_install(self) -> bool: - return self.need_install + return self.install def has_pch(self) -> bool: return bool(self.pch) @@ -1291,18 +1342,18 @@ if isinstance(dep, dependencies.InternalDependency): # Those parts that are internal. self.process_sourcelist(dep.sources) + self.extra_files.extend(f for f in dep.extra_files if f not in self.extra_files) self.add_include_dirs(dep.include_directories, dep.get_include_type()) - for l in dep.libraries: - self.link(l) - for l in dep.whole_libraries: - self.link_whole(l) + self.objects.extend(dep.objects) + self.link_targets.extend(dep.libraries) + self.link_whole_targets.extend(dep.whole_libraries) if dep.get_compile_args() or dep.get_link_args(): # Those parts that are external. extpart = dependencies.InternalDependency('undefined', [], dep.get_compile_args(), dep.get_link_args(), - [], [], [], [], {}, [], []) + [], [], [], [], [], {}, [], [], []) self.external_deps.append(extpart) # Deps of deps. self.add_deps(dep.ext_deps) @@ -1344,30 +1395,25 @@ def is_internal(self) -> bool: return False - def link(self, target): - 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() and not t.uses_rust(): - # When we're a static library and we link_with to an - # internal/convenience library, promote to link_whole. - # - # There are cases we cannot do this, however. In Rust, for - # example, this can't be done with Rust ABI libraries, though - # it could be done with C ABI libraries, though there are - # several meson issues that need to be fixed: - # https://github.com/mesonbuild/meson/issues/10722 - # https://github.com/mesonbuild/meson/issues/10723 - # https://github.com/mesonbuild/meson/issues/10724 - return self.link_whole(t) + def link(self, targets): + for t in targets: if not isinstance(t, (Target, CustomTargetIndex)): + if isinstance(t, dependencies.ExternalLibrary): + 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. + ''')) raise InvalidArguments(f'{t!r} is not a target.') if not t.is_linkable_target(): raise InvalidArguments(f"Link target '{t!s}' is not linkable.") + if isinstance(self, StaticLibrary) and self.install and t.is_internal(): + # When we're a static library and we link_with to an + # internal/convenience library, promote to link_whole. + self.link_whole([t], promoted=True) + continue if isinstance(self, SharedLibrary) and isinstance(t, StaticLibrary) and not t.pic: 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." @@ -1380,16 +1426,13 @@ mlog.warning(msg + ' This will fail in cross build.') self.link_targets.append(t) - def link_whole(self, target): - for t in listify(target): + def link_whole(self, targets, promoted: bool = False): + for t in targets: if isinstance(t, (CustomTarget, CustomTargetIndex)): if not t.is_linkable_target(): raise InvalidArguments(f'Custom target {t!r} is not linkable.') if t.links_dynamically(): raise InvalidArguments('Can only link_whole custom targets that are static 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(f'{t!r} is not a static library.') elif isinstance(self, SharedLibrary) and not t.pic: @@ -1402,18 +1445,50 @@ raise InvalidArguments(msg + ' This is not possible in a cross build.') else: mlog.warning(msg + ' This will fail in cross build.') - if isinstance(self, StaticLibrary): + if isinstance(self, StaticLibrary) and not self.uses_rust(): # When we're a static library and we link_whole: to another static # library, we need to add that target's objects to ourselves. - self.objects += t.extract_all_objects_recurse() + self.check_can_extract_objects(t, origin=self, promoted=promoted) + self.objects += [t.extract_all_objects()] + # If we install this static library we also need to include objects + # from all uninstalled static libraries it depends on. + if self.install: + for lib in t.get_internal_static_libraries(origin=self): + self.objects += [lib.extract_all_objects()] self.link_whole_targets.append(t) - def extract_all_objects_recurse(self) -> T.List[T.Union[str, 'ExtractedObjects']]: - objs = [self.extract_all_objects()] + @lru_cache(maxsize=None) + def get_internal_static_libraries(self, origin: StaticLibrary) -> OrderedSet[Target]: + result: OrderedSet[Target] = OrderedSet() + self.get_internal_static_libraries_recurse(result, origin) + return result + + def get_internal_static_libraries_recurse(self, result: OrderedSet[Target], origin: StaticLibrary) -> None: for t in self.link_targets: + if t.is_internal() and t not in result: + self.check_can_extract_objects(t, origin, promoted=True) + result.add(t) + t.get_internal_static_libraries_recurse(result, origin) + for t in self.link_whole_targets: if t.is_internal(): - objs += t.extract_all_objects_recurse() - return objs + t.get_internal_static_libraries_recurse(result, origin) + + def check_can_extract_objects(self, t: T.Union[Target, CustomTargetIndex], origin: StaticLibrary, promoted: bool = False) -> None: + if isinstance(t, (CustomTarget, CustomTargetIndex)) or t.uses_rust(): + # To extract objects from a custom target we would have to extract + # the archive, WIP implementation can be found in + # https://github.com/mesonbuild/meson/pull/9218. + # For Rust C ABI we could in theory have access to objects, but there + # are several meson issues that need to be fixed: + # https://github.com/mesonbuild/meson/issues/10722 + # https://github.com/mesonbuild/meson/issues/10723 + # https://github.com/mesonbuild/meson/issues/10724 + m = (f'Cannot link_whole a custom or Rust target {t.name!r} into a static library {origin.name!r}. ' + 'Instead, pass individual object files with the "objects:" keyword argument if possible.') + if promoted: + m += (f' Meson had to promote link to link_whole because {origin.name!r} is installed but not {t.name!r},' + f' and thus has to include objects from {t.name!r} to be usable.') + raise InvalidArguments(m) def add_pch(self, language: str, pchlist: T.List[str]) -> None: if not pchlist: @@ -1539,14 +1614,6 @@ # Languages used by dependencies dep_langs = self.get_langs_used_by_deps() - # This set contains all the languages a linker can link natively - # without extra flags. For instance, nvcc (cuda) can link C++ - # without injecting -lc++/-lstdc++, see - # https://github.com/mesonbuild/meson/issues/10570 - MASK_LANGS = frozenset([ - # (language, linker) - ('cpp', 'cuda'), - ]) # Pick a compiler based on the language priority-order for l in clink_langs: if l in self.compilers or l in dep_langs: @@ -1557,10 +1624,7 @@ 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] = [] - for dl in itertools.chain(self.compilers, dep_langs): - if dl != linker.language and (dl, linker.language) not in MASK_LANGS: - stdlib_args += all_compilers[dl].language_stdlib_only_link_flags(self.environment) + stdlib_args: T.List[str] = self.get_used_stdlib_args(linker.language) # Type of var 'linker' is Compiler. # Pretty hard to fix because the return value is passed everywhere return linker, stdlib_args @@ -1576,6 +1640,18 @@ raise AssertionError(f'Could not get a dynamic linker for build target {self.name!r}') + def get_used_stdlib_args(self, link_language: str) -> T.List[str]: + all_compilers = self.environment.coredata.compilers[self.for_machine] + all_langs = set(self.compilers).union(self.get_langs_used_by_deps()) + stdlib_args: T.List[str] = [] + for dl in all_langs: + if dl != link_language and (dl, link_language) not in self._MASK_LANGS: + # We need to use all_compilers here because + # get_langs_used_by_deps could return a language from a + # subproject + stdlib_args.extend(all_compilers[dl].language_stdlib_only_link_flags(self.environment)) + return stdlib_args + def uses_rust(self) -> bool: return 'rust' in self.compilers @@ -1629,9 +1705,43 @@ '\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.') + 'use shared_library() with `override_options: [\'b_lundef=false\']` instead.') link_target.force_soname = True +class FileInTargetPrivateDir: + """Represents a file with the path '/path/to/build/target_private_dir/fname'. + target_private_dir is the return value of get_target_private_dir which is e.g. 'subdir/target.p'. + """ + + def __init__(self, fname: str): + self.fname = fname + + def __str__(self) -> str: + return self.fname + +class FileMaybeInTargetPrivateDir: + """Union between 'File' and 'FileInTargetPrivateDir'""" + + def __init__(self, inner: T.Union[File, FileInTargetPrivateDir]): + self.inner = inner + + @property + def fname(self) -> str: + return self.inner.fname + + def rel_to_builddir(self, build_to_src: str, target_private_dir: str) -> str: + if isinstance(self.inner, FileInTargetPrivateDir): + return os.path.join(target_private_dir, self.inner.fname) + return self.inner.rel_to_builddir(build_to_src) + + def absolute_path(self, srcdir: str, builddir: str) -> str: + if isinstance(self.inner, FileInTargetPrivateDir): + raise RuntimeError('Unreachable code') + return self.inner.absolute_path(srcdir, builddir) + + def __str__(self) -> str: + return self.fname + class Generator(HoldableObject): def __init__(self, exe: T.Union['Executable', programs.ExternalProgram], arguments: T.List[str], @@ -1691,10 +1801,14 @@ output.depends.add(e) if isinstance(e, CustomTargetIndex): output.depends.add(e.target) - - if isinstance(e, (CustomTarget, CustomTargetIndex, GeneratedList)): + if isinstance(e, (CustomTarget, CustomTargetIndex)): output.depends.add(e) fs = [File.from_built_file(state.subdir, f) for f in e.get_outputs()] + elif isinstance(e, GeneratedList): + if preserve_path_from: + raise InvalidArguments("generator.process: 'preserve_path_from' is not allowed if one input is a 'generated_list'.") + output.depends.add(e) + fs = [FileInTargetPrivateDir(f) for f in e.get_outputs()] elif isinstance(e, str): fs = [File.from_source_file(state.environment.source_dir, state.subdir, e)] else: @@ -1705,6 +1819,7 @@ 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.') + f = FileMaybeInTargetPrivateDir(f) output.add_file(f, state) return output @@ -1722,9 +1837,9 @@ def __post_init__(self) -> None: self.name = self.generator.exe self.depends: T.Set[GeneratedTypes] = set() - self.infilelist: T.List['File'] = [] + self.infilelist: T.List[FileMaybeInTargetPrivateDir] = [] self.outfilelist: T.List[str] = [] - self.outmap: T.Dict[File, T.List[str]] = {} + self.outmap: T.Dict[FileMaybeInTargetPrivateDir, T.List[str]] = {} self.extra_depends = [] # XXX: Doesn't seem to be used? self.depend_files: T.List[File] = [] @@ -1740,7 +1855,7 @@ # know the absolute path of self.depend_files.append(File.from_absolute_file(path)) - def add_preserved_path_segment(self, infile: File, outfiles: T.List[str], state: T.Union['Interpreter', 'ModuleState']) -> T.List[str]: + def add_preserved_path_segment(self, infile: FileMaybeInTargetPrivateDir, 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) @@ -1750,7 +1865,7 @@ result.append(os.path.join(path_segment, of)) return result - def add_file(self, newfile: File, state: T.Union['Interpreter', 'ModuleState']) -> None: + def add_file(self, newfile: FileMaybeInTargetPrivateDir, state: T.Union['Interpreter', 'ModuleState']) -> None: self.infilelist.append(newfile) outfiles = self.generator.get_base_outnames(newfile.fname) if self.preserve_path_from: @@ -1758,13 +1873,13 @@ self.outfilelist += outfiles self.outmap[newfile] = outfiles - def get_inputs(self) -> T.List['File']: + def get_inputs(self) -> T.List[FileMaybeInTargetPrivateDir]: return self.infilelist def get_outputs(self) -> T.List[str]: return self.outfilelist - def get_outputs_for(self, filename: 'File') -> T.List[str]: + def get_outputs_for(self, filename: FileMaybeInTargetPrivateDir) -> T.List[str]: return self.outmap[filename] def get_generator(self) -> 'Generator': @@ -1782,10 +1897,18 @@ typename = 'executable' - def __init__(self, name: str, subdir: str, subproject: str, for_machine: MachineChoice, - sources: T.List[SourceOutputs], structured_sources: T.Optional['StructuredSources'], - objects, environment: environment.Environment, compilers: T.Dict[str, 'Compiler'], - kwargs): + def __init__( + self, + name: str, + subdir: str, + subproject: SubProject, + for_machine: MachineChoice, + sources: T.List['SourceOutputs'], + structured_sources: T.Optional[StructuredSources], + objects: T.List[ObjectTypes], + environment: environment.Environment, + compilers: T.Dict[str, 'Compiler'], + kwargs): key = OptionKey('b_pie') if 'pie' not in kwargs and key in environment.coredata.options: kwargs['pie'] = environment.coredata.options[key].value @@ -1831,6 +1954,9 @@ elif ('c' in self.compilers and self.compilers['c'].get_id() in {'ti', 'c2000'} or 'cpp' in self.compilers and self.compilers['cpp'].get_id() in {'ti', 'c2000'}): self.suffix = 'out' + elif ('c' in self.compilers and self.compilers['c'].get_id() in {'mwccarm', 'mwcceppc'} or + 'cpp' in self.compilers and self.compilers['cpp'].get_id() in {'mwccarm', 'mwcceppc'}): + self.suffix = 'nef' else: self.suffix = machine.get_exe_suffix() self.filename = self.name @@ -1860,9 +1986,13 @@ else: self.import_filename = self.gcc_import_filename - if machine.is_windows() and ('cs' in self.compilers or - self.uses_rust() or - self.get_using_msvc()): + create_debug_file = ( + machine.is_windows() + and ('cs' in self.compilers or self.uses_rust() or self.get_using_msvc()) + # .pdb file is created only when debug symbols are enabled + and self.environment.coredata.get_option(OptionKey("debug")) + ) + if create_debug_file: self.debug_filename = self.name + '.pdb' def get_default_install_dir(self) -> T.Tuple[str, str]: @@ -1906,15 +2036,32 @@ """ return self.outputs + def get_path(self) -> str: + """Provides compatibility with ExternalProgram.""" + return os.path.join(self.subdir, self.filename) + + def found(self) -> bool: + """Provides compatibility with ExternalProgram.""" + return True + + class StaticLibrary(BuildTarget): known_kwargs = known_stlib_kwargs typename = 'static library' - def __init__(self, name: str, subdir: str, subproject: str, for_machine: MachineChoice, - sources: T.List[SourceOutputs], structured_sources: T.Optional['StructuredSources'], - objects, environment: environment.Environment, compilers: T.Dict[str, 'Compiler'], - kwargs): + def __init__( + self, + name: str, + subdir: str, + subproject: SubProject, + for_machine: MachineChoice, + sources: T.List['SourceOutputs'], + structured_sources: T.Optional[StructuredSources], + objects: T.List[ObjectTypes], + environment: environment.Environment, + compilers: T.Dict[str, 'Compiler'], + kwargs): self.prelink = kwargs.get('prelink', False) if not isinstance(self.prelink, bool): raise InvalidArguments('Prelink keyword argument must be a boolean.') @@ -1933,6 +2080,18 @@ # Don't let configuration proceed with a non-static crate type elif self.rust_crate_type not in ['rlib', 'staticlib']: raise InvalidArguments(f'Crate type "{self.rust_crate_type}" invalid for static libraries; must be "rlib" or "staticlib"') + # See https://github.com/rust-lang/rust/issues/110460 + if self.rust_crate_type == 'rlib' and any(c in self.name for c in ['-', ' ', '.']): + raise InvalidArguments('Rust crate type "rlib" does not allow spaces, periods or dashes in the library name ' + 'due to a limitation of rustc. Replace them with underscores, for example') + if self.rust_crate_type == 'staticlib': + # FIXME: In the case of no-std we should not add those libraries, + # but we have no way to know currently. + rustc = self.compilers['rust'] + d = dependencies.InternalDependency('undefined', [], [], + rustc.native_static_libs, + [], [], [], [], [], {}, [], [], []) + self.external_deps.append(d) # 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 @@ -1976,17 +2135,25 @@ return True def is_internal(self) -> bool: - return not self.need_install + return not self.install class SharedLibrary(BuildTarget): known_kwargs = known_shlib_kwargs typename = 'shared library' - def __init__(self, name: str, subdir: str, subproject: str, for_machine: MachineChoice, - sources: T.List[SourceOutputs], structured_sources: T.Optional['StructuredSources'], - objects, environment: environment.Environment, compilers: T.Dict[str, 'Compiler'], - kwargs): + def __init__( + self, + name: str, + subdir: str, + subproject: SubProject, + for_machine: MachineChoice, + sources: T.List['SourceOutputs'], + structured_sources: T.Optional[StructuredSources], + objects: T.List[ObjectTypes], + environment: environment.Environment, + compilers: T.Dict[str, 'Compiler'], + kwargs): self.soversion = None self.ltversion = None # Max length 2, first element is compatibility_version, second is current_version @@ -2015,6 +2182,11 @@ # Don't let configuration proceed with a non-dynamic crate type elif self.rust_crate_type not in ['dylib', 'cdylib', 'proc-macro']: raise InvalidArguments(f'Crate type "{self.rust_crate_type}" invalid for dynamic libraries; must be "dylib", "cdylib", or "proc-macro"') + # See https://github.com/rust-lang/rust/issues/110460 + if self.rust_crate_type != 'cdylib' and any(c in self.name for c in ['-', ' ', '.']): + raise InvalidArguments('Rust crate types "dylib" and "proc-macro" do not allow spaces, periods or dashes in the library name ' + 'due to a limitation of rustc. Replace them with underscores, for example') + if not hasattr(self, 'prefix'): self.prefix = None if not hasattr(self, 'suffix'): @@ -2081,14 +2253,14 @@ prefix = '' # Import library is called foo.dll.lib self.import_filename = f'{self.name}.dll.lib' - # Debug files(.pdb) is only created with debug buildtype + # .pdb file is only created when debug symbols are enabled create_debug_file = self.environment.coredata.get_option(OptionKey("debug")) elif self.get_using_msvc(): # Shared library is of the form foo.dll prefix = '' # Import library is called foo.lib self.import_filename = self.vs_import_filename - # Debug files(.pdb) is only created with debug buildtype + # .pdb file is only created when debug symbols are enabled create_debug_file = self.environment.coredata.get_option(OptionKey("debug")) # Assume GCC-compatible naming else: @@ -2230,7 +2402,7 @@ elif isinstance(path, File): # When passing a generated file. self.vs_module_defs = path - elif hasattr(path, 'get_filename'): + elif isinstance(path, CustomTarget): # When passing output of a Custom Target self.vs_module_defs = File.from_built_file(path.subdir, path.get_filename()) else: @@ -2317,10 +2489,18 @@ typename = 'shared module' - def __init__(self, name: str, subdir: str, subproject: str, for_machine: MachineChoice, - sources: T.List[SourceOutputs], structured_sources: T.Optional['StructuredSources'], - objects, environment: environment.Environment, - compilers: T.Dict[str, 'Compiler'], kwargs): + def __init__( + self, + name: str, + subdir: str, + subproject: SubProject, + for_machine: MachineChoice, + sources: T.List['SourceOutputs'], + structured_sources: T.Optional[StructuredSources], + objects: T.List[ObjectTypes], + environment: environment.Environment, + compilers: T.Dict[str, 'Compiler'], + kwargs): if 'version' in kwargs: raise MesonException('Shared modules must not specify the version kwarg.') if 'soversion' in kwargs: @@ -2423,14 +2603,14 @@ backend: T.Optional['Backend'] = None, ): # TODO expose keyword arg to make MachineChoice.HOST configurable - super().__init__(name, subdir, subproject, False, MachineChoice.HOST, environment) + super().__init__(name, subdir, subproject, False, MachineChoice.HOST, environment, + install, build_always_stale) self.sources = list(sources) self.outputs = substitute_values( outputs, get_filenames_templates_dict( get_sources_string_names(sources, backend), [])) self.build_by_default = build_by_default if build_by_default is not None else install - self.build_always_stale = build_always_stale self.capture = capture self.console = console self.depend_files = list(depend_files or []) @@ -2441,7 +2621,6 @@ self.env = env or EnvironmentVariables() self.extra_depends = list(extra_depends or []) self.feed = feed - self.install = install self.install_dir = list(install_dir or []) self.install_mode = install_mode self.install_tag = _process_install_tag(install_tag, len(self.outputs)) @@ -2529,11 +2708,18 @@ raise InvalidArguments('Substitution in depfile for custom_target that does not have an input file.') return self.depfile + def is_linkable_output(self, output: str) -> bool: + if output.endswith(('.a', '.dll', '.lib', '.so', '.dylib')): + return True + # libfoo.so.X soname + if re.search(r'\.so(\.\d+)*$', output): + return True + return False + def is_linkable_target(self) -> bool: if len(self.outputs) != 1: return False - suf = os.path.splitext(self.outputs[0])[-1] - return suf in {'.a', '.dll', '.lib', '.so', '.dylib'} + return self.is_linkable_output(self.outputs[0]) def links_dynamically(self) -> bool: """Whether this target links dynamically or statically @@ -2562,7 +2748,7 @@ return False return CustomTargetIndex(self, self.outputs[0]).is_internal() - def extract_all_objects_recurse(self) -> T.List[T.Union[str, 'ExtractedObjects']]: + def extract_all_objects(self) -> T.List[T.Union[str, 'ExtractedObjects']]: return self.get_outputs() def type_suffix(self): @@ -2597,22 +2783,33 @@ subdir: str, subproject: str, environment: environment.Environment, - sources: T.List[File], + sources: T.List['SourceOutputs'], output_templ: str, compiler: Compiler, - kwargs): + backend: Backend, + compile_args: T.List[str], + include_directories: T.List[IncludeDirs], + dependencies: T.List[dependencies.Dependency]): compilers = {compiler.get_language(): compiler} + kwargs = { + 'build_by_default': False, + f'{compiler.language}_args': compile_args, + 'include_directories': include_directories, + 'dependencies': dependencies, + } super().__init__(name, subdir, subproject, compiler.for_machine, sources, None, [], environment, compilers, kwargs) self.filename = name self.compiler = compiler self.output_templ = output_templ self.outputs = [] - for f in sources: - plainname = os.path.basename(f.fname) - basename = os.path.splitext(plainname)[0] - self.outputs.append(output_templ.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname)) - self.sources_map = dict(zip(sources, self.outputs)) + self.sources_map: T.Dict[File, str] = {} + for f in self.sources: + self._add_output(f) + for gensrc in self.generated: + for s in gensrc.get_outputs(): + rel_src = backend.get_target_generated_dir(self, gensrc, s) + self._add_output(File.from_built_relative(rel_src)) def type_suffix(self) -> str: return "@compile" @@ -2621,6 +2818,13 @@ def is_unity(self) -> bool: return False + def _add_output(self, f: File) -> None: + plainname = os.path.basename(f.fname) + basename = os.path.splitext(plainname)[0] + o = self.output_templ.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) + self.outputs.append(o) + self.sources_map[f] = o + class RunTarget(Target, CommandBase): @@ -2674,6 +2878,9 @@ return "@run" class AliasTarget(RunTarget): + + typename = 'alias' + def __init__(self, name: str, dependencies: T.Sequence['Target'], subdir: str, subproject: str, environment: environment.Environment): super().__init__(name, [], dependencies, subdir, subproject, environment) @@ -2781,8 +2988,7 @@ return self.target.get_link_dep_subdirs() def is_linkable_target(self) -> bool: - suf = os.path.splitext(self.output)[-1] - return suf in {'.a', '.dll', '.lib', '.so', '.dylib'} + return self.target.is_linkable_output(self.output) def links_dynamically(self) -> bool: """Whether this target links dynamically or statically @@ -2804,8 +3010,8 @@ suf = os.path.splitext(self.output)[-1] return suf in {'.a', '.lib'} and not self.should_install() - def extract_all_objects_recurse(self) -> T.List[T.Union[str, 'ExtractedObjects']]: - return self.target.extract_all_objects_recurse() + def extract_all_objects(self) -> T.List[T.Union[str, 'ExtractedObjects']]: + return self.target.extract_all_objects() def get_custom_install_dir(self) -> T.List[T.Union[str, Literal[False]]]: return self.target.get_custom_install_dir() @@ -2895,11 +3101,20 @@ def load(build_dir: str) -> Build: filename = os.path.join(build_dir, 'meson-private', 'build.dat') try: - return pickle_load(filename, 'Build data', Build) + b = pickle_load(filename, 'Build data', Build) + # We excluded coredata when saving Build object, load it separately + b.environment.coredata = coredata.load(build_dir) + return b except FileNotFoundError: raise MesonException(f'No such build data file as {filename!r}.') def save(obj: Build, filename: str) -> None: - with open(filename, 'wb') as f: - pickle.dump(obj, f) + # Exclude coredata because we pickle it separately already + cdata = obj.environment.coredata + obj.environment.coredata = None + try: + with open(filename, 'wb') as f: + pickle.dump(obj, f) + finally: + obj.environment.coredata = cdata diff -Nru meson-1.0.1/mesonbuild/cargo/builder.py meson-1.2.1/mesonbuild/cargo/builder.py --- meson-1.0.1/mesonbuild/cargo/builder.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/mesonbuild/cargo/builder.py 2023-08-07 22:54:34.000000000 +0000 @@ -0,0 +1,284 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2022-2023 Intel Corporation + +"""Provides helpers for building AST + +This is meant to make building Meson AST from foreign (largely declarative) +build descriptions easier. +""" + +from __future__ import annotations +import builtins +import dataclasses +import typing as T + +from .. import mparser + + +def _token(tid: str, filename: str, value: mparser.TV_TokenTypes) -> mparser.Token[mparser.TV_TokenTypes]: + """Create a Token object, but with the line numbers stubbed out. + + :param tid: the token id (such as string, number, etc) + :param filename: the filename that the token was generated from + :param value: the value of the token + :return: A Token object + """ + return mparser.Token(tid, filename, -1, -1, -1, (-1, -1), value) + + +def string(value: str, filename: str) -> mparser.StringNode: + """Build A StringNode + + :param value: the value of the string + :param filename: the file that the value came from + :return: A StringNode + """ + return mparser.StringNode(_token('string', filename, value)) + + +def number(value: int, filename: str) -> mparser.NumberNode: + """Build A NumberNode + + :param value: the value of the number + :param filename: the file that the value came from + :return: A NumberNode + """ + return mparser.NumberNode(_token('number', filename, value)) + + +def bool(value: builtins.bool, filename: str) -> mparser.BooleanNode: + """Build A BooleanNode + + :param value: the value of the boolean + :param filename: the file that the value came from + :return: A BooleanNode + """ + return mparser.BooleanNode(_token('bool', filename, value)) + + +def array(value: T.List[mparser.BaseNode], filename: str) -> mparser.ArrayNode: + """Build an Array Node + + :param value: A list of nodes to insert into the array + :param filename: The file the array is from + :return: An ArrayNode built from the arguments + """ + args = mparser.ArgumentNode(_token('array', filename, 'unused')) + args.arguments = value + return mparser.ArrayNode(args, -1, -1, -1, -1) + + +def identifier(value: str, filename: str) -> mparser.IdNode: + """Build A IdNode + + :param value: the value of the boolean + :param filename: the file that the value came from + :return: A BooleanNode + """ + return mparser.IdNode(_token('id', filename, value)) + + +def method(name: str, id_: mparser.IdNode, + pos: T.Optional[T.List[mparser.BaseNode]] = None, + kw: T.Optional[T.Mapping[str, mparser.BaseNode]] = None, + ) -> mparser.MethodNode: + """Create a method call. + + :param name: the name of the method + :param id_: the object to call the method of + :param pos: a list of positional arguments, defaults to None + :param kw: a dictionary of keyword arguments, defaults to None + :return: a method call object + """ + args = mparser.ArgumentNode(_token('array', id_.filename, 'unused')) + if pos is not None: + args.arguments = pos + if kw is not None: + args.kwargs = {identifier(k, id_.filename): v for k, v in kw.items()} + return mparser.MethodNode(id_.filename, -1, -1, id_, name, args) + + +def function(name: str, filename: str, + pos: T.Optional[T.List[mparser.BaseNode]] = None, + kw: T.Optional[T.Mapping[str, mparser.BaseNode]] = None, + ) -> mparser.FunctionNode: + """Create a function call. + + :param name: the name of the function + :param filename: The name of the current file being evaluated + :param pos: a list of positional arguments, defaults to None + :param kw: a dictionary of keyword arguments, defaults to None + :return: a method call object + """ + args = mparser.ArgumentNode(_token('array', filename, 'unused')) + if pos is not None: + args.arguments = pos + if kw is not None: + args.kwargs = {identifier(k, filename): v for k, v in kw.items()} + return mparser.FunctionNode(filename, -1, -1, -1, -1, name, args) + + +def equal(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ComparisonNode: + """Create an equality operation + + :param lhs: The left hand side of the equal + :param rhs: the right hand side of the equal + :return: A compraison node + """ + return mparser.ComparisonNode('==', lhs, rhs) + + +def or_(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.OrNode: + """Create and OrNode + + :param lhs: The Left of the Node + :param rhs: The Right of the Node + :return: The OrNode + """ + return mparser.OrNode(lhs, rhs) + + +def and_(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.AndNode: + """Create an AndNode + + :param lhs: The left of the And + :param rhs: The right of the And + :return: The AndNode + """ + return mparser.AndNode(lhs, rhs) + + +def not_(value: mparser.BaseNode, filename: str) -> mparser.NotNode: + """Create a not node + + :param value: The value to negate + :param filename: the string filename + :return: The NotNode + """ + return mparser.NotNode(_token('not', filename, ''), value) + + +def assign(value: mparser.BaseNode, varname: str, filename: str) -> mparser.AssignmentNode: + """Create an AssignmentNode + + :param value: The rvalue + :param varname: The lvalue + :param filename: The filename + :return: An AssignmentNode + """ + return mparser.AssignmentNode(filename, -1, -1, varname, value) + + +def block(filename: str) -> mparser.CodeBlockNode: + return mparser.CodeBlockNode(_token('node', filename, '')) + + +@dataclasses.dataclass +class Builder: + + filename: str + + def assign(self, value: mparser.BaseNode, varname: str) -> mparser.AssignmentNode: + return assign(value, varname, self.filename) + + def string(self, value: str) -> mparser.StringNode: + """Build A StringNode + + :param value: the value of the string + :return: A StringNode + """ + return string(value, self.filename) + + def number(self, value: int) -> mparser.NumberNode: + """Build A NumberNode + + :param value: the value of the number + :return: A NumberNode + """ + return number(value, self.filename) + + def bool(self, value: builtins.bool) -> mparser.BooleanNode: + """Build A BooleanNode + + :param value: the value of the boolean + :return: A BooleanNode + """ + return bool(value, self.filename) + + def array(self, value: T.List[mparser.BaseNode]) -> mparser.ArrayNode: + """Build an Array Node + + :param value: A list of nodes to insert into the array + :return: An ArrayNode built from the arguments + """ + return array(value, self.filename) + + def identifier(self, value: str) -> mparser.IdNode: + """Build A IdNode + + :param value: the value of the boolean + :return: A BooleanNode + """ + return identifier(value, self.filename) + + def method(self, name: str, id_: mparser.IdNode, + pos: T.Optional[T.List[mparser.BaseNode]] = None, + kw: T.Optional[T.Mapping[str, mparser.BaseNode]] = None, + ) -> mparser.MethodNode: + """Create a method call. + + :param name: the name of the method + :param id_: the object to call the method of + :param pos: a list of positional arguments, defaults to None + :param kw: a dictionary of keyword arguments, defaults to None + :return: a method call object + """ + return method(name, id_, pos or [], kw or {}) + + def function(self, name: str, + pos: T.Optional[T.List[mparser.BaseNode]] = None, + kw: T.Optional[T.Mapping[str, mparser.BaseNode]] = None, + ) -> mparser.FunctionNode: + """Create a function call. + + :param name: the name of the function + :param pos: a list of positional arguments, defaults to None + :param kw: a dictionary of keyword arguments, defaults to None + :return: a method call object + """ + return function(name, self.filename, pos or [], kw or {}) + + def equal(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ComparisonNode: + """Create an equality operation + + :param lhs: The left hand side of the equal + :param rhs: the right hand side of the equal + :return: A compraison node + """ + return equal(lhs, rhs) + + def or_(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.OrNode: + """Create and OrNode + + :param lhs: The Left of the Node + :param rhs: The Right of the Node + :return: The OrNode + """ + return or_(lhs, rhs) + + def and_(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.AndNode: + """Create an AndNode + + :param lhs: The left of the And + :param rhs: The right of the And + :return: The AndNode + """ + return and_(lhs, rhs) + + def not_(self, value: mparser.BaseNode, filename: str) -> mparser.NotNode: + """Create a not node + + :param value: The value to negate + :return: The NotNode + """ + return not_(value, self.filename) diff -Nru meson-1.0.1/mesonbuild/cargo/cfg.py meson-1.2.1/mesonbuild/cargo/cfg.py --- meson-1.0.1/mesonbuild/cargo/cfg.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/mesonbuild/cargo/cfg.py 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,276 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2022-2023 Intel Corporation + +"""Rust CFG parser. + +Rust uses its `cfg()` format in cargo. + +This may have the following functions: + - all() + - any() + - not() + +And additionally is made up of `identifier [ = str]`. Where the str is optional, +so you could have examples like: +``` +[target.`cfg(unix)`.dependencies] +[target.'cfg(target_arch = "x86_64")'.dependencies] +[target.'cfg(all(target_arch = "x86_64", target_arch = "x86"))'.dependencies] +``` +""" + +from __future__ import annotations +import dataclasses +import enum +import functools +import typing as T + + +from . import builder +from .. import mparser +from ..mesonlib import MesonBugException + +if T.TYPE_CHECKING: + _T = T.TypeVar('_T') + _LEX_TOKEN = T.Tuple['TokenType', T.Optional[str]] + _LEX_STREAM = T.Iterable[_LEX_TOKEN] + _LEX_STREAM_AH = T.Iterator[T.Tuple[_LEX_TOKEN, T.Optional[_LEX_TOKEN]]] + + +class TokenType(enum.Enum): + + LPAREN = enum.auto() + RPAREN = enum.auto() + STRING = enum.auto() + IDENTIFIER = enum.auto() + ALL = enum.auto() + ANY = enum.auto() + NOT = enum.auto() + COMMA = enum.auto() + EQUAL = enum.auto() + + +def lexer(raw: str) -> _LEX_STREAM: + """Lex a cfg() expression. + + :param raw: The raw cfg() expression + :return: An iterable of tokens + """ + buffer: T.List[str] = [] + is_string: bool = False + for s in raw: + if s.isspace() or s in {')', '(', ',', '='} or (s == '"' and buffer): + val = ''.join(buffer) + buffer.clear() + if is_string: + yield (TokenType.STRING, val) + elif val == 'any': + yield (TokenType.ANY, None) + elif val == 'all': + yield (TokenType.ALL, None) + elif val == 'not': + yield (TokenType.NOT, None) + elif val: + yield (TokenType.IDENTIFIER, val) + + if s == '(': + yield (TokenType.LPAREN, None) + continue + elif s == ')': + yield (TokenType.RPAREN, None) + continue + elif s == ',': + yield (TokenType.COMMA, None) + continue + elif s == '=': + yield (TokenType.EQUAL, None) + continue + elif s.isspace(): + continue + + if s == '"': + is_string = not is_string + else: + buffer.append(s) + if buffer: + # This should always be an identifier + yield (TokenType.IDENTIFIER, ''.join(buffer)) + + +def lookahead(iter: T.Iterator[_T]) -> T.Iterator[T.Tuple[_T, T.Optional[_T]]]: + """Get the current value of the iterable, and the next if possible. + + :param iter: The iterable to look into + :yield: A tuple of the current value, and, if possible, the next + :return: nothing + """ + current: _T + next_: T.Optional[_T] + try: + next_ = next(iter) + except StopIteration: + # This is an empty iterator, there's nothing to look ahead to + return + + while True: + current = next_ + try: + next_ = next(iter) + except StopIteration: + next_ = None + + yield current, next_ + + if next_ is None: + break + + +@dataclasses.dataclass +class IR: + + """Base IR node for Cargo CFG.""" + + filename: str + +@dataclasses.dataclass +class String(IR): + + value: str + + +@dataclasses.dataclass +class Identifier(IR): + + value: str + + +@dataclasses.dataclass +class Equal(IR): + + lhs: IR + rhs: IR + + +@dataclasses.dataclass +class Any(IR): + + args: T.List[IR] + + +@dataclasses.dataclass +class All(IR): + + args: T.List[IR] + + +@dataclasses.dataclass +class Not(IR): + + value: IR + + +def _parse(ast: _LEX_STREAM_AH, filename: str) -> IR: + (token, value), n_stream = next(ast) + if n_stream is not None: + ntoken, _ = n_stream + else: + ntoken, _ = (None, None) + + stream: T.List[_LEX_TOKEN] + if token is TokenType.IDENTIFIER: + if ntoken is TokenType.EQUAL: + return Equal(filename, Identifier(filename, value), _parse(ast, filename)) + if token is TokenType.STRING: + return String(filename, value) + if token is TokenType.EQUAL: + # In this case the previous caller already has handled the equal + return _parse(ast, filename) + if token in {TokenType.ANY, TokenType.ALL}: + type_ = All if token is TokenType.ALL else Any + assert ntoken is TokenType.LPAREN + next(ast) # advance the iterator to get rid of the LPAREN + stream = [] + args: T.List[IR] = [] + while token is not TokenType.RPAREN: + (token, value), _ = next(ast) + if token is TokenType.COMMA: + args.append(_parse(lookahead(iter(stream)), filename)) + stream.clear() + else: + stream.append((token, value)) + if stream: + args.append(_parse(lookahead(iter(stream)), filename)) + return type_(filename, args) + if token is TokenType.NOT: + next(ast) # advance the iterator to get rid of the LPAREN + stream = [] + # Mypy can't figure out that token is overridden inside the while loop + while token is not TokenType.RPAREN: # type: ignore + (token, value), _ = next(ast) + stream.append((token, value)) + return Not(filename, _parse(lookahead(iter(stream)), filename)) + + raise MesonBugException(f'Unhandled Cargo token: {token}') + + +def parse(ast: _LEX_STREAM, filename: str) -> IR: + """Parse the tokenized list into Meson AST. + + :param ast: An iterable of Tokens + :param filename: The name of the file being parsed + :return: An mparser Node to be used as a conditional + """ + ast_i: _LEX_STREAM_AH = lookahead(iter(ast)) + return _parse(ast_i, filename) + + +@functools.singledispatch +def ir_to_meson(ir: T.Any) -> mparser.BaseNode: + raise NotImplementedError + + +@ir_to_meson.register +def _(ir: String) -> mparser.BaseNode: + return builder.string(ir.value, ir.filename) + + +@ir_to_meson.register +def _(ir: Identifier) -> mparser.BaseNode: + host_machine = builder.identifier('host_machine', ir.filename) + if ir.value == "target_arch": + return builder.method('cpu_family', host_machine) + elif ir.value in {"target_os", "target_family"}: + return builder.method('system', host_machine) + elif ir.value == "target_endian": + return builder.method('endian', host_machine) + raise MesonBugException(f"Unhandled Cargo identifier: {ir.value}") + + +@ir_to_meson.register +def _(ir: Equal) -> mparser.BaseNode: + return builder.equal(ir_to_meson(ir.lhs), ir_to_meson(ir.rhs)) + + +@ir_to_meson.register +def _(ir: Not) -> mparser.BaseNode: + return builder.not_(ir_to_meson(ir.value), ir.filename) + + +@ir_to_meson.register +def _(ir: Any) -> mparser.BaseNode: + args = iter(reversed(ir.args)) + last = next(args) + cur = builder.or_(ir_to_meson(next(args)), ir_to_meson(last)) + for a in args: + cur = builder.or_(ir_to_meson(a), cur) + return cur + + +@ir_to_meson.register +def _(ir: All) -> mparser.BaseNode: + args = iter(reversed(ir.args)) + last = next(args) + cur = builder.and_(ir_to_meson(next(args)), ir_to_meson(last)) + for a in args: + cur = builder.and_(ir_to_meson(a), cur) + return cur diff -Nru meson-1.0.1/mesonbuild/cargo/interpreter.py meson-1.2.1/mesonbuild/cargo/interpreter.py --- meson-1.0.1/mesonbuild/cargo/interpreter.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/mesonbuild/cargo/interpreter.py 2023-08-07 22:54:34.000000000 +0000 @@ -0,0 +1,451 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2022-2023 Intel Corporation + +"""Interpreter for converting Cargo Toml definitions to Meson AST + +There are some notable limits here. We don't even try to convert something with +a build.rs: there's so few limits on what Cargo allows a build.rs (basically +none), and no good way for us to convert them. In that case, an actual meson +port will be required. +""" + +from __future__ import annotations +import dataclasses +import glob +import importlib +import itertools +import json +import os +import shutil +import typing as T + +from . import builder +from . import version +from .. import mparser +from .._pathlib import Path +from ..mesonlib import MesonException, Popen_safe + +if T.TYPE_CHECKING: + from types import ModuleType + + from . import manifest + from ..environment import Environment + +# tomllib is present in python 3.11, before that it is a pypi module called tomli, +# we try to import tomllib, then tomli, +# TODO: add a fallback to toml2json? +tomllib: T.Optional[ModuleType] = None +toml2json: T.Optional[str] = None +for t in ['tomllib', 'tomli']: + try: + tomllib = importlib.import_module(t) + break + except ImportError: + pass +else: + # TODO: it would be better to use an Executable here, which could be looked + # up in the cross file or provided by a wrap. However, that will have to be + # passed in externally, since we don't have (and I don't think we should), + # have access to the `Environment` for that in this module. + toml2json = shutil.which('toml2json') + + +def load_toml(filename: str) -> T.Dict[object, object]: + if tomllib: + with open(filename, 'rb') as f: + raw = tomllib.load(f) + else: + if toml2json is None: + raise MesonException('Could not find an implementation of tomllib, nor toml2json') + + p, out, err = Popen_safe([toml2json, filename]) + if p.returncode != 0: + raise MesonException('toml2json failed to decode output\n', err) + + raw = json.loads(out) + + if not isinstance(raw, dict): + raise MesonException("Cargo.toml isn't a dictionary? How did that happen?") + + return raw + + +def fixup_meson_varname(name: str) -> str: + """Fixup a meson variable name + + :param name: The name to fix + :return: the fixed name + """ + return name.replace('-', '_') + +# Pylance can figure out that these do not, in fact, overlap, but mypy can't +@T.overload +def _fixup_raw_mappings(d: manifest.BuildTarget) -> manifest.FixedBuildTarget: ... # type: ignore + +@T.overload +def _fixup_raw_mappings(d: manifest.LibTarget) -> manifest.FixedLibTarget: ... # type: ignore + +@T.overload +def _fixup_raw_mappings(d: manifest.Dependency) -> manifest.FixedDependency: ... + +def _fixup_raw_mappings(d: T.Union[manifest.BuildTarget, manifest.LibTarget, manifest.Dependency] + ) -> T.Union[manifest.FixedBuildTarget, manifest.FixedLibTarget, + manifest.FixedDependency]: + """Fixup raw cargo mappings to ones more suitable for python to consume. + + This does the following: + * replaces any `-` with `_`, cargo likes the former, but python dicts make + keys with `-` in them awkward to work with + * Convert Dependndency versions from the cargo format to something meson + understands + + :param d: The mapping to fix + :return: the fixed string + """ + raw = {fixup_meson_varname(k): v for k, v in d.items()} + if 'version' in raw: + assert isinstance(raw['version'], str), 'for mypy' + raw['version'] = version.convert(raw['version']) + return T.cast('T.Union[manifest.FixedBuildTarget, manifest.FixedLibTarget, manifest.FixedDependency]', raw) + + +@dataclasses.dataclass +class Package: + + """Representation of a Cargo Package entry, with defaults filled in.""" + + name: str + version: str + description: str + resolver: T.Optional[str] = None + authors: T.List[str] = dataclasses.field(default_factory=list) + edition: manifest.EDITION = '2015' + rust_version: T.Optional[str] = None + documentation: T.Optional[str] = None + readme: T.Optional[str] = None + homepage: T.Optional[str] = None + repository: T.Optional[str] = None + license: T.Optional[str] = None + license_file: T.Optional[str] = None + keywords: T.List[str] = dataclasses.field(default_factory=list) + categories: T.List[str] = dataclasses.field(default_factory=list) + workspace: T.Optional[str] = None + build: T.Optional[str] = None + links: T.Optional[str] = None + exclude: T.List[str] = dataclasses.field(default_factory=list) + include: T.List[str] = dataclasses.field(default_factory=list) + publish: bool = True + metadata: T.Dict[str, T.Dict[str, str]] = dataclasses.field(default_factory=dict) + default_run: T.Optional[str] = None + autobins: bool = True + autoexamples: bool = True + autotests: bool = True + autobenches: bool = True + + +@dataclasses.dataclass +class Dependency: + + """Representation of a Cargo Dependency Entry.""" + + version: T.List[str] + registry: T.Optional[str] = None + git: T.Optional[str] = None + branch: T.Optional[str] = None + rev: T.Optional[str] = None + path: T.Optional[str] = None + optional: bool = False + package: T.Optional[str] = None + default_features: bool = False + features: T.List[str] = dataclasses.field(default_factory=list) + + @classmethod + def from_raw(cls, raw: manifest.DependencyV) -> Dependency: + """Create a dependency from a raw cargo dictionary""" + if isinstance(raw, str): + return cls(version.convert(raw)) + return cls(**_fixup_raw_mappings(raw)) + + +@dataclasses.dataclass +class BuildTarget: + + name: str + crate_type: T.List[manifest.CRATE_TYPE] = dataclasses.field(default_factory=lambda: ['lib']) + path: dataclasses.InitVar[T.Optional[str]] = None + + # https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-test-field + # True for lib, bin, test + test: bool = True + + # https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-doctest-field + # True for lib + doctest: bool = False + + # https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-bench-field + # True for lib, bin, benchmark + bench: bool = True + + # https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-doc-field + # True for libraries and binaries + doc: bool = False + + harness: bool = True + edition: manifest.EDITION = '2015' + required_features: T.List[str] = dataclasses.field(default_factory=list) + plugin: bool = False + + +@dataclasses.dataclass +class Library(BuildTarget): + + """Representation of a Cargo Library Entry.""" + + doctest: bool = True + doc: bool = True + proc_macro: bool = False + crate_type: T.List[manifest.CRATE_TYPE] = dataclasses.field(default_factory=lambda: ['lib']) + doc_scrape_examples: bool = True + + +@dataclasses.dataclass +class Binary(BuildTarget): + + """Representation of a Cargo Bin Entry.""" + + doc: bool = True + + +@dataclasses.dataclass +class Test(BuildTarget): + + """Representation of a Cargo Test Entry.""" + + bench: bool = True + + +@dataclasses.dataclass +class Benchmark(BuildTarget): + + """Representation of a Cargo Benchmark Entry.""" + + test: bool = True + + +@dataclasses.dataclass +class Example(BuildTarget): + + """Representation of a Cargo Example Entry.""" + + crate_type: T.List[manifest.CRATE_TYPE] = dataclasses.field(default_factory=lambda: ['bin']) + + +@dataclasses.dataclass +class Manifest: + + """Cargo Manifest definition. + + Most of these values map up to the Cargo Manifest, but with default values + if not provided. + + Cargo subprojects can contain what Meson wants to treat as multiple, + interdependent, subprojects. + + :param subdir: the subdirectory that this cargo project is in + :param path: the path within the cargo subproject. + """ + + package: Package + dependencies: T.Dict[str, Dependency] + dev_dependencies: T.Dict[str, Dependency] + build_dependencies: T.Dict[str, Dependency] + lib: Library + bin: T.List[Binary] + test: T.List[Test] + bench: T.List[Benchmark] + example: T.List[Example] + features: T.Dict[str, T.List[str]] + target: T.Dict[str, T.Dict[str, Dependency]] + subdir: str + path: str = '' + + +def _create_project(package: Package, build: builder.Builder, env: Environment) -> mparser.FunctionNode: + """Create a function call + + :param package: The Cargo package to generate from + :param filename: The full path to the file + :param meson_version: The generating meson version + :return: a FunctionNode + """ + args: T.List[mparser.BaseNode] = [] + args.extend([ + build.string(package.name), + build.string('rust'), + ]) + kwargs: T.Dict[str, mparser.BaseNode] = { + 'version': build.string(package.version), + # Always assume that the generated meson is using the latest features + # This will warn when when we generate deprecated code, which is helpful + # for the upkeep of the module + 'meson_version': build.string(f'>= {env.coredata.version}'), + 'default_options': build.array([build.string(f'rust_std={package.edition}')]), + } + if package.license: + kwargs['license'] = build.string(package.license) + elif package.license_file: + kwargs['license_files'] = build.string(package.license_file) + + return build.function('project', args, kwargs) + + +def _convert_manifest(raw_manifest: manifest.Manifest, subdir: str, path: str = '') -> Manifest: + # This cast is a bit of a hack to deal with proc-macro + lib = _fixup_raw_mappings(raw_manifest.get('lib', {})) + + # We need to set the name field if it's not set manually, + # including if other fields are set in the lib section + lib.setdefault('name', raw_manifest['package']['name']) + + pkg = T.cast('manifest.FixedPackage', + {fixup_meson_varname(k): v for k, v in raw_manifest['package'].items()}) + + return Manifest( + Package(**pkg), + {k: Dependency.from_raw(v) for k, v in raw_manifest.get('dependencies', {}).items()}, + {k: Dependency.from_raw(v) for k, v in raw_manifest.get('dev-dependencies', {}).items()}, + {k: Dependency.from_raw(v) for k, v in raw_manifest.get('build-dependencies', {}).items()}, + Library(**lib), + [Binary(**_fixup_raw_mappings(b)) for b in raw_manifest.get('bin', {})], + [Test(**_fixup_raw_mappings(b)) for b in raw_manifest.get('test', {})], + [Benchmark(**_fixup_raw_mappings(b)) for b in raw_manifest.get('bench', {})], + [Example(**_fixup_raw_mappings(b)) for b in raw_manifest.get('example', {})], + raw_manifest.get('features', {}), + {k: {k2: Dependency.from_raw(v2) for k2, v2 in v['dependencies'].items()} + for k, v in raw_manifest.get('target', {}).items()}, + subdir, + path, + ) + + +def _load_manifests(subdir: str) -> T.Dict[str, Manifest]: + filename = os.path.join(subdir, 'Cargo.toml') + raw = load_toml(filename) + + manifests: T.Dict[str, Manifest] = {} + + raw_manifest: T.Union[manifest.Manifest, manifest.VirtualManifest] + if 'package' in raw: + raw_manifest = T.cast('manifest.Manifest', raw) + manifest_ = _convert_manifest(raw_manifest, subdir) + manifests[manifest_.package.name] = manifest_ + else: + raw_manifest = T.cast('manifest.VirtualManifest', raw) + + if 'workspace' in raw_manifest: + # XXX: need to verify that python glob and cargo globbing are the + # same and probably write a glob implementation. Blarg + + # We need to chdir here to make the glob work correctly + pwd = os.getcwd() + os.chdir(subdir) + members: T.Iterable[str] + try: + members = itertools.chain.from_iterable( + glob.glob(m) for m in raw_manifest['workspace']['members']) + finally: + os.chdir(pwd) + if 'exclude' in raw_manifest['workspace']: + members = (x for x in members if x not in raw_manifest['workspace']['exclude']) + + for m in members: + filename = os.path.join(subdir, m, 'Cargo.toml') + raw = load_toml(filename) + + raw_manifest = T.cast('manifest.Manifest', raw) + man = _convert_manifest(raw_manifest, subdir, m) + manifests[man.package.name] = man + + return manifests + + +def load_all_manifests(subproject_dir: str) -> T.Dict[str, Manifest]: + """Find all cargo subprojects, and load them + + :param subproject_dir: Directory to look for subprojects in + :return: A dictionary of rust project names to Manifests + """ + manifests: T.Dict[str, Manifest] = {} + for p in Path(subproject_dir).iterdir(): + if p.is_dir() and (p / 'Cargo.toml').exists(): + manifests.update(_load_manifests(str(p))) + return manifests + + +def _create_lib(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: + kw: T.Dict[str, mparser.BaseNode] = {} + if cargo.dependencies: + ids = [build.identifier(f'dep_{n}') for n in cargo.dependencies] + kw['dependencies'] = build.array( + [build.method('get_variable', i, [build.string('dep')]) for i in ids]) + + # FIXME: currently assuming that an rlib is being generated, which is + # the most common. + return [ + build.assign( + build.function( + 'static_library', + [ + build.string(fixup_meson_varname(cargo.package.name)), + build.string(os.path.join('src', 'lib.rs')), + ], + kw, + ), + 'lib' + ), + + build.assign( + build.function( + 'declare_dependency', + kw={'link_with': build.identifier('lib'), **kw}, + ), + 'dep' + ) + ] + + +def interpret(cargo: Manifest, env: Environment) -> mparser.CodeBlockNode: + filename = os.path.join(cargo.subdir, cargo.path, 'Cargo.toml') + build = builder.Builder(filename) + + ast: T.List[mparser.BaseNode] = [ + _create_project(cargo.package, build, env), + build.assign(build.function('import', [build.string('rust')]), 'rust'), + ] + + if cargo.dependencies: + for name, dep in cargo.dependencies.items(): + kw = { + 'version': build.array([build.string(s) for s in dep.version]), + } + ast.extend([ + build.assign( + build.method( + 'cargo', + build.identifier('rust'), + [build.string(name)], + kw, + ), + f'dep_{fixup_meson_varname(name)}', + ), + ]) + + # Libs are always auto-discovered and there's no other way to handle them, + # which is unfortunate for reproducability + if os.path.exists(os.path.join(env.source_dir, cargo.subdir, cargo.path, 'src', 'lib.rs')): + ast.extend(_create_lib(cargo, build)) + + # XXX: make this not awful + block = builder.block(filename) + block.lines = ast + return block diff -Nru meson-1.0.1/mesonbuild/cargo/manifest.py meson-1.2.1/mesonbuild/cargo/manifest.py --- meson-1.0.1/mesonbuild/cargo/manifest.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/mesonbuild/cargo/manifest.py 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,227 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2022-2023 Intel Corporation + +"""Type definitions for cargo manifest files.""" + +from __future__ import annotations +import typing as T + +from typing_extensions import Literal, TypedDict, Required + +EDITION = Literal['2015', '2018', '2021'] +CRATE_TYPE = Literal['bin', 'lib', 'dylib', 'staticlib', 'cdylib', 'rlib', 'proc-macro'] + +Package = TypedDict( + 'Package', + { + 'name': Required[str], + 'version': Required[str], + 'authors': T.List[str], + 'edition': EDITION, + 'rust-version': str, + 'description': str, + 'readme': str, + 'license': str, + 'license-file': str, + 'keywords': T.List[str], + 'categories': T.List[str], + 'workspace': str, + 'build': str, + 'links': str, + 'include': T.List[str], + 'exclude': T.List[str], + 'publish': bool, + 'metadata': T.Dict[str, T.Dict[str, str]], + 'default-run': str, + 'autobins': bool, + 'autoexamples': bool, + 'autotests': bool, + 'autobenches': bool, + }, + total=False, +) +"""A description of the Package Dictionary.""" + +class FixedPackage(TypedDict, total=False): + + """A description of the Package Dictionary, fixed up.""" + + name: Required[str] + version: Required[str] + authors: T.List[str] + edition: EDITION + rust_version: str + description: str + readme: str + license: str + license_file: str + keywords: T.List[str] + categories: T.List[str] + workspace: str + build: str + links: str + include: T.List[str] + exclude: T.List[str] + publish: bool + metadata: T.Dict[str, T.Dict[str, str]] + default_run: str + autobins: bool + autoexamples: bool + autotests: bool + autobenches: bool + + +class Badge(TypedDict): + + """An entry in the badge section.""" + + status: Literal['actively-developed', 'passively-developed', 'as-is', 'experimental', 'deprecated', 'none'] + + +Dependency = TypedDict( + 'Dependency', + { + 'version': str, + 'registry': str, + 'git': str, + 'branch': str, + 'rev': str, + 'path': str, + 'optional': bool, + 'package': str, + 'default-features': bool, + 'features': T.List[str], + }, + total=False, +) +"""An entry in the *dependencies sections.""" + + +class FixedDependency(TypedDict, total=False): + + """An entry in the *dependencies sections, fixed up.""" + + version: T.List[str] + registry: str + git: str + branch: str + rev: str + path: str + optional: bool + package: str + default_features: bool + features: T.List[str] + + +DependencyV = T.Union[Dependency, str] +"""A Dependency entry, either a string or a Dependency Dict.""" + + +_BaseBuildTarget = TypedDict( + '_BaseBuildTarget', + { + 'path': str, + 'test': bool, + 'doctest': bool, + 'bench': bool, + 'doc': bool, + 'plugin': bool, + 'proc-macro': bool, + 'harness': bool, + 'edition': EDITION, + 'crate-type': T.List[CRATE_TYPE], + 'required-features': T.List[str], + }, + total=False, +) + + +class BuildTarget(_BaseBuildTarget, total=False): + + name: Required[str] + +class LibTarget(_BaseBuildTarget, total=False): + + name: str + + +class _BaseFixedBuildTarget(TypedDict, total=False): + path: str + test: bool + doctest: bool + bench: bool + doc: bool + plugin: bool + harness: bool + edition: EDITION + crate_type: T.List[CRATE_TYPE] + required_features: T.List[str] + + +class FixedBuildTarget(_BaseFixedBuildTarget, total=False): + + name: str + +class FixedLibTarget(_BaseFixedBuildTarget, total=False): + + name: Required[str] + proc_macro: bool + + +class Target(TypedDict): + + """Target entry in the Manifest File.""" + + dependencies: T.Dict[str, DependencyV] + + +class Workspace(TypedDict): + + """The representation of a workspace. + + In a vritual manifest the :attribute:`members` is always present, but in a + project manifest, an empty workspace may be provided, in which case the + workspace is implicitly filled in by values from the path based dependencies. + + the :attribute:`exclude` is always optional + """ + + members: T.List[str] + exclude: T.List[str] + + +Manifest = TypedDict( + 'Manifest', + { + 'package': Package, + 'badges': T.Dict[str, Badge], + 'dependencies': T.Dict[str, DependencyV], + 'dev-dependencies': T.Dict[str, DependencyV], + 'build-dependencies': T.Dict[str, DependencyV], + 'lib': LibTarget, + 'bin': T.List[BuildTarget], + 'test': T.List[BuildTarget], + 'bench': T.List[BuildTarget], + 'example': T.List[BuildTarget], + 'features': T.Dict[str, T.List[str]], + 'target': T.Dict[str, Target], + 'workspace': Workspace, + + # TODO: patch? + # TODO: replace? + }, + total=False, +) +"""The Cargo Manifest format.""" + + +class VirtualManifest(TypedDict): + + """The Representation of a virtual manifest. + + Cargo allows a root manifest that contains only a workspace, this is called + a virtual manifest. This doesn't really map 1:1 with any meson concept, + except perhaps the proposed "meta project". + """ + + workspace: Workspace diff -Nru meson-1.0.1/mesonbuild/cargo/version.py meson-1.2.1/mesonbuild/cargo/version.py --- meson-1.0.1/mesonbuild/cargo/version.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/mesonbuild/cargo/version.py 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2022-2023 Intel Corporation + +"""Convert Cargo versions into Meson compatible ones.""" + +from __future__ import annotations +import typing as T + + +def convert(cargo_ver: str) -> T.List[str]: + """Convert a Cargo compatible version into a Meson compatible one. + + :param cargo_ver: The version, as Cargo specifies + :return: A list of version constraints, as Meson understands them + """ + # Cleanup, just for safety + cargo_ver = cargo_ver.strip() + cargo_vers = [c.strip() for c in cargo_ver.split(',')] + + out: T.List[str] = [] + + for ver in cargo_vers: + # This covers >= and =< as well + # https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#comparison-requirements + if ver.startswith(('>', '<', '=')): + out.append(ver) + + elif ver.startswith('~'): + # Rust has these tilde requirements, which means that it is >= to + # the version, but less than the next version + # https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#tilde-requirements + # we convert those into a pair of constraints + v = ver[1:].split('.') + out.append(f'>= {".".join(v)}') + if len(v) == 3: + out.append(f'< {v[0]}.{int(v[1]) + 1}.0') + elif len(v) == 2: + out.append(f'< {v[0]}.{int(v[1]) + 1}') + else: + out.append(f'< {int(v[0]) + 1}') + + elif '*' in ver: + # Rust has astrisk requirements,, which are like 1.* == ~1 + # https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#wildcard-requirements + v = ver.split('.')[:-1] + if v: + out.append(f'>= {".".join(v)}') + if len(v) == 2: + out.append(f'< {v[0]}.{int(v[1]) + 1}') + elif len(v) == 1: + out.append(f'< {int(v[0]) + 1}') + + else: + # a Caret version is equivalent to the default strategy + # https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#caret-requirements + if ver.startswith('^'): + ver = ver[1:] + + # If there is no qualifier, then it means this or the next non-zero version + # That means that if this is `1.1.0``, then we need `>= 1.1.0` && `< 2.0.0` + # Or if we have `0.1.0`, then we need `>= 0.1.0` && `< 0.2.0` + # Or if we have `0.1`, then we need `>= 0.1.0` && `< 0.2.0` + # Or if we have `0.0.0`, then we need `< 1.0.0` + # Or if we have `0.0`, then we need `< 1.0.0` + # Or if we have `0`, then we need `< 1.0.0` + # Or if we have `0.0.3`, then we need `>= 0.0.3` && `< 0.0.4` + # https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-cratesio + # + # this works much like the ~ versions, but in reverse. Tilde starts + # at the patch version and works up, to the major version, while + # bare numbers start at the major version and work down to the patch + # version + vers = ver.split('.') + min_: T.List[str] = [] + max_: T.List[str] = [] + bumped = False + for v_ in vers: + if v_ != '0' and not bumped: + min_.append(v_) + max_.append(str(int(v_) + 1)) + bumped = True + else: + if not (bumped and v_ == '0'): + min_.append(v_) + if not bumped: + max_.append('0') + + # If there is no minimum, don't emit one + if set(min_) != {'0'}: + out.append('>= {}'.format('.'.join(min_))) + if set(max_) != {'0'}: + out.append('< {}'.format('.'.join(max_))) + else: + out.append('< 1') + + return out diff -Nru meson-1.0.1/mesonbuild/cmake/__init__.py meson-1.2.1/mesonbuild/cmake/__init__.py --- meson-1.0.1/mesonbuild/cmake/__init__.py 2022-06-19 19:10:06.000000000 +0000 +++ meson-1.2.1/mesonbuild/cmake/__init__.py 2023-06-28 14:48:20.000000000 +0000 @@ -19,30 +19,21 @@ '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, SingleTargetOptions, TargetOptions, cmake_defines_to_args, language_map, backend_generator_map, cmake_get_generator_args, check_cmake_args, cmake_is_debug +from .common import CMakeException, TargetOptions, cmake_defines_to_args, language_map, check_cmake_args, cmake_is_debug from .executor import CMakeExecutor -from .fileapi import CMakeFileAPI -from .generator import parse_generator_expressions from .interpreter import CMakeInterpreter from .toolchain import CMakeToolchain, CMakeExecScope -from .traceparser import CMakeTarget, CMakeTraceLine, CMakeTraceParser -from .tracetargets import resolve_cmake_trace_targets, ResolvedTarget +from .traceparser import CMakeTarget, CMakeTraceParser +from .tracetargets import resolve_cmake_trace_targets diff -Nru meson-1.0.1/mesonbuild/cmake/common.py meson-1.2.1/mesonbuild/cmake/common.py --- meson-1.0.1/mesonbuild/cmake/common.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/cmake/common.py 2023-05-30 15:42:56.000000000 +0000 @@ -23,6 +23,7 @@ if T.TYPE_CHECKING: from ..environment import Environment + from ..interpreterbase import TYPE_var language_map = { 'c': 'C', @@ -121,16 +122,11 @@ 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]: +def cmake_defines_to_args(raw: T.List[T.Dict[str, TYPE_var]], 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') @@ -146,7 +142,7 @@ return res -# TODO: this functuin will become obsolete once the `cmake_args` kwarg is dropped +# TODO: this function 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] diff -Nru meson-1.0.1/mesonbuild/cmake/traceparser.py meson-1.2.1/mesonbuild/cmake/traceparser.py --- meson-1.0.1/mesonbuild/cmake/traceparser.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/cmake/traceparser.py 2023-05-23 15:20:02.000000000 +0000 @@ -288,7 +288,7 @@ raise CMakeException(f'CMake: {function}() {error}\n{tline}') def _cmake_set(self, tline: CMakeTraceLine) -> None: - """Handler for the CMake set() function in all variaties. + """Handler for the CMake set() function in all varieties. comes in three flavors: set( [PARENT_SCOPE]) @@ -509,7 +509,7 @@ targets += curr.split(';') if not args: - return self._gen_exception('set_property', 'faild to parse argument list', tline) + return self._gen_exception('set_property', 'failed to parse argument list', tline) if len(args) == 1: # Tries to set property to nothing so nothing has to be done @@ -575,7 +575,7 @@ targets.append(curr) - # Now we need to try to reconsitute the original quoted format of the + # Now we need to try to reconstitute the original quoted format of the # arguments, as a property value could have spaces in it. Unlike # set_property() this is not context free. There are two approaches I # can think of, both have drawbacks: @@ -586,7 +586,7 @@ # # 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. + # synchronization 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 diff -Nru meson-1.0.1/mesonbuild/compilers/asm.py meson-1.2.1/mesonbuild/compilers/asm.py --- meson-1.0.1/mesonbuild/compilers/asm.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/asm.py 2023-08-07 22:54:34.000000000 +0000 @@ -1,11 +1,15 @@ import os import typing as T -from ..mesonlib import EnvironmentException, get_meson_command +from ..mesonlib import EnvironmentException, OptionKey, get_meson_command from .compilers import Compiler +from .mixins.metrowerks import MetrowerksCompiler, mwasmarm_instruction_set_args, mwasmeppc_instruction_set_args if T.TYPE_CHECKING: from ..environment import Environment + from ..linkers.linkers import DynamicLinker + from ..mesonlib import MachineChoice + from ..envconfig import MachineInfo nasm_optimization_args = { 'plain': [], @@ -22,6 +26,23 @@ language = 'nasm' id = 'nasm' + # https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features + crt_args: T.Dict[str, T.List[str]] = { + 'none': [], + 'md': ['/DEFAULTLIB:ucrt.lib', '/DEFAULTLIB:vcruntime.lib', '/DEFAULTLIB:msvcrt.lib'], + 'mdd': ['/DEFAULTLIB:ucrtd.lib', '/DEFAULTLIB:vcruntimed.lib', '/DEFAULTLIB:msvcrtd.lib'], + 'mt': ['/DEFAULTLIB:libucrt.lib', '/DEFAULTLIB:libvcruntime.lib', '/DEFAULTLIB:libcmt.lib'], + 'mtd': ['/DEFAULTLIB:libucrtd.lib', '/DEFAULTLIB:libvcruntimed.lib', '/DEFAULTLIB:libcmtd.lib'], + } + + def __init__(self, ccache: T.List[str], 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): + super().__init__(ccache, exelist, version, for_machine, info, linker, full_version, is_cross) + if 'link' in self.linker.id: + self.base_options.add(OptionKey('b_vscrt')) + def needs_static_linker(self) -> bool: return True @@ -97,9 +118,42 @@ def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: return [] + # Linking ASM-only objects into an executable or DLL + # require this, otherwise it'll fail to find + # _WinMain or _DllMainCRTStartup. + def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: + if not self.info.is_windows(): + return [] + if crt_val in self.crt_args: + return self.crt_args[crt_val] + 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[dbg] + elif buildtype == 'debugoptimized': + return self.crt_args[rel] + elif buildtype == 'release': + return self.crt_args[rel] + elif buildtype == 'minsize': + return self.crt_args[rel] + else: + assert buildtype == 'custom' + raise EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') + class YasmCompiler(NasmCompiler): id = 'yasm' + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + # Yasm is incompatible with Nasm optimization flags. + return [] + def get_exelist(self, ccache: bool = True) -> T.List[str]: # Wrap yasm executable with an internal script that will write depfile. exelist = super().get_exelist(ccache) @@ -229,3 +283,48 @@ def depfile_for_object(self, objfile: str) -> T.Optional[str]: return None + + +class MetrowerksAsmCompiler(MetrowerksCompiler, Compiler): + language = 'nasm' + + def __init__(self, ccache: T.List[str], 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): + Compiler.__init__(self, ccache, exelist, version, for_machine, info, linker, full_version, is_cross) + MetrowerksCompiler.__init__(self) + + self.warn_args = {'0': [], '1': [], '2': [], '3': [], 'everything': []} # type: T.Dict[str, T.List[str]] + self.can_compile_suffixes.add('s') + + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: + return [] + + def get_pic_args(self) -> T.List[str]: + return [] + + def needs_static_linker(self) -> bool: + return True + + +class MetrowerksAsmCompilerARM(MetrowerksAsmCompiler): + id = 'mwasmarm' + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwasmarm_instruction_set_args.get(instruction_set, None) + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + if self.info.cpu_family not in {'arm'}: + raise EnvironmentException(f'ASM compiler {self.id!r} does not support {self.info.cpu_family} CPU family') + + +class MetrowerksAsmCompilerEmbeddedPowerPC(MetrowerksAsmCompiler): + id = 'mwasmeppc' + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwasmeppc_instruction_set_args.get(instruction_set, None) + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + if self.info.cpu_family not in {'ppc'}: + raise EnvironmentException(f'ASM compiler {self.id!r} does not support {self.info.cpu_family} CPU family') diff -Nru meson-1.0.1/mesonbuild/compilers/c.py meson-1.2.1/mesonbuild/compilers/c.py --- meson-1.0.1/mesonbuild/compilers/c.py 2023-02-01 21:43:18.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/c.py 2023-06-28 14:48:20.000000000 +0000 @@ -34,6 +34,8 @@ from .mixins.elbrus import ElbrusCompiler from .mixins.pgi import PGICompiler from .mixins.emscripten import EmscriptenMixin +from .mixins.metrowerks import MetrowerksCompiler +from .mixins.metrowerks import mwccarm_instruction_set_args, mwcceppc_instruction_set_args from .compilers import ( gnu_winlibs, msvc_winlibs, @@ -45,7 +47,7 @@ from ..dependencies import Dependency from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice from ..programs import ExternalProgram from .compilers import CompileCheckMode @@ -482,10 +484,10 @@ args = [] std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] if std.value.startswith('gnu'): - mlog.log_once( + mlog.log( '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.') + 'may cause compilation to fail.', once=True) # 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') @@ -538,7 +540,7 @@ key = OptionKey('std', machine=self.for_machine, lang=self.language) std = options[key] if std.value == 'c89': - mlog.log_once("ICL doesn't explicitly implement c89, setting the standard to 'none', which is close.") + mlog.log("ICL doesn't explicitly implement c89, setting the standard to 'none', which is close.", once=True) elif std.value != 'none': args.append('/Qstd:' + std.value) return args @@ -738,3 +740,60 @@ class C2000CCompiler(TICCompiler): # Required for backwards compat with projects created before ti-cgt support existed id = 'c2000' + +class MetrowerksCCompilerARM(MetrowerksCompiler, CCompiler): + id = 'mwccarm' + + def __init__(self, ccache: T.List[str], 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, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + MetrowerksCompiler.__init__(self) + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwccarm_instruction_set_args.get(instruction_set, None) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + c_stds = ['c99'] + opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + return opts + + 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 != 'none': + args.append('-lang') + args.append(std.value) + return args + +class MetrowerksCCompilerEmbeddedPowerPC(MetrowerksCompiler, CCompiler): + id = 'mwcceppc' + + def __init__(self, ccache: T.List[str], 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, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + MetrowerksCompiler.__init__(self) + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwcceppc_instruction_set_args.get(instruction_set, None) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + c_stds = ['c99'] + opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + return opts + + 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 != 'none': + args.append('-lang ' + std.value) + return args diff -Nru meson-1.0.1/mesonbuild/compilers/c_function_attributes.py meson-1.2.1/mesonbuild/compilers/c_function_attributes.py --- meson-1.0.1/mesonbuild/compilers/c_function_attributes.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/c_function_attributes.py 2023-05-23 15:20:02.000000000 +0000 @@ -100,6 +100,8 @@ 'int foo(void) __attribute__((unused));', 'used': 'int foo(void) __attribute__((used));', + 'vector_size': + '__attribute__((vector_size(32))); int foo(void) { return 0; }', 'visibility': ''' int foo_def(void) __attribute__((visibility("default"))); int foo_hid(void) __attribute__((visibility("hidden"))); diff -Nru meson-1.0.1/mesonbuild/compilers/compilers.py meson-1.2.1/mesonbuild/compilers/compilers.py --- meson-1.0.1/mesonbuild/compilers/compilers.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/compilers.py 2023-08-07 22:54:34.000000000 +0000 @@ -26,7 +26,7 @@ from ..mesonlib import ( HoldableObject, EnvironmentException, MesonException, - Popen_safe, LibType, TemporaryDirectoryWinProof, OptionKey, + Popen_safe_logged, LibType, TemporaryDirectoryWinProof, OptionKey, ) from ..arglist import CompilerArgs @@ -36,7 +36,8 @@ from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker, RSPFileSyntax + from ..linkers import RSPFileSyntax + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice from ..dependencies import Dependency @@ -45,7 +46,7 @@ """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.""" +Also add corresponding autodetection code in detect.py.""" header_suffixes = {'h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di'} obj_suffixes = {'o', 'obj', 'res'} @@ -77,14 +78,14 @@ c_cpp_suffixes = {'h'} cpp_suffixes = set(lang_suffixes['cpp']) | c_cpp_suffixes c_suffixes = set(lang_suffixes['c']) | c_cpp_suffixes -assembler_suffixes = {'s', 'S', 'asm', 'masm'} +assembler_suffixes = {'s', 'S', 'sx', 'asm', 'masm'} llvm_ir_suffixes = {'ll'} all_suffixes = set(itertools.chain(*lang_suffixes.values(), assembler_suffixes, llvm_ir_suffixes, c_cpp_suffixes)) source_suffixes = all_suffixes - header_suffixes # List of languages that by default consume and output libraries following the # C ABI; these can generally be used interchangeably # This must be sorted, see sort_clink(). -clib_langs = ('objcpp', 'cpp', 'objc', 'c', 'fortran') +clib_langs = ('objcpp', 'cpp', 'objc', 'c', 'nasm', 'fortran') # 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() # This must be sorted, see sort_clink(). @@ -133,11 +134,14 @@ suffix = fname.split('.')[-1] return suffix in header_suffixes +def is_source_suffix(suffix: str) -> bool: + return suffix in source_suffixes + def is_source(fname: 'mesonlib.FileOrString') -> bool: if isinstance(fname, mesonlib.File): fname = fname.fname suffix = fname.split('.')[-1].lower() - return suffix in source_suffixes + return is_source_suffix(suffix) def is_assembly(fname: 'mesonlib.FileOrString') -> bool: if isinstance(fname, mesonlib.File): @@ -334,6 +338,17 @@ return v +def are_asserts_disabled(options: KeyedOptionDictType) -> bool: + """Should debug assertions be disabled + + :param options: OptionDictionary + :return: whether to disable assertions or not + """ + return (options[OptionKey('b_ndebug')].value == 'true' or + (options[OptionKey('b_ndebug')].value == 'if-release' and + options[OptionKey('buildtype')].value in {'release', 'plain'})) + + def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler') -> T.List[str]: args = [] # type T.List[str] try: @@ -365,10 +380,7 @@ except KeyError: pass try: - 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() + args += compiler.get_assert_args(are_asserts_disabled(options)) except KeyError: pass # This does not need a try...except @@ -456,11 +468,13 @@ class RunResult(HoldableObject): def __init__(self, compiled: bool, returncode: int = 999, - stdout: str = 'UNDEFINED', stderr: str = 'UNDEFINED'): + stdout: str = 'UNDEFINED', stderr: str = 'UNDEFINED', + cached: bool = False): self.compiled = compiled self.returncode = returncode self.stdout = stdout self.stderr = stderr + self.cached = cached class CompileResult(HoldableObject): @@ -598,7 +612,7 @@ return self.exelist.copy() if ccache else self.exelist_no_ccache.copy() def get_linker_exelist(self) -> T.List[str]: - return self.linker.get_exelist() + return self.linker.get_exelist() if self.linker else self.get_exelist() @abc.abstractmethod def get_output_args(self, outputname: str) -> T.List[str]: @@ -689,14 +703,40 @@ dependencies: T.Optional[T.List['Dependency']] = None) -> RunResult: raise EnvironmentException('Language %s does not support run checks.' % self.get_display_language()) + # Caching run() in general seems too risky (no way to know what the program + # depends on), but some callers know more about the programs they intend to + # run. + # For now we just accept code as a string, as that's what internal callers + # need anyway. If we wanted to accept files, the cache key would need to + # include mtime. + def cached_run(self, code: str, 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: + run_check_cache = env.coredata.run_check_cache + args = self.build_wrapper_args(env, extra_args, dependencies, CompileCheckMode('link')) + key = (code, tuple(args)) + if key in run_check_cache: + p = run_check_cache[key] + p.cached = True + mlog.debug('Using cached run result:') + mlog.debug('Code:\n', code) + mlog.debug('Args:\n', extra_args) + mlog.debug('Cached run returncode:\n', p.returncode) + mlog.debug('Cached run stdout:\n', p.stdout) + mlog.debug('Cached run stderr:\n', p.stderr) + else: + p = self.run(code, env, extra_args=extra_args, dependencies=dependencies) + run_check_cache[key] = p + return p + 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: + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]: raise EnvironmentException('Language %s does not support sizeof checks.' % self.get_display_language()) 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: + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]: raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language()) def has_function(self, funcname: str, prefix: str, env: 'Environment', *, @@ -724,7 +764,7 @@ return args.copy() def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], - libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]: + libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]: raise EnvironmentException(f'Language {self.get_display_language()} does not support library finding.') def get_library_naming(self, env: 'Environment', libtype: LibType, @@ -819,15 +859,12 @@ command_list = self.get_exelist(ccache=not no_ccache) + 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) + p, stdo, stde = Popen_safe_logged(command_list, msg='Command line', cwd=tmpdirname, env=os_env) result = CompileResult(stdo, stde, command_list, p.returncode, input_name=srcname) if want_output: @@ -904,6 +941,12 @@ return self.linker.build_rpath_args( env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath) + def get_archive_name(self, filename: str) -> str: + return self.linker.get_archive_name(filename) + + def get_command_to_archive_shlib(self) -> T.List[str]: + return self.linker.get_command_to_archive_shlib() + def thread_flags(self, env: 'Environment') -> T.List[str]: return [] @@ -1043,7 +1086,12 @@ def get_coverage_link_args(self) -> T.List[str]: return self.linker.get_coverage_args() - def get_disable_assert_args(self) -> T.List[str]: + def get_assert_args(self, disable: bool) -> T.List[str]: + """Get arguments to enable or disable assertion. + + :param disable: Whether to disable assertions + :return: A list of string arguments for this compiler + """ return [] def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: @@ -1200,7 +1248,7 @@ 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 + This generally needs to be set on a per-language basis. 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. @@ -1238,7 +1286,7 @@ 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. + """Helper for getting a cached 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(). @@ -1333,7 +1381,7 @@ # 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 + # This is how autotools works, and the env vars feature is for # autotools compatibility. largs.extend_value(comp_options) diff -Nru meson-1.0.1/mesonbuild/compilers/cpp.py meson-1.2.1/mesonbuild/compilers/cpp.py --- meson-1.0.1/mesonbuild/compilers/cpp.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/cpp.py 2023-08-07 22:54:34.000000000 +0000 @@ -39,6 +39,8 @@ from .mixins.elbrus import ElbrusCompiler from .mixins.pgi import PGICompiler from .mixins.emscripten import EmscriptenMixin +from .mixins.metrowerks import MetrowerksCompiler +from .mixins.metrowerks import mwccarm_instruction_set_args, mwcceppc_instruction_set_args if T.TYPE_CHECKING: from .compilers import CompileCheckMode @@ -46,7 +48,7 @@ from ..dependencies import Dependency from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice from ..programs import ExternalProgram CompilerMixinBase = CLikeCompiler @@ -58,8 +60,8 @@ if eh == 'none': args.append('-fno-exceptions') elif eh in {'s', 'c'}: - mlog.warning('non-MSVC compilers do not support ' + eh + ' exception handling.' + - 'You may want to set eh to \'default\'.') + mlog.warning(f'non-MSVC compilers do not support {eh} exception handling. ' + 'You may want to set eh to \'default\'.', fatal=False) class CPPCompiler(CLikeCompiler, Compiler): def attribute_check_func(self, name: str) -> str: @@ -181,7 +183,45 @@ return opts -class ClangCPPCompiler(ClangCompiler, CPPCompiler): +class _StdCPPLibMixin(CompilerMixinBase): + + """Detect whether to use libc++ or libstdc++.""" + + @functools.lru_cache(None) + def language_stdlib_only_link_flags(self, env: Environment) -> T.List[str]: + """Detect the C++ stdlib and default search dirs + + As an optimization, this method will cache the value, to avoid building the same values over and over + + :param env: An Environment object + :raises MesonException: If a stdlib cannot be determined + """ + + # 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_dirs = [f'-L{d}' for d in self.get_compiler_dirs(env, 'libraries')] + + machine = env.machines[self.for_machine] + assert machine is not None, 'for mypy' + + # We need to determine whether to use libc++ or libstdc++. We can't + # really know the answer in most cases, only the most likely answer, + # because a user can install things themselves or build custom images. + search_order: T.List[str] = [] + if machine.system in {'android', 'darwin', 'dragonfly', 'freebsd', 'netbsd', 'openbsd'}: + search_order = ['c++', 'stdc++'] + else: + search_order = ['stdc++', 'c++'] + for lib in search_order: + if self.find_library(lib, env, []) is not None: + return search_dirs + [f'-l{lib}'] + # TODO: maybe a bug exception? + raise MesonException('Could not detect either libc++ or libstdc++ as your C++ stdlib implementation.') + + +class ClangCPPCompiler(_StdCPPLibMixin, ClangCompiler, CPPCompiler): def __init__(self, ccache: T.List[str], 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, @@ -247,16 +287,6 @@ return libs return [] - 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_dirs: T.List[str] = [] - for d in self.get_compiler_dirs(env, 'libraries'): - search_dirs.append(f'-L{d}') - return search_dirs + ['-lstdc++'] - class ArmLtdClangCPPCompiler(ClangCPPCompiler): @@ -264,15 +294,7 @@ class AppleClangCPPCompiler(ClangCPPCompiler): - def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: - # We need to apply the search prefix here, as these link arguments may - # 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_dirs: T.List[str] = [] - for d in self.get_compiler_dirs(env, 'libraries'): - search_dirs.append(f'-L{d}') - return search_dirs + ['-lc++'] + pass class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler): @@ -351,7 +373,7 @@ return [] -class GnuCPPCompiler(GnuCompiler, CPPCompiler): +class GnuCPPCompiler(_StdCPPLibMixin, GnuCompiler, CPPCompiler): def __init__(self, ccache: T.List[str], 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, @@ -384,11 +406,15 @@ False, ) }) - opts[key].choices = [ + cppstd_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 version_compare(self.version, '>=12.2.0'): + cppstd_choices.append('c++23') + cppstd_choices.append('gnu++23') + opts[key].choices = cppstd_choices if self.info.is_windows() or self.info.is_cygwin(): opts.update({ key.evolve('winlibs'): coredata.UserArrayOption( @@ -428,16 +454,6 @@ 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, 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_dirs: T.List[str] = [] - for d in self.get_compiler_dirs(env, 'libraries'): - search_dirs.append(f'-L{d}') - return ['-lstdc++'] - class PGICPPCompiler(PGICompiler, CPPCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, @@ -692,7 +708,8 @@ 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) + 'attempting best effort; setting the standard to C++14', + once=True, fatal=False) # 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. @@ -738,7 +755,7 @@ 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') + mlog.warning('This version of MSVC does not support cpp_std arguments', fatal=False) options = copy.copy(options) options[key].value = 'none' @@ -888,3 +905,60 @@ class C2000CPPCompiler(TICPPCompiler): # Required for backwards compat with projects created before ti-cgt support existed id = 'c2000' + +class MetrowerksCPPCompilerARM(MetrowerksCompiler, CPPCompiler): + id = 'mwccarm' + + def __init__(self, ccache: T.List[str], 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, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + MetrowerksCompiler.__init__(self) + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwccarm_instruction_set_args.get(instruction_set, None) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CPPCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + return opts + + 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 != 'none': + args.append('-lang') + args.append(std.value) + return args + +class MetrowerksCPPCompilerEmbeddedPowerPC(MetrowerksCompiler, CPPCompiler): + id = 'mwcceppc' + + def __init__(self, ccache: T.List[str], 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, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + MetrowerksCompiler.__init__(self) + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwcceppc_instruction_set_args.get(instruction_set, None) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CPPCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + return opts + + 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 != 'none': + args.append('-lang ' + std.value) + return args diff -Nru meson-1.0.1/mesonbuild/compilers/cs.py meson-1.2.1/mesonbuild/compilers/cs.py --- meson-1.0.1/mesonbuild/compilers/cs.py 2022-11-01 19:00:11.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/cs.py 2023-05-30 15:42:56.000000000 +0000 @@ -100,7 +100,7 @@ pc = subprocess.Popen(self.exelist + self.get_always_args() + [src], cwd=work_dir) pc.wait() if pc.returncode != 0: - raise EnvironmentException('C# compiler %s can not compile programs.' % self.name_string()) + raise EnvironmentException('C# compiler %s cannot compile programs.' % self.name_string()) if self.runner: cmdlist = [self.runner, obj] else: diff -Nru meson-1.0.1/mesonbuild/compilers/cuda.py meson-1.2.1/mesonbuild/compilers/cuda.py --- meson-1.0.1/mesonbuild/compilers/cuda.py 2023-02-01 21:43:18.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/cuda.py 2023-06-28 14:48:20.000000000 +0000 @@ -34,7 +34,7 @@ from ..dependencies import Dependency from ..environment import Environment # noqa: F401 from ..envconfig import MachineInfo - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice from ..programs import ExternalProgram @@ -557,7 +557,7 @@ mlog.debug(stde) mlog.debug('-----') if pc.returncode != 0: - raise EnvironmentException(f'Compiler {self.name_string()} can not compile programs.') + raise EnvironmentException(f'Compiler {self.name_string()} cannot compile programs.') # Run sanity check (if possible) if self.is_cross: @@ -749,7 +749,7 @@ return self._to_host_flags(self.host_compiler.get_std_exe_link_args(), _Phase.LINKER) def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], - libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]: + libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]: return ['-l' + libname] # FIXME def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: @@ -787,5 +787,5 @@ 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() + def get_assert_args(self, disable: bool) -> T.List[str]: + return self.host_compiler.get_assert_args(disable) diff -Nru meson-1.0.1/mesonbuild/compilers/d.py meson-1.2.1/mesonbuild/compilers/d.py --- meson-1.0.1/mesonbuild/compilers/d.py 2022-12-10 16:38:19.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/d.py 2023-08-07 22:54:34.000000000 +0000 @@ -43,7 +43,7 @@ from ..programs import ExternalProgram from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice CompilerMixinBase = Compiler @@ -559,7 +559,7 @@ 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()) + raise EnvironmentException('D compiler %s cannot 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 @@ -735,7 +735,7 @@ 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: + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]: if extra_args is None: extra_args = [] t = f''' @@ -745,17 +745,17 @@ writeln(({typename}).sizeof); }} ''' - res = self.run(t, env, extra_args=extra_args, - dependencies=dependencies) + res = self.cached_run(t, env, extra_args=extra_args, + dependencies=dependencies) if not res.compiled: - return -1 + return -1, False if res.returncode != 0: raise mesonlib.EnvironmentException('Could not run sizeof test binary.') - return int(res.stdout) + return int(res.stdout), res.cached 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: + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]: if extra_args is None: extra_args = [] t = f''' @@ -774,7 +774,7 @@ align = int(res.stdout) if align == 0: raise mesonlib.EnvironmentException(f'Could not determine alignment of {typename}. Sorry. You might want to file a bug.') - return align + return align, res.cached 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, @@ -855,8 +855,10 @@ return args return args + ['-shared-libphobos'] - def get_disable_assert_args(self) -> T.List[str]: - return ['-frelease'] + def get_assert_args(self, disable: bool) -> T.List[str]: + if disable: + return ['-frelease'] + return [] # LDC uses the DMD frontend code to parse and analyse the code. # It then uses LLVM for the binary code generation and optimizations. @@ -927,8 +929,10 @@ return args return args + ['-link-defaultlib-shared'] - def get_disable_assert_args(self) -> T.List[str]: - return ['--release'] + def get_assert_args(self, disable: bool) -> T.List[str]: + if disable: + return ['--release'] + return [] def rsp_file_syntax(self) -> RSPFileSyntax: # We use `mesonlib.is_windows` here because we want to know what the @@ -1015,8 +1019,10 @@ return args return args + ['-defaultlib=phobos2', '-debuglib=phobos2'] - def get_disable_assert_args(self) -> T.List[str]: - return ['-release'] + def get_assert_args(self, disable: bool) -> T.List[str]: + if disable: + return ['-release'] + return [] def rsp_file_syntax(self) -> RSPFileSyntax: return RSPFileSyntax.MSVC diff -Nru meson-1.0.1/mesonbuild/compilers/detect.py meson-1.2.1/mesonbuild/compilers/detect.py --- meson-1.0.1/mesonbuild/compilers/detect.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/detect.py 2023-07-21 20:36:13.000000000 +0000 @@ -15,7 +15,7 @@ from ..mesonlib import ( MesonException, EnvironmentException, MachineChoice, join_args, - search_version, is_windows, Popen_safe, windows_proof_rm, + search_version, is_windows, Popen_safe, Popen_safe_logged, windows_proof_rm, ) from ..envconfig import BinaryTable from .. import mlog @@ -36,7 +36,7 @@ from .cpp import CPPCompiler from .fortran import FortranCompiler from .rust import RustCompiler - from ..linkers import StaticLinker + from ..linkers.linkers import StaticLinker, DynamicLinker from ..environment import Environment from ..programs import ExternalProgram @@ -111,11 +111,15 @@ } 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]: +def detect_compiler_for(env: 'Environment', lang: str, for_machine: MachineChoice, skip_sanity_check: bool) -> 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) + if comp is None: + return comp + assert comp.for_machine == for_machine + env.coredata.process_new_compiler(lang, comp, env) + if not skip_sanity_check: + comp.sanity_check(env.get_scratch_dir(), env) + env.coredata.compilers[comp.for_machine][lang] = comp return comp @@ -189,6 +193,9 @@ trials = [['xilib']] elif is_windows() and compiler.id == 'pgi': # this handles cpp / nvidia HPC, in addition to just c/fortran trials = [['ar']] # For PGI on Windows, "ar" is just a wrapper calling link/lib. + elif is_windows() and compiler.id == 'nasm': + # This may well be LINK.EXE if it's under a MSVC environment + trials = [defaults['vs_static_linker'], defaults['clang_cl_static_linker']] + default_linkers else: trials = default_linkers popen_exceptions = {} @@ -202,7 +209,7 @@ else: arg = '--version' try: - p, out, err = Popen_safe(linker + [arg]) + p, out, err = Popen_safe_logged(linker + [arg], msg='Detecting linker via') except OSError as e: popen_exceptions[join_args(linker + [arg])] = e continue @@ -234,6 +241,11 @@ return linkers.TILinker(linker) if out.startswith('The CompCert'): return linkers.CompCertLinker(linker) + if out.strip().startswith('Metrowerks') or out.strip().startswith('Freescale'): + if 'ARM' in out: + return linkers.MetrowerksStaticLinkerARM(linker) + else: + return linkers.MetrowerksStaticLinkerEmbeddedPowerPC(linker) if p.returncode == 0: return linkers.ArLinker(compiler.for_machine, linker) if p.returncode == 1 and err.startswith('usage'): # OSX @@ -266,6 +278,7 @@ is_cross = env.is_cross_build(for_machine) info = env.machines[for_machine] cls: T.Union[T.Type[CCompiler], T.Type[CPPCompiler]] + lnk: T.Union[T.Type[StaticLinker], T.Type[DynamicLinker]] for compiler in compilers: if isinstance(compiler, str): @@ -314,12 +327,7 @@ cmd = compiler + [arg] try: - mlog.debug('-----') - mlog.debug(f'Detecting compiler via: {join_args(cmd)}') - p, out, err = Popen_safe(cmd) - mlog.debug(f'compiler returned {p}') - mlog.debug(f'compiler stdout:\n{out}') - mlog.debug(f'compiler stderr:\n{err}') + p, out, err = Popen_safe_logged(cmd, msg='Detecting compiler via') except OSError as e: popen_exceptions[join_args(cmd)] = e continue @@ -331,7 +339,7 @@ version = search_version(out) guess_gcc_or_lcc: T.Optional[str] = None - if 'Free Software Foundation' in out or 'xt-' in out: + if 'Free Software Foundation' in out or out.startswith('xt-'): guess_gcc_or_lcc = 'gcc' if 'e2k' in out and 'lcc' in out: guess_gcc_or_lcc = 'lcc' @@ -379,7 +387,7 @@ if 'Arm C/C++/Fortran Compiler' in out: arm_ver_match = re.search(r'version (\d+)\.(\d+)\.?(\d+)? \(build number (\d+)\)', out) - assert arm_ver_match is not None, 'for mypy' # because mypy *should* be complaning that this could be None + assert arm_ver_match is not None, 'for mypy' # because mypy *should* be complaining that this could be None version = '.'.join([x for x in arm_ver_match.groups() if x is not None]) if lang == 'c': cls = c.ArmLtdClangCCompiler @@ -526,7 +534,6 @@ ccache, compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=l) if 'TMS320C2000 C/C++' in out or 'MSP430 C/C++' in out or 'TI ARM C/C++ Compiler' in out: - lnk: T.Union[T.Type[linkers.C2000DynamicLinker], T.Type[linkers.TIDynamicLinker]] if 'TMS320C2000 C/C++' in out: cls = c.C2000CCompiler if lang == 'c' else cpp.C2000CPPCompiler lnk = linkers.C2000DynamicLinker @@ -539,7 +546,7 @@ return cls( ccache, compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) - if 'ARM' in out: + if 'ARM' in out and not ('Metrowerks' in out or 'Freescale' in out): cls = c.ArmCCompiler if lang == 'c' else cpp.ArmCPPCompiler env.coredata.add_lang_args(cls.language, cls, for_machine, env) linker = linkers.ArmDynamicLinker(for_machine, version=version) @@ -570,6 +577,36 @@ ccache, compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) + if 'Metrowerks C/C++' in out or 'Freescale C/C++' in out: + if 'ARM' in out: + cls = c.MetrowerksCCompilerARM if lang == 'c' else cpp.MetrowerksCPPCompilerARM + lnk = linkers.MetrowerksLinkerARM + else: + cls = c.MetrowerksCCompilerEmbeddedPowerPC if lang == 'c' else cpp.MetrowerksCPPCompilerEmbeddedPowerPC + lnk = linkers.MetrowerksLinkerEmbeddedPowerPC + + mwcc_ver_match = re.search(r'Version (\d+)\.(\d+)\.?(\d+)? build (\d+)', out) + assert mwcc_ver_match is not None, 'for mypy' # because mypy *should* be complaning that this could be None + compiler_version = '.'.join(x for x in mwcc_ver_match.groups() if x is not None) + + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + ld = env.lookup_binary_entry(for_machine, cls.language + '_ld') + + if ld is not None: + _, o_ld, _ = Popen_safe(ld + ['--version']) + + mwld_ver_match = re.search(r'Version (\d+)\.(\d+)\.?(\d+)? build (\d+)', o_ld) + assert mwld_ver_match is not None, 'for mypy' # because mypy *should* be complaning that this could be None + linker_version = '.'.join(x for x in mwld_ver_match.groups() if x is not None) + + linker = lnk(ld, for_machine, version=linker_version) + else: + raise EnvironmentException(f'Failed to detect linker for {cls.id!r} compiler. Please update your cross file(s).') + + return cls( + ccache, compiler, 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}') @@ -589,7 +626,7 @@ for compiler in compilers: arg = '--version' try: - p, out, err = Popen_safe(compiler + [arg]) + p, out, err = Popen_safe_logged(compiler + [arg], msg='Detecting compiler via') except OSError as e: popen_exceptions[join_args(compiler + [arg])] = e continue @@ -627,7 +664,7 @@ for compiler in compilers: for arg in ['--version', '-V']: try: - p, out, err = Popen_safe(compiler + [arg]) + p, out, err = Popen_safe_logged(compiler + [arg], msg='Detecting compiler via') except OSError as e: popen_exceptions[join_args(compiler + [arg])] = e continue @@ -664,7 +701,7 @@ if 'Arm C/C++/Fortran Compiler' in out: cls = fortran.ArmLtdFlangFortranCompiler arm_ver_match = re.search(r'version (\d+)\.(\d+)\.?(\d+)? \(build number (\d+)\)', out) - assert arm_ver_match is not None, 'for mypy' # because mypy *should* be complaning that this could be None + assert arm_ver_match is not None, 'for mypy' # because mypy *should* be complaining that this could be None version = '.'.join([x for x in arm_ver_match.groups() if x is not None]) linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( @@ -712,7 +749,7 @@ compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) - if 'ifx (IFORT)' in out: + if 'ifx (IFORT)' in out or 'ifx (IFX)' in out: cls = fortran.IntelLLVMFortranCompiler linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( @@ -790,7 +827,7 @@ for compiler in compilers: arg = ['--version'] try: - p, out, err = Popen_safe(compiler + arg) + p, out, err = Popen_safe_logged(compiler + arg, msg='Detecting compiler via') except OSError as e: popen_exceptions[join_args(compiler + arg)] = e continue @@ -840,7 +877,7 @@ exelist = [defaults['java'][0]] try: - p, out, err = Popen_safe(exelist + ['-version']) + p, out, err = Popen_safe_logged(exelist + ['-version'], msg='Detecting compiler via') except OSError: raise EnvironmentException('Could not execute Java compiler: {}'.format(join_args(exelist))) if 'javac' in out or 'javac' in err: @@ -861,7 +898,7 @@ info = env.machines[for_machine] for comp in compilers: try: - p, out, err = Popen_safe(comp + ['--version']) + p, out, err = Popen_safe_logged(comp + ['--version'], msg='Detecting compiler via') except OSError as e: popen_exceptions[join_args(comp + ['--version'])] = e continue @@ -890,13 +927,19 @@ popen_exceptions: T.Dict[str, Exception] = {} for comp in compilers: try: - err = Popen_safe(comp + ['-V'])[2] + _, out, err = Popen_safe_logged(comp + ['-V'], msg='Detecting compiler via') except OSError as e: popen_exceptions[join_args(comp + ['-V'])] = e continue - version = search_version(err) - if 'Cython' in err: + version: T.Optional[str] = None + # 3.0 + if 'Cython' in out: + version = search_version(out) + # older + elif 'Cython' in err: + version = search_version(err) + if version is not None: 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) @@ -913,7 +956,7 @@ exelist = [defaults['vala'][0]] try: - p, out = Popen_safe(exelist + ['--version'])[0:2] + p, out = Popen_safe_logged(exelist + ['--version'], msg='Detecting compiler via')[0:2] except OSError: raise EnvironmentException('Could not execute Vala compiler: {}'.format(join_args(exelist))) version = search_version(out) @@ -938,7 +981,7 @@ for compiler in compilers: arg = ['--version'] try: - out = Popen_safe(compiler + arg)[1] + out = Popen_safe_logged(compiler + arg, msg='Detecting compiler via')[1] except OSError as e: popen_exceptions[join_args(compiler + arg)] = e continue @@ -949,7 +992,18 @@ # 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' + # clippy returns its own version and not the rustc version by + # default so try harder here to get the correct version. + # Also replace the whole output with the rustc output in + # case this is later used for other purposes. + arg = ['--rustc', '--version'] + try: + out = Popen_safe(compiler + arg)[1] + except OSError as e: + popen_exceptions[join_args(compiler + arg)] = e + continue + version = search_version(out) + cls = rust.ClippyRustCompiler if 'rustc' in out: @@ -966,7 +1020,7 @@ 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 ' + 'or use the RUSTC_LD environment variable, otherwise meson ' 'will override your selection.') compiler = compiler.copy() # avoid mutating the original list @@ -1070,7 +1124,7 @@ if 'LLVM D compiler' in out: cls = d.LLVMDCompiler # LDC seems to require a file - # We cannot use NamedTemproraryFile on windows, its documented + # We cannot use NamedTemporaryFile 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') @@ -1108,7 +1162,7 @@ elif 'The D Language Foundation' in out or 'Digital Mars' in out: cls = d.DmdDCompiler # DMD seems to require a file - # We cannot use NamedTemproraryFile on windows, its documented + # We cannot use NamedTemporaryFile 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') @@ -1150,7 +1204,7 @@ exelist = [defaults['swift'][0]] try: - p, _, err = Popen_safe(exelist + ['-v']) + p, _, err = Popen_safe_logged(exelist + ['-v'], msg='Detecting compiler via') except OSError: raise EnvironmentException('Could not execute Swift compiler: {}'.format(join_args(exelist))) version = search_version(err) @@ -1167,7 +1221,7 @@ raise EnvironmentException('Unknown compiler: ' + join_args(exelist)) def detect_nasm_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: - from .asm import NasmCompiler, YasmCompiler + from .asm import NasmCompiler, YasmCompiler, MetrowerksAsmCompilerARM, MetrowerksAsmCompilerEmbeddedPowerPC compilers, _, _ = _get_compilers(env, 'nasm', for_machine) is_cross = env.is_cross_build(for_machine) @@ -1186,7 +1240,7 @@ default_path = os.path.join(os.environ['ProgramFiles'], 'NASM') comp[0] = shutil.which(comp[0], path=default_path) or comp[0] try: - output = Popen_safe(comp + ['--version'])[1] + output = Popen_safe_logged(comp + ['--version'], msg='Detecting compiler via')[1] except OSError as e: popen_exceptions[' '.join(comp + ['--version'])] = e continue @@ -1200,6 +1254,16 @@ comp_class = YasmCompiler env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) return comp_class([], comp, version, for_machine, info, cc.linker, is_cross=is_cross) + elif 'Metrowerks' in output or 'Freescale' in output: + if 'ARM' in output: + comp_class_mwasmarm = MetrowerksAsmCompilerARM + env.coredata.add_lang_args(comp_class_mwasmarm.language, comp_class_mwasmarm, for_machine, env) + return comp_class_mwasmarm([], comp, version, for_machine, info, cc.linker, is_cross=is_cross) + else: + comp_class_mwasmeppc = MetrowerksAsmCompilerEmbeddedPowerPC + env.coredata.add_lang_args(comp_class_mwasmeppc.language, comp_class_mwasmeppc, for_machine, env) + return comp_class_mwasmeppc([], comp, version, for_machine, info, cc.linker, is_cross=is_cross) + _handle_exceptions(popen_exceptions, compilers) raise EnvironmentException('Unreachable code (exception to make mypy happy)') diff -Nru meson-1.0.1/mesonbuild/compilers/fortran.py meson-1.2.1/mesonbuild/compilers/fortran.py --- meson-1.0.1/mesonbuild/compilers/fortran.py 2022-12-10 16:38:19.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/fortran.py 2023-08-07 22:54:34.000000000 +0000 @@ -40,7 +40,7 @@ from ..dependencies import Dependency from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice from ..programs import ExternalProgram from .compilers import CompileCheckMode @@ -117,9 +117,9 @@ return filename def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], - libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]: + libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]: code = 'stop; end program' - return self._find_library_impl(libname, env, extra_dirs, code, libtype) + return self._find_library_impl(libname, env, extra_dirs, code, libtype, lib_prefix_warning) 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') diff -Nru meson-1.0.1/mesonbuild/compilers/java.py meson-1.2.1/mesonbuild/compilers/java.py --- meson-1.0.1/mesonbuild/compilers/java.py 2022-12-10 16:38:19.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/java.py 2023-05-30 15:42:56.000000000 +0000 @@ -97,7 +97,7 @@ pc = subprocess.Popen(self.exelist + [src], cwd=work_dir) pc.wait() if pc.returncode != 0: - raise EnvironmentException(f'Java compiler {self.name_string()} can not compile programs.') + raise EnvironmentException(f'Java compiler {self.name_string()} cannot compile programs.') runner = shutil.which(self.javarunner) if runner: cmdlist = [runner, obj] diff -Nru meson-1.0.1/mesonbuild/compilers/mixins/arm.py meson-1.2.1/mesonbuild/compilers/mixins/arm.py --- meson-1.0.1/mesonbuild/compilers/mixins/arm.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/mixins/arm.py 2023-06-28 14:48:20.000000000 +0000 @@ -19,7 +19,7 @@ import typing as T from ... import mesonlib -from ...linkers import ArmClangDynamicLinker +from ...linkers.linkers import ArmClangDynamicLinker from ...mesonlib import OptionKey from ..compilers import clike_debug_args from .clang import clang_color_args @@ -90,6 +90,7 @@ 'everything': default_warn_args + []} # type: T.Dict[str, T.List[str]] # Assembly self.can_compile_suffixes.add('s') + self.can_compile_suffixes.add('sx') def get_pic_args(self) -> T.List[str]: # FIXME: Add /ropi, /rwpi, /fpic etc. qualifiers to --apcs @@ -161,6 +162,7 @@ 'b_ndebug', 'b_staticpic', 'b_colorout']} # Assembly self.can_compile_suffixes.add('s') + self.can_compile_suffixes.add('sx') def get_pic_args(self) -> T.List[str]: # PIC support is not enabled by default for ARM, diff -Nru meson-1.0.1/mesonbuild/compilers/mixins/clang.py meson-1.2.1/mesonbuild/compilers/mixins/clang.py --- meson-1.0.1/mesonbuild/compilers/mixins/clang.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/mixins/clang.py 2023-08-07 22:54:34.000000000 +0000 @@ -20,7 +20,7 @@ import typing as T from ... import mesonlib -from ...linkers import AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker, \ +from ...linkers.linkers import AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker, \ MoldDynamicLinker from ...mesonlib import OptionKey from ..compilers import CompileCheckMode diff -Nru meson-1.0.1/mesonbuild/compilers/mixins/clike.py meson-1.2.1/mesonbuild/compilers/mixins/clike.py --- meson-1.0.1/mesonbuild/compilers/mixins/clike.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/mixins/clike.py 2023-08-07 22:54:34.000000000 +0000 @@ -16,7 +16,7 @@ """Mixin classes to be shared between C and C++ compilers. -Without this we'll end up with awful diamond inherintance problems. The goal +Without this we'll end up with awful diamond inheritance problems. The goal of this is to have mixin's, which are classes that are designed *not* to be standalone, they only work through inheritance. """ @@ -35,7 +35,7 @@ from ... import arglist from ... import mesonlib from ... import mlog -from ...linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker +from ...linkers.linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker from ...mesonlib import LibType from ...coredata import OptionKey from .. import compilers @@ -327,7 +327,7 @@ mlog.debug(stde) mlog.debug('-----') if pc.returncode != 0: - raise mesonlib.EnvironmentException(f'Compiler {self.name_string()} can not compile programs.') + raise mesonlib.EnvironmentException(f'Compiler {self.name_string()} cannot compile programs.') # Run sanity check if self.is_cross: if self.exe_wrapper is None: @@ -432,7 +432,7 @@ 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 + # TODO: the caller should handle the listing of these arguments if extra_args is None: extra_args = [] else: @@ -498,8 +498,8 @@ 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} + t = f'''{prefix} + #include int main(void) {{ static int a[1-2*!({expression})]; a[0]=0; return 0; }}''' return self.compiles(t, env, extra_args=extra_args, dependencies=dependencies)[0] @@ -559,8 +559,8 @@ extra_args = [] if self.is_cross: return self.cross_compute_int(expression, low, high, guess, prefix, env, extra_args, dependencies) - t = f'''#include - {prefix} + t = f'''{prefix} + #include int main(void) {{ printf("%ld\\n", (long)({expression})); return 0; @@ -578,8 +578,8 @@ dependencies: T.Optional[T.List['Dependency']] = None) -> int: if extra_args is None: extra_args = [] - t = f'''#include - {prefix} + t = f'''{prefix} + #include int main(void) {{ {typename} something; return 0; @@ -591,33 +591,34 @@ 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: + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]: if extra_args is None: extra_args = [] if self.is_cross: - return self.cross_sizeof(typename, prefix, env, extra_args=extra_args, - dependencies=dependencies) - t = f'''#include - {prefix} + r = self.cross_sizeof(typename, prefix, env, extra_args=extra_args, + dependencies=dependencies) + return r, False + t = f'''{prefix} + #include int main(void) {{ printf("%ld\\n", (long)(sizeof({typename}))); return 0; }}''' - res = self.run(t, env, extra_args=extra_args, - dependencies=dependencies) + res = self.cached_run(t, env, extra_args=extra_args, + dependencies=dependencies) if not res.compiled: - return -1 + return -1, False if res.returncode != 0: raise mesonlib.EnvironmentException('Could not run sizeof test binary.') - return int(res.stdout) + return int(res.stdout), res.cached 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 = [] - t = f'''#include - {prefix} + t = f'''{prefix} + #include int main(void) {{ {typename} something; return 0; @@ -625,8 +626,8 @@ if not self.compiles(t, env, extra_args=extra_args, dependencies=dependencies)[0]: return -1 - t = f'''#include - {prefix} + t = f'''{prefix} + #include struct tmp {{ char c; {typename} target; @@ -635,15 +636,16 @@ 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: + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]: if extra_args is None: extra_args = [] if self.is_cross: - return self.cross_alignment(typename, prefix, env, extra_args=extra_args, - dependencies=dependencies) - t = f'''#include + r = self.cross_alignment(typename, prefix, env, extra_args=extra_args, + dependencies=dependencies) + return r, False + t = f'''{prefix} + #include #include - {prefix} struct tmp {{ char c; {typename} target; @@ -652,8 +654,8 @@ printf("%d", (int)offsetof(struct tmp, target)); return 0; }}''' - res = self.run(t, env, extra_args=extra_args, - dependencies=dependencies) + res = self.cached_run(t, env, extra_args=extra_args, + dependencies=dependencies) if not res.compiled: raise mesonlib.EnvironmentException('Could not compile alignment test.') if res.returncode != 0: @@ -661,7 +663,7 @@ align = int(res.stdout) if align == 0: raise mesonlib.EnvironmentException(f'Could not determine alignment of {typename}. Sorry. You might want to file a bug.') - return align + return align, res.cached def get_define(self, dname: str, prefix: str, env: 'Environment', extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], @@ -686,7 +688,7 @@ # Get the preprocessed value after the delimiter, # minus the extra newline at the end and # merge string literals. - return self._concatenate_string_literals(p.stdout.split(delim + '\n')[-1][:-1]), cached + return self._concatenate_string_literals(p.stdout.split(delim + '\n')[-1][:-1]).strip(), cached def get_return_value(self, fname: str, rtype: str, prefix: str, env: 'Environment', extra_args: T.Optional[T.List[str]], @@ -1117,9 +1119,9 @@ ''' returns true if the output produced is 64-bit, false if 32-bit ''' - return self.sizeof('void *', '', env) == 8 + return self.sizeof('void *', '', env)[0] == 8 - def _find_library_real(self, libname: str, env: 'Environment', extra_dirs: T.List[str], code: str, libtype: LibType) -> T.Optional[T.List[str]]: + def _find_library_real(self, libname: str, env: 'Environment', extra_dirs: T.List[str], code: str, libtype: LibType, lib_prefix_warning: bool) -> 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. @@ -1158,13 +1160,13 @@ trial = self._get_file_from_list(env, trials) if not trial: continue - if libname.startswith('lib') and trial.name.startswith(libname): + if libname.startswith('lib') and trial.name.startswith(libname) and lib_prefix_warning: mlog.warning(f'find_library({libname!r}) starting in "lib" only works by accident and is not portable') return [trial.as_posix()] return None def _find_library_impl(self, libname: str, env: 'Environment', extra_dirs: T.List[str], - code: str, libtype: LibType) -> T.Optional[T.List[str]]: + code: str, libtype: LibType, lib_prefix_warning: bool) -> T.Optional[T.List[str]]: # These libraries are either built-in or invalid if libname in self.ignore_libs: return [] @@ -1172,7 +1174,7 @@ 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, lib_prefix_warning) self.find_library_cache[key] = value else: value = self.find_library_cache[key] @@ -1181,9 +1183,9 @@ return value.copy() def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], - libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]: + libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]: code = 'int main(void) { return 0; }\n' - return self._find_library_impl(libname, env, extra_dirs, code, libtype) + return self._find_library_impl(libname, env, extra_dirs, code, libtype, lib_prefix_warning) def find_framework_paths(self, env: 'Environment') -> T.List[str]: ''' @@ -1330,8 +1332,10 @@ 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'] + def get_assert_args(self, disable: bool) -> T.List[str]: + if disable: + return ['-DNDEBUG'] + return [] @functools.lru_cache(maxsize=None) def can_compile(self, src: 'mesonlib.FileOrString') -> bool: diff -Nru meson-1.0.1/mesonbuild/compilers/mixins/compcert.py meson-1.2.1/mesonbuild/compilers/mixins/compcert.py --- meson-1.0.1/mesonbuild/compilers/mixins/compcert.py 2022-12-10 16:38:19.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/mixins/compcert.py 2023-08-07 22:54:34.000000000 +0000 @@ -68,6 +68,7 @@ def __init__(self) -> None: # Assembly self.can_compile_suffixes.add('s') + self.can_compile_suffixes.add('sx') default_warn_args = [] # type: T.List[str] self.warn_args = {'0': [], '1': default_warn_args, diff -Nru meson-1.0.1/mesonbuild/compilers/mixins/emscripten.py meson-1.2.1/mesonbuild/compilers/mixins/emscripten.py --- meson-1.0.1/mesonbuild/compilers/mixins/emscripten.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/mixins/emscripten.py 2023-08-07 22:54:34.000000000 +0000 @@ -86,9 +86,9 @@ 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]]: + libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]: if not libname.endswith('.js'): - return super().find_library(libname, env, extra_dirs, libtype) + return super().find_library(libname, env, extra_dirs, libtype, lib_prefix_warning) if os.path.isabs(libname): if os.path.exists(libname): return [libname] diff -Nru meson-1.0.1/mesonbuild/compilers/mixins/gnu.py meson-1.2.1/mesonbuild/compilers/mixins/gnu.py --- meson-1.0.1/mesonbuild/compilers/mixins/gnu.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/mixins/gnu.py 2023-08-07 22:54:34.000000000 +0000 @@ -196,11 +196,13 @@ "-Wduplicated-branches", ], "8.1.0": [ - "-Wattribute-alias=2", "-Wcast-align=strict", "-Wsuggest-attribute=cold", "-Wsuggest-attribute=malloc", ], + "9.1.0": [ + "-Wattribute-alias=2", + ], "10.1.0": [ "-Wanalyzer-too-complex", "-Warith-conversion", @@ -325,18 +327,18 @@ ], } # type: T.Dict[str, T.List[str]] +_LANG_MAP = { + 'c': 'c', + 'cpp': 'c++', + 'objc': 'objective-c', + 'objcpp': 'objective-c++' +} @functools.lru_cache(maxsize=None) def gnulike_default_include_dirs(compiler: T.Tuple[str, ...], lang: str) -> 'ImmutableListProtocol[str]': - lang_map = { - 'c': 'c', - 'cpp': 'c++', - 'objc': 'objective-c', - 'objcpp': 'objective-c++' - } - if lang not in lang_map: + if lang not in _LANG_MAP: return [] - lang = lang_map[lang] + lang = _LANG_MAP[lang] env = os.environ.copy() env["LC_ALL"] = 'C' cmd = list(compiler) + [f'-x{lang}', '-E', '-v', '-'] @@ -387,6 +389,7 @@ self.base_options.add(OptionKey('b_sanitize')) # All GCC-like backends can do assembly self.can_compile_suffixes.add('s') + self.can_compile_suffixes.add('sx') def get_pic_args(self) -> T.List[str]: if self.info.is_windows() or self.info.is_cygwin() or self.info.is_darwin(): @@ -555,7 +558,8 @@ # We want to allow preprocessing files with any extension, such as # foo.c.in. In that case we need to tell GCC/CLANG to treat them as # assembly file. - return self.get_preprocess_only_args() + ['-x', 'assembler-with-cpp'] + lang = _LANG_MAP.get(self.language, 'assembler-with-cpp') + return self.get_preprocess_only_args() + [f'-x{lang}'] class GnuCompiler(GnuLikeCompiler): diff -Nru meson-1.0.1/mesonbuild/compilers/mixins/metrowerks.py meson-1.2.1/mesonbuild/compilers/mixins/metrowerks.py --- meson-1.0.1/mesonbuild/compilers/mixins/metrowerks.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/mixins/metrowerks.py 2023-08-07 22:54:34.000000000 +0000 @@ -0,0 +1,300 @@ +# 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. +from __future__ import annotations + +"""Representations specific to the Metrowerks/Freescale Embedded C/C++ compiler family.""" + +import os +import typing as T + +from ...mesonlib import EnvironmentException, OptionKey + +if T.TYPE_CHECKING: + from ...envconfig import MachineInfo + from ...compilers.compilers import Compiler, CompileCheckMode +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 + +mwcc_buildtype_args = { + 'plain': [], + 'debug': ['-g'], + 'debugoptimized': ['-g', '-O4'], + 'release': ['-O4,p'], + 'minsize': ['-Os'], + 'custom': [], +} # type: T.Dict[str, T.List[str]] + +mwccarm_instruction_set_args = { + 'generic': ['-proc', 'generic'], + 'v4': ['-proc', 'v4'], + 'v4t': ['-proc', 'v4t'], + 'v5t': ['-proc', 'v5t'], + 'v5te': ['-proc', 'v5te'], + 'v6': ['-proc', 'v6'], + 'arm7tdmi': ['-proc', 'arm7tdmi'], + 'arm710t': ['-proc', 'arm710t'], + 'arm720t': ['-proc', 'arm720t'], + 'arm740t': ['-proc', 'arm740t'], + 'arm7ej': ['-proc', 'arm7ej'], + 'arm9tdmi': ['-proc', 'arm9tdmi'], + 'arm920t': ['-proc', 'arm920t'], + 'arm922t': ['-proc', 'arm922t'], + 'arm940t': ['-proc', 'arm940t'], + 'arm9ej': ['-proc', 'arm9ej'], + 'arm926ej': ['-proc', 'arm926ej'], + 'arm946e': ['-proc', 'arm946e'], + 'arm966e': ['-proc', 'arm966e'], + 'arm1020e': ['-proc', 'arm1020e'], + 'arm1022e': ['-proc', 'arm1022e'], + 'arm1026ej': ['-proc', 'arm1026ej'], + 'dbmx1': ['-proc', 'dbmx1'], + 'dbmxl': ['-proc', 'dbmxl'], + 'XScale': ['-proc', 'XScale'], + 'pxa255': ['-proc', 'pxa255'], + 'pxa261': ['-proc', 'pxa261'], + 'pxa262': ['-proc', 'pxa262'], + 'pxa263': ['-proc', 'pxa263'] +} # type: T.Dict[str, T.List[str]] + +mwcceppc_instruction_set_args = { + 'generic': ['-proc', 'generic'], + '401': ['-proc', '401'], + '403': ['-proc', '403'], + '505': ['-proc', '505'], + '509': ['-proc', '509'], + '555': ['-proc', '555'], + '601': ['-proc', '601'], + '602': ['-proc', '602'], + '603': ['-proc', '603'], + '603e': ['-proc', '603e'], + '604': ['-proc', '604'], + '604e': ['-proc', '604e'], + '740': ['-proc', '740'], + '750': ['-proc', '750'], + '801': ['-proc', '801'], + '821': ['-proc', '821'], + '823': ['-proc', '823'], + '850': ['-proc', '850'], + '860': ['-proc', '860'], + '7400': ['-proc', '7400'], + '7450': ['-proc', '7450'], + '8240': ['-proc', '8240'], + '8260': ['-proc', '8260'], + 'e500': ['-proc', 'e500'], + 'gekko': ['-proc', 'gekko'], +} # type: T.Dict[str, T.List[str]] + +mwasmarm_instruction_set_args = { + 'arm4': ['-proc', 'arm4'], + 'arm4t': ['-proc', 'arm4t'], + 'arm4xm': ['-proc', 'arm4xm'], + 'arm4txm': ['-proc', 'arm4txm'], + 'arm5': ['-proc', 'arm5'], + 'arm5T': ['-proc', 'arm5T'], + 'arm5xM': ['-proc', 'arm5xM'], + 'arm5TxM': ['-proc', 'arm5TxM'], + 'arm5TE': ['-proc', 'arm5TE'], + 'arm5TExP': ['-proc', 'arm5TExP'], + 'arm6': ['-proc', 'arm6'], + 'xscale': ['-proc', 'xscale'] +} # type: T.Dict[str, T.List[str]] + +mwasmeppc_instruction_set_args = { + '401': ['-proc', '401'], + '403': ['-proc', '403'], + '505': ['-proc', '505'], + '509': ['-proc', '509'], + '555': ['-proc', '555'], + '56X': ['-proc', '56X'], + '601': ['-proc', '601'], + '602': ['-proc', '602'], + '603': ['-proc', '603'], + '603e': ['-proc', '603e'], + '604': ['-proc', '604'], + '604e': ['-proc', '604e'], + '740': ['-proc', '740'], + '74X': ['-proc', '74X'], + '750': ['-proc', '750'], + '75X': ['-proc', '75X'], + '801': ['-proc', '801'], + '821': ['-proc', '821'], + '823': ['-proc', '823'], + '850': ['-proc', '850'], + '85X': ['-proc', '85X'], + '860': ['-proc', '860'], + '86X': ['-proc', '86X'], + '87X': ['-proc', '87X'], + '88X': ['-proc', '88X'], + '5100': ['-proc', '5100'], + '5200': ['-proc', '5200'], + '7400': ['-proc', '7400'], + '744X': ['-proc', '744X'], + '7450': ['-proc', '7450'], + '745X': ['-proc', '745X'], + '82XX': ['-proc', '82XX'], + '8240': ['-proc', '8240'], + '824X': ['-proc', '824X'], + '8260': ['-proc', '8260'], + '827X': ['-proc', '827X'], + '8280': ['-proc', '8280'], + 'e300': ['-proc', 'e300'], + 'e300c2': ['-proc', 'e300c2'], + 'e300c3': ['-proc', 'e300c3'], + 'e300c4': ['-proc', 'e300c4'], + 'e600': ['-proc', 'e600'], + '85xx': ['-proc', '85xx'], + 'e500': ['-proc', 'e500'], + 'e500v2': ['-proc', 'e500v2'], + 'Zen': ['-proc', 'Zen'], + '5565': ['-proc', '5565'], + '5674': ['-proc', '5674'], + 'gekko': ['-proc', 'gekko'], + 'generic': ['-proc', 'generic'], +} # type: T.Dict[str, T.List[str]] + +mwcc_optimization_args = { + 'plain': [], + '0': ['-O0'], + 'g': ['-Op'], + '1': ['-O1'], + '2': ['-O2'], + '3': ['-O3'], + 's': ['-Os'] +} # type: T.Dict[str, T.List[str]] + +mwcc_debug_args = { + False: [], + True: ['-g'] +} # type: T.Dict[bool, T.List[str]] + + +class MetrowerksCompiler(Compiler): + id = 'mwcc' + + # These compilers can actually invoke the linker, but they choke on + # linker-specific flags. So it's best to invoke the linker directly + INVOKES_LINKER = False + + def __init__(self) -> None: + if not self.is_cross: + raise EnvironmentException(f'{id} supports only cross-compilation.') + + self.base_options = { + OptionKey(o) for o in ['b_pch', 'b_ndebug']} + + default_warn_args = [] # type: T.List[str] + self.warn_args = {'0': ['-w', 'off'], + '1': default_warn_args, + '2': default_warn_args + ['-w', 'most'], + '3': default_warn_args + ['-w', 'all'], + 'everything': default_warn_args + ['-w', 'full']} # type: T.Dict[str, T.List[str]] + + def depfile_for_object(self, objfile: str) -> T.Optional[str]: + # Earlier versions of these compilers do not support specifying + # a custom name for a depfile, and can only generate '.d' + return os.path.splitext(objfile)[0] + '.' + self.get_depfile_suffix() + + def get_always_args(self) -> T.List[str]: + return ['-gccinc'] + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + return mwcc_buildtype_args[buildtype] + + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + return [] + + def get_compile_only_args(self) -> T.List[str]: + return ['-c'] + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + return mwcc_debug_args[is_debug] + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + # Check comment in depfile_for_object() + return ['-gccdep', '-MD'] + + def get_depfile_suffix(self) -> str: + return 'd' + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if not path: + path = '.' + return ['-I' + path] + + def get_no_optimization_args(self) -> T.List[str]: + return ['-opt', 'off'] + + 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 mwcc_optimization_args[optimization_level] + + def get_output_args(self, target: str) -> T.List[str]: + return ['-o', target] + + def get_pic_args(self) -> T.List[str]: + return ['-pic'] + + def get_preprocess_only_args(self) -> T.List[str]: + return ['-E'] + + def get_preprocess_to_file_args(self) -> T.List[str]: + return ['-P'] + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + return ['-prefix', self.get_pch_name(header)] + + def get_pch_name(self, name: str) -> str: + return os.path.basename(name) + '.' + self.get_pch_suffix() + + def get_pch_suffix(self) -> str: + return 'mch' + + def get_warn_args(self, level: str) -> T.List[str]: + return self.warn_args[level] + + def get_werror_args(self) -> T.List[str]: + return ['-w', 'error'] + + @classmethod + def _unix_args_to_native(cls, args: T.List[str], info: MachineInfo) -> 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[:2] == '-I': + parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:])) + + return parameter_list diff -Nru meson-1.0.1/mesonbuild/compilers/mixins/visualstudio.py meson-1.2.1/mesonbuild/compilers/mixins/visualstudio.py --- meson-1.0.1/mesonbuild/compilers/mixins/visualstudio.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/mixins/visualstudio.py 2023-08-07 22:54:34.000000000 +0000 @@ -213,7 +213,7 @@ return ['/DEF:' + defsfile] def gen_pch_args(self, header: str, source: str, pchname: str) -> T.Tuple[str, T.List[str]]: - objname = os.path.splitext(pchname)[0] + '.obj' + objname = os.path.splitext(source)[0] + '.obj' return objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname] def openmp_flags(self) -> T.List[str]: @@ -423,7 +423,7 @@ def __init__(self, target: str): super().__init__(target) - # Visual Studio 2013 and erlier don't support the /utf-8 argument. + # Visual Studio 2013 and earlier don't support the /utf-8 argument. # We want to remove it. We also want to make an explicit copy so we # don't mutate class constant state if mesonlib.version_compare(self.version, '<19.00') and '/utf-8' in self.always_args: @@ -450,7 +450,7 @@ 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. + # and they cannot be called. return None return super().get_instruction_set_args(instruction_set) @@ -469,6 +469,7 @@ # Assembly self.can_compile_suffixes.add('s') + self.can_compile_suffixes.add('sx') def has_arguments(self, args: T.List[str], env: 'Environment', code: str, mode: str) -> T.Tuple[bool, bool]: if mode != 'link': diff -Nru meson-1.0.1/mesonbuild/compilers/mixins/xc16.py meson-1.2.1/mesonbuild/compilers/mixins/xc16.py --- meson-1.0.1/mesonbuild/compilers/mixins/xc16.py 2022-12-10 16:38:19.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/mixins/xc16.py 2023-05-23 15:20:02.000000000 +0000 @@ -65,6 +65,7 @@ raise EnvironmentException('xc16 supports only cross-compilation.') # Assembly self.can_compile_suffixes.add('s') + self.can_compile_suffixes.add('sx') default_warn_args = [] # type: T.List[str] self.warn_args = {'0': [], '1': default_warn_args, diff -Nru meson-1.0.1/mesonbuild/compilers/objc.py meson-1.2.1/mesonbuild/compilers/objc.py --- meson-1.0.1/mesonbuild/compilers/objc.py 2022-12-10 16:38:19.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/objc.py 2023-06-28 14:48:20.000000000 +0000 @@ -27,7 +27,7 @@ from ..programs import ExternalProgram from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice diff -Nru meson-1.0.1/mesonbuild/compilers/objcpp.py meson-1.2.1/mesonbuild/compilers/objcpp.py --- meson-1.0.1/mesonbuild/compilers/objcpp.py 2022-12-10 16:38:19.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/objcpp.py 2023-06-28 14:48:20.000000000 +0000 @@ -27,7 +27,7 @@ from ..programs import ExternalProgram from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice class ObjCPPCompiler(CLikeCompiler, Compiler): diff -Nru meson-1.0.1/mesonbuild/compilers/rust.py meson-1.2.1/mesonbuild/compilers/rust.py --- meson-1.0.1/mesonbuild/compilers/rust.py 2022-11-01 19:00:11.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/rust.py 2023-07-21 20:36:13.000000000 +0000 @@ -15,19 +15,21 @@ import subprocess, os.path import textwrap +import re import typing as T -from .. import coredata -from ..mesonlib import EnvironmentException, MesonException, Popen_safe, OptionKey +from .. import coredata, mlog +from ..mesonlib import EnvironmentException, MesonException, Popen_safe, OptionKey, join_args from .compilers import Compiler, rust_buildtype_args, clike_debug_args if T.TYPE_CHECKING: from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType from ..envconfig import MachineInfo from ..environment import Environment # noqa: F401 - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice from ..programs import ExternalProgram + from ..dependencies import Dependency rust_optimization_args = { @@ -62,9 +64,10 @@ is_cross=is_cross, full_version=full_version, linker=linker) self.exe_wrapper = exe_wrapper - self.base_options.add(OptionKey('b_colorout')) + self.base_options.update({OptionKey(o) for o in ['b_colorout', 'b_ndebug']}) if 'link' in self.linker.id: self.base_options.add(OptionKey('b_vscrt')) + self.native_static_libs: T.List[str] = [] def needs_static_linker(self) -> bool: return False @@ -77,20 +80,17 @@ '''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() - assert isinstance(_stdo, bytes) - assert isinstance(_stde, bytes) - stdo = _stdo.decode('utf-8', errors='replace') - stde = _stde.decode('utf-8', errors='replace') + + cmdlist = self.exelist + ['-o', output_name, source_name] + pc, stdo, stde = Popen_safe(cmdlist, cwd=work_dir) + mlog.debug('Sanity check compiler command line:', join_args(cmdlist)) + mlog.debug('Sanity check compile stdout:') + mlog.debug(stdo) + mlog.debug('-----\nSanity check compile stderr:') + mlog.debug(stde) + mlog.debug('-----') if pc.returncode != 0: - raise EnvironmentException('Rust compiler {} can not compile programs.\n{}\n{}'.format( - self.name_string(), - stdo, - stde)) + raise EnvironmentException(f'Rust compiler {self.name_string()} cannot compile programs.') if self.is_cross: if self.exe_wrapper is None: # Can't check if the binaries run so we have to assume they do @@ -101,7 +101,19 @@ pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) pe.wait() if pe.returncode != 0: - raise EnvironmentException('Executables created by Rust compiler %s are not runnable.' % self.name_string()) + raise EnvironmentException(f'Executables created by Rust compiler {self.name_string()} are not runnable.') + # Get libraries needed to link with a Rust staticlib + cmdlist = self.exelist + ['--crate-type', 'staticlib', '--print', 'native-static-libs', source_name] + p, stdo, stde = Popen_safe(cmdlist, cwd=work_dir) + if p.returncode == 0: + match = re.search('native-static-libs: (.*)$', stde, re.MULTILINE) + if match: + # Exclude some well known libraries that we don't need because they + # are always part of C/C++ linkers. Rustc probably should not print + # them, pkg-config for example never specify them. + # FIXME: https://github.com/rust-lang/rust/issues/55120 + exclude = {'-lc', '-lgcc_s', '-lkernel32', '-ladvapi32'} + self.native_static_libs = [i for i in match.group(1).split() if i not in exclude] def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: return ['--dep-info', outfile] @@ -153,6 +165,12 @@ ), } + def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]: + # Rust doesn't have dependency compile arguments so simply return + # nothing here. Dependencies are linked and all required metadata is + # provided by the linker flags. + return [] + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] key = OptionKey('std', machine=self.for_machine, lang=self.language) @@ -189,14 +207,18 @@ return self._WARNING_LEVELS["0"] def get_pic_args(self) -> T.List[str]: - # This defaults to - return ['-C', 'relocation-model=pic'] + # relocation-model=pic is rustc's default already. + return [] 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 [] + def get_assert_args(self, disable: bool) -> T.List[str]: + action = "no" if disable else "yes" + return ['-C', f'debug-assertions={action}', '-C', 'overflow-checks=no'] + class ClippyRustCompiler(RustCompiler): diff -Nru meson-1.0.1/mesonbuild/compilers/swift.py meson-1.2.1/mesonbuild/compilers/swift.py --- meson-1.0.1/mesonbuild/compilers/swift.py 2022-11-01 19:00:11.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/swift.py 2023-06-28 14:48:20.000000000 +0000 @@ -23,7 +23,7 @@ if T.TYPE_CHECKING: from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice swift_optimization_args = { @@ -116,7 +116,7 @@ pc = subprocess.Popen(self.exelist + extra_flags + ['-emit-executable', '-o', output_name, src], cwd=work_dir) pc.wait() if pc.returncode != 0: - raise EnvironmentException('Swift compiler %s can not compile programs.' % self.name_string()) + raise EnvironmentException('Swift compiler %s cannot compile programs.' % self.name_string()) if self.is_cross: # Can't check if the binaries run so we have to assume they do return diff -Nru meson-1.0.1/mesonbuild/compilers/vala.py meson-1.2.1/mesonbuild/compilers/vala.py --- meson-1.0.1/mesonbuild/compilers/vala.py 2022-11-01 19:00:11.000000000 +0000 +++ meson-1.2.1/mesonbuild/compilers/vala.py 2023-08-07 22:54:34.000000000 +0000 @@ -102,7 +102,7 @@ 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 = f'Vala compiler {self.name_string()!r} can not compile programs' + msg = f'Vala compiler {self.name_string()!r} cannot compile programs' raise EnvironmentException(msg) def get_buildtype_args(self, buildtype: str) -> T.List[str]: @@ -111,7 +111,7 @@ return [] def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], - libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]: + libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> 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 diff -Nru meson-1.0.1/mesonbuild/coredata.py meson-1.2.1/mesonbuild/coredata.py --- meson-1.0.1/mesonbuild/coredata.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/coredata.py 2023-08-07 22:54:34.000000000 +0000 @@ -1,5 +1,4 @@ -# Copyright 2012-2022 The Meson development team - +# Copyright 2013-2023 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 @@ -13,6 +12,8 @@ # limitations under the License. from __future__ import annotations +import copy + from . import mlog, mparser import pickle, os, uuid import sys @@ -26,7 +27,7 @@ default_prefix, default_datadir, default_includedir, default_infodir, default_localedir, default_mandir, default_sbindir, default_sysconfdir, split_args, OptionKey, OptionType, stringlistify, - pickle_load, replace_if_different + pickle_load ) from .wrap import WrapMode import ast @@ -38,7 +39,7 @@ if T.TYPE_CHECKING: from . import dependencies - from .compilers.compilers import Compiler, CompileResult + from .compilers.compilers import Compiler, CompileResult, RunResult from .dependencies.detect import TV_DepID from .environment import Environment from .mesonlib import OptionOverrideProxy, FileOrString @@ -48,6 +49,8 @@ MutableKeyedOptionDictType = T.Dict['OptionKey', 'UserOption[T.Any]'] KeyedOptionDictType = T.Union[MutableKeyedOptionDictType, OptionOverrideProxy] CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, FileOrString, T.Tuple[str, ...], str] + # code, args + RunCheckCacheKey = T.Tuple[str, T.Tuple[str, ...]] # typeshed StrOrBytesPath = T.Union[str, bytes, os.PathLike[str], os.PathLike[bytes]] @@ -56,16 +59,34 @@ # # Pip requires that RCs are named like this: '0.1.0.rc1' # But the corresponding Git tag needs to be '0.1.0rc1' -version = '1.0.1' +version = '1.2.1' -backendlist = ['ninja', 'vs', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'vs2017', 'vs2019', 'vs2022', 'xcode'] +# The next stable version when we are in dev. This is used to allow projects to +# require meson version >=1.2.0 when using 1.1.99. FeatureNew won't warn when +# using a feature introduced in 1.2.0 when using Meson 1.1.99. +stable_version = version +if stable_version.endswith('.99'): + stable_version_array = stable_version.split('.') + stable_version_array[-1] = '0' + stable_version_array[-2] = str(int(stable_version_array[-2]) + 1) + stable_version = '.'.join(stable_version_array) + +backendlist = ['ninja', 'vs', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'vs2017', 'vs2019', 'vs2022', 'xcode', 'none'] +genvslitelist = ['vs2022'] +buildtypelist = ['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom'] -default_yielding = False +DEFAULT_YIELDING = False # Can't bind this near the class method it seems, sadly. _T = T.TypeVar('_T') +def get_genvs_default_buildtype_list() -> list: + # just debug, debugoptimized, and release for now + # but this should probably be configurable through some extra option, alongside --genvslite. + return buildtypelist[1:-2] + + class MesonVersionMismatchException(MesonException): '''Build directory generated with Meson version is incompatible with current version''' def __init__(self, old_version: str, current_version: str) -> None: @@ -76,16 +97,17 @@ class UserOption(T.Generic[_T], HoldableObject): - def __init__(self, description: str, choices: T.Optional[T.Union[str, T.List[_T]]], yielding: T.Optional[bool]): + def __init__(self, description: str, choices: T.Optional[T.Union[str, T.List[_T]]], + yielding: bool, + deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): super().__init__() self.choices = choices self.description = description - if yielding is None: - yielding = default_yielding if not isinstance(yielding, bool): raise MesonException('Value of "yielding" must be a boolean.') self.yielding = yielding - self.deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False + self.deprecated = deprecated + self.readonly = False def listify(self, value: T.Any) -> T.List[T.Any]: return [value] @@ -100,12 +122,15 @@ def validate_value(self, value: T.Any) -> _T: raise RuntimeError('Derived option class did not override validate_value.') - def set_value(self, newvalue: T.Any) -> None: + def set_value(self, newvalue: T.Any) -> bool: + oldvalue = getattr(self, 'value', None) self.value = self.validate_value(newvalue) + return self.value != oldvalue class UserStringOption(UserOption[str]): - def __init__(self, description: str, value: T.Any, yielding: T.Optional[bool] = None): - super().__init__(description, None, yielding) + def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, + deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): + super().__init__(description, None, yielding, deprecated) self.set_value(value) def validate_value(self, value: T.Any) -> str: @@ -114,8 +139,9 @@ return value class UserBooleanOption(UserOption[bool]): - def __init__(self, description: str, value, yielding: T.Optional[bool] = None) -> None: - super().__init__(description, [True, False], yielding) + def __init__(self, description: str, value, yielding: bool = DEFAULT_YIELDING, + deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): + super().__init__(description, [True, False], yielding, deprecated) self.set_value(value) def __bool__(self) -> bool: @@ -133,7 +159,8 @@ raise MesonException('Value %s is not boolean (true or false).' % value) class UserIntegerOption(UserOption[int]): - def __init__(self, description: str, value: T.Any, yielding: T.Optional[bool] = None): + def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, + deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): min_value, max_value, default_value = value self.min_value = min_value self.max_value = max_value @@ -143,7 +170,7 @@ if max_value is not None: c.append('<=' + str(max_value)) choices = ', '.join(c) - super().__init__(description, choices, yielding) + super().__init__(description, choices, yielding, deprecated) self.set_value(default_value) def validate_value(self, value: T.Any) -> int: @@ -171,8 +198,9 @@ 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) + def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, + deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): + super().__init__(description, (0, 0o777, value), yielding, deprecated) self.choices = ['preserve', '0000-0777'] def printable_value(self) -> str: @@ -181,7 +209,7 @@ return format(self.value, '04o') def validate_value(self, value: T.Any) -> T.Union[str, OctalInt]: - if value is None or value == 'preserve': + if value == 'preserve': return 'preserve' return OctalInt(super().validate_value(value)) @@ -192,8 +220,10 @@ raise MesonException(f'Invalid mode: {e}') class UserComboOption(UserOption[str]): - def __init__(self, description: str, choices: T.List[str], value: T.Any, yielding: T.Optional[bool] = None): - super().__init__(description, choices, yielding) + def __init__(self, description: str, choices: T.List[str], value: T.Any, + yielding: bool = DEFAULT_YIELDING, + deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): + super().__init__(description, choices, yielding, deprecated) if not isinstance(self.choices, list): raise MesonException('Combo choices must be an array.') for i in self.choices: @@ -216,8 +246,12 @@ return value class UserArrayOption(UserOption[T.List[str]]): - 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)) + def __init__(self, description: str, value: T.Union[str, T.List[str]], + split_args: bool = False, user_input: bool = False, + allow_dups: bool = False, yielding: bool = DEFAULT_YIELDING, + choices: T.Optional[T.List[str]] = None, + deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): + super().__init__(description, choices if choices is not None else [], yielding, deprecated) self.split_args = split_args self.allow_dups = allow_dups self.value = self.validate_value(value, user_input=user_input) @@ -275,8 +309,9 @@ class UserFeatureOption(UserComboOption): static_choices = ['enabled', 'disabled', 'auto'] - def __init__(self, description: str, value: T.Any, yielding: T.Optional[bool] = None): - super().__init__(description, self.static_choices, value, yielding) + def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, + deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): + super().__init__(description, self.static_choices, value, yielding, deprecated) self.name: T.Optional[str] = None # TODO: Refactor options to all store their name def is_enabled(self) -> bool: @@ -297,11 +332,10 @@ @classmethod def from_type(cls, dep: 'dependencies.Dependency') -> 'DependencyCacheType': - from . import dependencies # As more types gain search overrides they'll need to be added here - if isinstance(dep, dependencies.PkgConfigDependency): + if dep.type_name == 'pkgconfig': return cls.PKG_CONFIG - if isinstance(dep, dependencies.CMakeDependency): + if dep.type_name == 'cmake': return cls.CMAKE return cls.OTHER @@ -455,13 +489,14 @@ # want to overwrite options for such subprojects. self.initialized_subprojects: T.Set[str] = set() - # For host == build configuraitons these caches should be the same. + # For host == build configurations 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() + self.run_check_cache: T.Dict['RunCheckCacheKey', 'RunResult'] = OrderedDict() # CMake cache self.cmake_cache: PerMachine[CMakeStateCache] = PerMachine(CMakeStateCache(), CMakeStateCache()) @@ -568,7 +603,7 @@ except TypeError: return value if option.name.endswith('dir') and value.is_absolute() and \ - option not in BULITIN_DIR_NOPREFIX_OPTIONS: + option not in BUILTIN_DIR_NOPREFIX_OPTIONS: try: # Try to relativize the path. value = value.relative_to(prefix) @@ -636,7 +671,8 @@ raise MesonException(f'Tried to get unknown builtin option {str(key)}') - def set_option(self, key: OptionKey, value) -> None: + def set_option(self, key: OptionKey, value, first_invocation: bool = False) -> bool: + dirty = False if key.is_builtin(): if key.name == 'prefix': value = self.sanitize_prefix(value) @@ -676,23 +712,25 @@ newname = opt.deprecated newkey = OptionKey.from_string(newname).evolve(subproject=key.subproject) mlog.deprecation(f'Option {key.name!r} is replaced by {newname!r}') - self.set_option(newkey, value) + dirty |= self.set_option(newkey, value, first_invocation) - opt.set_value(value) + changed = opt.set_value(value) + if changed and opt.readonly and not first_invocation: + raise MesonException(f'Tried modify read only option {str(key)!r}') + dirty |= changed 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() + dirty |= self._set_others_from_buildtype(value) - def clear_deps_cache(self): + return dirty + + def clear_cache(self) -> None: self.deps.host.clear() self.deps.build.clear() + self.compiler_check_cache.clear() + self.run_check_cache.clear() - def get_nondefault_buildtype_args(self): + def get_nondefault_buildtype_args(self) -> T.List[T.Union[T.Tuple[str, str, str], T.Tuple[str, bool, bool]]]: result = [] value = self.options[OptionKey('buildtype')].value if value == 'plain': @@ -721,7 +759,9 @@ result.append(('debug', actual_debug, debug)) return result - def _set_others_from_buildtype(self, value: str) -> None: + def _set_others_from_buildtype(self, value: str) -> bool: + dirty = False + if value == 'plain': opt = 'plain' debug = False @@ -739,9 +779,12 @@ debug = True else: assert value == 'custom' - return - self.options[OptionKey('optimization')].set_value(opt) - self.options[OptionKey('debug')].set_value(debug) + return False + + dirty |= self.options[OptionKey('optimization')].set_value(opt) + dirty |= self.options[OptionKey('debug')].set_value(debug) + + return dirty @staticmethod def is_per_machine_option(optname: OptionKey) -> bool: @@ -749,17 +792,6 @@ 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.List[str]: return self.options[OptionKey('args', machine=for_machine, lang=lang)].value @@ -775,7 +807,7 @@ continue oldval = self.options[key] - if type(oldval) != type(value): + if type(oldval) is not type(value): self.options[key] = value elif oldval.choices != value.choices: # If the choices have changed, use the new value, but attempt @@ -785,45 +817,50 @@ try: value.set_value(oldval.value) except MesonException: - mlog.warning(f'Old value(s) of {key} are no longer valid, resetting to default ({value.value}).') + mlog.warning(f'Old value(s) of {key} are no longer valid, resetting to default ({value.value}).', + fatal=False) 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 copy_build_options_from_regular_ones(self) -> None: + def copy_build_options_from_regular_ones(self) -> bool: + dirty = False 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) + dirty |= 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) + dirty |= bv.set_value(hv.value) except KeyError: continue - def set_options(self, options: T.Dict[OptionKey, T.Any], subproject: str = '') -> None: + return dirty + + def set_options(self, options: T.Dict[OptionKey, T.Any], subproject: str = '', first_invocation: bool = False) -> bool: + dirty = False if not self.is_cross_build(): 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 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: + dirty |= self.options[OptionKey('prefix')].set_value(prefix) + for key in BUILTIN_DIR_NOPREFIX_OPTIONS: if key not in options: - self.options[key].set_value(BUILTIN_OPTIONS[key].prefixed_default(key, prefix)) + dirty |= self.options[key].set_value(BUILTIN_OPTIONS[key].prefixed_default(key, prefix)) unknown_options: T.List[OptionKey] = [] for k, v in options.items(): if k == pfk: continue elif k in self.options: - self.set_option(k, v) + dirty |= self.set_option(k, v, first_invocation) elif k.machine != MachineChoice.BUILD and k.type != OptionType.COMPILER: unknown_options.append(k) if unknown_options: @@ -832,11 +869,13 @@ raise MesonException(f'{sub}Unknown options: "{unknown_options_str}"') if not self.is_cross_build(): - self.copy_build_options_from_regular_ones() + dirty |= self.copy_build_options_from_regular_ones() + + return dirty def set_default_options(self, default_options: T.MutableMapping[OptionKey, str], subproject: str, env: 'Environment') -> None: # Main project can set default options on subprojects, but subprojects - # can only set default options on themself. + # can only set default options on themselves. # Preserve order: if env.options has 'buildtype' it must come after # 'optimization' if it is in default_options. options: T.MutableMapping[OptionKey, T.Any] = OrderedDict() @@ -870,7 +909,7 @@ continue options[k] = v - self.set_options(options, subproject=subproject) + self.set_options(options, subproject=subproject, first_invocation=env.first_invocation) def add_compiler_options(self, options: 'MutableKeyedOptionDictType', lang: str, for_machine: MachineChoice, env: 'Environment') -> None: @@ -892,14 +931,13 @@ def process_new_compiler(self, lang: str, comp: 'Compiler', env: 'Environment') -> None: from . import compilers - self.compilers[comp.for_machine][lang] = comp self.add_compiler_options(comp.get_options(), lang, comp.for_machine, env) enabled_opts: T.List[OptionKey] = [] for key in comp.base_options: if key in self.options: continue - oobj = compilers.base_options[key] + oobj = copy.deepcopy(compilers.base_options[key]) if key in env.options: oobj.set_value(env.options[key]) enabled_opts.append(key) @@ -930,7 +968,10 @@ self.constants = {'True': True, 'False': False} self.sections = {} - self.parser.read(filenames) + try: + self.parser.read(filenames) + except configparser.Error as e: + raise EnvironmentException(f'Malformed cross or native file: {e}') # Parse [constants] first so they can be used in other sections if self.parser.has_section('constants'): @@ -951,9 +992,11 @@ value = value.replace('\\', '\\\\') try: ast = mparser.Parser(value, 'machinefile').parse() + if not ast.lines: + raise EnvironmentException('value cannot be empty') res = self._evaluate_statement(ast.lines[0]) - except MesonException: - raise EnvironmentException(f'Malformed value in machine file variable {entry!r}.') + except MesonException as e: + raise EnvironmentException(f'Malformed value in machine file variable {entry!r}: {str(e)}.') except KeyError as e: raise EnvironmentException(f'Undefined constant {e.args[0]!r} in machine file variable {entry!r}.') section[entry] = res @@ -1051,9 +1094,7 @@ def load(build_dir: str) -> CoreData: filename = os.path.join(build_dir, 'meson-private', 'coredata.dat') - obj = pickle_load(filename, 'Coredata', CoreData) - assert isinstance(obj, CoreData), 'for mypy' - return obj + return pickle_load(filename, 'Coredata', CoreData) def save(obj: CoreData, build_dir: str) -> str: @@ -1069,7 +1110,7 @@ pickle.dump(obj, f) f.flush() os.fsync(f.fileno()) - replace_if_different(filename, tempfilename) + os.replace(tempfilename, filename) return filename @@ -1125,12 +1166,13 @@ """ def __init__(self, opt_type: T.Type[_U], description: str, default: T.Any, yielding: bool = True, *, - choices: T.Any = None): + choices: T.Any = None, readonly: bool = False): self.opt_type = opt_type self.description = description self.default = default self.choices = choices self.yielding = yielding + self.readonly = readonly def init_option(self, name: 'OptionKey', value: T.Optional[T.Any], prefix: str) -> _U: """Create an instance of opt_type and return it.""" @@ -1139,7 +1181,9 @@ keywords = {'yielding': self.yielding, 'value': value} if self.choices: keywords['choices'] = self.choices - return self.opt_type(self.description, **keywords) + o = self.opt_type(self.description, **keywords) + o.readonly = self.readonly + return o def _argparse_action(self) -> T.Optional[str]: # If the type is a boolean, the presence of the argument in --foo form @@ -1167,7 +1211,7 @@ if self.opt_type in [UserComboOption, UserIntegerOption]: return self.default try: - return BULITIN_DIR_NOPREFIX_OPTIONS[name][prefix] + return BUILTIN_DIR_NOPREFIX_OPTIONS[name][prefix] except KeyError: pass return self.default @@ -1200,6 +1244,7 @@ (OptionKey('includedir'), BuiltinOption(UserStringOption, 'Header file directory', default_includedir())), (OptionKey('infodir'), BuiltinOption(UserStringOption, 'Info page directory', default_infodir())), (OptionKey('libdir'), BuiltinOption(UserStringOption, 'Library directory', default_libdir())), + (OptionKey('licensedir'), BuiltinOption(UserStringOption, 'Licenses directory', '')), (OptionKey('libexecdir'), BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir())), (OptionKey('localedir'), BuiltinOption(UserStringOption, 'Locale data directory', default_localedir())), (OptionKey('localstatedir'), BuiltinOption(UserStringOption, 'Localstate data directory', 'var')), @@ -1211,9 +1256,18 @@ BUILTIN_CORE_OPTIONS: 'MutableKeyedOptionDictType' = OrderedDict([ (OptionKey('auto_features'), BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto')), - (OptionKey('backend'), BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist)), + (OptionKey('backend'), BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist, + readonly=True)), + (OptionKey('genvslite'), + BuiltinOption( + UserComboOption, + 'Setup multiple buildtype-suffixed ninja-backend build directories, ' + 'and a [builddir]_vs containing a Visual Studio meta-backend with multiple configurations that calls into them', + 'vs2022', + choices=genvslitelist) + ), (OptionKey('buildtype'), BuiltinOption(UserComboOption, 'Build type to use', 'debug', - choices=['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom'])), + choices=buildtypelist)), (OptionKey('debug'), BuiltinOption(UserBooleanOption, 'Enable debug symbols and other information', True)), (OptionKey('default_library'), BuiltinOption(UserComboOption, 'Default library type', 'shared', choices=['shared', 'static', 'both'], yielding=False)), @@ -1230,12 +1284,15 @@ (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', [])), + (OptionKey('vsenv'), BuiltinOption(UserBooleanOption, 'Activate Visual Studio environment', False, readonly=True)), # Pkgconfig module (OptionKey('relocatable', module='pkgconfig'), BuiltinOption(UserBooleanOption, 'Generate pkgconfig files as relocatable', False)), # Python module + (OptionKey('bytecompile', module='python'), + BuiltinOption(UserIntegerOption, 'Whether to compile bytecode', (-1, 2, 0))), (OptionKey('install_env', module='python'), BuiltinOption(UserComboOption, 'Which python environment to install to', 'prefix', choices=['auto', 'prefix', 'system', 'venv'])), (OptionKey('platlibdir', module='python'), @@ -1253,7 +1310,7 @@ # Special prefix-dependent defaults for installation directories that reside in # a path outside of the prefix in FHS and common usage. -BULITIN_DIR_NOPREFIX_OPTIONS: T.Dict[OptionKey, T.Dict[str, str]] = { +BUILTIN_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'}, @@ -1261,24 +1318,25 @@ OptionKey('purelibdir', module='python'): {}, } -FORBIDDEN_TARGET_NAMES = {'clean': None, - 'clean-ctlist': None, - 'clean-gcno': None, - 'clean-gcda': None, - 'coverage': None, - 'coverage-text': None, - 'coverage-xml': None, - 'coverage-html': None, - 'phony': None, - 'PHONY': None, - 'all': None, - 'test': None, - 'benchmark': None, - 'install': None, - 'uninstall': None, - 'build.ninja': None, - 'scan-build': None, - 'reconfigure': None, - 'dist': None, - 'distcheck': None, - } +FORBIDDEN_TARGET_NAMES = frozenset({ + 'clean', + 'clean-ctlist', + 'clean-gcno', + 'clean-gcda', + 'coverage', + 'coverage-text', + 'coverage-xml', + 'coverage-html', + 'phony', + 'PHONY', + 'all', + 'test', + 'benchmark', + 'install', + 'uninstall', + 'build.ninja', + 'scan-build', + 'reconfigure', + 'dist', + 'distcheck', +}) diff -Nru meson-1.0.1/mesonbuild/dependencies/__init__.py meson-1.2.1/mesonbuild/dependencies/__init__.py --- meson-1.0.1/mesonbuild/dependencies/__init__.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/__init__.py 2023-06-28 14:48:20.000000000 +0000 @@ -12,35 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .boost import BoostDependency -from .cuda import CudaDependency -from .hdf5 import hdf5_factory from .base import Dependency, InternalDependency, ExternalDependency, NotFoundDependency, MissingCompiler from .base import ( ExternalLibrary, DependencyException, DependencyMethods, BuiltinDependency, SystemDependency, get_leaf_external_dependencies) -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, JNISystemDependency, 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, - dl_factory, openssl_factory, libcrypto_factory, libssl_factory, -) -from .platform import AppleFrameworks -from .qt import qt4_factory, qt5_factory, qt6_factory -from .ui import GnuStepDependency, WxDependency, gl_factory, sdl2_factory, vulkan_factory __all__ = [ 'Dependency', @@ -54,16 +30,6 @@ 'DependencyMethods', 'MissingCompiler', - 'CMakeDependency', - 'ConfigToolDependency', - 'DubDependency', - 'ExtraFrameworkDependency', - 'PkgConfigDependency', - - 'DependencyFactory', - - 'ThreadDependency', - 'find_external_dependency', 'get_dep_identifier', 'get_leaf_external_dependencies', @@ -226,57 +192,66 @@ # - An ExternalDependency subclass # - A DependencyFactory object # - A callable with a signature of (Environment, MachineChoice, Dict[str, Any]) -> List[Callable[[], ExternalDependency]] -packages.update({ +# +# The internal "defaults" attribute contains a separate dictionary mapping +# for lazy imports. The values must be: +# - a string naming the submodule that should be imported from `mesonbuild.dependencies` to populate the dependency +packages.defaults.update({ # From dev: - 'gtest': gtest_factory, - 'gmock': gmock_factory, - 'llvm': llvm_factory, - 'valgrind': ValgrindDependency, - 'zlib': zlib_factory, - 'jni': JNISystemDependency, - 'jdk': JDKSystemDependency, + 'gtest': 'dev', + 'gmock': 'dev', + 'llvm': 'dev', + 'valgrind': 'dev', + 'zlib': 'dev', + 'jni': 'dev', + 'jdk': 'dev', - 'boost': BoostDependency, - 'cuda': CudaDependency, + 'boost': 'boost', + 'cuda': 'cuda', # per-file - 'coarray': coarray_factory, - 'hdf5': hdf5_factory, - 'mpi': mpi_factory, - 'scalapack': scalapack_factory, + 'coarray': 'coarrays', + 'hdf5': 'hdf5', + 'mpi': 'mpi', + 'scalapack': 'scalapack', # From misc: - 'blocks': BlocksDependency, - 'curses': curses_factory, - 'netcdf': netcdf_factory, - 'openmp': OpenMPDependency, - '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, - 'dl': dl_factory, - 'openssl': openssl_factory, - 'libcrypto': libcrypto_factory, - 'libssl': libssl_factory, + 'blocks': 'misc', + 'curses': 'misc', + 'netcdf': 'misc', + 'openmp': 'misc', + 'threads': 'misc', + 'pcap': 'misc', + 'cups': 'misc', + 'libwmf': 'misc', + 'libgcrypt': 'misc', + 'gpgme': 'misc', + 'shaderc': 'misc', + 'iconv': 'misc', + 'intl': 'misc', + 'dl': 'misc', + 'openssl': 'misc', + 'libcrypto': 'misc', + 'libssl': 'misc', # From platform: - 'appleframeworks': AppleFrameworks, + 'appleframeworks': 'platform', + + # from python: + 'python3': 'python', + 'pybind11': 'python', # From ui: - 'gl': gl_factory, - 'gnustep': GnuStepDependency, - 'qt4': qt4_factory, - 'qt5': qt5_factory, - 'qt6': qt6_factory, - 'sdl2': sdl2_factory, - 'wxwidgets': WxDependency, - 'vulkan': vulkan_factory, + 'gl': 'ui', + 'gnustep': 'ui', + 'sdl2': 'ui', + 'wxwidgets': 'ui', + 'vulkan': 'ui', + + # from qt + 'qt4': 'qt', + 'qt5': 'qt', + 'qt6': 'qt', }) _packages_accept_language.update({ 'hdf5', diff -Nru meson-1.0.1/mesonbuild/dependencies/base.py meson-1.2.1/mesonbuild/dependencies/base.py --- meson-1.0.1/mesonbuild/dependencies/base.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/base.py 2023-06-28 14:48:20.000000000 +0000 @@ -31,13 +31,12 @@ if T.TYPE_CHECKING: from .._typing import ImmutableListProtocol - from ..build import StructuredSources from ..compilers.compilers import Compiler from ..environment import Environment from ..interpreterbase import FeatureCheckBase from ..build import ( CustomTarget, IncludeDirs, CustomTargetIndex, LibTypes, - StaticLibrary + StaticLibrary, StructuredSources, ExtractedObjects ) from ..mesonlib import FileOrString @@ -100,7 +99,7 @@ return kwargs['include_type'] def __init__(self, type_name: DependencyTypeName, kwargs: T.Dict[str, T.Any]) -> None: - self.name = "null" + self.name = f'dep{id(self)}' self.version: T.Optional[str] = None self.language: T.Optional[str] = None # None means C-like self.is_found = False @@ -111,6 +110,7 @@ # If None, self.link_args will be used self.raw_link_args: T.Optional[T.List[str]] = None self.sources: T.List[T.Union['FileOrString', 'CustomTarget', 'StructuredSources']] = [] + self.extra_files: T.List[mesonlib.File] = [] self.include_type = self._process_include_type_kw(kwargs) self.ext_deps: T.List[Dependency] = [] self.d_features: T.DefaultDict[str, T.List[T.Any]] = collections.defaultdict(list) @@ -172,6 +172,10 @@ As an example, gtest-all.cc when using GTest.""" return self.sources + def get_extra_files(self) -> T.List[mesonlib.File]: + """Mostly for introspection and IDEs""" + return self.extra_files + def get_name(self) -> str: return self.name @@ -251,8 +255,10 @@ libraries: T.List[LibTypes], whole_libraries: T.List[T.Union[StaticLibrary, CustomTarget, CustomTargetIndex]], sources: T.Sequence[T.Union[FileOrString, CustomTarget, StructuredSources]], + extra_files: T.Sequence[mesonlib.File], ext_deps: T.List[Dependency], variables: T.Dict[str, str], - d_module_versions: T.List[T.Union[str, int]], d_import_dirs: T.List['IncludeDirs']): + d_module_versions: T.List[T.Union[str, int]], d_import_dirs: T.List['IncludeDirs'], + objects: T.List['ExtractedObjects']): super().__init__(DependencyTypeName('internal'), {}) self.version = version self.is_found = True @@ -262,8 +268,10 @@ self.libraries = libraries self.whole_libraries = whole_libraries self.sources = list(sources) + self.extra_files = list(extra_files) self.ext_deps = ext_deps self.variables = variables + self.objects = objects if d_module_versions: self.d_features['versions'] = d_module_versions if d_import_dirs: @@ -302,12 +310,14 @@ def get_partial_dependency(self, *, compile_args: bool = False, link_args: bool = False, links: bool = False, - includes: bool = False, sources: bool = False) -> 'InternalDependency': + includes: bool = False, sources: bool = False, + extra_files: 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 [] final_whole_libraries = self.whole_libraries.copy() if links else [] final_sources = self.sources.copy() if sources else [] + final_extra_files = self.extra_files.copy() if extra_files else [] final_includes = self.include_directories.copy() if includes else [] final_deps = [d.get_partial_dependency( compile_args=compile_args, link_args=link_args, links=links, @@ -315,7 +325,7 @@ return InternalDependency( self.version, final_includes, final_compile_args, final_link_args, final_libraries, final_whole_libraries, - final_sources, final_deps, self.variables, [], []) + final_sources, final_extra_files, final_deps, self.variables, [], [], []) def get_include_dirs(self) -> T.List['IncludeDirs']: return self.include_directories @@ -542,9 +552,20 @@ 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 = {f'-L{p}' for p in environment.get_compiler_system_dirs(for_machine)} + exclude = {f'-L{p}' for p in environment.get_compiler_system_lib_dirs(for_machine)} return [l for l in link_args if l not in exclude] +def strip_system_includedirs(environment: 'Environment', for_machine: MachineChoice, include_args: T.List[str]) -> T.List[str]: + """Remove -I arguments. + + leaving these in will break builds where user want dependencies with system + include-type used in rust.bindgen targets as if will cause system headers + to not be found. + """ + + exclude = {f'-I{p}' for p in environment.get_compiler_system_include_dirs(for_machine)} + return [i for i in include_args if i 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): diff -Nru meson-1.0.1/mesonbuild/dependencies/boost.py meson-1.2.1/mesonbuild/dependencies/boost.py --- meson-1.0.1/mesonbuild/dependencies/boost.py 2022-12-10 16:38:19.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/boost.py 2023-08-07 22:54:34.000000000 +0000 @@ -23,6 +23,7 @@ from .. import mesonlib from .base import DependencyException, SystemDependency +from .detect import packages from .pkgconfig import PkgConfigDependency from .misc import threads_factory @@ -80,7 +81,7 @@ # 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.3 Filter the remaining 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 @@ -243,7 +244,7 @@ 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. + # Handle the boost_python naming madness. # See https://github.com/mesonbuild/meson/issues/4788 for some distro # specific naming variations. other_tags = [] # type: T.List[str] @@ -738,6 +739,7 @@ # BOOST_ALL_DYN_LINK should not be required with the known defines below return ['-DBOOST_ALL_NO_LIB'] # Disable automatic linking +packages['boost'] = BoostDependency # 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 diff -Nru meson-1.0.1/mesonbuild/dependencies/cmake.py meson-1.2.1/mesonbuild/dependencies/cmake.py --- meson-1.0.1/mesonbuild/dependencies/cmake.py 2022-12-10 16:38:19.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/cmake.py 2023-05-30 15:42:56.000000000 +0000 @@ -388,6 +388,7 @@ 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 += [f'-DSTATIC={self.static}'] cmake_opts += args cmake_opts += self.traceparser.trace_args() cmake_opts += toolchain.get_cmake_args() @@ -489,7 +490,7 @@ 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: + # configurations can be in the *_LIBRARIES variables. 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) @@ -505,7 +506,7 @@ 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` + # are implicitly `general` cfg_matches = True # Try to use old style variables if no module is specified diff -Nru meson-1.0.1/mesonbuild/dependencies/coarrays.py meson-1.2.1/mesonbuild/dependencies/coarrays.py --- meson-1.0.1/mesonbuild/dependencies/coarrays.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/coarrays.py 2023-08-07 22:54:34.000000000 +0000 @@ -18,6 +18,7 @@ from .base import DependencyMethods, detect_compiler, SystemDependency from .cmake import CMakeDependency +from .detect import packages from .pkgconfig import PkgConfigDependency from .factory import factory_methods @@ -51,6 +52,7 @@ candidates.append(functools.partial(CoarrayDependency, env, kwargs)) return candidates +packages['coarray'] = coarray_factory class CoarrayDependency(SystemDependency): diff -Nru meson-1.0.1/mesonbuild/dependencies/configtool.py meson-1.2.1/mesonbuild/dependencies/configtool.py --- meson-1.0.1/mesonbuild/dependencies/configtool.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/configtool.py 2023-06-28 14:48:20.000000000 +0000 @@ -14,7 +14,7 @@ from __future__ import annotations from .base import ExternalDependency, DependencyException, DependencyTypeName -from ..mesonlib import listify, Popen_safe, split_args, version_compare, version_compare_many +from ..mesonlib import listify, Popen_safe, Popen_safe_logged, split_args, version_compare, version_compare_many from ..programs import find_external_program from .. import mlog import re @@ -43,6 +43,7 @@ tool_name: T.Optional[str] = None version_arg = '--version' skip_version: T.Optional[str] = None + allow_default_for_cross = False __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): @@ -85,7 +86,7 @@ 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): + self.tool_name, self.tools, allow_default_for_cross=self.allow_default_for_cross): if not potential_bin.found(): continue tool = potential_bin.get_command() @@ -142,7 +143,7 @@ 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) + p, out, err = Popen_safe_logged(self.config + args) if p.returncode != 0: if self.required: raise DependencyException(f'Could not generate {stage} for {self.name}.\n{err}') diff -Nru meson-1.0.1/mesonbuild/dependencies/cuda.py meson-1.2.1/mesonbuild/dependencies/cuda.py --- meson-1.0.1/mesonbuild/dependencies/cuda.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/cuda.py 2023-06-28 14:48:20.000000000 +0000 @@ -23,6 +23,7 @@ from .. import mlog from ..environment import detect_cpu_family from .base import DependencyException, SystemDependency +from .detect import packages if T.TYPE_CHECKING: @@ -290,3 +291,5 @@ for lib in self.requested_modules: args += self.lib_modules[lib] return args + +packages['cuda'] = CudaDependency diff -Nru meson-1.0.1/mesonbuild/dependencies/data/CMakeLists.txt meson-1.2.1/mesonbuild/dependencies/data/CMakeLists.txt --- meson-1.0.1/mesonbuild/dependencies/data/CMakeLists.txt 2021-04-01 21:13:00.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/data/CMakeLists.txt 2023-05-30 15:42:56.000000000 +0000 @@ -8,6 +8,10 @@ set(_packageName "${NAME}") string(TOUPPER "${_packageName}" PACKAGE_NAME) +if("${STATIC}" STREQUAL "True") + set("${NAME}_USE_STATIC_LIBS" "ON") +endif() + while(TRUE) if ("${VERSION}" STREQUAL "") find_package("${NAME}" QUIET COMPONENTS ${COMPS}) diff -Nru meson-1.0.1/mesonbuild/dependencies/data/CMakeListsLLVM.txt meson-1.2.1/mesonbuild/dependencies/data/CMakeListsLLVM.txt --- meson-1.0.1/mesonbuild/dependencies/data/CMakeListsLLVM.txt 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/data/CMakeListsLLVM.txt 2023-05-23 15:20:02.000000000 +0000 @@ -1,8 +1,24 @@ +# 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) +list(REMOVE_DUPLICATES LLVM_MESON_VERSIONS) + while(TRUE) - find_package(LLVM REQUIRED CONFIG QUIET) + #Activate CMake version selection + foreach(i IN LISTS LLVM_MESON_VERSIONS) + find_package(LLVM ${i} + CONFIG + NAMES ${LLVM_MESON_PACKAGE_NAMES} + QUIET) + if(LLVM_FOUND) + break() + endif() + endforeach() # ARCHS has to be set via the CMD interface if(LLVM_FOUND OR "${ARCHS}" STREQUAL "") @@ -13,9 +29,70 @@ list(REMOVE_AT ARCHS 0) endwhile() +function(meson_llvm_cmake_dynamic_available mod out) + # Check if we can only compare LLVM_DYLIB_COMPONENTS, because + # we do not need complex component translation logic, if all + # is covered by one variable + if(mod IN_LIST LLVM_DYLIB_COMPONENTS) + set(${out} TRUE PARENT_SCOPE) + return() + elseif((NOT (mod IN_LIST LLVM_DYLIB_COMPONENTS)) + AND (NOT("${LLVM_DYLIB_COMPONENTS}" STREQUAL "all"))) + set(${out} FALSE PARENT_SCOPE) + return() + endif() + + # Complex heuristic to filter all pseudo-components and skip invalid names + # LLVM_DYLIB_COMPONENTS will be 'all', because in other case we returned + # in previous check. 'all' is also handled there. + set(llvm_pseudo_components "native" "backend" "engine" "all-targets") + is_llvm_target_specifier(${mod} mod_spec INCLUDED_TARGETS) + string(TOUPPER "${LLVM_AVAILABLE_LIBS}" capitalized_libs) + string(TOUPPER "${LLVM_TARGETS_TO_BUILD}" capitalized_tgts) + if(mod_spec) + set(${out} TRUE PARENT_SCOPE) + elseif(mod IN_LIST capitalized_tgts) + set(${out} TRUE PARENT_SCOPE) + elseif(mod IN_LIST llvm_pseudo_components) + set(${out} TRUE PARENT_SCOPE) + elseif(LLVM${mod} IN_LIST capitalized_libs) + set(${out} TRUE PARENT_SCOPE) + else() + set(${out} FALSE PARENT_SCOPE) + endif() +endfunction() + +function(is_static target ret) + if(TARGET ${target}) + get_target_property(target_type ${target} TYPE) + if(target_type STREQUAL "STATIC_LIBRARY") + set(${ret} TRUE PARENT_SCOPE) + return() + endif() + endif() + set(${ret} FALSE PARENT_SCOPE) +endfunction() + +# Concatenate LLVM_MESON_REQUIRED_MODULES and LLVM_MESON_OPTIONAL_MODULES +set(LLVM_MESON_MODULES ${LLVM_MESON_REQUIRED_MODULES} ${LLVM_MESON_OPTIONAL_MODULES}) + + +# Check if LLVM exists in dynamic world +# Initialization before modules checking if(LLVM_FOUND) - set(PACKAGE_FOUND TRUE) + if(LLVM_MESON_DYLIB AND TARGET LLVM) + set(PACKAGE_FOUND TRUE) + elseif(NOT LLVM_MESON_DYLIB) + # Use LLVMSupport to check if static targets exist + set(static_tg FALSE) + is_static(LLVMSupport static_tg) + if(static_tg) + set(PACKAGE_FOUND TRUE) + endif(static_tg) + endif() +endif() +if(PACKAGE_FOUND) foreach(mod IN LISTS LLVM_MESON_MODULES) # Reset variables set(out_mods) @@ -25,23 +102,53 @@ 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() + # Special case - "all-targets" pseudo target + # Just append all targets, if pseudo-target exists + if("${mod}" STREQUAL "all-targets") + set(mod_L ${LLVM_TARGETS_TO_BUILD}) + string(TOUPPER "${LLVM_TARGETS_TO_BUILD}" mod_U) + endif() + + # Check if required module is linked is inside libLLVM.so. + # If not, skip this module + if(LLVM_MESON_DYLIB + AND DEFINED LLVM_DYLIB_COMPONENTS) + meson_llvm_cmake_dynamic_available(${mod} MOD_F) + meson_llvm_cmake_dynamic_available(${mod_L} MOD_L_F) + meson_llvm_cmake_dynamic_available(${mod_U} MOD_U_F) + if(MOD_F OR MOD_L_F OR MOD_U_F) + set(MESON_LLVM_TARGETS_${mod} LLVM) + endif() + elseif(LLVM_MESON_DYLIB AND (mod IN_LIST LLVM_MESON_REQUIRED_MODULES)) + # Dynamic was requested, but no required variables set, we cannot continue + set(PACKAGE_FOUND FALSE) + break() + elseif(LLVM_MESON_DYLIB) + # Dynamic was requested, and we request optional modules only. Continue + continue() + else() + # CMake only do this for static components, and we + # replicate its behaviour + # 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) + set(static_tg FALSE) + is_static(${i} static_tg) + if(static_tg) + 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() + endif() endforeach() # Check the following variables: @@ -62,7 +169,10 @@ # LLVM_LIBRARIES # LLVM_LIBS set(libs) - if(DEFINED LLVM_LIBRARIES) + #Hardcode LLVM, because we links with libLLVM.so when dynamic + if(LLVM_MESON_DYLIB) + get_target_property(libs LLVM IMPORTED_LOCATION) + elseif(DEFINED LLVM_LIBRARIES) set(libs LLVM_LIBRARIES) elseif(DEFINED LLVM_LIBS) set(libs LLVM_LIBS) diff -Nru meson-1.0.1/mesonbuild/dependencies/detect.py meson-1.2.1/mesonbuild/dependencies/detect.py --- meson-1.0.1/mesonbuild/dependencies/detect.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/detect.py 2023-06-28 14:48:20.000000000 +0000 @@ -13,16 +13,13 @@ # limitations under the License. from __future__ import annotations +import collections, functools, importlib +import typing as T + 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 @@ -30,12 +27,25 @@ TV_DepIDEntry = T.Union[str, bool, int, T.Tuple[str, ...]] TV_DepID = T.Tuple[T.Tuple[str, TV_DepIDEntry], ...] + PackageTypes = T.Union[T.Type[ExternalDependency], DependencyFactory, WrappedFactoryFunc] + +class DependencyPackages(collections.UserDict): + data: T.Dict[str, PackageTypes] + defaults: T.Dict[str, str] = {} + + def __missing__(self, key: str) -> PackageTypes: + if key in self.defaults: + modn = self.defaults[key] + importlib.import_module(f'mesonbuild.dependencies.{modn}') + + return self.data[key] + raise KeyError(key) + + def __contains__(self, key: object) -> bool: + return key in self.defaults or key in self.data # These must be defined in this file to avoid cyclical references. -packages: T.Dict[ - str, - T.Union[T.Type[ExternalDependency], 'DependencyFactory', 'WrappedFactoryFunc'] -] = {} +packages = DependencyPackages() _packages_accept_language: T.Set[str] = set() def get_dep_identifier(name: str, kwargs: T.Dict[str, T.Any]) -> 'TV_DepID': @@ -80,7 +90,7 @@ 'wxwidgets': 'WxWidgets', } -def find_external_dependency(name: str, env: 'Environment', kwargs: T.Dict[str, object]) -> T.Union['ExternalDependency', NotFoundDependency]: +def find_external_dependency(name: str, env: 'Environment', kwargs: T.Dict[str, object], candidates: T.Optional[T.List['DependencyGenerator']] = None) -> T.Union['ExternalDependency', NotFoundDependency]: assert name required = kwargs.get('required', True) if not isinstance(required, bool): @@ -101,7 +111,8 @@ 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) + if candidates is None: + candidates = _build_external_dependency_list(name, env, for_machine, kwargs) pkg_exc: T.List[DependencyException] = [] pkgdep: T.List[ExternalDependency] = [] @@ -191,37 +202,34 @@ 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 kwargs.get('method', 'auto') == 'auto': + # Just use the standard detection methods. + methods = ['pkg-config', 'extraframework', 'cmake'] + else: + # If it's explicitly requested, use that detection method (only). + methods = [kwargs['method']] - # 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 + # Exclusive to when it is explicitly requested + if 'dub' in methods: + from .dub import DubDependency + candidates.append(functools.partial(DubDependency, name, env, kwargs)) - # Otherwise, just use the pkgconfig and cmake dependency detector - if 'auto' == kwargs.get('method', 'auto'): + # Preferred first candidate for auto. + if 'pkg-config' in methods: + from .pkgconfig import PkgConfigDependency candidates.append(functools.partial(PkgConfigDependency, name, env, kwargs)) - # On OSX, also try framework dependency detector + # On OSX only, try framework dependency detector. + if 'extraframework' in methods: if env.machines[for_machine].is_darwin(): + from .framework import ExtraFrameworkDependency candidates.append(functools.partial(ExtraFrameworkDependency, name, env, kwargs)) - # Only use CMake as a last resort, since it might not work 100% (see #6113) + # Only use CMake: + # - if it's explicitly requested + # - as a last resort, since it might not work 100% (see #6113) + if 'cmake' in methods: + from .cmake import CMakeDependency candidates.append(functools.partial(CMakeDependency, name, env, kwargs)) return candidates diff -Nru meson-1.0.1/mesonbuild/dependencies/dev.py meson-1.2.1/mesonbuild/dependencies/dev.py --- meson-1.0.1/mesonbuild/dependencies/dev.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/dev.py 2023-06-28 14:48:20.000000000 +0000 @@ -24,15 +24,17 @@ import shutil import subprocess import typing as T +import functools from mesonbuild.interpreterbase.decorators import FeatureDeprecated from .. import mesonlib, mlog from ..environment import get_llvm_tool_names -from ..mesonlib import version_compare, stringlistify, extract_as_list -from .base import DependencyException, DependencyMethods, detect_compiler, strip_system_libdirs, SystemDependency, ExternalDependency, DependencyTypeName +from ..mesonlib import version_compare, version_compare_many, search_version, stringlistify, extract_as_list +from .base import DependencyException, DependencyMethods, detect_compiler, strip_system_includedirs, strip_system_libdirs, SystemDependency, ExternalDependency, DependencyTypeName from .cmake import CMakeDependency from .configtool import ConfigToolDependency +from .detect import packages from .factory import DependencyFactory from .misc import threads_factory from .pkgconfig import PkgConfigDependency @@ -418,14 +420,15 @@ super().__init__(name, env, kwargs, language='cpp', force_use_global_compilers=True) - # 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') + if self.traceparser is None: return - if self.traceparser is None: + if not self.is_found: + return + + #CMake will return not found due to not defined LLVM_DYLIB_COMPONENTS + if not self.static and version_compare(self.version, '< 7.0') and self.llvm_modules: + mlog.warning('Before version 7.0 cmake does not export modules for dynamic linking, cannot check required modules') return # Extract extra include directories and definitions @@ -436,6 +439,7 @@ 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.compile_args = strip_system_includedirs(env, self.for_machine, self.compile_args) if not self._add_sub_dependency(threads_factory(env, self.for_machine, {})): self.is_found = False return @@ -444,8 +448,33 @@ # Use a custom CMakeLists.txt for LLVM return 'CMakeListsLLVM.txt' + # Check version in CMake to return exact version as config tool (latest allowed) + # It is safe to add .0 to latest argument, it will discarded if we use search_version + def llvm_cmake_versions(self) -> T.List[str]: + + def ver_from_suf(req: str) -> str: + return search_version(req.strip('-')+'.0') + + def version_sorter(a: str, b: str) -> int: + if version_compare(a, "="+b): + return 0 + if version_compare(a, "<"+b): + return 1 + return -1 + + llvm_requested_versions = [ver_from_suf(x) for x in get_llvm_tool_names('') if version_compare(ver_from_suf(x), '>=0')] + if self.version_reqs: + llvm_requested_versions = [ver_from_suf(x) for x in get_llvm_tool_names('') if version_compare_many(ver_from_suf(x), self.version_reqs)] + # CMake sorting before 3.18 is incorrect, sort it here instead + return sorted(llvm_requested_versions, key=functools.cmp_to_key(version_sorter)) + + # Split required and optional modules to distinguish it in CMake def _extra_cmake_opts(self) -> T.List[str]: - return ['-DLLVM_MESON_MODULES={}'.format(';'.join(self.llvm_modules + self.llvm_opt_modules))] + return ['-DLLVM_MESON_REQUIRED_MODULES={}'.format(';'.join(self.llvm_modules)), + '-DLLVM_MESON_OPTIONAL_MODULES={}'.format(';'.join(self.llvm_opt_modules)), + '-DLLVM_MESON_PACKAGE_NAMES={}'.format(';'.join(get_llvm_tool_names(self.name))), + '-DLLVM_MESON_VERSIONS={}'.format(';'.join(self.llvm_cmake_versions())), + '-DLLVM_MESON_DYLIB={}'.format('OFF' if self.static else 'ON')] 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 = [] @@ -455,7 +484,7 @@ if required: raise self._gen_exception(f'LLVM module {mod} was not found') else: - mlog.warning('Optional LLVM module', mlog.bold(mod), 'was not found') + mlog.warning('Optional LLVM module', mlog.bold(mod), 'was not found', fatal=False) continue for i in cm_targets: res += [(i, required)] @@ -479,6 +508,8 @@ def get_link_args(self, language: T.Optional[str] = None, raw: bool = False) -> T.List[str]: return [] +packages['valgrind'] = ValgrindDependency + class ZlibSystemDependency(SystemDependency): @@ -534,8 +565,11 @@ modules: T.List[str] = mesonlib.listify(kwargs.get('modules', [])) for module in modules: if module not in {'jvm', 'awt'}: - log = mlog.error if self.required else mlog.debug - log(f'Unknown JNI module ({module})') + msg = f'Unknown JNI module ({module})' + if self.required: + mlog.error(msg) + else: + mlog.debug(msg) self.is_found = False return @@ -553,8 +587,11 @@ res = subprocess.run(['/usr/libexec/java_home', '--failfast', '--arch', m.cpu_family], stdout=subprocess.PIPE) if res.returncode != 0: - log = mlog.error if self.required else mlog.debug - log('JAVA_HOME could not be discovered on the system. Please set it explicitly.') + msg = 'JAVA_HOME could not be discovered on the system. Please set it explicitly.' + if self.required: + mlog.error(msg) + else: + mlog.debug(msg) self.is_found = False return self.java_home = pathlib.Path(res.stdout.decode().strip()) @@ -637,6 +674,8 @@ return None +packages['jni'] = JNISystemDependency + class JDKSystemDependency(JNISystemDependency): def __init__(self, environment: 'Environment', kwargs: JNISystemDependencyKW): @@ -649,29 +688,31 @@ 'Use the jni system dependency instead' )) +packages['jdk'] = JDKSystemDependency + -llvm_factory = DependencyFactory( +packages['llvm'] = llvm_factory = DependencyFactory( 'LLVM', [DependencyMethods.CMAKE, DependencyMethods.CONFIG_TOOL], cmake_class=LLVMDependencyCMake, configtool_class=LLVMDependencyConfigTool, ) -gtest_factory = DependencyFactory( +packages['gtest'] = gtest_factory = DependencyFactory( 'gtest', [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM], pkgconfig_class=GTestDependencyPC, system_class=GTestDependencySystem, ) -gmock_factory = DependencyFactory( +packages['gmock'] = gmock_factory = DependencyFactory( 'gmock', [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM], pkgconfig_class=GMockDependencyPC, system_class=GMockDependencySystem, ) -zlib_factory = DependencyFactory( +packages['zlib'] = zlib_factory = DependencyFactory( 'zlib', [DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE, DependencyMethods.SYSTEM], cmake_name='ZLIB', diff -Nru meson-1.0.1/mesonbuild/dependencies/dub.py meson-1.2.1/mesonbuild/dependencies/dub.py --- meson-1.0.1/mesonbuild/dependencies/dub.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/dub.py 2023-05-30 15:42:56.000000000 +0000 @@ -15,7 +15,7 @@ from .base import ExternalDependency, DependencyException, DependencyTypeName from .pkgconfig import PkgConfigDependency -from ..mesonlib import (Popen_safe, OptionKey, join_args) +from ..mesonlib import (Popen_safe, OptionKey, join_args, version_compare) from ..programs import ExternalProgram from .. import mlog import re @@ -26,8 +26,11 @@ if T.TYPE_CHECKING: from ..environment import Environment + class DubDependency(ExternalDependency): - class_dubbin = None + # dub program and version + class_dubbin: T.Optional[T.Tuple[ExternalProgram, str]] = None + class_dubbin_searched = False def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]): super().__init__(DependencyTypeName('dub'), environment, kwargs, language='d') @@ -41,19 +44,27 @@ if 'required' in kwargs: self.required = kwargs.get('required') + if DubDependency.class_dubbin is None and not DubDependency.class_dubbin_searched: + DubDependency.class_dubbin = self._check_dub() + DubDependency.class_dubbin_searched = True 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 + (self.dubbin, dubver) = DubDependency.class_dubbin + assert isinstance(self.dubbin, ExternalProgram) + + # Check if Dub version is compatible with Meson + if version_compare(dubver, '>1.31.1'): + if self.required: + raise DependencyException( + f"DUB version {dubver} is not compatible with Meson (can't locate artifacts in Dub cache)") + self.is_found = False + return + mlog.debug('Determining dependency {!r} with DUB executable ' '{!r}'.format(name, self.dubbin.get_path())) @@ -125,13 +136,16 @@ elif 'compiler' not in compatibilities: mlog.error(mlog.bold(pack_id), 'found but not compiled with ', mlog.bold(dub_comp_id)) elif dub_comp_id != 'gdc' and 'compiler_version' not in compatibilities: - mlog.error(mlog.bold(pack_id), 'found but not compiled with', mlog.bold(f'{dub_comp_id}-{self.compiler.version}')) + mlog.error(mlog.bold(pack_id), 'found but not compiled with', + mlog.bold(f'{dub_comp_id}-{self.compiler.version}')) elif 'arch' not in compatibilities: mlog.error(mlog.bold(pack_id), 'found but not compiled for', mlog.bold(dub_arch)) elif 'platform' not in compatibilities: - mlog.error(mlog.bold(pack_id), 'found but not compiled for', mlog.bold(description['platform'].join('.'))) + mlog.error(mlog.bold(pack_id), 'found but not compiled for', + mlog.bold(description['platform'].join('.'))) elif 'configuration' not in compatibilities: - mlog.error(mlog.bold(pack_id), 'found but not compiled for the', mlog.bold(pkg['configuration']), 'configuration') + mlog.error(mlog.bold(pack_id), 'found but not compiled for the', + mlog.bold(pkg['configuration']), 'configuration') else: mlog.error(mlog.bold(pack_id), 'not found') @@ -168,7 +182,7 @@ self.is_found = False return - ## check that the main dependency is indeed a library + # check that the main dependency is indeed a library if pkg['name'] == name: self.is_found = True @@ -318,11 +332,12 @@ if ret != 0: mlog.error('Failed to run {!r}', mlog.bold(dub_comp_id)) return (None, None) - d_ver_reg = re.search('v[0-9].[0-9][0-9][0-9].[0-9]', res) # Ex.: v2.081.2 + 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: frontend_version = d_ver_reg.group() - frontend_id = frontend_version.rsplit('.', 1)[0].replace('v', '').replace('.', '') # Fix structure. Ex.: 2081 + frontend_id = frontend_version.rsplit('.', 1)[0].replace( + 'v', '').replace('.', '') # Fix structure. Ex.: 2081 comp_versions.extend([frontend_version, frontend_id]) compatibilities: T.Set[str] = set() @@ -380,25 +395,40 @@ p, out, err = Popen_safe(self.compiler.get_exelist() + args, env=env) return p.returncode, out.strip(), err.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(): + def _check_dub(self) -> T.Optional[T.Tuple[ExternalProgram, str]]: + + def find() -> T.Optional[T.Tuple[ExternalProgram, str]]: + dubbin = ExternalProgram('dub', silent=True) + + if not dubbin.found(): + return None + 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 + return None + except (FileNotFoundError, PermissionError): - dubbin = False + return None + + vermatch = re.search(r'DUB version (\d+\.\d+\.\d+.*), ', out.strip()) + if vermatch: + dubver = vermatch.group(1) + else: + mlog.warning(f"Found dub {' '.join(dubbin.get_command())} but couldn't parse version in {out.strip()}") + return None + + return (dubbin, dubver) + + found = find() + + if found is None: + mlog.log('Found DUB:', mlog.red('NO')) else: - dubbin = False - if isinstance(dubbin, ExternalProgram): + (dubbin, dubver) = found mlog.log('Found DUB:', mlog.bold(dubbin.get_path()), - '(%s)' % out.strip()) - else: - mlog.log('Found DUB:', mlog.red('NO')) - return dubbin + '(version %s)' % dubver) + + return found diff -Nru meson-1.0.1/mesonbuild/dependencies/hdf5.py meson-1.2.1/mesonbuild/dependencies/hdf5.py --- meson-1.0.1/mesonbuild/dependencies/hdf5.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/hdf5.py 2023-08-07 22:54:34.000000000 +0000 @@ -25,6 +25,7 @@ from ..programs import ExternalProgram from .base import DependencyException, DependencyMethods from .configtool import ConfigToolDependency +from .detect import packages from .pkgconfig import PkgConfigDependency from .factory import factory_methods import typing as T @@ -178,3 +179,5 @@ candidates.append(functools.partial(HDF5ConfigToolDependency, 'hdf5', env, kwargs, language)) return candidates + +packages['hdf5'] = hdf5_factory diff -Nru meson-1.0.1/mesonbuild/dependencies/misc.py meson-1.2.1/mesonbuild/dependencies/misc.py --- meson-1.0.1/mesonbuild/dependencies/misc.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/misc.py 2023-08-07 22:54:34.000000000 +0000 @@ -15,19 +15,17 @@ # This file contains the detection logic for miscellaneous external dependencies. from __future__ import annotations -from pathlib import Path import functools import re -import sysconfig import typing as T from .. import mesonlib from .. import mlog -from ..environment import detect_cpu_family from .base import DependencyException, DependencyMethods from .base import BuiltinDependency, SystemDependency from .cmake import CMakeDependency from .configtool import ConfigToolDependency +from .detect import packages from .factory import DependencyFactory, factory_methods from .pkgconfig import PkgConfigDependency @@ -60,6 +58,8 @@ return candidates +packages['netcdf'] = netcdf_factory + class DlBuiltinDependency(BuiltinDependency): def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): @@ -139,6 +139,8 @@ if not self.is_found: mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but omp.h missing.') +packages['openmp'] = OpenMPDependency + class ThreadDependency(SystemDependency): def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: @@ -186,108 +188,8 @@ self.is_found = True +packages['blocks'] = BlocksDependency -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' - # We can only be sure that it is Python 3 at this point - self.version = '3' - self._find_libpy3_windows(environment) - - @staticmethod - def get_windows_python_arch() -> T.Optional[str]: - pyplat = sysconfig.get_platform() - if pyplat == 'mingw': - pycc = sysconfig.get_config_var('CC') - if pycc.startswith('x86_64'): - return '64' - elif pycc.startswith(('i686', 'i386')): - return '32' - else: - 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(f'Unknown Windows Python platform {pyplat!r}') - return None - - 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') / f'libpython{vernum}.a' - else: - comp = self.get_compiler() - if comp.id == "gcc": - libpath = Path(f'python{vernum}.dll') - else: - libpath = Path('libs') / f'python{vernum}.lib' - lib = Path(sysconfig.get_config_var('base')) / libpath - elif pyplat == 'mingw': - if self.static: - libname = sysconfig.get_config_var('LIBRARY') - else: - libname = sysconfig.get_config_var('LDLIBRARY') - lib = Path(sysconfig.get_config_var('LIBDIR')) / libname - if not lib.exists(): - mlog.log('Could not find Python3 library {!r}'.format(str(lib))) - return None - return [str(lib)] - - 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. - ''' - pyarch = self.get_windows_python_arch() - if pyarch is None: - self.is_found = False - return - arch = detect_cpu_family(env.coredata.compilers.host) - if arch == 'x86': - arch = '32' - elif arch == 'x86_64': - arch = '64' - else: - # We can't cross-compile Python 3 dependencies on Windows yet - 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)) - self.is_found = False - return - # This can fail if the library is not found - largs = self.get_windows_link_args() - if largs is None: - self.is_found = False - return - self.link_args = largs - # Compile args - inc = sysconfig.get_path('include') - platinc = sysconfig.get_path('platinclude') - self.compile_args = ['-I' + inc] - if inc != platinc: - self.compile_args.append('-I' + platinc) - self.version = sysconfig.get_config_var('py_version') - self.is_found = True - - @staticmethod - def log_tried() -> str: - return 'sysconfig' class PcapDependencyConfigTool(ConfigToolDependency): @@ -437,7 +339,7 @@ ('curses', ['curses.h']), ] - # Not sure how else to elegently break out of both loops + # Not sure how else to elegantly break out of both loops for lib, headers in candidates: l = self.clib_compiler.find_library(lib, env, []) if l: @@ -594,6 +496,7 @@ candidates.append(functools.partial(CursesSystemDependency, 'curses', env, kwargs)) return candidates +packages['curses'] = curses_factory @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM}) @@ -629,94 +532,84 @@ candidates.append(functools.partial(ShadercDependency, env, kwargs)) return candidates +packages['shaderc'] = shaderc_factory -cups_factory = DependencyFactory( +packages['cups'] = cups_factory = DependencyFactory( 'cups', [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK, DependencyMethods.CMAKE], configtool_class=CupsDependencyConfigTool, cmake_name='Cups', ) -dl_factory = DependencyFactory( +packages['dl'] = dl_factory = DependencyFactory( 'dl', [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM], builtin_class=DlBuiltinDependency, system_class=DlSystemDependency, ) -gpgme_factory = DependencyFactory( +packages['gpgme'] = gpgme_factory = DependencyFactory( 'gpgme', [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL], configtool_class=GpgmeDependencyConfigTool, ) -libgcrypt_factory = DependencyFactory( +packages['libgcrypt'] = libgcrypt_factory = DependencyFactory( 'libgcrypt', [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL], configtool_class=LibGCryptDependencyConfigTool, ) -libwmf_factory = DependencyFactory( +packages['libwmf'] = libwmf_factory = DependencyFactory( 'libwmf', [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL], configtool_class=LibWmfDependencyConfigTool, ) -pcap_factory = DependencyFactory( +packages['pcap'] = 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( +packages['threads'] = threads_factory = DependencyFactory( 'threads', [DependencyMethods.SYSTEM, DependencyMethods.CMAKE], cmake_name='Threads', system_class=ThreadDependency, ) -iconv_factory = DependencyFactory( +packages['iconv'] = iconv_factory = DependencyFactory( 'iconv', [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM], builtin_class=IconvBuiltinDependency, system_class=IconvSystemDependency, ) -intl_factory = DependencyFactory( +packages['intl'] = intl_factory = DependencyFactory( 'intl', [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM], builtin_class=IntlBuiltinDependency, system_class=IntlSystemDependency, ) -openssl_factory = DependencyFactory( +packages['openssl'] = openssl_factory = DependencyFactory( 'openssl', [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.CMAKE], system_class=OpensslSystemDependency, cmake_class=lambda name, env, kwargs: CMakeDependency('OpenSSL', env, dict(kwargs, modules=['OpenSSL::Crypto', 'OpenSSL::SSL'])), ) -libcrypto_factory = DependencyFactory( +packages['libcrypto'] = libcrypto_factory = DependencyFactory( 'libcrypto', [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.CMAKE], system_class=OpensslSystemDependency, cmake_class=lambda name, env, kwargs: CMakeDependency('OpenSSL', env, dict(kwargs, modules=['OpenSSL::Crypto'])), ) -libssl_factory = DependencyFactory( +packages['libssl'] = libssl_factory = DependencyFactory( 'libssl', [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.CMAKE], system_class=OpensslSystemDependency, diff -Nru meson-1.0.1/mesonbuild/dependencies/mpi.py meson-1.2.1/mesonbuild/dependencies/mpi.py --- meson-1.0.1/mesonbuild/dependencies/mpi.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/mpi.py 2023-08-07 22:54:34.000000000 +0000 @@ -21,6 +21,7 @@ from ..environment import detect_cpu_family from .base import DependencyMethods, detect_compiler, SystemDependency from .configtool import ConfigToolDependency +from .detect import packages from .factory import factory_methods from .pkgconfig import PkgConfigDependency @@ -100,6 +101,8 @@ return candidates +packages['mpi'] = mpi_factory + class _MPIConfigToolDependency(ConfigToolDependency): diff -Nru meson-1.0.1/mesonbuild/dependencies/pkgconfig.py meson-1.2.1/mesonbuild/dependencies/pkgconfig.py --- meson-1.0.1/mesonbuild/dependencies/pkgconfig.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/pkgconfig.py 2023-08-07 22:54:34.000000000 +0000 @@ -16,7 +16,7 @@ from pathlib import Path from .base import ExternalDependency, DependencyException, sort_libpaths, DependencyTypeName -from ..mesonlib import OptionKey, OrderedSet, PerMachine, Popen_safe +from ..mesonlib import OptionKey, OrderedSet, PerMachine, Popen_safe, Popen_safe_logged from ..programs import find_external_program, ExternalProgram from .. import mlog from pathlib import PurePath @@ -28,6 +28,7 @@ if T.TYPE_CHECKING: from ..environment import Environment from ..mesonlib import MachineChoice + from ..utils.core import EnvironOrDict from .._typing import ImmutableListProtocol from ..build import EnvironmentVariables @@ -121,15 +122,8 @@ 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}") - if out: - mlog.debug(f'stdout:\n{out}\n-----------') - if err: - mlog.debug(f'stderr:\n{err}\n-----------') - return rc, out, err + p, out, err = Popen_safe_logged(cmd, env=env) + return p.returncode, out.strip(), err.strip() @staticmethod def get_env(environment: 'Environment', for_machine: MachineChoice, @@ -152,7 +146,7 @@ return env @staticmethod - def setup_env(env: T.MutableMapping[str, str], environment: 'Environment', for_machine: MachineChoice, + def setup_env(env: EnvironOrDict, environment: 'Environment', for_machine: MachineChoice, uninstalled: bool = False) -> T.Dict[str, str]: envvars = PkgConfigDependency.get_env(environment, for_machine, uninstalled) env = envvars.get_env(env) @@ -162,7 +156,7 @@ mlog.debug(f'env[{key}]: {value}') return env - def _call_pkgbin(self, args: T.List[str], env: T.Optional[T.MutableMapping[str, str]] = None) -> T.Tuple[int, str, str]: + def _call_pkgbin(self, args: T.List[str], env: T.Optional[EnvironOrDict] = None) -> T.Tuple[int, str, str]: assert isinstance(self.pkgbin, ExternalProgram) env = env or os.environ env = PkgConfigDependency.setup_env(env, self.env, self.for_machine) @@ -322,7 +316,8 @@ continue if self.clib_compiler: args = self.clib_compiler.find_library(lib[2:], self.env, - libpaths, self.libtype) + libpaths, self.libtype, + lib_prefix_warning=False) # 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. @@ -413,7 +408,7 @@ else: variable = out.strip() - # pkg-config doesn't distinguish between empty and non-existent variables + # pkg-config doesn't distinguish between empty and nonexistent variables # use the variable list to check for variable existence if not variable: ret, out, _ = self._call_pkgbin(['--print-variables', self.name]) diff -Nru meson-1.0.1/mesonbuild/dependencies/platform.py meson-1.2.1/mesonbuild/dependencies/platform.py --- meson-1.0.1/mesonbuild/dependencies/platform.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/platform.py 2023-06-28 14:48:20.000000000 +0000 @@ -17,6 +17,7 @@ from __future__ import annotations from .base import DependencyTypeName, ExternalDependency, DependencyException +from .detect import packages from ..mesonlib import MesonException import typing as T @@ -58,3 +59,5 @@ @staticmethod def log_tried() -> str: return 'framework' + +packages['appleframeworks'] = AppleFrameworks diff -Nru meson-1.0.1/mesonbuild/dependencies/python.py meson-1.2.1/mesonbuild/dependencies/python.py --- meson-1.0.1/mesonbuild/dependencies/python.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/python.py 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,417 @@ +# Copyright 2022 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 __future__ import annotations + +import functools, json, os, textwrap +from pathlib import Path +import typing as T + +from .. import mesonlib, mlog +from .base import process_method_kw, DependencyMethods, DependencyTypeName, ExternalDependency, SystemDependency +from .configtool import ConfigToolDependency +from .detect import packages +from .factory import DependencyFactory +from .framework import ExtraFrameworkDependency +from .pkgconfig import PkgConfigDependency +from ..environment import detect_cpu_family +from ..programs import ExternalProgram + +if T.TYPE_CHECKING: + from typing_extensions import TypedDict + + from .factory import DependencyGenerator + from ..environment import Environment + from ..mesonlib import MachineChoice + + class PythonIntrospectionDict(TypedDict): + + install_paths: T.Dict[str, str] + is_pypy: bool + is_venv: bool + link_libpython: bool + sysconfig_paths: T.Dict[str, str] + paths: T.Dict[str, str] + platform: str + suffix: str + variables: T.Dict[str, str] + version: str + + _Base = ExternalDependency +else: + _Base = object + + +class Pybind11ConfigToolDependency(ConfigToolDependency): + + tools = ['pybind11-config'] + + # any version of the tool is valid, since this is header-only + allow_default_for_cross = True + + # pybind11 in 2.10.4 added --version, sanity-check another flag unique to it + # in the meantime + skip_version = '--pkgconfigdir' + + 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(['--includes'], 'compile_args') + + +class BasicPythonExternalProgram(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 + self.cached_version = None + + # 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, + 'is_venv': False, + 'link_libpython': False, + 'sysconfig_paths': {}, + 'paths': {}, + 'platform': 'sentinel', + 'suffix': 'sentinel', + 'variables': {}, + 'version': '0.0', + } + self.pure: bool = True + + 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) -> bool: + # Sanity check, we expect to have something that at least quacks in tune + + import importlib.resources + + with importlib.resources.path('mesonbuild.scripts', 'python_info.py') as f: + cmd = self.get_command() + [str(f)] + 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']): + self.info = T.cast('PythonIntrospectionDict', info) + return True + else: + return False + + +class _PythonDependencyBase(_Base): + + def __init__(self, python_holder: 'BasicPythonExternalProgram', embed: bool): + self.embed = embed + self.version: str = python_holder.info['version'] + self.platform = python_holder.info['platform'] + self.variables = python_holder.info['variables'] + self.paths = python_holder.info['paths'] + self.is_pypy = python_holder.info['is_pypy'] + # The "-embed" version of python.pc / python-config was introduced in 3.8, + # and distutils extension linking was changed to be considered a non embed + # usage. Before then, this dependency always uses the embed=True handling + # because that is the only one that exists. + # + # On macOS and some Linux distros (Debian) distutils doesn't link extensions + # against libpython, even on 3.7 and below. We call into distutils and + # mirror its behavior. See https://github.com/mesonbuild/meson/issues/4117 + self.link_libpython = python_holder.info['link_libpython'] or embed + 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 + + +class PythonPkgConfigDependency(PkgConfigDependency, _PythonDependencyBase): + + def __init__(self, name: str, environment: 'Environment', + kwargs: T.Dict[str, T.Any], installation: 'BasicPythonExternalProgram', + libpc: bool = False): + if libpc: + mlog.debug(f'Searching for {name!r} via pkgconfig lookup in LIBPC') + else: + mlog.debug(f'Searching for {name!r} via fallback pkgconfig lookup in default paths') + + PkgConfigDependency.__init__(self, name, environment, kwargs) + _PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False)) + + if libpc and not self.is_found: + mlog.debug(f'"python-{self.version}" could not be found in LIBPC, this is likely due to a relocated python installation') + + # pkg-config files are usually accurate starting with python 3.8 + if not self.link_libpython and mesonlib.version_compare(self.version, '< 3.8'): + self.link_args = [] + + +class PythonFrameworkDependency(ExtraFrameworkDependency, _PythonDependencyBase): + + def __init__(self, name: str, environment: 'Environment', + kwargs: T.Dict[str, T.Any], installation: 'BasicPythonExternalProgram'): + ExtraFrameworkDependency.__init__(self, name, environment, kwargs) + _PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False)) + + +class PythonSystemDependency(SystemDependency, _PythonDependencyBase): + + def __init__(self, name: str, environment: 'Environment', + kwargs: T.Dict[str, T.Any], installation: 'BasicPythonExternalProgram'): + SystemDependency.__init__(self, name, environment, kwargs) + _PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False)) + + # match pkg-config behavior + if self.link_libpython: + # link args + if mesonlib.is_windows(): + self.find_libpy_windows(environment) + else: + self.find_libpy(environment) + else: + self.is_found = True + + # compile args + inc_paths = mesonlib.OrderedSet([ + self.variables.get('INCLUDEPY'), + self.paths.get('include'), + self.paths.get('platinclude')]) + + self.compile_args += ['-I' + path for path in inc_paths if path] + + # https://sourceforge.net/p/mingw-w64/mailman/message/30504611/ + # https://github.com/python/cpython/pull/100137 + if mesonlib.is_windows() and self.get_windows_python_arch().endswith('64') and mesonlib.version_compare(self.version, '<3.12'): + self.compile_args += ['-DMS_WIN64='] + + if not self.clib_compiler.has_header('Python.h', '', environment, extra_args=self.compile_args): + self.is_found = False + + def find_libpy(self, environment: 'Environment') -> None: + if self.is_pypy: + if self.major_version == 3: + libname = 'pypy3-c' + else: + libname = 'pypy-c' + libdir = os.path.join(self.variables.get('base'), 'bin') + libdirs = [libdir] + else: + libname = f'python{self.version}' + if 'DEBUG_EXT' in self.variables: + libname += self.variables['DEBUG_EXT'] + if 'ABIFLAGS' in self.variables: + libname += self.variables['ABIFLAGS'] + libdirs = [] + + largs = self.clib_compiler.find_library(libname, environment, libdirs) + if largs is not None: + self.link_args = largs + self.is_found = True + + def get_windows_python_arch(self) -> T.Optional[str]: + if self.platform == 'mingw': + pycc = self.variables.get('CC') + if pycc.startswith('x86_64'): + return 'x86_64' + elif pycc.startswith(('i686', 'i386')): + return 'x86' + else: + mlog.log(f'MinGW Python built with unknown CC {pycc!r}, please file a bug') + return None + elif self.platform == 'win32': + return 'x86' + elif self.platform in {'win64', 'win-amd64'}: + return 'x86_64' + elif self.platform in {'win-arm64'}: + return 'aarch64' + mlog.log(f'Unknown Windows Python platform {self.platform!r}') + return None + + def get_windows_link_args(self) -> T.Optional[T.List[str]]: + if self.platform.startswith('win'): + vernum = self.variables.get('py_version_nodot') + verdot = self.variables.get('py_version_short') + imp_lower = self.variables.get('implementation_lower', 'python') + if self.static: + libpath = Path('libs') / f'libpython{vernum}.a' + else: + comp = self.get_compiler() + if comp.id == "gcc": + if imp_lower == 'pypy' and verdot == '3.8': + # The naming changed between 3.8 and 3.9 + libpath = Path('libpypy3-c.dll') + elif imp_lower == 'pypy': + libpath = Path(f'libpypy{verdot}-c.dll') + else: + libpath = Path(f'python{vernum}.dll') + else: + libpath = Path('libs') / f'python{vernum}.lib' + # For a debug build, pyconfig.h may force linking with + # pythonX_d.lib (see meson#10776). This cannot be avoided + # and won't work unless we also have a debug build of + # Python itself (except with pybind11, which has an ugly + # hack to work around this) - so emit a warning to explain + # the cause of the expected link error. + buildtype = self.env.coredata.get_option(mesonlib.OptionKey('buildtype')) + assert isinstance(buildtype, str) + debug = self.env.coredata.get_option(mesonlib.OptionKey('debug')) + # `debugoptimized` buildtype may not set debug=True currently, see gh-11645 + is_debug_build = debug or buildtype == 'debug' + vscrt_debug = False + if mesonlib.OptionKey('b_vscrt') in self.env.coredata.options: + vscrt = self.env.coredata.options[mesonlib.OptionKey('b_vscrt')].value + if vscrt in {'mdd', 'mtd', 'from_buildtype', 'static_from_buildtype'}: + vscrt_debug = True + if is_debug_build and vscrt_debug and not self.variables.get('Py_DEBUG'): + mlog.warning(textwrap.dedent('''\ + Using a debug build type with MSVC or an MSVC-compatible compiler + when the Python interpreter is not also a debug build will almost + certainly result in a failed build. Prefer using a release build + type or a debug Python interpreter. + ''')) + # 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: '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() + if pyarch is None: + self.is_found = False + return + arch = detect_cpu_family(env.coredata.compilers.host) + if arch != pyarch: + mlog.log('Need', mlog.bold(self.name), f'for {arch}, but found {pyarch}') + self.is_found = False + return + # This can fail if the library is not found + largs = self.get_windows_link_args() + if largs is None: + self.is_found = False + return + self.link_args = largs + self.is_found = True + + @staticmethod + def log_tried() -> str: + return 'sysconfig' + +def python_factory(env: 'Environment', for_machine: 'MachineChoice', + kwargs: T.Dict[str, T.Any], + installation: T.Optional['BasicPythonExternalProgram'] = None) -> T.List['DependencyGenerator']: + # We can't use the factory_methods decorator here, as we need to pass the + # extra installation argument + methods = process_method_kw({DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM}, kwargs) + embed = kwargs.get('embed', False) + candidates: T.List['DependencyGenerator'] = [] + from_installation = installation is not None + # When not invoked through the python module, default installation. + if installation is None: + installation = BasicPythonExternalProgram('python3', mesonlib.python_command) + installation.sanity() + pkg_version = installation.info['variables'].get('LDVERSION') or installation.info['version'] + + if DependencyMethods.PKGCONFIG in methods: + if from_installation: + pkg_libdir = installation.info['variables'].get('LIBPC') + pkg_embed = '-embed' if embed and mesonlib.version_compare(installation.info['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: 'BasicPythonExternalProgram') -> 'ExternalDependency': + if not pkg_libdir: + # there is no LIBPC, so we can't search in it + empty = ExternalDependency(DependencyTypeName('pkgconfig'), env, {}) + empty.name = 'python' + return empty + + old_pkg_libdir = os.environ.pop('PKG_CONFIG_LIBDIR', None) + old_pkg_path = os.environ.pop('PKG_CONFIG_PATH', None) + os.environ['PKG_CONFIG_LIBDIR'] = pkg_libdir + try: + return PythonPkgConfigDependency(name, env, kwargs, installation, True) + finally: + def set_env(name: str, value: str) -> None: + 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.append(functools.partial(wrap_in_pythons_pc_dir, pkg_name, env, kwargs, installation)) + # We only need to check both, if a python install has a LIBPC. It might point to the wrong location, + # e.g. relocated / cross compilation, but the presence of LIBPC indicates we should definitely look for something. + if pkg_libdir is not None: + candidates.append(functools.partial(PythonPkgConfigDependency, pkg_name, env, kwargs, installation)) + else: + candidates.append(functools.partial(PkgConfigDependency, 'python3', env, kwargs)) + + 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 + +packages['python3'] = python_factory + +packages['pybind11'] = pybind11_factory = DependencyFactory( + 'pybind11', + [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.CMAKE], + configtool_class=Pybind11ConfigToolDependency, +) diff -Nru meson-1.0.1/mesonbuild/dependencies/qt.py meson-1.2.1/mesonbuild/dependencies/qt.py --- meson-1.0.1/mesonbuild/dependencies/qt.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/qt.py 2023-06-28 14:48:20.000000000 +0000 @@ -24,6 +24,7 @@ from .base import DependencyException, DependencyMethods from .configtool import ConfigToolDependency +from .detect import packages from .framework import ExtraFrameworkDependency from .pkgconfig import PkgConfigDependency from .factory import DependencyFactory @@ -105,9 +106,10 @@ class QtExtraFrameworkDependency(ExtraFrameworkDependency): - def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None): + def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], qvars: T.Dict[str, str], language: T.Optional[str] = None): super().__init__(name, env, kwargs, language=language) self.mod_name = name[2:] + self.qt_extra_include_directory = qvars['QT_INSTALL_HEADERS'] def get_compile_args(self, with_private_headers: bool = False, qt_version: str = "0") -> T.List[str]: if self.found(): @@ -115,6 +117,8 @@ 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)] + if self.qt_extra_include_directory: + args += ['-I' + self.qt_extra_include_directory] return args return [] @@ -252,15 +256,15 @@ """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.tool_name = f'qmake{self.qtver}' self.tools = [f'qmake{self.qtver}', f'qmake-{self.name}', '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 + # any version requirements 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() @@ -325,7 +329,7 @@ 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 + mesonlib.listify(libdir)) # TODO: shouldn't be necessary if libfiles: libfile = libfiles[0] else: @@ -361,7 +365,7 @@ for m in modules: fname = 'Qt' + m mlog.debug('Looking for qt framework ' + fname) - fwdep = QtExtraFrameworkDependency(fname, self.env, fw_kwargs, language=self.language) + fwdep = QtExtraFrameworkDependency(fname, self.env, fw_kwargs, qvars, 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, @@ -464,21 +468,21 @@ return _qt_get_private_includes(mod_inc_dir, module, self.version) -qt4_factory = DependencyFactory( +packages['qt4'] = qt4_factory = DependencyFactory( 'qt4', [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL], pkgconfig_class=Qt4PkgConfigDependency, configtool_class=Qt4ConfigToolDependency, ) -qt5_factory = DependencyFactory( +packages['qt5'] = qt5_factory = DependencyFactory( 'qt5', [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL], pkgconfig_class=Qt5PkgConfigDependency, configtool_class=Qt5ConfigToolDependency, ) -qt6_factory = DependencyFactory( +packages['qt6'] = qt6_factory = DependencyFactory( 'qt6', [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL], pkgconfig_class=Qt6PkgConfigDependency, diff -Nru meson-1.0.1/mesonbuild/dependencies/scalapack.py meson-1.2.1/mesonbuild/dependencies/scalapack.py --- meson-1.0.1/mesonbuild/dependencies/scalapack.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/scalapack.py 2023-08-07 22:54:34.000000000 +0000 @@ -22,6 +22,7 @@ from .base import DependencyMethods from .base import DependencyException from .cmake import CMakeDependency +from .detect import packages from .pkgconfig import PkgConfigDependency from .factory import factory_methods @@ -52,6 +53,8 @@ return candidates +packages['scalapack'] = scalapack_factory + class MKLPkgConfigDependency(PkgConfigDependency): diff -Nru meson-1.0.1/mesonbuild/dependencies/ui.py meson-1.2.1/mesonbuild/dependencies/ui.py --- meson-1.0.1/mesonbuild/dependencies/ui.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/dependencies/ui.py 2023-06-28 14:48:20.000000000 +0000 @@ -29,6 +29,7 @@ from .base import DependencyException, DependencyMethods, DependencyTypeName, SystemDependency from .configtool import ConfigToolDependency +from .detect import packages from .factory import DependencyFactory if T.TYPE_CHECKING: @@ -45,12 +46,20 @@ self.link_args = ['-framework', 'OpenGL'] # FIXME: Detect version using self.clib_compiler return - if self.env.machines[self.for_machine].is_windows(): + elif self.env.machines[self.for_machine].is_windows(): self.is_found = True # FIXME: Use self.clib_compiler.find_library() self.link_args = ['-lopengl32'] # FIXME: Detect version using self.clib_compiler return + else: + links = self.clib_compiler.find_library('GL', environment, []) + has_header = self.clib_compiler.has_header('GL/gl.h', '', environment)[0] + if links and has_header: + self.is_found = True + self.link_args = links + elif links: + raise DependencyException('Found GL runtime library but no development header files') class GnuStepDependency(ConfigToolDependency): @@ -128,6 +137,8 @@ version = '1' return version +packages['gnustep'] = GnuStepDependency + class SDL2DependencyConfigTool(ConfigToolDependency): @@ -179,6 +190,7 @@ raise DependencyException('wxwidgets module argument is not a string') return candidates +packages['wxwidgets'] = WxDependency class VulkanDependencySystem(SystemDependency): @@ -236,19 +248,20 @@ self.link_args.append(lib) return -gl_factory = DependencyFactory( +packages['gl'] = gl_factory = DependencyFactory( 'gl', [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM], system_class=GLDependencySystem, ) -sdl2_factory = DependencyFactory( +packages['sdl2'] = sdl2_factory = DependencyFactory( 'sdl2', - [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK], + [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK, DependencyMethods.CMAKE], configtool_class=SDL2DependencyConfigTool, + cmake_name='SDL2', ) -vulkan_factory = DependencyFactory( +packages['vulkan'] = vulkan_factory = DependencyFactory( 'vulkan', [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM], system_class=VulkanDependencySystem, diff -Nru meson-1.0.1/mesonbuild/envconfig.py meson-1.2.1/mesonbuild/envconfig.py --- meson-1.0.1/mesonbuild/envconfig.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/envconfig.py 2023-06-28 14:48:20.000000000 +0000 @@ -28,7 +28,7 @@ # and cross file currently), and also assists with the reading environment # variables. # -# At this time there isn't an ironclad difference between this an other sources +# At this time there isn't an ironclad difference between this and other sources # of state like `coredata`. But one rough guide is much what is in `coredata` is # the *output* of the configuration process: the final decisions after tests. # This, on the other hand has *inputs*. The config files are parsed, but @@ -167,7 +167,7 @@ return language + '_stdlib' in self.properties # Some of get_stdlib, get_root, get_sys_root are wider than is actually - # true, but without heterogenious dict annotations it's not practical to + # true, but without heterogeneous dict annotations it's not practical to # narrow them def get_stdlib(self, language: str) -> T.Union[str, T.List[str]]: stdlib = self.properties[language + '_stdlib'] @@ -237,6 +237,12 @@ value = T.cast('T.Optional[str]', self.properties.get('java_home')) return Path(value) if value else None + def get_bindgen_clang_args(self) -> T.List[str]: + value = mesonlib.listify(self.properties.get('bindgen_clang_arguments', [])) + if not all(isinstance(v, str) for v in value): + raise EnvironmentException('bindgen_clang_arguments must be a string or an array of strings') + return T.cast('T.List[str]', value) + def __eq__(self, other: object) -> bool: if isinstance(other, type(self)): return self.properties == other.properties @@ -260,6 +266,8 @@ cpu_family: str cpu: str endian: str + kernel: T.Optional[str] + subsystem: T.Optional[str] def __post_init__(self) -> None: self.is_64_bit: bool = self.cpu_family in CPU_FAMILIES_64_BIT @@ -283,7 +291,11 @@ if endian not in ('little', 'big'): mlog.warning(f'Unknown endian {endian}') - return cls(literal['system'], cpu_family, literal['cpu'], endian) + system = literal['system'] + kernel = literal.get('kernel', None) + subsystem = literal.get('subsystem', None) + + return cls(system, cpu_family, literal['cpu'], endian, kernel, subsystem) def is_windows(self) -> bool: """ @@ -351,6 +363,12 @@ """ return self.system == 'gnu' + def is_aix(self) -> bool: + """ + Machine is aix? + """ + return self.system == 'aix' + def is_irix(self) -> bool: """Machine is IRIX?""" return self.system.startswith('irix') diff -Nru meson-1.0.1/mesonbuild/environment.py meson-1.2.1/mesonbuild/environment.py --- meson-1.0.1/mesonbuild/environment.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/environment.py 2023-08-07 22:54:34.000000000 +0000 @@ -157,6 +157,8 @@ # unless it becomes a stable release. suffixes = [ '', # base (no suffix) + '-16', '16', + '-15', '15', '-14', '14', '-13', '13', '-12', '12', @@ -337,6 +339,11 @@ # AIX always returns powerpc, check here for 64-bit if any_compiler_has_define(compilers, '__64BIT__'): trial = 'ppc64' + # MIPS64 is able to run MIPS32 code natively, so there is a chance that + # such mixture mentioned above exists. + elif trial == 'mips64': + if compilers and not any_compiler_has_define(compilers, '__mips64'): + trial = 'mips' if trial not in known_cpu_families: mlog.warning(f'Unknown CPU family {trial!r}, please report this at ' @@ -375,7 +382,10 @@ if '64' not in trial: trial = 'mips' else: - trial = 'mips64' + if compilers and not any_compiler_has_define(compilers, '__mips64'): + trial = 'mips' + else: + trial = 'mips64' elif trial == 'ppc': # AIX always returns powerpc, check here for 64-bit if any_compiler_has_define(compilers, '__64BIT__'): @@ -385,6 +395,38 @@ # detect_cpu_family() above. return trial +KERNEL_MAPPINGS: T.Mapping[str, str] = {'freebsd': 'freebsd', + 'openbsd': 'openbsd', + 'netbsd': 'netbsd', + 'windows': 'nt', + 'android': 'linux', + 'linux': 'linux', + 'cygwin': 'nt', + 'darwin': 'xnu', + 'dragonfly': 'dragonfly', + 'haiku': 'haiku', + } + +def detect_kernel(system: str) -> T.Optional[str]: + if system == 'sunos': + # This needs to be /usr/bin/uname because gnu-uname could be installed and + # won't provide the necessary information + p, out, _ = Popen_safe(['/usr/bin/uname', '-o']) + if p.returncode != 0: + raise MesonException('Failed to run "/usr/bin/uname -o"') + out = out.lower().strip() + if out not in {'illumos', 'solaris'}: + mlog.warning(f'Got an unexpected value for kernel on a SunOS derived platform, expcted either "illumos" or "solaris", but got "{out}".' + "Please open a Meson issue with the OS you're running and the value detected for your kernel.") + return None + return out + return KERNEL_MAPPINGS.get(system, None) + +def detect_subsystem(system: str) -> T.Optional[str]: + if system == 'darwin': + return 'macos' + return system + def detect_system() -> str: if sys.platform == 'cygwin': return 'cygwin' @@ -401,11 +443,14 @@ underlying ''detect_*'' method can be called to explicitly use the partial information. """ + system = detect_system() return MachineInfo( - detect_system(), + system, detect_cpu_family(compilers) if compilers is not None else None, detect_cpu(compilers) if compilers is not None else None, - sys.byteorder) + sys.byteorder, + detect_kernel(system), + detect_subsystem(system)) # TODO make this compare two `MachineInfo`s purely. How important is the # `detect_cpu_family({})` distinction? It is the one impediment to that. @@ -423,6 +468,7 @@ return \ (machine_info.cpu_family == true_build_cpu_family) or \ ((true_build_cpu_family == 'x86_64') and (machine_info.cpu_family == 'x86')) or \ + ((true_build_cpu_family == 'mips64') and (machine_info.cpu_family == 'mips')) or \ ((true_build_cpu_family == 'aarch64') and (machine_info.cpu_family == 'arm')) class Environment: @@ -456,7 +502,7 @@ # If we stored previous command line options, we can recover from # a broken/outdated coredata. if os.path.isfile(coredata.get_cmd_line_file(self.build_dir)): - mlog.warning('Regenerating configuration from scratch.') + mlog.warning('Regenerating configuration from scratch.', fatal=False) mlog.log('Reason:', mlog.red(str(e))) coredata.read_cmd_line_file(self.build_dir, options) self.create_new_coredata(options) @@ -552,7 +598,8 @@ 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') + 'See: https://mesonbuild.com/Builtin-options.html#build-type-options', + fatal=False) exe_wrapper = self.lookup_binary_entry(MachineChoice.HOST, 'exe_wrapper') if exe_wrapper is not None: @@ -671,7 +718,7 @@ # 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 + # have subtly different behavior. `$CFLAGS` will be # added to the linker command line if the compiler # acts as a linker driver, `-Dc_args` will not. # @@ -827,7 +874,7 @@ def get_datadir(self) -> str: return self.coredata.get_option(OptionKey('datadir')) - def get_compiler_system_dirs(self, for_machine: MachineChoice): + def get_compiler_system_lib_dirs(self, for_machine: MachineChoice): for comp in self.coredata.compilers[for_machine].values(): if comp.id == 'clang': index = 1 @@ -846,6 +893,18 @@ out = out.split('\n')[index].lstrip('libraries: =').split(':') return [os.path.normpath(p) for p in out] + def get_compiler_system_include_dirs(self, for_machine: MachineChoice): + for comp in self.coredata.compilers[for_machine].values(): + if comp.id == 'clang': + break + elif comp.id == 'gcc': + break + else: + # This option is only supported by gcc and clang. If we don't get a + # GCC or Clang compiler return and empty list. + return [] + return comp.get_default_include_dirs() + def need_exe_wrapper(self, for_machine: MachineChoice = MachineChoice.HOST): value = self.properties[for_machine].get('needs_exe_wrapper', None) if value is not None: diff -Nru meson-1.0.1/mesonbuild/interpreter/compiler.py meson-1.2.1/mesonbuild/interpreter/compiler.py --- meson-1.0.1/mesonbuild/interpreter/compiler.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/interpreter/compiler.py 2023-08-07 22:54:34.000000000 +0000 @@ -1,11 +1,13 @@ -# SPDX-Licnese-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team # Copyright © 2021 Intel Corporation from __future__ import annotations +import collections import enum import functools import os +import itertools import typing as T from .. import build @@ -28,6 +30,7 @@ from ..compilers import Compiler, RunResult from ..interpreterbase import TYPE_var, TYPE_kwargs from .kwargs import ExtractRequired, ExtractSearchDirs + from .interpreter.interpreter import SourceOutputs from typing_extensions import TypedDict, Literal @@ -57,7 +60,7 @@ args: T.List[str] dependencies: T.List[dependencies.Dependency] - class CompupteIntKW(CommonKW): + class ComputeIntKW(CommonKW): guess: T.Optional[int] high: T.Optional[int] @@ -85,6 +88,7 @@ output: str compile_args: T.List[str] include_directories: T.List[build.IncludeDirs] + dependencies: T.List[dependencies.Dependency] class _TestMode(enum.Enum): @@ -163,6 +167,8 @@ _HEADER_KWS: T.List[KwargInfo] = [REQUIRED_KW.evolve(since='0.50.0', default=False), *_COMMON_KWS] class CompilerHolder(ObjectHolder['Compiler']): + preprocess_uid: T.Dict[str, itertools.count] = collections.defaultdict(itertools.count) + def __init__(self, compiler: 'Compiler', interpreter: 'Interpreter'): super().__init__(compiler, interpreter) self.environment = self.env @@ -267,10 +273,12 @@ def alignment_method(self, args: T.Tuple[str], kwargs: 'AlignmentKw') -> int: typename = args[0] deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=self.compiler.is_cross) - 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) + result, cached = self.compiler.alignment(typename, kwargs['prefix'], self.environment, + extra_args=kwargs['args'], + dependencies=deps) + cached_msg = mlog.blue('(cached)') if cached else '' + mlog.log('Checking for alignment of', + mlog.bold(typename, True), msg, mlog.bold(str(result)), cached_msg) return result @typed_pos_args('compiler.run', (str, mesonlib.File)) @@ -397,7 +405,7 @@ KwargInfo('guess', (int, NoneType)), *_COMMON_KWS, ) - def compute_int_method(self, args: T.Tuple[str], kwargs: 'CompupteIntKW') -> int: + def compute_int_method(self, args: T.Tuple[str], kwargs: 'ComputeIntKW') -> 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'], compile_only=self.compiler.is_cross) @@ -414,9 +422,11 @@ 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'], compile_only=self.compiler.is_cross) - 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) + esize, cached = self.compiler.sizeof(element, kwargs['prefix'], self.environment, + extra_args=extra_args, dependencies=deps) + cached_msg = mlog.blue('(cached)') if cached else '' + mlog.log('Checking for size of', + mlog.bold(element, True), msg, mlog.bold(str(esize)), cached_msg) return esize @FeatureNew('compiler.get_define', '0.40.0') @@ -438,9 +448,12 @@ def compiles_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool: code = args[0] if isinstance(code, mesonlib.File): + if code.is_built: + FeatureNew.single_use('compiler.compiles with file created at setup time', '1.2.0', self.subproject, + 'It was broken and either errored or returned false.', self.current_node) self.interpreter.add_build_def_file(code) code = mesonlib.File.from_absolute_file( - code.rel_to_builddir(self.environment.source_dir)) + code.absolute_path(self.environment.source_dir, self.environment.build_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) @@ -462,9 +475,12 @@ code = args[0] compiler = None if isinstance(code, mesonlib.File): + if code.is_built: + FeatureNew.single_use('compiler.links with file created at setup time', '1.2.0', self.subproject, + 'It was broken and either errored or returned false.', self.current_node) self.interpreter.add_build_def_file(code) code = mesonlib.File.from_absolute_file( - code.rel_to_builddir(self.environment.source_dir)) + code.absolute_path(self.environment.source_dir, self.environment.build_dir)) suffix = code.suffix if suffix not in self.compiler.file_suffixes: for_machine = self.compiler.for_machine @@ -750,30 +766,38 @@ return self.compiler.get_argument_syntax() @FeatureNew('compiler.preprocess', '0.64.0') - @typed_pos_args('compiler.preprocess', varargs=(mesonlib.File, str), min_varargs=1) + @typed_pos_args('compiler.preprocess', varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList), min_varargs=1) @typed_kwargs( 'compiler.preprocess', KwargInfo('output', str, default='@PLAINNAME@.i'), KwargInfo('compile_args', ContainerTypeInfo(list, str), listify=True, default=[]), _INCLUDE_DIRS_KW, + _DEPENDENCIES_KW.evolve(since='1.1.0'), ) def preprocess_method(self, args: T.Tuple[T.List['mesonlib.FileOrString']], kwargs: 'PreprocessKW') -> T.List[build.CustomTargetIndex]: compiler = self.compiler.get_preprocessor() - sources = self.interpreter.source_strings_to_files(args[0]) - tg_kwargs = { - f'{self.compiler.language}_args': kwargs['compile_args'], - 'build_by_default': False, - 'include_directories': kwargs['include_directories'], - } + sources: 'SourceOutputs' = self.interpreter.source_strings_to_files(args[0]) + if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in sources): + FeatureNew.single_use('compiler.preprocess with generated sources', '1.1.0', self.subproject, + location=self.current_node) + + tg_counter = next(self.preprocess_uid[self.interpreter.subdir]) + if tg_counter > 0: + FeatureNew.single_use('compiler.preprocess used multiple times', '1.1.0', self.subproject, + location=self.current_node) + tg_name = f'preprocessor_{tg_counter}' tg = build.CompileTarget( - 'preprocessor', + tg_name, self.interpreter.subdir, self.subproject, self.environment, sources, kwargs['output'], compiler, - tg_kwargs) + self.interpreter.backend, + kwargs['compile_args'], + kwargs['include_directories'], + kwargs['dependencies']) self.interpreter.add_target(tg.name, tg) # Expose this target as list of its outputs, so user can pass them to # other targets, list outputs, etc. diff -Nru meson-1.0.1/mesonbuild/interpreter/dependencyfallbacks.py meson-1.2.1/mesonbuild/interpreter/dependencyfallbacks.py --- meson-1.0.1/mesonbuild/interpreter/dependencyfallbacks.py 2022-10-24 19:25:24.000000000 +0000 +++ meson-1.2.1/mesonbuild/interpreter/dependencyfallbacks.py 2023-06-28 14:48:20.000000000 +0000 @@ -19,7 +19,7 @@ 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: + default_options: T.Optional[T.Dict[OptionKey, str]] = None) -> None: super().__init__(subproject=interpreter.subproject) self.interpreter = interpreter self.subproject = interpreter.subproject @@ -30,7 +30,7 @@ self.allow_fallback = allow_fallback self.subproject_name: T.Optional[str] = None self.subproject_varname: T.Optional[str] = None - self.subproject_kwargs = {'default_options': default_options or []} + self.subproject_kwargs = {'default_options': default_options or {}} self.names: T.List[str] = [] self.forcefallback: bool = False self.nofallback: bool = False @@ -114,12 +114,11 @@ # 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_options = func_kwargs.get('default_options', {}) + if static is not None and 'default_library' not 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) + mlog.log(f'Building fallback subproject with default_library={default_library}') + default_options[OptionKey('default_library')] = default_library func_kwargs['default_options'] = default_options # Configure the subproject @@ -220,6 +219,8 @@ mlog.log('Dependency', mlog.bold(self._display_name), 'found:', mlog.red('NO'), *info) return cached_dep + elif self.forcefallback and self.subproject_name: + cached_dep = None else: info = [mlog.blue('(cached)')] cached_dep = self.coredata.deps[for_machine].get(identifier) diff -Nru meson-1.0.1/mesonbuild/interpreter/interpreter.py meson-1.2.1/mesonbuild/interpreter/interpreter.py --- meson-1.0.1/mesonbuild/interpreter/interpreter.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/interpreter/interpreter.py 2023-08-07 22:54:34.000000000 +0000 @@ -23,8 +23,9 @@ 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, PerMachine) +from ..mesonlib import (MesonBugException, MesonException, HoldableObject, + FileMode, MachineChoice, OptionKey, listify, + extract_as_list, has_path_sep, PerMachine) from ..programs import ExternalProgram, NonExistingExternalProgram from ..dependencies import Dependency from ..depfile import DepFile @@ -32,10 +33,9 @@ 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 import FeatureNew, FeatureDeprecated, FeatureBroken, FeatureNewKwargs, FeatureDeprecatedKwargs +from ..interpreterbase import ObjectHolder, ContextManagerObject from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule -from ..cmake import CMakeInterpreter from ..backend.backends import ExecutableSerialisation from . import interpreterobjects as OBJ @@ -79,6 +79,7 @@ INSTALL_TAG_KW, LANGUAGE_KW, NATIVE_KW, + OVERRIDE_OPTIONS_KW, PRESERVE_PATH_KW, REQUIRED_KW, SOURCES_KW, @@ -122,6 +123,8 @@ build.BuildTarget, build.CustomTargetIndex, build.CustomTarget, build.ExtractedObjects, build.GeneratedList, build.StructuredSources] + BuildTargetSource = T.Union[mesonlib.FileOrString, build.GeneratedTypes, build.StructuredSources] + def _project_version_validator(value: T.Union[T.List, str, mesonlib.File, None]) -> T.Optional[str]: if isinstance(value, list): @@ -232,7 +235,7 @@ generate a Meson AST via introspection, etc. ''' - ALLOW_BUILD_DIR_FILE_REFFERENCES = 1 + ALLOW_BUILD_DIR_FILE_REFERENCES = 1 permitted_dependency_kwargs = { 'allow_fallback', @@ -288,7 +291,6 @@ # 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') self.relaxations = relaxations or set() if not mock and ast is None: self.load_root_meson_file() @@ -414,6 +416,8 @@ }) if 'MESON_UNIT_TEST' in os.environ: self.funcs.update({'exception': self.func_exception}) + if 'MESON_RUNNING_IN_PROJECT_TESTS' in os.environ: + self.funcs.update({'expect_error': self.func_expect_error}) def build_holder_map(self) -> None: ''' @@ -521,6 +525,25 @@ else: raise InterpreterException(f'Module returned a value of unknown type {v!r}.') + def handle_meson_version(self, pv: str, location: mparser.BaseNode) -> None: + if not mesonlib.version_compare(coredata.stable_version, pv): + raise InterpreterException.from_node(f'Meson version is {coredata.version} but project requires {pv}', node=location) + mesonlib.project_meson_versions[self.subproject] = pv + + def handle_meson_version_from_ast(self) -> None: + if not self.ast.lines: + return + project = self.ast.lines[0] + # first line is always project() + if not isinstance(project, mparser.FunctionNode): + return + for kw, val in project.args.kwargs.items(): + assert isinstance(kw, mparser.IdNode), 'for mypy' + if kw.value == 'meson_version': + # mypy does not understand "and isinstance" + if isinstance(val, mparser.StringNode): + self.handle_meson_version(val.value, val) + def get_build_def_files(self) -> mesonlib.OrderedSet[str]: return self.build_def_files @@ -668,15 +691,19 @@ LINK_WITH_KW, LINK_WHOLE_KW.evolve(since='0.46.0'), SOURCES_KW, + KwargInfo('extra_files', ContainerTypeInfo(list, (mesonlib.File, str)), listify=True, default=[], since='1.2.0'), VARIABLES_KW.evolve(since='0.54.0', since_values={list: '0.56.0'}), KwargInfo('version', (str, NoneType)), + KwargInfo('objects', ContainerTypeInfo(list, build.ExtractedObjects), listify=True, default=[], since='1.1.0'), ) def func_declare_dependency(self, node, args, kwargs): deps = kwargs['dependencies'] incs = self.extract_incdirs(kwargs) libs = kwargs['link_with'] libs_whole = kwargs['link_whole'] + objects = kwargs['objects'] sources = self.source_strings_to_files(kwargs['sources']) + extra_files = self.source_strings_to_files(kwargs['extra_files']) compile_args = kwargs['compile_args'] link_args = kwargs['link_args'] variables = kwargs['variables'] @@ -702,8 +729,9 @@ raise InterpreterException('Invalid dependency') dep = dependencies.InternalDependency(version, incs, compile_args, - link_args, libs, libs_whole, sources, deps, - variables, d_module_versions, d_import_dirs) + link_args, libs, libs_whole, sources, extra_files, + deps, variables, d_module_versions, d_import_dirs, + objects) return dep @typed_pos_args('assert', bool, optargs=[str]) @@ -776,7 +804,7 @@ progname = name break else: - raise MesonBugException('cmd was a built executable but not found in overrides table') + raise InterpreterException(f'Program {cmd.description()!r} is a compiled executable and therefore cannot be used during configuration') raise InterpreterException(overridden_msg.format(progname, cmd.description())) if isinstance(cmd, ExternalProgram): if not cmd.found(): @@ -862,7 +890,7 @@ mlog.log('Subproject', mlog.bold(subp_name), ':', 'skipped: feature', mlog.bold(feature), 'disabled') return self.disabled_subproject(subp_name, disabled_feature=feature) - default_options = coredata.create_options_dict(kwargs['default_options'], subp_name) + default_options = {k.evolve(subproject=subp_name): v for k, v in kwargs['default_options'].items()} if subp_name == '': raise InterpreterException('Subproject name must not be empty.') @@ -954,12 +982,9 @@ 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 - + with mlog.nested_warnings(): + subi.run() + subi_warnings = mlog.get_warning_count() mlog.log('Subproject', mlog.bold(subp_name), 'finished.') mlog.log() @@ -971,11 +996,12 @@ 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) + self.subprojects[subp_name] = SubprojectHolder(subi, subdir, warnings=subi_warnings, + callstack=self.subproject_stack) # Duplicates are possible when subproject uses files from project root if build_def_files: self.build_def_files.update(build_def_files) - # We always need the subi.build_def_files, to propgate sub-sub-projects + # We always need the subi.build_def_files, to propagate sub-sub-projects self.build_def_files.update(subi.build_def_files) self.build.merge(subi.build) self.build.subprojects[subp_name] = subi.project_version @@ -984,6 +1010,7 @@ def _do_subproject_cmake(self, subp_name: str, subdir: str, subdir_abs: str, default_options: T.Dict[OptionKey, str], kwargs: kwtypes.DoSubproject) -> SubprojectHolder: + from ..cmake import CMakeInterpreter with mlog.nested(subp_name): new_build = self.build.copy() prefix = self.coredata.options[OptionKey('prefix')].value @@ -1022,7 +1049,7 @@ [str(f) for f in cm_int.bs_files], is_translated=True, relaxations={ - InterpreterRuleRelaxation.ALLOW_BUILD_DIR_FILE_REFFERENCES, + InterpreterRuleRelaxation.ALLOW_BUILD_DIR_FILE_REFERENCES, } ) result.cm_interpreter = cm_int @@ -1101,21 +1128,30 @@ # 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 OptionKey('genvslite') in self.user_defined_options.cmd_line_options.keys(): + # Use of the '--genvslite vsxxxx' option ultimately overrides any '--backend xxx' + # option the user may specify. + backend_name = self.coredata.get_option(OptionKey('genvslite')) + self.backend = backends.get_genvslite_backend(backend_name, self.build, self) + else: + backend_name = self.coredata.get_option(OptionKey('backend')) + self.backend = backends.get_backend_from_name(backend_name, self.build, self) if self.backend is None: - raise InterpreterException(f'Unknown backend "{backend}".') - if backend != self.backend.name: + raise InterpreterException(f'Unknown backend "{backend_name}".') + if backend_name != 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) + if not self.environment.first_invocation: + raise MesonBugException(f'Backend changed from {backend_name} to {self.backend.name}') + self.coredata.set_option(OptionKey('backend'), self.backend.name, first_invocation=True) # 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) + self.coredata.init_backend_options(backend_name) options = {k: v for k, v in self.environment.options.items() if k.is_backend()} self.coredata.set_options(options) @@ -1132,7 +1168,8 @@ 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('license', (ContainerTypeInfo(list, str), NoneType), default=None, listify=True), + KwargInfo('license_files', ContainerTypeInfo(list, str), default=[], listify=True, since='1.1.0'), KwargInfo('subproject_dir', str, default='subprojects'), ) def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str]], kwargs: 'kwtypes.Project') -> None: @@ -1143,25 +1180,41 @@ # 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'] + self.handle_meson_version(kwargs['meson_version'], node) - if os.path.exists(self.option_file): + # Load "meson.options" before "meson_options.txt", and produce a warning if + # it is being used with an old version. I have added check that if both + # exist the warning isn't raised + option_file = os.path.join(self.source_root, self.subdir, 'meson.options') + old_option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt') + + if os.path.exists(option_file): + if os.path.exists(old_option_file): + if os.path.samefile(option_file, old_option_file): + mlog.debug("Not warning about meson.options with version minimum < 1.1 because meson_options.txt also exists") + else: + raise MesonException("meson.options and meson_options.txt both exist, but are not the same file.") + else: + FeatureNew.single_use('meson.options file', '1.1', self.subproject, 'Use meson_options.txt instead') + else: + option_file = old_option_file + if os.path.exists(option_file): oi = optinterpreter.OptionInterpreter(self.subproject) - oi.process(self.option_file) + oi.process(option_file) self.coredata.update_project_options(oi.options) - self.add_build_def_file(self.option_file) + self.add_build_def_file(option_file) + + if self.subproject: + self.project_default_options = {k.evolve(subproject=self.subproject): v + for k, v in kwargs['default_options'].items()} + else: + self.project_default_options = kwargs['default_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 = 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 @@ -1198,8 +1251,20 @@ 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 kwargs['license'] is None: + proj_license = ['unknown'] + if kwargs['license_files']: + raise InvalidArguments('Project `license` name must be specified when `license_files` is set') + else: + proj_license = kwargs['license'] + proj_license_files = [] + for i in self.source_strings_to_files(kwargs['license_files']): + ifname = i.absolute_path(self.environment.source_dir, + self.environment.build_dir) + proj_license_files.append((ifname, i)) + self.build.dep_manifest[proj_name] = build.DepManifest(self.project_version, proj_license, + proj_license_files, self.subproject) if self.subproject in self.build.projects: raise InvalidCode('Second call to project().') @@ -1238,9 +1303,9 @@ # 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 + vsenv = self.coredata.get_option(OptionKey('vsenv')) + force_vsenv = vsenv or backend.startswith('vs') + mesonlib.setup_vsenv(force_vsenv) self.add_languages(proj_langs, True, MachineChoice.HOST) self.add_languages(proj_langs, False, MachineChoice.BUILD) @@ -1312,16 +1377,19 @@ section, values, kwargs['bool_yn'], kwargs['list_sep'], self.subproject) def _print_summary(self) -> None: - # Add automatic 'Supbrojects' section in main project. + # Add automatic 'Subprojects' section in main project. all_subprojects = collections.OrderedDict() for name, subp in sorted(self.subprojects.items()): - value = subp.found() + value = [subp.found()] if subp.disabled_feature: - value = [value, f'Feature {subp.disabled_feature!r} disabled'] + value += [f'Feature {subp.disabled_feature!r} disabled'] elif subp.exception: - value = [value, str(subp.exception)] + value += [str(subp.exception)] elif subp.warnings > 0: - value = [value, f'{subp.warnings} warnings'] + value += [f'{subp.warnings} warnings'] + if subp.callstack: + stack = ' => '.join(subp.callstack) + value += [f'(from {stack})'] all_subprojects[name] = value if all_subprojects: self.summary_impl('Subprojects', all_subprojects, @@ -1377,6 +1445,24 @@ def func_exception(self, node, args, kwargs): raise RuntimeError('unit test traceback :)') + @noKwargs + @typed_pos_args('expect_error', str) + def func_expect_error(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: TYPE_kwargs) -> ContextManagerObject: + class ExpectErrorObject(ContextManagerObject): + def __init__(self, msg: str, subproject: str) -> None: + super().__init__(subproject) + self.msg = msg + + def __exit__(self, exc_type, exc_val, exc_tb): + if exc_val is None: + raise InterpreterException('Expecting an error but code block succeeded') + if isinstance(exc_val, mesonlib.MesonException): + msg = str(exc_val) + if msg != self.msg: + raise InterpreterException(f'Expecting error {self.msg!r} but got {msg!r}') + return True + return ExpectErrorObject(args[0], self.subproject) + def add_languages(self, args: T.List[str], required: bool, for_machine: MachineChoice) -> bool: success = self.add_languages_for(args, required, for_machine) if not self.coredata.is_cross_build(): @@ -1418,14 +1504,13 @@ comp = self.coredata.compilers[for_machine].get(lang) if not comp: try: - comp = compilers.detect_compiler_for(self.environment, lang, for_machine) + skip_sanity_check = self.should_skip_sanity_check(for_machine) + if skip_sanity_check: + mlog.log('Cross compiler sanity tests disabled via the cross file.', once=True) + comp = compilers.detect_compiler_for(self.environment, lang, for_machine, skip_sanity_check) 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: + except mesonlib.MesonException: if not required: mlog.log('Compiler for language', mlog.bold(lang), 'for the', machine_name, @@ -1592,6 +1677,10 @@ if progobj: return progobj + if args[0] == 'meson': + # Override find_program('meson') to return what we were invoked with + return ExternalProgram('meson', self.environment.get_build_command(), silent=True) + fallback = None wrap_mode = self.coredata.get_option(OptionKey('wrap_mode')) if wrap_mode != WrapMode.nofallback and self.environment.wrap_resolver: @@ -1617,7 +1706,7 @@ mlog.bold(' '.join(args))) sp_kwargs: kwtypes.DoSubproject = { 'required': required, - 'default_options': [], + 'default_options': {}, 'version': [], 'cmake_options': [], 'options': None, @@ -1662,10 +1751,10 @@ @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) + @typed_kwargs('dependency', DEFAULT_OPTIONS.evolve(since='0.38.0'), allow_unknown=True) def func_dependency(self, node: mparser.BaseNode, args: T.Tuple[T.List[str]], kwargs) -> Dependency: # Replace '' by empty list of names names = [n for n in args[0] if n] @@ -1716,39 +1805,72 @@ @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): + @typed_pos_args('executable', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('executable', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_executable(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> build.Executable: return self.build_target(node, args, kwargs, build.Executable) @permittedKwargs(build.known_stlib_kwargs) - def func_static_lib(self, node, args, kwargs): + @typed_pos_args('static_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('static_library', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_static_lib(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> build.StaticLibrary: return self.build_target(node, args, kwargs, build.StaticLibrary) @permittedKwargs(build.known_shlib_kwargs) - def func_shared_lib(self, node, args, kwargs): + @typed_pos_args('shared_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('shared_library', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_shared_lib(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> build.SharedLibrary: 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): + @typed_pos_args('both_libraries', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('both_libraries', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_both_lib(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> build.BothLibraries: 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): + @typed_pos_args('shared_module', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('shared_module', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_shared_module(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> build.SharedModule: return self.build_target(node, args, kwargs, build.SharedModule) @permittedKwargs(known_library_kwargs) - def func_library(self, node, args, kwargs): + @typed_pos_args('library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('library', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_library(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> build.Executable: return self.build_library(node, args, kwargs) @permittedKwargs(build.known_jar_kwargs) - def func_jar(self, node, args, kwargs): + @typed_pos_args('jar', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('jar', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_jar(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[T.Union[str, mesonlib.File, build.GeneratedTypes]]], + kwargs) -> build.Jar: 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): + @typed_pos_args('build_target', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('build_target', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_build_target(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary, + build.SharedModule, build.BothLibraries, build.Jar]: if 'target_type' not in kwargs: raise InterpreterException('Missing target_type keyword argument') target_type = kwargs.pop('target_type') @@ -1901,7 +2023,7 @@ build_by_default = kwargs['build_always'] build_always_stale = kwargs['build_by_default'] - # These are are nullaable so that we can know whether they're explicitly + # These are nullable 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 build_by_default is None: @@ -1923,9 +2045,9 @@ command[0] = self.find_program_impl([command[0]]) if len(inputs) > 1 and kwargs['feed']: - raise InvalidArguments('custom_target: "feed" keyword argument can only be used used with a single input') + raise InvalidArguments('custom_target: "feed" keyword argument can only be used with a single input') if len(kwargs['output']) > 1 and kwargs['capture']: - raise InvalidArguments('custom_target: "capture" keyword argument can only be used used with a single output') + raise InvalidArguments('custom_target: "capture" keyword argument can only be used with a single output') if kwargs['capture'] and kwargs['console']: raise InvalidArguments('custom_target: "capture" and "console" keyword arguments are mutually exclusive') for c in command: @@ -2274,7 +2396,7 @@ 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}'") + raise InterpreterException(f"Nonexistent build file '{buildfilename!s}'") with open(absname, encoding='utf-8') as f: code = f.read() assert isinstance(code, str) @@ -2398,7 +2520,7 @@ exclude = (set(kwargs['exclude_files']), set(kwargs['exclude_directories'])) srcdir = os.path.join(self.environment.source_dir, self.subdir, args[0]) - if not os.path.isdir(srcdir) or not any(os.scandir(srcdir)): + if not os.path.isdir(srcdir) or not any(os.listdir(srcdir)): FeatureNew.single_use('install_subdir with empty directory', '0.47.0', self.subproject, location=node) FeatureDeprecated.single_use('install_subdir with empty directory', '0.60.0', self.subproject, 'It worked by accident and is buggy. Use install_emptydir instead.', node) @@ -2533,7 +2655,7 @@ file_encoding = kwargs['encoding'] missing_variables, confdata_useless = \ mesonlib.do_conf_file(inputs_abs[0], ofile_abs, conf, - fmt, file_encoding) + fmt, file_encoding, self.subproject) if missing_variables: var_list = ", ".join(repr(m) for m in sorted(missing_variables)) mlog.warning( @@ -2876,6 +2998,7 @@ mlog.log('Build targets in project:', mlog.bold(str(len(self.build.targets)))) FeatureNew.report(self.subproject) FeatureDeprecated.report(self.subproject) + FeatureBroken.report(self.subproject) if not self.is_subproject(): self.print_extra_warnings() self._print_summary() @@ -2894,10 +3017,12 @@ 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) + value = self.coredata.options[OptionKey('b_sanitize')].value + mlog.warning(textwrap.dedent(f'''\ + Trying to use {value} sanitizer on Clang with b_lundef. + This will probably not work. + Try setting b_lundef to false instead.'''), + location=self.current_node) # noqa: E128 # Check that the indicated file is within the same subproject # as we currently are. This is to stop people doing @@ -2936,7 +3061,7 @@ inputtype = 'directory' else: inputtype = 'file' - if InterpreterRuleRelaxation.ALLOW_BUILD_DIR_FILE_REFFERENCES in self.relaxations and builddir in norm.parents: + if InterpreterRuleRelaxation.ALLOW_BUILD_DIR_FILE_REFERENCES in self.relaxations and builddir in norm.parents: return if srcdir not in norm.parents: # Grabbing files outside the source tree is ok. @@ -2960,7 +3085,7 @@ 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[mesonlib.FileOrString, build.GeneratedTypes]) -> T.List[T.Union[mesonlib.File, build.GeneratedTypes]]: ... # noqa: F811 + def source_strings_to_files(self, sources: T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]]) -> T.List[T.Union[mesonlib.File, build.GeneratedTypes]]: ... # noqa: F811 @T.overload def source_strings_to_files(self, sources: T.List['SourceInputs'], strict: bool = True) -> T.List['SourceOutputs']: ... # noqa: F811 @@ -3010,6 +3135,8 @@ "internal use. Please rename.") def add_target(self, name: str, tobj: build.Target) -> None: + if self.backend.name == 'none': + raise InterpreterException('Install-only backend cannot generate target rules, try using `--backend=ninja`.') if name == '': raise InterpreterException('Target name must not be empty.') if name.strip() == '': @@ -3030,9 +3157,8 @@ raise InvalidCode(f'Tried to create target "{name}", but a target of that name already exists.') if isinstance(tobj, build.BuildTarget): - missing_languages = tobj.process_compilers() - self.add_languages(missing_languages, True, tobj.for_machine) - tobj.process_compilers_late(missing_languages) + self.add_languages(tobj.missing_languages, True, tobj.for_machine) + tobj.process_compilers_late() self.add_stdlib_info(tobj) self.build.targets[idname] = tobj @@ -3044,14 +3170,6 @@ shared_lib = self.build_target(node, args, kwargs, build.SharedLibrary) static_lib = self.build_target(node, args, kwargs, build.StaticLibrary) - # 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 @@ -3061,7 +3179,7 @@ # issue for you. reuse_object_files = False else: - reuse_object_files = pic + reuse_object_files = static_lib.pic if reuse_object_files: # Replace sources with objects from the shared library to avoid @@ -3089,6 +3207,7 @@ raise InterpreterException(f'Unknown default_library value: {default_library}.') def build_target(self, node: mparser.BaseNode, args, kwargs, targetclass): + @FeatureNewKwargs('build target', '1.2.0', ['rust_dependency_map']) @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.38.0', ['build_by_default']) @@ -3098,12 +3217,22 @@ build_target_decorator_caller(self, node, args, kwargs) - if not args: - raise InterpreterException('Target does not have a name.') - name, *sources = args + name, sources = args for_machine = self.machine_from_native_kwarg(kwargs) if 'sources' in kwargs: sources += listify(kwargs['sources']) + if any(isinstance(s, build.BuildTarget) for s in sources): + FeatureBroken.single_use('passing references to built targets as a source file', '1.1.0', self.subproject, + 'Consider using `link_with` or `link_whole` if you meant to link, or dropping them as otherwise they are ignored.', + node) + if any(isinstance(s, build.ExtractedObjects) for s in sources): + FeatureBroken.single_use('passing object files as sources', '1.1.0', self.subproject, + 'Pass these to the `objects` keyword instead, they are ignored when passed as sources.', + node) + # Go ahead and drop these here, since they're only allowed through for + # backwards compatibility anyway + sources = [s for s in sources + if not isinstance(s, (build.BuildTarget, build.ExtractedObjects))] sources = self.source_strings_to_files(sources) objs = extract_as_list(kwargs, 'objects') kwargs['dependencies'] = extract_as_list(kwargs, 'dependencies') @@ -3155,7 +3284,6 @@ kwargs['include_directories'] = self.extract_incdirs(kwargs) target = targetclass(name, self.subdir, self.subproject, for_machine, srcs, struct, objs, self.environment, self.compilers[for_machine], kwargs) - target.project_version = self.project_version self.add_target(name, target) self.project_args_frozen = True diff -Nru meson-1.0.1/mesonbuild/interpreter/interpreterobjects.py meson-1.2.1/mesonbuild/interpreter/interpreterobjects.py --- meson-1.0.1/mesonbuild/interpreter/interpreterobjects.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/interpreter/interpreterobjects.py 2023-08-07 22:54:34.000000000 +0000 @@ -41,6 +41,8 @@ separator: str +_ERROR_MSG_KW: KwargInfo[T.Optional[str]] = KwargInfo('error_message', (str, NoneType)) + def extract_required_kwarg(kwargs: 'kwargs.ExtractRequired', subproject: 'SubProject', @@ -97,6 +99,9 @@ 'auto': self.auto_method, 'require': self.require_method, 'disable_auto_if': self.disable_auto_if_method, + 'enable_auto_if': self.enable_auto_if_method, + 'disable_if': self.disable_if_method, + 'enable_if': self.enable_if_method, }) @property @@ -108,6 +113,11 @@ disabled.value = 'disabled' return disabled + def as_enabled(self) -> coredata.UserFeatureOption: + enabled = copy.deepcopy(self.held_object) + enabled.value = 'enabled' + return enabled + @noPosargs @noKwargs def enabled_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: @@ -129,22 +139,51 @@ def auto_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: return self.value == 'auto' + def _disable_if(self, condition: bool, message: T.Optional[str]) -> coredata.UserFeatureOption: + if not condition: + return copy.deepcopy(self.held_object) + + if self.value == 'enabled': + err_msg = f'Feature {self.held_object.name} cannot be enabled' + if message: + err_msg += f': {message}' + raise InterpreterException(err_msg) + return self.as_disabled() + @FeatureNew('feature_option.require()', '0.59.0') @typed_pos_args('feature_option.require', bool) @typed_kwargs( 'feature_option.require', - KwargInfo('error_message', (str, NoneType)) + _ERROR_MSG_KW, ) def require_method(self, args: T.Tuple[bool], kwargs: 'kwargs.FeatureOptionRequire') -> coredata.UserFeatureOption: - if args[0]: + return self._disable_if(not args[0], kwargs['error_message']) + + @FeatureNew('feature_option.disable_if()', '1.1.0') + @typed_pos_args('feature_option.disable_if', bool) + @typed_kwargs( + 'feature_option.disable_if', + _ERROR_MSG_KW, + ) + def disable_if_method(self, args: T.Tuple[bool], kwargs: 'kwargs.FeatureOptionRequire') -> coredata.UserFeatureOption: + return self._disable_if(args[0], kwargs['error_message']) + + @FeatureNew('feature_option.enable_if()', '1.1.0') + @typed_pos_args('feature_option.enable_if', bool) + @typed_kwargs( + 'feature_option.enable_if', + _ERROR_MSG_KW, + ) + def enable_if_method(self, args: T.Tuple[bool], kwargs: 'kwargs.FeatureOptionRequire') -> coredata.UserFeatureOption: + if not args[0]: return copy.deepcopy(self.held_object) - if self.value == 'enabled': - err_msg = f'Feature {self.held_object.name} cannot be enabled' + if self.value == 'disabled': + err_msg = f'Feature {self.held_object.name} cannot be disabled' if kwargs['error_message']: err_msg += f': {kwargs["error_message"]}' raise InterpreterException(err_msg) - return self.as_disabled() + return self.as_enabled() @FeatureNew('feature_option.disable_auto_if()', '0.59.0') @noKwargs @@ -152,6 +191,12 @@ def disable_auto_if_method(self, args: T.Tuple[bool], kwargs: TYPE_kwargs) -> coredata.UserFeatureOption: return copy.deepcopy(self.held_object) if self.value != 'auto' or not args[0] else self.as_disabled() + @FeatureNew('feature_option.enable_auto_if()', '1.1.0') + @noKwargs + @typed_pos_args('feature_option.enable_auto_if', bool) + def enable_auto_if_method(self, args: T.Tuple[bool], kwargs: TYPE_kwargs) -> coredata.UserFeatureOption: + return self.as_enabled() if self.value == 'auto' and args[0] else copy.deepcopy(self.held_object) + class RunProcess(MesonInterpreterObject): @@ -594,6 +639,8 @@ 'cpu': self.cpu_method, 'cpu_family': self.cpu_family_method, 'endian': self.endian_method, + 'kernel': self.kernel_method, + 'subsystem': self.subsystem_method, }) @noPosargs @@ -616,6 +663,21 @@ def endian_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: return self.held_object.endian + @noPosargs + @noKwargs + def kernel_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + if self.held_object.kernel is not None: + return self.held_object.kernel + raise InterpreterException('Kernel not defined or could not be autodetected.') + + @noPosargs + @noKwargs + def subsystem_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + if self.held_object.subsystem is not None: + return self.held_object.subsystem + raise InterpreterException('Subsystem not defined or could not be autodetected.') + + class IncludeDirsHolder(ObjectHolder[build.IncludeDirs]): pass @@ -686,7 +748,8 @@ subdir: str, warnings: int = 0, disabled_feature: T.Optional[str] = None, - exception: T.Optional[Exception] = None) -> None: + exception: T.Optional[Exception] = None, + callstack: T.Optional[T.List[str]] = None) -> None: super().__init__() self.held_object = subinterpreter self.warnings = warnings @@ -694,6 +757,7 @@ self.exception = exception self.subdir = PurePath(subdir).as_posix() self.cm_interpreter: T.Optional[CMakeInterpreter] = None + self.callstack = callstack self.methods.update({'get_variable': self.get_variable_method, 'found': self.found_method, }) @@ -840,6 +904,9 @@ @noPosargs @noKwargs + @FeatureDeprecated('BuildTarget.get_id', '1.2.0', + 'This was never formally documented and does not seem to have a real world use. ' + + 'See https://github.com/mesonbuild/meson/pull/6061') def get_id_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: return self._target_object.get_id() diff -Nru meson-1.0.1/mesonbuild/interpreter/kwargs.py meson-1.2.1/mesonbuild/interpreter/kwargs.py --- meson-1.0.1/mesonbuild/interpreter/kwargs.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/interpreter/kwargs.py 2023-08-07 22:54:34.000000000 +0000 @@ -12,7 +12,7 @@ from .. import build from .. import coredata from ..compilers import Compiler -from ..mesonlib import MachineChoice, File, FileMode, FileOrString +from ..mesonlib import MachineChoice, File, FileMode, FileOrString, OptionKey from ..modules.cmake import CMakeSubprojectOptions from ..programs import ExternalProgram @@ -57,7 +57,7 @@ """Keyword Arguments for `test` - `test` only adds the `is_prallel` argument over benchmark, so inherintance + `test` only adds the `is_parallel` argument over benchmark, so inheritance is helpful here. """ @@ -203,7 +203,7 @@ version: T.Optional[FileOrString] meson_version: T.Optional[str] - default_options: T.List[str] + default_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] license: T.List[str] subproject_dir: str @@ -298,13 +298,13 @@ class Subproject(ExtractRequired): - default_options: T.List[str] + default_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] version: T.List[str] class DoSubproject(ExtractRequired): - default_options: T.List[str] + default_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] version: T.List[str] cmake_options: T.List[str] options: T.Optional[CMakeSubprojectOptions] diff -Nru meson-1.0.1/mesonbuild/interpreter/mesonmain.py meson-1.2.1/mesonbuild/interpreter/mesonmain.py --- meson-1.0.1/mesonbuild/interpreter/mesonmain.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/interpreter/mesonmain.py 2023-08-07 22:54:34.000000000 +0000 @@ -1,6 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team # Copyright © 2021 Intel Corporation +from __future__ import annotations import os import typing as T @@ -8,7 +9,7 @@ from .. import mesonlib from .. import dependencies from .. import build -from .. import mlog +from .. import mlog, coredata from ..mesonlib import MachineChoice, OptionKey from ..programs import OverrideProgram, ExternalProgram @@ -37,6 +38,7 @@ skip_if_destdir: bool install_tag: str + dry_run: bool class NativeKW(TypedDict): @@ -52,35 +54,37 @@ 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, + self.methods.update({'add_devenv': self.add_devenv_method, + 'add_dist_script': self.add_dist_script_method, + 'add_install_script': self.add_install_script_method, + 'add_postconf_script': self.add_postconf_script_method, + 'backend': self.backend_method, + 'build_options': self.build_options_method, + 'build_root': self.build_root_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, + 'get_compiler': self.get_compiler_method, + 'get_cross_property': self.get_cross_property_method, + 'get_external_property': self.get_external_property_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, + 'global_source_root': self.global_source_root_method, + 'has_exe_wrapper': self.has_exe_wrapper_method, + 'has_external_property': self.has_external_property_method, 'install_dependency_manifest': self.install_dependency_manifest_method, + 'is_cross_build': self.is_cross_build_method, + 'is_subproject': self.is_subproject_method, + 'is_unity': self.is_unity_method, 'override_dependency': self.override_dependency_method, 'override_find_program': self.override_find_program_method, - 'project_version': self.project_version_method, + 'project_build_root': self.project_build_root_method, 'project_license': self.project_license_method, - 'version': self.version_method, + 'project_license_files': self.project_license_files_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, + 'project_source_root': self.project_source_root_method, + 'project_version': self.project_version_method, + 'source_root': self.source_root_method, + 'version': self.version_method, }) def _find_source_script( @@ -100,7 +104,7 @@ largs.append(found) largs.extend(args) - es = self.interpreter.backend.get_executable_serialisation(largs) + es = self.interpreter.backend.get_executable_serialisation(largs, verbose=True) es.subproject = self.interpreter.subproject return es @@ -150,6 +154,7 @@ 'meson.add_install_script', KwargInfo('skip_if_destdir', bool, default=False, since='0.57.0'), KwargInfo('install_tag', (str, NoneType), since='0.60.0'), + KwargInfo('dry_run', bool, default=False, since='1.1.0'), ) def add_install_script_method( self, @@ -160,6 +165,7 @@ 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'] + script.dry_run = kwargs['dry_run'] self.build.install_scripts.append(script) @typed_pos_args( @@ -371,7 +377,7 @@ 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 + # which FuncOverrideDependency is, but mypy can't figure that out nkwargs = T.cast('T.Dict[str, T.Any]', kwargs.copy()) if static is None: del nkwargs['static'] @@ -400,6 +406,12 @@ 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 + @FeatureNew('meson.project_license_files()', '1.1.0') + @noPosargs + @noKwargs + def project_license_files_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[mesonlib.File]: + return [l[1] for l in self.build.dep_manifest[self.interpreter.active_projectname].license_files] + @noPosargs @noKwargs def version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> MesonVersionString: @@ -454,3 +466,12 @@ converted = env_convertor_with_method(env, kwargs['method'], kwargs['separator']) assert isinstance(converted, build.EnvironmentVariables) self.build.devenv.append(converted) + + @noPosargs + @noKwargs + @FeatureNew('meson.build_options', '1.1.0') + def build_options_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + options = self.interpreter.user_defined_options + if options is None: + return '' + return coredata.format_cmd_line_options(options) diff -Nru meson-1.0.1/mesonbuild/interpreter/primitives/integer.py meson-1.2.1/mesonbuild/interpreter/primitives/integer.py --- meson-1.0.1/mesonbuild/interpreter/primitives/integer.py 2022-06-19 19:10:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/interpreter/primitives/integer.py 2023-06-28 14:48:20.000000000 +0000 @@ -3,13 +3,8 @@ from __future__ import annotations from ...interpreterbase import ( - ObjectHolder, - MesonOperator, - typed_operator, - noKwargs, - noPosargs, - - InvalidArguments + FeatureBroken, InvalidArguments, MesonOperator, ObjectHolder, + noKwargs, noPosargs, typed_operator, ) import typing as T @@ -53,6 +48,13 @@ def display_name(self) -> str: return 'int' + def operator_call(self, operator: MesonOperator, other: TYPE_var) -> TYPE_var: + if isinstance(other, bool): + FeatureBroken.single_use('int operations with non-int', '1.2.0', self.subproject, + 'It is not commutative and only worked because of leaky Python abstractions.', + location=self.current_node) + return super().operator_call(operator, other) + @noKwargs @noPosargs def is_even_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: diff -Nru meson-1.0.1/mesonbuild/interpreter/primitives/string.py meson-1.2.1/mesonbuild/interpreter/primitives/string.py --- meson-1.0.1/mesonbuild/interpreter/primitives/string.py 2022-12-10 16:38:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/interpreter/primitives/string.py 2023-08-07 22:54:34.000000000 +0000 @@ -38,6 +38,7 @@ 'join': self.join_method, 'replace': self.replace_method, 'split': self.split_method, + 'splitlines': self.splitlines_method, 'strip': self.strip_method, 'substring': self.substring_method, 'to_int': self.to_int_method, @@ -105,11 +106,18 @@ return re.sub(r'@(\d+)@', arg_replace, self.held_object) @noKwargs + @noPosargs + @FeatureNew('str.splitlines', '1.2.0') + def splitlines_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]: + return self.held_object.splitlines() + + @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 + @FeatureNew('str.replace', '0.58.0') @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]) @@ -122,9 +130,12 @@ @noKwargs @typed_pos_args('str.strip', optargs=[str]) def strip_method(self, args: T.Tuple[T.Optional[str]], kwargs: TYPE_kwargs) -> str: + if args[0]: + FeatureNew.single_use('str.strip with a positional argument', '0.43.0', self.subproject, location=self.current_node) return self.held_object.strip(args[0]) @noKwargs + @FeatureNew('str.substring', '0.56.0') @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 diff -Nru meson-1.0.1/mesonbuild/interpreter/type_checking.py meson-1.2.1/mesonbuild/interpreter/type_checking.py --- meson-1.0.1/mesonbuild/interpreter/type_checking.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/interpreter/type_checking.py 2023-08-07 22:54:34.000000000 +0000 @@ -13,7 +13,6 @@ BothLibraries, SharedLibrary, StaticLibrary, Jar, Executable) from ..coredata import UserFeatureOption from ..dependencies import Dependency, InternalDependency -from ..interpreterbase import FeatureNew from ..interpreterbase.decorators import KwargInfo, ContainerTypeInfo from ..mesonlib import (File, FileMode, MachineChoice, listify, has_path_sep, OptionKey, EnvironmentVariables) @@ -26,7 +25,6 @@ from typing_extensions import Literal from ..interpreterbase import TYPE_var - from ..interpreterbase.decorators import FeatureCheckBase from ..mesonlib import EnvInitValueType _FullEnvInitValueType = T.Union[EnvironmentVariables, T.List[str], T.List[T.List[str]], EnvInitValueType, str, None] @@ -89,23 +87,27 @@ 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' + return 'second component 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 'third component 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` + """Convert the DSL form of the `install_mode` keyword argument to `FileMode`""" - This is not required, and if not required returns None + if not mode: + return FileMode() - 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)) + # This has already been validated by the validator. False denotes "use + # default". mypy is totally incapable of understanding it, because + # generators clobber types via homogeneous return. But also we *must* + # convert the first element different from the rest + m1 = mode[0] if isinstance(mode[0], str) else None + rest = (m if isinstance(m, (str, int)) else None for m in mode[1:]) + + return FileMode(m1, *rest) def _lower_strlist(input: T.List[str]) -> T.List[str]: @@ -182,7 +184,7 @@ 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], - allow_dict_list: bool = True) -> T.Optional[str]: + only_dict_str: bool = True) -> T.Optional[str]: def _splitter(v: str) -> T.Optional[str]: split = v.split('=', 1) if len(split) == 1: @@ -203,18 +205,21 @@ elif isinstance(value, dict): # We don't need to spilt here, just do the type checking for k, dv in value.items(): - if allow_dict_list: + if only_dict_str: if any(i for i in listify(dv) if not isinstance(i, str)): return f"Dictionary element {k} must be a string or list of strings not {dv!r}" - elif not isinstance(dv, str): - return f"Dictionary element {k} must be a string not {dv!r}" + elif isinstance(dv, list): + if any(not isinstance(i, str) for i in dv): + return f"Dictionary element {k} must be a string, bool, integer or list of strings, not {dv!r}" + elif not isinstance(dv, (str, bool, int)): + return f"Dictionary element {k} must be a string, bool, integer or list of strings, not {dv!r}" # We know that otherwise we have an EnvironmentVariables object or None, and # we're okay at this point return None def _options_validator(value: T.Union[EnvironmentVariables, T.List['TYPE_var'], T.Dict[str, 'TYPE_var'], str, None]) -> T.Optional[str]: - # Reusing the env validator is a littl overkill, but nicer than duplicating the code - return _env_validator(value, allow_dict_list=False) + # Reusing the env validator is a little overkill, but nicer than duplicating the code + return _env_validator(value, only_dict_str=False) def split_equal_string(input: str) -> T.Tuple[str, str]: """Split a string in the form `x=y` @@ -279,25 +284,36 @@ 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 +def _override_options_convertor(raw: T.Union[str, T.List[str], T.Dict[str, T.Union[str, int, bool, T.List[str]]]]) -> T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]]: + if isinstance(raw, str): + raw = [raw] + if isinstance(raw, list): + output: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] = {} + for each in raw: + k, v = split_equal_string(each) + output[OptionKey.from_string(k)] = v + return output + return {OptionKey.from_string(k): v for k, v in raw.items()} -OVERRIDE_OPTIONS_KW: KwargInfo[T.List[str]] = KwargInfo( +OVERRIDE_OPTIONS_KW: KwargInfo[T.Union[str, T.Dict[str, T.Union[str, int, bool, T.List[str]]], T.List[str]]] = KwargInfo( 'override_options', - ContainerTypeInfo(list, str), - listify=True, - default=[], + (str, ContainerTypeInfo(list, str), ContainerTypeInfo(dict, (str, int, bool, list))), + default={}, validator=_options_validator, convertor=_override_options_convertor, + since_values={dict: '1.2.0'}, ) def _output_validator(outputs: T.List[str]) -> T.Optional[str]: + output_set = set(outputs) + if len(output_set) != len(outputs): + seen = set() + for el in outputs: + if el in seen: + return f"contains {el!r} multiple times, but no duplicates are allowed." + seen.add(el) for i in outputs: if i == '': return 'Output must not be empty.' @@ -376,21 +392,7 @@ default=[], ) -def include_dir_string_new(val: T.List[T.Union[str, IncludeDirs]]) -> T.Iterable[FeatureCheckBase]: - strs = [v for v in val if isinstance(v, str)] - if strs: - str_msg = ", ".join(f"'{s}'" for s in strs) - yield FeatureNew('include_directories kwarg of type string', '1.0.0', - f'Use include_directories({str_msg}) instead') - -# for cases like default_options and override_options -DEFAULT_OPTIONS: KwargInfo[T.List[str]] = KwargInfo( - 'default_options', - ContainerTypeInfo(list, str), - listify=True, - default=[], - validator=_options_validator, -) +DEFAULT_OPTIONS = OVERRIDE_OPTIONS_KW.evolve(name='default_options') ENV_METHOD_KW = KwargInfo('method', str, default='set', since='0.62.0', validator=in_set_validator({'set', 'prepend', 'append'})) diff -Nru meson-1.0.1/mesonbuild/interpreterbase/__init__.py meson-1.2.1/mesonbuild/interpreterbase/__init__.py --- meson-1.0.1/mesonbuild/interpreterbase/__init__.py 2022-06-19 19:10:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/interpreterbase/__init__.py 2023-08-07 22:54:34.000000000 +0000 @@ -18,6 +18,7 @@ 'ObjectHolder', 'IterableObject', 'MutableInterpreterObject', + 'ContextManagerObject', 'MesonOperator', @@ -52,6 +53,7 @@ 'FeatureCheckBase', 'FeatureNew', 'FeatureDeprecated', + 'FeatureBroken', 'FeatureNewKwargs', 'FeatureDeprecatedKwargs', @@ -80,6 +82,7 @@ ObjectHolder, IterableObject, MutableInterpreterObject, + ContextManagerObject, TV_fw_var, TV_fw_args, @@ -116,6 +119,7 @@ FeatureCheckBase, FeatureNew, FeatureDeprecated, + FeatureBroken, FeatureNewKwargs, FeatureDeprecatedKwargs, ) diff -Nru meson-1.0.1/mesonbuild/interpreterbase/baseobjects.py meson-1.2.1/mesonbuild/interpreterbase/baseobjects.py --- meson-1.0.1/mesonbuild/interpreterbase/baseobjects.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/interpreterbase/baseobjects.py 2023-08-07 22:54:24.000000000 +0000 @@ -22,6 +22,7 @@ import typing as T from abc import ABCMeta +from contextlib import AbstractContextManager if T.TYPE_CHECKING: from typing_extensions import Protocol @@ -118,12 +119,12 @@ # 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): + if type(self) is not type(other): self._throw_comp_exception(other, '==') return self == other def op_not_equals(self, other: TYPE_var) -> bool: - if type(self) != type(other): + if type(self) is not type(other): self._throw_comp_exception(other, '!=') return self != other @@ -156,12 +157,12 @@ # 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): + if type(self.held_object) is not 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): + if type(self.held_object) is not type(other): self._throw_comp_exception(other, '!=') return self.held_object != other @@ -180,3 +181,7 @@ def size(self) -> int: raise MesonBugException(f'size not implemented for {self.__class__.__name__}') + +class ContextManagerObject(MesonInterpreterObject, AbstractContextManager): + def __init__(self, subproject: 'SubProject') -> None: + super().__init__(subproject=subproject) diff -Nru meson-1.0.1/mesonbuild/interpreterbase/decorators.py meson-1.2.1/mesonbuild/interpreterbase/decorators.py --- meson-1.0.1/mesonbuild/interpreterbase/decorators.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/interpreterbase/decorators.py 2023-08-07 22:54:34.000000000 +0000 @@ -313,15 +313,25 @@ 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 any(not isinstance(i, self.contains) for i in iter_): + 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 check_any(self, value: T.Any) -> bool: + """Check a value should emit new/deprecated feature. + + :param value: A value to check + :return: True if any of the items in value matches, False otherwise + """ + if not isinstance(value, self.container): + return False + iter_ = iter(value.values()) if isinstance(value, dict) else iter(value) + return any(isinstance(i, self.contains) for i in iter_) + def description(self) -> str: """Human readable description of this container type. @@ -382,7 +392,6 @@ added in. :param not_set_warning: A warning message that is logged if the kwarg is not set by the user. - :param feature_validator: A callable returning an iterable of FeatureNew | FeatureDeprecated objects. """ def __init__(self, name: str, types: T.Union[T.Type[_T], T.Tuple[T.Union[T.Type[_T], ContainerTypeInfo], ...], ContainerTypeInfo], @@ -390,11 +399,10 @@ default: T.Optional[_T] = None, since: T.Optional[str] = None, since_message: T.Optional[str] = None, - since_values: T.Optional[T.Dict[T.Union[_T, T.Type[T.List], T.Type[T.Dict]], T.Union[str, T.Tuple[str, str]]]] = None, + since_values: T.Optional[T.Dict[T.Union[_T, ContainerTypeInfo, type], 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.Union[_T, T.Type[T.List], T.Type[T.Dict]], T.Union[str, T.Tuple[str, str]]]] = None, - feature_validator: T.Optional[T.Callable[[_T], T.Iterable[FeatureCheckBase]]] = None, + deprecated_values: T.Optional[T.Dict[T.Union[_T, ContainerTypeInfo, type], 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): @@ -406,7 +414,6 @@ self.since = since self.since_message = since_message self.since_values = since_values - self.feature_validator = feature_validator self.deprecated = deprecated self.deprecated_message = deprecated_message self.deprecated_values = deprecated_values @@ -421,11 +428,10 @@ 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.Union[_T, T.Type[T.List], T.Type[T.Dict]], T.Union[str, T.Tuple[str, str]]], None, _NULL_T] = _NULL, + since_values: T.Union[T.Dict[T.Union[_T, ContainerTypeInfo, type], 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.Union[_T, T.Type[T.List], T.Type[T.Dict]], T.Union[str, T.Tuple[str, str]]], None, _NULL_T] = _NULL, - feature_validator: T.Union[T.Callable[[_T], T.Iterable[FeatureCheckBase]], None, _NULL_T] = _NULL, + deprecated_values: T.Union[T.Dict[T.Union[_T, ContainerTypeInfo, type], 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. @@ -451,7 +457,6 @@ 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, - feature_validator=feature_validator if not isinstance(feature_validator, _NULL_T) else self.feature_validator, validator=validator if not isinstance(validator, _NULL_T) else self.validator, convertor=convertor if not isinstance(convertor, _NULL_T) else self.convertor, ) @@ -465,7 +470,7 @@ 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 + If type 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 @@ -512,23 +517,28 @@ def emit_feature_change(values: T.Dict[_T, T.Union[str, T.Tuple[str, str]]], feature: T.Union[T.Type['FeatureDeprecated'], T.Type['FeatureNew']]) -> None: for n, version in values.items(): - warn = False if isinstance(version, tuple): version, msg = version else: msg = None - if n in {dict, list}: - assert isinstance(n, type), 'for mypy' + warning: T.Optional[str] = None + if isinstance(n, ContainerTypeInfo): + if n.check_any(value): + warning = f'of type {n.description()}' + elif isinstance(n, type): if isinstance(value, n): - feature.single_use(f'"{name}" keyword argument "{info.name}" of type {n.__name__}', version, subproject, msg, location=node) - elif isinstance(value, (dict, list)): - warn = n in value - else: - warn = n == value - - if warn: - feature.single_use(f'"{name}" keyword argument "{info.name}" value "{n}"', version, subproject, msg, location=node) + warning = f'of type {n.__name__}' + elif isinstance(value, list): + if n in value: + warning = f'value "{n}" in list' + elif isinstance(value, dict): + if n in value.keys(): + warning = f'value "{n}" in dict keys' + elif n == value: + warning = f'value "{n}"' + if warning: + feature.single_use(f'"{name}" keyword argument "{info.name}" {warning}', 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 @@ -562,10 +572,6 @@ if msg is not None: raise InvalidArguments(f'{name} keyword argument "{info.name}" {msg}') - if info.feature_validator is not None: - for each in info.feature_validator(value): - each.use(subproject, node) - if info.deprecated_values is not None: emit_feature_change(info.deprecated_values, FeatureDeprecated) @@ -577,7 +583,7 @@ 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)}' + assert check_value_type(types_tuple, info.default), f'In function {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) @@ -598,6 +604,7 @@ feature_registry: T.ClassVar[T.Dict[str, T.Dict[str, T.Set[T.Tuple[str, T.Optional['mparser.BaseNode']]]]]] emit_notice = False + unconditional = False def __init__(self, feature_name: str, feature_version: str, extra_message: str = ''): self.feature_name = feature_name # type: str @@ -619,7 +626,7 @@ def use(self, subproject: 'SubProject', location: T.Optional['mparser.BaseNode'] = None) -> None: tv = self.get_target_version(subproject) # No target version - if tv == '': + if tv == '' and not self.unconditional: return # Target version is new enough, don't warn if self.check_version(tv, self.feature_version) and not self.emit_notice: @@ -652,10 +659,11 @@ fv = cls.feature_registry[subproject] tv = cls.get_target_version(subproject) for version in sorted(fv.keys()): + message = ', '.join(sorted({f"'{i[0]}'" for i in fv[version]})) if cls.check_version(tv, version): - notice_str += '\n * {}: {}'.format(version, {i[0] for i in fv[version]}) + notice_str += '\n * {}: {{{}}}'.format(version, message) else: - warning_str += '\n * {}: {}'.format(version, {i[0] for i in fv[version]}) + warning_str += '\n * {}: {{{}}}'.format(version, message) if '\n' in notice_str: mlog.notice(notice_str, fatal=False) if '\n' in warning_str: @@ -695,7 +703,7 @@ # 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]]]]]] + feature_registry = {} @staticmethod def check_version(target_version: str, feature_version: str) -> bool: @@ -726,7 +734,7 @@ # 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]]]]]] + feature_registry = {} emit_notice = True @staticmethod @@ -754,6 +762,40 @@ mlog.warning(*args, location=location) +class FeatureBroken(FeatureCheckBase): + """Checks for broken features""" + + # Class variable, shared across all instances + # + # Format: {subproject: {feature_version: set(feature_names)}} + feature_registry = {} + unconditional = True + + @staticmethod + def check_version(target_version: str, feature_version: str) -> bool: + # always warn for broken stuff + return False + + @staticmethod + def get_warning_str_prefix(tv: str) -> str: + return 'Broken features used:' + + @staticmethod + def get_notice_str_prefix(tv: str) -> str: + return '' + + def log_usage_warning(self, tv: str, location: T.Optional['mparser.BaseNode']) -> None: + args = [ + 'Project uses feature that was always broken,', + 'and is now deprecated since', + f"'{self.feature_version}':", + f'{self.feature_name}.', + ] + if self.extra_message: + args.append(self.extra_message) + mlog.deprecation(*args, location=location) + + # This cannot be a dataclass due to https://github.com/python/mypy/issues/5374 class FeatureCheckKwargsBase(metaclass=abc.ABCMeta): diff -Nru meson-1.0.1/mesonbuild/interpreterbase/interpreterbase.py meson-1.2.1/mesonbuild/interpreterbase/interpreterbase.py --- meson-1.0.1/mesonbuild/interpreterbase/interpreterbase.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/interpreterbase/interpreterbase.py 2023-08-07 22:54:34.000000000 +0000 @@ -16,8 +16,7 @@ # or an interpreter-based tool. from __future__ import annotations -from .. import mparser, mesonlib -from .. import environment +from .. import environment, mparser, mesonlib from .baseobjects import ( InterpreterObject, @@ -26,17 +25,19 @@ InterpreterObjectTypeVar, ObjectHolder, IterableObject, + ContextManagerObject, HoldableTypes, ) from .exceptions import ( + BreakRequest, + ContinueRequest, InterpreterException, - InvalidCode, InvalidArguments, + InvalidCode, + MesonException, SubdirDoneRequest, - ContinueRequest, - BreakRequest ) from .decorators import FeatureNew @@ -71,6 +72,13 @@ T.Callable[[mparser.BaseNode, T.List[TYPE_var], T.Dict[str, TYPE_var]], TYPE_var] ] + +class InvalidCodeOnVoid(InvalidCode): + + def __init__(self, op_type: str) -> None: + super().__init__(f'Cannot perform {op_type!r} operation on void statement.') + + class InterpreterBase: def __init__(self, source_root: str, subdir: str, subproject: 'SubProject'): self.source_root = source_root @@ -94,6 +102,10 @@ # current meson version target within that if-block. self.tmp_meson_version = None # type: T.Optional[str] + def handle_meson_version_from_ast(self, strict: bool = True) -> None: + # do nothing in an AST interpreter + return + 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): @@ -105,8 +117,13 @@ assert isinstance(code, str) try: self.ast = mparser.Parser(code, mesonfile).parse() - except mesonlib.MesonException as me: + self.handle_meson_version_from_ast() + except mparser.ParseException as me: me.file = mesonfile + # try to detect parser errors from new syntax added by future + # meson versions, and just tell the user to update meson + self.ast = me.ast + self.handle_meson_version_from_ast() raise me def parse_project(self) -> None: @@ -166,8 +183,9 @@ 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 + # NOTE: self.current_node is continually updated during processing + e.lineno = self.current_node.lineno # type: ignore + e.colno = self.current_node.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. @@ -223,6 +241,8 @@ raise ContinueRequest() elif isinstance(cur, mparser.BreakNode): raise BreakRequest() + elif isinstance(cur, mparser.TestCaseClauseNode): + return self.evaluate_testcase(cur) else: raise InvalidCode("Unknown statement.") return None @@ -238,7 +258,10 @@ 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)) + key_holder = self.evaluate_statement(key) + if key_holder is None: + raise InvalidArguments('Key cannot be void.') + str_key = _unholder(key_holder) if not isinstance(str_key, str): raise InvalidArguments('Key must be a string') return str_key @@ -248,6 +271,8 @@ def evaluate_notstatement(self, cur: mparser.NotNode) -> InterpreterObject: v = self.evaluate_statement(cur.value) + if v is None: + raise InvalidCodeOnVoid('not') if isinstance(v, Disabler): return v return self._holderify(v.operator_call(MesonOperator.NOT, None)) @@ -259,10 +284,12 @@ # statement evaluation. self.tmp_meson_version = None result = self.evaluate_statement(i.condition) + if result is None: + raise InvalidCodeOnVoid('if') 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__}.') + raise mesonlib.MesonBugException(f'Argument to if ({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.') @@ -279,11 +306,25 @@ self.evaluate_codeblock(node.elseblock) return None + def evaluate_testcase(self, node: mparser.TestCaseClauseNode) -> T.Optional[Disabler]: + result = self.evaluate_statement(node.condition) + if isinstance(result, Disabler): + return result + if not isinstance(result, ContextManagerObject): + raise InvalidCode(f'testcase clause {result!r} does not evaluate to a context manager.') + with result: + self.evaluate_codeblock(node.block) + return None + def evaluate_comparison(self, node: mparser.ComparisonNode) -> InterpreterObject: val1 = self.evaluate_statement(node.left) + if val1 is None: + raise MesonException('Cannot compare a void statement on the left-hand side') if isinstance(val1, Disabler): return val1 val2 = self.evaluate_statement(node.right) + if val2 is None: + raise MesonException('Cannot compare a void statement on the right-hand side') if isinstance(val2, Disabler): return val2 @@ -308,30 +349,40 @@ def evaluate_andstatement(self, cur: mparser.AndNode) -> InterpreterObject: l = self.evaluate_statement(cur.left) + if l is None: + raise MesonException('Cannot compare a void statement on the left-hand side') 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 r is None: + raise MesonException('Cannot compare a void statement on the right-hand side') 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 l is None: + raise MesonException('Cannot compare a void statement on the left-hand side') 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 r is None: + raise MesonException('Cannot compare a void statement on the right-hand side') 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 v is None: + raise InvalidCodeOnVoid('unary minus') if isinstance(v, Disabler): return v v.current_node = cur @@ -344,6 +395,8 @@ r = self.evaluate_statement(cur.right) if isinstance(r, Disabler): return r + if l is None or r is None: + raise InvalidCodeOnVoid(cur.operation) mapping: T.Dict[str, MesonOperator] = { 'add': MesonOperator.PLUS, @@ -359,6 +412,8 @@ def evaluate_ternary(self, node: mparser.TernaryNode) -> T.Optional[InterpreterObject]: assert isinstance(node, mparser.TernaryNode) result = self.evaluate_statement(node.condition) + if result is None: + raise MesonException('Cannot use a void statement as condition for ternary operator.') if isinstance(result, Disabler): return result result.current_node = node @@ -424,6 +479,8 @@ assert isinstance(node, mparser.PlusAssignmentNode) varname = node.var_name addition = self.evaluate_statement(node.value) + if addition is None: + raise InvalidCodeOnVoid('plus assign') # Remember that all variables are immutable. We must always create a # full new variable and then assign it. @@ -435,12 +492,15 @@ def evaluate_indexing(self, node: mparser.IndexNode) -> InterpreterObject: assert isinstance(node, mparser.IndexNode) iobject = self.evaluate_statement(node.iobject) + if iobject is None: + raise InterpreterException('Tried to evaluate indexing on void.') if isinstance(iobject, Disabler): return iobject - index = _unholder(self.evaluate_statement(node.index)) + index_holder = self.evaluate_statement(node.index) + if index_holder is None: + raise InvalidArguments('Cannot use void statement as index.') + index = _unholder(index_holder) - 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)) @@ -457,6 +517,7 @@ func_args = flatten(posargs) if not getattr(func, 'no-second-level-holder-flattening', False): func_args, kwargs = resolve_second_level_holders(func_args, kwargs) + self.current_node = node res = func(node, func_args, kwargs) return self._holderify(res) if res is not None else None else: @@ -464,14 +525,14 @@ return None def method_call(self, node: mparser.MethodNode) -> T.Optional[InterpreterObject]: - invokable = node.source_object + invocable = node.source_object obj: T.Optional[InterpreterObject] - if isinstance(invokable, mparser.IdNode): - object_display_name = f'variable "{invokable.value}"' - obj = self.get_variable(invokable.value) + if isinstance(invocable, mparser.IdNode): + object_display_name = f'variable "{invocable.value}"' + obj = self.get_variable(invocable.value) else: - object_display_name = invokable.__class__.__name__ - obj = self.evaluate_statement(invokable) + object_display_name = invocable.__class__.__name__ + obj = self.evaluate_statement(invocable) method_name = node.name (h_args, h_kwargs) = self.reduce_arguments(node.args) (args, kwargs) = self._unholder_args(h_args, h_kwargs) @@ -485,7 +546,7 @@ self.validate_extraction(obj.held_object) elif not isinstance(obj, Disabler): raise InvalidArguments(f'Invalid operation "extract_objects" on {object_display_name} of type {type(obj).__name__}') - obj.current_node = node + obj.current_node = self.current_node = node res = obj.method_call(method_name, args, kwargs) return self._holderify(res) if res is not None else None @@ -539,6 +600,7 @@ reduced_val = self.evaluate_statement(val) if reduced_val is None: raise InvalidArguments(f'Value of key {reduced_key} is void.') + self.current_node = key if duplicate_key_error and reduced_key in reduced_kw: raise InvalidArguments(duplicate_key_error.format(reduced_key)) reduced_kw[reduced_key] = reduced_val @@ -578,7 +640,7 @@ 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.') + raise InvalidCode('Can not assign void to variable.') if holderify: variable = self._holderify(variable) else: diff -Nru meson-1.0.1/mesonbuild/linkers/__init__.py meson-1.2.1/mesonbuild/linkers/__init__.py --- meson-1.0.1/mesonbuild/linkers/__init__.py 2022-10-24 19:25:24.000000000 +0000 +++ meson-1.2.1/mesonbuild/linkers/__init__.py 2023-06-28 14:48:20.000000000 +0000 @@ -12,125 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. + +from .base import ArLikeLinker, RSPFileSyntax from .detect import ( defaults, guess_win_linker, guess_nix_linker, ) -from .linkers import ( - RSPFileSyntax, - - StaticLinker, - VisualStudioLikeLinker, - VisualStudioLinker, - IntelVisualStudioLinker, - AppleArLinker, - ArLinker, - ArmarLinker, - DLinker, - CcrxLinker, - Xc16Linker, - CompCertLinker, - C2000Linker, - TILinker, - AIXArLinker, - PGIStaticLinker, - NvidiaHPC_StaticLinker, - - DynamicLinker, - PosixDynamicLinkerMixin, - GnuLikeDynamicLinkerMixin, - AppleDynamicLinker, - GnuDynamicLinker, - GnuGoldDynamicLinker, - GnuBFDDynamicLinker, - LLVMDynamicLinker, - MoldDynamicLinker, - WASMDynamicLinker, - CcrxDynamicLinker, - Xc16DynamicLinker, - CompCertDynamicLinker, - C2000DynamicLinker, - TIDynamicLinker, - ArmDynamicLinker, - ArmClangDynamicLinker, - QualcommLLVMDynamicLinker, - PGIDynamicLinker, - NvidiaHPC_DynamicLinker, - NAGDynamicLinker, - - VisualStudioLikeLinkerMixin, - MSVCDynamicLinker, - ClangClDynamicLinker, - XilinkDynamicLinker, - SolarisDynamicLinker, - AIXDynamicLinker, - OptlinkDynamicLinker, - CudaLinker, - - prepare_rpaths, - order_rpaths, - evaluate_rpath, -) __all__ = [ + # base.py + 'ArLikeLinker', + 'RSPFileSyntax', + # detect.py 'defaults', 'guess_win_linker', 'guess_nix_linker', - - # linkers.py - 'RSPFileSyntax', - - 'StaticLinker', - 'VisualStudioLikeLinker', - 'VisualStudioLinker', - 'IntelVisualStudioLinker', - 'ArLinker', - 'ArmarLinker', - 'DLinker', - 'CcrxLinker', - 'Xc16Linker', - 'CompCertLinker', - 'C2000Linker', - 'TILinker', - 'AIXArLinker', - 'AppleArLinker', - 'PGIStaticLinker', - 'NvidiaHPC_StaticLinker', - - 'DynamicLinker', - 'PosixDynamicLinkerMixin', - 'GnuLikeDynamicLinkerMixin', - 'AppleDynamicLinker', - 'GnuDynamicLinker', - 'GnuGoldDynamicLinker', - 'GnuBFDDynamicLinker', - 'LLVMDynamicLinker', - 'MoldDynamicLinker', - 'WASMDynamicLinker', - 'CcrxDynamicLinker', - 'Xc16DynamicLinker', - 'CompCertDynamicLinker', - 'C2000DynamicLinker', - 'TIDynamicLinker', - 'ArmDynamicLinker', - 'ArmClangDynamicLinker', - 'QualcommLLVMDynamicLinker', - 'PGIDynamicLinker', - 'NvidiaHPC_DynamicLinker', - 'NAGDynamicLinker', - - 'VisualStudioLikeLinkerMixin', - 'MSVCDynamicLinker', - 'ClangClDynamicLinker', - 'XilinkDynamicLinker', - 'SolarisDynamicLinker', - 'AIXDynamicLinker', - 'OptlinkDynamicLinker', - 'CudaLinker', - - 'prepare_rpaths', - 'order_rpaths', - 'evaluate_rpath', ] diff -Nru meson-1.0.1/mesonbuild/linkers/base.py meson-1.2.1/mesonbuild/linkers/base.py --- meson-1.0.1/mesonbuild/linkers/base.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/mesonbuild/linkers/base.py 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,50 @@ +# Copyright 2012-2023 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 + +# https://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. + +# Core public classes for linkers. +from __future__ import annotations + +import enum +import typing as T + +if T.TYPE_CHECKING: + from ..environment import Environment + + +@enum.unique +class RSPFileSyntax(enum.Enum): + + """Which RSP file syntax the compiler supports.""" + + MSVC = enum.auto() + GCC = enum.auto() + + +class ArLikeLinker: + # 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, env: 'Environment', 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 diff -Nru meson-1.0.1/mesonbuild/linkers/detect.py meson-1.2.1/mesonbuild/linkers/detect.py --- meson-1.0.1/mesonbuild/linkers/detect.py 2023-02-01 21:43:18.000000000 +0000 +++ meson-1.2.1/mesonbuild/linkers/detect.py 2023-07-21 20:36:13.000000000 +0000 @@ -17,21 +17,7 @@ from .. import mlog from ..mesonlib import ( EnvironmentException, - Popen_safe, join_args, search_version -) -from .linkers import ( - AppleDynamicLinker, - LLVMLD64DynamicLinker, - GnuGoldDynamicLinker, - GnuBFDDynamicLinker, - MoldDynamicLinker, - LLVMDynamicLinker, - QualcommLLVMDynamicLinker, - MSVCDynamicLinker, - ClangClDynamicLinker, - SolarisDynamicLinker, - AIXDynamicLinker, - OptlinkDynamicLinker, + Popen_safe, Popen_safe_logged, join_args, search_version ) import re @@ -62,6 +48,7 @@ comp_version: str, for_machine: MachineChoice, *, use_linker_prefix: bool = True, invoked_directly: bool = True, extra_args: T.Optional[T.List[str]] = None) -> 'DynamicLinker': + from . import linkers 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 @@ -86,27 +73,27 @@ p, o, _ = Popen_safe(compiler + check_args) if 'LLD' in o.split('\n', maxsplit=1)[0]: if '(compatible with GNU linkers)' in o: - return LLVMDynamicLinker( + return linkers.LLVMDynamicLinker( compiler, for_machine, comp_class.LINKER_PREFIX, override, version=search_version(o)) elif not invoked_directly: - return ClangClDynamicLinker( + return linkers.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 + # We've already handled the non-direct case above p, o, e = Popen_safe(compiler + check_args) if 'LLD' in o.split('\n', maxsplit=1)[0]: - return ClangClDynamicLinker( + return linkers.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: # Optlink's stdout *may* begin with a \r character. - return OptlinkDynamicLinker(compiler, for_machine, version=search_version(o)) + return linkers.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) @@ -115,7 +102,7 @@ else: target = 'x86' - return MSVCDynamicLinker( + return linkers.MSVCDynamicLinker( for_machine, [], machine=target, exelist=compiler, prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [], version=search_version(out), direct=invoked_directly) @@ -139,6 +126,7 @@ :for_machine: which machine this linker targets :extra_args: Any additional arguments required (such as a source file) """ + from . import linkers env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) extra_args = extra_args or [] @@ -157,11 +145,7 @@ check_args += override mlog.debug('-----') - mlog.debug(f'Detecting linker via: {join_args(compiler + check_args)}') - p, o, e = Popen_safe(compiler + check_args) - mlog.debug(f'linker returned {p}') - mlog.debug(f'linker stdout:\n{o}') - mlog.debug(f'linker stderr:\n{e}') + p, o, e = Popen_safe_logged(compiler + check_args, msg='Detecting linker via') v = search_version(o + e) linker: DynamicLinker @@ -170,22 +154,18 @@ cmd = compiler + override + [comp_class.LINKER_PREFIX + '-v'] + extra_args else: cmd = compiler + override + comp_class.LINKER_PREFIX + ['-v'] + extra_args - mlog.debug('-----') - mlog.debug(f'Detecting LLD linker via: {join_args(cmd)}') - _, newo, newerr = Popen_safe(cmd) - mlog.debug(f'linker stdout:\n{newo}') - mlog.debug(f'linker stderr:\n{newerr}') + _, newo, newerr = Popen_safe_logged(cmd, msg='Detecting LLD linker via') lld_cls: T.Type[DynamicLinker] if 'ld64.lld' in newerr: - lld_cls = LLVMLD64DynamicLinker + lld_cls = linkers.LLVMLD64DynamicLinker else: - lld_cls = LLVMDynamicLinker + lld_cls = linkers.LLVMDynamicLinker linker = lld_cls( compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) elif 'Snapdragon' in e and 'LLVM' in e: - linker = QualcommLLVMDynamicLinker( + linker = linkers.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, @@ -204,36 +184,32 @@ _, o, e = Popen_safe([linker_cmd, '--version']) v = search_version(o) - linker = LLVMDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) + linker = linkers.LLVMDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) # first might be 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): cmd = compiler + [comp_class.LINKER_PREFIX + '-v'] + extra_args else: cmd = compiler + comp_class.LINKER_PREFIX + ['-v'] + extra_args - mlog.debug('-----') - mlog.debug(f'Detecting Apple linker via: {join_args(cmd)}') - _, newo, newerr = Popen_safe(cmd) - mlog.debug(f'linker stdout:\n{newo}') - mlog.debug(f'linker stderr:\n{newerr}') + _, newo, newerr = Popen_safe_logged(cmd, msg='Detecting Apple linker via') for line in newerr.split('\n'): - if 'PROJECT:ld' in line: + if 'PROJECT:ld' in line or 'PROJECT:dyld' in line: v = line.split('-')[1] break else: __failed_to_detect_linker(compiler, check_args, o, e) - linker = AppleDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) + linker = linkers.AppleDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) elif 'GNU' in o or 'GNU' in e: gnu_cls: T.Type[GnuDynamicLinker] # this is always the only thing on stdout, except for swift # which may or may not redirect the linker stdout to stderr if o.startswith('GNU gold') or e.startswith('GNU gold'): - gnu_cls = GnuGoldDynamicLinker + gnu_cls = linkers.GnuGoldDynamicLinker elif o.startswith('mold') or e.startswith('mold'): - gnu_cls = MoldDynamicLinker + gnu_cls = linkers.MoldDynamicLinker else: - gnu_cls = GnuBFDDynamicLinker + gnu_cls = linkers.GnuBFDDynamicLinker linker = gnu_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'): @@ -242,7 +218,7 @@ break else: v = 'unknown version' - linker = SolarisDynamicLinker( + linker = linkers.SolarisDynamicLinker( compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) elif 'ld: 0706-012 The -- flag is not recognized' in e: @@ -250,7 +226,7 @@ _, _, 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( + linker = linkers.AIXDynamicLinker( compiler, for_machine, comp_class.LINKER_PREFIX, override, version=search_version(e)) else: diff -Nru meson-1.0.1/mesonbuild/linkers/linkers.py meson-1.2.1/mesonbuild/linkers/linkers.py --- meson-1.0.1/mesonbuild/linkers/linkers.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/linkers/linkers.py 2023-08-07 22:54:34.000000000 +0000 @@ -14,10 +14,11 @@ from __future__ import annotations import abc -import enum import os import typing as T +import re +from .base import ArLikeLinker, RSPFileSyntax from .. import mesonlib from ..mesonlib import EnvironmentException, MesonException from ..arglist import CompilerArgs @@ -28,15 +29,6 @@ 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 @@ -168,26 +160,7 @@ 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, env: 'Environment', 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): +class ArLinker(ArLikeLinker, StaticLinker): id = 'ar' def __init__(self, for_machine: mesonlib.MachineChoice, exelist: T.List[str]): @@ -227,7 +200,7 @@ id = 'applear' -class ArmarLinker(ArLikeLinker): +class ArmarLinker(ArLikeLinker, StaticLinker): id = 'armar' @@ -322,11 +295,33 @@ id = 'ar2000' -class AIXArLinker(ArLikeLinker): +class AIXArLinker(ArLikeLinker, StaticLinker): id = 'aixar' std_args = ['-csr', '-Xany'] +class MetrowerksStaticLinker(StaticLinker): + + def can_linker_accept_rsp(self) -> bool: + return True + + def get_linker_always_args(self) -> T.List[str]: + return ['-library'] + + def get_output_args(self, target: str) -> T.List[str]: + return ['-o', target] + + def rsp_file_syntax(self) -> RSPFileSyntax: + return RSPFileSyntax.GCC + + +class MetrowerksStaticLinkerARM(MetrowerksStaticLinker): + id = 'mwldarm' + + +class MetrowerksStaticLinkerEmbeddedPowerPC(MetrowerksStaticLinker): + id = 'mwldeppc' + 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 @@ -547,6 +542,14 @@ suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: return [] + def get_archive_name(self, filename: str) -> str: + #Only used by AIX. + return str() + + def get_command_to_archive_shlib(self) -> T.List[str]: + #Only used by AIX. + return [] + class PosixDynamicLinkerMixin: @@ -928,7 +931,7 @@ class CcrxDynamicLinker(DynamicLinker): - """Linker for Renesis CCrx compiler.""" + """Linker for Renesas CCrx compiler.""" id = 'rlink' @@ -1216,7 +1219,7 @@ class VisualStudioLikeLinkerMixin: - """Mixin class for for dynamic linkers that act like Microsoft's link.exe.""" + """Mixin class for dynamic linkers that act like Microsoft's link.exe.""" if T.TYPE_CHECKING: for_machine = MachineChoice.HOST @@ -1446,6 +1449,21 @@ def get_allow_undefined_args(self) -> T.List[str]: return self._apply_prefix(['-berok']) + def get_archive_name(self, filename: str) -> str: + # In AIX we allow the shared library name to have the lt_version and so_version. + # But the archive name must just be .a . + # For Example shared object can have the name libgio.so.0.7200.1 but the archive + # must have the name libgio.a having libgio.a (libgio.so.0.7200.1) in the + # archive. This regular expression is to do the same. + filename = re.sub('[.][a]([.]?([0-9]+))*([.]?([a-z]+))*', '.a', filename.replace('.so', '.a')) + return filename + + def get_command_to_archive_shlib(self) -> T.List[str]: + # Archive shared library object and remove the shared library object, + # since it already exists in the archive. + command = ['ar', '-q', '-v', '$out', '$in', '&&', 'rm', '-f', '$in'] + return command + def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: # AIX's linker always links the whole archive: "The ld command # processes all input files in the same manner, whether they are @@ -1465,9 +1483,9 @@ 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) + sys_path = env.get_compiler_system_lib_dirs(self.for_machine) if len(sys_path) == 0: - # get_compiler_system_dirs doesn't support our compiler. + # get_compiler_system_lib_dirs doesn't support our compiler. # Use the default system library path all_paths.update(['/usr/lib', '/lib']) else: @@ -1554,3 +1572,46 @@ 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 MetrowerksLinker(DynamicLinker): + + def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, + *, version: str = 'unknown version'): + super().__init__(exelist, for_machine, '', [], + version=version) + + def fatal_warnings(self) -> T.List[str]: + return ['-w', 'error'] + + def get_allow_undefined_args(self) -> T.List[str]: + return [] + + def get_accepts_rsp(self) -> bool: + return True + + def get_lib_prefix(self) -> str: + return "" + + def get_linker_always_args(self) -> T.List[str]: + return [] + + def get_output_args(self, target: str) -> T.List[str]: + return ['-o', target] + + def get_search_args(self, dirname: str) -> T.List[str]: + return self._apply_prefix('-L' + dirname) + + def invoked_by_compiler(self) -> bool: + return False + + def rsp_file_syntax(self) -> RSPFileSyntax: + return RSPFileSyntax.GCC + + +class MetrowerksLinkerARM(MetrowerksLinker): + id = 'mwldarm' + + +class MetrowerksLinkerEmbeddedPowerPC(MetrowerksLinker): + id = 'mwldeppc' diff -Nru meson-1.0.1/mesonbuild/mcompile.py meson-1.2.1/mesonbuild/mcompile.py --- meson-1.0.1/mesonbuild/mcompile.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/mcompile.py 2023-05-30 15:42:56.000000000 +0000 @@ -26,7 +26,6 @@ from . import mlog from . import mesonlib -from . import coredata from .mesonlib import MesonException, RealPathAction, join_args, setup_vsenv from mesonbuild.environment import detect_ninja from mesonbuild.coredata import UserArrayOption @@ -90,6 +89,7 @@ 'shared_library', 'shared_module', 'custom', + 'alias', 'run', 'jar', } @@ -108,11 +108,9 @@ 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)): + if ((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] @@ -121,7 +119,7 @@ elif len(found_targets) > 1: suggestions: T.List[str] = [] for i in found_targets: - p = Path(i['filename'][0]).relative_to(resolved_bdir) + p = Path(i['filename'][0]).relative_to(resolved_bdir).parent / i['name'] t = i['type'].replace(' ', '_') suggestions.append(f'- ./{p}:{t}') suggestions_str = '\n'.join(suggestions) @@ -133,7 +131,7 @@ 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': + if intro_target['type'] in {'alias', 'run'}: return [target.name] else: return [str(Path(out_file).relative_to(builddir.resolve())) for out_file in intro_target['filename']] @@ -172,7 +170,7 @@ 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' + assert intro_target['type'] not in {'alias', '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 @@ -192,7 +190,7 @@ if options.targets: intro_data = parse_introspect_data(builddir) has_run_target = any( - get_target_from_intro_data(ParsedTargetName(t), builddir, intro_data)['type'] == 'run' + get_target_from_intro_data(ParsedTargetName(t), builddir, intro_data)['type'] in {'alias', 'run'} for t in options.targets) if has_run_target: @@ -333,10 +331,10 @@ 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) - vsenv_active = setup_vsenv(b.need_vsenv) - if vsenv_active: + cdata = b.environment.coredata + need_vsenv = T.cast('bool', cdata.get_option(mesonlib.OptionKey('vsenv'))) + if setup_vsenv(need_vsenv): mlog.log(mlog.green('INFO:'), 'automatically activated MSVC compiler environment') cmd = [] # type: T.List[str] diff -Nru meson-1.0.1/mesonbuild/mconf.py meson-1.2.1/mesonbuild/mconf.py --- meson-1.0.1/mesonbuild/mconf.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/mconf.py 2023-08-07 22:54:34.000000000 +0000 @@ -32,6 +32,9 @@ if T.TYPE_CHECKING: import argparse + # cannot be TV_Loggable, because non-ansidecorators do direct string concat + LOGLINE = T.Union[str, mlog.AnsiDecorator] + def add_arguments(parser: 'argparse.ArgumentParser') -> None: coredata.register_builtin_arguments(parser) parser.add_argument('builddir', nargs='?', default='.') @@ -40,7 +43,7 @@ parser.add_argument('--no-pager', action='store_false', dest='pager', help='Do not redirect output to a pager') -def stringify(val: T.Any) -> T.Union[str, T.List[T.Any]]: # T.Any because of recursion... +def stringify(val: T.Any) -> str: if isinstance(val, bool): return str(val).lower() elif isinstance(val, list): @@ -57,43 +60,41 @@ class Conf: - def __init__(self, build_dir): + def __init__(self, build_dir: str): self.build_dir = os.path.abspath(os.path.realpath(build_dir)) if 'meson.build' in [os.path.basename(self.build_dir), self.build_dir]: self.build_dir = os.path.dirname(self.build_dir) self.build = None self.max_choices_line_length = 60 - self.name_col = [] - self.value_col = [] - self.choices_col = [] - self.descr_col = [] + self.name_col: T.List[LOGLINE] = [] + self.value_col: T.List[LOGLINE] = [] + self.choices_col: T.List[LOGLINE] = [] + self.descr_col: T.List[LOGLINE] = [] self.all_subprojects: T.Set[str] = set() if os.path.isdir(os.path.join(self.build_dir, 'meson-private')): self.build = build.load(self.build_dir) self.source_dir = self.build.environment.get_source_dir() - self.coredata = coredata.load(self.build_dir) + self.coredata = self.build.environment.coredata self.default_values_only = False elif os.path.isfile(os.path.join(self.build_dir, environment.build_filename)): # Make sure that log entries in other parts of meson don't interfere with the JSON output - mlog.disable() - self.source_dir = os.path.abspath(os.path.realpath(self.build_dir)) - intr = mintro.IntrospectionInterpreter(self.source_dir, '', 'ninja', visitors = [AstIDGenerator()]) - intr.analyze() - # Re-enable logging just in case - mlog.enable() + with mlog.no_logging(): + self.source_dir = os.path.abspath(os.path.realpath(self.build_dir)) + intr = mintro.IntrospectionInterpreter(self.source_dir, '', 'ninja', visitors = [AstIDGenerator()]) + intr.analyze() self.coredata = intr.coredata self.default_values_only = True else: raise ConfException(f'Directory {build_dir} is neither a Meson build directory nor a project source directory.') - def clear_cache(self): - self.coredata.clear_deps_cache() + def clear_cache(self) -> None: + self.coredata.clear_cache() - def set_options(self, options): - self.coredata.set_options(options) + def set_options(self, options: T.Dict[OptionKey, str]) -> bool: + return self.coredata.set_options(options) - def save(self): + def save(self) -> None: # Do nothing when using introspection if self.default_values_only: return @@ -129,12 +130,16 @@ mlog.log(line[0]) continue - def wrap_text(text, width): + def wrap_text(text: LOGLINE, width: int) -> mlog.TV_LoggableList: raw = text.text if isinstance(text, mlog.AnsiDecorator) else text indent = ' ' if raw.startswith('[') else '' - wrapped = textwrap.wrap(raw, width, subsequent_indent=indent) + wrapped_ = textwrap.wrap(raw, width, subsequent_indent=indent) + # We cast this because https://github.com/python/mypy/issues/1965 + # mlog.TV_LoggableList does not provide __len__ for stringprotocol if isinstance(text, mlog.AnsiDecorator): - wrapped = [mlog.AnsiDecorator(i, text.code) for i in wrapped] + wrapped = T.cast('T.List[LOGLINE]', [mlog.AnsiDecorator(i, text.code) for i in wrapped_]) + else: + wrapped = T.cast('T.List[LOGLINE]', wrapped_) # Add padding here to get even rows, as `textwrap.wrap()` will # only shorten, not lengthen each item return [str(i) + ' ' * (width - len(i)) for i in wrapped] @@ -151,15 +156,15 @@ items = [l[i] if l[i] else ' ' * four_column[i] for i in range(4)] mlog.log(*items) - def split_options_per_subproject(self, options: 'coredata.KeyedOptionDictType') -> T.Dict[str, 'coredata.KeyedOptionDictType']: - result: T.Dict[str, 'coredata.KeyedOptionDictType'] = {} + def split_options_per_subproject(self, options: 'coredata.KeyedOptionDictType') -> T.Dict[str, 'coredata.MutableKeyedOptionDictType']: + result: T.Dict[str, 'coredata.MutableKeyedOptionDictType'] = {} for k, o in options.items(): if k.subproject: self.all_subprojects.add(k.subproject) result.setdefault(k.subproject, {})[k] = o return result - def _add_line(self, name, value, choices, descr) -> None: + def _add_line(self, name: LOGLINE, value: LOGLINE, choices: LOGLINE, descr: LOGLINE) -> None: if isinstance(name, mlog.AnsiDecorator): name.text = ' ' * self.print_margin + name.text else: @@ -169,21 +174,21 @@ self.choices_col.append(choices) self.descr_col.append(descr) - def add_option(self, name, descr, value, choices): + def add_option(self, name: str, descr: str, value: T.Any, choices: T.Any) -> None: value = stringify(value) choices = stringify(choices) self._add_line(mlog.green(name), mlog.yellow(value), mlog.blue(choices), descr) - def add_title(self, title): - title = mlog.cyan(title) + def add_title(self, title: str) -> None: + newtitle = mlog.cyan(title) descr = mlog.cyan('Description') value = mlog.cyan('Default Value' if self.default_values_only else 'Current Value') choices = mlog.cyan('Possible Values') self._add_line('', '', '', '') - self._add_line(title, value, choices, descr) - self._add_line('-' * len(title), '-' * len(value), '-' * len(choices), '-' * len(descr)) + self._add_line(newtitle, value, choices, descr) + self._add_line('-' * len(newtitle), '-' * len(value), '-' * len(choices), '-' * len(descr)) - def add_section(self, section): + def add_section(self, section: str) -> None: self.print_margin = 0 self._add_line('', '', '', '') self._add_line(mlog.normal_yellow(section + ':'), '', '', '') @@ -204,13 +209,13 @@ printable_value = auto.printable_value() self.add_option(str(root), o.description, printable_value, o.choices) - def print_conf(self, pager: bool): + def print_conf(self, pager: bool) -> None: if pager: mlog.start_pager() - def print_default_values_warning(): + def print_default_values_warning() -> None: mlog.warning('The source directory instead of the build directory was specified.') - mlog.warning('Only the default values for the project are printed, and all command line parameters are ignored.') + mlog.warning('Only the default values for the project are printed.') if self.default_values_only: print_default_values_warning() @@ -225,10 +230,10 @@ 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) + dir_options: 'coredata.MutableKeyedOptionDictType' = {} + test_options: 'coredata.MutableKeyedOptionDictType' = {} + core_options: 'coredata.MutableKeyedOptionDictType' = {} + module_options: T.Dict[str, 'coredata.MutableKeyedOptionDictType'] = collections.defaultdict(dict) for k, v in self.coredata.options.items(): if k in dir_option_names: dir_options[k] = v @@ -287,7 +292,7 @@ self.print_nondefault_buildtype_options() - def print_nondefault_buildtype_options(self): + def print_nondefault_buildtype_options(self) -> None: mismatching = self.coredata.get_nondefault_buildtype_args() if not mismatching: return @@ -296,26 +301,26 @@ for m in mismatching: mlog.log(f'{m[0]:21}{m[1]:10}{m[2]:10}') -def run(options): +def run(options: argparse.Namespace) -> int: coredata.parse_cmd_line_options(options) builddir = os.path.abspath(os.path.realpath(options.builddir)) + print_only = not options.cmd_line_options and not options.clearcache c = None try: c = Conf(builddir) - if c.default_values_only: + if c.default_values_only and not print_only: + raise mesonlib.MesonException('No valid build directory found, cannot modify options.') + if c.default_values_only or print_only: c.print_conf(options.pager) return 0 save = False if options.cmd_line_options: - c.set_options(options.cmd_line_options) + save = c.set_options(options.cmd_line_options) coredata.update_cmd_line_file(builddir, options) - save = True - elif options.clearcache: + if options.clearcache: c.clear_cache() save = True - else: - c.print_conf(options.pager) if save: c.save() mintro.update_build_options(c.coredata, c.build.environment.info_dir) diff -Nru meson-1.0.1/mesonbuild/mdevenv.py meson-1.2.1/mesonbuild/mdevenv.py --- meson-1.0.1/mesonbuild/mdevenv.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/mdevenv.py 2023-08-07 22:54:34.000000000 +0000 @@ -7,7 +7,7 @@ import itertools from pathlib import Path -from . import build, minstall, dependencies +from . import build, minstall from .mesonlib import (MesonException, is_windows, setup_vsenv, OptionKey, get_wine_shortpath, MachineChoice) from . import mlog @@ -23,8 +23,12 @@ help='Path to build directory') parser.add_argument('--workdir', '-w', type=Path, default=None, help='Directory to cd into before running (default: builddir, Since 1.0.0)') - parser.add_argument('--dump', action='store_true', - help='Only print required environment (Since 0.62.0)') + parser.add_argument('--dump', nargs='?', const=True, + help='Only print required environment (Since 0.62.0) ' + + 'Takes an optional file path (Since 1.1.0)') + parser.add_argument('--dump-format', default='export', + choices=['sh', 'export', 'vscode'], + help='Format used with --dump (Since 1.1.0)') parser.add_argument('devcmd', nargs=argparse.REMAINDER, metavar='command', help='Command to run in developer environment (default: interactive shell)') @@ -50,7 +54,7 @@ env['WINEPATH'] = get_wine_shortpath([winecmd], winepath.split(';')) mlog.log('Meson detected wine and has set WINEPATH accordingly') -def get_env(b: build.Build, dump: bool) -> T.Tuple[T.Dict[str, str], T.Set[str]]: +def get_env(b: build.Build, dump_fmt: T.Optional[str]) -> T.Tuple[T.Dict[str, str], T.Set[str]]: extra_env = build.EnvironmentVariables() extra_env.set('MESON_DEVENV', ['1']) extra_env.set('MESON_PROJECT_NAME', [b.project_name]) @@ -59,10 +63,11 @@ if sysroot: extra_env.set('QEMU_LD_PREFIX', [sysroot]) - env = {} if dump else os.environ.copy() + env = {} if dump_fmt else os.environ.copy() + default_fmt = '${0}' if dump_fmt in {'sh', 'export'} else None varnames = set() for i in itertools.chain(b.devenv, {extra_env}): - env = i.get_env(env, dump) + env = i.get_env(env, default_fmt) varnames |= i.get_names() reduce_winepath(env) @@ -70,9 +75,10 @@ return env, varnames def bash_completion_files(b: build.Build, install_data: 'InstallData') -> T.List[str]: + from .dependencies.pkgconfig import PkgConfigDependency result = [] - dep = dependencies.PkgConfigDependency('bash-completion', b.environment, - {'required': False, 'silent': True, 'version': '>=2.10'}) + dep = PkgConfigDependency('bash-completion', b.environment, + {'required': False, 'silent': True, 'version': '>=2.10'}) if dep.found(): prefix = b.environment.coredata.get_option(OptionKey('prefix')) assert isinstance(prefix, str), 'for mypy' @@ -140,6 +146,12 @@ mlog.log(' - Change current workdir to', mlog.bold(str(rel_path.parent)), 'or use', mlog.bold(f'--init-command {rel_path}')) +def dump(devenv: T.Dict[str, str], varnames: T.Set[str], dump_format: T.Optional[str], output: T.Optional[T.TextIO] = None) -> None: + for name in varnames: + print(f'{name}="{devenv[name]}"', file=output) + if dump_format == 'export': + print(f'export {name}', file=output) + def run(options: argparse.Namespace) -> int: privatedir = Path(options.builddir) / 'meson-private' buildfile = privatedir / 'build.dat' @@ -148,14 +160,18 @@ b = build.load(options.builddir) workdir = options.workdir or options.builddir - setup_vsenv(b.need_vsenv) # Call it before get_env to get vsenv vars as well - devenv, varnames = get_env(b, options.dump) + need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) + setup_vsenv(need_vsenv) # Call it before get_env to get vsenv vars as well + dump_fmt = options.dump_format if options.dump else None + devenv, varnames = get_env(b, dump_fmt) if options.dump: if options.devcmd: raise MesonException('--dump option does not allow running other command.') - for name in varnames: - print(f'{name}="{devenv[name]}"') - print(f'export {name}') + if options.dump is True: + dump(devenv, varnames, dump_fmt) + else: + with open(options.dump, "w", encoding='utf-8') as output: + dump(devenv, varnames, dump_fmt, output) return 0 if b.environment.need_exe_wrapper(): diff -Nru meson-1.0.1/mesonbuild/mdist.py meson-1.2.1/mesonbuild/mdist.py --- meson-1.0.1/mesonbuild/mdist.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/mdist.py 2023-06-28 14:48:20.000000000 +0000 @@ -14,6 +14,7 @@ from __future__ import annotations +import abc import argparse import gzip import os @@ -24,23 +25,30 @@ import tarfile import tempfile import hashlib +import typing as T + +from dataclasses import dataclass from glob import glob from pathlib import Path from mesonbuild.environment import detect_ninja from mesonbuild.mesonlib import (MesonException, RealPathAction, quiet_git, - windows_proof_rmtree, setup_vsenv) + windows_proof_rmtree, setup_vsenv, OptionKey) from mesonbuild.msetup import add_arguments as msetup_argparse from mesonbuild.wrap import wrap from mesonbuild import mlog, build, coredata from .scripts.meson_exe import run_exe +if T.TYPE_CHECKING: + from ._typing import ImmutableListProtocol + from .mesonlib import ExecutableSerialisation + archive_choices = ['gztar', 'xztar', 'zip'] archive_extension = {'gztar': '.tar.gz', 'xztar': '.tar.xz', 'zip': '.zip'} -def add_arguments(parser): +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('--allow-dirty', action='store_true', @@ -53,7 +61,7 @@ help='Do not build and test generated packages.') -def create_hash(fname): +def create_hash(fname: str) -> None: hashname = fname + '.sha256sum' m = hashlib.sha256() m.update(open(fname, 'rb').read()) @@ -63,178 +71,200 @@ 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) - msg_uncommitted_changes = 'Repository has uncommitted changes that will not be included in the dist tarball' -def handle_dirty_opt(msg, allow_dirty: bool): +def handle_dirty_opt(msg: str, allow_dirty: bool) -> None: if allow_dirty: mlog.warning(msg) else: mlog.error(msg + '\n' + 'Use --allow-dirty to ignore the warning and proceed anyway') sys.exit(1) -def process_submodules(src, distdir, options): - module_file = os.path.join(src, '.gitmodules') - if not os.path.exists(module_file): - return - 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 - elif status in {'+', 'U'}: - handle_dirty_opt(f'Submodule {subpath!r} has uncommitted changes that will not be included in the dist tarball', options.allow_dirty) - - copy_git(os.path.join(src, subpath), distdir, revision=sha1, prefix=subpath) - - -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: - 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 = run_exe(d, env) - if rc != 0: - sys.exit('Dist script errored out') - except OSError: - 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): +def is_git(src_root: str) -> bool: ''' 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 process_git_project(src_root, distdir, options): - if git_have_dirty_index(src_root): - handle_dirty_opt(msg_uncommitted_changes, options.allow_dirty) - if os.path.exists(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, options) - -def create_dist_git(dist_name, archives, src_root, bld_root, dist_sub, dist_scripts, subprojects, options): - distdir = os.path.join(dist_sub, dist_name) - process_git_project(src_root, distdir, options) - 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): - process_git_project(sub_src_root, sub_distdir, options) +def is_hg(src_root: str) -> bool: + return os.path.isdir(os.path.join(src_root, '.hg')) + + +@dataclass +class Dist(metaclass=abc.ABCMeta): + dist_name: str + src_root: str + bld_root: str + dist_scripts: T.List[ExecutableSerialisation] + subprojects: T.Dict[str, str] + options: argparse.Namespace + + def __post_init__(self) -> None: + self.dist_sub = os.path.join(self.bld_root, 'meson-dist') + self.distdir = os.path.join(self.dist_sub, self.dist_name) + + @abc.abstractmethod + def create_dist(self, archives: T.List[str]) -> T.List[str]: + pass + + def run_dist_scripts(self) -> None: + assert os.path.isabs(self.distdir) + env = {} + env['MESON_DIST_ROOT'] = self.distdir + env['MESON_SOURCE_ROOT'] = self.src_root + env['MESON_BUILD_ROOT'] = self.bld_root + for d in self.dist_scripts: + if d.subproject and d.subproject not in self.subprojects: + continue + subdir = self.subprojects.get(d.subproject, '') + env['MESON_PROJECT_DIST_ROOT'] = os.path.join(self.distdir, subdir) + env['MESON_PROJECT_SOURCE_ROOT'] = os.path.join(self.src_root, subdir) + env['MESON_PROJECT_BUILD_ROOT'] = os.path.join(self.bld_root, subdir) + name = ' '.join(d.cmd_args) + print(f'Running custom dist script {name!r}') + try: + rc = run_exe(d, env) + if rc != 0: + sys.exit('Dist script errored out') + except OSError: + print(f'Failed to run dist script {name!r}') + sys.exit(1) + + +class GitDist(Dist): + def git_root(self, dir_: str) -> Path: + # 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'], dir_, check=True)[1].strip() + if not prefix: + return Path(dir_) + prefix_level = len(Path(prefix).parents) + return Path(dir_).parents[prefix_level - 1] + + def have_dirty_index(self) -> bool: + '''Check whether there are uncommitted changes in git''' + ret = subprocess.call(['git', '-C', self.src_root, 'diff-index', '--quiet', 'HEAD']) + return ret == 1 + + def copy_git(self, src: T.Union[str, os.PathLike], distdir: str, revision: str = 'HEAD', + prefix: T.Optional[str] = None, subdir: T.Optional[str] = None) -> 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_git_project(self, src_root: str, distdir: str) -> None: + if self.have_dirty_index(): + handle_dirty_opt(msg_uncommitted_changes, self.options.allow_dirty) + if os.path.exists(distdir): + windows_proof_rmtree(distdir) + repo_root = self.git_root(src_root) + if repo_root.samefile(src_root): + os.makedirs(distdir) + self.copy_git(src_root, distdir) else: - shutil.copytree(sub_src_root, sub_distdir) - 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) - windows_proof_rmtree(distdir) - return output_names + 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) + self.copy_git(repo_root, tmp_distdir, subdir=str(subdir)) + Path(tmp_distdir, subdir).rename(distdir) + windows_proof_rmtree(tmp_distdir) + self.process_submodules(src_root, distdir) -def is_hg(src_root): - return os.path.isdir(os.path.join(src_root, '.hg')) + def process_submodules(self, src: str, distdir: str) -> None: + module_file = os.path.join(src, '.gitmodules') + if not os.path.exists(module_file): + return + 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 + elif status in {'+', 'U'}: + handle_dirty_opt(f'Submodule {subpath!r} has uncommitted changes that will not be included in the dist tarball', self.options.allow_dirty) + + self.copy_git(os.path.join(src, subpath), distdir, revision=sha1, prefix=subpath) + + def create_dist(self, archives: T.List[str]) -> T.List[str]: + self.process_git_project(self.src_root, self.distdir) + for path in self.subprojects.values(): + sub_src_root = os.path.join(self.src_root, path) + sub_distdir = os.path.join(self.distdir, path) + if os.path.exists(sub_distdir): + continue + if is_git(sub_src_root): + self.process_git_project(sub_src_root, sub_distdir) + else: + shutil.copytree(sub_src_root, sub_distdir) + self.run_dist_scripts() + output_names = [] + for a in archives: + compressed_name = self.distdir + archive_extension[a] + shutil.make_archive(self.distdir, a, root_dir=self.dist_sub, base_dir=self.dist_name) + output_names.append(compressed_name) + windows_proof_rmtree(self.distdir) + return output_names + + +class HgDist(Dist): + def have_dirty_index(self) -> bool: + '''Check whether there are uncommitted changes in hg''' + out = subprocess.check_output(['hg', '-R', self.src_root, 'summary']) + return b'commit: (clean)' not in out + + def create_dist(self, archives: T.List[str]) -> T.List[str]: + if self.have_dirty_index(): + handle_dirty_opt(msg_uncommitted_changes, self.options.allow_dirty) + if self.dist_scripts: + mlog.warning('dist scripts are not supported in Mercurial projects') + + os.makedirs(self.dist_sub, exist_ok=True) + tarname = os.path.join(self.dist_sub, self.dist_name + '.tar') + xzname = tarname + '.xz' + gzname = tarname + '.gz' + zipname = os.path.join(self.dist_sub, self.dist_name + '.zip') + # 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', self.src_root, '-S', '-t', 'tar', + '-X', self.src_root + '/.hg[a-z]*', tarname]) + output_names = [] + if 'xztar' in archives: + import lzma + with lzma.open(xzname, 'wb') as xf, open(tarname, 'rb') as tf: + shutil.copyfileobj(tf, xf) + output_names.append(xzname) + if 'gztar' in archives: + with gzip.open(gzname, 'wb') as zf, open(tarname, 'rb') as tf: + shutil.copyfileobj(tf, zf) + output_names.append(gzname) + os.unlink(tarname) + if 'zip' in archives: + subprocess.check_call(['hg', 'archive', '-R', self.src_root, '-S', '-t', 'zip', zipname]) + output_names.append(zipname) + return output_names -def hg_have_dirty_index(src_root): - '''Check whether there are uncommitted changes in hg''' - out = subprocess.check_output(['hg', '-R', src_root, 'summary']) - return b'commit: (clean)' not in out - -def create_dist_hg(dist_name, archives, src_root, bld_root, dist_sub, dist_scripts, options): - if hg_have_dirty_index(src_root): - handle_dirty_opt(msg_uncommitted_changes, options.allow_dirty) - 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') - # 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 'xztar' in archives: - import lzma - with lzma.open(xzname, 'wb') as xf, open(tarname, 'rb') as tf: - shutil.copyfileobj(tf, xf) - output_names.append(xzname) - if 'gztar' in archives: - with gzip.open(gzname, 'wb') as zf, open(tarname, 'rb') as tf: - shutil.copyfileobj(tf, zf) - output_names.append(gzname) - os.unlink(tarname) - if 'zip' in archives: - subprocess.check_call(['hg', 'archive', '-R', src_root, '-S', '-t', 'zip', zipname]) - output_names.append(zipname) - return output_names -def run_dist_steps(meson_command, unpacked_src_dir, builddir, installdir, ninja_args): +def run_dist_steps(meson_command: T.List[str], unpacked_src_dir: str, builddir: str, installdir: str, ninja_args: T.List[str]) -> int: if subprocess.call(meson_command + ['--backend=ninja', unpacked_src_dir, builddir]) != 0: print('Running Meson on distribution package failed') return 1 @@ -251,7 +281,7 @@ return 1 return 0 -def check_dist(packagename, meson_command, extra_meson_args, bld_root, privdir): +def check_dist(packagename: str, meson_command: ImmutableListProtocol[str], extra_meson_args: T.List[str], bld_root: str, privdir: str) -> int: print(f'Testing distribution package {packagename}') unpackdir = os.path.join(privdir, 'dist-unpack') builddir = os.path.join(privdir, 'dist-build') @@ -265,6 +295,7 @@ unpacked_files = glob(os.path.join(unpackdir, '*')) assert len(unpacked_files) == 1 unpacked_src_dir = unpacked_files[0] + meson_command += ['setup'] meson_command += create_cmdline_args(bld_root) meson_command += extra_meson_args @@ -278,16 +309,16 @@ print(f'Distribution package {packagename} tested') return ret -def create_cmdline_args(bld_root): +def create_cmdline_args(bld_root: str) -> T.List[str]: parser = argparse.ArgumentParser() msetup_argparse(parser) args = parser.parse_args([]) coredata.parse_cmd_line_options(args) coredata.read_cmd_line_file(bld_root, args) - args.cmd_line_options.pop(coredata.OptionKey('backend'), '') + args.cmd_line_options.pop(OptionKey('backend'), '') return shlex.split(coredata.format_cmd_line_options(args)) -def determine_archives_to_generate(options): +def determine_archives_to_generate(options: argparse.Namespace) -> T.List[str]: result = [] for i in options.formats.split(','): if i not in archive_choices: @@ -297,19 +328,19 @@ sys.exit('No archive types specified.') return result -def run(options): +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) + need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) + setup_vsenv(need_vsenv) # This import must be load delayed, otherwise it will get the default # value of None. 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') - dist_sub = os.path.join(bld_root, 'meson-dist') dist_name = b.project_name + '-' + b.project_version @@ -324,16 +355,21 @@ subprojects[sub] = os.path.join(b.subproject_dir, directory) extra_meson_args.append('-Dwrap_mode=nodownload') + cls: T.Type[Dist] if is_git(src_root): - names = create_dist_git(dist_name, archives, src_root, bld_root, dist_sub, b.dist_scripts, subprojects, options) + cls = GitDist elif is_hg(src_root): if subprojects: print('--include-subprojects option currently not supported with Mercurial') return 1 - names = create_dist_hg(dist_name, archives, src_root, bld_root, dist_sub, b.dist_scripts, options) + cls = HgDist else: print('Dist currently only works with Git or Mercurial repos') return 1 + + project = cls(dist_name, src_root, bld_root, b.dist_scripts, subprojects, options) + names = project.create_dist(archives) + if names is None: return 1 rc = 0 diff -Nru meson-1.0.1/mesonbuild/mesonmain.py meson-1.2.1/mesonbuild/mesonmain.py --- meson-1.0.1/mesonbuild/mesonmain.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/mesonmain.py 2023-05-23 15:20:02.000000000 +0000 @@ -236,6 +236,13 @@ mesonlib.set_meson_command(mainfile) def run(original_args, mainfile): + if os.environ.get('MESON_SHOW_DEPRECATIONS'): + # workaround for https://bugs.python.org/issue34624 + import warnings + for typ in [DeprecationWarning, SyntaxWarning, FutureWarning, PendingDeprecationWarning]: + warnings.filterwarnings('error', category=typ, module='mesonbuild') + warnings.filterwarnings('ignore', message=".*importlib-resources.*") + if sys.version_info >= (3, 10) and os.environ.get('MESON_RUNNING_IN_PROJECT_TESTS'): # workaround for https://bugs.python.org/issue34624 import warnings @@ -283,7 +290,7 @@ assert os.path.isabs(sys.executable) launcher = sys.executable else: - launcher = os.path.realpath(sys.argv[0]) + launcher = os.path.abspath(sys.argv[0]) return run(sys.argv[1:], launcher) if __name__ == '__main__': diff -Nru meson-1.0.1/mesonbuild/minit.py meson-1.2.1/mesonbuild/minit.py --- meson-1.0.1/mesonbuild/minit.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/minit.py 2023-08-07 22:54:34.000000000 +0000 @@ -23,7 +23,7 @@ import os import re from glob import glob -from mesonbuild import mesonlib +from mesonbuild import build, mesonlib, mlog from mesonbuild.coredata import FORBIDDEN_TARGET_NAMES from mesonbuild.environment import detect_ninja from mesonbuild.templates.samplefactory import sameple_generator @@ -181,10 +181,17 @@ print('Build directory already exists, deleting it.') shutil.rmtree(options.builddir) print('Building...') - cmd = mesonlib.get_meson_command() + [options.builddir] + cmd = mesonlib.get_meson_command() + ['setup', options.builddir] ret = subprocess.run(cmd) if ret.returncode: raise SystemExit + + b = build.load(options.builddir) + need_vsenv = T.cast('bool', b.environment.coredata.get_option(mesonlib.OptionKey('vsenv'))) + vsenv_active = mesonlib.setup_vsenv(need_vsenv) + if vsenv_active: + mlog.log(mlog.green('INFO:'), 'automatically activated MSVC compiler environment') + cmd = detect_ninja() + ['-C', options.builddir] ret = subprocess.run(cmd) if ret.returncode: diff -Nru meson-1.0.1/mesonbuild/minstall.py meson-1.2.1/mesonbuild/minstall.py --- meson-1.0.1/mesonbuild/minstall.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/minstall.py 2023-08-07 22:54:34.000000000 +0000 @@ -14,20 +14,21 @@ from __future__ import annotations from glob import glob -from pathlib import Path import argparse import errno import os +import selectors import shlex import shutil import subprocess import sys import typing as T +import re -from . import build -from . import environment +from . import build, coredata, environment from .backend.backends import InstallData -from .mesonlib import MesonException, Popen_safe, RealPathAction, is_windows, setup_vsenv, pickle_load, is_osx +from .mesonlib import (MesonException, Popen_safe, RealPathAction, is_windows, + is_aix, setup_vsenv, pickle_load, is_osx, OptionKey) from .scripts import depfixer, destdir_join from .scripts.meson_exe import run_exe try: @@ -42,7 +43,7 @@ ExecutableSerialisation, InstallDataBase, InstallEmptyDir, InstallSymlinkData, TargetInstallData ) - from .mesonlib import FileMode + from .mesonlib import FileMode, EnvironOrDict try: from typing import Protocol @@ -130,9 +131,7 @@ def load_install_data(fname: str) -> InstallData: - obj = pickle_load(fname, 'InstallData', InstallData) - assert isinstance(obj, InstallData), 'fo mypy' - return obj + return pickle_load(fname, 'InstallData', InstallData) def is_executable(path: str, follow_symlinks: bool = False) -> bool: '''Checks whether any of the "x" bits are set in the source file mode.''' @@ -209,10 +208,10 @@ except PermissionError as e: print(f'{path!r}: Unable to set owner {mode.owner!r} and group {mode.group!r}: {e.strerror}, ignoring...') except LookupError: - print(f'{path!r}: Non-existent owner {mode.owner!r} or group {mode.group!r}: ignoring...') + print(f'{path!r}: Nonexistent owner {mode.owner!r} or group {mode.group!r}: ignoring...') except OSError as e: if e.errno == errno.EINVAL: - print(f'{path!r}: Non-existent numeric owner {mode.owner!r} or group {mode.group!r}: ignoring...') + print(f'{path!r}: Nonexistent numeric owner {mode.owner!r} or group {mode.group!r}: ignoring...') else: raise # Must set permissions *after* setting owner/group otherwise the @@ -361,9 +360,9 @@ 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) + def run_exe(self, exe: ExecutableSerialisation, extra_env: T.Optional[T.Dict[str, str]] = None) -> int: + if (not self.dry_run) or exe.dry_run: + return run_exe(exe, extra_env) return 0 def should_install(self, d: T.Union[TargetInstallData, InstallEmptyDir, @@ -482,6 +481,8 @@ raise ValueError(f'dst_dir must be absolute, got {dst_dir}') if exclude is not None: exclude_files, exclude_dirs = exclude + exclude_files = {os.path.normpath(x) for x in exclude_files} + exclude_dirs = {os.path.normpath(x) for x in exclude_dirs} else: exclude_files = exclude_dirs = set() for root, dirs, files in os.walk(src_dir): @@ -556,19 +557,42 @@ 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 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:], - '-C', os.getcwd()) - else: + if is_windows() or destdir != '' or not os.isatty(sys.stdout.fileno()) or not os.isatty(sys.stderr.fileno()): + # can't elevate to root except in an interactive unix environment *and* when not doing a destdir install raise + rootcmd = os.environ.get('MESON_ROOT_CMD') or shutil.which('sudo') or shutil.which('doas') + pkexec = shutil.which('pkexec') + if rootcmd is None and pkexec is not None and 'PKEXEC_UID' not in os.environ: + rootcmd = pkexec + + if rootcmd is not None: + print('Installation failed due to insufficient permissions.') + s = selectors.DefaultSelector() + s.register(sys.stdin, selectors.EVENT_READ) + ans = None + for attempt in range(5): + print(f'Attempt to use {rootcmd} to gain elevated privileges? [y/n] ', end='', flush=True) + if s.select(30): + # we waited on sys.stdin *only* + ans = sys.stdin.readline().rstrip('\n') + else: + print() + break + if ans in {'y', 'n'}: + break + else: + if ans is not None: + raise MesonException('Answer not one of [y/n]') + if ans == 'y': + os.execlp(rootcmd, rootcmd, sys.executable, main_file, *sys.argv[1:], + '-C', os.getcwd(), '--no-rebuild') + raise def do_strip(self, strip_bin: T.List[str], fname: str, outname: str) -> None: self.log(f'Stripping target {fname!r}.') if is_osx(): # macOS expects dynamic objects to be stripped with -x maximum. - # To also strip the debug info, -S must be added. + # To also strip the debug info, -S must be added. # See: https://www.unix.com/man-page/osx/1/strip/ returncode, stdo, stde = self.Popen_safe(strip_bin + ['-S', '-x', outname]) else: @@ -649,16 +673,25 @@ 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': fullprefix, 'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in d.mesonintrospect]), } if self.options.quiet: env['MESON_INSTALL_QUIET'] = '1' + if self.dry_run: + env['MESON_INSTALL_DRY_RUN'] = '1' for i in d.install_scripts: if not self.should_install(i): continue + + if i.installdir_map is not None: + mapp = i.installdir_map + else: + mapp = {'prefix': d.prefix} + localenv = env.copy() + localenv.update({'MESON_INSTALL_'+k.upper(): os.path.join(d.prefix, v) for k, v in mapp.items()}) + localenv.update({'MESON_INSTALL_DESTDIR_'+k.upper(): get_destdir_path(destdir, fullprefix, v) for k, v in mapp.items()}) + 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}') @@ -666,7 +699,7 @@ self.did_install_something = True # Custom script must report itself if it does nothing. self.log(f'Running custom install script {name!r}') try: - rc = self.run_exe(i, env) + rc = self.run_exe(i, localenv) except OSError: print(f'FAILED: install script \'{name}\' could not be run, stopped') # POSIX shells return 127 when a command could not be found @@ -677,6 +710,12 @@ def install_targets(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: for t in d.targets: + # In AIX, we archive our shared libraries. When we install any package in AIX we need to + # install the archive in which the shared library exists. The below code does the same. + # We change the .so files having lt_version or so_version to archive file install. + if is_aix(): + if '.so' in t.fname: + t.fname = re.sub('[.][a]([.]?([0-9]+))*([.]?([a-z]+))*', '.a', t.fname.replace('.so', '.a')) if not self.should_install(t): continue if not os.path.exists(t.fname): @@ -731,8 +770,11 @@ # file mode needs to be set last, after strip/depfixer editing self.set_mode(outname, install_mode, d.install_umask) -def rebuild_all(wd: str) -> bool: - if not (Path(wd) / 'build.ninja').is_file(): +def rebuild_all(wd: str, backend: str) -> bool: + if backend == 'none': + # nothing to build... + return True + if backend != 'ninja': print('Only ninja backend is supported to rebuild the project before installation.') return True @@ -741,7 +783,53 @@ print("Can't find ninja, can't rebuild test.") return False - ret = subprocess.run(ninja + ['-C', wd]).returncode + def drop_privileges() -> T.Tuple[T.Optional[EnvironOrDict], T.Optional[T.Callable[[], None]]]: + if not is_windows() and os.geteuid() == 0: + import pwd + env = os.environ.copy() + + if os.environ.get('SUDO_USER') is not None: + orig_user = env.pop('SUDO_USER') + orig_uid = env.pop('SUDO_UID', 0) + orig_gid = env.pop('SUDO_GID', 0) + try: + homedir = pwd.getpwuid(int(orig_uid)).pw_dir + except KeyError: + # `sudo chroot` leaves behind stale variable and builds as root without a user + return None, None + elif os.environ.get('DOAS_USER') is not None: + orig_user = env.pop('DOAS_USER') + try: + pwdata = pwd.getpwnam(orig_user) + except KeyError: + # `doas chroot` leaves behind stale variable and builds as root without a user + return None, None + orig_uid = pwdata.pw_uid + orig_gid = pwdata.pw_gid + homedir = pwdata.pw_dir + else: + return None, None + + if os.stat(os.path.join(wd, 'build.ninja')).st_uid != int(orig_uid): + # the entire build process is running with sudo, we can't drop privileges + return None, None + + env['USER'] = orig_user + env['HOME'] = homedir + + def wrapped() -> None: + print(f'Dropping privileges to {orig_user!r} before running ninja...') + if orig_gid is not None: + os.setgid(int(orig_gid)) + if orig_uid is not None: + os.setuid(int(orig_uid)) + + return env, wrapped + else: + return None, None + + env, preexec_fn = drop_privileges() + ret = subprocess.run(ninja + ['-C', wd], env=env, preexec_fn=preexec_fn).returncode if ret != 0: print(f'Could not rebuild {wd}') return False @@ -757,8 +845,10 @@ 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): + need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) + setup_vsenv(need_vsenv) + backend = T.cast('str', b.environment.coredata.get_option(coredata.OptionKey('backend'))) + if not rebuild_all(opts.wd, backend): sys.exit(-1) os.chdir(opts.wd) with open(os.path.join(log_dir, 'install-log.txt'), 'w', encoding='utf-8') as lf: diff -Nru meson-1.0.1/mesonbuild/mintro.py meson-1.2.1/mesonbuild/mintro.py --- meson-1.0.1/mesonbuild/mintro.py 2022-10-24 19:25:13.000000000 +0000 +++ meson-1.2.1/mesonbuild/mintro.py 2023-08-07 22:54:34.000000000 +0000 @@ -20,15 +20,21 @@ Currently only works for the Ninja backend. Others use generated project files and don't need this info.""" +from contextlib import redirect_stdout import collections +import dataclasses import json import os from pathlib import Path, PurePath +import sys import typing as T -from . import build, mesonlib, mlog, coredata as cdata +from . import build, mesonlib, coredata as cdata from .ast import IntrospectionInterpreter, BUILD_TARGET_FUNCTIONS, AstConditionLevel, AstIDGenerator, AstIndentationGenerator, AstJSONPrinter from .backend import backends +from .dependencies import Dependency +from . import environment +from .interpreterbase import ObjectHolder from .mesonlib import OptionKey from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode @@ -74,10 +80,12 @@ ('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)), + ('compilers', IntroCommand('List used compilers', func=lambda: list_compilers(coredata))), + ('dependencies', IntroCommand('List external dependencies', func=lambda: list_deps(coredata, backend), 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))), + ('machines', IntroCommand('Information about host, build, and target machines', func=lambda: list_machines(builddata))), ('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))), @@ -129,6 +137,7 @@ os.path.join(installdata.build_dir, target.fname): { 'destination': target.out_name, 'tag': target.tag or None, + 'subproject': target.subproject or None, } for target in installdata.targets }, @@ -146,11 +155,20 @@ 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)) - plan[data_type] = plan.get(data_type, {}) - plan[data_type][data.path] = { + entry = { 'destination': install_path_name, 'tag': data.tag or None, + 'subproject': data.subproject or None, } + + if key == 'install_subdirs': + exclude_files, exclude_dirs = data.exclude or ([], []) + entry['exclude_dirs'] = list(exclude_dirs) + entry['exclude_files'] = list(exclude_files) + + plan[data_type] = plan.get(data_type, {}) + plan[data_type][data.path] = entry + return plan def get_target_dir(coredata: cdata.CoreData, subdir: str) -> str: @@ -204,6 +222,7 @@ 'sources': [str(x) for x in sources], 'generated_sources': [] }], + 'depends': [], 'extra_files': [str(x) for x in extra_f], 'subproject': None, # Subprojects are not supported 'installed': i['installed'] @@ -240,14 +259,23 @@ 'name': target.get_basename(), 'id': idname, 'type': target.get_typename(), - 'defined_in': os.path.normpath(os.path.join(src_dir, target.subdir, 'meson.build')), + 'defined_in': os.path.normpath(os.path.join(src_dir, target.subdir, environment.build_filename)), '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 + 'subproject': target.subproject or None, + 'dependencies': [d.name for d in getattr(target, 'external_deps', [])], + 'depends': [lib.get_id() for lib in getattr(target, 'dependencies', [])] } + vs_module_defs = getattr(target, 'vs_module_defs', None) + if vs_module_defs is not None: + t['vs_module_defs'] = vs_module_defs.relative_name() + win_subsystem = getattr(target, 'win_subsystem', None) + if win_subsystem is not None: + t['win_subsystem'] = win_subsystem + if installdata and target.should_install(): t['installed'] = True ifn = [install_lookuptable.get(x, [None]) for x in target.get_outputs()] @@ -319,12 +347,12 @@ return optlist def find_buildsystem_files_list(src_dir: str) -> T.List[str]: + build_files = frozenset({'meson.build', 'meson.options', 'meson_options.txt'}) # I feel dirty about this. But only slightly. - filelist = [] # type: T.List[str] + filelist: T.List[str] = [] for root, _, files in os.walk(src_dir): - for f in files: - if f in {'meson.build', 'meson_options.txt'}: - filelist.append(os.path.relpath(os.path.join(root, f), src_dir)) + filelist.extend(os.path.relpath(os.path.join(root, f), src_dir) + for f in build_files.intersection(files)) return filelist def list_buildsystem_files(builddata: build.Build, interpreter: Interpreter) -> T.List[str]: @@ -333,6 +361,23 @@ filelist = [PurePath(src_dir, x).as_posix() for x in filelist] return filelist +def list_compilers(coredata: cdata.CoreData) -> T.Dict[str, T.Dict[str, T.Dict[str, str]]]: + compilers: T.Dict[str, T.Dict[str, T.Dict[str, str]]] = {} + for machine in ('host', 'build'): + compilers[machine] = {} + for language, compiler in getattr(coredata.compilers, machine).items(): + compilers[machine][language] = { + 'id': compiler.get_id(), + 'exelist': compiler.get_exelist(), + 'linker_exelist': compiler.get_linker_exelist(), + 'file_suffixes': compiler.file_suffixes, + 'default_suffix': compiler.get_default_suffix(), + 'version': compiler.version, + 'full_version': compiler.full_version, + 'linker_id': compiler.get_linker_id(), + } + return compilers + def list_deps_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[str, bool]]]: result = [] # type: T.List[T.Dict[str, T.Union[str, bool]]] for i in intr.dependencies: @@ -346,15 +391,49 @@ result += [{k: v for k, v in i.items() if k in keys}] return result -def list_deps(coredata: cdata.CoreData) -> T.List[T.Dict[str, T.Union[str, T.List[str]]]]: - result = [] # type: T.List[T.Dict[str, T.Union[str, T.List[str]]]] +def list_deps(coredata: cdata.CoreData, backend: backends.Backend) -> T.List[T.Dict[str, T.Union[str, T.List[str]]]]: + result: T.Dict[str, T.Dict[str, T.Union[str, T.List[str]]]] = {} + + def _src_to_str(src_file: T.Union[mesonlib.FileOrString, build.CustomTarget, build.StructuredSources, build.CustomTargetIndex, build.GeneratedList]) -> T.List[str]: + if isinstance(src_file, str): + return [src_file] + if isinstance(src_file, mesonlib.File): + return [src_file.absolute_path(backend.source_dir, backend.build_dir)] + if isinstance(src_file, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)): + return src_file.get_outputs() + if isinstance(src_file, build.StructuredSources): + return [f for s in src_file.as_list() for f in _src_to_str(s)] + raise mesonlib.MesonBugException(f'Invalid file type {type(src_file)}.') + + def _create_result(d: Dependency, varname: T.Optional[str] = None) -> T.Dict[str, T.Any]: + return { + 'name': d.name, + 'type': d.type_name, + 'version': d.get_version(), + 'compile_args': d.get_compile_args(), + 'link_args': d.get_link_args(), + 'include_directories': [i for idirs in d.get_include_dirs() for i in idirs.to_string_list(backend.source_dir)], + 'sources': [f for s in d.get_sources() for f in _src_to_str(s)], + 'extra_files': [f for s in d.get_extra_files() for f in _src_to_str(s)], + 'dependencies': [e.name for e in d.ext_deps], + 'depends': [lib.get_id() for lib in getattr(d, 'libraries', [])], + 'meson_variables': [varname] if varname else [], + } + for d in coredata.deps.host.values(): if d.found(): - result += [{'name': d.name, - 'version': d.get_version(), - 'compile_args': d.get_compile_args(), - 'link_args': d.get_link_args()}] - return result + result[d.name] = _create_result(d) + + for varname, holder in backend.interpreter.variables.items(): + if isinstance(holder, ObjectHolder): + d = holder.held_object + if isinstance(d, Dependency) and d.found(): + if d.name in result: + T.cast(T.List[str], result[d.name]['meson_variables']).append(varname) + else: + result[d.name] = _create_result(d, varname) + + return list(result.values()) 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]]]] @@ -377,6 +456,7 @@ to['priority'] = t.priority to['protocol'] = str(t.protocol) to['depends'] = t.depends + to['extra_paths'] = t.extra_paths result.append(to) return result @@ -386,6 +466,16 @@ 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_machines(builddata: build.Build) -> T.Dict[str, T.Dict[str, T.Union[str, bool]]]: + machines: T.Dict[str, T.Dict[str, T.Union[str, bool]]] = {} + for m in ('host', 'build', 'target'): + machine = getattr(builddata.environment.machines, m) + machines[m] = dataclasses.asdict(machine) + machines[m]['is_64_bit'] = machine.is_64_bit + machines[m]['exe_suffix'] = machine.get_exe_suffix() + machines[m]['object_suffix'] = machine.get_object_suffix() + return machines + 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, @@ -453,13 +543,12 @@ 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) - assert backend is not None - intr = IntrospectionInterpreter(sourcedir, '', backend.name, visitors = [AstIDGenerator(), AstIndentationGenerator(), AstConditionLevel()]) - intr.analyze() - # Re-enable logging just in case - mlog.enable() + with redirect_stdout(sys.stderr): + backend = backends.get_backend_from_name(options.backend) + assert backend is not None + intr = IntrospectionInterpreter(sourcedir, '', backend.name, visitors = [AstIDGenerator(), AstIndentationGenerator(), AstConditionLevel()]) + intr.analyze() + for key, val in intro_types.items(): if (not options.all and not getattr(options, key, False)) or not val.no_bd: continue diff -Nru meson-1.0.1/mesonbuild/mlog.py meson-1.2.1/mesonbuild/mlog.py --- meson-1.0.1/mesonbuild/mlog.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/mlog.py 2023-08-07 22:54:34.000000000 +0000 @@ -12,6 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""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.""" + +from __future__ import annotations + +import enum import os import io import sys @@ -22,14 +29,16 @@ import shutil import typing as T from contextlib import contextmanager +from dataclasses import dataclass, field 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.""" + from .mparser import BaseNode + + TV_Loggable = T.Union[str, 'AnsiDecorator', StringProtocol] + TV_LoggableList = T.List[TV_Loggable] def is_windows() -> bool: platname = platform.system().lower() @@ -76,55 +85,352 @@ except AttributeError: pass -log_dir = None # type: T.Optional[str] -log_file = None # type: T.Optional[T.TextIO] -log_fname = 'meson-log.txt' # type: str -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 -log_pager: T.Optional['subprocess.Popen'] = None - -def disable() -> None: - global log_disable_stdout # pylint: disable=global-statement - log_disable_stdout = True +_in_ci = 'CI' in os.environ -def enable() -> None: - global log_disable_stdout # pylint: disable=global-statement - log_disable_stdout = False -def set_quiet() -> None: - global log_errors_only # pylint: disable=global-statement - log_errors_only = True +class _Severity(enum.Enum): + + NOTICE = enum.auto() + WARNING = enum.auto() + ERROR = enum.auto() + DEPRECATION = enum.auto() + +@dataclass +class _Logger: -def set_verbose() -> None: - global log_errors_only # pylint: disable=global-statement + log_dir: T.Optional[str] = None + log_depth: T.List[str] = field(default_factory=list) + log_file: T.Optional[T.TextIO] = None + log_timestamp_start: T.Optional[float] = None + log_fatal_warnings = False + log_disable_stdout = False log_errors_only = False + logged_once: T.Set[T.Tuple[str, ...]] = field(default_factory=set) + log_warnings_counter = 0 + log_pager: T.Optional['subprocess.Popen'] = None + + _LOG_FNAME: T.ClassVar[str] = 'meson-log.txt' + + @contextmanager + def no_logging(self) -> T.Iterator[None]: + self.log_disable_stdout = True + try: + yield + finally: + self.log_disable_stdout = False + + @contextmanager + def force_logging(self) -> T.Iterator[None]: + restore = self.log_disable_stdout + self.log_disable_stdout = False + try: + yield + finally: + self.log_disable_stdout = restore + + def set_quiet(self) -> None: + self.log_errors_only = True + + def set_verbose(self) -> None: + self.log_errors_only = False + + def set_timestamp_start(self, start: float) -> None: + self.log_timestamp_start = start + + def shutdown(self) -> T.Optional[str]: + if self.log_file is not None: + path = self.log_file.name + exception_around_goer = self.log_file + self.log_file = None + exception_around_goer.close() + return path + self.stop_pager() + return None + + def start_pager(self) -> None: + if not colorize_console(): + return + pager_cmd = [] + if 'PAGER' in os.environ: + pager_cmd = shlex.split(os.environ['PAGER']) + else: + less = shutil.which('less') + if not less and is_windows(): + git = shutil.which('git') + if git: + path = Path(git).parents[1] / 'usr' / 'bin' + less = shutil.which('less', path=str(path)) + if less: + pager_cmd = [less] + if not pager_cmd: + return + try: + # Set 'LESS' environment variable, rather than arguments in + # pager_cmd, to also support the case where the user has 'PAGER' + # set to 'less'. Arguments set are: + # "R" : support color + # "X" : do not clear the screen when leaving the pager + # "F" : skip the pager if content fits into the screen + env = os.environ.copy() + if 'LESS' not in env: + env['LESS'] = 'RXF' + # Set "-c" for lv to support color + if 'LV' not in env: + env['LV'] = '-c' + self.log_pager = subprocess.Popen(pager_cmd, stdin=subprocess.PIPE, + text=True, encoding='utf-8', env=env) + except Exception as e: + # Ignore errors, unless it is a user defined pager. + if 'PAGER' in os.environ: + from .mesonlib import MesonException + raise MesonException(f'Failed to start pager: {str(e)}') + + def stop_pager(self) -> None: + if self.log_pager: + try: + self.log_pager.stdin.flush() + self.log_pager.stdin.close() + except BrokenPipeError: + pass + self.log_pager.wait() + self.log_pager = None + + def initialize(self, logdir: str, fatal_warnings: bool = False) -> None: + self.log_dir = logdir + self.log_file = open(os.path.join(logdir, self._LOG_FNAME), 'w', encoding='utf-8') + self.log_fatal_warnings = fatal_warnings + + def process_markup(self, args: T.Sequence[TV_Loggable], keep: bool) -> T.List[str]: + arr = [] # type: T.List[str] + if self.log_timestamp_start is not None: + arr = ['[{:.3f}]'.format(time.monotonic() - self.log_timestamp_start)] + for arg in args: + if arg is None: + continue + if isinstance(arg, str): + arr.append(arg) + elif isinstance(arg, AnsiDecorator): + arr.append(arg.get_text(keep)) + else: + arr.append(str(arg)) + return arr + + def force_print(self, *args: str, nested: bool, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + if self.log_disable_stdout: + return + iostr = io.StringIO() + print(*args, sep=sep, end=end, file=iostr) + + raw = iostr.getvalue() + if self.log_depth: + prepend = self.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) -def initialize(logdir: str, fatal_warnings: bool = False) -> None: - global log_dir, log_file, log_fatal_warnings # pylint: disable=global-statement - log_dir = logdir - 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: - global log_timestamp_start # pylint: disable=global-statement - log_timestamp_start = start - -def shutdown() -> T.Optional[str]: - global log_file # pylint: disable=global-statement - if log_file is not None: - path = log_file.name - exception_around_goer = log_file - log_file = None - exception_around_goer.close() - return path - stop_pager() - return None + # _Something_ is going to get printed. + try: + output = self.log_pager.stdin if self.log_pager else None + print(raw, end='', file=output) + except UnicodeEncodeError: + cleaned = raw.encode('ascii', 'replace').decode('ascii') + print(cleaned, end='') + + def debug(self, *args: TV_Loggable, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + arr = process_markup(args, False) + if self.log_file is not None: + print(*arr, file=self.log_file, sep=sep, end=end) + self.log_file.flush() + + def _log(self, *args: TV_Loggable, is_error: bool = False, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + arr = process_markup(args, False) + if self.log_file is not None: + print(*arr, file=self.log_file, sep=sep, end=end) + self.log_file.flush() + if colorize_console(): + arr = process_markup(args, True) + if not self.log_errors_only or is_error: + force_print(*arr, nested=nested, sep=sep, end=end) + + def _debug_log_cmd(self, cmd: str, args: T.List[str]) -> None: + if not _in_ci: + return + args = [f'"{x}"' for x in args] # Quote all args, just in case + self.debug('!meson_ci!/{} {}'.format(cmd, ' '.join(args))) + + def cmd_ci_include(self, file: str) -> None: + self._debug_log_cmd('ci_include', [file]) + + def log(self, *args: TV_Loggable, is_error: bool = False, + once: bool = False, nested: bool = True, + sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + if once: + self._log_once(*args, is_error=is_error, nested=nested, sep=sep, end=end) + else: + self._log(*args, is_error=is_error, nested=nested, sep=sep, end=end) + + def _log_once(self, *args: TV_Loggable, is_error: bool = False, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + """Log variant that only prints a given message one time per meson invocation. + + This considers ansi decorated values by the values they wrap without + regard for the AnsiDecorator itself. + """ + 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 self.logged_once: + return + self.logged_once.add(t) + self._log(*args, is_error=is_error, nested=nested, sep=sep, end=end) + + def _log_error(self, severity: _Severity, *rargs: TV_Loggable, + once: bool = False, fatal: bool = True, + location: T.Optional[BaseNode] = None, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None, + is_error: bool = True) -> None: + from .mesonlib import MesonException, relpath + + # 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 is _Severity.NOTICE: + label = [bold('NOTICE:')] # type: TV_LoggableList + elif severity is _Severity.WARNING: + label = [yellow('WARNING:')] + elif severity is _Severity.ERROR: + label = [red('ERROR:')] + elif severity is _Severity.DEPRECATION: + label = [red('DEPRECATION:')] + # rargs is a tuple, not a list + args = label + list(rargs) + + if location is not None: + 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('TV_LoggableList', [location_str]) + args = location_list + args + + log(*args, once=once, nested=nested, sep=sep, end=end, is_error=is_error) + + self.log_warnings_counter += 1 + + if self.log_fatal_warnings and fatal: + raise MesonException("Fatal warnings enabled, aborting") + + def error(self, *args: TV_Loggable, + once: bool = False, fatal: bool = True, + location: T.Optional[BaseNode] = None, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + return self._log_error(_Severity.ERROR, *args, once=once, fatal=fatal, location=location, + nested=nested, sep=sep, end=end, is_error=True) + + def warning(self, *args: TV_Loggable, + once: bool = False, fatal: bool = True, + location: T.Optional[BaseNode] = None, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + return self._log_error(_Severity.WARNING, *args, once=once, fatal=fatal, location=location, + nested=nested, sep=sep, end=end, is_error=True) + + def deprecation(self, *args: TV_Loggable, + once: bool = False, fatal: bool = True, + location: T.Optional[BaseNode] = None, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + return self._log_error(_Severity.DEPRECATION, *args, once=once, fatal=fatal, location=location, + nested=nested, sep=sep, end=end, is_error=True) + + def notice(self, *args: TV_Loggable, + once: bool = False, fatal: bool = True, + location: T.Optional[BaseNode] = None, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + return self._log_error(_Severity.NOTICE, *args, once=once, fatal=fatal, location=location, + nested=nested, sep=sep, end=end, is_error=False) + + def exception(self, e: Exception, prefix: T.Optional[AnsiDecorator] = None) -> None: + if prefix is None: + prefix = red('ERROR:') + self.log() + args = [] # type: T.List[T.Union[AnsiDecorator, str]] + 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())) # type: ignore + args.append(f'{path}:{e.lineno}:{e.colno}:') # type: ignore + if prefix: + args.append(prefix) + args.append(str(e)) + + with self.force_logging(): + self.log(*args, is_error=True) + + @contextmanager + def nested(self, name: str = '') -> T.Generator[None, None, None]: + self.log_depth.append(name) + try: + yield + finally: + self.log_depth.pop() + + def get_log_dir(self) -> str: + return self.log_dir + + def get_log_depth(self) -> int: + return len(self.log_depth) + + @contextmanager + def nested_warnings(self) -> T.Iterator[None]: + old = self.log_warnings_counter + self.log_warnings_counter = 0 + try: + yield + finally: + self.log_warnings_counter = old + + def get_warning_count(self) -> int: + return self.log_warnings_counter + +_logger = _Logger() +cmd_ci_include = _logger.cmd_ci_include +debug = _logger.debug +deprecation = _logger.deprecation +error = _logger.error +exception = _logger.exception +force_print = _logger.force_print +get_log_depth = _logger.get_log_depth +get_log_dir = _logger.get_log_dir +get_warning_count = _logger.get_warning_count +initialize = _logger.initialize +log = _logger.log +nested = _logger.nested +nested_warnings = _logger.nested_warnings +no_logging = _logger.no_logging +notice = _logger.notice +process_markup = _logger.process_markup +set_quiet = _logger.set_quiet +set_timestamp_start = _logger.set_timestamp_start +set_verbose = _logger.set_verbose +shutdown = _logger.shutdown +start_pager = _logger.start_pager +stop_pager = _logger.stop_pager +warning = _logger.warning class AnsiDecorator: plain_code = "\033[0m" @@ -148,9 +454,6 @@ 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 @@ -201,161 +504,9 @@ def normal_cyan(text: str) -> AnsiDecorator: return AnsiDecorator(text, "\033[36m") -# This really should be AnsiDecorator or anything that implements -# __str__(), but that requires protocols from typing_extensions -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)] - for arg in args: - if arg is None: - continue - if isinstance(arg, str): - arr.append(arg) - elif isinstance(arg, AnsiDecorator): - arr.append(arg.get_text(keep)) - else: - arr.append(str(arg)) - return arr - -def force_print(*args: str, nested: bool, **kwargs: T.Any) -> None: - if log_disable_stdout: - return - iostr = io.StringIO() - kwargs['file'] = iostr - print(*args, **kwargs) - - raw = iostr.getvalue() - 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: - output = log_pager.stdin if log_pager else None - print(raw, end='', file=output) - except UnicodeEncodeError: - cleaned = raw.encode('ascii', 'replace').decode('ascii') - print(cleaned, end='') - -# We really want a heterogeneous dict for this, but that's in typing_extensions -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) - log_file.flush() - -def _debug_log_cmd(cmd: str, args: T.List[str]) -> None: - if not _in_ci: - return - 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: 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(): - arr = process_markup(args, True) - if not log_errors_only or is_error: - force_print(*arr, nested=nested, **kwargs) - -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 ansi decorated values by the values they wrap without - regard for the AnsiDecorator itself. - """ - 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) - -# 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: +def get_error_location_string(fname: StringProtocol, 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 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 == 'notice': - label = [bold('NOTICE:')] # type: TV_LoggableList - elif severity == 'warning': - label = [yellow('WARNING:')] - elif severity == 'error': - label = [red('ERROR:')] - elif severity == 'deprecation': - label = [red('DEPRECATION:')] - else: - raise MesonException('Invalid severity ' + severity) - # rargs is a tuple, not a list - args = label + list(rargs) - - location = kwargs.pop('location', None) - if location is not None: - 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('TV_LoggableList', [location_str]) - args = location_list + args - - log(*args, once=once, **kwargs) - - global log_warnings_counter # pylint: disable=global-statement - log_warnings_counter += 1 - - if log_fatal_warnings and fatal: - raise MesonException("Fatal warnings enabled, aborting") - -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 deprecation(*args: TV_Loggable, **kwargs: T.Any) -> None: - return _log_error('deprecation', *args, **kwargs, is_error=True) - -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""" # Go up "current" until we find a common ancestor to target @@ -371,27 +522,6 @@ # we failed, should not get here return target -def exception(e: Exception, prefix: T.Optional[AnsiDecorator] = None) -> None: - if prefix is None: - prefix = red('ERROR:') - log() - args = [] # type: T.List[T.Union[AnsiDecorator, str]] - 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())) # type: ignore - args.append(f'{path}:{e.lineno}:{e.colno}:') # type: ignore - if prefix: - args.append(prefix) - args.append(str(e)) - - restore = log_disable_stdout - if restore: - enable() - log(*args, is_error=True) - if restore: - disable() - # Format a list for logging purposes as a string. It separates # all but the last item with commas, and the last with 'and'. def format_list(input_list: T.List[str]) -> str: @@ -405,61 +535,13 @@ else: return '' -@contextmanager -def nested(name: str = '') -> T.Generator[None, None, None]: - log_depth.append(name) - try: - yield - finally: - log_depth.pop() - -def start_pager() -> None: - if not colorize_console(): - return - pager_cmd = [] - if 'PAGER' in os.environ: - pager_cmd = shlex.split(os.environ['PAGER']) - else: - less = shutil.which('less') - if not less and is_windows(): - git = shutil.which('git') - if git: - path = Path(git).parents[1] / 'usr' / 'bin' - less = shutil.which('less', path=str(path)) - if less: - pager_cmd = [less] - if not pager_cmd: - return - global log_pager # pylint: disable=global-statement - assert log_pager is None - try: - # Set 'LESS' environment variable, rather than arguments in - # pager_cmd, to also support the case where the user has 'PAGER' - # set to 'less'. Arguments set are: - # "R" : support color - # "X" : do not clear the screen when leaving the pager - # "F" : skip the pager if content fits into the screen - env = os.environ.copy() - if 'LESS' not in env: - env['LESS'] = 'RXF' - # Set "-c" for lv to support color - if 'LV' not in env: - env['LV'] = '-c' - log_pager = subprocess.Popen(pager_cmd, stdin=subprocess.PIPE, - text=True, encoding='utf-8', env=env) - except Exception as e: - # Ignore errors, unless it is a user defined pager. - if 'PAGER' in os.environ: - from .mesonlib import MesonException - raise MesonException(f'Failed to start pager: {str(e)}') -def stop_pager() -> None: - global log_pager # pylint: disable=global-statement - if log_pager: - try: - log_pager.stdin.flush() - log_pager.stdin.close() - except BrokenPipeError: - pass - log_pager.wait() - log_pager = None +def code_line(text: str, line: str, colno: int) -> str: + """Print a line with a caret pointing to the colno + + :param text: A message to display before the line + :param line: The line of code to be pointed to + :param colno: The column number to point at + :return: A formatted string of the text, line, and a caret + """ + return f'{text}\n{line}\n{" " * colno}^' diff -Nru meson-1.0.1/mesonbuild/modules/__init__.py meson-1.2.1/mesonbuild/modules/__init__.py --- meson-1.0.1/mesonbuild/modules/__init__.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/__init__.py 2023-08-07 22:54:34.000000000 +0000 @@ -18,20 +18,19 @@ import dataclasses import typing as T -from .. import mesonlib +from .. import build, mesonlib from ..build import IncludeDirs from ..interpreterbase.decorators import noKwargs, noPosargs from ..mesonlib import relpath, HoldableObject, MachineChoice from ..programs import ExternalProgram if T.TYPE_CHECKING: - from .. import build from ..interpreter import Interpreter from ..interpreter.interpreterobjects import MachineHolder from ..interpreterbase import TYPE_var, TYPE_kwargs from ..programs import OverrideProgram from ..wrap import WrapMode - from ..build import EnvironmentVariables, Executable + from ..build import Executable from ..dependencies import Dependency class ModuleState: @@ -86,10 +85,13 @@ 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, + def find_program(self, prog: T.Union[mesonlib.FileOrString, T.List[mesonlib.FileOrString]], + required: bool = True, + version_func: T.Optional[T.Callable[[T.Union[ExternalProgram, Executable, OverrideProgram]], str]] = None, wanted: T.Optional[str] = None, silent: bool = False, - for_machine: MachineChoice = MachineChoice.HOST) -> 'ExternalProgram': + for_machine: MachineChoice = MachineChoice.HOST) -> T.Union[ExternalProgram, Executable, OverrideProgram]: + if not isinstance(prog, list): + prog = [prog] return self._interpreter.find_program_impl(prog, required=required, version_func=version_func, wanted=wanted, silent=silent, for_machine=for_machine) @@ -117,7 +119,7 @@ def dependency(self, depname: str, native: bool = False, required: bool = True, wanted: T.Optional[str] = None) -> 'Dependency': - kwargs = {'native': native, 'required': required} + kwargs: T.Dict[str, object] = {'native': native, 'required': required} if wanted: kwargs['version'] = wanted # FIXME: Even if we fix the function, mypy still can't figure out what's @@ -142,7 +144,7 @@ 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']: + module: T.Optional[str] = None) -> T.Union[T.List[str], str, int, bool, 'WrapMode']: return self.environment.coredata.get_option(mesonlib.OptionKey(name, subproject, machine, lang, module)) def is_user_defined_option(self, name: str, subproject: str = '', @@ -216,8 +218,8 @@ def found() -> bool: return True - def get_devenv(self) -> T.Optional['EnvironmentVariables']: - return None + def postconf_hook(self, b: build.Build) -> None: + 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 @@ -243,13 +245,11 @@ return False -def is_module_library(fname): +def is_module_library(fname: mesonlib.FileOrString) -> bool: ''' Check if the file is a library-like file generated by a module-specific target, such as GirTarget or TypelibTarget ''' - if hasattr(fname, 'fname'): - fname = fname.fname suffix = fname.split('.')[-1] return suffix in {'gir', 'typelib'} @@ -260,3 +260,18 @@ self.return_value = return_value assert isinstance(new_objects, list) self.new_objects: T.List[T.Union['TYPE_var', 'build.ExecutableSerialisation']] = new_objects + +class GResourceTarget(build.CustomTarget): + pass + +class GResourceHeaderTarget(build.CustomTarget): + pass + +class GirTarget(build.CustomTarget): + pass + +class TypelibTarget(build.CustomTarget): + pass + +class VapiTarget(build.CustomTarget): + pass diff -Nru meson-1.0.1/mesonbuild/modules/cmake.py meson-1.2.1/mesonbuild/modules/cmake.py --- meson-1.0.1/mesonbuild/modules/cmake.py 2022-10-24 19:25:24.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/cmake.py 2023-07-21 20:36:13.000000000 +0000 @@ -47,7 +47,9 @@ from . import ModuleState from ..cmake import SingleTargetOptions - from ..interpreter import kwargs + from ..environment import Environment + from ..interpreter import Interpreter, kwargs + from ..interpreterbase import TYPE_kwargs, TYPE_var class WriteBasicPackageVersionFile(TypedDict): @@ -118,7 +120,7 @@ 'found': self.found_method, }) - def _args_to_info(self, args): + def _args_to_info(self, args: T.List[str]) -> T.Dict[str, str]: if len(args) != 1: raise InterpreterException('Exactly one argument is required.') @@ -135,13 +137,13 @@ @noKwargs @stringArgs - def get_variable(self, state, args, kwargs): + def get_variable(self, state: ModuleState, args: T.List[str], kwargs: TYPE_kwargs) -> TYPE_var: return self.subp.get_variable_method(args, kwargs) @FeatureNewKwargs('dependency', '0.56.0', ['include_type']) @permittedKwargs({'include_type'}) @stringArgs - def dependency(self, state, args, kwargs): + def dependency(self, state: ModuleState, args: T.List[str], kwargs: T.Dict[str, str]) -> dependencies.Dependency: info = self._args_to_info(args) if info['func'] == 'executable': raise InvalidArguments(f'{args[0]} is an executable and does not support the dependency() method. Use target() instead.') @@ -155,31 +157,31 @@ @noKwargs @stringArgs - def include_directories(self, state, args, kwargs): + def include_directories(self, state: ModuleState, args: T.List[str], kwargs: TYPE_kwargs) -> build.IncludeDirs: info = self._args_to_info(args) return self.get_variable(state, [info['inc']], kwargs) @noKwargs @stringArgs - def target(self, state, args, kwargs): + def target(self, state: ModuleState, args: T.List[str], kwargs: TYPE_kwargs) -> build.Target: info = self._args_to_info(args) return self.get_variable(state, [info['tgt']], kwargs) @noKwargs @stringArgs - def target_type(self, state, args, kwargs): + def target_type(self, state: ModuleState, args: T.List[str], kwargs: TYPE_kwargs) -> str: info = self._args_to_info(args) return info['func'] @noPosargs @noKwargs - def target_list(self, state, args, kwargs): + def target_list(self, state: ModuleState, args: TYPE_var, kwargs: TYPE_kwargs) -> T.List[str]: return self.cm_interpreter.target_list() @noPosargs @noKwargs @FeatureNew('CMakeSubproject.found()', '0.53.2') - def found_method(self, state, args, kwargs): + def found_method(self, state: ModuleState, args: TYPE_var, kwargs: TYPE_kwargs) -> bool: return self.subp is not None @@ -205,40 +207,34 @@ return self.target_options[kwargs['target']] return self.target_options.global_options + @typed_pos_args('subproject_options.add_cmake_defines', varargs=dict) @noKwargs - def add_cmake_defines(self, state, args, kwargs) -> None: - self.cmake_options += cmake_defines_to_args(args) + def add_cmake_defines(self, state: ModuleState, args: T.Tuple[T.List[T.Dict[str, TYPE_var]]], kwargs: TYPE_kwargs) -> None: + self.cmake_options += cmake_defines_to_args(args[0]) - @stringArgs + @typed_pos_args('subproject_options.set_override_option', str, str) @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') + def set_override_option(self, state: ModuleState, args: T.Tuple[str, str], kwargs: TYPE_kwargs) -> None: self._get_opts(kwargs).set_opt(args[0], args[1]) + @typed_pos_args('subproject_options.set_install', bool) @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') + def set_install(self, state: ModuleState, args: T.Tuple[bool], kwargs: TYPE_kwargs) -> None: self._get_opts(kwargs).set_install(args[0]) - @stringArgs + @typed_pos_args('subproject_options.append_compile_args', str, varargs=str, min_varargs=1) @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:]) + def append_compile_args(self, state: ModuleState, args: T.Tuple[str, T.List[str]], kwargs: TYPE_kwargs) -> None: + self._get_opts(kwargs).append_args(args[0], args[1]) - @stringArgs + @typed_pos_args('subproject_options.append_compile_args', varargs=str, min_varargs=1) @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) + def append_link_args(self, state: ModuleState, args: T.Tuple[T.List[str]], kwargs: TYPE_kwargs) -> None: + self._get_opts(kwargs).append_link_args(args[0]) @noPosargs @noKwargs - def clear(self, state, args, kwargs) -> None: + def clear(self, state: ModuleState, args: TYPE_var, kwargs: TYPE_kwargs) -> None: self.cmake_options.clear() self.target_options = TargetOptions() @@ -249,7 +245,7 @@ INFO = ModuleInfo('cmake', '0.50.0') - def __init__(self, interpreter): + def __init__(self, interpreter: Interpreter) -> None: super().__init__(interpreter) self.methods.update({ 'write_basic_package_version_file': self.write_basic_package_version_file, @@ -258,7 +254,7 @@ 'subproject_options': self.subproject_options, }) - def detect_voidp_size(self, env): + def detect_voidp_size(self, env: Environment) -> int: compilers = env.coredata.compilers.host compiler = compilers.get('c', None) if not compiler: @@ -267,9 +263,9 @@ if not compiler: raise mesonlib.MesonException('Requires a C or C++ compiler to compute sizeof(void *).') - return compiler.sizeof('void *', '', env) + return compiler.sizeof('void *', '', env)[0] - def detect_cmake(self, state): + def detect_cmake(self, state: ModuleState) -> bool: if self.cmake_detected: return True @@ -301,7 +297,7 @@ KwargInfo('version', str, required=True), INSTALL_DIR_KW, ) - def write_basic_package_version_file(self, state, args, kwargs: 'WriteBasicPackageVersionFile'): + def write_basic_package_version_file(self, state: ModuleState, args: TYPE_var, kwargs: 'WriteBasicPackageVersionFile') -> ModuleReturnValue: arch_independent = kwargs['arch_independent'] compatibility = kwargs['compatibility'] name = kwargs['name'] @@ -321,17 +317,17 @@ version_file = os.path.join(state.environment.scratch_dir, f'{name}ConfigVersion.cmake') - conf = { - 'CVF_VERSION': (version, ''), - 'CMAKE_SIZEOF_VOID_P': (str(self.detect_voidp_size(state.environment)), ''), - 'CVF_ARCH_INDEPENDENT': (arch_independent, ''), + conf: T.Dict[str, T.Union[str, bool, int]] = { + 'CVF_VERSION': version, + 'CMAKE_SIZEOF_VOID_P': str(self.detect_voidp_size(state.environment)), + 'CVF_ARCH_INDEPENDENT': arch_independent, } - mesonlib.do_conf_file(template_file, version_file, conf, 'meson') + mesonlib.do_conf_file(template_file, version_file, build.ConfigurationData(conf), 'meson') 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): + def create_package_file(self, infile: str, outfile: str, PACKAGE_RELATIVE_PATH: str, extra: str, confdata: build.ConfigurationData) -> None: package_init = PACKAGE_INIT_BASE.replace('@PACKAGE_RELATIVE_PATH@', PACKAGE_RELATIVE_PATH) package_init = package_init.replace('@inputFileName@', os.path.basename(infile)) package_init += extra @@ -369,7 +365,7 @@ KwargInfo('name', str, required=True), INSTALL_DIR_KW, ) - def configure_package_config_file(self, state, args, kwargs: 'ConfigurePackageConfigFile'): + def configure_package_config_file(self, state: ModuleState, args: TYPE_var, kwargs: 'ConfigurePackageConfigFile') -> build.Data: inputfile = kwargs['input'] if isinstance(inputfile, str): inputfile = mesonlib.File.from_source_file(state.environment.source_dir, state.subdir, inputfile) @@ -395,7 +391,8 @@ if not os.path.isabs(abs_install_dir): abs_install_dir = os.path.join(prefix, install_dir) - PACKAGE_RELATIVE_PATH = os.path.relpath(prefix, abs_install_dir) + # path used in cmake scripts are POSIX even on Windows + PACKAGE_RELATIVE_PATH = pathlib.PurePath(os.path.relpath(prefix, abs_install_dir)).as_posix() extra = '' if re.match('^(/usr)?/lib(64)?/.+', abs_install_dir): extra = PACKAGE_INIT_EXT.replace('@absInstallDir@', abs_install_dir) @@ -435,7 +432,7 @@ 'required': kwargs_['required'], 'options': kwargs_['options'], 'cmake_options': kwargs_['cmake_options'], - 'default_options': [], + 'default_options': {}, 'version': [], } subp = self.interpreter.do_subproject(dirname, 'cmake', kw) @@ -446,8 +443,8 @@ @FeatureNew('subproject_options', '0.55.0') @noKwargs @noPosargs - def subproject_options(self, state, args, kwargs) -> CMakeSubprojectOptions: + def subproject_options(self, state: ModuleState, args: TYPE_var, kwargs: TYPE_kwargs) -> CMakeSubprojectOptions: return CMakeSubprojectOptions() -def initialize(*args, **kwargs): +def initialize(*args: T.Any, **kwargs: T.Any) -> CmakeModule: return CmakeModule(*args, **kwargs) diff -Nru meson-1.0.1/mesonbuild/modules/cuda.py meson-1.2.1/mesonbuild/modules/cuda.py --- meson-1.0.1/mesonbuild/modules/cuda.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/cuda.py 2023-04-21 10:42:56.000000000 +0000 @@ -237,6 +237,10 @@ cuda_common_gpu_architectures += ['7.5+PTX'] # noqa: E221 cuda_hi_limit_gpu_architecture = '8.0' # noqa: E221 + # need to account for the fact that Ampere is commonly assumed to include + # SM8.0 and SM8.6 even though CUDA 11.0 doesn't support SM8.6 + cuda_ampere_bin = ['8.0'] + cuda_ampere_ptx = ['8.0'] if version_compare(cuda_version, '>=11.0'): cuda_known_gpu_architectures += ['Ampere'] # noqa: E221 cuda_common_gpu_architectures += ['8.0'] # noqa: E221 @@ -249,6 +253,9 @@ cuda_hi_limit_gpu_architecture = '8.6' # noqa: E221 if version_compare(cuda_version, '>=11.1'): + cuda_ampere_bin += ['8.6'] # noqa: E221 + cuda_ampere_ptx = ['8.6'] # noqa: E221 + cuda_common_gpu_architectures += ['8.6'] # noqa: E221 cuda_all_gpu_architectures += ['8.6'] # noqa: E221 @@ -320,7 +327,7 @@ 'Volta': (['7.0'], ['7.0']), 'Xavier': (['7.2'], []), 'Turing': (['7.5'], ['7.5']), - 'Ampere': (['8.0'], ['8.0']), + 'Ampere': (cuda_ampere_bin, cuda_ampere_ptx), 'Orin': (['8.7'], []), 'Lovelace': (['8.9'], ['8.9']), 'Hopper': (['9.0'], ['9.0']), diff -Nru meson-1.0.1/mesonbuild/modules/dlang.py meson-1.2.1/mesonbuild/modules/dlang.py --- meson-1.0.1/mesonbuild/modules/dlang.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/dlang.py 2023-06-28 14:48:20.000000000 +0000 @@ -20,8 +20,9 @@ import os from . import ExtensionModule, ModuleInfo -from .. import dependencies from .. import mlog +from ..dependencies import Dependency +from ..dependencies.dub import DubDependency from ..interpreterbase import typed_pos_args from ..mesonlib import Popen_safe, MesonException @@ -39,7 +40,7 @@ def _init_dub(self, state): if DlangModule.class_dubbin is None: - self.dubbin = dependencies.DubDependency.class_dubbin + self.dubbin = DubDependency.class_dubbin DlangModule.class_dubbin = self.dubbin else: self.dubbin = DlangModule.class_dubbin @@ -82,7 +83,7 @@ config[key] = {} if isinstance(value, list): for dep in value: - if isinstance(dep, dependencies.Dependency): + if isinstance(dep, Dependency): name = dep.get_name() ret, res = self._call_dubbin(['describe', name]) if ret == 0: @@ -91,7 +92,7 @@ config[key][name] = '' else: config[key][name] = version - elif isinstance(value, dependencies.Dependency): + elif isinstance(value, Dependency): name = value.get_name() ret, res = self._call_dubbin(['describe', name]) if ret == 0: diff -Nru meson-1.0.1/mesonbuild/modules/external_project.py meson-1.2.1/mesonbuild/modules/external_project.py --- meson-1.0.1/mesonbuild/modules/external_project.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/external_project.py 2023-08-07 22:54:34.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 __future__ import annotations from pathlib import Path import os @@ -22,7 +23,8 @@ from .. import mlog, build from ..compilers.compilers import CFLAGS_MAPPING from ..envconfig import ENV_VAR_PROG_MAP -from ..dependencies import InternalDependency, PkgConfigDependency +from ..dependencies import InternalDependency +from ..dependencies.pkgconfig import PkgConfigDependency from ..interpreterbase import FeatureNew from ..interpreter.type_checking import ENV_KW, DEPENDS_KW from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args @@ -33,9 +35,10 @@ from typing_extensions import TypedDict from . import ModuleState + from .._typing import ImmutableListProtocol + from ..build import BuildTarget, CustomTarget from ..interpreter import Interpreter from ..interpreterbase import TYPE_var - from ..build import BuildTarget, CustomTarget class Dependency(TypedDict): @@ -51,6 +54,9 @@ class ExternalProject(NewExtensionModule): + + make: ImmutableListProtocol[str] + def __init__(self, state: 'ModuleState', configure_command: str, @@ -199,7 +205,7 @@ 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') + log_filename = Path(mlog.get_log_dir(), f'{self.name}-{step}.log') output = None if not self.verbose: output = open(log_filename, 'w', encoding='utf-8') @@ -223,7 +229,7 @@ '--srcdir', self.src_dir.as_posix(), '--builddir', self.build_dir.as_posix(), '--installdir', self.install_dir.as_posix(), - '--logdir', mlog.log_dir, + '--logdir', mlog.get_log_dir(), '--make', join_args(self.make), ] if self.verbose: @@ -269,7 +275,7 @@ link_args = [f'-L{abs_libdir}', f'-l{libname}'] sources = self.target dep = InternalDependency(version, [], compile_args, link_args, [], - [], [sources], [], {}, [], []) + [], [sources], [], [], {}, [], [], []) return dep diff -Nru meson-1.0.1/mesonbuild/modules/gnome.py meson-1.2.1/mesonbuild/modules/gnome.py --- meson-1.0.1/mesonbuild/modules/gnome.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/gnome.py 2023-08-07 22:54:34.000000000 +0000 @@ -24,20 +24,23 @@ import textwrap import typing as T -from . import ExtensionModule, ModuleInfo -from . import ModuleReturnValue +from . import ( + ExtensionModule, GirTarget, GResourceHeaderTarget, GResourceTarget, ModuleInfo, + ModuleReturnValue, TypelibTarget, VapiTarget, +) from .. import build from .. import interpreter from .. import mesonlib from .. import mlog from ..build import CustomTarget, CustomTargetIndex, Executable, GeneratedList, InvalidArguments -from ..dependencies import Dependency, PkgConfigDependency, InternalDependency -from ..interpreter.type_checking import DEPENDS_KW, DEPEND_FILES_KW, INSTALL_DIR_KW, INSTALL_KW, NoneType, SOURCES_KW, in_set_validator +from ..dependencies import Dependency, InternalDependency +from ..dependencies.pkgconfig import PkgConfigDependency +from ..interpreter.type_checking import DEPENDS_KW, DEPEND_FILES_KW, ENV_KW, INSTALL_DIR_KW, INSTALL_KW, NoneType, SOURCES_KW, 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, join_args, + MachineChoice, MesonException, OrderedSet, Popen_safe, join_args, quote_arg ) from ..programs import OverrideProgram from ..scripts.gettext import read_linguas @@ -248,21 +251,6 @@ return f'element {c+1} {badlist}' return None -class GResourceTarget(build.CustomTarget): - pass - -class GResourceHeaderTarget(build.CustomTarget): - pass - -class GirTarget(build.CustomTarget): - pass - -class TypelibTarget(build.CustomTarget): - pass - -class VapiTarget(build.CustomTarget): - pass - # gresource compilation is broken due to the way # the resource compiler and Ninja clash about it # @@ -319,14 +307,15 @@ gresource_dep_needed_version): mlog.warning('GLib compiled dependencies do not work reliably with \n' 'the current version of GLib. See the following upstream issue:', - mlog.bold('https://bugzilla.gnome.org/show_bug.cgi?id=774368')) + mlog.bold('https://bugzilla.gnome.org/show_bug.cgi?id=774368'), + once=True, fatal=False) @staticmethod 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'), - once=True) + once=True, fatal=False) @typed_kwargs( 'gnome.post_install', @@ -402,7 +391,7 @@ glib_version = self._get_native_glib_version(state) glib_compile_resources = state.find_program('glib-compile-resources') - cmd: T.List[T.Union[ExternalProgram, str]] = [glib_compile_resources, '@INPUT@'] + cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [glib_compile_resources, '@INPUT@'] source_dirs = kwargs['source_dir'] dependencies = kwargs['dependencies'] @@ -419,7 +408,7 @@ 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' \ + m = 'The "dependencies" argument of gnome.compile_resources() cannot\n' \ 'be used with the current version of glib-compile-resources due to\n' \ '' raise MesonException(m) @@ -492,7 +481,7 @@ raise MesonException('GResource header is installed yet export is not enabled') depfile: T.Optional[str] = None - target_cmd: T.List[T.Union[ExternalProgram, str]] + target_cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] if not mesonlib.version_compare(glib_version, gresource_dep_needed_version): # This will eventually go out of sync if dependencies are added target_cmd = cmd @@ -783,8 +772,9 @@ self.devenv = build.EnvironmentVariables() self.devenv.prepend(varname, [value]) - def get_devenv(self) -> T.Optional[build.EnvironmentVariables]: - return self.devenv + def postconf_hook(self, b: build.Build) -> None: + if self.devenv is not None: + b.devenv.append(self.devenv) def _get_gir_dep(self, state: 'ModuleState') -> T.Tuple[Dependency, T.Union[build.Executable, 'ExternalProgram', 'OverrideProgram'], T.Union[build.Executable, 'ExternalProgram', 'OverrideProgram']]: @@ -978,6 +968,10 @@ # settings user could have set in machine file, like PKG_CONFIG_LIBDIR, # SYSROOT, etc. run_env = PkgConfigDependency.get_env(state.environment, MachineChoice.HOST, uninstalled=True) + # g-ir-scanner uses Python's distutils to find the compiler, which uses 'CC' + cc_exelist = state.environment.coredata.compilers.host['c'].get_exelist() + run_env.set('CC', [quote_arg(x) for x in cc_exelist], ' ') + run_env.merge(kwargs['env']) return GirTarget( girfile, @@ -1022,6 +1016,7 @@ install_dir=[install_dir], install_tag=['typelib'], build_by_default=kwargs['build_by_default'], + env=kwargs['env'], ) @staticmethod @@ -1094,6 +1089,7 @@ INSTALL_KW, _BUILD_BY_DEFAULT.evolve(since='0.40.0'), _EXTRA_ARGS_KW, + ENV_KW.evolve(since='1.2.0'), 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'), @@ -1231,7 +1227,7 @@ srcdir = os.path.join(state.build_to_src, state.subdir) outdir = state.subdir - cmd: T.List[T.Union[ExternalProgram, str]] = [state.find_program('glib-compile-schemas'), '--targetdir', outdir, srcdir] + cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [state.find_program('glib-compile-schemas'), '--targetdir', outdir, srcdir] if state.subdir == '': targetname = 'gsettings-compile' else: @@ -1310,7 +1306,7 @@ pot_file = os.path.join('@SOURCE_ROOT@', state.subdir, 'C', project_id + '.pot') pot_sources = [os.path.join('@SOURCE_ROOT@', state.subdir, 'C', s) for s in sources] - pot_args: T.List[T.Union['ExternalProgram', str]] = [itstool, '-o', pot_file] + pot_args: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [itstool, '-o', pot_file] pot_args.extend(pot_sources) pottarget = build.RunTarget(f'help-{project_id}-pot', pot_args, [], os.path.join(state.subdir, 'C'), state.subproject, @@ -1339,7 +1335,7 @@ targets.append(l_data) po_file = l + '.po' - po_args: T.List[T.Union['ExternalProgram', str]] = [ + po_args: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [ msgmerge, '-q', '-o', os.path.join('@SOURCE_ROOT@', l_subdir, po_file), os.path.join('@SOURCE_ROOT@', l_subdir, po_file), pot_file] @@ -1461,6 +1457,7 @@ program_name = 'gtkdoc-' + tool program = state.find_program(program_name) path = program.get_path() + assert path is not None, "This shouldn't be possible since program should be found" t_args.append(f'--{program_name}={path}') if namespace: t_args.append('--namespace=' + namespace) @@ -1595,7 +1592,7 @@ kwargs: 'GdbusCodegen') -> ModuleReturnValue: namebase = args[0] xml_files: T.List[T.Union['FileOrString', build.GeneratedTypes]] = [args[1]] if args[1] else [] - cmd: T.List[T.Union['ExternalProgram', str]] = [state.find_program('gdbus-codegen')] + cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [state.find_program('gdbus-codegen')] cmd.extend(kwargs['extra_args']) # Autocleanup supported? @@ -1913,7 +1910,7 @@ install_dir: T.Optional[T.Sequence[T.Union[str, bool]]] = None, depends: T.Optional[T.Sequence[T.Union[CustomTarget, CustomTargetIndex, BuildTarget]]] = None ) -> build.CustomTarget: - real_cmd: T.List[T.Union[str, ExternalProgram]] = [state.find_program(['glib-mkenums', 'mkenums'])] + real_cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [state.find_program(['glib-mkenums', 'mkenums'])] real_cmd.extend(cmd) _install_dir = install_dir or state.environment.coredata.get_option(mesonlib.OptionKey('includedir')) assert isinstance(_install_dir, str), 'for mypy' @@ -1957,7 +1954,7 @@ new_genmarshal = mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.53.3') - cmd: T.List[T.Union['ExternalProgram', str]] = [state.find_program('glib-genmarshal')] + cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [state.find_program('glib-genmarshal')] if kwargs['prefix']: cmd.extend(['--prefix', kwargs['prefix']]) if kwargs['extra_args']: @@ -1966,7 +1963,8 @@ 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')) + mlog.bold('https://github.com/mesonbuild/meson/pull/2049'), + once=True, fatal=False) for k in ['internal', 'nostdinc', 'skip_source', 'stdinc', 'valist_marshallers']: # Mypy can't figure out that this is correct if kwargs[k]: # type: ignore @@ -2101,7 +2099,7 @@ 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, packages = self._extract_vapi_packages(state, kwargs['packages']) - cmd: T.List[T.Union[str, 'ExternalProgram']] + cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] 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']]) @@ -2146,12 +2144,12 @@ ) # So to try our best to get this to just work we need: - # - link with with the correct library + # - link with the correct library # - include the vapi and dependent vapi files in sources # - 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) diff -Nru meson-1.0.1/mesonbuild/modules/hotdoc.py meson-1.2.1/mesonbuild/modules/hotdoc.py --- meson-1.0.1/mesonbuild/modules/hotdoc.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/hotdoc.py 2023-08-07 22:54:34.000000000 +0000 @@ -247,7 +247,8 @@ ncwd = os.path.join(self.sourcedir, self.subdir) mlog.log('Generating Hotdoc configuration for: ', mlog.bold(self.name)) os.chdir(ncwd) - self.hotdoc.run_hotdoc(self.flatten_config_command()) + if self.hotdoc.run_hotdoc(self.flatten_config_command()) != 0: + raise MesonException('hotdoc failed to configure') os.chdir(cwd) def ensure_file(self, value): @@ -338,9 +339,22 @@ install_script = None if install: + datadir = os.path.join(self.state.get_option('prefix'), self.state.get_option('datadir')) + devhelp = self.kwargs.get('devhelp_activate', False) + if not isinstance(devhelp, bool): + FeatureDeprecated.single_use('hotdoc.generate_doc() devhelp_activate must be boolean', '1.1.0', self.state.subproject) + devhelp = False + if devhelp: + install_from = os.path.join(fullname, 'devhelp') + install_to = os.path.join(datadir, 'devhelp') + else: + install_from = os.path.join(fullname, 'html') + install_to = os.path.join(datadir, 'doc', self.name, 'html') + install_script = self.state.backend.get_executable_serialisation(self.build_command + [ "--internal", "hotdoc", - "--install", os.path.join(fullname, 'html'), + "--install", install_from, + "--docdir", install_to, '--name', self.name, '--builddir', os.path.join(self.builddir, self.subdir)] + self.hotdoc.get_command() + diff -Nru meson-1.0.1/mesonbuild/modules/i18n.py meson-1.2.1/mesonbuild/modules/i18n.py --- meson-1.0.1/mesonbuild/modules/i18n.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/i18n.py 2023-05-30 15:42:56.000000000 +0000 @@ -23,6 +23,7 @@ from ..interpreter.type_checking import CT_BUILD_BY_DEFAULT, CT_INPUT_KW, INSTALL_TAG_KW, OUTPUT_KW, INSTALL_DIR_KW, INSTALL_KW, NoneType, in_set_validator from ..interpreterbase import FeatureNew from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, noPosargs, typed_kwargs, typed_pos_args +from ..programs import ExternalProgram from ..scripts.gettext import read_linguas if T.TYPE_CHECKING: @@ -32,7 +33,6 @@ from ..build import Target from ..interpreter import Interpreter from ..interpreterbase import TYPE_var - from ..programs import ExternalProgram class MergeFile(TypedDict): @@ -134,7 +134,7 @@ 'gettext': self.gettext, 'itstool_join': self.itstool_join, }) - self.tools: T.Dict[str, T.Optional[ExternalProgram]] = { + self.tools: T.Dict[str, T.Optional[T.Union[ExternalProgram, build.Executable]]] = { 'itstool': None, 'msgfmt': None, 'msginit': None, @@ -166,6 +166,15 @@ def merge_file(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'MergeFile') -> ModuleReturnValue: if self.tools['msgfmt'] is None or not self.tools['msgfmt'].found(): self.tools['msgfmt'] = state.find_program('msgfmt', for_machine=mesonlib.MachineChoice.BUILD) + if isinstance(self.tools['msgfmt'], ExternalProgram): + try: + have_version = self.tools['msgfmt'].get_version() + except mesonlib.MesonException as e: + raise mesonlib.MesonException('i18n.merge_file requires GNU msgfmt') from e + want_version = '>=0.19' if kwargs['type'] == 'desktop' else '>=0.19.7' + if not mesonlib.version_compare(have_version, want_version): + msg = f'i18n.merge_file requires GNU msgfmt {want_version} to produce files of type: ' + kwargs['type'] + f' (got: {have_version})' + raise mesonlib.MesonException(msg) podir = path.join(state.build_to_src, state.subdir, kwargs['po_dir']) ddirs = self._get_data_dirs(state, kwargs['data_dirs']) @@ -207,7 +216,7 @@ return ModuleReturnValue(ct, [ct]) - @typed_pos_args('i81n.gettext', str) + @typed_pos_args('i18n.gettext', str) @typed_kwargs( 'i18n.gettext', _ARGS, @@ -285,7 +294,7 @@ path.join(state.subdir, l, 'LC_MESSAGES'), state.subproject, state.environment, - [self.tools['msgfmt'], '@INPUT@', '-o', '@OUTPUT@'], + [self.tools['msgfmt'], '-o', '@OUTPUT@', '@INPUT@'], [po_file], [f'{packagename}.mo'], install=install, diff -Nru meson-1.0.1/mesonbuild/modules/icestorm.py meson-1.2.1/mesonbuild/modules/icestorm.py --- meson-1.0.1/mesonbuild/modules/icestorm.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/icestorm.py 2023-05-23 15:20:02.000000000 +0000 @@ -40,7 +40,7 @@ def __init__(self, interpreter: Interpreter) -> None: super().__init__(interpreter) - self.tools: T.Dict[str, ExternalProgram] = {} + self.tools: T.Dict[str, T.Union[ExternalProgram, build.Executable]] = {} self.methods.update({ 'project': self.project, }) diff -Nru meson-1.0.1/mesonbuild/modules/java.py meson-1.2.1/mesonbuild/modules/java.py --- meson-1.0.1/mesonbuild/modules/java.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/java.py 2023-05-30 15:42:56.000000000 +0000 @@ -42,7 +42,7 @@ def __get_java_compiler(self, state: ModuleState) -> Compiler: if 'java' not in state.environment.coredata.compilers[MachineChoice.BUILD]: - detect_compiler_for(state.environment, 'java', MachineChoice.BUILD) + detect_compiler_for(state.environment, 'java', MachineChoice.BUILD, False) return state.environment.coredata.compilers[MachineChoice.BUILD]['java'] @FeatureNew('java.generate_native_headers', '0.62.0') diff -Nru meson-1.0.1/mesonbuild/modules/keyval.py meson-1.2.1/mesonbuild/modules/keyval.py --- meson-1.0.1/mesonbuild/modules/keyval.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/keyval.py 2023-05-23 15:20:02.000000000 +0000 @@ -55,7 +55,7 @@ return result @noKwargs - @typed_pos_args('keyval.laod', (str, mesonlib.File)) + @typed_pos_args('keyval.load', (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 diff -Nru meson-1.0.1/mesonbuild/modules/pkgconfig.py meson-1.2.1/mesonbuild/modules/pkgconfig.py --- meson-1.0.1/mesonbuild/modules/pkgconfig.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/pkgconfig.py 2023-08-07 22:54:34.000000000 +0000 @@ -26,7 +26,7 @@ from .. import mesonlib from .. import mlog from ..coredata import BUILTIN_DIR_OPTIONS -from ..dependencies import ThreadDependency +from ..dependencies.pkgconfig import PkgConfigDependency from ..interpreter.type_checking import D_MODULE_VERSIONS_KW, INSTALL_DIR_KW, VARIABLES_KW, NoneType from ..interpreterbase import FeatureNew, FeatureDeprecated from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args @@ -99,6 +99,7 @@ def __init__(self, state: ModuleState, name: str, metadata: T.Dict[str, MetaData]) -> None: self.state = state self.name = name + self.metadata = metadata self.pub_libs: T.List[LIBS] = [] self.pub_reqs: T.List[str] = [] self.priv_libs: T.List[LIBS] = [] @@ -106,7 +107,7 @@ self.cflags: T.List[str] = [] self.version_reqs: T.DefaultDict[str, T.Set[str]] = defaultdict(set) self.link_whole_targets: T.List[T.Union[build.CustomTarget, build.CustomTargetIndex, build.StaticLibrary]] = [] - self.metadata = metadata + self.uninstalled_incdirs: mesonlib.OrderedSet[str] = mesonlib.OrderedSet() def add_pub_libs(self, libs: T.List[ANY_DEP]) -> None: p_libs, reqs, cflags = self._process_libs(libs, True) @@ -152,7 +153,7 @@ and obj.get_id() in self.metadata): self._check_generated_pc_deprecation(obj) processed_reqs.append(self.metadata[obj.get_id()].filebase) - elif isinstance(obj, dependencies.PkgConfigDependency): + elif isinstance(obj, PkgConfigDependency): if obj.found(): processed_reqs.append(obj.name) self.add_version_reqs(obj.name, obj.version_reqs) @@ -162,7 +163,7 @@ self.add_version_reqs(name, [version_req] if version_req is not None else None) elif isinstance(obj, dependencies.Dependency) and not obj.found(): pass - elif isinstance(obj, ThreadDependency): + elif isinstance(obj, dependencies.ExternalDependency) and obj.name == 'threads': pass else: raise mesonlib.MesonException('requires argument not a string, ' @@ -173,6 +174,15 @@ def add_cflags(self, cflags: T.List[str]) -> None: self.cflags += mesonlib.stringlistify(cflags) + def _add_uninstalled_incdirs(self, incdirs: T.List[build.IncludeDirs], subdir: T.Optional[str] = None) -> None: + for i in incdirs: + curdir = i.get_curdir() + for d in i.get_incdirs(): + path = os.path.join(curdir, d) + self.uninstalled_incdirs.add(path) + if subdir is not None: + self.uninstalled_incdirs.add(subdir) + def _process_libs( self, libs: T.List[ANY_DEP], public: bool ) -> T.Tuple[T.List[T.Union[str, build.SharedLibrary, build.StaticLibrary, build.CustomTarget, build.CustomTargetIndex]], T.List[str], T.List[str]]: @@ -185,17 +195,20 @@ and obj.get_id() in self.metadata): self._check_generated_pc_deprecation(obj) processed_reqs.append(self.metadata[obj.get_id()].filebase) - elif isinstance(obj, dependencies.ValgrindDependency): + elif isinstance(obj, dependencies.ExternalDependency) and obj.name == 'valgrind': pass - elif isinstance(obj, dependencies.PkgConfigDependency): + elif isinstance(obj, PkgConfigDependency): if obj.found(): processed_reqs.append(obj.name) self.add_version_reqs(obj.name, obj.version_reqs) elif isinstance(obj, dependencies.InternalDependency): if obj.found(): + if obj.objects: + raise mesonlib.MesonException('.pc file cannot refer to individual object files.') processed_libs += obj.get_link_args() processed_cflags += obj.get_compile_args() self._add_lib_dependencies(obj.libraries, obj.whole_libraries, obj.ext_deps, public, private_external_deps=True) + self._add_uninstalled_incdirs(obj.get_include_dirs()) elif isinstance(obj, dependencies.Dependency): if obj.found(): processed_libs += obj.get_link_args() @@ -208,8 +221,10 @@ # than needed build deps. # See https://bugs.freedesktop.org/show_bug.cgi?id=105572 processed_libs.append(obj) + self._add_uninstalled_incdirs(obj.get_include_dirs(), obj.get_subdir()) elif isinstance(obj, (build.SharedLibrary, build.StaticLibrary)): processed_libs.append(obj) + self._add_uninstalled_incdirs(obj.get_include_dirs(), obj.get_subdir()) # 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. @@ -366,6 +381,7 @@ # Track already generated pkg-config files This is stored as a class # variable so that multiple `import()`s share metadata + devenv: T.Optional[build.EnvironmentVariables] = None _metadata: T.ClassVar[T.Dict[str, MetaData]] = {} def __init__(self) -> None: @@ -374,6 +390,10 @@ 'generate': self.generate, }) + def postconf_hook(self, b: build.Build) -> None: + if self.devenv is not None: + b.devenv.append(self.devenv) + def _get_lname(self, l: T.Union[build.SharedLibrary, build.StaticLibrary, build.CustomTarget, build.CustomTargetIndex], msg: str, pcfile: str) -> str: if isinstance(l, (build.CustomTargetIndex, build.CustomTarget)): @@ -422,8 +442,8 @@ return ('${prefix}' / libdir).as_posix() def _generate_pkgconfig_file(self, state: ModuleState, deps: DependenciesHelper, - subdirs: T.List[str], name: T.Optional[str], - description: T.Optional[str], url: str, version: str, + subdirs: T.List[str], name: str, + description: str, url: str, version: str, pcfile: str, conflicts: T.List[str], variables: T.List[T.Tuple[str, str]], unescaped_variables: T.List[T.Tuple[str, str]], @@ -554,27 +574,6 @@ if isinstance(l, (build.CustomTarget, build.CustomTargetIndex)) or 'cs' not in l.compilers: yield f'-l{lname}' - def get_uninstalled_include_dirs(libs: T.List[LIBS]) -> T.List[str]: - result: T.List[str] = [] - 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: T.List[LIBS]) -> T.Iterable[str]: - 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: @@ -582,7 +581,10 @@ cflags: T.List[str] = [] if uninstalled: - cflags += generate_uninstalled_cflags(deps.pub_libs + deps.priv_libs) + for d in deps.uninstalled_incdirs: + for basedir in ['${prefix}', '${srcdir}']: + path = self._escape(PurePath(basedir, d).as_posix()) + cflags.append(f'-I{path}') else: for d in subdirs: if d == '.': @@ -636,11 +638,13 @@ else: if kwargs['version'] is None: FeatureNew.single_use('pkgconfig.generate implicit version keyword', '0.46.0', state.subproject) + msg = ('pkgconfig.generate: if a library is not passed as a ' + 'positional argument, the {!r} keyword argument is ' + 'required.') if kwargs['name'] is None: - raise build.InvalidArguments( - 'pkgconfig.generate: if a library is not passed as a ' - 'positional argument, the name keyword argument is ' - 'required.') + raise build.InvalidArguments(msg.format('name')) + if kwargs['description'] is None: + raise build.InvalidArguments(msg.format('description')) dataonly = kwargs['dataonly'] if dataonly: @@ -735,6 +739,8 @@ if not isinstance(lib, str) and lib.get_id() not in self._metadata: self._metadata[lib.get_id()] = MetaData( filebase, name, state.current_node) + if self.devenv is None: + self.devenv = PkgConfigDependency.get_env(state.environment, mesonlib.MachineChoice.HOST, uninstalled=True) return ModuleReturnValue(res, [res]) diff -Nru meson-1.0.1/mesonbuild/modules/python.py meson-1.2.1/mesonbuild/modules/python.py --- meson-1.0.1/mesonbuild/modules/python.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/python.py 2023-08-07 22:54:34.000000000 +0000 @@ -13,12 +13,7 @@ # limitations under the License. from __future__ import annotations -from pathlib import Path -import copy -import functools -import json -import os -import shutil +import copy, json, os, shutil import typing as T from . import ExtensionModule, ModuleInfo @@ -26,10 +21,9 @@ 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 ..dependencies.detect import get_dep_identifier -from ..environment import detect_cpu_family +from ..dependencies import NotFoundDependency +from ..dependencies.detect import get_dep_identifier, find_external_dependency +from ..dependencies.python import BasicPythonExternalProgram, python_factory, _PythonDependencyBase from ..interpreter import ExternalProgramHolder, extract_required_kwarg, permitted_dependency_kwargs from ..interpreter import primitives as P_OBJ from ..interpreter.type_checking import NoneType, PRESERVE_PATH_KW @@ -45,27 +39,12 @@ from typing_extensions import TypedDict from . import ModuleState - from ..build import SharedModule, Data - from ..dependencies import ExternalDependency, Dependency - from ..dependencies.factory import DependencyGenerator - from ..environment import Environment + from ..build import Build, SharedModule, Data + from ..dependencies import Dependency from ..interpreter import Interpreter from ..interpreter.kwargs import ExtractRequired from ..interpreterbase.interpreterbase import TYPE_var, TYPE_kwargs - class PythonIntrospectionDict(TypedDict): - - install_paths: T.Dict[str, str] - is_pypy: bool - is_venv: bool - link_libpython: bool - sysconfig_paths: T.Dict[str, str] - paths: T.Dict[str, str] - platform: str - suffix: str - variables: T.Dict[str, str] - version: str - class PyInstallKw(TypedDict): pure: T.Optional[bool] @@ -78,403 +57,25 @@ modules: T.List[str] pure: T.Optional[bool] - _Base = ExternalDependency -else: - _Base = object - mod_kwargs = {'subdir'} mod_kwargs.update(known_shmod_kwargs) mod_kwargs -= {'name_prefix', 'name_suffix'} -class _PythonDependencyBase(_Base): - - def __init__(self, python_holder: 'PythonInstallation', embed: bool): - self.embed = embed - self.version: str = python_holder.version - self.platform = python_holder.platform - self.variables = python_holder.variables - self.paths = python_holder.paths - # The "-embed" version of python.pc / python-config was introduced in 3.8, - # and distutils extension linking was changed to be considered a non embed - # usage. Before then, this dependency always uses the embed=True handling - # because that is the only one that exists. - # - # On macOS and some Linux distros (Debian) distutils doesn't link extensions - # against libpython, even on 3.7 and below. We call into distutils and - # mirror its behavior. See https://github.com/mesonbuild/meson/issues/4117 - self.link_libpython = python_holder.link_libpython or embed - 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 - - -class PythonPkgConfigDependency(PkgConfigDependency, _PythonDependencyBase): - - def __init__(self, name: str, environment: 'Environment', - kwargs: T.Dict[str, T.Any], installation: 'PythonInstallation', - libpc: bool = False): - if libpc: - mlog.debug(f'Searching for {name!r} via pkgconfig lookup in LIBPC') - else: - mlog.debug(f'Searching for {name!r} via fallback pkgconfig lookup in default paths') - - PkgConfigDependency.__init__(self, name, environment, kwargs) - _PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False)) - - if libpc and not self.is_found: - mlog.debug(f'"python-{self.version}" could not be found in LIBPC, this is likely due to a relocated python installation') - - # pkg-config files are usually accurate starting with python 3.8 - if not self.link_libpython and mesonlib.version_compare(self.version, '< 3.8'): - self.link_args = [] - - -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)) - - -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: - self._find_libpy(installation, environment) +class PythonExternalProgram(BasicPythonExternalProgram): - if not self.link_libpython: - # match pkg-config behavior - self.link_args = [] - - if not self.clib_compiler.has_header('Python.h', '', environment, extra_args=self.compile_args): - self.is_found = False - - def _find_libpy(self, python_holder: 'PythonInstallation', environment: 'Environment') -> None: - if python_holder.is_pypy: - if self.major_version == 3: - libname = 'pypy3-c' - else: - libname = 'pypy-c' - libdir = os.path.join(self.variables.get('base'), 'bin') - libdirs = [libdir] - else: - libname = f'python{self.version}' - if 'DEBUG_EXT' in self.variables: - libname += self.variables['DEBUG_EXT'] - if 'ABIFLAGS' in self.variables: - libname += self.variables['ABIFLAGS'] - libdirs = [] - - largs = self.clib_compiler.find_library(libname, environment, libdirs) - if largs is not None: - self.link_args = largs - - self.is_found = largs is not None or not self.link_libpython - - inc_paths = mesonlib.OrderedSet([ - self.variables.get('INCLUDEPY'), - self.paths.get('include'), - self.paths.get('platinclude')]) - - self.compile_args += ['-I' + path for path in inc_paths if path] - - def _get_windows_python_arch(self) -> T.Optional[str]: - if self.platform == 'mingw': - pycc = self.variables.get('CC') - if pycc.startswith('x86_64'): - return '64' - elif pycc.startswith(('i686', 'i386')): - return '32' - else: - 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(f'Unknown Windows Python platform {self.platform!r}') - return None - - def _get_windows_link_args(self) -> T.Optional[T.List[str]]: - if self.platform.startswith('win'): - vernum = self.variables.get('py_version_nodot') - verdot = self.variables.get('py_version_short') - imp_lower = self.variables.get('implementation_lower', 'python') - if self.static: - libpath = Path('libs') / f'libpython{vernum}.a' - else: - comp = self.get_compiler() - if comp.id == "gcc": - if imp_lower == 'pypy' and verdot == '3.8': - # The naming changed between 3.8 and 3.9 - libpath = Path('libpypy3-c.dll') - elif imp_lower == 'pypy': - libpath = Path(f'libpypy{verdot}-c.dll') - else: - libpath = Path(f'python{vernum}.dll') - else: - 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: '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() - if pyarch is None: - self.is_found = False - return - arch = detect_cpu_family(env.coredata.compilers.host) - if arch == 'x86': - arch = '32' - elif arch == 'x86_64': - arch = '64' - else: - # We can't cross-compile Python 3 dependencies on Windows yet - 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), 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() - if largs is None: - self.is_found = False - return - self.link_args = largs - # Compile args - inc_paths = mesonlib.OrderedSet([ - self.variables.get('INCLUDEPY'), - self.paths.get('include'), - self.paths.get('platinclude')]) - - self.compile_args += ['-I' + path for path in inc_paths if path] - - # https://sourceforge.net/p/mingw-w64/mailman/message/30504611/ - # https://github.com/python/cpython/pull/100137 - if pyarch == '64' and mesonlib.version_compare(self.version, '<3.12'): - self.compile_args += ['-DMS_WIN64'] - - self.is_found = True - - -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': - if not pkg_libdir: - # there is no LIBPC, so we can't search in it - return NotFoundDependency('python', env) - - old_pkg_libdir = os.environ.pop('PKG_CONFIG_LIBDIR', None) - old_pkg_path = os.environ.pop('PKG_CONFIG_PATH', None) - os.environ['PKG_CONFIG_LIBDIR'] = pkg_libdir - try: - return PythonPkgConfigDependency(name, env, kwargs, installation, True) - 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.append(functools.partial(wrap_in_pythons_pc_dir, pkg_name, env, kwargs, installation)) - # We only need to check both, if a python install has a LIBPC. It might point to the wrong location, - # e.g. relocated / cross compilation, but the presence of LIBPC indicates we should definitely look for something. - if pkg_libdir is not None: - candidates.append(functools.partial(PythonPkgConfigDependency, pkg_name, env, kwargs, installation)) - - if DependencyMethods.SYSTEM in methods: - candidates.append(functools.partial(PythonSystemDependency, 'python', env, kwargs, installation)) - - 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 - -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 - cmd = Distribution().get_command_obj('build_ext') - cmd.ensure_finalized() - return bool(cmd.get_libraries(Extension('dummy', []))) - -variables = sysconfig.get_config_vars() -variables.update({'base_prefix': getattr(sys, 'base_prefix', sys.prefix)}) - -if sys.version_info < (3, 0): - suffix = variables.get('SO') -elif sys.version_info < (3, 8, 7): - # https://bugs.python.org/issue?@action=redirect&bpo=39825 - from distutils.sysconfig import get_config_var - suffix = get_config_var('EXT_SUFFIX') -else: - suffix = variables.get('EXT_SUFFIX') - -print(json.dumps({ - 'variables': variables, - 'paths': paths, - 'sysconfig_paths': sysconfig.get_paths(), - 'install_paths': install_paths, - 'version': sysconfig.get_python_version(), - 'platform': sysconfig.get_platform(), - 'is_pypy': '__pypy__' in sys.builtin_module_names, - 'is_venv': sys.prefix != variables['base_prefix'], - 'link_libpython': links_against_libpython(), - 'suffix': suffix, -})) -''' - - -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, - 'is_venv': False, - 'link_libpython': False, - 'sysconfig_paths': {}, - 'paths': {}, - 'platform': 'sentinal', - 'variables': {}, - 'version': '0.0', - } - self.pure: bool = True - - 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 + # This is a ClassVar instead of an instance bool, because although an + # installation is cached, we actually copy it, modify attributes such as pure, + # and return a temporary one rather than the cached object. + run_bytecompile: T.ClassVar[T.Dict[str, bool]] = {} def sanity(self, state: T.Optional['ModuleState'] = None) -> bool: - # Sanity check, we expect to have something that at least quacks in tune - from tempfile import NamedTemporaryFile - with NamedTemporaryFile(suffix='.py', delete=False, mode='w', encoding='utf-8') as tf: - tmpfilename = tf.name - tf.write(INTROSPECT_COMMAND) - cmd = self.get_command() + [tmpfilename] - p, stdout, stderr = mesonlib.Popen_safe(cmd) - os.unlink(tmpfilename) - 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']): - self.info = T.cast('PythonIntrospectionDict', info) + ret = super().sanity() + if ret: self.platlib = self._get_path(state, 'platlib') self.purelib = self._get_path(state, 'purelib') - return True - else: - return False + return ret def _get_path(self, state: T.Optional['ModuleState'], key: str) -> None: rel_path = self.info['install_paths'][key][1:] @@ -584,13 +185,8 @@ new_kwargs = kwargs.copy() new_kwargs['required'] = False - methods = process_method_kw({DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM}, kwargs) - # it's theoretically (though not practically) possible to not bind dep, let's ensure it is. - dep: Dependency = NotFoundDependency('python', self.interpreter.environment) - for d in python_factory(self.interpreter.environment, for_machine, new_kwargs, methods, self): - dep = d() - if dep.found(): - break + candidates = python_factory(self.interpreter.environment, for_machine, new_kwargs, self.held_object) + dep = find_external_dependency('python', self.interpreter.environment, new_kwargs, candidates) self.interpreter.coredata.deps[for_machine].put(identifier, dep) return dep @@ -620,6 +216,7 @@ ) def install_sources_method(self, args: T.Tuple[T.List[T.Union[str, mesonlib.File]]], kwargs: 'PyInstallKw') -> 'Data': + self.held_object.run_bytecompile[self.version] = True tag = kwargs['install_tag'] or 'python-runtime' pure = kwargs['pure'] if kwargs['pure'] is not None else self.pure install_dir = self._get_install_dir_impl(pure, kwargs['subdir']) @@ -633,6 +230,7 @@ @noPosargs @typed_kwargs('python_installation.install_dir', _PURE_KW, _SUBDIR_KW) def get_install_dir_method(self, args: T.List['TYPE_var'], kwargs: 'PyInstallKw') -> str: + self.held_object.run_bytecompile[self.version] = True pure = kwargs['pure'] if kwargs['pure'] is not None else self.pure return self._get_install_dir_impl(pure, kwargs['subdir']) @@ -701,15 +299,67 @@ 'find_installation': self.find_installation, }) + def _get_install_scripts(self) -> T.List[mesonlib.ExecutableSerialisation]: + backend = self.interpreter.backend + ret = [] + optlevel = self.interpreter.environment.coredata.get_option(mesonlib.OptionKey('bytecompile', module='python')) + if optlevel == -1: + return ret + if not any(PythonExternalProgram.run_bytecompile.values()): + return ret + + installdata = backend.create_install_data() + py_files = [] + + def should_append(f, isdir: bool = False): + # This uses the install_plan decorated names to see if the original source was propagated via + # install_sources() or get_install_dir(). + return f.startswith(('{py_platlib}', '{py_purelib}')) and (f.endswith('.py') or isdir) + + for t in installdata.targets: + if should_append(t.out_name): + py_files.append((t.out_name, os.path.join(installdata.prefix, t.outdir, os.path.basename(t.fname)))) + for d in installdata.data: + if should_append(d.install_path_name): + py_files.append((d.install_path_name, os.path.join(installdata.prefix, d.install_path))) + for d in installdata.install_subdirs: + if should_append(d.install_path_name, True): + py_files.append((d.install_path_name, os.path.join(installdata.prefix, d.install_path))) + + import importlib.resources + pycompile = os.path.join(self.interpreter.environment.get_scratch_dir(), 'pycompile.py') + with open(pycompile, 'wb') as f: + f.write(importlib.resources.read_binary('mesonbuild.scripts', 'pycompile.py')) + + for i in self.installations.values(): + if isinstance(i, PythonExternalProgram) and i.run_bytecompile[i.info['version']]: + i = T.cast(PythonExternalProgram, i) + manifest = f'python-{i.info["version"]}-installed.json' + manifest_json = [] + for name, f in py_files: + if f.startswith((os.path.join(installdata.prefix, i.platlib), os.path.join(installdata.prefix, i.purelib))): + manifest_json.append(name) + with open(os.path.join(self.interpreter.environment.get_scratch_dir(), manifest), 'w', encoding='utf-8') as f: + json.dump(manifest_json, f) + cmd = i.command + [pycompile, manifest, str(optlevel)] + + script = backend.get_executable_serialisation(cmd, verbose=True, tag='python-runtime', + installdir_map={'py_purelib': i.purelib, 'py_platlib': i.platlib}) + ret.append(script) + return ret + + def postconf_hook(self, b: Build) -> None: + b.install_scripts.extend(self._get_install_scripts()) + # https://www.python.org/dev/peps/pep-0397/ @staticmethod def _get_win_pythonpath(name_or_path: str) -> T.Optional[str]: - if name_or_path not in ['python2', 'python3']: + if not name_or_path.startswith(('python2', 'python3')): return None if not shutil.which('py'): # program not installed, return without an exception return None - ver = {'python2': '-2', 'python3': '-3'}[name_or_path] + ver = f'-{name_or_path[6:]}' cmd = ['py', ver, '-c', "import sysconfig; print(sysconfig.get_config_var('BINDIR'))"] _, stdout, _ = mesonlib.Popen_safe(cmd) directory = stdout.strip() @@ -736,7 +386,8 @@ # 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 = PythonExternalProgram('python') + tmp_python = ExternalProgram.from_entry(display_name, 'python') + python = PythonExternalProgram(name_or_path, ext_prog=tmp_python) if python.found(): if python.sanity(state): @@ -748,7 +399,7 @@ else: mlog.warning(sanitymsg, location=state.current_node) - return NonExistingExternalProgram() + return NonExistingExternalProgram(python.name) @disablerIfNotFound @typed_pos_args('python.find_installation', optargs=[str]) @@ -816,14 +467,15 @@ if not python.found(): if required: raise mesonlib.MesonException('{} not found'.format(name_or_path or 'python')) - return NonExistingExternalProgram() + return NonExistingExternalProgram(python.name) elif missing_modules: if required: raise mesonlib.MesonException('{} is missing modules: {}'.format(name_or_path or 'python', ', '.join(missing_modules))) - return NonExistingExternalProgram() + return NonExistingExternalProgram(python.name) else: python = copy.copy(python) python.pure = kwargs['pure'] + python.run_bytecompile.setdefault(python.info['version'], False) return python raise mesonlib.MesonBugException('Unreachable code was reached (PythonModule.find_installation).') diff -Nru meson-1.0.1/mesonbuild/modules/qt.py meson-1.2.1/mesonbuild/modules/qt.py --- meson-1.0.1/mesonbuild/modules/qt.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/qt.py 2023-05-23 15:20:02.000000000 +0000 @@ -108,7 +108,7 @@ self.qt_version = qt_version # It is important that this list does not change order as the order of # the returned ExternalPrograms will change as well - self.tools: T.Dict[str, ExternalProgram] = { + self.tools: T.Dict[str, T.Union[ExternalProgram, build.Executable]] = { 'moc': NonExistingExternalProgram('moc'), 'uic': NonExistingExternalProgram('uic'), 'rcc': NonExistingExternalProgram('rcc'), @@ -152,7 +152,7 @@ arg = ['-v'] # Ensure that the version of qt and each tool are the same - def get_version(p: ExternalProgram) -> str: + def get_version(p: T.Union[ExternalProgram, build.Executable]) -> str: _, out, err = Popen_safe(p.get_command() + arg) if name == 'lrelease' or not qt_dep.version.startswith('4'): care = out @@ -587,7 +587,7 @@ ts = os.path.basename(ts) else: outdir = state.subdir - cmd: T.List[T.Union[ExternalProgram, str]] = [self.tools['lrelease'], '@INPUT@', '-qm', '@OUTPUT@'] + cmd: T.List[T.Union[ExternalProgram, build.Executable, str]] = [self.tools['lrelease'], '@INPUT@', '-qm', '@OUTPUT@'] lrelease_target = build.CustomTarget( f'qt{self.qt_version}-compile-{ts}', outdir, diff -Nru meson-1.0.1/mesonbuild/modules/qt4.py meson-1.2.1/mesonbuild/modules/qt4.py --- meson-1.0.1/mesonbuild/modules/qt4.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/qt4.py 2023-05-23 15:20:02.000000000 +0000 @@ -12,17 +12,23 @@ # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations +import typing as T + from .qt import QtBaseModule from . import ModuleInfo +if T.TYPE_CHECKING: + from ..interpreter import Interpreter + class Qt4Module(QtBaseModule): INFO = ModuleInfo('qt4') - def __init__(self, interpreter): + def __init__(self, interpreter: Interpreter): QtBaseModule.__init__(self, interpreter, qt_version=4) -def initialize(*args, **kwargs): - return Qt4Module(*args, **kwargs) +def initialize(interp: Interpreter) -> Qt4Module: + return Qt4Module(interp) diff -Nru meson-1.0.1/mesonbuild/modules/qt5.py meson-1.2.1/mesonbuild/modules/qt5.py --- meson-1.0.1/mesonbuild/modules/qt5.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/qt5.py 2023-05-23 15:20:02.000000000 +0000 @@ -12,17 +12,23 @@ # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations +import typing as T + from .qt import QtBaseModule from . import ModuleInfo +if T.TYPE_CHECKING: + from ..interpreter import Interpreter + class Qt5Module(QtBaseModule): INFO = ModuleInfo('qt5') - def __init__(self, interpreter): + def __init__(self, interpreter: Interpreter): QtBaseModule.__init__(self, interpreter, qt_version=5) -def initialize(*args, **kwargs): - return Qt5Module(*args, **kwargs) +def initialize(interp: Interpreter) -> Qt5Module: + return Qt5Module(interp) diff -Nru meson-1.0.1/mesonbuild/modules/qt6.py meson-1.2.1/mesonbuild/modules/qt6.py --- meson-1.0.1/mesonbuild/modules/qt6.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/qt6.py 2023-05-23 15:20:02.000000000 +0000 @@ -12,17 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations +import typing as T + from .qt import QtBaseModule from . import ModuleInfo +if T.TYPE_CHECKING: + from ..interpreter import Interpreter class Qt6Module(QtBaseModule): INFO = ModuleInfo('qt6', '0.57.0') - def __init__(self, interpreter): + def __init__(self, interpreter: Interpreter): QtBaseModule.__init__(self, interpreter, qt_version=6) -def initialize(*args, **kwargs): - return Qt6Module(*args, **kwargs) +def initialize(interp: Interpreter) -> Qt6Module: + return Qt6Module(interp) diff -Nru meson-1.0.1/mesonbuild/modules/rust.py meson-1.2.1/mesonbuild/modules/rust.py --- meson-1.0.1/mesonbuild/modules/rust.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/rust.py 2023-08-07 22:54:34.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright © 2020-2022 Intel Corporation +# Copyright © 2020-2023 Intel Corporation # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,18 +18,20 @@ from . import ExtensionModule, ModuleReturnValue, ModuleInfo from .. import mlog -from ..build import BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, IncludeDirs, CustomTarget, StructuredSources +from ..build import BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, IncludeDirs, CustomTarget, InvalidArguments, Jar, StructuredSources +from ..compilers.compilers import are_asserts_disabled from ..dependencies import Dependency, ExternalLibrary -from ..interpreter.type_checking import DEPENDENCIES_KW, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES, include_dir_string_new +from ..interpreter.type_checking import DEPENDENCIES_KW, LINK_WITH_KW, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs from ..mesonlib import File if T.TYPE_CHECKING: from . import ModuleState + from ..build import LibTypes from ..interpreter import Interpreter from ..interpreter import kwargs as _kwargs from ..interpreter.interpreter import SourceInputs, SourceOutputs - from ..programs import ExternalProgram + from ..programs import ExternalProgram, OverrideProgram from typing_extensions import TypedDict @@ -37,6 +39,8 @@ dependencies: T.List[T.Union[Dependency, ExternalLibrary]] is_parallel: bool + link_with: T.List[LibTypes] + rust_args: T.List[str] class FuncBindgen(TypedDict): @@ -56,7 +60,7 @@ def __init__(self, interpreter: Interpreter) -> None: super().__init__(interpreter) - self._bindgen_bin: T.Optional[ExternalProgram] = None + self._bindgen_bin: T.Optional[T.Union[ExternalProgram, Executable, OverrideProgram]] = None self.methods.update({ 'test': self.test, 'bindgen': self.bindgen, @@ -67,6 +71,14 @@ 'rust.test', *TEST_KWS, DEPENDENCIES_KW, + LINK_WITH_KW.evolve(since='1.2.0'), + KwargInfo( + 'rust_args', + ContainerTypeInfo(list, str), + listify=True, + default=[], + since='1.2.0', + ), KwargInfo('is_parallel', bool, default=False), ) def test(self, state: ModuleState, args: T.Tuple[str, BuildTarget], kwargs: FuncTest) -> ModuleReturnValue: @@ -111,6 +123,9 @@ rust.test('rust_lib_test', rust_lib) ``` """ + if any(isinstance(t, Jar) for t in kwargs.get('link_with', [])): + raise InvalidArguments('Rust tests cannot link with Jar targets') + name = args[0] base_target: BuildTarget = args[1] if not base_target.uses_rust(): @@ -138,12 +153,14 @@ tkwargs['args'] = extra_args + ['--test', '--format', 'pretty'] tkwargs['protocol'] = 'rust' - new_target_kwargs = base_target.kwargs.copy() + new_target_kwargs = base_target.original_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['rust_args'] = \ + new_target_kwargs.get('rust_args', []) + kwargs['rust_args'] + ['--test'] new_target_kwargs['install'] = False new_target_kwargs['dependencies'] = new_target_kwargs.get('dependencies', []) + kwargs['dependencies'] + new_target_kwargs['link_with'] = new_target_kwargs.get('link_with', []) + kwargs['link_with'] sources = T.cast('T.List[SourceOutputs]', base_target.sources.copy()) sources.extend(base_target.generated) @@ -172,7 +189,7 @@ listify=True, required=True, ), - INCLUDE_DIRECTORIES.evolve(feature_validator=include_dir_string_new), + INCLUDE_DIRECTORIES.evolve(since_values={ContainerTypeInfo(list, str): '1.0.0'}), OUTPUT_KW, DEPENDENCIES_KW.evolve(since='1.0.0'), ) @@ -193,11 +210,16 @@ else: depends.append(d) - clang_args: T.List[str] = [] + # Copy to avoid subsequent calls mutating the original + # TODO: if we want this to be per-machine we'll need a native kwarg + clang_args = state.environment.properties.host.get_bindgen_clang_args().copy() + for i in state.process_include_dirs(kwargs['include_directories']): # bindgen always uses clang, so it's safe to hardcode -I here clang_args.extend([f'-I{x}' for x in i.to_string_list( state.environment.get_source_dir(), state.environment.get_build_dir())]) + if are_asserts_disabled(state.environment.coredata.options): + clang_args.append('-DNDEBUG') for de in kwargs['dependencies']: for i in de.get_include_dirs(): diff -Nru meson-1.0.1/mesonbuild/modules/windows.py meson-1.2.1/mesonbuild/modules/windows.py --- meson-1.0.1/mesonbuild/modules/windows.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/modules/windows.py 2023-07-21 20:36:13.000000000 +0000 @@ -86,7 +86,8 @@ if not rescomp or not rescomp.found(): comp = self.detect_compiler(state.environment.coredata.compilers[for_machine]) - if comp.id in {'msvc', 'clang-cl', 'intel-cl'}: + if comp.id in {'msvc', 'clang-cl', 'intel-cl'} or (comp.linker and comp.linker.id in {'link', 'lld-link'}): + # Microsoft compilers uses rc irrespective of the frontend rescomp = ExternalProgram('rc', silent=True) else: rescomp = ExternalProgram('windres', silent=True) @@ -96,6 +97,7 @@ for (arg, match, rc_type) in [ ('/?', '^.*Microsoft.*Resource Compiler.*$', ResourceCompilerType.rc), + ('/?', 'LLVM Resource Converter.*$', ResourceCompilerType.rc), ('--version', '^.*GNU windres.*$', ResourceCompilerType.windres), ('--version', '^.*Wine Resource Compiler.*$', ResourceCompilerType.wrc), ]: @@ -164,7 +166,7 @@ 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 + # This dance avoids a case where two indexes 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) diff -Nru meson-1.0.1/mesonbuild/mparser.py meson-1.2.1/mesonbuild/mparser.py --- meson-1.0.1/mesonbuild/mparser.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/mparser.py 2023-06-28 14:48:20.000000000 +0000 @@ -12,12 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. from __future__ import annotations - -from dataclasses import dataclass +from dataclasses import dataclass, field import re import codecs -import types +import os import typing as T + from .mesonlib import MesonException from . import mlog @@ -37,25 +37,20 @@ | \\[\\'abfnrtv] # Single-character escapes )''', re.UNICODE | re.VERBOSE) -class MesonUnicodeDecodeError(MesonException): - def __init__(self, match: str) -> None: - super().__init__(match) - self.match = match - def decode_match(match: T.Match[str]) -> str: - try: - return codecs.decode(match.group(0).encode(), 'unicode_escape') - except UnicodeDecodeError: - raise MesonUnicodeDecodeError(match.group(0)) + return codecs.decode(match.group(0).encode(), 'unicode_escape') class ParseException(MesonException): + + ast: T.Optional[CodeBlockNode] = None + 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__("{}\n{}\n{}".format(text, line, '{}^'.format(' ' * colno))) + super().__init__(mlog.code_line(text, line, colno)) self.lineno = lineno self.colno = colno -class BlockParseException(MesonException): +class BlockParseException(ParseException): def __init__( self, text: str, @@ -75,7 +70,7 @@ # Followed by a caret to show the block start # Followed by underscores # Followed by a caret to show the block end. - super().__init__("{}\n{}\n{}".format(text, line, '{}^{}^'.format(' ' * start_colno, '_' * (colno - start_colno - 1)))) + MesonException.__init__(self, "{}\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 @@ -84,7 +79,7 @@ # Followed by a message saying where the block started. # Followed by the line of the block start. # Followed by a caret for the block start. - super().__init__("%s\n%s\n%s\nFor a block that started at %d,%d\n%s\n%s" % (text, line, '%s^' % (' ' * colno), start_lineno, start_colno, start_line, "%s^" % (' ' * start_colno))) + MesonException.__init__(self, "%s\n%s\n%s\nFor a block that started at %d,%d\n%s\n%s" % (text, line, '%s^' % (' ' * colno), start_lineno, start_colno, start_line, "%s^" % (' ' * start_colno))) self.lineno = lineno self.colno = colno @@ -114,6 +109,9 @@ 'endif', 'and', 'or', 'not', 'foreach', 'endforeach', 'in', 'continue', 'break'} self.future_keywords = {'return'} + self.in_unit_test = 'MESON_RUNNING_IN_PROJECT_TESTS' in os.environ + if self.in_unit_test: + self.keywords.update({'testcase', 'endtestcase'}) self.token_specification = [ # Need to be sorted longest to shortest. ('ignore', re.compile(r'[ \t]')), @@ -197,16 +195,12 @@ elif tid in {'string', 'fstring'}: # Handle here and not on the regexp to give a better error message. if match_text.find("\n") != -1: - msg = ParseException("Newline character in a string detected, use ''' (three single quotes) " - "for multiline strings instead.\n" - "This will become a hard error in a future Meson release.", - self.getline(line_start), lineno, col) - mlog.warning(msg, location=BaseNode(lineno, col, filename)) + msg = ("Newline character in a string detected, use ''' (three single quotes) " + "for multiline strings instead.\n" + "This will become a hard error in a future Meson release.") + mlog.warning(mlog.code_line(msg, self.getline(line_start), col), location=BaseNode(lineno, col, filename)) 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(f"Failed to parse escape sequence: '{err.match}' in string:\n {match_text}") + value = ESCAPE_SEQUENCE_SINGLE_RE.sub(decode_match, value) elif tid in {'multiline_string', 'multiline_fstring'}: # For multiline strings, parse out the value and pass # through the normal string logic. @@ -239,31 +233,32 @@ else: if match_text in self.future_keywords: 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)) + location=BaseNode(lineno, col, filename)) value = match_text yield Token(tid, filename, curline_start, curline, col, bytespan, value) break if not matched: raise ParseException('lexer', self.getline(line_start), lineno, col) -@dataclass(eq=False) +@dataclass class BaseNode: lineno: int colno: int - filename: str - end_lineno: T.Optional[int] = None - end_colno: T.Optional[int] = None + filename: str = field(hash=False) + end_lineno: int = field(hash=False) + end_colno: int = field(hash=False) - def __post_init__(self) -> None: - if self.end_lineno is None: - self.end_lineno = self.lineno - if self.end_colno is None: - self.end_colno = self.colno + def __init__(self, lineno: int, colno: int, filename: str, end_lineno: T.Optional[int] = None, end_colno: T.Optional[int] = None) -> None: + self.lineno = lineno + self.colno = colno + self.filename = filename + self.end_lineno = end_lineno if end_lineno is not None else lineno + self.end_colno = end_colno if end_colno is not None else colno # Attributes for the visitors - self.level = 0 # type: int - self.ast_id = '' # type: str - self.condition_level = 0 # type: int + self.level = 0 + self.ast_id = '' + self.condition_level = 0 def accept(self, visitor: 'AstVisitor') -> None: fname = 'visit_{}'.format(type(self).__name__) @@ -272,43 +267,32 @@ if callable(func): func(self) +@dataclass(unsafe_hash=True) class ElementaryNode(T.Generic[TV_TokenTypes], BaseNode): + + value: TV_TokenTypes + bytespan: T.Tuple[int, int] = field(hash=False) + 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] + self.value = token.value + self.bytespan = token.bytespan class BooleanNode(ElementaryNode[bool]): - def __init__(self, token: Token[bool]): - super().__init__(token) - assert isinstance(self.value, bool) + pass class IdNode(ElementaryNode[str]): - def __init__(self, token: Token[str]): - super().__init__(token) - assert isinstance(self.value, str) - def __str__(self) -> str: return "Id node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno) class NumberNode(ElementaryNode[int]): - def __init__(self, token: Token[int]): - super().__init__(token) - assert isinstance(self.value, int) + pass class StringNode(ElementaryNode[str]): - def __init__(self, token: Token[str]): - super().__init__(token) - assert isinstance(self.value, str) - 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 f"Format string node: '{self.value}' ({self.lineno}, {self.colno})." @@ -322,12 +306,18 @@ class BreakNode(ElementaryNode): pass +@dataclass(unsafe_hash=True) class ArgumentNode(BaseNode): + + arguments: T.List[BaseNode] = field(hash=False) + commas: T.List[Token] = field(hash=False) + kwargs: T.Dict[BaseNode, BaseNode] = field(hash=False) + 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.arguments = [] + self.commas = [] + self.kwargs = {} self.order_error = False def prepend(self, statement: BaseNode) -> None: @@ -363,122 +353,229 @@ def __len__(self) -> int: return self.num_args() # Fixme +@dataclass(unsafe_hash=True) class ArrayNode(BaseNode): + + args: ArgumentNode + 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 + self.args = args +@dataclass(unsafe_hash=True) class DictNode(BaseNode): + + args: ArgumentNode + 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: int, colno: int, filename: str): - super().__init__(lineno, colno, filename) - self.value = None + pass +@dataclass(unsafe_hash=True) class OrNode(BaseNode): + + left: BaseNode + right: BaseNode + 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 + self.left = left + self.right = right +@dataclass(unsafe_hash=True) class AndNode(BaseNode): + + left: BaseNode + right: BaseNode + 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 + self.left = left + self.right = right +@dataclass(unsafe_hash=True) class ComparisonNode(BaseNode): + + left: BaseNode + right: BaseNode + ctype: COMPARISONS + def __init__(self, ctype: COMPARISONS, left: BaseNode, right: BaseNode): super().__init__(left.lineno, left.colno, left.filename) - self.left = left # type: BaseNode - self.right = right # type: BaseNode + self.left = left + self.right = right self.ctype = ctype +@dataclass(unsafe_hash=True) class ArithmeticNode(BaseNode): + + left: BaseNode + right: BaseNode + # TODO: use a Literal for operation + operation: str + 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 + self.left = left + self.right = right + self.operation = operation + +@dataclass(unsafe_hash=True) class NotNode(BaseNode): + + value: BaseNode + def __init__(self, token: Token[TV_TokenTypes], value: BaseNode): super().__init__(token.lineno, token.colno, token.filename) - self.value = value # type: BaseNode + self.value = value +@dataclass(unsafe_hash=True) class CodeBlockNode(BaseNode): + + lines: T.List[BaseNode] = field(hash=False) + def __init__(self, token: Token[TV_TokenTypes]): super().__init__(token.lineno, token.colno, token.filename) - self.lines = [] # type: T.List[BaseNode] + self.lines = [] +@dataclass(unsafe_hash=True) class IndexNode(BaseNode): + + iobject: BaseNode + index: BaseNode + 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 + self.iobject = iobject + self.index = index +@dataclass(unsafe_hash=True) class MethodNode(BaseNode): + + source_object: BaseNode + name: str + args: ArgumentNode + 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 + self.source_object = source_object + self.name = name assert isinstance(self.name, str) - self.args = args # type: ArgumentNode + self.args = args +@dataclass(unsafe_hash=True) class FunctionNode(BaseNode): + + func_name: str + args: ArgumentNode + 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 + self.func_name = func_name assert isinstance(func_name, str) - self.args = args # type: ArgumentNode + self.args = args + +@dataclass(unsafe_hash=True) class AssignmentNode(BaseNode): + + var_name: str + value: BaseNode + 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 + self.var_name = var_name assert isinstance(var_name, str) - self.value = value # type: BaseNode + self.value = value + +@dataclass(unsafe_hash=True) class PlusAssignmentNode(BaseNode): + + var_name: str + value: BaseNode + 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 + self.var_name = var_name assert isinstance(var_name, str) - self.value = value # type: BaseNode + self.value = value + +@dataclass(unsafe_hash=True) class ForeachClauseNode(BaseNode): + + varnames: T.List[str] = field(hash=False) + items: BaseNode + block: CodeBlockNode + 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 + self.varnames = varnames + self.items = items + self.block = block + +@dataclass(unsafe_hash=True) class IfNode(BaseNode): + + condition: BaseNode + block: CodeBlockNode + 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 + self.condition = condition + self.block = block + +@dataclass(unsafe_hash=True) class IfClauseNode(BaseNode): + + ifs: T.List[IfNode] = field(hash=False) + elseblock: T.Union[EmptyNode, CodeBlockNode] + 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] + self.ifs = [] + self.elseblock = None + +@dataclass(unsafe_hash=True) +class TestCaseClauseNode(BaseNode): + condition: BaseNode + block: CodeBlockNode + + def __init__(self, condition: BaseNode, block: CodeBlockNode): + super().__init__(condition.lineno, condition.colno, condition.filename) + self.condition = condition + self.block = block + +@dataclass(unsafe_hash=True) class UMinusNode(BaseNode): + + value: BaseNode + def __init__(self, current_location: Token, value: BaseNode): super().__init__(current_location.lineno, current_location.colno, current_location.filename) - self.value = value # type: BaseNode + self.value = value + +@dataclass(unsafe_hash=True) class TernaryNode(BaseNode): + + condition: BaseNode + trueblock: BaseNode + falseblock: BaseNode + 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 + self.condition = condition + self.trueblock = trueblock + self.falseblock = falseblock if T.TYPE_CHECKING: COMPARISONS = Literal['==', '!=', '<', '<=', '>=', '>', 'in', 'notin'] @@ -551,7 +648,11 @@ def parse(self) -> CodeBlockNode: block = self.codeblock() - self.expect('eof') + try: + self.expect('eof') + except ParseException as e: + e.ast = block + raise return block def statement(self) -> BaseNode: @@ -810,6 +911,12 @@ return self.codeblock() return EmptyNode(self.current.lineno, self.current.colno, self.current.filename) + def testcaseblock(self) -> TestCaseClauseNode: + condition = self.statement() + self.expect('eol') + block = self.codeblock() + return TestCaseClauseNode(condition, block) + def line(self) -> BaseNode: block_start = self.current if self.current == 'eol': @@ -826,14 +933,22 @@ return ContinueNode(self.current) if self.accept('break'): return BreakNode(self.current) + if self.lexer.in_unit_test and self.accept('testcase'): + block = self.testcaseblock() + self.block_expect('endtestcase', block_start) + return block return self.statement() def codeblock(self) -> CodeBlockNode: block = CodeBlockNode(self.current) cond = True - while cond: - curline = self.line() - if not isinstance(curline, EmptyNode): - block.lines.append(curline) - cond = self.accept('eol') + try: + while cond: + curline = self.line() + if not isinstance(curline, EmptyNode): + block.lines.append(curline) + cond = self.accept('eol') + except ParseException as e: + e.ast = block + raise return block diff -Nru meson-1.0.1/mesonbuild/msetup.py meson-1.2.1/mesonbuild/msetup.py --- meson-1.0.1/mesonbuild/msetup.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/msetup.py 2023-08-07 22:54:34.000000000 +0000 @@ -13,24 +13,13 @@ # limitations under the License. from __future__ import annotations -import typing as T -import time -import sys, stat -import datetime -import os.path -import platform +import argparse, datetime, glob, json, os, platform, shutil, sys, tempfile, time import cProfile as profile -import argparse -import tempfile -import shutil -import glob - -from . import environment, interpreter, mesonlib -from . import build -from . import mlog, coredata -from . import mintro -from .mesonlib import MesonException, MachineChoice -from .dependencies import PkgConfigDependency +from pathlib import Path +import typing as T + +from . import build, coredata, environment, interpreter, mesonlib, mintro, mlog +from .mesonlib import MesonException git_ignore_file = '''# This file is autogenerated by Meson. If you change or delete it, it won't be recreated. * @@ -52,10 +41,6 @@ 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', @@ -89,9 +74,9 @@ try: restore.append((shutil.copy(filename, d), filename)) except FileNotFoundError: - raise MesonException( - 'Cannot find cmd_line.txt. This is probably because this ' - 'build directory was configured with a meson version < 0.49.0.') + # validate_dirs() already verified that build_dir has + # a partial build or is empty. + pass coredata.read_cmd_line_file(self.build_dir, options) @@ -118,9 +103,10 @@ return os.path.exists(fname) def validate_core_dirs(self, dir1: str, dir2: str) -> T.Tuple[str, str]: + invalid_msg_prefix = f'Neither source directory {dir1!r} nor build directory {dir2!r}' if dir1 is None: if dir2 is None: - if not os.path.exists('meson.build') and os.path.exists('../meson.build'): + if not self.has_build_file('.') and self.has_build_file('..'): dir2 = '..' else: raise MesonException('Must specify at least one directory name.') @@ -129,14 +115,16 @@ dir2 = os.getcwd() ndir1 = os.path.abspath(os.path.realpath(dir1)) ndir2 = os.path.abspath(os.path.realpath(dir2)) - if not os.path.exists(ndir1): - os.makedirs(ndir1) - if not os.path.exists(ndir2): - os.makedirs(ndir2) - if not stat.S_ISDIR(os.stat(ndir1).st_mode): - raise MesonException(f'{dir1} is not a directory') - if not stat.S_ISDIR(os.stat(ndir2).st_mode): - raise MesonException(f'{dir2} is not a directory') + if not os.path.exists(ndir1) and not os.path.exists(ndir2): + raise MesonException(f'{invalid_msg_prefix} exist.') + try: + os.makedirs(ndir1, exist_ok=True) + except FileExistsError as e: + raise MesonException(f'{dir1} is not a directory') from e + try: + os.makedirs(ndir2, exist_ok=True) + except FileExistsError as e: + raise MesonException(f'{dir2} is not a directory') from e 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))) @@ -148,11 +136,9 @@ return ndir1, ndir2 if self.has_build_file(ndir2): return ndir2, ndir1 - raise MesonException(f'Neither directory contains a build file {environment.build_filename}.') + raise MesonException(f'{invalid_msg_prefix} contain 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: @@ -160,33 +146,43 @@ 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 Path(build_dir) in Path(src_dir).parents: + raise MesonException(f'Build directory {build_dir} cannot be a parent of source directory {src_dir}') + if not os.listdir(build_dir): + self.add_vcs_ignore_files(build_dir) + return src_dir, build_dir + priv_dir = os.path.join(build_dir, 'meson-private') + has_valid_build = os.path.exists(os.path.join(priv_dir, 'coredata.dat')) + has_partial_build = os.path.isdir(priv_dir) + if has_valid_build: if not reconfigure and not wipe: - print('Directory already configured.\n' - '\nJust run your build command (e.g. ninja) and Meson will regenerate as necessary.\n' + print('Directory already configured.\n\n' + 'Just run your build command (e.g. ninja) and Meson will regenerate as necessary.\n' 'If ninja fails, run "ninja reconfigure" or "meson setup --reconfigure"\n' - 'to force Meson to regenerate.\n' - '\nIf build failures persist, run "meson setup --wipe" to rebuild from scratch\n' - 'using the same options as passed when configuring the build.' - '\nTo change option values, run "meson configure" instead.') - raise SystemExit - 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(f'Directory does not contain a valid build tree:\n{build_dir}') + 'to force Meson to regenerate.\n\n' + 'If build failures persist, run "meson setup --wipe" to rebuild from scratch\n' + 'using the same options as passed when configuring the build.\n' + 'To change option values, run "meson configure" instead.') + # FIXME: This returns success and ignores new option values from CLI. + # We should either make this a hard error, or update options and + # return success. + # Note that making this an error would not be backward compatible (and also isn't + # universally agreed on): https://github.com/mesonbuild/meson/pull/4249. + raise SystemExit(0) + elif not has_partial_build and wipe: + raise MesonException(f'Directory is not empty and does not contain a previous build:\n{build_dir}') return src_dir, build_dir - def generate(self) -> None: + # See class Backend's 'generate' for comments on capture args and returned dictionary. + def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: 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: mlog.set_timestamp_start(time.monotonic()) with mesonlib.BuildDirLock(self.build_dir): - self._generate(env) + return self._generate(env, capture, vslite_ctx) - def _generate(self, env: environment.Environment) -> None: + def _generate(self, env: environment.Environment, capture: bool, vslite_ctx: dict) -> T.Optional[dict]: # 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)) @@ -207,10 +203,11 @@ b = build.Build(env) intr = interpreter.Interpreter(b, user_defined_options=user_defined_options) - if env.is_cross_build(): - logger_fun = mlog.log - else: - logger_fun = mlog.debug + # Super hack because mlog.log and mlog.debug have different signatures, + # and there is currently no way to annotate them correctly, unionize them, or + # even to write `T.Callable[[*mlog.TV_Loggable], None]` + logger_fun = T.cast('T.Callable[[mlog.TV_Loggable, mlog.TV_Loggable], None]', + (mlog.log if env.is_cross_build() else mlog.debug)) build_machine = intr.builtin['build_machine'] host_machine = intr.builtin['host_machine'] target_machine = intr.builtin['target_machine'] @@ -225,7 +222,7 @@ 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') + fname = os.path.join(self.build_dir, 'meson-logs', 'profile-interpreter.log') profile.runctx('intr.run()', globals(), locals(), filename=fname) else: intr.run() @@ -234,6 +231,7 @@ raise cdf: T.Optional[str] = None + captured_compile_args: T.Optional[dict] = None 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 @@ -243,13 +241,17 @@ # sync with the time that gets applied to any files. Thus, we dump this file as late as # possible, but before build files, and if any error occurs, delete it. cdf = env.dump_coredata() + + self.finalize_postconf_hooks(b, intr) if self.options.profile: fname = f'profile-{intr.backend.name}-backend.log' - fname = os.path.join(self.build_dir, 'meson-private', fname) - profile.runctx('intr.backend.generate()', globals(), locals(), filename=fname) + fname = os.path.join(self.build_dir, 'meson-logs', fname) + profile.runctx('gen_result = intr.backend.generate(capture, vslite_ctx)', globals(), locals(), filename=fname) + captured_compile_args = locals()['gen_result'] + assert captured_compile_args is None or isinstance(captured_compile_args, dict) else: - intr.backend.generate() - self._finalize_devenv(b, intr) + captured_compile_args = intr.backend.generate(capture, vslite_ctx) + build.save(b, dumpfile) if env.first_invocation: # Use path resolved by coredata because they could have been @@ -262,7 +264,7 @@ # Generate an IDE introspection file with the same syntax as the already existing API if self.options.profile: - fname = os.path.join(self.build_dir, 'meson-private', 'profile-introspector.log') + fname = os.path.join(self.build_dir, 'meson-logs', 'profile-introspector.log') profile.runctx('mintro.generate_introspection_file(b, intr.backend)', globals(), locals(), filename=fname) else: mintro.generate_introspection_file(b, intr.backend) @@ -282,6 +284,15 @@ 'Please consider using `meson devenv` instead. See https://github.com/mesonbuild/meson/pull/9243 ' 'for details.') + if self.options.profile: + fname = os.path.join(self.build_dir, 'meson-logs', 'profile-startup-modules.json') + mods = set(sys.modules.keys()) + mesonmods = {mod for mod in mods if (mod+'.').startswith('mesonbuild.')} + stdmods = sorted(mods - mesonmods) + data = {'stdlib': {'modules': stdmods, 'count': len(stdmods)}, 'meson': {'modules': sorted(mesonmods), 'count': len(mesonmods)}} + with open(fname, 'w', encoding='utf-8') as f: + json.dump(data, f) + except Exception as e: mintro.write_meson_info_file(b, [e]) if cdf is not None: @@ -292,13 +303,46 @@ os.unlink(cdf) raise - def _finalize_devenv(self, b: build.Build, intr: interpreter.Interpreter) -> None: + return captured_compile_args + + def finalize_postconf_hooks(self, b: build.Build, intr: interpreter.Interpreter) -> None: b.devenv.append(intr.backend.get_devenv()) - b.devenv.append(PkgConfigDependency.get_env(intr.environment, MachineChoice.HOST, uninstalled=True)) for mod in intr.modules.values(): - devenv = mod.get_devenv() - if devenv: - b.devenv.append(devenv) + mod.postconf_hook(b) + +def run_genvslite_setup(options: argparse.Namespace) -> None: + # With --genvslite, we essentially want to invoke multiple 'setup' iterations. I.e. - + # meson setup ... builddirprefix_debug + # meson setup ... builddirprefix_debugoptimized + # meson setup ... builddirprefix_release + # along with also setting up a new, thin/lite visual studio solution and projects with the multiple debug/opt/release configurations that + # invoke the appropriate 'meson compile ...' build commands upon the normal visual studio build/rebuild/clean actions, instead of using + # the native VS/msbuild system. + builddir_prefix = options.builddir + genvsliteval = options.cmd_line_options.pop(mesonlib.OptionKey('genvslite')) + # The command line may specify a '--backend' option, which doesn't make sense in conjunction with + # '--genvslite', where we always want to use a ninja back end - + k_backend = mesonlib.OptionKey('backend') + if k_backend in options.cmd_line_options.keys(): + if options.cmd_line_options[k_backend] != 'ninja': + raise MesonException('Explicitly specifying a backend option with \'genvslite\' is not necessary ' + '(the ninja backend is always used) but specifying a non-ninja backend ' + 'conflicts with a \'genvslite\' setup') + else: + options.cmd_line_options[k_backend] = 'ninja' + buildtypes_list = coredata.get_genvs_default_buildtype_list() + vslite_ctx = {} + + for buildtypestr in buildtypes_list: + options.builddir = f'{builddir_prefix}_{buildtypestr}' # E.g. builddir_release + options.cmd_line_options[mesonlib.OptionKey('buildtype')] = buildtypestr + app = MesonApp(options) + vslite_ctx[buildtypestr] = app.generate(capture=True) + #Now for generating the 'lite' solution and project files, which will use these builds we've just set up, above. + options.builddir = f'{builddir_prefix}_vs' + options.cmd_line_options[mesonlib.OptionKey('genvslite')] = genvsliteval + app = MesonApp(options) + app.generate(capture=False, vslite_ctx=vslite_ctx) def run(options: T.Union[argparse.Namespace, T.List[str]]) -> int: if not isinstance(options, argparse.Namespace): @@ -306,6 +350,11 @@ add_arguments(parser) options = parser.parse_args(options) coredata.parse_cmd_line_options(options) - app = MesonApp(options) - app.generate() + + if mesonlib.OptionKey('genvslite') in options.cmd_line_options.keys(): + run_genvslite_setup(options) + else: + app = MesonApp(options) + app.generate() + return 0 diff -Nru meson-1.0.1/mesonbuild/msubprojects.py meson-1.2.1/mesonbuild/msubprojects.py --- meson-1.0.1/mesonbuild/msubprojects.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/msubprojects.py 2023-08-07 22:54:34.000000000 +0000 @@ -14,6 +14,7 @@ import zipfile from . import mlog +from .ast import IntrospectionInterpreter, AstIDGenerator from .mesonlib import quiet_git, GitException, Popen_safe, MesonException, windows_proof_rmtree from .wrap.wrap import (Resolver, WrapException, ALL_TYPES, PackageDefinition, parse_patch_url, update_wrap_file, get_releases) @@ -207,13 +208,17 @@ self.log(self.git_output(cmd)) def git_stash(self) -> None: - # That git command return 1 (failure) when there is something to stash. + # That git command return some output 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]: + if quiet_git(['status', '--porcelain', ':!/.meson-subproject-wrap-hash.txt'], self.repo_dir)[1].strip(): # Don't pipe stdout here because we want the user to see their changes have # been saved. - self.git_verbose(['stash']) + # Note: `--all` is used, and not `--include-untracked`, to prevent + # a potential error if `.meson-subproject-wrap-hash.txt` matches a + # gitignore pattern. + # We must add the dot in addition to the negation, because older versions of git have a bug. + self.git_verbose(['stash', 'push', '--all', ':!/.meson-subproject-wrap-hash.txt', '.']) def git_show(self) -> None: commit_message = self.git_output(['show', '--quiet', '--pretty=format:%h%n%d%n%s%n[%an]']) @@ -246,9 +251,10 @@ return True def git_checkout(self, revision: str, create: bool = False) -> bool: - cmd = ['checkout', '--ignore-other-worktrees', revision, '--'] + cmd = ['checkout', '--ignore-other-worktrees'] if create: - cmd.insert(1, '-b') + cmd.append('-b') + cmd += [revision, '--'] try: # Stash local changes, commits can always be found back in reflog, to # avoid any data lost by mistake. @@ -680,15 +686,20 @@ 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.') + source_dir = os.path.relpath(os.path.realpath(options.sourcedir)) + if not os.path.isfile(os.path.join(source_dir, 'meson.build')): + mlog.error('Directory', mlog.bold(source_dir), 'does not seem to be a Meson source directory.') return 1 - subprojects_dir = os.path.join(src_dir, 'subprojects') - if not os.path.isdir(subprojects_dir): - mlog.log('Directory', mlog.bold(src_dir), 'does not seem to have subprojects.') + with mlog.no_logging(): + intr = IntrospectionInterpreter(source_dir, '', 'none', visitors = [AstIDGenerator()]) + intr.load_root_meson_file() + intr.sanity_check_ast() + intr.parse_project() + subproject_dir = intr.subproject_dir + if not os.path.isdir(os.path.join(source_dir, subproject_dir)): + mlog.log('Directory', mlog.bold(source_dir), 'does not seem to have subprojects.') return 0 - r = Resolver(src_dir, 'subprojects', wrap_frontend=True, allow_insecure=options.allow_insecure) + r = Resolver(source_dir, subproject_dir, wrap_frontend=True, allow_insecure=options.allow_insecure, silent=True) if options.subprojects: wraps = [wrap for name, wrap in r.wraps.items() if name in options.subprojects] else: @@ -699,7 +710,8 @@ 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() + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) executor = ThreadPoolExecutor(options.num_processes) if types: wraps = [wrap for wrap in wraps if wrap.type in types] @@ -708,7 +720,7 @@ pre_func(options) logger = Logger(len(wraps)) for wrap in wraps: - dirname = Path(subprojects_dir, wrap.directory).as_posix() + dirname = Path(subproject_dir, wrap.directory).as_posix() runner = Runner(logger, r, wrap, dirname, options) task = loop.run_in_executor(executor, runner.run) tasks.append(task) diff -Nru meson-1.0.1/mesonbuild/mtest.py meson-1.2.1/mesonbuild/mtest.py --- meson-1.0.1/mesonbuild/mtest.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/mtest.py 2023-08-07 22:54:34.000000000 +0000 @@ -19,6 +19,7 @@ from collections import deque from contextlib import suppress from copy import deepcopy +from fnmatch import fnmatch import argparse import asyncio import datetime @@ -43,7 +44,7 @@ from . import build from . import environment from . import mlog -from .coredata import major_versions_differ, MesonVersionMismatchException +from .coredata import MesonVersionMismatchException, OptionKey, major_versions_differ from .coredata import version as coredata_version from .mesonlib import (MesonException, OrderedSet, RealPathAction, get_wine_shortpath, join_args, split_args, setup_vsenv) @@ -71,6 +72,26 @@ # Exit if 3 Ctrl-C's are received within one second MAX_CTRLC = 3 +# Define unencodable xml characters' regex for replacing them with their +# printable representation +UNENCODABLE_XML_UNICHRS: T.List[T.Tuple[int, int]] = [ + (0x00, 0x08), (0x0B, 0x0C), (0x0E, 0x1F), (0x7F, 0x84), + (0x86, 0x9F), (0xFDD0, 0xFDEF), (0xFFFE, 0xFFFF)] +# Not narrow build +if sys.maxunicode >= 0x10000: + UNENCODABLE_XML_UNICHRS.extend([ + (0x1FFFE, 0x1FFFF), (0x2FFFE, 0x2FFFF), + (0x3FFFE, 0x3FFFF), (0x4FFFE, 0x4FFFF), + (0x5FFFE, 0x5FFFF), (0x6FFFE, 0x6FFFF), + (0x7FFFE, 0x7FFFF), (0x8FFFE, 0x8FFFF), + (0x9FFFE, 0x9FFFF), (0xAFFFE, 0xAFFFF), + (0xBFFFE, 0xBFFFF), (0xCFFFE, 0xCFFFF), + (0xDFFFE, 0xDFFFF), (0xEFFFE, 0xEFFFF), + (0xFFFFE, 0xFFFFF), (0x10FFFE, 0x10FFFF)]) +UNENCODABLE_XML_CHR_RANGES = [fr'{chr(low)}-{chr(high)}' for (low, high) in UNENCODABLE_XML_UNICHRS] +UNENCODABLE_XML_CHRS_RE = re.compile('([' + ''.join(UNENCODABLE_XML_CHR_RANGES) + '])') + + def is_windows() -> bool: platname = platform.system().lower() return platname == 'windows' @@ -185,7 +206,7 @@ # functions here because the status returned by subprocess is munged. It # returns a negative value if the process was killed by a signal rather than # the raw status returned by `wait()`. Also, If a shell sits between Meson - # the the actual unit test that shell is likely to convert a termination due + # the actual unit test that shell is likely to convert a termination due # to a signal into an exit status of 128 plus the signal number. if retcode < 0: signum = -retcode @@ -505,7 +526,9 @@ self.progress_task = None # type: T.Optional[asyncio.Future] self.max_left_width = 0 # type: int self.stop = False - self.update = asyncio.Event() + # TODO: before 3.10 this cannot be created immediately, because + # it will create a new event loop + self.update: asyncio.Event self.should_erase_line = '' self.test_count = 0 self.started_tests = 0 @@ -575,7 +598,7 @@ def start(self, harness: 'TestHarness') -> None: async def report_progress() -> None: - loop = asyncio.get_event_loop() + loop = asyncio.get_running_loop() next_update = 0.0 self.request_update() while not self.stop: @@ -603,6 +626,7 @@ self.emit_progress(harness) self.flush() + self.update = asyncio.Event() self.test_count = harness.test_count self.cols = max(self.cols, harness.max_left_width + 30) @@ -1032,12 +1056,16 @@ filename = os.path.join(self.test.workdir, filename) try: - self.junit = et.parse(filename) + with open(filename, 'r', encoding='utf8', errors='replace') as f: + self.junit = et.parse(f) 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 + except et.ParseError as e: + # ExitCode will handle the failure, don't generate a stacktrace. + mlog.error(f'Unable to parse {filename}: {e!s}') super().complete() @@ -1140,14 +1168,21 @@ TestRun.PROTOCOL_TO_CLASS[TestProtocol.RUST] = TestRunRust +# Check unencodable characters in xml output and replace them with +# their printable representation +def replace_unencodable_xml_chars(original_str: str) -> str: + # [1:-1] is needed for removing `'` characters from both start and end + # of the string + replacement_lambda = lambda illegal_chr: repr(illegal_chr.group())[1:-1] + return UNENCODABLE_XML_CHRS_RE.sub(replacement_lambda, original_str) def decode(stream: T.Union[None, bytes]) -> str: if stream is None: return '' try: - return stream.decode('utf-8') + return replace_unencodable_xml_chars(stream.decode('utf-8')) except UnicodeDecodeError: - return stream.decode('iso-8859-1', errors='ignore') + return replace_unencodable_xml_chars(stream.decode('iso-8859-1', errors='ignore')) async def read_decode(reader: asyncio.StreamReader, queue: T.Optional['asyncio.Queue[T.Optional[str]]'], @@ -1229,13 +1264,14 @@ # 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 + loop = asyncio.get_running_loop() + deadline = None if timeout is None else 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() + timeout = deadline - loop.time() check_futures(futures) @@ -1443,7 +1479,7 @@ async def run(self, harness: 'TestHarness') -> TestRun: if self.cmd is None: - self.stdo = 'Not run because can not execute cross compiled binaries.' + self.stdo = 'Not run because cannot execute cross compiled binaries.' harness.log_start_test(self.runobj) self.runobj.complete_skip() else: @@ -1578,12 +1614,6 @@ if self.options.no_rebuild: return - if not (Path(self.options.wd) / 'build.ninja').is_file(): - print('Only ninja backend is supported to rebuild tests before running them.') - # Disable, no point in trying to build anything later - self.options.no_rebuild = True - return - self.ninja = environment.detect_ninja() if not self.ninja: print("Can't find ninja, can't rebuild test.") @@ -1603,9 +1633,12 @@ # happen before rebuild_deps(), because we need the correct list of # tests and their dependencies to compute if not self.options.no_rebuild: - ret = subprocess.run(self.ninja + ['build.ninja']).returncode - if ret != 0: - raise TestException(f'Could not configure {self.options.wd!r}') + teststdo = subprocess.run(self.ninja + ['-n', 'build.ninja'], capture_output=True).stdout + if b'ninja: no work to do.' not in teststdo and b'samu: nothing to do' not in teststdo: + stdo = sys.stderr if self.options.list else sys.stdout + ret = subprocess.run(self.ninja + ['build.ninja'], stdout=stdo.fileno()) + if ret.returncode != 0: + raise TestException(f'Could not configure {self.options.wd!r}') self.build_data = build.load(os.getcwd()) if not self.options.setup: @@ -1857,21 +1890,52 @@ run all tests with that name across all subprojects, which is identical to "meson test foo1" ''' + patterns: T.Dict[T.Tuple[str, str], bool] = {} for arg in self.options.args: + # Replace empty components by wildcards: + # '' -> '*:*' + # 'name' -> '*:name' + # ':name' -> '*:name' + # 'proj:' -> 'proj:*' if ':' in arg: subproj, name = arg.split(':', maxsplit=1) + if name == '': + name = '*' + if subproj == '': # in case arg was ':' + subproj = '*' 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 + subproj, name = '*', arg + patterns[(subproj, name)] = False - def get_tests(self) -> T.List[TestSerialisation]: + for t in tests: + # For each test, find the first matching pattern + # and mark it as used. yield the matching tests. + for subproj, name in list(patterns): + if fnmatch(t.project_name, subproj) and fnmatch(t.name, name): + patterns[(subproj, name)] = True + yield t + break + + for (subproj, name), was_used in patterns.items(): + if not was_used: + # For each unused pattern... + arg = f'{subproj}:{name}' + for t in tests: + # ... if it matches a test, then it wasn't used because another + # pattern matched the same test before. + # Report it as a warning. + if fnmatch(t.project_name, subproj) and fnmatch(t.name, name): + mlog.warning(f'{arg} test name is redundant and was not used') + break + else: + # If the pattern doesn't match any test, + # report it as an error. We don't want the `test` command to + # succeed on an invalid pattern. + raise MesonException(f'{arg} test name does not match any test') + + def get_tests(self, errorfile: T.Optional[T.IO] = None) -> T.List[TestSerialisation]: if not self.tests: - print('No tests defined.') + print('No tests defined.', file=errorfile) return [] tests = [t for t in self.tests if self.test_suitable(t)] @@ -1879,7 +1943,7 @@ tests = list(self.tests_from_args(tests)) if not tests: - print('No suitable tests defined.') + print('No suitable tests defined.', file=errorfile) return [] return tests @@ -1922,9 +1986,12 @@ 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)) + + # TODO: this is the default for python 3.8 + if sys.platform == 'win32': + asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) + + asyncio.run(self._run_tests(runners)) finally: self.close_logfiles() @@ -1942,6 +2009,7 @@ running_tests = {} # type: T.Dict[asyncio.Future, str] interrupted = False ctrlc_times = deque(maxlen=MAX_CTRLC) # type: T.Deque[float] + loop = asyncio.get_running_loop() async def run_test(test: SingleTestRunner) -> None: async with semaphore: @@ -1990,7 +2058,7 @@ nonlocal interrupted if interrupted: return - ctrlc_times.append(asyncio.get_event_loop().time()) + ctrlc_times.append(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') @@ -2007,10 +2075,10 @@ if sys.platform != 'win32': if os.getpgid(0) == os.getpid(): - asyncio.get_event_loop().add_signal_handler(signal.SIGINT, sigint_handler) + 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) + loop.add_signal_handler(signal.SIGINT, sigterm_handler) + loop.add_signal_handler(signal.SIGTERM, sigterm_handler) try: for runner in runners: if not runner.is_parallel: @@ -2027,13 +2095,13 @@ await complete_all(futures) finally: if sys.platform != 'win32': - asyncio.get_event_loop().remove_signal_handler(signal.SIGINT) - asyncio.get_event_loop().remove_signal_handler(signal.SIGTERM) + loop.remove_signal_handler(signal.SIGINT) + 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() + tests = th.get_tests(errorfile=sys.stderr) for t in tests: print(th.get_pretty_suite(t)) return not tests @@ -2087,10 +2155,6 @@ 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(): @@ -2098,7 +2162,18 @@ return 1 b = build.load(options.wd) - setup_vsenv(b.need_vsenv) + need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) + setup_vsenv(need_vsenv) + + if not options.no_rebuild: + backend = b.environment.coredata.get_option(OptionKey('backend')) + if backend == 'none': + # nothing to build... + options.no_rebuild = True + elif backend != 'ninja': + print('Only ninja backend is supported to rebuild tests before running them.') + # Disable, no point in trying to build anything later + options.no_rebuild = True with TestHarness(options) as th: try: diff -Nru meson-1.0.1/mesonbuild/optinterpreter.py meson-1.2.1/mesonbuild/optinterpreter.py --- meson-1.0.1/mesonbuild/optinterpreter.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/optinterpreter.py 2023-05-23 15:20:02.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 __future__ import annotations import re import typing as T @@ -19,11 +20,16 @@ from . import mesonlib from . import mparser from . import mlog -from .interpreterbase import FeatureNew, typed_pos_args, typed_kwargs, ContainerTypeInfo, KwargInfo, permittedKwargs +from .interpreterbase import FeatureNew, typed_pos_args, typed_kwargs, ContainerTypeInfo, KwargInfo +from .interpreter.type_checking import NoneType, in_set_validator + if T.TYPE_CHECKING: from .interpreterbase import TYPE_var, TYPE_kwargs from .interpreterbase import SubProject - from typing_extensions import TypedDict + from typing_extensions import TypedDict, Literal + + _DEPRECATED_ARGS = T.Union[bool, str, T.Dict[str, str], T.List[str]] + FuncOptionArgs = TypedDict('FuncOptionArgs', { 'type': str, 'description': str, @@ -32,16 +38,32 @@ 'value': object, 'min': T.Optional[int], 'max': T.Optional[int], - 'deprecated': T.Union[bool, str, 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], + 'deprecated': _DEPRECATED_ARGS, }) + class StringArgs(TypedDict): + value: str + + class BooleanArgs(TypedDict): + value: bool + + class ComboArgs(TypedDict): + value: str + choices: T.List[str] + + class IntegerArgs(TypedDict): + value: int + min: T.Optional[int] + max: T.Optional[int] + + class StringArrayArgs(TypedDict): + value: T.Optional[T.Union[str, T.List[str]]] + choices: T.List[str] + + class FeatureArgs(TypedDict): + value: Literal['enabled', 'disabled', 'auto'] + choices: T.List[str] + class OptionException(mesonlib.MesonException): pass @@ -54,13 +76,14 @@ def __init__(self, subproject: 'SubProject') -> None: self.options: 'coredata.MutableKeyedOptionDictType' = {} 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, - } + self.option_types: T.Dict[str, T.Callable[..., coredata.UserOption]] = { + '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: str) -> None: try: @@ -145,17 +168,25 @@ (posargs, kwargs) = self.reduce_arguments(node.args) self.func_option(posargs, kwargs) - @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, str, ContainerTypeInfo(dict, str), ContainerTypeInfo(list, str)), - default=False, since='0.60.0') - ) + @typed_kwargs( + 'option', + KwargInfo( + 'type', + str, + required=True, + validator=in_set_validator({'string', 'boolean', 'integer', 'combo', 'array', 'feature'}) + ), + KwargInfo('description', str, default=''), + KwargInfo( + 'deprecated', + (bool, str, ContainerTypeInfo(dict, str), ContainerTypeInfo(list, str)), + default=False, + since='0.60.0', + since_values={str: '0.63.0'}, + ), + KwargInfo('yield', bool, default=coredata.DEFAULT_YIELDING, since='0.45.0'), + allow_unknown=True, + ) @typed_pos_args('option', str) def func_option(self, args: T.Tuple[str], kwargs: 'FuncOptionArgs') -> None: opt_name = args[0] @@ -166,60 +197,83 @@ raise OptionException('Option name %s is reserved.' % opt_name) opt_type = kwargs['type'] - parser = self.option_types.get(opt_type) - if not parser: - raise OptionException(f'Unknown type {opt_type}.') + parser = self.option_types[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 isinstance(opt.deprecated, str): - FeatureNew.single_use('String value to "deprecated" keyword argument', '0.63.0', self.subproject) + # Drop the arguments we've already consumed + n_kwargs = {k: v for k, v in kwargs.items() + if k not in {'type', 'description', 'deprecated', 'yield'}} + + opt = parser(description, (kwargs['yield'], kwargs['deprecated']), n_kwargs) 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') + @typed_kwargs( + 'string option', + KwargInfo('value', str, default=''), + ) + def string_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArgs) -> coredata.UserOption: + return coredata.UserStringOption(description, kwargs['value'], *args) + + @typed_kwargs( + 'boolean option', + KwargInfo( + 'value', + (bool, str), + default=True, + validator=lambda x: None if isinstance(x, bool) or x in {'true', 'false'} else 'boolean options must have boolean values', + deprecated_values={str: ('1.1.0', 'use a boolean, not a string')}, + ), + ) + def boolean_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: BooleanArgs) -> coredata.UserOption: + return coredata.UserBooleanOption(description, kwargs['value'], *args) + + @typed_kwargs( + 'combo option', + KwargInfo('value', (str, NoneType)), + KwargInfo('choices', ContainerTypeInfo(list, str, allow_empty=False), required=True), + ) + def combo_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: ComboArgs) -> coredata.UserOption: + choices = kwargs['choices'] + value = kwargs['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.') + value = kwargs['choices'][0] + return coredata.UserComboOption(description, choices, value, *args) + + @typed_kwargs( + 'integer option', + KwargInfo( + 'value', + (int, str), + default=True, + deprecated_values={str: ('1.1.0', 'use an integer, not a string')}, + convertor=int, + ), + KwargInfo('min', (int, NoneType)), + KwargInfo('max', (int, NoneType)), + ) + def integer_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: IntegerArgs) -> coredata.UserOption: + value = kwargs['value'] + inttuple = (kwargs['min'], kwargs['max'], value) + return coredata.UserIntegerOption(description, inttuple, *args) + + @typed_kwargs( + 'string array option', + KwargInfo('value', (ContainerTypeInfo(list, str), str, NoneType)), + KwargInfo('choices', ContainerTypeInfo(list, str), default=[]), + ) + def string_array_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArrayArgs) -> coredata.UserOption: + choices = kwargs['choices'] + value = kwargs['value'] if kwargs['value'] is not None else choices return coredata.UserArrayOption(description, value, choices=choices, - yielding=kwargs['yield']) + yielding=args[0], + deprecated=args[1]) - @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']) + @typed_kwargs( + 'feature option', + KwargInfo('value', str, default='auto', validator=in_set_validator({'auto', 'enabled', 'disabled'})), + ) + def feature_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: FeatureArgs) -> coredata.UserOption: + return coredata.UserFeatureOption(description, kwargs['value'], *args) diff -Nru meson-1.0.1/mesonbuild/programs.py meson-1.2.1/mesonbuild/programs.py --- meson-1.0.1/mesonbuild/programs.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/programs.py 2023-08-07 22:54:34.000000000 +0000 @@ -26,7 +26,7 @@ from . import mesonlib from . import mlog -from .mesonlib import MachineChoice +from .mesonlib import MachineChoice, OrderedSet if T.TYPE_CHECKING: from .environment import Environment @@ -354,16 +354,19 @@ 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.""" + """Find an external program, checking the cross file plus any default options.""" + potential_names = OrderedSet(default_names) + potential_names.add(name) # 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 + for potential_name in potential_names: + potential_cmd = env.lookup_binary_entry(for_machine, potential_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(potential_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 diff -Nru meson-1.0.1/mesonbuild/rewriter.py meson-1.2.1/mesonbuild/rewriter.py --- meson-1.0.1/mesonbuild/rewriter.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/rewriter.py 2023-05-23 15:20:02.000000000 +0000 @@ -25,7 +25,7 @@ from __future__ import annotations from .ast import IntrospectionInterpreter, BUILD_TARGET_FUNCTIONS, AstConditionLevel, AstIDGenerator, AstIndentationGenerator, AstPrinter -from mesonbuild.mesonlib import MesonException +from mesonbuild.mesonlib import MesonException, setup_vsenv from . import mlog, environment from functools import wraps from .mparser import Token, ArrayNode, ArgumentNode, AssignmentNode, BooleanNode, ElementaryNode, IdNode, FunctionNode, StringNode @@ -45,7 +45,7 @@ subparsers = parser.add_subparsers(dest='type', title='Rewriter commands', description='Rewrite command to execute') # Target - tgt_parser = subparsers.add_parser('target', help='Modify a target', formatter_class=formatter) + tgt_parser = subparsers.add_parser('target', aliases=['tgt'], help='Modify a target', formatter_class=formatter) tgt_parser.add_argument('-s', '--subdir', default='', dest='subdir', help='Subdirectory of the new target (only for the "add_target" action)') 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)') @@ -64,13 +64,13 @@ kw_parser.add_argument('kwargs', nargs='*', help='Pairs of keyword and value') # Default options - def_parser = subparsers.add_parser('default-options', help='Modify the project default options', formatter_class=formatter) + def_parser = subparsers.add_parser('default-options', aliases=['def'], help='Modify the project default options', formatter_class=formatter) def_parser.add_argument('operation', choices=rewriter_keys['default_options']['operation'][2], help='Action to execute') def_parser.add_argument('options', nargs='*', help='Key, value pairs of configuration option') # JSON file/command - cmd_parser = subparsers.add_parser('command', help='Execute a JSON array of commands', formatter_class=formatter) + cmd_parser = subparsers.add_parser('command', aliases=['cmd'], help='Execute a JSON array of commands', formatter_class=formatter) cmd_parser.add_argument('json', help='JSON string or file to execute') class RequiredKeys: @@ -569,31 +569,33 @@ if key not in arg_node.kwargs: arg_node.kwargs[key] = None - modifyer = kwargs_def[key](arg_node.kwargs[key]) - if not modifyer.can_modify(): + modifier = kwargs_def[key](arg_node.kwargs[key]) + if not modifier.can_modify(): mlog.log(' -- Skipping', mlog.bold(key), 'because it is to complex to modify') # Apply the operation val_str = str(val) if cmd['operation'] == 'set': mlog.log(' -- Setting', mlog.bold(key), 'to', mlog.yellow(val_str)) - modifyer.set_value(val) + modifier.set_value(val) elif cmd['operation'] == 'add': mlog.log(' -- Adding', mlog.yellow(val_str), 'to', mlog.bold(key)) - modifyer.add_value(val) + modifier.add_value(val) elif cmd['operation'] == 'remove': mlog.log(' -- Removing', mlog.yellow(val_str), 'from', mlog.bold(key)) - modifyer.remove_value(val) + modifier.remove_value(val) elif cmd['operation'] == 'remove_regex': mlog.log(' -- Removing all values matching', mlog.yellow(val_str), 'from', mlog.bold(key)) - modifyer.remove_regex(val) + modifier.remove_regex(val) # Write back the result - arg_node.kwargs[key] = modifyer.get_node() + arg_node.kwargs[key] = modifier.get_node() num_changed += 1 # 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()} + for k, v in arg_node.kwargs.items(): + k.level = v.level if num_changed > 0 and node not in self.modified_nodes: self.modified_nodes += [node] @@ -1041,6 +1043,7 @@ mlog.set_quiet() try: + setup_vsenv() rewriter = Rewriter(options.sourcedir, skip_errors=options.skip) rewriter.analyze_meson() diff -Nru meson-1.0.1/mesonbuild/scripts/clangformat.py meson-1.2.1/mesonbuild/scripts/clangformat.py --- meson-1.0.1/mesonbuild/scripts/clangformat.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/scripts/clangformat.py 2023-04-21 10:42:56.000000000 +0000 @@ -23,10 +23,9 @@ from ..programs import ExternalProgram import typing as T -def run_clang_format(fname: Path, exelist: T.List[str], check: bool) -> subprocess.CompletedProcess: +def run_clang_format(fname: Path, exelist: T.List[str], check: bool, cformat_ver: T.Optional[str]) -> subprocess.CompletedProcess: clangformat_10 = False - if check: - cformat_ver = ExternalProgram('clang-format', exelist).get_version() + if check and cformat_ver: if version_compare(cformat_ver, '>=10'): clangformat_10 = True exelist = exelist + ['--dry-run', '--Werror'] @@ -58,4 +57,9 @@ print('Could not execute clang-format "%s"' % ' '.join(exelist)) return 1 - return run_tool('clang-format', srcdir, builddir, run_clang_format, exelist, options.check) + if options.check: + cformat_ver = ExternalProgram('clang-format', exelist, silent=True).get_version() + else: + cformat_ver = None + + return run_tool('clang-format', srcdir, builddir, run_clang_format, exelist, options.check, cformat_ver) diff -Nru meson-1.0.1/mesonbuild/scripts/cmake_run_ctgt.py meson-1.2.1/mesonbuild/scripts/cmake_run_ctgt.py --- meson-1.0.1/mesonbuild/scripts/cmake_run_ctgt.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/scripts/cmake_run_ctgt.py 2023-05-23 15:20:02.000000000 +0000 @@ -35,7 +35,7 @@ commands += [[]] continue - i = i.replace('"', '') # Remove lefover quotes + i = i.replace('"', '') # Remove leftover quotes commands[-1] += [i] # Execute diff -Nru meson-1.0.1/mesonbuild/scripts/coverage.py meson-1.2.1/mesonbuild/scripts/coverage.py --- meson-1.0.1/mesonbuild/scripts/coverage.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/scripts/coverage.py 2023-05-23 15:20:09.000000000 +0000 @@ -157,7 +157,7 @@ '--html-details', '--print-summary', '-o', os.path.join(htmloutdir, 'index.html'), - ]) + ] + gcov_exe_args) outfiles.append(('Html', pathlib.Path(htmloutdir, 'index.html'))) elif outputs: print('lcov/genhtml or gcovr >= 3.3 needed to generate Html coverage report') diff -Nru meson-1.0.1/mesonbuild/scripts/depfixer.py meson-1.2.1/mesonbuild/scripts/depfixer.py --- meson-1.0.1/mesonbuild/scripts/depfixer.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/scripts/depfixer.py 2023-05-23 15:20:02.000000000 +0000 @@ -350,7 +350,7 @@ 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 + # deduped. This means changing the rpath string might break something # completely unrelated. This has already happened once with X.org. # Thus we want to keep this change as small as possible to minimize # the chance of obliterating other strings. It might still happen diff -Nru meson-1.0.1/mesonbuild/scripts/env2mfile.py meson-1.2.1/mesonbuild/scripts/env2mfile.py --- meson-1.0.1/mesonbuild/scripts/env2mfile.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/scripts/env2mfile.py 2023-08-07 22:54:24.000000000 +0000 @@ -44,6 +44,10 @@ help='Generate a native compilation file.') parser.add_argument('--system', default=None, help='Define system for cross compilation.') + parser.add_argument('--subsystem', default=None, + help='Define subsystem for cross compilation.') + parser.add_argument('--kernel', default=None, + help='Define kernel for cross compilation.') parser.add_argument('--cpu', default=None, help='Define cpu for cross compilation.') parser.add_argument('--cpu-family', default=None, @@ -61,6 +65,8 @@ self.cmake: T.Dict[str, T.Union[str, T.List[str]]] = {} self.system: T.Optional[str] = None + self.subsystem: T.Optional[str] = None + self.kernel: T.Optional[str] = None self.cpu: T.Optional[str] = None self.cpu_family: T.Optional[str] = None self.endian: T.Optional[str] = None @@ -131,13 +137,16 @@ if objcpp_link_args: infos.link_args['objcpp'] = objcpp_link_args -cpu_family_map = { +deb_cpu_family_map = { 'mips64el': 'mips64', 'i686': 'x86', + 'powerpc64le': 'ppc64', } -cpu_map = { + +deb_cpu_map = { 'armhf': 'arm7hlf', - 'mips64el': 'mips64' + 'mips64el': 'mips64', + 'powerpc64le': 'ppc64', } def deb_detect_cmake(infos: MachineInfo, data: T.Dict[str, str]) -> None: @@ -145,7 +154,10 @@ system_processor_map = {'arm': 'armv7l', 'mips64el': 'mips64', 'powerpc64le': 'ppc64le'} infos.cmake["CMAKE_C_COMPILER"] = infos.compilers['c'] - infos.cmake["CMAKE_CXX_COMPILER"] = infos.compilers['cpp'] + try: + infos.cmake["CMAKE_CXX_COMPILER"] = infos.compilers['cpp'] + except KeyError: + pass infos.cmake["CMAKE_SYSTEM_NAME"] = system_name_map[data['DEB_HOST_ARCH_OS']] infos.cmake["CMAKE_SYSTEM_PROCESSOR"] = system_processor_map.get(data['DEB_HOST_GNU_CPU'], data['DEB_HOST_GNU_CPU']) @@ -160,7 +172,7 @@ pass def detect_cross_debianlike(options: T.Any) -> MachineInfo: - if options.debarch is None: + if options.debarch == 'auto': cmd = ['dpkg-architecture'] else: cmd = ['dpkg-architecture', '-a' + options.debarch] @@ -175,10 +187,12 @@ data[k] = v host_arch = data['DEB_HOST_GNU_TYPE'] host_os = data['DEB_HOST_ARCH_OS'] - host_cpu_family = cpu_family_map.get(data['DEB_HOST_GNU_CPU'], - data['DEB_HOST_GNU_CPU']) - host_cpu = cpu_map.get(data['DEB_HOST_ARCH'], - data['DEB_HOST_ARCH']) + host_subsystem = host_os + host_kernel = 'linux' + host_cpu_family = deb_cpu_family_map.get(data['DEB_HOST_GNU_CPU'], + data['DEB_HOST_GNU_CPU']) + host_cpu = deb_cpu_map.get(data['DEB_HOST_ARCH'], + data['DEB_HOST_ARCH']) host_endian = data['DEB_HOST_ARCH_ENDIAN'] compilerstems = [('c', 'gcc'), @@ -199,7 +213,7 @@ except ValueError: pass try: - infos.binaries['pkgconfig'] = locate_path("%s-pkg-config" % host_arch) + infos.binaries['pkg-config'] = locate_path("%s-pkg-config" % host_arch) except ValueError: pass # pkg-config is optional try: @@ -207,6 +221,8 @@ except ValueError: pass infos.system = host_os + infos.subsystem = host_subsystem + infos.kernel = host_kernel infos.cpu_family = host_cpu_family infos.cpu = host_cpu infos.endian = host_endian @@ -254,11 +270,18 @@ ofile.write(f"cpu_family = '{infos.cpu_family}'\n") ofile.write(f"endian = '{infos.endian}'\n") ofile.write(f"system = '{infos.system}'\n") + if infos.subsystem: + ofile.write(f"subsystem = '{infos.subsystem}'\n") + if infos.kernel: + ofile.write(f"kernel = '{infos.kernel}'\n") + os.replace(tmpfilename, ofilename) def detect_language_args_from_envvars(langname: str, envvar_suffix: str = '') -> T.Tuple[T.List[str], T.List[str]]: ldflags = tuple(shlex.split(os.environ.get('LDFLAGS' + envvar_suffix, ''))) - compile_args = shlex.split(os.environ.get(compilers.CFLAGS_MAPPING[langname] + envvar_suffix, '')) + compile_args = [] + if langname in compilers.CFLAGS_MAPPING: + compile_args = shlex.split(os.environ.get(compilers.CFLAGS_MAPPING[langname] + envvar_suffix, '')) if langname in compilers.LANGUAGES_USING_CPPFLAGS: cppflags = tuple(shlex.split(os.environ.get('CPPFLAGS' + envvar_suffix, ''))) lang_compile_args = list(cppflags) + compile_args @@ -289,8 +312,16 @@ if binstr: infos.binaries[binname] = shlex.split(binstr) +def detect_properties_from_envvars(infos: MachineInfo, envvar_suffix: str = '') -> None: + var = os.environ.get('PKG_CONFIG_LIBDIR' + envvar_suffix) + if var is not None: + infos.properties['pkg_config_libdir'] = var + var = os.environ.get('PKG_CONFIG_SYSROOT_DIR' + envvar_suffix) + if var is not None: + infos.properties['sys_root'] = var + def detect_cross_system(infos: MachineInfo, options: T.Any) -> None: - for optname in ('system', 'cpu', 'cpu_family', 'endian'): + for optname in ('system', 'subsystem', 'kernel', 'cpu', 'cpu_family', 'endian'): v = getattr(options, optname) if not v: mlog.error(f'Cross property "{optname}" missing, set it with --{optname.replace("_", "-")}.') @@ -305,6 +336,8 @@ print('Detecting cross environment via environment variables.') infos = detect_compilers_from_envvars() detect_cross_system(infos, options) + detect_binaries_from_envvars(infos) + detect_properties_from_envvars(infos) return infos def add_compiler_if_missing(infos: MachineInfo, langname: str, exe_names: T.List[str]) -> None: @@ -350,6 +383,7 @@ detect_missing_native_compilers(infos) detect_binaries_from_envvars(infos, esuffix) detect_missing_native_binaries(infos) + detect_properties_from_envvars(infos, esuffix) return infos def run(options: T.Any) -> None: diff -Nru meson-1.0.1/mesonbuild/scripts/hotdochelper.py meson-1.2.1/mesonbuild/scripts/hotdochelper.py --- meson-1.0.1/mesonbuild/scripts/hotdochelper.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/scripts/hotdochelper.py 2023-05-23 15:20:02.000000000 +0000 @@ -15,14 +15,16 @@ parser.add_argument('--name') parser.add_argument('--builddir') parser.add_argument('--project-version') +parser.add_argument('--docdir') def run(argv: T.List[str]) -> int: options, args = parser.parse_known_args(argv) subenv = os.environ.copy() - for ext_path in options.extra_extension_path: - subenv['PYTHONPATH'] = subenv.get('PYTHONPATH', '') + ':' + ext_path + val = subenv.get('PYTHONPATH') + paths = [val] if val else [] + subenv['PYTHONPATH'] = os.pathsep.join(paths + options.extra_extension_path) res = subprocess.call(args, cwd=options.builddir, env=subenv) if res != 0: @@ -31,9 +33,7 @@ if options.install: source_dir = os.path.join(options.builddir, options.install) destdir = os.environ.get('DESTDIR', '') - installdir = destdir_join(destdir, - os.path.join(os.environ['MESON_INSTALL_PREFIX'], - 'share/doc/', options.name, "html")) + installdir = destdir_join(destdir, options.docdir) shutil.rmtree(installdir, ignore_errors=True) shutil.copytree(source_dir, installdir) diff -Nru meson-1.0.1/mesonbuild/scripts/meson_exe.py meson-1.2.1/mesonbuild/scripts/meson_exe.py --- meson-1.0.1/mesonbuild/scripts/meson_exe.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/scripts/meson_exe.py 2023-05-23 15:20:09.000000000 +0000 @@ -72,7 +72,8 @@ if p.returncode == 0xc0000135: # STATUS_DLL_NOT_FOUND on Windows indicating a common problem that is otherwise hard to diagnose - raise FileNotFoundError('due to missing DLLs') + strerror = 'Failed to run due to missing DLLs, with path: ' + child_env['PATH'] + raise FileNotFoundError(p.returncode, strerror, cmd_args) if p.returncode != 0: if exe.pickled: diff -Nru meson-1.0.1/mesonbuild/scripts/pycompile.py meson-1.2.1/mesonbuild/scripts/pycompile.py --- meson-1.0.1/mesonbuild/scripts/pycompile.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/mesonbuild/scripts/pycompile.py 2023-05-30 15:42:56.000000000 +0000 @@ -0,0 +1,65 @@ +# 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. + +# ignore all lints for this file, since it is run by python2 as well + +# type: ignore +# pylint: disable=deprecated-module + +import json, os, subprocess, sys +from compileall import compile_file + +quiet = int(os.environ.get('MESON_INSTALL_QUIET', 0)) + +def compileall(files): + for f in files: + # f is prefixed by {py_xxxxlib}, both variants are 12 chars + # the key is the middle 10 chars of the prefix + key = f[1:11].upper() + f = f[12:] + + ddir = None + fullpath = os.environ['MESON_INSTALL_DESTDIR_'+key] + f + f = os.environ['MESON_INSTALL_'+key] + f + + if fullpath != f: + ddir = os.path.dirname(f) + + if os.path.isdir(fullpath): + for root, _, files in os.walk(fullpath): + if ddir is not None: + ddir = root.replace(fullpath, f, 1) + for dirf in files: + if dirf.endswith('.py'): + fullpath = os.path.join(root, dirf) + compile_file(fullpath, ddir, force=True, quiet=quiet) + else: + compile_file(fullpath, ddir, force=True, quiet=quiet) + +def run(manifest): + data_file = os.path.join(os.path.dirname(__file__), manifest) + with open(data_file, 'rb') as f: + dat = json.load(f) + compileall(dat) + +if __name__ == '__main__': + manifest = sys.argv[1] + run(manifest) + if len(sys.argv) > 2: + optlevel = int(sys.argv[2]) + # python2 only needs one or the other + if optlevel == 1 or (sys.version_info >= (3,) and optlevel > 0): + subprocess.check_call([sys.executable, '-O'] + sys.argv[:2]) + if optlevel == 2: + subprocess.check_call([sys.executable, '-OO'] + sys.argv[:2]) diff -Nru meson-1.0.1/mesonbuild/scripts/python_info.py meson-1.2.1/mesonbuild/scripts/python_info.py --- meson-1.0.1/mesonbuild/scripts/python_info.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/mesonbuild/scripts/python_info.py 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +# ignore all lints for this file, since it is run by python2 as well + +# type: ignore +# pylint: disable=deprecated-module + +import sys + +# do not inject mesonbuild.scripts +# python -P would work too, but is exclusive to >=3.11 +if sys.path[0].endswith('scripts'): + del sys.path[0] + +import json, os, sysconfig +import distutils.command.install + +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 + cmd = Distribution().get_command_obj('build_ext') + cmd.ensure_finalized() + return bool(cmd.get_libraries(Extension('dummy', []))) + +variables = sysconfig.get_config_vars() +variables.update({'base_prefix': getattr(sys, 'base_prefix', sys.prefix)}) + +if sys.version_info < (3, 0): + suffix = variables.get('SO') +elif sys.version_info < (3, 8, 7): + # https://bugs.python.org/issue?@action=redirect&bpo=39825 + from distutils.sysconfig import get_config_var + suffix = get_config_var('EXT_SUFFIX') +else: + suffix = variables.get('EXT_SUFFIX') + +print(json.dumps({ + 'variables': variables, + 'paths': paths, + 'sysconfig_paths': sysconfig.get_paths(), + 'install_paths': install_paths, + 'version': sysconfig.get_python_version(), + 'platform': sysconfig.get_platform(), + 'is_pypy': '__pypy__' in sys.builtin_module_names, + 'is_venv': sys.prefix != variables['base_prefix'], + 'link_libpython': links_against_libpython(), + 'suffix': suffix, +})) diff -Nru meson-1.0.1/mesonbuild/scripts/run_tool.py meson-1.2.1/mesonbuild/scripts/run_tool.py --- meson-1.0.1/mesonbuild/scripts/run_tool.py 2022-10-24 19:25:13.000000000 +0000 +++ meson-1.2.1/mesonbuild/scripts/run_tool.py 2023-04-21 10:42:56.000000000 +0000 @@ -19,7 +19,7 @@ from concurrent.futures import ThreadPoolExecutor from ..compilers import lang_suffixes -from ..mesonlib import Popen_safe +from ..mesonlib import quiet_git import typing as T if T.TYPE_CHECKING: @@ -43,8 +43,8 @@ if patterns: globs = [srcdir.glob(p) for p in patterns] else: - p, o, _ = Popen_safe(['git', 'ls-files'], cwd=srcdir) - if p.returncode == 0: + r, o = quiet_git(['ls-files'], srcdir) + if r: globs = [[Path(srcdir, f) for f in o.splitlines()]] else: globs = [srcdir.glob('**/*')] diff -Nru meson-1.0.1/mesonbuild/utils/core.py meson-1.2.1/mesonbuild/utils/core.py --- meson-1.0.1/mesonbuild/utils/core.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/utils/core.py 2023-08-07 22:54:34.000000000 +0000 @@ -27,9 +27,12 @@ import typing as T if T.TYPE_CHECKING: + from hashlib import _Hash from typing_extensions import Literal from ..mparser import BaseNode - from . import programs + from .. import programs + + EnvironOrDict = T.Union[T.Dict[str, str], os._Environ[str]] EnvInitValueType = T.Dict[str, T.Union[str, T.List[str]]] @@ -68,7 +71,7 @@ class EnvironmentVariables(HoldableObject): def __init__(self, values: T.Optional[EnvInitValueType] = None, init_method: Literal['set', 'prepend', 'append'] = 'set', separator: str = os.pathsep) -> None: - self.envvars: T.List[T.Tuple[T.Callable[[T.Dict[str, str], str, T.List[str], str], str], str, T.List[str], str]] = [] + self.envvars: T.List[T.Tuple[T.Callable[[T.Dict[str, str], str, T.List[str], str, T.Optional[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: T.Set[str] = set() @@ -82,7 +85,7 @@ repr_str = "<{0}: {1}>" return repr_str.format(self.__class__.__name__, self.envvars) - def hash(self, hasher: T.Any): + def hash(self, hasher: _Hash) -> None: myenv = self.get_env({}) for key in sorted(myenv.keys()): hasher.update(bytes(key, encoding='utf-8')) @@ -96,6 +99,11 @@ def get_names(self) -> T.Set[str]: return self.varnames + def merge(self, other: EnvironmentVariables) -> None: + for method, name, values, separator in other.envvars: + self.varnames.add(name) + self.envvars.append((method, name, values, separator)) + 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)) @@ -122,10 +130,10 @@ curr = env.get(name, default_value) return separator.join(values if curr is None else values + [curr]) - def get_env(self, full_env: T.MutableMapping[str, str], dump: bool = False) -> T.Dict[str, str]: + def get_env(self, full_env: EnvironOrDict, default_fmt: T.Optional[str] = None) -> T.Dict[str, str]: env = full_env.copy() for method, name, values, separator in self.envvars: - default_value = f'${name}' if dump else None + default_value = default_fmt.format(name) if default_fmt else None env[name] = method(env, name, values, separator, default_value) return env @@ -144,8 +152,10 @@ feed: T.Optional[bool] = None tag: T.Optional[str] = None verbose: bool = False + installdir_map: T.Optional[T.Dict[str, str]] = None def __post_init__(self) -> None: self.pickled = False self.skip_if_destdir = False self.subproject = '' + self.dry_run = False diff -Nru meson-1.0.1/mesonbuild/utils/universal.py meson-1.2.1/mesonbuild/utils/universal.py --- meson-1.0.1/mesonbuild/utils/universal.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/utils/universal.py 2023-08-07 22:54:34.000000000 +0000 @@ -37,12 +37,26 @@ from .core import MesonException, HoldableObject if T.TYPE_CHECKING: - from typing_extensions import Literal + from typing_extensions import Literal, Protocol from .._typing import ImmutableListProtocol from ..build import ConfigurationData from ..coredata import KeyedOptionDictType, UserOption + from ..environment import Environment from ..compilers.compilers import Compiler + from ..interpreterbase.baseobjects import SubProject + + class _EnvPickleLoadable(Protocol): + + environment: Environment + + class _VerPickleLoadable(Protocol): + + version: str + + # A generic type for pickle_load. This allows any type that has either a + # .version or a .environment to be passed. + _PL = T.TypeVar('_PL', bound=T.Union[_EnvPickleLoadable, _VerPickleLoadable]) FileOrString = T.Union['File', str] @@ -130,6 +144,7 @@ 'path_is_in_root', 'pickle_load', 'Popen_safe', + 'Popen_safe_logged', 'quiet_git', 'quote_arg', 'relative_to_if_possible', @@ -162,8 +177,8 @@ from glob import glob -if os.path.basename(sys.executable) == 'meson.exe': - # In Windows and using the MSI installed executable. +if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'): + # using a PyInstaller bundle, e.g. the MSI installed executable python_command = [sys.executable, 'runpython'] else: python_command = [sys.executable] @@ -255,7 +270,7 @@ 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 SecondLevelHolder(HoldableObject, metaclass=abc.ABCMeta): ''' A second level object holder. The primary purpose @@ -687,15 +702,23 @@ 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') - stdo = stdo.replace('ppc7400', 'ppc') - stdo = stdo.replace('ppc970', 'ppc') + map_arch = { + 'i386': 'x86', + 'arm64': 'aarch64', + 'arm64e': 'aarch64', + 'ppc7400': 'ppc', + 'ppc970': 'ppc', + } + lipo_archs = stdo.split() + meson_archs = [map_arch.get(lipo_arch, lipo_arch) for lipo_arch in lipo_archs] + # Add generic name for armv7 and armv7s if 'armv7' in stdo: - stdo += ' arm' - return stdo.split() + meson_archs.append('arm') + + return meson_archs def windows_detect_native_arch() -> str: """ @@ -740,7 +763,7 @@ 'name': 'git', 'cmd': 'git', 'repo_dir': '.git', - 'get_rev': 'git describe --dirty=+', + 'get_rev': 'git describe --dirty=+ --always', 'rev_regex': '(.*)', 'dep': '.git/logs/HEAD' }, @@ -1192,7 +1215,7 @@ return re.sub(regex, variable_replace, line), missing_variables def do_define(regex: T.Pattern[str], line: str, confdata: 'ConfigurationData', - variable_format: Literal['meson', 'cmake', 'cmake@']) -> str: + variable_format: Literal['meson', 'cmake', 'cmake@'], subproject: T.Optional[SubProject] = None) -> str: def get_cmake_define(line: str, confdata: 'ConfigurationData') -> str: arr = line.split() define_value = [] @@ -1205,8 +1228,12 @@ 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()) + if len(arr) != 2: + if variable_format == 'meson': + raise MesonException('#mesondefine does not contain exactly two tokens: %s' % line.strip()) + elif subproject is not None: + from ..interpreterbase.decorators import FeatureNew + FeatureNew.single_use('cmakedefine without exactly two tokens', '0.54.1', subproject) varname = arr[1] try: @@ -1242,7 +1269,7 @@ def do_conf_str(src: str, data: list, confdata: 'ConfigurationData', variable_format: Literal['meson', 'cmake', 'cmake@'], - encoding: str = 'utf-8') -> T.Tuple[T.List[str], T.Set[str], bool]: + encoding: str = 'utf-8', subproject: T.Optional[SubProject] = None) -> 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: @@ -1266,7 +1293,7 @@ for line in data: if line.startswith(search_token): confdata_useless = False - line = do_define(regex, line, confdata, variable_format) + line = do_define(regex, line, confdata, variable_format, subproject) 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}"') @@ -1280,14 +1307,14 @@ def do_conf_file(src: str, dst: str, confdata: 'ConfigurationData', variable_format: Literal['meson', 'cmake', 'cmake@'], - encoding: str = 'utf-8') -> T.Tuple[T.Set[str], bool]: + encoding: str = 'utf-8', subproject: T.Optional[SubProject] = None) -> 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) + (result, missing_variables, confdata_useless) = do_conf_str(src, data, confdata, variable_format, encoding, subproject) dst_tmp = dst + '~' try: with open(dst_tmp, 'w', encoding=encoding, newline='') as f: @@ -1494,6 +1521,21 @@ return p, o, e +def Popen_safe_logged(args: T.List[str], msg: str = 'Called', **kwargs: T.Any) -> T.Tuple['subprocess.Popen[str]', str, str]: + ''' + Wrapper around Popen_safe that assumes standard piped o/e and logs this to the meson log. + ''' + p, o, e = Popen_safe(args, **kwargs) + rc, out, err = p.returncode, o.strip(), e.strip() + mlog.debug('-----------') + mlog.debug(f'{msg}: `{join_args(args)}` -> {rc}') + if out: + mlog.debug(f'stdout:\n{out}\n-----------') + if err: + mlog.debug(f'stderr:\n{err}\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 @@ -1875,17 +1917,20 @@ __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): + bar_type: T.Optional[str] = None, desc: T.Optional[str] = None, + disable: T.Optional[bool] = 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='') + self.disable = not mlog.colorize_console() if disable is None else disable + if not self.disable: + 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 @@ -1896,8 +1941,9 @@ return next(self.iterable) def print_dot(self) -> None: - print('.', end='') - sys.stdout.flush() + if not self.disable: + print('.', end='') + sys.stdout.flush() self.printed_dots += 1 def update(self, progress: int) -> None: @@ -1911,7 +1957,8 @@ self.print_dot() def close(self) -> None: - print('') + if not self.disable: + print() try: from tqdm import tqdm @@ -1922,10 +1969,17 @@ 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}) + kwargs.update({'unit': 'B', + 'unit_scale': True, + 'unit_divisor': 1024, + 'leave': True, + 'bar_format': '{l_bar}{bar}| {n_fmt}/{total_fmt} {rate_fmt} eta {remaining}', + }) + else: - kwargs.update({'leave': False}) - kwargs['ncols'] = 100 + kwargs.update({'leave': False, + 'bar_format': '{l_bar}{bar}| {n_fmt}/{total_fmt} eta {remaining}', + }) super().__init__(*args, **kwargs) ProgressBar = ProgressBarTqdm @@ -2098,6 +2152,7 @@ 'includedir', 'infodir', 'libdir', + 'licensedir', 'libexecdir', 'localedir', 'localstatedir', @@ -2111,6 +2166,7 @@ 'debug', 'default_library', 'errorlogs', + 'genvslite', 'install_umask', 'layout', 'optimization', @@ -2125,6 +2181,7 @@ 'force_fallback_for', 'pkg_config_path', 'cmake_prefix_path', + 'vsenv', } @@ -2275,7 +2332,7 @@ 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. + """Create a new copy of this key, but with altered members. For example: >>> a = OptionKey('foo', '', MachineChoice.Host) @@ -2298,11 +2355,11 @@ return self.evolve(subproject='') def as_build(self) -> 'OptionKey': - """Convenience method for key.evolve(machine=MachinceChoice.BUILD).""" + """Convenience method for key.evolve(machine=MachineChoice.BUILD).""" return self.evolve(machine=MachineChoice.BUILD) def as_host(self) -> 'OptionKey': - """Convenience method for key.evolve(machine=MachinceChoice.HOST).""" + """Convenience method for key.evolve(machine=MachineChoice.HOST).""" return self.evolve(machine=MachineChoice.HOST) def is_backend(self) -> bool: @@ -2325,7 +2382,8 @@ """Convenience method to check if this is a base option.""" return self.type is OptionType.BASE -def pickle_load(filename: str, object_name: str, object_type: T.Type) -> T.Any: + +def pickle_load(filename: str, object_name: str, object_type: T.Type[_PL]) -> _PL: load_fail_msg = f'{object_name} file {filename!r} is corrupted. Try with a fresh build tree.' try: with open(filename, 'rb') as f: @@ -2341,11 +2399,18 @@ f'meson setup {build_dir} --wipe') if not isinstance(obj, object_type): raise MesonException(load_fail_msg) + + # Because these Protocols are not available at runtime (and cannot be made + # available at runtime until we drop support for Python < 3.8), we have to + # do a bit of hackery so that mypy understands what's going on here + version: str + if hasattr(obj, 'version'): + version = T.cast('_VerPickleLoadable', obj).version + else: + version = T.cast('_EnvPickleLoadable', obj).environment.coredata.version + from ..coredata import version as coredata_version from ..coredata import major_versions_differ, MesonVersionMismatchException - version = getattr(obj, 'version', None) - if version is None: - version = obj.environment.coredata.version if major_versions_differ(version, coredata_version): raise MesonVersionMismatchException(version, coredata_version) return obj diff -Nru meson-1.0.1/mesonbuild/utils/vsenv.py meson-1.2.1/mesonbuild/utils/vsenv.py --- meson-1.0.1/mesonbuild/utils/vsenv.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/mesonbuild/utils/vsenv.py 2023-08-07 22:54:34.000000000 +0000 @@ -70,7 +70,7 @@ ) bat_info = json.loads(bat_json) if not bat_info: - # VS installer instelled but not VS itself maybe? + # VS installer installed but not VS itself maybe? raise MesonException('Could not parse vswhere.exe output') bat_root = pathlib.Path(bat_info[0]['installationPath']) if windows_detect_native_arch() == 'arm64': diff -Nru meson-1.0.1/mesonbuild/wrap/wrap.py meson-1.2.1/mesonbuild/wrap/wrap.py --- meson-1.0.1/mesonbuild/wrap/wrap.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/mesonbuild/wrap/wrap.py 2023-07-21 20:36:13.000000000 +0000 @@ -34,7 +34,7 @@ from base64 import b64encode from netrc import netrc -from pathlib import Path +from pathlib import Path, PurePath from . import WrapMode from .. import coredata @@ -54,8 +54,7 @@ except ImportError: has_ssl = False -REQ_TIMEOUT = 600.0 -SSL_WARNING_PRINTED = False +REQ_TIMEOUT = 30.0 WHITELIST_SUBDOMAIN = 'wrapdb.mesonbuild.com' ALL_TYPES = ['file', 'git', 'hg', 'svn'] @@ -96,10 +95,7 @@ raise WrapException(f'SSL module not available in {sys.executable}: Cannot contact the WrapDB.{insecure_msg}') else: # following code is only for those without Python SSL - global SSL_WARNING_PRINTED # pylint: disable=global-statement - if not SSL_WARNING_PRINTED: - mlog.warning(f'SSL module not available in {sys.executable}: WrapDB traffic not authenticated.') - SSL_WARNING_PRINTED = True + mlog.warning(f'SSL module not available in {sys.executable}: WrapDB traffic not authenticated.', once=True) # If we got this far, allow_insecure was manually passed nossl_url = url._replace(scheme='http') @@ -228,6 +224,8 @@ self.diff_files.append(path) def parse_provide_section(self, config: configparser.ConfigParser) -> None: + if config.has_section('provides'): + raise WrapException('Unexpected "[provides]" section, did you mean "[provide]"?') if config.has_section('provide'): for k, v in config['provide'].items(): if k == 'dependency_names': @@ -287,6 +285,7 @@ wrap_mode: WrapMode = WrapMode.default wrap_frontend: bool = False allow_insecure: bool = False + silent: bool = False def __post_init__(self) -> None: self.subdir_root = os.path.join(self.source_dir, self.subdir) @@ -434,10 +433,10 @@ # 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('''\ + f.write(textwrap.dedent(f'''\ [wrap-redirect] - filename = {} - '''.format(os.path.relpath(self.wrap.filename, self.subdir_root)))) + filename = {PurePath(os.path.relpath(self.wrap.filename, self.subdir_root)).as_posix()} + ''')) else: # No wrap file, it's a dummy package definition for an existing # directory. Use the source code in place. @@ -697,7 +696,8 @@ return hashvalue, tmpfile.name sys.stdout.flush() progress_bar = ProgressBar(bar_type='download', total=dlsize, - desc='Downloading') + desc='Downloading', + disable=(self.silent or None)) while True: block = resp.read(blocksize) if block == b'': @@ -798,7 +798,8 @@ raise WrapException(f'Diff file "{path}" does not exist') relpath = os.path.relpath(str(path), self.dirname) if PATCH: - cmd = [PATCH, '-f', '-p1', '-i', relpath] + # Always pass a POSIX path to patch, because on Windows it's MSYS + cmd = [PATCH, '-f', '-p1', '-i', str(Path(relpath).as_posix())] elif GIT: # If the `patch` command is not available, fall back to `git # apply`. The `--work-tree` is necessary in case we're inside a diff -Nru meson-1.0.1/packaging/createmsi.py meson-1.2.1/packaging/createmsi.py --- meson-1.0.1/packaging/createmsi.py 2022-06-07 18:25:16.000000000 +0000 +++ meson-1.2.1/packaging/createmsi.py 2023-08-07 22:54:24.000000000 +0000 @@ -31,7 +31,7 @@ from mesonbuild import coredata # Elementtree does not support CDATA. So hack it. -WINVER_CHECK = ' 602)]]>' +WINVER_CHECK = 'Installed OR (VersionNT64 > 602)>' def gen_guid(): ''' @@ -102,7 +102,7 @@ 'Title': 'Meson', 'Description': 'Meson executables', 'Level': '1', - 'Absent': 'disallow', + 'AllowAbsent': 'no', }, self.staging_dirs[1]: { 'Id': 'NinjaProgram', @@ -160,49 +160,44 @@ ''' 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', { + self.root = ET.Element('Wix', { + 'xmlns': 'http://wixtoolset.org/schemas/v4/wxs', + 'xmlns:ui': 'http://wixtoolset.org/schemas/v4/wxs/ui' + }) + + package = ET.SubElement(self.root, 'Package', { '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': '*', + ET.SubElement(package, 'SummaryInformation', { '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.'}) + ET.SubElement(package, + 'Launch', + {'Message': 'This application is only supported on Windows 10 or higher.', + 'Condition': 'X'*len(WINVER_CHECK)}) + + ET.SubElement(package, 'MajorUpgrade', + {'DowngradeErrorMessage': + 'A newer version of Meson is already installed.'}) - package.set('Platform', 'x64') - ET.SubElement(product, 'Media', { + ET.SubElement(package, 'Media', { 'Id': '1', 'Cabinet': 'meson.cab', 'EmbedCab': 'yes', }) - targetdir = ET.SubElement(product, 'Directory', { - 'Id': 'TARGETDIR', - 'Name': 'SourceDir', + targetdir = ET.SubElement(package, 'StandardDirectory', { + 'Id': 'ProgramFiles64Folder', }) - progfiledir = ET.SubElement(targetdir, 'Directory', { - 'Id': self.progfile_dir, - }) - installdir = ET.SubElement(progfiledir, 'Directory', { + installdir = ET.SubElement(targetdir, 'Directory', { 'Id': 'INSTALLDIR', 'Name': 'Meson', }) @@ -213,16 +208,12 @@ 'Language': '0', }) - ET.SubElement(product, 'Property', { - 'Id': 'WIXUI_INSTALLDIR', - 'Value': 'INSTALLDIR', - }) - ET.SubElement(product, 'UIRef', { + ET.SubElement(package, 'ui:WixUI', { 'Id': 'WixUI_FeatureTree', }) for s_d in self.staging_dirs: assert os.path.isdir(s_d) - top_feature = ET.SubElement(product, 'Feature', { + top_feature = ET.SubElement(package, 'Feature', { 'Id': 'Complete', 'Title': 'Meson ' + self.version, 'Description': 'The complete package', @@ -246,7 +237,7 @@ }) 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 + # ElementTree cannot do pretty-printing, 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: @@ -277,10 +268,10 @@ component_id = f'ApplicationFiles{self.component_num}' comp_xml_node = ET.SubElement(parent_xml_node, 'Component', { 'Id': component_id, + 'Bitness': 'always64', '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', @@ -311,23 +302,40 @@ ''' 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]) + subprocess.check_call(['wix', + 'build', + '-bindvariable', 'WixUILicenseRtf=packaging\\License.rtf', + '-ext', 'WixToolset.UI.wixext', + '-culture', 'en-us', + '-arch', 'x64', + '-o', + self.final_output, + self.main_xml, + ]) + + +def install_wix(): + subprocess.check_call(['dotnet', + 'nuget', + 'add', + 'source', + 'https://api.nuget.org/v3/index.json']) + subprocess.check_call(['dotnet', + 'tool', + 'install', + '--global', + 'wix']) + subprocess.check_call(['wix', + 'extension', + 'add', + 'WixToolset.UI.wixext', + ]) if __name__ == '__main__': if not os.path.exists('meson.py'): sys.exit(print('Run me in the top level source dir.')) + if not shutil.which('wix'): + install_wix() subprocess.check_call(['pip', 'install', '--upgrade', 'pyinstaller']) p = PackageGenerator() diff -Nru meson-1.0.1/packaging/createpkg.py meson-1.2.1/packaging/createpkg.py --- meson-1.0.1/packaging/createpkg.py 2022-06-07 18:25:16.000000000 +0000 +++ meson-1.2.1/packaging/createpkg.py 2023-05-30 15:43:02.000000000 +0000 @@ -16,6 +16,7 @@ import subprocess import shutil, sys, os +from glob import glob import xml.etree.ElementTree as ET @@ -41,7 +42,10 @@ 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' + pyinstaller_bin = glob('/Users/jpakkane/Library/Python/*/bin/pyinstaller') + if len(pyinstaller_bin) != 1: + sys.exit('Could not determine unique installer.') + pyinstaller_bin = pyinstaller_bin[0] pyinst_cmd = [pyinstaller_bin, '--clean', '--additional-hooks-dir=packaging', @@ -85,7 +89,7 @@ ET.SubElement(root, 'pkg-ref', {'id': self.identifier}) ET.SubElement(root, 'options', {'customize': 'never', 'require-scripts': 'false', - 'hostArhcitectures': 'x86_64,arm64'}) + 'hostArchitectures': '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}) @@ -96,7 +100,7 @@ '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 + # ElementTree cannot do pretty-printing, 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: diff -Nru meson-1.0.1/packaging/hook-mesonbuild.py meson-1.2.1/packaging/hook-mesonbuild.py --- meson-1.0.1/packaging/hook-mesonbuild.py 2022-06-19 19:10:07.000000000 +0000 +++ meson-1.2.1/packaging/hook-mesonbuild.py 2023-08-07 22:54:24.000000000 +0000 @@ -21,11 +21,15 @@ modules = ['mesonbuild.' + modname + '.' + x for x in modules if not x.startswith('_')] return modules -datas += collect_data_files('mesonbuild.scripts') +datas += collect_data_files('mesonbuild.scripts', include_py_files=True, excludes=['**/__pycache__']) datas += collect_data_files('mesonbuild.cmake.data') datas += collect_data_files('mesonbuild.dependencies.data') +# lazy-loaded +hiddenimports += get_all_modules_from_dir('mesonbuild/dependencies') +# imported by meson.build files hiddenimports += get_all_modules_from_dir('mesonbuild/modules') +# executed when named on CLI hiddenimports += get_all_modules_from_dir('mesonbuild/scripts') # Python packagers want to be minimal and only copy the things diff -Nru meson-1.0.1/run_meson_command_tests.py meson-1.2.1/run_meson_command_tests.py --- meson-1.0.1/run_meson_command_tests.py 2023-02-01 21:43:18.000000000 +0000 +++ meson-1.2.1/run_meson_command_tests.py 2023-04-21 10:42:56.000000000 +0000 @@ -135,8 +135,7 @@ (bindir / 'python3').symlink_to(python_command[0]) os.environ['PATH'] = str(bindir) + os.pathsep + os.environ['PATH'] # use our overridden PATH-compatible python - path_resolved_meson_command = resolved_meson_command.copy() - path_resolved_meson_command[0] = str(bindir / 'python3') + path_resolved_meson_command = [str(bindir / 'meson')] # See if it works! meson_py = 'meson' meson_setup = [meson_py, 'setup'] diff -Nru meson-1.0.1/run_project_tests.py meson-1.2.1/run_project_tests.py --- meson-1.0.1/run_project_tests.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/run_project_tests.py 2023-06-28 14:48:20.000000000 +0000 @@ -63,7 +63,6 @@ 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 @@ -154,7 +153,7 @@ if self.language in {'c', 'cpp'}: has_pdb = canonical_compiler == 'msvc' elif self.language == 'd': - # dmd's optlink does not genearte pdb iles + # dmd's optlink does not generate pdb files has_pdb = env.coredata.compilers.host['d'].linker.id in {'link', 'lld-link'} # Abort if the platform does not match @@ -213,7 +212,9 @@ 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(): + if 'mwcc' in canonical_compiler: + return p.with_suffix('.nef') + elif env.machines.host.is_windows() or env.machines.host.is_cygwin(): return p.with_suffix('.exe') elif self.typ == 'pdb': if self.version: @@ -290,6 +291,7 @@ failing_logs: T.List[str] = [] print_debug = 'MESON_PRINT_TEST_OUTPUT' in os.environ under_ci = 'CI' in os.environ +ci_is_github = 'GITHUB_ACTIONS' in os.environ raw_ci_jobname = os.environ.get('MESON_CI_JOBNAME', None) ci_jobname = raw_ci_jobname if raw_ci_jobname != 'thirdparty' else None do_debug = under_ci or print_debug @@ -421,11 +423,16 @@ def _run_ci_include(args: T.List[str]) -> str: + header = f'Included file {args[0]}:' + footer = '' + if ci_is_github: + header = f'::group::==== {header} ====' + footer = '::endgroup::' if not args: return 'At least one parameter required' try: data = Path(args[0]).read_text(errors='ignore', encoding='utf-8') - return 'Included file {}:\n{}\n'.format(args[0], data) + return f'{header}\n{data}\n{footer}' except Exception: return 'Failed to open {}'.format(args[0]) @@ -533,7 +540,7 @@ # coded to run as a batch process. def clear_internal_caches() -> None: import mesonbuild.interpreterbase - from mesonbuild.dependencies import CMakeDependency + from mesonbuild.dependencies.cmake import CMakeDependency from mesonbuild.mesonlib import PerMachine mesonbuild.interpreterbase.FeatureNew.feature_registry = {} CMakeDependency.class_cmakeinfo = PerMachine(None, None) @@ -655,16 +662,19 @@ 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) + inprocess, res = run_configure(gen_args, env=test.env, catch_exception=True) + returncode, stdo, stde = res + cmd = '(inprocess) $ ' if inprocess else '$ ' + cmd += mesonlib.join_args(gen_args) try: logfile = Path(test_build_dir, 'meson-logs', 'meson-log.txt') with logfile.open(errors='ignore', encoding='utf-8') as fid: - mesonlog = fid.read() + mesonlog = '\n'.join((cmd, fid.read())) except Exception: mesonlog = no_meson_log_msg cicmds = run_ci_commands(mesonlog) testresult = TestResult(cicmds) - testresult.add_step(BuildStep.configure, stdo, stde, mesonlog, time.time() - gen_start) + testresult.add_step(BuildStep.configure, '\n'.join((cmd, stdo)), stde, mesonlog, time.time() - gen_start) output_msg = validate_output(test, stdo, stde) testresult.mlog += output_msg if output_msg: diff -Nru meson-1.0.1/run_tests.py meson-1.2.1/run_tests.py --- meson-1.0.1/run_tests.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/run_tests.py 2023-08-07 22:54:34.000000000 +0000 @@ -36,7 +36,7 @@ from mesonbuild.compilers.c import CCompiler from mesonbuild.compilers.detect import detect_c_compiler -from mesonbuild import dependencies +from mesonbuild.dependencies.pkgconfig import PkgConfigDependency from mesonbuild import mesonlib from mesonbuild import mesonmain from mesonbuild import mtest @@ -297,13 +297,13 @@ out = StringIO() with mock.patch.object(sys, 'stdout', out), mock.patch.object(sys, 'stderr', out): returncode = mtest.run_with_args(commandlist) - return returncode, stdout.getvalue() + return returncode, out.getvalue() def clear_meson_configure_class_caches() -> None: CCompiler.find_library_cache = {} CCompiler.find_framework_cache = {} - dependencies.PkgConfigDependency.pkgbin_cache = {} - dependencies.PkgConfigDependency.class_pkgbin = mesonlib.PerMachine(None, None) + PkgConfigDependency.pkgbin_cache = {} + PkgConfigDependency.class_pkgbin = mesonlib.PerMachine(None, None) mesonlib.project_meson_versions = collections.defaultdict(str) 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]: @@ -327,11 +327,11 @@ pc, o, e = mesonlib.Popen_safe(full_command, env=env) return pc.returncode, o, e -def run_configure(commandlist: T.List[str], env: T.Optional[T.Dict[str, str]] = None, catch_exception: bool = False) -> T.Tuple[int, str, str]: +def run_configure(commandlist: T.List[str], env: T.Optional[T.Dict[str, str]] = None, catch_exception: bool = False) -> T.Tuple[bool, 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, catch_exception=catch_exception) + return (False, run_configure_external(meson_exe + commandlist, env=env)) + return (True, run_configure_inprocess(commandlist, env=env, catch_exception=catch_exception)) def print_system_info(): print(mlog.bold('System information.')) @@ -358,7 +358,7 @@ parser.add_argument('--no-unittests', action='store_true', default=False) (options, _) = parser.parse_known_args() returncode = 0 - backend, _ = guess_backend(options.backend, shutil.which('msbuild')) + _, backend_flags = guess_backend(options.backend, shutil.which('msbuild')) no_unittests = options.no_unittests # Running on a developer machine? Be nice! if not mesonlib.is_windows() and not mesonlib.is_haiku() and 'CI' not in os.environ: @@ -394,7 +394,7 @@ else: print(mlog.bold('Running unittests.')) print(flush=True) - cmd = mesonlib.python_command + ['run_unittests.py', '--backend=' + backend.name, '-v'] + cmd = mesonlib.python_command + ['run_unittests.py', '-v'] + backend_flags if options.failfast: cmd += ['--failfast'] returncode += subprocess_call(cmd, env=env) diff -Nru meson-1.0.1/run_unittests.py meson-1.2.1/run_unittests.py --- meson-1.0.1/run_unittests.py 2022-12-10 16:46:15.000000000 +0000 +++ meson-1.2.1/run_unittests.py 2023-06-28 14:48:20.000000000 +0000 @@ -36,6 +36,7 @@ import mesonbuild.modules.pkgconfig from unittests.allplatformstests import AllPlatformTests +from unittests.cargotests import CargoVersionTest, CargoCfgTest from unittests.darwintests import DarwinTests from unittests.failuretests import FailureTests from unittests.linuxcrosstests import LinuxCrossArmTests, LinuxCrossMingwTests diff -Nru meson-1.0.1/setup.cfg meson-1.2.1/setup.cfg --- meson-1.0.1/setup.cfg 2023-02-23 22:09:18.125258400 +0000 +++ meson-1.2.1/setup.cfg 2023-08-07 22:56:08.500238000 +0000 @@ -5,13 +5,15 @@ author = Jussi Pakkanen author_email = jpakkane@gmail.com url = https://mesonbuild.com +project_urls = + Source = https://github.com/mesonbuild/meson keywords = meson mesonbuild build system cmake license = Apache License, Version 2.0 -license_file = COPYING +license_files = COPYING classifiers = Development Status :: 5 - Production/Stable Environment :: Console diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cmake/26 cmake package prefix dir/cmakePackagePrefixDirConfig.cmake.in" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cmake/26 cmake package prefix dir/cmakePackagePrefixDirConfig.cmake.in" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cmake/26 cmake package prefix dir/cmakePackagePrefixDirConfig.cmake.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cmake/26 cmake package prefix dir/cmakePackagePrefixDirConfig.cmake.in" 2023-07-21 20:36:13.000000000 +0000 @@ -0,0 +1 @@ +@PACKAGE_INIT@ diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cmake/26 cmake package prefix dir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cmake/26 cmake package prefix dir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cmake/26 cmake package prefix dir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cmake/26 cmake package prefix dir/meson.build" 2023-07-21 20:36:13.000000000 +0000 @@ -0,0 +1,19 @@ +project('cmakePackagePrefixDir', 'c', version: '1.0.0') + +cmake = import('cmake') + +cmake.configure_package_config_file( + name: 'cmakePackagePrefixDir', + input: 'cmakePackagePrefixDirConfig.cmake.in', + configuration: configuration_data(), +) + +# NOTE: can't use fs.read because cmakePackagePrefixDirConfig.cmake is in build_dir +python = find_program('python3') +lines = run_command(python, '-c', + '[print(line, end="") for line in open("@0@")]'.format(meson.current_build_dir() / 'cmakePackagePrefixDirConfig.cmake'), check : true, +).stdout().split('\n') + +message(lines) + +assert(lines[5] == 'get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../.." ABSOLUTE)') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cmake/26 cmake package prefix dir/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cmake/26 cmake package prefix dir/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cmake/26 cmake package prefix dir/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cmake/26 cmake package prefix dir/test.json" 2023-07-21 20:36:13.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/cmake/cmakePackagePrefixDir/cmakePackagePrefixDirConfig.cmake"} + ] +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cmake/9 disabled subproject/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cmake/9 disabled subproject/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cmake/9 disabled subproject/meson.build" 2023-02-01 21:57:16.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cmake/9 disabled subproject/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -2,5 +2,5 @@ cm = import('cmake') -sub_pro = cm.subproject('nothinig', required: false) +sub_pro = cm.subproject('nothing', required: false) assert(not sub_pro.found(), 'subproject found() reports wrong value') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/100 postconf with args/postconf.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/100 postconf with args/postconf.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/100 postconf with args/postconf.py" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/100 postconf with args/postconf.py" 2023-07-21 20:36:13.000000000 +0000 @@ -12,7 +12,7 @@ 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: +with open(input_file, encoding='utf-8') as f: data = f.readline().strip() -with open(output_file, 'w') as f: +with open(output_file, 'w', encoding='utf-8') as f: f.write(template.format(data, sys.argv[1], sys.argv[2])) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/102 extract same name/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/102 extract same name/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/102 extract same name/meson.build" 2023-02-01 21:58:50.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/102 extract same name/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -9,7 +9,7 @@ # # 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.') + error('MESON_SKIP_TEST, Xcode cannot extract objs when they would have the same filename.') endif lib = library('somelib', ['lib.c', 'src/lib.c']) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/105 generatorcustom/gen.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/105 generatorcustom/gen.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/105 generatorcustom/gen.c" 2023-02-01 21:43:18.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/105 generatorcustom/gen.c" 2023-04-21 10:42:56.000000000 +0000 @@ -22,9 +22,17 @@ fprintf(output, "#pragma once\n"); fprintf(output, "#define "); - char c; + int bytes_copied = 0; + int c; while((c = fgetc(input)) != EOF) { - fputc(c, output); + if(fputc(c, output) == EOF) { + fprintf(stderr, "Writing to output file failed.\n"); + return 1; + } + if(++bytes_copied > 10000) { + fprintf(stderr, "File copy stuck in an eternal loop!\n"); + return 1; + } } fputc('\n', output); diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/117 shared module/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/117 shared module/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/117 shared module/meson.build" 2023-02-01 21:58:59.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/117 shared module/meson.build" 2023-04-21 10:42:56.000000000 +0000 @@ -36,5 +36,6 @@ # Shared module that does not export any symbols shared_module('nosyms', 'nosyms.c', + override_options: ['werror=false'], install : true, install_dir : join_paths(get_option('libdir'), 'modules')) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/130 include order/inc3/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/130 include order/inc3/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/130 include order/inc3/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/130 include order/inc3/meson.build" 2023-04-21 10:42:56.000000000 +0000 @@ -0,0 +1,2 @@ +configure_file(output: 'prefer-build-dir-over-src-dir.h', + configuration: configuration_data()) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/130 include order/inc3/prefer-build-dir-over-src-dir.h" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/130 include order/inc3/prefer-build-dir-over-src-dir.h" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/130 include order/inc3/prefer-build-dir-over-src-dir.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/130 include order/inc3/prefer-build-dir-over-src-dir.h" 2023-04-21 10:42:56.000000000 +0000 @@ -0,0 +1 @@ +#error "inc3/prefer-build-dir-over-src-dir.h included" diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/130 include order/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/130 include order/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/130 include order/meson.build" 2023-02-01 21:59:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/130 include order/meson.build" 2023-04-21 10:42:56.000000000 +0000 @@ -12,6 +12,8 @@ # Custom target dir with a built header subdir('ctsub') +# Configures a header file +subdir('inc3') # Defines an internal dep subdir('sub1') # Defines a per-target include path @@ -32,5 +34,5 @@ test('oh', f) # Test that the order in include_directories() is maintained -incs = include_directories('inc1', 'inc2') +incs = include_directories('inc1', 'inc2', 'inc3') executable('ordertest', 'ordertest.c', include_directories: incs) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/130 include order/ordertest.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/130 include order/ordertest.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/130 include order/ordertest.c" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/130 include order/ordertest.c" 2023-04-21 10:42:56.000000000 +0000 @@ -1,4 +1,5 @@ #include "hdr.h" +#include "prefer-build-dir-over-src-dir.h" #if !defined(SOME_DEFINE) || SOME_DEFINE != 42 #error "Should have picked up hdr.h from inc1/hdr.h" diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/132 get define/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/132 get define/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/132 get define/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/132 get define/test.json" 2023-07-05 15:40:06.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "matrix": { + "options": { + "c_std": [ + { "val": "none" }, + { "val": "c11" } + ] + } + } +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/14 configure file/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/14 configure file/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/14 configure file/meson.build" 2023-02-01 21:58:01.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/14 configure file/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -161,7 +161,7 @@ install_dir : false, configuration : conf) -# test intsall_dir with install: false +# test install_dir with install: false cfile = configure_file(input : 'config.h.in', output : 'do_not_get_installed_in_install_dir.h', install : false, diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/147 simd/simd_mmx.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/147 simd/simd_mmx.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/147 simd/simd_mmx.c" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/147 simd/simd_mmx.c" 2023-04-21 10:42:56.000000000 +0000 @@ -45,14 +45,16 @@ * enough to fit in int16; */ int i; + /* This is unused due to below comment about GCC 8. __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 = (int64_t)(result); + */ + /* The above 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. diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/148 shared module resolving symbol in executable/prog.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/148 shared module resolving symbol in executable/prog.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/148 shared module resolving symbol in executable/prog.c" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/148 shared module resolving symbol in executable/prog.c" 2023-04-21 10:42:56.000000000 +0000 @@ -30,7 +30,7 @@ int expected, actual; fptr importedfunc; - if (argc=0) {}; // noop + (void)argc; // noop #ifdef _WIN32 HMODULE h = LoadLibraryA(argv[1]); diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/151 duplicate source names/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/151 duplicate source names/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/151 duplicate source names/meson.build" 2023-02-01 21:59:26.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/151 duplicate source names/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -9,7 +9,7 @@ # # 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.') + error('MESON_SKIP_TEST, Xcode cannot extract objs when they would have the same filename.') endif sources = [] diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/158 disabler/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/158 disabler/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/158 disabler/meson.build" 2023-02-01 21:59:32.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/158 disabler/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -97,7 +97,7 @@ get_d = get_variable('d6') assert(is_disabler(get_d), 'get_variable should yield a disabler') -get_fallback_d = get_variable('nonexistant', disabler()) +get_fallback_d = get_variable('nonexistent', disabler()) assert(is_disabler(get_fallback_d), 'get_variable fallback should yield a disabler') var_true = true diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/178 bothlibraries/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/178 bothlibraries/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/178 bothlibraries/meson.build" 2023-02-01 21:59:45.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/178 bothlibraries/meson.build" 2023-05-23 15:20:09.000000000 +0000 @@ -54,7 +54,8 @@ # both_libraries the static has no sources and thus no compilers, resulting in # the executable linking using the C compiler. # https://github.com/Netflix/vmaf/issues/1107 -libccpp = both_libraries('ccpp', 'foo.cpp', 'libfile.c') +libccpp = both_libraries('ccpp', 'foo.cpp', 'libfile.c', + cpp_args : ['-std=c++11']) exe = executable('prog-ccpp', 'main2.c', link_with: libccpp.get_static_lib(), c_args : ['-DSTATIC_COMPILATION'], diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/182 find override/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/182 find override/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/182 find override/meson.build" 2023-02-01 21:59:47.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/182 find override/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -18,7 +18,7 @@ assert(tool.full_path() != '') assert(tool.full_path() == tool.path()) -# six_meson_exe is an overritten project executable +# six_meson_exe is an overridden project executable six_prog = find_program('six_meson_exe') assert(six_prog.found()) assert(six_prog.full_path() != '') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/189 check header/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/189 check header/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/189 check header/meson.build" 2023-02-01 21:59:52.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/189 check header/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -44,5 +44,5 @@ # 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.') + 'Found nonexistent header.') endforeach diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/192 feature option/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/192 feature option/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/192 feature option/meson.build" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/192 feature option/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -15,8 +15,13 @@ 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.enable_if(true, error_message: 'xyz').enabled(), 'Should be enabled option') +assert(required_opt.enable_if(false, error_message: 'xyz').enabled(), 'Should be enabled option') +assert(required_opt.disable_if(false, 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(required_opt.enable_auto_if(true).enabled(), 'Should be enabled option') +assert(required_opt.enable_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') @@ -24,8 +29,14 @@ 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.enable_if(true).enabled(), 'Should be enabled option') +assert(optional_opt.enable_if(false).auto(), 'Should be auto option') +assert(optional_opt.disable_if(true).disabled(), 'Should be disabled auto option') +assert(optional_opt.disable_if(false).auto(), 'Should be 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(optional_opt.enable_auto_if(true).enabled(), 'Should be disabled auto option') +assert(optional_opt.enable_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') @@ -33,8 +44,13 @@ 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.enable_if(false).disabled(), 'Should be disabled option') +assert(disabled_opt.disable_if(true).disabled(), 'Should be disabled option') +assert(disabled_opt.disable_if(false).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') +assert(disabled_opt.enable_auto_if(true).disabled(), 'Should be disabled option') +assert(disabled_opt.enable_auto_if(false).disabled(), 'Should be disabled option') dep = dependency('threads', required : required_opt) assert(dep.found(), 'Should find required "threads" dep') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/195 generator in subdir/com/mesonbuild/genprog.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/195 generator in subdir/com/mesonbuild/genprog.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/195 generator in subdir/com/mesonbuild/genprog.py" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/195 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(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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/195 generator in subdir/com/mesonbuild/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/195 generator in subdir/com/mesonbuild/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/195 generator in subdir/com/mesonbuild/meson.build" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/195 generator in subdir/com/mesonbuild/meson.build" 2023-04-21 10:42:56.000000000 +0000 @@ -1,4 +1,4 @@ -gprog = find_program('genprog.py') +gprog = find_program('tooldir/genprog.py') gen = generator(gprog, \ output : ['@BASENAME@.c', '@BASENAME@.h'], diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/195 generator in subdir/com/mesonbuild/tooldir/genprog.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/195 generator in subdir/com/mesonbuild/tooldir/genprog.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/195 generator in subdir/com/mesonbuild/tooldir/genprog.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/195 generator in subdir/com/mesonbuild/tooldir/genprog.py" 2023-04-21 10:42:56.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/196 subproject with features/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/196 subproject with features/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/196 subproject with features/meson.build" 2023-02-01 21:59:56.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/196 subproject with features/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -10,7 +10,7 @@ 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.') +assert(disabled_dep.found() == false, 'Subproject 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')) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/197 function attributes/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/197 function attributes/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/197 function attributes/meson.build" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/197 function attributes/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -53,6 +53,7 @@ 'sentinel', 'unused', 'used', + 'vector_size', 'warn_unused_result', 'weak', ] diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/20 global arg/prog.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/20 global arg/prog.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/20 global arg/prog.c" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/20 global arg/prog.c" 2023-05-23 15:20:02.000000000 +0000 @@ -11,7 +11,7 @@ #endif #if !defined(GLOBAL_HOST) && !defined(GLOBAL_BUILD) - #error "Neither global_host nor glogal_build is set." + #error "Neither global_host nor global_build is set." #endif #if defined(GLOBAL_HOST) && defined(GLOBAL_BUILD) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/208 link custom/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/208 link custom/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/208 link custom/meson.build" 2023-02-01 22:00:03.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/208 link custom/meson.build" 2023-04-21 10:42:56.000000000 +0000 @@ -83,4 +83,11 @@ 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 +test('custom_target_2', exe2) + +# Link with custom target containing a SONAME +dummy3 = shared_library('dummy3', 'dummy.c', version: '1.0') +t = custom_target(input: dummy, output: 'libcustom@PLAINNAME@', command: [custom_prog, '@INPUT@', '@OUTPUT@']) +lib3 = static_library('lib3', 'outerlib.c', link_with: t) +exe3 = executable('exe3', 'custom_target.c', link_with: lib3) +test('custom_target_3', exe3) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/216 custom target input extracted objects/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/216 custom target input extracted objects/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/216 custom target input extracted objects/meson.build" 2023-02-01 22:00:12.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/216 custom target input extracted objects/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -1,7 +1,7 @@ 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.') + error('MESON_SKIP_TEST: sometimes Xcode puts object files in weird paths and we cannot extract them.') endif diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/220 fs module/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/220 fs module/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/220 fs module/meson.build" 2023-02-01 22:00:13.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/220 fs module/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -120,7 +120,7 @@ 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') +assert(fs.is_samepath(f[0], f[1]), 'is_samepath not detecting same files') if not is_windows and build_machine.system() != 'cygwin' assert(fs.is_samepath(symlink, 'meson.build'), 'symlink is_samepath fail') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/222 native prop/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/222 native prop/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/222 native prop/meson.build" 2023-02-01 22:00:13.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/222 native prop/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -8,16 +8,16 @@ 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.') +assert(x==ref, 'did not get native property with native:false and non-cross build.') -x = meson.get_external_property('notexist', 'fallback') +x = meson.get_external_property('nonexistent', 'fallback') assert(x=='fallback', 'fallback did not work') -x = meson.get_external_property('notexist', 'fallback', native: true) +x = meson.get_external_property('nonexistent', 'fallback', native: true) assert(x=='fallback', 'fallback native:true did not work') -x = meson.get_external_property('notexist', 'fallback', native: false) +x = meson.get_external_property('nonexistent', 'fallback', native: false) assert(x=='fallback', 'fallback native:false did not work') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long command line/codegen.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long command line/codegen.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long command line/codegen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long command line/codegen.py" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long command line/main.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long command line/main.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long command line/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long command line/main.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +int main(void) { return 0; } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long command line/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long command line/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long command line/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long command line/meson.build" 2023-05-23 15:20:02.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 pathnames + # 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long command line/name_gen.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long command line/name_gen.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long command line/name_gen.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long command line/name_gen.py" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long commmand line/codegen.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long commmand line/codegen.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long commmand line/codegen.py" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long commmand line/codegen.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#!/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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long commmand line/main.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long commmand line/main.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long commmand line/main.c" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long commmand line/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int main(void) { return 0; } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long commmand line/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long commmand line/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long commmand line/meson.build" 2023-02-01 22:00:54.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long commmand line/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long commmand line/name_gen.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long commmand line/name_gen.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/227 very long commmand line/name_gen.py" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/227 very long commmand line/name_gen.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -#!/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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/235 invalid standard overridden to valid/main.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/235 invalid standard overridden to valid/main.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/235 invalid standard overridden to valid/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/235 invalid standard overridden to valid/main.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/235 invalid standard overridden to valid/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/235 invalid standard overridden to valid/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/235 invalid standard overridden to valid/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/235 invalid standard overridden to valid/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/235 invalid standard overridden to valid/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/235 invalid standard overridden to valid/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/235 invalid standard overridden to valid/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/235 invalid standard overridden to valid/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "matrix": { + "options": { + "c_std": [ + { "val": "c89" } + ] + } + } +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/235 invalid standard overriden to valid/main.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/235 invalid standard overriden to valid/main.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/235 invalid standard overriden to valid/main.c" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/235 invalid standard overriden to valid/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -int main(void) { - return 0; -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/235 invalid standard overriden to valid/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/235 invalid standard overriden to valid/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/235 invalid standard overriden to valid/meson.build" 2023-02-01 22:00:29.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/235 invalid standard overriden to valid/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/235 invalid standard overriden to valid/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/235 invalid standard overriden to valid/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/235 invalid standard overriden to valid/test.json" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/235 invalid standard overriden to valid/test.json" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -{ - "matrix": { - "options": { - "c_std": [ - { "val": "c89" } - ] - } - } -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/239 includedir violation/subprojects/sub/include/placeholder.h" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/239 includedir violation/subprojects/sub/include/placeholder.h" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/239 includedir violation/subprojects/sub/include/placeholder.h" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/239 includedir violation/subprojects/sub/include/placeholder.h" 2023-05-30 15:42:56.000000000 +0000 @@ -1,3 +1,3 @@ #pragma once -// Git can not handle empty directories, so there must be something here. +// Git cannot handle empty directories, so there must be something here. diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/245 custom target index source/main.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/245 custom target index source/main.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/245 custom target index source/main.c" 2021-12-26 16:24:25.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/245 custom target index source/main.c" 2023-04-21 10:42:56.000000000 +0000 @@ -1,8 +1,10 @@ #include #include "gen.h" -int main(int argc) +int main(int argc, char **argv) { + (void)argv; + assert(argc == 3); return genfunc(); } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/247 deprecated option/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/247 deprecated option/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/247 deprecated option/meson_options.txt" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/247 deprecated option/meson_options.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -16,7 +16,7 @@ # A boolean option has been replaced by a feature with another name, old true/false values # are accepted by the new option for backward compatibility. -option('o6', type: 'boolean', value: 'true', deprecated: 'o7') +option('o6', type: 'boolean', value: true, deprecated: 'o7') option('o7', type: 'feature', value: 'enabled', deprecated: {'true': 'enabled', 'false': 'disabled'}) # A project option is replaced by a module option diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/252 install data structured/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/252 install data structured/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/252 install data structured/meson.build" 2023-02-01 22:00:46.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/252 install data structured/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -1,4 +1,4 @@ -project('install structured data') +project('install structured data', default_options: ['python.bytecompile=-1']) install_data( 'dir1/file1', diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/254 long output/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/254 long output/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/254 long output/meson.build" 2023-02-01 22:00:49.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/254 long output/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,5 +1,5 @@ project('long-stderr', 'c') dumper = executable('dumper', 'dumper.c') -test('dump-test', dumper) -test('dump-test-TAP', dumper, protocol : 'tap') +test('dump-test', dumper, timeout: 60) +test('dump-test-TAP', dumper, protocol : 'tap', timeout: 60) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/257 generated header dep/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/257 generated header dep/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/257 generated header dep/meson.build" 2023-02-01 22:00:54.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/257 generated header dep/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -8,7 +8,7 @@ # dependency on the header file. This happened in GLib: # https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2917. -python = import('python').find_installation() +python = find_program('python3') header = custom_target( output: 'foo.h', capture: true, diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/259 preprocess/bar.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/259 preprocess/bar.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/259 preprocess/bar.c" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/259 preprocess/bar.c" 2023-05-23 15:20:02.000000000 +0000 @@ -1,3 +1,3 @@ -int bar(void) { - return BAR; +int @BAR@(void) { + return BAR + PLOP; } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/259 preprocess/math.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/259 preprocess/math.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/259 preprocess/math.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/259 preprocess/math.c" 2023-07-05 15:40:06.000000000 +0000 @@ -0,0 +1,3 @@ +// Verify we preprocess as C language, otherwise including math.h would fail. +// See https://github.com/mesonbuild/meson/issues/11940. +#include diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/259 preprocess/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/259 preprocess/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/259 preprocess/meson.build" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/259 preprocess/meson.build" 2023-07-05 15:40:06.000000000 +0000 @@ -4,7 +4,18 @@ add_project_arguments(['-DFOO=0', '-DBAR=0'], language: 'c') -pp_files = cc.preprocess('foo.c', 'bar.c', output: '@PLAINNAME@') +fs = import('fs') +bar_content = fs.read('bar.c') +bar_x = custom_target( + input: 'bar.c', + output: 'bar.x', + command: ['python3', '-c', '''import sys;print(sys.argv[1].replace('@BAR@', 'bar'))''', bar_content], + capture: true, +) + +dep = declare_dependency(compile_args: '-DPLOP=0') + +pp_files = cc.preprocess('foo.c', bar_x, 'math.c', output: '@PLAINNAME@.c', dependencies: dep) foreach f : pp_files message(f.full_path()) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/26 find program/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/26 find program/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/26 find program/meson.build" 2023-02-01 21:58:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/26 find program/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -35,5 +35,5 @@ 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']) +prog = find_program('test_subdir.py', dirs : ['/nonexistent', meson.current_source_dir() / 'scripts']) assert(prog.found(), 'Program should be found') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/260 declare_dependency objects/bar.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/260 declare_dependency objects/bar.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/260 declare_dependency objects/bar.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/260 declare_dependency objects/bar.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +void bar(void) {} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/260 declare_dependency objects/foo.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/260 declare_dependency objects/foo.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/260 declare_dependency objects/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/260 declare_dependency objects/foo.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +extern void bar(void); + +void foo(void) { bar(); } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/260 declare_dependency objects/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/260 declare_dependency objects/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/260 declare_dependency objects/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/260 declare_dependency objects/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,23 @@ +# Test that declare_dependency(objects: ...) fixes issues with duplicated +# objects in the final link line, thanks to deduplication of dependencies. +# The commented declare_dependency() invocation using link_whole instead +# fails thusly: +# +# ar csrDT libbar.a libfoo.a.p/foo.c.o libbar.a.p/bar.c.o +# ar csrDT libfoo.a libfoo.a.p/foo.c.o +# cc -o prog prog.p/prog.c.o -Wl,--as-needed -Wl,--no-undefined -Wl,--whole-archive -Wl,--start-group libfoo.a libbar.a -Wl,--end-group -Wl,--no-whole-archive +# /usr/bin/ld: libfoo.a.p/foo.c.o: in function `foo': +# ../foo.c:3: multiple definition of `foo'; libfoo.a.p/foo.c.o:../foo.c:3: first defined here + +project('Transitive declare_dependency(objects)', 'c') + +libfoo = static_library('foo', 'foo.c') +#foo = declare_dependency(link_whole: libfoo) +foo = declare_dependency(objects: libfoo.extract_all_objects(recursive: true)) + +libbar = static_library('bar', 'bar.c', dependencies: foo) + +#bar = declare_dependency(link_whole: libbar, dependencies: foo) +bar = declare_dependency(objects: libbar.extract_all_objects(recursive: true), dependencies: foo) + +executable('prog', sources: files('prog.c'), dependencies: [foo, bar]) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/260 declare_dependency objects/prog.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/260 declare_dependency objects/prog.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/260 declare_dependency objects/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/260 declare_dependency objects/prog.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +extern void foo(void); + +int main(void) { foo(); } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/261 testcase clause/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/261 testcase clause/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/261 testcase clause/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/261 testcase clause/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,37 @@ +project('testcase clause') + +# To make sure unreachable code is not executed. +unreachable = true + +# Verify assertion exception gets catched and dropped. +testcase expect_error('Assert failed: false') + assert(false) + unreachable = false +endtestcase +assert(unreachable) + +# The inner testcase raises an exception because it did not receive the expected +# error message. The outer testcase catches the inner testcase exception and +# drop it. +testcase expect_error('Expecting error \'something\' but got \'Assert failed: false\'') + testcase expect_error('something') + assert(false) + unreachable = false + endtestcase + unreachable = false +endtestcase +assert(unreachable) + +# The inner testcase raises an exception because it did not receive an +# exception. The outer testcase catches the inner testcase exception and +# drop it. +testcase expect_error('Expecting an error but code block succeeded') + testcase expect_error('something') + reached = true + endtestcase + unreachable = false +endtestcase +assert(reached) +assert(unreachable) + +message('all good') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/261 testcase clause/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/261 testcase clause/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/261 testcase clause/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/261 testcase clause/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "stdout": [ + { + "line": ".*all good", + "match": "re", + "count": 1 + } + ] +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/262 generator chain/data.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/262 generator chain/data.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/262 generator chain/data.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/262 generator chain/data.txt" 2023-05-30 15:42:56.000000000 +0000 @@ -0,0 +1 @@ +stage1 diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/262 generator chain/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/262 generator chain/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/262 generator chain/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/262 generator chain/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -0,0 +1,19 @@ +project('Generator Chain', 'c') + +stage1_exe = find_program('stage1.py') + +stage2_exe = find_program('stage2.py') + +stage1_gen = generator(stage1_exe, + output : '@PLAINNAME@.inter', + arguments : ['@INPUT@', '@OUTPUT@']) + +stage2_gen = generator(stage2_exe, + output : '@PLAINNAME@.c', + arguments : ['@INPUT@', '@OUTPUT@']) + +out = stage2_gen.process(stage1_gen.process('data.txt')) + +hello = executable('hello', out) + +test('basic', hello) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/262 generator chain/stage1.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/262 generator chain/stage1.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/262 generator chain/stage1.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/262 generator chain/stage1.py" 2023-05-30 15:42:56.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 +import sys +from pathlib import Path + +assert(Path(sys.argv[1]).read_text() == 'stage1\n') +Path(sys.argv[2]).write_text('stage2\n') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/262 generator chain/stage2.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/262 generator chain/stage2.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/262 generator chain/stage2.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/262 generator chain/stage2.py" 2023-05-30 15:42:56.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 +import sys +from pathlib import Path + +assert(Path(sys.argv[1]).read_text() == 'stage2\n') +Path(sys.argv[2]).write_text('int main(void){}\n') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/263 default_options dict/lib.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/263 default_options dict/lib.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/263 default_options dict/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/263 default_options dict/lib.c" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1 @@ +#warning Make sure this is not fatal diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/263 default_options dict/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/263 default_options dict/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/263 default_options dict/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/263 default_options dict/meson.build" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,22 @@ +project('test default options', 'c', + default_options: { + 'bool': true, + 'int': 42, + 'str': 'foo', + 'array': ['foo'], + 'werror': true, + }, +) + +assert(get_option('bool') == true) +assert(get_option('int') == 42) +assert(get_option('str') == 'foo') +assert(get_option('array') == ['foo']) +assert(get_option('werror') == true) + +cc = meson.get_compiler('c') + +# MSVC does not support #warning +if cc.get_id() != 'msvc' + static_library('foo', 'lib.c', override_options: {'werror': false}) +endif diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/263 default_options dict/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/263 default_options dict/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/263 default_options dict/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/263 default_options dict/meson_options.txt" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,4 @@ +option('bool', type: 'boolean', value: false) +option('int', type: 'integer', value: 0) +option('str', type: 'string', value: 'bar') +option('array', type: 'array', value: ['bar']) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/27 multiline string/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/27 multiline string/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/27 multiline string/meson.build" 2023-02-01 21:58:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/27 multiline string/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -34,4 +34,4 @@ return 0; }''' -assert(cc.compiles(prog), 'multline test compile failed') +assert(cc.compiles(prog), 'multiline test compile failed') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/28 try compile/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/28 try compile/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/28 try compile/meson.build" 2023-02-01 21:58:08.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/28 try compile/meson.build" 2023-08-07 22:54:34.000000000 +0000 @@ -8,20 +8,27 @@ 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 +foreach lang : ['c', 'cpp'] + compiler = meson.get_compiler(lang) + + if compiler.compiles(code, name : 'code should succeed') == false + error('Compiler ' + compiler.get_id() + ' is fail.') + endif + + if compiler.compiles(files('valid.c'), name : 'file should succeed') == false error('Compiler ' + compiler.get_id() + ' is fail.') endif - if compiler.compiles(files('valid.c'), name : 'should succeed') == false + copied = configure_file(input: 'valid.c', output: lang + '-valid-copy.c', copy: true) + if compiler.compiles(copied, name : 'built file should succeed') == false error('Compiler ' + compiler.get_id() + ' is fail.') endif - if compiler.compiles(breakcode, name : 'should fail') + if compiler.compiles(breakcode, name : 'code should fail') error('Compiler ' + compiler.get_id() + ' returned true on broken code.') endif - if compiler.compiles(files('invalid.c'), name : 'should fail') + if compiler.compiles(files('invalid.c'), name : 'file should fail') error('Compiler ' + compiler.get_id() + ' returned true on broken code.') endif endforeach diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/32 has header/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/32 has header/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/32 has header/meson.build" 2023-02-01 21:58:10.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/32 has header/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -49,6 +49,6 @@ # 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.') + 'Found nonexistent header.') endforeach endforeach diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/33 run program/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/33 run program/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/33 run program/meson.build" 2023-02-01 21:58:11.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/33 run program/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,4 +1,4 @@ -project('run command', version : run_command('get-version.py', check : true).stdout().strip()) +project('run command', version : run_command('get-version.py', check : true).stdout().strip(), meson_version: '>=0.1.0') if build_machine.system() == 'windows' c = run_command('cmd', '/c', 'echo', 'hello', check: false) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/33 run program/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/33 run program/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/33 run program/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/33 run program/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "line": "test cases/common/33 run program/meson.build:1: WARNING: Project targets '>=0.1.0' but uses feature introduced in '0.47.0': check arg in run_command.", + "comment": "This triggers on line 1 -- the line with the project() function" + } + ] +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/35 string operations/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/35 string operations/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/35 string operations/meson.build" 2023-02-01 21:58:12.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/35 string operations/meson.build" 2023-06-28 14:48:20.000000000 +0000 @@ -125,3 +125,15 @@ 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') + +# str.splitlines() +assert('foo\nbar\nbaz'.splitlines() == ['foo', 'bar', 'baz'], 'splitlines is broken') +assert(''.splitlines() == [], 'splitlines with empty string is broken') +assert('foo\rbar\nbaz\n'.splitlines() == ['foo', 'bar', 'baz'], 'splitlines trailing newline is broken') +assert('hello\r\nworld'.splitlines() == ['hello', 'world']) +assert( + ' leading ws\nand trailing\t'.splitlines() == [' leading ws', 'and trailing\t'], + 'splitlines leading/trailing whitespace is broken', +) +assert('\n\r\n\r'.splitlines() == ['', '', ''], 'splitlines is broken') +assert('foo'.splitlines() == ['foo'], 'splitlines is broken') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/36 has function/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/36 has function/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/36 has function/meson.build" 2023-02-01 21:58:15.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/36 has function/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -37,11 +37,11 @@ if cc.has_function('hfkerhisadf', prefix : '#include', args : unit_test_args) - error('Found non-existent function "hfkerhisadf".') + error('Found nonexistent function "hfkerhisadf".') endif if cc.has_function('hfkerhisadf', args : unit_test_args) - error('Found non-existent function "hfkerhisadf".') + error('Found nonexistent function "hfkerhisadf".') endif # With glibc (before 2.32, see below) on Linux, lchmod is a stub that will diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/40 options/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/40 options/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/40 options/meson.build" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/40 options/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,4 +1,4 @@ -project('options', 'c') +project('options', 'c', meson_version : '>= 1.0.0') if get_option('testoption') != 'optval' error('Incorrect value to test option') @@ -43,3 +43,6 @@ endif assert(get_option('wrap_mode') == 'default', 'Wrap mode option is broken.') +assert(get_option('boolean_string') == false) +assert(get_option('boolean_string2') == true) +assert(get_option('integer_string') == 42) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/40 options/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/40 options/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/40 options/meson_options.txt" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/40 options/meson_options.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -5,5 +5,9 @@ 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: 'Some CAPS', description : 'An option with mixed capitalization') option('CASESENSITIVE', type : 'string', value: 'ALL CAPS', description : 'An option with all caps') + +option('boolean_string', type : 'boolean', value : 'false') +option('boolean_string2', type : 'boolean', value : 'true') +option('integer_string', type : 'integer', value : '42') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/40 options/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/40 options/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/40 options/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/40 options/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": " * 1.1.0: {'\"boolean option\" keyword argument \"value\" of type str', '\"integer option\" keyword argument \"value\" of type str'}" + } + ] +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/42 subproject/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/42 subproject/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/42 subproject/meson.build" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/42 subproject/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,6 +1,8 @@ project('subproj user', 'c', version : '2.3.4', - license : 'mylicense') + license : 'mylicense', + license_files: 'mylicense.txt', +) assert(meson.project_name() == 'subproj user', 'Incorrect project name') @@ -24,5 +26,5 @@ unknown_var = sub.get_variable('does-not-exist', []) if unknown_var != [] - error ('unexpetced fallback value for subproject.get_variable()') + error ('unexpected fallback value for subproject.get_variable()') endif diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/42 subproject/subprojects/sublib/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/42 subproject/subprojects/sublib/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/42 subproject/subprojects/sublib/meson.build" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/42 subproject/subprojects/sublib/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,6 +1,8 @@ project('subproject', 'c', version : '1.0.0', - license : ['sublicense1', 'sublicense2']) + license : ['sublicense1', 'sublicense2'], + license_files: ['sublicense1.txt', 'sublicense2.txt'], +) if not meson.is_subproject() error('Claimed to be master project even though we are a subproject.') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/42 subproject/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/42 subproject/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/42 subproject/test.json" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/42 subproject/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -2,6 +2,9 @@ "installed": [ {"type": "exe", "file": "usr/bin/user"}, {"type": "pdb", "file": "usr/bin/user"}, - {"type": "file", "file": "usr/share/sublib/sublib.depmf"} + {"type": "file", "file": "usr/share/sublib/sublib.depmf"}, + {"type": "file", "file": "usr/share/sublib/mylicense.txt"}, + {"type": "file", "file": "usr/share/sublib/subprojects/sublib/sublicense1.txt"}, + {"type": "file", "file": "usr/share/sublib/subprojects/sublib/sublicense2.txt"} ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/44 pkgconfig-gen/dependencies/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/44 pkgconfig-gen/dependencies/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/44 pkgconfig-gen/dependencies/meson.build" 2022-10-24 19:25:13.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/44 pkgconfig-gen/dependencies/meson.build" 2023-06-28 14:48:20.000000000 +0000 @@ -60,3 +60,11 @@ libraries : internal_lib, filebase : 'pub-lib-order', ) + +# This will be built against both simple7.pc and simple7-uninstalled.pc, check +# that include directories works in both cases. +simple7 = dependency('simple7') +exe = executable('test2', 'test2.c', + dependencies: simple7, +) +test('Test2', exe) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/44 pkgconfig-gen/dependencies/test2.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/44 pkgconfig-gen/dependencies/test2.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/44 pkgconfig-gen/dependencies/test2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/44 pkgconfig-gen/dependencies/test2.c" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,8 @@ +#include +#include + +int main(void) { + if (INC1 + INC2 != 3) + return 1; + return 0; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/44 pkgconfig-gen/inc1/inc1.h" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/44 pkgconfig-gen/inc1/inc1.h" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/44 pkgconfig-gen/inc1/inc1.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/44 pkgconfig-gen/inc1/inc1.h" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1 @@ +#define INC1 1 diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/44 pkgconfig-gen/inc2/inc2.h" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/44 pkgconfig-gen/inc2/inc2.h" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/44 pkgconfig-gen/inc2/inc2.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/44 pkgconfig-gen/inc2/inc2.h" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1 @@ +#define INC2 2 diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/44 pkgconfig-gen/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/44 pkgconfig-gen/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/44 pkgconfig-gen/meson.build" 2023-02-01 21:58:18.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/44 pkgconfig-gen/meson.build" 2023-08-07 22:54:24.000000000 +0000 @@ -8,7 +8,7 @@ endif # First check we have pkg-config >= 0.29 -pkgconfig = find_program('pkg-config', required: false) +pkgconfig = find_program('pkg-config', native: true, required: false) if not pkgconfig.found() error('MESON_SKIP_TEST: pkg-config not found') endif @@ -18,7 +18,7 @@ error('MESON_SKIP_TEST: pkg-config version \'' + v + '\' too old') endif -python = import('python').find_installation() +python = find_program('python3') fs = import('fs') pkgg = import('pkgconfig') @@ -176,3 +176,20 @@ description : 'Check that variables can be single string', variables: 'foo=bar', ) + +# without a mainlib, name/description are mandatory +testcase expect_error('pkgconfig.generate: if a library is not passed as a positional argument, the \'name\' keyword argument is required.') + pkgg.generate(description: 'empty data') +endtestcase + +testcase expect_error('pkgconfig.generate: if a library is not passed as a positional argument, the \'description\' keyword argument is required.') + pkgg.generate(name: 'foobar') +endtestcase + +# Make sure the -uninstalled.pc file contains both include directories. +# See dependencies/test2.c that gets built against both simple7.pc and +# simple7-uninstalled.pc. +simple7 = library('simple7', include_directories: 'inc1') +dep = declare_dependency(include_directories: 'inc2') +install_headers('inc1/inc1.h', 'inc2/inc2.h') +pkgg.generate(simple7, libraries: dep) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/44 pkgconfig-gen/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/44 pkgconfig-gen/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/44 pkgconfig-gen/test.json" 2022-10-02 21:19:36.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/44 pkgconfig-gen/test.json" 2023-06-28 14:48:20.000000000 +0000 @@ -1,6 +1,8 @@ { "installed": [ {"type": "file", "file": "usr/include/simple.h"}, + {"type": "file", "file": "usr/include/inc1.h"}, + {"type": "file", "file": "usr/include/inc2.h"}, {"type": "file", "file": "usr/lib/libstat2.a"}, {"type": "file", "file": "usr/lib/pkgconfig/simple.pc"}, {"type": "file", "file": "usr/lib/pkgconfig/libanswer.pc"}, @@ -13,13 +15,14 @@ {"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/simple7.pc"}, {"type": "file", "file": "usr/lib/pkgconfig/ct.pc"}, {"type": "file", "file": "usr/lib/pkgconfig/ct0.pc"}, {"type": "file", "file": "usr/share/pkgconfig/libhello_nolib.pc"} ], "stdout": [ { - "line": "test cases/common/44 pkgconfig-gen/meson.build:164: WARNING: Project targets '>=0.60.0' but uses feature introduced in '0.62.0': pkgconfig.generate implicit variable for builtin directories." + "line": "test cases/common/44 pkgconfig-gen/meson.build:160: WARNING: Project targets '>=0.60.0' but uses feature introduced in '0.62.0': pkgconfig.generate implicit variable for builtin directories." }, { "line": "test cases/common/44 pkgconfig-gen/meson.build:170: WARNING: Project targets '>=0.60.0' but uses feature introduced in '0.62.0': pkgconfig.generate implicit variable for builtin directories.", diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/51 run target/helloprinter.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/51 run target/helloprinter.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/51 run target/helloprinter.c" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/51 run target/helloprinter.c" 2023-05-30 15:42:56.000000000 +0000 @@ -2,7 +2,7 @@ int main(int argc, char **argv) { if(argc != 2) { - printf("I can not haz argument.\n"); + printf("I cannot haz argument.\n"); return 1; } else { printf("I can haz argument: %s\n", argv[1]); diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/53 install script/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/53 install script/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/53 install script/meson.build" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/53 install script/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,6 +1,6 @@ project('custom install script', 'c') -meson.add_install_script('myinstall.py', 'diiba/daaba', 'file.dat') +meson.add_install_script('myinstall.py', 'diiba/daaba', 'file.dat', dry_run: true) meson.add_install_script('myinstall.py', 'this/should', 'also-work.dat') subdir('src') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/53 install script/myinstall.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/53 install script/myinstall.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/53 install script/myinstall.py" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/53 install script/myinstall.py" 2023-05-23 15:20:02.000000000 +0000 @@ -5,6 +5,7 @@ import shutil prefix = os.environ['MESON_INSTALL_DESTDIR_PREFIX'] +dry_run = bool(os.environ.get('MESON_INSTALL_DRY_RUN')) def main() -> None: @@ -16,15 +17,24 @@ dirname = os.path.join(prefix, args.dirname) if not os.path.exists(dirname): - os.makedirs(dirname) + if dry_run: + print(f"DRYRUN: Creating directory {dirname}") + else: + os.makedirs(dirname) if args.mode == 'create': for name in args.files: - with open(os.path.join(dirname, name), 'w') as f: - f.write('') + if dry_run: + print(f'DRYRUN: Writing file {name}') + else: + with open(os.path.join(dirname, name), 'w') as f: + f.write('') else: for name in args.files: - shutil.copy(name, dirname) + if dry_run: + print(f"DRYRUN: Copying file {name} to {dirname}") + else: + shutil.copy(name, dirname) if __name__ == "__main__": diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/56 array methods/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/56 array methods/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/56 array methods/meson.build" 2023-02-01 21:58:24.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/56 array methods/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -18,7 +18,7 @@ endif if file_list.contains(file_c[0]) - error('Contains with ObjectHolder lists found non existent object') + error('Contains with ObjectHolder lists found nonexistent object') endif if empty.contains('abc') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/59 install subdir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/59 install subdir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/59 install subdir/meson.build" 2023-02-01 21:58:25.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/59 install subdir/meson.build" 2023-04-21 10:42:56.000000000 +0000 @@ -7,6 +7,12 @@ exclude_directories : ['excluded'], install_dir : 'share') +# More exclusions +install_subdir('sub3', + exclude_files : ['data/excluded.txt'], + exclude_directories : ['data/excluded'], + install_dir : 'share') + subdir('subdir') # A subdir with write perms only for the owner # and read-list perms for owner and group diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/59 install subdir/sub3/data/data.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/59 install subdir/sub3/data/data.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/59 install subdir/sub3/data/data.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/59 install subdir/sub3/data/data.txt" 2023-04-21 10:42:56.000000000 +0000 @@ -0,0 +1 @@ +data diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/59 install subdir/sub3/data/excluded/excluded.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/59 install subdir/sub3/data/excluded/excluded.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/59 install subdir/sub3/data/excluded/excluded.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/59 install subdir/sub3/data/excluded/excluded.txt" 2023-04-21 10:42:56.000000000 +0000 @@ -0,0 +1 @@ +excluded diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/59 install subdir/sub3/data/excluded.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/59 install subdir/sub3/data/excluded.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/59 install subdir/sub3/data/excluded.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/59 install subdir/sub3/data/excluded.txt" 2023-04-21 10:42:56.000000000 +0000 @@ -0,0 +1 @@ +excluded diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/59 install subdir/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/59 install subdir/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/59 install subdir/test.json" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/59 install subdir/test.json" 2023-04-21 10:42:56.000000000 +0000 @@ -12,6 +12,7 @@ {"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": "file", "file": "usr/share/sub3/data/data.txt"}, {"type": "dir", "file": "usr/share/new_directory"} ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/94 threads/threadprog.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/94 threads/threadprog.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/94 threads/threadprog.c" 2023-02-01 21:43:18.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/94 threads/threadprog.c" 2023-04-21 10:42:56.000000000 +0000 @@ -3,7 +3,7 @@ #include #include -DWORD WINAPI thread_func(void) { +DWORD WINAPI thread_func(void *arg) { printf("Printing from a thread.\n"); return 0; } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/98 subproject subdir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/98 subproject subdir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/98 subproject subdir/meson.build" 2023-02-01 21:58:49.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/98 subproject subdir/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -27,7 +27,7 @@ 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') +d = dependency('sub_implicit', default_options: 'opt=overridden') assert(d.found(), 'Should implicitly fallback') # Verify that implicit fallback works because sub_implicit.wrap has diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build" 2021-10-11 16:26:46.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -10,4 +10,4 @@ # 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 +assert(get_option('opt') == 'overridden') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/98 subproject subdir/subprojects/subsubsub-1.0/.meson-subproject-wrap-hash.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/98 subproject subdir/subprojects/subsubsub-1.0/.meson-subproject-wrap-hash.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/98 subproject subdir/subprojects/subsubsub-1.0/.meson-subproject-wrap-hash.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/98 subproject subdir/subprojects/subsubsub-1.0/.meson-subproject-wrap-hash.txt" 2023-07-21 20:12:17.000000000 +0000 @@ -0,0 +1 @@ +0fd8007dd44a1a5eb5c01af4c138f0993c6cb44da194b36db04484212eff591b diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/98 subproject subdir/subprojects/subsubsub-1.0/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/98 subproject subdir/subprojects/subsubsub-1.0/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/98 subproject subdir/subprojects/subsubsub-1.0/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/98 subproject subdir/subprojects/subsubsub-1.0/meson.build" 2023-07-21 20:12:17.000000000 +0000 @@ -0,0 +1,3 @@ +project('subsubsub') + +meson.override_dependency('subsubsub', declare_dependency()) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/98 subproject subdir/subprojects/subsubsub.wrap" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/98 subproject subdir/subprojects/subsubsub.wrap" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/98 subproject subdir/subprojects/subsubsub.wrap" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/98 subproject subdir/subprojects/subsubsub.wrap" 2023-07-21 20:14:40.000000000 +0000 @@ -0,0 +1,2 @@ +[wrap-redirect] +filename = sub_implicit/subprojects/subsub/subprojects/subsubsub.wrap diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/99 postconf/postconf.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/99 postconf/postconf.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/common/99 postconf/postconf.py" 2021-04-27 06:50:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/common/99 postconf/postconf.py" 2023-07-21 20:36:13.000000000 +0000 @@ -10,7 +10,7 @@ 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: +with open(input_file, encoding='utf-8') as f: data = f.readline().strip() -with open(output_file, 'w') as f: +with open(output_file, 'w', encoding='utf-8') as f: f.write(template.format(data)) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cython/1 basic/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cython/1 basic/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cython/1 basic/meson.build" 2021-08-18 11:22:15.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cython/1 basic/meson.build" 2023-05-23 15:20:09.000000000 +0000 @@ -1,11 +1,14 @@ project( 'basic cython project', ['cython', 'c'], - default_options : ['warning_level=3'] + default_options : ['warning_level=3', 'buildtype=release'], ) -py_mod = import('python') -py3 = py_mod.find_installation() +if meson.backend() != 'ninja' + error('MESON_SKIP_TEST: Ninja backend required') +endif + +py3 = import('python').find_installation() py3_dep = py3.dependency(required : false) if not py3_dep.found() error('MESON_SKIP_TEST: Python library not found.') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cython/2 generated sources/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cython/2 generated sources/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cython/2 generated sources/meson.build" 2023-02-20 12:58:43.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cython/2 generated sources/meson.build" 2023-05-23 15:20:09.000000000 +0000 @@ -1,12 +1,16 @@ project( 'generated cython sources', - ['cython'], + ['cython', 'c'], + default_options : ['buildtype=release'], ) -py_mod = import('python') -py3 = py_mod.find_installation('python3') -py3_dep = py3.dependency(required : false) +if meson.backend() != 'ninja' + error('MESON_SKIP_TEST: Ninja backend required') +endif + fs = import('fs') +py3 = import('python').find_installation('python3') +py3_dep = py3.dependency(required : false) if not py3_dep.found() error('MESON_SKIP_TEST: Python library not found.') endif @@ -18,7 +22,7 @@ command : [py3, '@INPUT@', '@OUTPUT@'], ) -ct_ext = py3.extension_module('ct', ct, dependencies : py3_dep) +ct_ext = py3.extension_module('ct', ct) test( 'custom target', @@ -35,7 +39,7 @@ command : [py3, '@INPUT@', '@OUTPUT@'], ) -cti_ext = py3.extension_module('cti', cti[0], dependencies : py3_dep) +cti_ext = py3.extension_module('cti', cti[0]) cf = configure_file( input : 'configure.pyx.in', @@ -43,7 +47,7 @@ copy : true, ) -cf_ext = py3.extension_module('cf', cf, dependencies : py3_dep) +cf_ext = py3.extension_module('cf', cf) test( 'configure file', @@ -61,7 +65,6 @@ g_ext = py3.extension_module( 'g', gen.process('g.in'), - dependencies : py3_dep, ) test( diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cython/3 cython_args/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cython/3 cython_args/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/cython/3 cython_args/meson.build" 2022-03-25 20:12:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/cython/3 cython_args/meson.build" 2023-05-23 15:20:09.000000000 +0000 @@ -1,7 +1,14 @@ -project('cython_args', ['cython', 'c']) +project('cython_args', ['cython', 'c'], + # Needed because Windows Python builds are release-only and tend to be + # unhappy with a debug build type. + default_options : ['buildtype=release'] +) + +if meson.backend() != 'ninja' + error('MESON_SKIP_TEST: Ninja backend required') +endif -pymod = import('python') -python = pymod.find_installation('python3') +python = import('python').find_installation('python3') python_dep = python.dependency() if not python_dep.found() error('MESON_SKIP_TEST: Python library not found.') @@ -12,9 +19,9 @@ files('cythonargs.pyx'), cython_args: [ '--compile-time-env', - 'VALUE=1' + 'VALUE=1', + '-3', ], - dependencies: [python_dep] ) test( diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/11 dub/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/11 dub/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/11 dub/meson.build" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/11 dub/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -1,5 +1,7 @@ project('dub-example', 'd') +error('MESON_SKIP_TEST: Dub support is broken at the moment (#11773)') + dub_exe = find_program('dub', required : false) if not dub_exe.found() error('MESON_SKIP_TEST: Dub not found') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/13 declare dep/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/13 declare dep/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/13 declare dep/meson.build" 2023-02-01 22:03:50.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/13 declare dep/meson.build" 2023-07-21 20:36:13.000000000 +0000 @@ -3,7 +3,7 @@ ) my_dep = declare_dependency( - d_module_versions: ['TestVersion', 1], + d_module_versions: ['TestVersion'], d_import_dirs: include_directories('views'), ) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/14 dub with deps/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/14 dub with deps/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/14 dub with deps/meson.build" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/14 dub with deps/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -1,5 +1,7 @@ project('dub-with-deps-example', ['d']) +error('MESON_SKIP_TEST: Dub support is broken at the moment (#11773)') + dub_exe = find_program('dub', required : false) if not dub_exe.found() error('MESON_SKIP_TEST: Dub not found') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/3 shared library/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/3 shared library/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/3 shared library/meson.build" 2023-02-01 22:03:17.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/3 shared library/meson.build" 2023-07-16 14:56:29.000000000 +0000 @@ -3,7 +3,7 @@ dc = meson.get_compiler('d') if dc.get_id() == 'gcc' if dc.version().version_compare('< 8') - error('MESON_SKIP_TEST: GDC < 8.0 can not build shared libraries') + error('MESON_SKIP_TEST: GDC < 8.0 cannot build shared libraries') endif endif diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/4 library versions/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/4 library versions/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/4 library versions/meson.build" 2023-02-01 22:03:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/4 library versions/meson.build" 2023-07-16 14:56:28.000000000 +0000 @@ -3,7 +3,7 @@ dc = meson.get_compiler('d') if dc.get_id() == 'gcc' if dc.version().version_compare('< 8') - error('MESON_SKIP_TEST: GDC < 8.0 can not build shared libraries') + error('MESON_SKIP_TEST: GDC < 8.0 cannot build shared libraries') endif endif diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/7 multilib/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/7 multilib/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/7 multilib/meson.build" 2023-02-01 22:03:41.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/7 multilib/meson.build" 2023-07-16 14:56:40.000000000 +0000 @@ -3,7 +3,7 @@ dc = meson.get_compiler('d') if dc.get_id() == 'gcc' if dc.version().version_compare('< 8') - error('MESON_SKIP_TEST: GDC < 8.0 can not build shared libraries') + error('MESON_SKIP_TEST: GDC < 8.0 cannot build shared libraries') endif endif diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/9 features/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/9 features/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/d/9 features/meson.build" 2023-02-01 22:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/d/9 features/meson.build" 2023-07-21 20:36:13.000000000 +0000 @@ -1,5 +1,16 @@ project('D Features', 'd', default_options : ['debug=false']) +dc = meson.get_compiler('d') + +# GDC 13 hard errors if options are given number values. +# https://github.com/mesonbuild/meson/pull/11996 + +if dc.get_id() == 'gcc' and dc.version().version_compare('>=13') + number_options_supported = false +else + number_options_supported = true +endif + # ONLY FOR BACKWARDS COMPATIBILITY. # DO NOT DO THIS IN NEW CODE! # USE include_directories() INSTEAD OF BUILDING @@ -46,12 +57,13 @@ test('dapp_test', e_test) # test version level -e_version_int = executable('dapp_version_int', - test_src, - d_import_dirs: [data_dir], - d_module_versions: ['With_VersionInteger', 3], -) -test('dapp_version_int_t', e_version_int, args: ['debug']) +if number_options_supported + e_version_int = executable('dapp_version_int', + test_src, + d_import_dirs: [data_dir], + d_module_versions: ['With_VersionInteger', 3], + ) + test('dapp_version_int_t', e_version_int, args: ['debug']) # test version level failure e_version_int_fail = executable('dapp_version_int_fail', @@ -60,6 +72,7 @@ d_module_versions: ['With_VersionInteger', 2], ) test('dapp_version_int_t_fail', e_version_int_fail, args: ['debug'], should_fail: true) +endif # test debug conditions: disabled e_no_debug = executable('dapp_no_debug', @@ -69,23 +82,34 @@ ) test('dapp_no_debug_t_fail', e_no_debug, args: ['debug'], should_fail: true) -# test debug conditions: enabled -e_debug = executable('dapp_debug', - test_src, - d_import_dirs: [data_dir], - d_module_versions: ['With_Debug'], - d_debug: 1, -) -test('dapp_debug_t', e_debug, args: ['debug']) - -# test debug conditions: integer -e_debug_int = executable('dapp_debug_int', - test_src, - d_import_dirs: [data_dir], - d_module_versions: ['With_DebugInteger'], - d_debug: 3, -) -test('dapp_debug_int_t', e_debug_int, args: ['debug']) +if number_options_supported + # test debug conditions: enabled + e_debug = executable('dapp_debug', + test_src, + d_import_dirs: [data_dir], + d_module_versions: ['With_Debug'], + d_debug: 1, + ) + test('dapp_debug_t', e_debug, args: ['debug']) + + # test debug conditions: integer + e_debug_int = executable('dapp_debug_int', + test_src, + d_import_dirs: [data_dir], + d_module_versions: ['With_DebugInteger'], + d_debug: 3, + ) + test('dapp_debug_int_t', e_debug_int, args: ['debug']) + + # test with all debug conditions at once, and with redundant values + e_debug_all = executable('dapp_debug_all', + test_src, + d_import_dirs: [data_dir], + d_module_versions: ['With_DebugAll'], + d_debug: ['4', 'DebugIdentifier', 2, 'DebugIdentifierUnused'], + ) + test('dapp_debug_all_t', e_debug_all, args: ['debug']) +endif # test debug conditions: identifier e_debug_ident = executable('dapp_debug_ident', @@ -95,12 +119,3 @@ d_debug: 'DebugIdentifier', ) test('dapp_debug_ident_t', e_debug_ident, args: ['debug']) - -# test with all debug conditions at once, and with redundant values -e_debug_all = executable('dapp_debug_all', - test_src, - d_import_dirs: [data_dir], - d_module_versions: ['With_DebugAll'], - d_debug: ['4', 'DebugIdentifier', 2, 'DebugIdentifierUnused'], -) -test('dapp_debug_all_t', e_debug_all, args: ['debug']) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/10 out of bounds/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/10 out of bounds/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/10 out of bounds/test.json" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/10 out of bounds/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +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." + "line": "test cases/failing/10 out of bounds/meson.build:4:6: ERROR: Index 0 out of bounds of array of size 0." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/100 no glib-compile-resources/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/100 no glib-compile-resources/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/100 no glib-compile-resources/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/100 no glib-compile-resources/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/100 no glib-compile-resources/meson.build:8:0: ERROR: Program 'glib-compile-resources' not found or not executable" + "line": "test cases/failing/100 no glib-compile-resources/meson.build:8:12: ERROR: Program 'glib-compile-resources' not found or not executable" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/104 no fallback/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/104 no fallback/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/104 no fallback/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/104 no fallback/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -2,7 +2,7 @@ "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 .*)" + "line": ".*/meson\\.build:2:11: ERROR: (Pkg-config binary for machine MachineChoice\\.HOST not found\\. Giving up\\.|Dependency \"foob\" not found, tried .*)" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/105 feature require/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/105 feature require/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/105 feature require/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/105 feature require/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": ".*/meson\\.build:2:0: ERROR: Feature reqfeature cannot be enabled: frobnicator not available" + "line": ".*/meson\\.build:2:31: ERROR: Feature reqfeature cannot be enabled: frobnicator not available" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/106 feature require.bis/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/106 feature require.bis/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/106 feature require.bis/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/106 feature require.bis/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": ".*/meson\\.build:2:0: ERROR: Feature reqfeature cannot be enabled" + "line": ".*/meson\\.build:2:31: ERROR: Feature reqfeature cannot be enabled" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/107 no build get_external_property/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/107 no build get_external_property/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/107 no build get_external_property/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/107 no build get_external_property/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/107 no build get_external_property/meson.build:3:0: ERROR: Unknown property for build machine: nonexisting" + "line": "test cases/failing/107 no build get_external_property/meson.build:3:14: ERROR: Unknown property for build machine: nonexisting" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/109 invalid fstring/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/109 invalid fstring/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/109 invalid fstring/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/109 invalid fstring/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/109 invalid fstring/meson.build:3:0: ERROR: Identifier \"foo\" does not name a variable." + "line": "test cases/failing/109 invalid fstring/meson.build:3:4: ERROR: Identifier \"foo\" does not name a variable." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/11 object arithmetic/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/11 object arithmetic/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/11 object arithmetic/test.json" 2021-11-02 19:58:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/11 object arithmetic/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -2,7 +2,7 @@ "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 .*" + "line": "test cases/failing/11 object arithmetic/meson\\.build:3:12: ERROR: The `\\+` operator of str does not accept objects of type MesonMain .*" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/110 compiler argument checking/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/110 compiler argument checking/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/110 compiler argument checking/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/110 compiler argument checking/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/110 compiler argument checking/meson.build:4:0: ERROR: Compiler for C does not support \"-meson-goober-arg-for-testing\"" + "line": "test cases/failing/110 compiler argument checking/meson.build:4:25: ERROR: Compiler for C does not support \"-meson-goober-arg-for-testing\"" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/112 cmake executable dependency/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/112 cmake executable dependency/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/112 cmake executable dependency/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/112 cmake executable dependency/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/112 cmake executable dependency/meson.build:9:0: ERROR: main is an executable and does not support the dependency() method. Use target() instead." + "line": "test cases/failing/112 cmake executable dependency/meson.build:9:14: ERROR: main is an executable and does not support the dependency() method. Use target() instead." } ], "tools": { diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/115 run_target in test/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/115 run_target in test/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/115 run_target in test/meson.build" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/115 run_target in test/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ project('trivial test', 'c') -py_inst = import('python').find_installation() +python = find_program('python3') exe = executable('trivialprog', 'trivial.c') -runt = run_target('invalid', command: [py_inst, '--version']) +runt = run_target('invalid', command: [python, '--version']) test('runtest', exe, args: runt) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/116 run_target in add_install_script/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/116 run_target in add_install_script/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/116 run_target in add_install_script/meson.build" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/116 run_target in add_install_script/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ project('trivial test', 'c') -py_inst = import('python').find_installation() +python = find_program('python3') exe = executable('trivialprog', 'trivial.c') -runt = run_target('invalid', command: [py_inst, '--version']) +runt = run_target('invalid', command: [python, '--version']) meson.add_install_script(exe, runt) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/118 subproject version conflict/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/118 subproject version conflict/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/118 subproject version conflict/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/118 subproject version conflict/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/118 subproject version conflict/meson.build:4:0: ERROR: Subproject B version is 100 but ['1'] required." + "line": "test cases/failing/118 subproject version conflict/meson.build:4:8: ERROR: Subproject B version is 100 but ['1'] required." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/119 structured source empty string/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/119 structured source empty string/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/119 structured source empty string/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/119 structured source empty string/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/119 structured source empty string/meson.build:7:0: ERROR: structured_sources: keys to dictionary argument may not be an empty string." + "line": "test cases/failing/119 structured source empty string/meson.build:9:2: ERROR: structured_sources: keys to dictionary argument may not be an empty string." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/12 string arithmetic/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/12 string arithmetic/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/12 string arithmetic/test.json" 2021-11-02 19:58:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/12 string arithmetic/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +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)" + "line": "test cases/failing/12 string arithmetic/meson.build:3:12: ERROR: The `+` operator of str does not accept objects of type int (3)" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/122 cmake subproject error/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/122 cmake subproject error/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/122 cmake subproject error/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/122 cmake subproject error/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/122 cmake subproject error/meson.build:8:0: ERROR: Failed to configure the CMake subproject: Fancy error message" + "line": "test cases/failing/122 cmake subproject error/meson.build:8:14: ERROR: Failed to configure the CMake subproject: Fancy error message" } ], "tools": { diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/127 extract from unity/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/127 extract from unity/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/127 extract from unity/test.json" 2022-10-24 19:25:13.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/127 extract from unity/test.json" 2023-05-30 15:42:56.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/127 extract from unity/meson.build:4:0: ERROR: Single object files can not be extracted in Unity builds. You can only extract all the object files for each compiler at once." + "line": "test cases/failing/127 extract from unity/meson.build:4:37: ERROR: Single object files cannot be extracted in Unity builds. You can only extract all the object files for each compiler at once." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/129 generator host binary/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/129 generator host binary/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/129 generator host binary/meson.build" 2023-02-01 21:43:18.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/129 generator host binary/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -8,7 +8,7 @@ exe = executable('exe', 'exe.c', native : false) -gen = generator(exe, output : '@BASENAME@.c', arguments : ['@INPUT@', '@OUTPU@']) +gen = generator(exe, output : '@BASENAME@.c', arguments : ['@INPUT@', '@OUTPUT@']) foo = gen.process('lib.in') library('foo', foo) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/13 array arithmetic/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/13 array arithmetic/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/13 array arithmetic/test.json" 2021-11-02 19:58:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/13 array arithmetic/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +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." + "line": "test cases/failing/13 array arithmetic/meson.build:3:19: ERROR: Object <[ArrayHolder] holds [list]: ['a', 'b']> of type array does not support the `*` operator." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/130 invalid ast/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/130 invalid ast/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/130 invalid ast/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/130 invalid ast/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +project('invalid ast crash', meson_version: '0.1.0') + += >%@ diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/130 invalid ast/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/130 invalid ast/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/130 invalid ast/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/130 invalid ast/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "stdout": [ + { + "match": "re", + "line": "test cases/failing/130 invalid ast/meson.build:1:44: ERROR: Meson version is [0-9.]+(\\.rc[0-9]+)? but project requires 0.1.0" + } + ] +} + diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/131 invalid project function/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/131 invalid project function/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/131 invalid project function/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/131 invalid project function/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +project('invalid project function with bad kwargs', meson_version: '0.1.0', unknown_kwarg: 'val') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/131 invalid project function/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/131 invalid project function/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/131 invalid project function/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/131 invalid project function/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "stdout": [ + { + "match": "re", + "line": "test cases/failing/131 invalid project function/meson.build:1:67: ERROR: Meson version is [0-9.]+(\\.rc[0-9]+)? but project requires 0.1.0" + } + ] +} + diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/16 extract from subproject/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/16 extract from subproject/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/16 extract from subproject/test.json" 2021-04-01 21:12:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/16 extract from subproject/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/16 extract from subproject/meson.build:6:0: ERROR: Tried to extract objects from a different subproject." + "line": "test cases/failing/16 extract from subproject/meson.build:7:32: ERROR: Tried to extract objects from a different subproject." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/20 version/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/20 version/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/20 version/test.json" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/20 version/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": "test cases/failing/20 version/meson\\.build:1:0: ERROR: Meson version is .* but project requires >100\\.0\\.0" + "line": "test cases/failing/20 version/meson\\.build:1:44: ERROR: Meson version is .* but project requires >100\\.0\\.0" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/21 subver/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/21 subver/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/21 subver/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/21 subver/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +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." + "line": "test cases/failing/21 subver/meson.build:3:4: ERROR: Subproject foo version is 1.0.0 but ['>1.0.0'] required." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/28 no crossprop/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/28 no crossprop/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/28 no crossprop/test.json" 2021-04-27 06:49:45.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/28 no crossprop/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/28 no crossprop/meson.build:3:0: ERROR: Unknown property for host machine: nonexisting" + "line": "test cases/failing/28 no crossprop/meson.build:3:14: ERROR: Unknown property for host machine: nonexisting" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/3 missing subdir/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/3 missing subdir/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/3 missing subdir/test.json" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/3 missing subdir/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -3,7 +3,7 @@ { "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'" + "line": "test cases/failing/3 missing subdir/meson\\.build:3:0: ERROR: Nonexistent build file 'missing[\\\\/]meson\\.build'" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/30 invalid man extension/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/30 invalid man extension/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/30 invalid man extension/test.json" 2021-08-18 11:22:15.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/30 invalid man extension/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +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" + "line": "test cases/failing/30 invalid man extension/meson.build:2:5: ERROR: Man file must have a file extension of a number between 1 and 9" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/31 no man extension/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/31 no man extension/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/31 no man extension/test.json" 2021-08-18 11:22:15.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/31 no man extension/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +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" + "line": "test cases/failing/31 no man extension/meson.build:2:5: ERROR: Man file must have a file extension of a number between 1 and 9" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/32 exe static shared/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/32 exe static shared/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/32 exe static shared/test.json" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/32 exe static shared/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +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." + "line": "test cases/failing/32 exe static shared/meson.build:9:9: 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/34 dependency not-required then required/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/34 dependency not-required then required/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/34 dependency not-required then required/test.json" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/34 dependency not-required then required/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -2,7 +2,7 @@ "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 .*)" + "line": ".*/meson\\.build:4:10: ERROR: (Pkg-config binary for machine MachineChoice\\.HOST not found\\. Giving up\\.|Dependency \"foo\\-bar\\-xyz\\-12\\.3\" not found, tried .*)" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/39 kwarg assign/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/39 kwarg assign/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/39 kwarg assign/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/39 kwarg assign/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/39 kwarg assign/meson.build:3:0: ERROR: Tried to assign values inside an argument list." + "line": "test cases/failing/39 kwarg assign/meson.build:3:30: ERROR: Tried to assign values inside an argument list." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/4 missing meson.build/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/4 missing meson.build/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/4 missing meson.build/test.json" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/4 missing meson.build/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -3,7 +3,7 @@ { "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'" + "line": "test cases/failing/4 missing meson\\.build/meson\\.build:3:0: ERROR: Nonexistent build file 'subdir[\\\\/]meson\\.build'" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/49 executable comparison/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/49 executable comparison/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/49 executable comparison/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/49 executable comparison/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": "test cases/failing/49 executable comparison/meson.build:6:0: ERROR: Object of type Executable does not support the `<` operator." + "line": "test cases/failing/49 executable comparison/meson.build:6:14: ERROR: Object of type Executable does not support the `<` operator." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/50 inconsistent comparison/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/50 inconsistent comparison/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/50 inconsistent comparison/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/50 inconsistent comparison/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/50 inconsistent comparison/meson.build:5:0: ERROR: Object <[ArrayHolder] holds [list]: []> of type array does not support the `<` operator." + "line": "test cases/failing/50 inconsistent comparison/meson.build:5:12: ERROR: Object <[ArrayHolder] holds [list]: []> of type array does not support the `<` operator." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/56 link with executable/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/56 link with executable/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/56 link with executable/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/56 link with executable/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/56 link with executable/meson.build:4:0: ERROR: Link target 'prog' is not linkable." + "line": "test cases/failing/56 link with executable/meson.build:4:4: ERROR: Link target 'prog' is not linkable." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/59 bad option argument/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/59 bad option argument/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/59 bad option argument/meson_options.txt" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/59 bad option argument/meson_options.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -1 +1 @@ -option('name', type : 'string', vaule : 'foo') +option('name', type : 'string', value_ : 'foo') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/59 bad option argument/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/59 bad option argument/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/59 bad option argument/test.json" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/59 bad option argument/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/59 bad option argument/meson_options.txt:1:0: ERROR: option got unknown keyword arguments \"vaule\"" + "line": "test cases/failing/59 bad option argument/meson_options.txt:1:0: ERROR: string option got unknown keyword arguments \"value_\"" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/6 missing incdir/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/6 missing incdir/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/6 missing incdir/test.json" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/6 missing incdir/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/6 missing incdir/meson.build:3:0: ERROR: Include dir nosuchdir does not exist." + "line": "test cases/failing/6 missing incdir/meson.build:3:6: ERROR: Include dir nosuchdir does not exist." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/64 dependency not-found and required/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/64 dependency not-found and required/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/64 dependency not-found and required/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/64 dependency not-found and required/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/64 dependency not-found and required/meson.build:2:0: ERROR: Dependency is required but has no candidates." + "line": "test cases/failing/64 dependency not-found and required/meson.build:2:6: ERROR: Dependency is required but has no candidates." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/65 subproj different versions/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/65 subproj different versions/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/65 subproj different versions/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/65 subproj different versions/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/65 subproj different versions/subprojects/b/meson.build:3:0: ERROR: Dependency 'c' is required but not found." + "line": "test cases/failing/65 subproj different versions/subprojects/b/meson.build:3:8: ERROR: Dependency 'c' is required but not found." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/66 wrong boost module/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/66 wrong boost module/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/66 wrong boost module/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/66 wrong boost module/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/66 wrong boost module/meson.build:9:0: ERROR: Dependency \"boost\" not found, tried system" + "line": "test cases/failing/66 wrong boost module/meson.build:9:10: ERROR: Dependency \"boost\" not found, tried system" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/70 override used/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/70 override used/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/70 override used/meson.build" 2022-10-02 21:19:36.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/70 override used/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,4 +1,4 @@ -project('overridde an already found exe') +project('override an already found exe') old = find_program('something.py') replacement = find_program('other.py') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/74 link with shared module on osx/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/74 link with shared module on osx/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/74 link with shared module on osx/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/74 link with shared module on osx/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/74 link with shared module on osx/meson.build:8:0: ERROR: target prog links against shared module mymodule. This is not permitted on OSX" + "line": "test cases/failing/74 link with shared module on osx/meson.build:8:4: ERROR: target prog links against shared module mymodule. This is not permitted on OSX" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/75 non ascii in ascii encoded configure file/config9.h.in" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/75 non ascii in ascii encoded configure file/config9.h.in" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/75 non ascii in ascii encoded configure file/config9.h.in" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/75 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/75 non ascii in ascii encoded configure file/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/75 non ascii in ascii encoded configure file/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/75 non ascii in ascii encoded configure file/meson.build" 2022-10-02 21:19:36.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/75 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') -# 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/75 non ascii in ascii encoded configure file/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/75 non ascii in ascii encoded configure file/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/75 non ascii in ascii encoded configure file/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/75 non ascii in ascii encoded configure file/test.json" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -{ - "stdout": [ - { - "match": "re", - "line": "test cases/failing/75 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/75 non-ascii in ascii encoded configure file/config9.h.in" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/75 non-ascii in ascii encoded configure file/config9.h.in" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/75 non-ascii in ascii encoded configure file/config9.h.in" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/75 non-ascii in ascii encoded configure file/config9.h.in" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +#define MESSAGE "@var@" diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/75 non-ascii in ascii encoded configure file/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/75 non-ascii in ascii encoded configure file/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/75 non-ascii in ascii encoded configure file/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/75 non-ascii in ascii encoded configure file/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,10 @@ +project('non-ascii to ascii encoding') +# 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/75 non-ascii in ascii encoded configure file/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/75 non-ascii in ascii encoded configure file/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/75 non-ascii in ascii encoded configure file/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/75 non-ascii in ascii encoded configure file/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "match": "re", + "line": "test cases/failing/75 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/76 subproj dependency not-found and required/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/76 subproj dependency not-found and required/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/76 subproj dependency not-found and required/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/76 subproj dependency not-found and required/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/76 subproj dependency not-found and required/meson.build:2:0: ERROR: Neither a subproject directory nor a missing.wrap file was found." + "line": "test cases/failing/76 subproj dependency not-found and required/meson.build:2:10: ERROR: Neither a subproject directory nor a missing.wrap file was found." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/78 framework dependency with version/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/78 framework dependency with version/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/78 framework dependency with version/meson.build" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/78 framework dependency with version/meson.build" 2023-05-30 15:43:02.000000000 +0000 @@ -5,4 +5,4 @@ endif # do individual frameworks have a meaningful version to test? And multiple frameworks might be listed... -dep = dependency('appleframeworks', modules: 'foundation', version: '>0') +dep = dependency('appleframeworks', modules: 'Foundation', version: '>0') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/78 framework dependency with version/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/78 framework dependency with version/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/78 framework dependency with version/test.json" 2022-10-24 19:25:13.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/78 framework dependency with version/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/78 framework dependency with version/meson.build:8:0: ERROR: Dependency lookup for appleframeworks with method 'framework' failed: Unknown version, but need ['>0']." + "line": "test cases/failing/78 framework dependency with version/meson.build:8:6: ERROR: Dependency lookup for appleframeworks with method 'framework' failed: Unknown version, but need ['>0']." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/8 recursive/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/8 recursive/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/8 recursive/test.json" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/8 recursive/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/8 recursive/subprojects/b/meson.build:3:0: ERROR: Recursive include of subprojects: a => b => a." + "line": "test cases/failing/8 recursive/subprojects/b/meson.build:3:4: ERROR: Recursive include of subprojects: a => b => a." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/80 gl dependency with version/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/80 gl dependency with version/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/80 gl dependency with version/test.json" 2022-10-24 19:25:13.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/80 gl dependency with version/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/80 gl dependency with version/meson.build:9:0: ERROR: Dependency lookup for gl with method 'system' failed: Unknown version, but need ['>0']." + "line": "test cases/failing/80 gl dependency with version/meson.build:9:6: ERROR: Dependency lookup for gl with method 'system' failed: Unknown version, but need ['>0']." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/81 threads dependency with version/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/81 threads dependency with version/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/81 threads dependency with version/test.json" 2022-10-24 19:25:13.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/81 threads dependency with version/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/81 threads dependency with version/meson.build:3:0: ERROR: Dependency lookup for threads with method 'system' failed: Unknown version, but need ['>0']." + "line": "test cases/failing/81 threads dependency with version/meson.build:3:6: ERROR: Dependency lookup for threads with method 'system' failed: Unknown version, but need ['>0']." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/82 gtest dependency with version/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/82 gtest dependency with version/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/82 gtest dependency with version/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/82 gtest dependency with version/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/82 gtest dependency with version/meson.build:8:0: ERROR: Dependency 'gtest' is required but not found." + "line": "test cases/failing/82 gtest dependency with version/meson.build:8:6: ERROR: Dependency 'gtest' is required but not found." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/83 dub library/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/83 dub library/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/83 dub library/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/83 dub library/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/83 dub library/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/83 dub library/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/83 dub library/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/83 dub library/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/83 dub library/meson.build:11:0: ERROR: Dependency \"dubtestproject\" not found" + } + ] +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/83 dub libray/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/83 dub libray/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/83 dub libray/meson.build" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/83 dub libray/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/83 dub libray/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/83 dub libray/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/83 dub libray/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/83 dub libray/test.json" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -{ - "stdout": [ - { - "line": "test cases/failing/83 dub libray/meson.build:11:0: ERROR: Dependency \"dubtestproject\" not found" - } - ] -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/86 subproj not-found dep/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/86 subproj not-found dep/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/86 subproj not-found dep/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/86 subproj not-found dep/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/86 subproj not-found dep/meson.build:2:0: ERROR: Dependency '(anonymous)' is required but not found." + "line": "test cases/failing/86 subproj not-found dep/meson.build:2:10: ERROR: Dependency '(anonymous)' is required but not found." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/88 kwarg dupe/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/88 kwarg dupe/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/88 kwarg dupe/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/88 kwarg dupe/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/88 kwarg dupe/meson.build:5:0: ERROR: Entry \"install\" defined both as a keyword argument and in a \"kwarg\" entry." + "line": "test cases/failing/88 kwarg dupe/meson.build:6:2: ERROR: Entry \"install\" defined both as a keyword argument and in a \"kwarg\" entry." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/89 missing pch file/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/89 missing pch file/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/89 missing pch file/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/89 missing pch file/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -2,7 +2,7 @@ "stdout": [ { "comment": "literal 'pch/prog.h' from meson.build appears in output, irrespective of os.path.sep", - "line": "test cases/failing/89 missing pch file/meson.build:2:0: ERROR: File pch/prog.h does not exist." + "line": "test cases/failing/89 missing pch file/meson.build:2:6: ERROR: File pch/prog.h does not exist." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/90 pch source different folder/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/90 pch source different folder/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/90 pch source different folder/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/90 pch source different folder/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/90 pch source different folder/meson.build:4:0: ERROR: PCH files must be stored in the same folder." + "line": "test cases/failing/90 pch source different folder/meson.build:4:6: ERROR: PCH files must be stored in the same folder." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/93 add dict non string key/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/93 add dict non string key/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/93 add dict non string key/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/93 add dict non string key/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/93 add dict non string key/meson.build:9:0: ERROR: Key must be a string" + "line": "test cases/failing/93 add dict non string key/meson.build:9:9: ERROR: Key must be a string" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/94 add dict duplicate keys/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/94 add dict duplicate keys/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/94 add dict duplicate keys/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/94 add dict duplicate keys/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/94 add dict duplicate keys/meson.build:9:0: ERROR: Duplicate dictionary key: myKey" + "line": "test cases/failing/94 add dict duplicate keys/meson.build:9:27: ERROR: Duplicate dictionary key: myKey" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/95 no host get_external_property/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/95 no host get_external_property/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/failing/95 no host get_external_property/test.json" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/failing/95 no host get_external_property/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/95 no host get_external_property/meson.build:3:0: ERROR: Unknown property for host machine: nonexisting" + "line": "test cases/failing/95 no host get_external_property/meson.build:3:14: ERROR: Unknown property for host machine: nonexisting" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/fortran/22 extract_objects/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/fortran/22 extract_objects/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/fortran/22 extract_objects/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/fortran/22 extract_objects/meson.build" 2023-05-23 15:20:09.000000000 +0000 @@ -0,0 +1,17 @@ +project('test_project', 'fortran') + +if get_option('unity') == 'on' + error('MESON_SKIP_TEST: extract_objects does not work in unity builds') +endif + +libfoo = static_library( + 'foo', + sources : ['foo1.f90', 'foo2.f90']) + +foo1_object = libfoo.extract_objects('foo1.f90') + +libfinal = library( + 'final', + sources : 'bar.f90', + objects : foo1_object, +) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/fortran/23 preprocess/main.f90" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/fortran/23 preprocess/main.f90" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/fortran/23 preprocess/main.f90" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/fortran/23 preprocess/main.f90" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,4 @@ +#define MYDEF program +MYDEF foo + write (*,*) 'Hello, world!' +end MYDEF foo diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/fortran/23 preprocess/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/fortran/23 preprocess/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/fortran/23 preprocess/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/fortran/23 preprocess/meson.build" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,7 @@ +project('preprocess', 'fortran') + +fc = meson.get_compiler('fortran') + +pp_files = fc.preprocess('main.f90', output: '@PLAINNAME@') + +library('foo', pp_files) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/1 boost/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/1 boost/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/1 boost/meson.build" 2023-02-01 22:05:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/1 boost/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -17,7 +17,7 @@ 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) +notfound = dependency('boost', static: s, modules : ['this_should_not_exist_on_any_system'], required: false) assert(not notfound.found()) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/14 doxygen/doc/Doxyfile.in" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/14 doxygen/doc/Doxyfile.in" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/14 doxygen/doc/Doxyfile.in" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/14 doxygen/doc/Doxyfile.in" 2023-05-23 15:20:02.000000000 +0000 @@ -58,7 +58,7 @@ # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = doc +OUTPUT_DIRECTORY = "@TOP_BUILDDIR@/doc" # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/14 doxygen/doc/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/14 doxygen/doc/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/14 doxygen/doc/meson.build" 2021-11-02 19:58:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/14 doxygen/doc/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,5 +1,5 @@ -cdata.set('TOP_SRCDIR', meson.source_root()) -cdata.set('TOP_BUILDDIR', meson.build_root()) +cdata.set('TOP_SRCDIR', meson.project_source_root()) +cdata.set('TOP_BUILDDIR', meson.project_build_root()) doxyfile = configure_file(input: 'Doxyfile.in', output: 'Doxyfile', diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/14 doxygen/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/14 doxygen/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/14 doxygen/meson.build" 2023-02-01 22:06:19.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/14 doxygen/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,4 +1,4 @@ -project('doxygen test', 'cpp', version : '0.1.0') +project('doxygen test', 'cpp', version : '0.1.0', meson_version: '>=0.56') spede_inc = include_directories('include') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/15 llvm/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/15 llvm/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/15 llvm/meson.build" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/15 llvm/meson.build" 2023-06-28 14:48:20.000000000 +0000 @@ -2,50 +2,115 @@ method = get_option('method') static = get_option('link-static') -d = dependency('llvm', required : false, method : method, static : static) + +d = dependency('llvm', required : false, static : static) if not d.found() error('MESON_SKIP_TEST llvm not found.') endif -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, method : method) -assert(d.found() == false, 'ancient llvm module found') - -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, method : method) -assert(d.found() == true, 'Cannot set version constraints') - -dep_tinfo = dependency('tinfo', required : false) -if not dep_tinfo.found() - cpp = meson.get_compiler('cpp') - dep_tinfo = cpp.find_library('tinfo', required: false) -endif - -llvm_dep = dependency( - 'llvm', - modules : ['bitwriter', 'asmprinter', 'executionengine', 'target', - 'mcjit', 'nativecodegen', 'amdgpu'], - required : false, - static : static, - method : method, -) +modules_to_find = [ + 'bitwriter', 'asmprinter', 'executionengine', 'mcjit', 'target', + 'nativecodegen', 'amdgpu', 'engine' +] + +if method == 'combination' + if not d.version().version_compare(static ? '>0.1' : '>=7.0') + error('MESON_SKIP_TEST: llvm version is too low') + endif + llvm_ct_dep = dependency( + 'llvm', + modules : modules_to_find, + required : false, + static : static, + method : 'config-tool', + ) -if not llvm_dep.found() - error('MESON_SKIP_TEST required llvm modules not found.') + if static and d.version().startswith('16.0') and d.version()[5].to_int() <= 6 + message('Skipping modules with cmake due to an LLVM bug, see https://github.com/mesonbuild/meson/issues/11642') + llvm_cm_dep = dependency( + 'llvm', + required : false, + static : static, + method : 'cmake', + ) + else + llvm_cm_dep = dependency( + 'llvm', + modules : modules_to_find, + required : false, + static : static, + method : 'cmake', + ) + endif + + assert(llvm_ct_dep.found() and llvm_cm_dep.found(), 'config-tool and cmake both need to be found') + cm_version_major = llvm_cm_dep.version().split('.')[0].to_int() + cm_version_minor = llvm_cm_dep.version().split('.')[1].to_int() + ct_version_major = llvm_ct_dep.version().split('.')[0].to_int() + ct_version_minor = llvm_ct_dep.version().split('.')[1].to_int() + assert(cm_version_major == ct_version_major, 'config-tool and cmake returns different major versions') + assert(cm_version_minor == ct_version_minor, 'config-tool and cmake returns different minor versions') +else + if not static and method == 'cmake' + d = dependency('llvm', version : '>=7.0', required : false, static : static) + if not d.found() + error('MESON_SKIP_TEST llvm version is too low for cmake dynamic link.') + endif + endif + + 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, method : method) + assert(d.found() == false, 'ancient llvm module found') + + 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, method : method) + assert(d.found() == true, 'Cannot set version constraints') + + # Check if we have to get pseudo components + d = dependency('llvm', modules: ['all-targets','native','engine'], required: false, static : static, method : method) + assert(d.found() == true, 'Cannot find pseudo components') + + dep_tinfo = dependency('tinfo', required : false) + if not dep_tinfo.found() + cpp = meson.get_compiler('cpp') + dep_tinfo = cpp.find_library('tinfo', required: false) + endif + + if static and method == 'cmake' and d.version().startswith('16.0') and d.version()[5].to_int() <= 5 + message('Skipping modules with cmake due to an LLVM bug, see https://github.com/mesonbuild/meson/issues/11642') + llvm_dep = dependency( + 'llvm', + required : false, + static : static, + method : method, + ) + else + llvm_dep = dependency( + 'llvm', + modules : modules_to_find, + required : false, + static : static, + method : method, + ) + endif + + 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), + ] + ) 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/15 llvm/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/15 llvm/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/15 llvm/meson_options.txt" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/15 llvm/meson_options.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ option( 'method', type : 'combo', - choices : ['config-tool', 'cmake'] + choices : ['config-tool', 'cmake', 'combination'] ) option( 'link-static', diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/15 llvm/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/15 llvm/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/15 llvm/test.json" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/15 llvm/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -3,16 +3,17 @@ "options": { "method": [ { "val": "config-tool", "skip_on_jobname": ["msys2-gcc"]}, - { "val": "cmake", "skip_on_jobname": ["msys2-gcc"] } + { "val": "cmake", "skip_on_jobname": ["msys2-gcc"] }, + { "val": "combination", "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"] + "skip_on_jobname": ["azure", "cygwin"], + "tools": { + "cmake": ">=3.11" + } } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/16 sdl2/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/16 sdl2/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/16 sdl2/meson_options.txt" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/16 sdl2/meson_options.txt" 2023-05-30 15:42:56.000000000 +0000 @@ -1,6 +1,6 @@ option( 'method', type : 'combo', - choices : ['auto', 'pkg-config', 'config-tool', 'sdlconfig', 'extraframework'], + choices : ['auto', 'pkg-config', 'config-tool', 'sdlconfig', 'extraframework', 'cmake'], value : 'auto', ) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/16 sdl2/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/16 sdl2/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/16 sdl2/test.json" 2021-11-02 19:58:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/16 sdl2/test.json" 2023-05-30 15:42:56.000000000 +0000 @@ -6,7 +6,8 @@ { "val": "pkg-config" }, { "val": "config-tool" }, { "val": "sdlconfig" }, - { "val": "extraframework", "skip_on_os": ["!darwin"], "skip_on_jobname": ["macos"] } + { "val": "extraframework", "skip_on_os": ["!darwin"], "skip_on_jobname": ["macos"] }, + { "val": "cmake", "skip_on_jobname": ["bionic"] } ] } }, diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/21 libwmf/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/21 libwmf/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/21 libwmf/meson.build" 2023-02-01 22:06:53.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/21 libwmf/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -10,7 +10,7 @@ assert(libwmf_ver.split('.').length() > 1, 'libwmf version is "@0@"'.format(libwmf_ver)) message('libwmf version is "@0@"'.format(libwmf_ver)) # Workaround for Debian bug 912563 where libwmf-devel returns cflags -# that do not not have Freetype include paths but their headers +# that do not have Freetype include paths but their headers # use them unconditionally. ft_dep = dependency('freetype2') e = executable('libwmf_prog', 'libwmf_prog.c', dependencies : [libwmf_dep, ft_dep]) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/25 hdf5/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/25 hdf5/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/25 hdf5/meson.build" 2021-04-01 21:12:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/25 hdf5/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -29,7 +29,7 @@ # 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 + # mixing gfortran with non-gcc doesn't work on windows test_fortran = false endif diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/27 gpgme/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/27 gpgme/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/27 gpgme/test.json" 2023-02-20 12:58:43.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/27 gpgme/test.json" 2023-08-07 22:54:05.000000000 +0000 @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "cygwin", "macos", "msys2", "linux-arch"] + "skip_on_jobname": ["azure", "cygwin", "macos", "msys2", "linux-arch", "ubuntu"] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/4 qt/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/4 qt/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/4 qt/meson.build" 2023-02-01 22:05:54.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/4 qt/meson.build" 2023-05-25 18:34:59.000000000 +0000 @@ -65,7 +65,7 @@ extra_cpp_args = [] if meson.is_unity() extra_cpp_args += '-DUNITY_BUILD' - prep_rcc = qtmodule.preprocess(qt + '_unity_ressource', qresources : ['stuff.qrc', 'stuff2.qrc'], method : get_option('method')) + prep_rcc = qtmodule.preprocess(qt + '_unity_resource', qresources : ['stuff.qrc', 'stuff2.qrc'], method : get_option('method')) else prep_rcc = qtmodule.preprocess(qresources : ['stuff.qrc', 'stuff2.qrc'], method : get_option('method')) endif @@ -152,7 +152,8 @@ endif # Check we can apply a version constraint - dependency(qt, modules: qt_modules, version: '>=@0@'.format(qtdep.version()), method : get_option('method')) + accept_versions = ['>=@0@'.format(qtdep.version()), '<@0@'.format(qtdep.version()[0].to_int() + 1)] + dependency(qt, modules: qt_modules, version: accept_versions, method : get_option('method')) endif endforeach diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/4 qt/subfolder/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/4 qt/subfolder/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/4 qt/subfolder/meson.build" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/4 qt/subfolder/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -23,7 +23,7 @@ extra_cpp_args = [] if meson.is_unity() extra_cpp_args += '-DUNITY_BUILD' - qresources = qtmodule.preprocess(qt + '_subfolder_unity_ressource',qresources : ['resources/stuff3.qrc', rc_file]) + qresources = qtmodule.preprocess(qt + '_subfolder_unity_resource',qresources : ['resources/stuff3.qrc', rc_file]) else qresources = qtmodule.preprocess(qresources : ['resources/stuff3.qrc', rc_file]) endif diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/5 protocol buffers/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/5 protocol buffers/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/5 protocol buffers/meson.build" 2023-02-01 22:05:53.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/5 protocol buffers/meson.build" 2023-08-07 22:54:05.000000000 +0000 @@ -1,4 +1,4 @@ -project('protocol buffer test', 'cpp', default_options: ['cpp_std=c++11']) +project('protocol buffer test', 'cpp', default_options: ['cpp_std=c++14']) protoc = find_program('protoc', required : false) dep = dependency('protobuf', required : false) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/copy.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/copy.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/copy.py" 2021-08-18 11:22:15.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/copy.py" 2023-05-23 15:20:02.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 -# Copyright © 2021 Intel Corproation +# Copyright © 2021 Intel Corporation import argparse import shutil diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/dep1/dep1.h" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/dep1/dep1.h" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/dep1/dep1.h" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/dep1/dep1.h" 2023-05-30 15:42:56.000000000 +0000 @@ -1,8 +1,8 @@ #ifndef MESON_DEP1_H #define MESON_DEP1_H -#if !defined (MESON_TEST) -#error "MESON_TEST not defined." +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." #endif #include diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/dep1/dep2/dep2.h" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/dep1/dep2/dep2.h" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/dep1/dep2/dep2.h" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/dep1/dep2/dep2.h" 2023-05-30 15:42:56.000000000 +0000 @@ -1,8 +1,8 @@ #ifndef MESON_DEP2_H #define MESON_DEP2_H -#if !defined (MESON_TEST) -#error "MESON_TEST not defined." +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." #endif #include diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h" 2023-05-30 15:42:56.000000000 +0000 @@ -1,8 +1,8 @@ #ifndef MESON_DEP3_H #define MESON_DEP3_H -#if !defined (MESON_TEST) -#error "MESON_TEST not defined." +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." #endif #include diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/meson-sample.h" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/meson-sample.h" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/meson-sample.h" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/meson-sample.h" 2023-05-30 15:42:56.000000000 +0000 @@ -1,8 +1,12 @@ #ifndef MESON_SAMPLE_H #define MESON_SAMPLE_H -#if !defined (MESON_TEST) -#error "MESON_TEST not defined." +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." +#endif + +#if !defined (MESON_TEST_2) +#error "MESON_TEST_2 not defined." #endif #include diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/meson-sample2.h" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/meson-sample2.h" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/meson-sample2.h" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/meson-sample2.h" 2023-05-30 15:42:56.000000000 +0000 @@ -1,8 +1,8 @@ #ifndef MESON_SAMPLE2_H #define MESON_SAMPLE2_H -#if !defined (MESON_TEST) -#error "MESON_TEST not defined." +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." #endif #include diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/gir/meson.build" 2021-11-02 19:58:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/gir/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -4,7 +4,7 @@ lib2sources = ['meson-sample2.c', 'meson-sample2.h'] gen_source = custom_target( - 'meson_smaple3.h', + 'meson_sample3.h', input : 'meson-sample.h', output : 'meson-sample3.h', command : [find_program('copy.py'), '@INPUT@', '@OUTPUT@'], @@ -14,6 +14,7 @@ girlib = shared_library( 'gir_lib', sources : libsources, + c_args: '-DMESON_TEST_2', dependencies : [gobj, dep1_dep], install : true ) @@ -28,6 +29,7 @@ girexe = executable( 'girprog', sources : 'prog.c', + c_args: '-DMESON_TEST_2', dependencies : [glib, gobj, gir, dep1_dep], link_with : girlib ) @@ -37,6 +39,7 @@ gnome.generate_gir( girlib, girlib2, sources : [libsources, lib2sources, gen_source], + env : {'CPPFLAGS': '-DMESON_TEST_2'}, nsversion : '1.0', namespace : 'Meson', symbol_prefix : 'meson', diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/frameworks/7 gnome/meson.build" 2023-02-01 22:06:14.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/frameworks/7 gnome/meson.build" 2023-08-07 22:54:05.000000000 +0000 @@ -23,7 +23,7 @@ cc = meson.get_compiler('c') -add_global_arguments('-DMESON_TEST', language : 'c') +add_global_arguments('-DMESON_TEST_1', language : 'c') if cc.get_id() == 'intel' # Ignore invalid GCC pragma warnings from glib # https://bugzilla.gnome.org/show_bug.cgi?id=776562 @@ -51,6 +51,15 @@ gir = dependency('gobject-introspection-1.0') gmod = dependency('gmodule-2.0') +# GLib >= 2.76 removed slice allocator which causes a leak in g-i to now be +# visible to asan. The leak should be fixed in g-i >= 1.76.2: +# https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/411 +if get_option('b_sanitize') != 'none' and \ + gir.version().version_compare('<=1.76.1') and \ + glib.version().version_compare('>=2.76') + error('MESON_SKIP_TEST gobject-introspection >=1.76.2 is required with address sanitizer.') +endif + # Test that static deps don't error out when static libraries aren't found glib_static = dependency('glib-2.0', static : true) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/java/3 args/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/java/3 args/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/java/3 args/meson.build" 2023-02-01 22:01:38.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/java/3 args/meson.build" 2023-05-30 15:43:02.000000000 +0000 @@ -1,8 +1,8 @@ project('simplejava', 'java') -add_project_arguments('-target', '1.7', language : 'java') +add_project_arguments('-target', '1.8', language : 'java') javaprog = jar('myprog', 'com/mesonbuild/Simple.java', main_class : 'com.mesonbuild.Simple', - java_args : ['-source', '1.7']) + java_args : ['-source', '1.8']) test('mytest', javaprog) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/java/8 codegen custom target/com/mesonbuild/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/java/8 codegen custom target/com/mesonbuild/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/java/8 codegen custom target/com/mesonbuild/meson.build" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/java/8 codegen custom target/com/mesonbuild/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,4 +1,4 @@ -python = import('python').find_installation('python3') +python = find_program('python3') config_file = custom_target('confgen', input : 'Config.java.in', diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake" 2021-10-23 16:36:11.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake" 2023-05-23 15:20:02.000000000 +0000 @@ -5,7 +5,7 @@ set(cmMesonTestF1_LIBRARIES general ${ZLIB_LIBRARY}) set(cmMesonTestF1_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) - add_library(CMMesonTESTf1::evil_non_standard_trget UNKNOWN IMPORTED) + add_library(CMMesonTESTf1::evil_non_standard_target UNKNOWN IMPORTED) else() set(cmMesonTestF1_FOUND OFF) endif() diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/linuxlike/13 cmake dependency/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/linuxlike/13 cmake dependency/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/linuxlike/13 cmake dependency/test.json" 2021-10-23 16:36:11.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/linuxlike/13 cmake dependency/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -8,7 +8,7 @@ "line": "WARNING: Could not find and exact match for the CMake dependency cmMesonTestF1." }, { - "line": " ['CMMesonTESTf1::evil_non_standard_trget']" + "line": " ['CMMesonTESTf1::evil_non_standard_target']" } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/linuxlike/5 dependency versions/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/linuxlike/5 dependency versions/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/linuxlike/5 dependency versions/meson.build" 2023-02-01 22:01:26.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/linuxlike/5 dependency versions/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -82,7 +82,7 @@ # 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'], + fallback : ['nonexistent', 'fakezlib_dep'], required: false) assert(not d.found(), 'version should not match and it should not fallback') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/nasm/2 asm language/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/nasm/2 asm language/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/nasm/2 asm language/meson.build" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/nasm/2 asm language/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -5,6 +5,14 @@ error('MESON_SKIP_TEST: nasm only supported for x86 and x86_64') endif +if host_machine.system() == 'windows' + error('MESON_SKIP_TEST: this test asm is not made for Windows') +endif + +if meson.backend().startswith('vs') + error('MESON_SKIP_TEST: VS backend does not recognise NASM yet') +endif + if not add_languages('nasm', required: false) nasm = find_program('nasm', 'yasm', required: false) assert(not nasm.found()) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/nasm/3 nasm only/dummy.asm" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/nasm/3 nasm only/dummy.asm" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/nasm/3 nasm only/dummy.asm" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/nasm/3 nasm only/dummy.asm" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,4 @@ +global dummy +section .rdata align=16 +dummy: + dd 0x00010203 diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/nasm/3 nasm only/dummy.def" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/nasm/3 nasm only/dummy.def" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/nasm/3 nasm only/dummy.def" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/nasm/3 nasm only/dummy.def" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,2 @@ +EXPORTS + dummy diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/nasm/3 nasm only/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/nasm/3 nasm only/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/nasm/3 nasm only/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/nasm/3 nasm only/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,17 @@ +project('nasm only') + +if not add_languages('nasm', required: false) + error('MESON_SKIP_TEST: nasm not found') +endif + +if meson.backend().startswith('vs') + error('MESON_SKIP_TEST: VS backend does not recognise NASM yet') +endif + +sources = files('dummy.asm') + +dummy = library( + 'dummy', + sources, + vs_module_defs: 'dummy.def', +) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/native/2 global arg/prog.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/native/2 global arg/prog.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/native/2 global arg/prog.c" 2021-04-01 21:13:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/native/2 global arg/prog.c" 2023-05-23 15:20:02.000000000 +0000 @@ -11,7 +11,7 @@ #endif #if !defined(GLOBAL_HOST) && !defined(GLOBAL_BUILD) - #error "Neither global_host nor glogal_build is set." + #error "Neither global_host nor global_build is set." #endif #if defined(GLOBAL_HOST) && defined(GLOBAL_BUILD) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/objc/2 nsstring/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/objc/2 nsstring/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/objc/2 nsstring/meson.build" 2023-02-01 22:03:59.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/objc/2 nsstring/meson.build" 2023-05-30 15:43:02.000000000 +0000 @@ -1,7 +1,7 @@ project('nsstring', 'objc') if host_machine.system() == 'darwin' - dep = dependency('appleframeworks', modules : 'foundation') + dep = dependency('appleframeworks', modules : 'Foundation') elif host_machine.system() == 'cygwin' error('MESON_SKIP_TEST GNUstep is not packaged for Cygwin.') else diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/osx/6 multiframework/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/osx/6 multiframework/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/osx/6 multiframework/meson.build" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/osx/6 multiframework/meson.build" 2023-05-30 15:43:02.000000000 +0000 @@ -4,7 +4,7 @@ # that causes a build failure when defining two modules. The # arguments for the latter module overwrote the arguments for # the first one rather than adding to them. -cocoa_dep = dependency('appleframeworks', modules : ['AppKit', 'foundation']) +cocoa_dep = dependency('appleframeworks', modules : ['AppKit', 'Foundation']) executable('deptester', 'main.m', diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/1 basic/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/1 basic/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/1 basic/meson.build" 2023-02-01 22:04:39.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/1 basic/meson.build" 2023-05-23 15:20:09.000000000 +0000 @@ -8,6 +8,9 @@ error('MESON_SKIP_TEST python 3 required for tests') endif +py_full_version = py.version() +message(f'Using python version: @py_full_version@') + py_purelib = py.get_path('purelib') if not (py_purelib.endswith('site-packages') or py_purelib.endswith('dist-packages')) error('Python3 purelib path seems invalid? ' + py_purelib) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/blaster.py.in" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/blaster.py.in" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/blaster.py.in" 2021-10-11 16:26:46.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/blaster.py.in" 2023-05-30 15:42:56.000000000 +0000 @@ -8,4 +8,4 @@ raise SystemExit('Returned result not an integer.') if result != 1: - raise SystemExit(f'Returned result {result} is not 1.') + raise SystemExit('Returned result {} is not 1.'.format(result)) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/ext/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/ext/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/ext/meson.build" 2022-06-19 19:10:14.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/ext/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -4,6 +4,12 @@ install: true, ) +pylib2 = py2.extension_module('tachyon', + 'tachyon_module.c', + c_args: '-DMESON_MODULENAME="tachyon"', + install: true, +) + subdir('nested') subdir('wrongdir') pypathdir = meson.current_build_dir() diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/ext/nested/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/ext/nested/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/ext/nested/meson.build" 2022-06-19 19:10:14.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/ext/nested/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -13,3 +13,20 @@ pure: false, subdir: 'nested', ) + + +py2.extension_module('tachyon', + '../tachyon_module.c', + c_args: '-DMESON_MODULENAME="nested.tachyon"', + install: true, + subdir: 'nested' +) +py2.install_sources( + configure_file( + input: '../../blaster.py.in', + output: 'blaster.py', + configuration: {'tachyon_module': 'nested.tachyon'} + ), + pure: false, + subdir: 'nested', +) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/ext/tachyon_module.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/ext/tachyon_module.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/ext/tachyon_module.c" 2021-10-11 16:26:46.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/ext/tachyon_module.c" 2023-05-30 15:42:56.000000000 +0000 @@ -1,5 +1,5 @@ /* - Copyright 2016 The Meson development team + 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. @@ -27,7 +27,11 @@ return NULL; result = strcmp(message, "shoot") ? 0 : 1; +#if PY_VERSION_HEX < 0x03000000 + return PyInt_FromLong(result); +#else return PyLong_FromLong(result); +#endif } static PyMethodDef TachyonMethods[] = { @@ -36,9 +40,14 @@ {NULL, NULL, 0, NULL} }; +#if PY_VERSION_HEX < 0x03000000 +PyMODINIT_FUNC inittachyon(void) { + Py_InitModule("tachyon", TachyonMethods); +} +#else static struct PyModuleDef tachyonmodule = { PyModuleDef_HEAD_INIT, - MESON_MODULENAME, + "tachyon", NULL, -1, TachyonMethods @@ -47,3 +56,4 @@ PyMODINIT_FUNC PyInit_tachyon(void) { return PyModule_Create(&tachyonmodule); } +#endif diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/ext/wrongdir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/ext/wrongdir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/ext/wrongdir/meson.build" 2022-06-19 19:10:14.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/ext/wrongdir/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -4,3 +4,9 @@ install: true, install_dir: get_option('libdir') ) +py2.extension_module('tachyon', + '../tachyon_module.c', + c_args: '-DMESON_MODULENAME="tachyon"', + install: true, + install_dir: get_option('libdir') +) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/meson.build" 2023-02-01 22:04:41.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -1,5 +1,5 @@ project('Python extension module', 'c', - default_options : ['buildtype=release']) + default_options : ['buildtype=release', 'werror=true', 'python.bytecompile=-1']) # Because Windows Python ships only with optimized libs, # we must build this project the same way. @@ -10,6 +10,7 @@ py_mod = import('python') py = py_mod.find_installation() +py2 = py_mod.find_installation('python2', required: get_option('python2'), disabler: true) py_dep = py.dependency(required: false) if not py_dep.found() @@ -31,6 +32,12 @@ py.install_sources(blaster, pure: false) py.install_sources(blaster, subdir: 'pure') +install_subdir('subinst', install_dir: py.get_install_dir(pure: false)) + +py2.install_sources(blaster, pure: false) +py2.install_sources(blaster, subdir: 'pure') +install_subdir('subinst', install_dir: py2.get_install_dir(pure: false)) + py3_pkg_dep = dependency('python3', method: 'pkg-config', required : false) if py3_pkg_dep.found() diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/meson_options.txt" 2023-05-30 15:42:56.000000000 +0000 @@ -0,0 +1 @@ +option('python2', type: 'feature', value: 'disabled') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/subinst/printer.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/subinst/printer.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/subinst/printer.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/subinst/printer.py" 2023-05-30 15:42:56.000000000 +0000 @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +print('subinst') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/subinst/submod/printer.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/subinst/submod/printer.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/subinst/submod/printer.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/subinst/submod/printer.py" 2023-05-30 15:42:56.000000000 +0000 @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +print('subinst.submod') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/2 extmodule/test.json" 2021-10-11 16:26:46.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/2 extmodule/test.json" 2023-05-30 15:42:56.000000000 +0000 @@ -7,6 +7,8 @@ { "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_file", "file": "usr/@PYTHON_PLATLIB@/subinst/printer.py" }, + { "type": "python_file", "file": "usr/@PYTHON_PLATLIB@/subinst/submod/printer.py" }, { "type": "python_lib", "file": "usr/lib/tachyon" }, { "type": "py_implib", "file": "usr/lib/tachyon" } ] diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/3 cython/libdir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/3 cython/libdir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/3 cython/libdir/meson.build" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/3 cython/libdir/meson.build" 2023-05-23 15:20:09.000000000 +0000 @@ -1,11 +1,11 @@ pyx_c = custom_target('storer_pyx', output : 'storer_pyx.c', input : 'storer.pyx', - command : [cython, '@INPUT@', '-o', '@OUTPUT@'], + command : [cython, '@INPUT@', '-o', '@OUTPUT@', '-3'], ) slib = py3.extension_module('storer', 'storer.c', pyx_c, - dependencies : py3_dep) +) pydir = meson.current_build_dir() diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/3 cython/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/3 cython/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/3 cython/meson.build" 2021-04-01 21:12:21.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/3 cython/meson.build" 2023-05-23 15:20:09.000000000 +0000 @@ -1,6 +1,6 @@ project('cython', 'c', - default_options : ['warning_level=3']) - + default_options : ['warning_level=3', 'buildtype=release'] +) if meson.backend() != 'ninja' error('MESON_SKIP_TEST: Ninja backend required') endif @@ -10,8 +10,7 @@ error('MESON_SKIP_TEST: Cython3 not found.') endif -py_mod = import('python') -py3 = py_mod.find_installation() +py3 = import('python').find_installation(pure: false) py3_dep = py3.dependency(required: false) if not py3_dep.found() error('MESON_SKIP_TEST: Python library not found.') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/6 failing subproject/subprojects/bar/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/6 failing subproject/subprojects/bar/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/6 failing subproject/subprojects/bar/meson.build" 2021-08-18 11:22:25.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/6 failing subproject/subprojects/bar/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,4 +1,4 @@ project('bar', 'cpp') python = import('python').find_installation('python3') -dependency('nonexistant-dependency') +dependency('nonexistent-dependency') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/7 install path/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/7 install path/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/7 install path/meson.build" 2023-02-01 22:04:45.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/7 install path/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -1,7 +1,8 @@ project('install path', default_options: [ + 'python.bytecompile=-1', 'python.purelibdir=/pure', - 'python.platlibdir=/plat' + 'python.platlibdir=/plat', ] ) @@ -17,4 +18,8 @@ install_data('test.py', install_dir: py_plat.get_install_dir() / 'kw/data') install_data('test.py', install_dir: py_plat.get_install_dir(pure: true) / 'kwrevert/data') +if get_option('backend') == 'none' + subdir('target') +endif + subdir('structured') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/7 install path/target/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/7 install path/target/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/python/7 install path/target/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/python/7 install path/target/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +testcase expect_error('Install-only backend cannot generate target rules, try using `--backend=ninja`.') + import('fs').copyfile('../test.py') +endtestcase diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/1 basic/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/1 basic/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/1 basic/meson.build" 2023-02-01 22:02:50.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/1 basic/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -1,4 +1,4 @@ -project('rustprog', 'rust') +project('rustprog', 'rust', default_options : ['b_ndebug=true']) e = executable('rust-program', 'prog.rs', rust_args : ['-C', 'lto'], # Just a test @@ -7,3 +7,14 @@ test('rusttest', e) subdir('subdir') + +# this should fail due to debug_assert +test( + 'debug_assert_on', + executable( + 'rust-program2', + 'prog.rs', + override_options : ['b_ndebug=false'], + ), + should_fail : true, +) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/1 basic/prog.rs" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/1 basic/prog.rs" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/1 basic/prog.rs" 2021-11-02 19:58:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/1 basic/prog.rs" 2023-05-30 15:42:56.000000000 +0000 @@ -1,4 +1,5 @@ fn main() { let foo = "rust compiler is working"; + debug_assert!(false, "debug_asserts on!"); println!("{}", foo); } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/12 bindgen/dependencies/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/12 bindgen/dependencies/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/12 bindgen/dependencies/meson.build" 2022-12-16 18:51:36.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/12 bindgen/dependencies/meson.build" 2023-04-21 10:42:56.000000000 +0000 @@ -12,6 +12,8 @@ external_dep = static_library( 'external_dep', [external_dep_rs], + # for generated code, do not lint + rust_args: ['-A', 'warnings'], dependencies : dep_zlib.partial_dependency(links : true), ) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/12 bindgen/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/12 bindgen/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/12 bindgen/test.json" 2022-12-10 16:38:19.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/12 bindgen/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/rust/12 bindgen/meson.build:30: WARNING: Project targets '>= 0.63' but uses feature introduced in '1.0.0': include_directories kwarg of type string. Use include_directories('include') instead" + "line": "test cases/rust/12 bindgen/meson.build:27: WARNING: Project targets '>= 0.63' but uses feature introduced in '1.0.0': \"rust.bindgen\" keyword argument \"include_directories\" of type array[str]." } ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/13 external c dependencies/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/13 external c dependencies/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/13 external c dependencies/test.json" 2021-04-27 06:49:45.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/13 external c dependencies/test.json" 2023-05-30 15:42:56.000000000 +0000 @@ -12,7 +12,8 @@ ] }, "exclude": [ - { "static": true, "method": "pkg-config" } + { "static": true, "method": "pkg-config" }, + { "static": true, "method": "cmake" } ] } } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/16 internal c dependencies/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/16 internal c dependencies/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/16 internal c dependencies/meson.build" 2023-02-01 22:03:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/16 internal c dependencies/meson.build" 2023-04-21 10:42:56.000000000 +0000 @@ -3,12 +3,16 @@ test_prog = find_program('test.py') static = static_library('static', 'lib.c', c_args : '-DMODE="static"') -exe = executable('static', 'main.rs', link_with : static) +# Add some -I compiler arguments to make sure they're not passed to the Rust +# compiler when handling the dependency. +static_dep = declare_dependency(link_with : static, compile_args : ['-Idoesnotexist']) +exe = executable('static', 'main.rs', dependencies : static_dep) 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) + shared_dep = declare_dependency(link_with : shared, compile_args : ['-Idoesnotexist']) + exe = executable('shared', 'main.rs', dependencies : shared_dep) test('shared linkage', test_prog, args : [exe, 'This is a shared C library']) endif diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/17 staticlib link staticlib/branch.rs" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/17 staticlib link staticlib/branch.rs" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/17 staticlib link staticlib/branch.rs" 2022-03-09 20:14:44.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/17 staticlib link staticlib/branch.rs" 2023-05-30 15:42:56.000000000 +0000 @@ -1,4 +1,4 @@ #[no_mangle] pub extern "C" fn what_have_we_here() -> i32 { - leaf::HOW_MANY * leaf::HOW_MANY + myleaf::HOW_MANY * myleaf::HOW_MANY } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/17 staticlib link staticlib/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/17 staticlib link staticlib/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/17 staticlib link staticlib/meson.build" 2023-02-01 22:02:59.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/17 staticlib link staticlib/meson.build" 2023-05-30 15:42:56.000000000 +0000 @@ -3,6 +3,6 @@ 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) +branch = static_library('branch', 'branch.rs', link_with: leaf, rust_crate_type : 'staticlib', rust_dependency_map : { 'leaf' : 'myleaf' }, install : true) e = executable('prog', 'prog.c', link_with : branch, install : true) test('linktest', e) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/18 proc-macro/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/18 proc-macro/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/18 proc-macro/meson.build" 2023-02-01 22:03:01.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/18 proc-macro/meson.build" 2023-06-28 14:48:20.000000000 +0000 @@ -13,7 +13,8 @@ main = executable( 'main', 'use.rs', - link_with : pm + link_with : pm, + rust_args : ['-C', 'panic=abort'], ) test('main_test', main) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/19 structured sources/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/19 structured sources/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/19 structured sources/meson.build" 2023-02-01 22:03:06.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/19 structured sources/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -27,7 +27,7 @@ ), ) -# Should not be coppied +# Should not be copied executable( 'no_copy_target', structured_sources( diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/20 rust and cpp/lib.cpp" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/20 rust and cpp/lib.cpp" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/20 rust and cpp/lib.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/20 rust and cpp/lib.cpp" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2023 Intel Corporation + +#include "lib.hpp" + +#include + +namespace { + +uint64_t priv_length(const std::string & str) { + return str.length(); +} + +} + +extern "C" uint64_t lib_length(const char * str) { + return priv_length(str); +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/20 rust and cpp/lib.hpp" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/20 rust and cpp/lib.hpp" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/20 rust and cpp/lib.hpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/20 rust and cpp/lib.hpp" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2023 Intel Corporation + +#include +#include + +extern "C" uint64_t lib_length(const char * str); + diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/20 rust and cpp/main.rs" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/20 rust and cpp/main.rs" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/20 rust and cpp/main.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/20 rust and cpp/main.rs" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2023 Intel Corporation + +use std::ffi::CString; +use std::os::raw::c_char; + +extern "C" { + fn lib_length(s: *const c_char) -> u64; +} + +fn main() { + let len: u64; + unsafe { + let c_str = CString::new("Hello, world!").unwrap(); + len = lib_length(c_str.as_ptr()); + } + + std::process::exit(if len == 13 { 0 } else { 1 }) +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/20 rust and cpp/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/20 rust and cpp/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/20 rust and cpp/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/20 rust and cpp/meson.build" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2023 Intel Corporation + +project( + 'Rust and C++', + 'rust', 'cpp', + default_options : ['cpp_std=c++14'], + meson_version : '>= 1.2.0', +) + +cpplib = static_library('cpp', 'lib.cpp') +exe = executable('main', 'main.rs', link_with : cpplib) + +test('main', exe) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/20 rust and cpp/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/20 rust and cpp/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/20 rust and cpp/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/20 rust and cpp/test.json" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "matrix": { + "options": { + "b_vscrt": [ + { "val": "none" }, + { "val": "mdd" }, + { "val": "md" }, + { "val": "mtd" }, + { "val": "mt" }, + { "val": "from_buildtype" }, + { "val": "static_from_buildtype" } + ] + } + } +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/5 polyglot static/clib.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/5 polyglot static/clib.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/5 polyglot static/clib.c" 2023-02-23 22:07:04.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/5 polyglot static/clib.c" 2023-07-21 20:36:13.000000000 +0000 @@ -1,6 +1,7 @@ #include +#include -void hello_from_rust(void); +int32_t hello_from_rust(const int32_t a, const int32_t b); static void hello_from_c(void) { printf("Hello from C!\n"); @@ -8,5 +9,6 @@ void hello_from_both(void) { hello_from_c(); - hello_from_rust(); + if (hello_from_rust(2, 3) == 5) + printf("Hello from Rust!\n"); } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/5 polyglot static/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/5 polyglot static/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/5 polyglot static/meson.build" 2023-02-23 22:07:04.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/5 polyglot static/meson.build" 2023-08-07 22:54:24.000000000 +0000 @@ -1,18 +1,26 @@ project('static rust and c polyglot executable', 'c', 'rust') -deps = [ - meson.get_compiler('c').find_library('dl', required: false), - meson.get_compiler('c').find_library('m', required: false), - dependency('threads'), -] +r = static_library('stuff', 'stuff.rs', rust_crate_type : 'staticlib') -extra_winlibs = meson.get_compiler('c').get_id() in ['msvc', 'clang-cl'] ? ['userenv.lib', 'ws2_32.lib', 'bcrypt.lib'] : [] +# clib is installed static library and stuff is not installed. That means that +# to be usable clib must link_whole stuff. Meson automatically promote to link_whole, +# as it would do with C libraries, but then cannot extract objects from stuff and +# thus should error out. +# FIXME: We should support this use-case in the future. +testcase expect_error('Cannot link_whole a custom or Rust target \'stuff\' into a static library \'clib\'. Instead, pass individual object files with the "objects:" keyword argument if possible. Meson had to promote link to link_whole because \'clib\' is installed but not \'stuff\', and thus has to include objects from \'stuff\' to be usable.') + l = static_library('clib', 'clib.c', link_with : r, install : true) +endtestcase + +l = static_library('clib', 'clib.c', link_with : r) -r = static_library('stuff', 'stuff.rs', rust_crate_type : 'staticlib') -l = static_library('clib', 'clib.c', link_with : r, install : true) e = executable('prog', 'prog.c', - dependencies: deps, link_with : l, - link_args: extra_winlibs, install : true) test('polyglottest', e) + +# Create a version that has overflow-checks on, then run a test to ensure that +# the overflow-checks is larger than the other version by some ammount +r2 = static_library('stuff2', 'stuff.rs', rust_crate_type : 'staticlib', rust_args : ['-C', 'overflow-checks=on']) +l2 = static_library('clib2', 'clib.c') +e2 = executable('prog2', 'prog.c', link_with : [r2, l2]) +test('overflow-checks', find_program('overflow_size_checks.py'), args : [e, e2]) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/5 polyglot static/overflow_size_checks.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/5 polyglot static/overflow_size_checks.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/5 polyglot static/overflow_size_checks.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/5 polyglot static/overflow_size_checks.py" 2023-07-21 20:36:13.000000000 +0000 @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2023 Intel Corporation + +from __future__ import annotations +import argparse +import os +import typing as T + +if T.TYPE_CHECKING: + class Arguments(T.Protocol): + checks_off: str + checks_on: str + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument('checks_off') + parser.add_argument('checks_on') + args: Arguments = parser.parse_args() + + off = os.stat(args.checks_off).st_size + on = os.stat(args.checks_on).st_size + + assert on > off, f'Expected binary built with overflow-checks to be bigger, but it was smaller. with: "{on}"B, without: "{off}"B' + + +if __name__ == "__main__": + main() diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/5 polyglot static/stuff.rs" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/5 polyglot static/stuff.rs" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/5 polyglot static/stuff.rs" 2023-02-23 22:07:04.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/5 polyglot static/stuff.rs" 2023-07-21 20:36:13.000000000 +0000 @@ -1,6 +1,4 @@ -#![crate_name = "stuff"] - #[no_mangle] -pub extern "C" fn hello_from_rust() { - println!("Hello from Rust!"); +pub extern "C" fn hello_from_rust(a: i32, b: i32) -> i32 { + a + b } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/5 polyglot static/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/5 polyglot static/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/5 polyglot static/test.json" 2023-02-23 22:07:04.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/5 polyglot static/test.json" 2023-07-05 15:40:06.000000000 +0000 @@ -1,7 +1,6 @@ { "installed": [ {"type": "exe", "file": "usr/bin/prog"}, - {"type": "pdb", "file": "usr/bin/prog"}, - {"type": "file", "file": "usr/lib/libclib.a"} + {"type": "pdb", "file": "usr/bin/prog"} ] } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/9 unit tests/helper.rs" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/9 unit tests/helper.rs" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/9 unit tests/helper.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/9 unit tests/helper.rs" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,3 @@ +pub fn subtract(a: i32, b: i32) -> i32 { + a - b +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/9 unit tests/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/9 unit tests/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/9 unit tests/meson.build" 2023-02-01 22:02:43.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/9 unit tests/meson.build" 2023-06-28 14:48:20.000000000 +0000 @@ -31,13 +31,17 @@ suite : ['foo'], ) -exe = executable('rust_exe', ['test2.rs', 'test.rs']) +exe = executable('rust_exe', ['test2.rs', 'test.rs'], build_by_default : false) rust = import('unstable-rust') rust.test('rust_test_from_exe', exe, should_fail : true) -lib = static_library('rust_static', ['test.rs']) +lib = static_library('rust_static', ['test.rs'], build_by_default : false) rust.test('rust_test_from_static', lib, args: ['--skip', 'test_add_intentional_fail']) -lib = shared_library('rust_shared', ['test.rs']) +lib = shared_library('rust_shared', ['test.rs'], build_by_default : false) rust.test('rust_test_from_shared', lib, args: ['--skip', 'test_add_intentional_fail']) + +helper = static_library('helper', 'helper.rs') +lib = static_library('rust_link_with', 'test3.rs', build_by_default : false) +rust.test('rust_test_link_with', lib, link_with : helper, rust_args : ['--cfg', 'broken="false"']) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/9 unit tests/test2.rs" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/9 unit tests/test2.rs" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/9 unit tests/test2.rs" 2021-04-01 21:13:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/9 unit tests/test2.rs" 2023-05-23 15:20:02.000000000 +0000 @@ -3,8 +3,8 @@ 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 first = args[1].parse::().expect("Invalid value for first argument."); + let second = args[2].parse::().expect("Invalid value for second argument."); let new = test::add(first, second); println!("New value: {}", new); diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/9 unit tests/test3.rs" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/9 unit tests/test3.rs" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/rust/9 unit tests/test3.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/rust/9 unit tests/test3.rs" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,23 @@ +pub fn add(a: i32, b: i32) -> i32 { + a + b +} + +#[cfg(test)] +mod tests { + extern crate helper; + + use super::*; + + // This is an intentinally broken test that should be turned off by extra rust arguments + #[cfg(not(broken = "false"))] + #[test] + fn test_broken() { + assert_eq!(0, 5); + } + + #[test] + fn test_add_sub() { + let x = helper::subtract(6, 5); + assert_eq!(add(x, 5), 6); + } +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/100 custom target name/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/100 custom target name/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/100 custom target name/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/100 custom target name/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,14 @@ +project('custom target name', 'c') + +python = find_program('python3') + +# 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/100 custom target name/subdir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/100 custom target name/subdir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/100 custom target name/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/100 custom target name/subdir/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/100 relative find program/foo.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/100 relative find program/foo.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/100 relative find program/foo.py" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/100 relative find program/foo.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/usr/bin/env python3 - -exit(0) \ No newline at end of file diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/100 relative find program/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/100 relative find program/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/100 relative find program/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/100 relative find program/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('relative find program') - -subdir('subdir') \ No newline at end of file diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/100 relative find program/subdir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/100 relative find program/subdir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/100 relative find program/subdir/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/100 relative find program/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -prog = find_program('./foo.py', required: false) -assert(not prog.found()) \ No newline at end of file diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/101 relative find program/foo.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/101 relative find program/foo.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/101 relative find program/foo.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/101 relative find program/foo.py" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +exit(0) \ No newline at end of file diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/101 relative find program/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/101 relative find program/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/101 relative find program/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/101 relative find program/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +project('relative find program') + +subdir('subdir') \ No newline at end of file diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/101 relative find program/subdir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/101 relative find program/subdir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/101 relative find program/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/101 relative find program/subdir/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/101 rlib linkage/lib2.rs" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/101 rlib linkage/lib2.rs" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/101 rlib linkage/lib2.rs" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/101 rlib linkage/lib2.rs" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -use lib; - -pub fn fun() { - lib::fun(); -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/101 rlib linkage/main.rs" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/101 rlib linkage/main.rs" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/101 rlib linkage/main.rs" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/101 rlib linkage/main.rs" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -use lib2::fun; - -fn main() { - fun(); -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/101 rlib linkage/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/101 rlib linkage/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/101 rlib linkage/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/101 rlib linkage/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/102 python without pkgconfig/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/102 python without pkgconfig/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/102 python without pkgconfig/meson.build" 2022-12-10 16:38:19.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/102 python without pkgconfig/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('python without pkgconfig', 'c') - -# This unit test is ran with PKG_CONFIG=notfound -import('python').find_installation().dependency() diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/102 rlib linkage/lib2.rs" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/102 rlib linkage/lib2.rs" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/102 rlib linkage/lib2.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/102 rlib linkage/lib2.rs" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,5 @@ +use lib; + +pub fn fun() { + lib::fun(); +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/102 rlib linkage/main.rs" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/102 rlib linkage/main.rs" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/102 rlib linkage/main.rs" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/102 rlib linkage/main.rs" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,5 @@ +use lib2::fun; + +fn main() { + fun(); +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/102 rlib linkage/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/102 rlib linkage/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/102 rlib linkage/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/102 rlib linkage/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/103 python without pkgconfig/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/103 python without pkgconfig/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/103 python without pkgconfig/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/103 python without pkgconfig/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,4 @@ +project('python without pkgconfig', 'c') + +# This unit test is ran with PKG_CONFIG=notfound +import('python').find_installation().dependency() diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/103 strip/lib.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/103 strip/lib.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/103 strip/lib.c" 2022-11-01 19:00:11.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/103 strip/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#include - -void func(void){ fprintf(stderr, "Test 1 2 3\n"); } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/103 strip/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/103 strip/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/103 strip/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/103 strip/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('strip', 'c') - -shared_library('a', 'lib.c', install: true) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/104 debug function/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/104 debug function/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/104 debug function/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/104 debug function/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('debug function', 'c') - -debug('This is an example debug output, should only end up in debug log') -debug('Test logging other things', true, 1, ['Array'], {'Key' : 'Value'}) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/104 strip/lib.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/104 strip/lib.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/104 strip/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/104 strip/lib.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +#include + +void func(void){ fprintf(stderr, "Test 1 2 3\n"); } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/104 strip/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/104 strip/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/104 strip/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/104 strip/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +project('strip', 'c') + +shared_library('a', 'lib.c', install: true) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/105 debug function/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/105 debug function/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/105 debug function/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/105 debug function/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,4 @@ +project('debug function', 'c') + +debug('This is an example debug output, should only end up in debug log') +debug('Test logging other things', true, 1, ['Array'], {'Key' : 'Value'}) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/105 pkgconfig relocatable with absolute path/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/105 pkgconfig relocatable with absolute path/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/105 pkgconfig relocatable with absolute path/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/105 pkgconfig relocatable with absolute path/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -project( - 'pkgconfig-relocatable-with-absolute-path', - version : '1.0', - default_options: [ - 'pkgconfig.relocatable=true', - ]) - -pkgg = import('pkgconfig') - -pkgg.generate( - name : 'libsimple', - version : '1.0', - description : 'A simple pkgconfig.', - install_dir: get_option('prefix')/'share/misc/pkgconfig', -) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 pkgconfig relocatable with absolute path/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 pkgconfig relocatable with absolute path/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 pkgconfig relocatable with absolute path/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 pkgconfig relocatable with absolute path/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,15 @@ +project( + 'pkgconfig-relocatable-with-absolute-path', + version : '1.0', + default_options: [ + 'pkgconfig.relocatable=true', + ]) + +pkgg = import('pkgconfig') + +pkgg.generate( + name : 'libsimple', + version : '1.0', + description : 'A simple pkgconfig.', + install_dir: get_option('prefix')/'share/misc/pkgconfig', +) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/cp.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/cp.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/cp.py" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/cp.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -from sys import argv -from shutil import copy - -copy(argv[1], argv[2]) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/main.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/main.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/main.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/main.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -extern int foo(void); - -int main(void) -{ - return foo(); -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -project('foo', 'c') - -symlinked_subproject = subproject('symlinked_subproject').get_variable('dep') - -executable('foo', - sources : 'main.c', - dependencies : symlinked_subproject -) - -custom_target( - input : symlinked_subproject.get_variable('datadir') / 'datafile', - output : 'datafile_copy', - command : [find_program('cp.py'), '@INPUT@', '@OUTPUT@'], - build_always : true -) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/symlinked_subproject/datadir/datafile" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/symlinked_subproject/datadir/datafile" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/symlinked_subproject/datadir/datafile" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/symlinked_subproject/datadir/datafile" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -hello meson diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/symlinked_subproject/datadir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/symlinked_subproject/datadir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/symlinked_subproject/datadir/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/symlinked_subproject/datadir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -install_data('datafile') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/symlinked_subproject/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/symlinked_subproject/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/symlinked_subproject/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/symlinked_subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -project('symlinked_subproject', 'c', version : '1.0.0') - -dep = declare_dependency( - sources : 'src.c', - variables : { - 'datadir': meson.current_source_dir() / 'datadir' - } -) - -subdir('datadir') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/symlinked_subproject/src.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/symlinked_subproject/src.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/106 subproject symlink/symlinked_subproject/src.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/106 subproject symlink/symlinked_subproject/src.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -int foo(void) -{ - return 0; -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 new subproject on reconfigure/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 new subproject on reconfigure/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 new subproject on reconfigure/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 new subproject on reconfigure/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('New subproject on reconfigure') - -subproject('foo', required: get_option('foo')) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 new subproject on reconfigure/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 new subproject on reconfigure/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 new subproject on reconfigure/meson_options.txt" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 new subproject on reconfigure/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -option('foo', type: 'feature', value: 'disabled') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 new subproject on reconfigure/subprojects/foo/foo.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 new subproject on reconfigure/subprojects/foo/foo.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 new subproject on reconfigure/subprojects/foo/foo.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 new subproject on reconfigure/subprojects/foo/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -void foo(void); -void foo(void) {} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 new subproject on reconfigure/subprojects/foo/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 new subproject on reconfigure/subprojects/foo/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 new subproject on reconfigure/subprojects/foo/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 new subproject on reconfigure/subprojects/foo/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -project('foo', 'c') - -# Ensure that builtin options have been initialised. -assert(get_option('default_library') == 'shared') - -# This uses default_library option internally and used to cause a crash: -# https://github.com/mesonbuild/meson/issues/10225. -library('foo', 'foo.c') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/cp.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/cp.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/cp.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/cp.py" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +from sys import argv +from shutil import copy + +copy(argv[1], argv[2]) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/main.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/main.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/main.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,6 @@ +extern int foo(void); + +int main(void) +{ + return foo(); +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,15 @@ +project('foo', 'c') + +symlinked_subproject = subproject('symlinked_subproject').get_variable('dep') + +executable('foo', + sources : 'main.c', + dependencies : symlinked_subproject +) + +custom_target( + input : symlinked_subproject.get_variable('datadir') / 'datafile', + output : 'datafile_copy', + command : [find_program('cp.py'), '@INPUT@', '@OUTPUT@'], + build_always : true +) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/symlinked_subproject/datadir/datafile" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/symlinked_subproject/datadir/datafile" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/symlinked_subproject/datadir/datafile" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/symlinked_subproject/datadir/datafile" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +hello meson diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/symlinked_subproject/datadir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/symlinked_subproject/datadir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/symlinked_subproject/datadir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/symlinked_subproject/datadir/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +install_data('datafile') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/symlinked_subproject/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/symlinked_subproject/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/symlinked_subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/symlinked_subproject/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,10 @@ +project('symlinked_subproject', 'c', version : '1.0.0') + +dep = declare_dependency( + sources : 'src.c', + variables : { + 'datadir': meson.current_source_dir() / 'datadir' + } +) + +subdir('datadir') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/symlinked_subproject/src.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/symlinked_subproject/src.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/107 subproject symlink/symlinked_subproject/src.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/107 subproject symlink/symlinked_subproject/src.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,4 @@ +int foo(void) +{ + return 0; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/108 configure same noop/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/108 configure same noop/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/108 configure same noop/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/108 configure same noop/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -project('configure same noop test') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/108 configure same noop/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/108 configure same noop/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/108 configure same noop/meson_options.txt" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/108 configure same noop/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -option( - 'opt', - type : 'string', - value: '', -) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/108 new subproject on reconfigure/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/108 new subproject on reconfigure/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/108 new subproject on reconfigure/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/108 new subproject on reconfigure/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +project('New subproject on reconfigure') + +subproject('foo', required: get_option('foo')) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/108 new subproject on reconfigure/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/108 new subproject on reconfigure/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/108 new subproject on reconfigure/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/108 new subproject on reconfigure/meson_options.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +option('foo', type: 'feature', value: 'disabled') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/108 new subproject on reconfigure/subprojects/foo/foo.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/108 new subproject on reconfigure/subprojects/foo/foo.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/108 new subproject on reconfigure/subprojects/foo/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/108 new subproject on reconfigure/subprojects/foo/foo.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,2 @@ +void foo(void); +void foo(void) {} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/108 new subproject on reconfigure/subprojects/foo/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/108 new subproject on reconfigure/subprojects/foo/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/108 new subproject on reconfigure/subprojects/foo/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/108 new subproject on reconfigure/subprojects/foo/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,8 @@ +project('foo', 'c') + +# Ensure that builtin options have been initialised. +assert(get_option('default_library') == 'shared') + +# This uses default_library option internally and used to cause a crash: +# https://github.com/mesonbuild/meson/issues/10225. +library('foo', 'foo.c') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/109 configure same noop/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/109 configure same noop/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/109 configure same noop/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/109 configure same noop/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +project('configure same noop test') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/109 configure same noop/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/109 configure same noop/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/109 configure same noop/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/109 configure same noop/meson_options.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,6 @@ +option('string', type : 'string', value: '') +option('boolean', type : 'boolean', value: false) +option('combo', type : 'combo', choices : ['one', 'two', 'three'], value: 'one') +option('integer', type : 'integer', value: 5) +option('array', type : 'array', value: ['one', 'two']) +option('feature', type : 'feature', value : 'enabled') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/109 freeze/freeze.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/109 freeze/freeze.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/109 freeze/freeze.c" 2022-11-21 19:54:10.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/109 freeze/freeze.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -#include -#include -#include -#include - -static void do_nothing(int signo, siginfo_t *info, void *context) { -} - -int main(int argc, char **argv) { - struct sigaction sa; - memset(&sa, 0, sizeof(struct sigaction)); - sa.sa_sigaction = do_nothing; - if (sigaction(SIGTERM, &sa, NULL) == -1) { - printf("Could not set up signal handler.\n"); - return 1; - } - printf("Freezing forever.\n"); - while(1) { - } - return 0; -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/109 freeze/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/109 freeze/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/109 freeze/meson.build" 2022-11-21 19:54:10.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/109 freeze/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -project('freeze', 'c') - -e = executable('freeze', 'freeze.c') -test('freeze', e, timeout: 1) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/110 classpath/com/mesonbuild/Simple.java" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/110 classpath/com/mesonbuild/Simple.java" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/110 classpath/com/mesonbuild/Simple.java" 2022-12-16 18:51:36.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/110 classpath/com/mesonbuild/Simple.java" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -package com.mesonbuild; - -class Simple { - public static void main(String [] args) { - System.out.println("Java is working.\n"); - } -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/110 classpath/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/110 classpath/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/110 classpath/meson.build" 2022-12-16 18:51:36.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/110 classpath/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -project('simplejava', 'java') - -one = jar('one', 'com/mesonbuild/Simple.java', - main_class : 'com.mesonbuild.Simple', - install : true, - install_dir : get_option('bindir'), -) - -two = jar('two', 'com/mesonbuild/Simple.java', - main_class : 'com.mesonbuild.Simple', - install : true, - install_dir : get_option('bindir'), - link_with : one, -) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/110 freeze/freeze.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/110 freeze/freeze.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/110 freeze/freeze.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/110 freeze/freeze.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +static void do_nothing(int signo, siginfo_t *info, void *context) { +} + +int main(int argc, char **argv) { + struct sigaction sa; + memset(&sa, 0, sizeof(struct sigaction)); + sa.sa_sigaction = do_nothing; + if (sigaction(SIGTERM, &sa, NULL) == -1) { + printf("Could not set up signal handler.\n"); + return 1; + } + printf("Freezing forever.\n"); + while(1) { + } + return 0; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/110 freeze/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/110 freeze/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/110 freeze/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/110 freeze/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,4 @@ +project('freeze', 'c') + +e = executable('freeze', 'freeze.c') +test('freeze', e, timeout: 1) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/110 replace unencodable xml chars/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/110 replace unencodable xml chars/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/110 replace unencodable xml chars/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/110 replace unencodable xml chars/meson.build" 2023-07-21 20:36:13.000000000 +0000 @@ -0,0 +1,4 @@ +project('replace unencodable xml chars') + +test_script = find_program('script.py') +test('main', test_script) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/110 replace unencodable xml chars/script.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/110 replace unencodable xml chars/script.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/110 replace unencodable xml chars/script.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/110 replace unencodable xml chars/script.py" 2023-07-21 20:36:13.000000000 +0000 @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +import sys + +# Print base string(\nHello Meson\n) to see valid chars are not replaced +print('\n\x48\x65\x6c\x6c\x6f\x20\x4d\x65\x73\x6f\x6e\n') +# Print invalid input from all known unencodable chars +print( + '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f\x10\x11' + '\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f') + +# Cover for potential encoding issues +try: + print( + '\x80\x81\x82\x83\x84\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f' + '\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e' + '\x9f\ufdd0\ufdd1\ufdd2\ufdd3\ufdd4\ufdd5\ufdd6\ufdd7\ufdd8' + '\ufdd9\ufdda\ufddb\ufddc\ufddd\ufdde\ufddf\ufde0\ufde1' + '\ufde2\ufde3\ufde4\ufde5\ufde6\ufde7\ufde8\ufde9\ufdea' + '\ufdeb\ufdec\ufded\ufdee\ufdef\ufffe\uffff') +except: + pass + +# Cover for potential encoding issues +try: + if sys.maxunicode >= 0x10000: + print( + '\U0001fffe\U0001ffff\U0002fffe\U0002ffff' + '\U0003fffe\U0003ffff\U0004fffe\U0004ffff' + '\U0005fffe\U0005ffff\U0006fffe\U0006ffff' + '\U0007fffe\U0007ffff\U0008fffe\U0008ffff' + '\U0009fffe\U0009ffff\U000afffe\U000affff' + '\U000bfffe\U000bffff\U000cfffe\U000cffff' + '\U000dfffe\U000dffff\U000efffe\U000effff' + '\U000ffffe\U000fffff\U0010fffe\U0010ffff') +except: + pass diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/111 classpath/com/mesonbuild/Simple.java" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/111 classpath/com/mesonbuild/Simple.java" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/111 classpath/com/mesonbuild/Simple.java" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/111 classpath/com/mesonbuild/Simple.java" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,7 @@ +package com.mesonbuild; + +class Simple { + public static void main(String [] args) { + System.out.println("Java is working.\n"); + } +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/111 classpath/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/111 classpath/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/111 classpath/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/111 classpath/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,14 @@ +project('simplejava', 'java') + +one = jar('one', 'com/mesonbuild/Simple.java', + main_class : 'com.mesonbuild.Simple', + install : true, + install_dir : get_option('bindir'), +) + +two = jar('two', 'com/mesonbuild/Simple.java', + main_class : 'com.mesonbuild.Simple', + install : true, + install_dir : get_option('bindir'), + link_with : one, +) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/112 list build options/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/112 list build options/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/112 list build options/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/112 list build options/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,6 @@ +project('feature user option', 'c') + +feature_opts = get_option('auto_features') +optional_opt = get_option('optional') + +message('Build options:', meson.build_options()) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/112 list build options/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/112 list build options/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/112 list build options/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/112 list build options/meson_options.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +option('optional', type : 'feature', value : 'auto', description : 'An optional feature') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/113 complex link cases/main.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/113 complex link cases/main.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/113 complex link cases/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/113 complex link cases/main.c" 2023-07-05 15:40:06.000000000 +0000 @@ -0,0 +1,6 @@ +int s3(void); + +int main(int argc, char *argv[]) +{ + return s3(); +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/113 complex link cases/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/113 complex link cases/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/113 complex link cases/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/113 complex link cases/meson.build" 2023-08-07 22:54:24.000000000 +0000 @@ -0,0 +1,111 @@ +project('complex link cases', 'c') + +cc = meson.get_compiler('c') + +# In all tests, e1 uses s3 which uses s2 which uses s1. + +# Executable links with s3 and s1 but not s2 because it is included in s3. +s1 = static_library('t1-s1', 's1.c') +s2 = static_library('t1-s2', 's2.c', link_with: s1) +s3 = static_library('t1-s3', 's3.c', link_whole: s2) +e = executable('t1-e1', 'main.c', link_with: s3) + +# s3 is installed but not s1 so it has to include s1 too. +# Executable links only s3 because it contains s1 and s2. +s1 = static_library('t2-s1', 's1.c') +s2 = static_library('t2-s2', 's2.c', link_with: s1) +s3 = static_library('t2-s3', 's3.c', link_whole: s2, install: true) +e = executable('t2-e1', 'main.c', link_with: s3) + +# Executable needs to link with s3 only +s1 = static_library('t3-s1', 's1.c') +s2 = static_library('t3-s2', 's2.c', link_with: s1) +s3 = shared_library('t3-s3', 's3.c', link_with: s2) +e = executable('t3-e1', 'main.c', link_with: s3) + +# Executable needs to link with s3 and s2 +s1 = static_library('t4-s1', 's1.c') +s2 = shared_library('t4-s2', 's2.c', link_with: s1) +s3 = static_library('t4-s3', 's3.c', link_with: s2) +e = executable('t4-e1', 'main.c', link_with: s3) + +# Executable needs to link with s3 and s1 +s1 = shared_library('t5-s1', 's1.c') +s2 = static_library('t5-s2', 's2.c', link_with: s1) +s3 = static_library('t5-s3', 's3.c', link_with: s2, install: true) +e = executable('t5-e1', 'main.c', link_with: s3) + +# Executable needs to link with s3 and s2 +s1 = static_library('t6-s1', 's1.c') +s2 = static_library('t6-s2', 's2.c', link_with: s1, install: true) +s3 = static_library('t6-s3', 's3.c', link_with: s2, install: true) +e = executable('t6-e1', 'main.c', link_with: s3) + +# Regression test: s1 gets promoted to link_whole and that used to make all other +# libraries in the list (s2) to be ignored. +# Executable only needs to link with s3. +# See https://github.com/mesonbuild/meson/issues/11956. +s1 = static_library('t7-s1', 's1.c') +s2 = static_library('t7-s2', 's2.c') +s3 = static_library('t7-s3', 's3.c', link_with: [s1, s2], install: true) +e = executable('t7-e1', 'main.c', link_with: s3) + +# Regression test: s3 should come last in the linker command. This seems to be +# required for at least backward compatibility reasons: +# https://github.com/mesonbuild/meson/pull/11957#issuecomment-1629243208 +s1 = static_library('t8-s1', 's1.c') +s2 = static_library('t8-s2', 's2.c') +s3 = static_library('t8-s3', 's3.c') +e = executable('t8-e1', 'main.c', + link_with: [s1, s2], + dependencies: declare_dependency(link_with: s3), +) + +if cc.get_argument_syntax() == 'gcc' + # s1 is an internal static library, using custom target. + s1_o = custom_target( + input: 's1.c', + output: 's1.c.o', + command: [cc.cmd_array(), '-c', '-o', '@OUTPUT@', '@INPUT@'] + ) + s1 = custom_target( + output: 'libt9-s1.a', + command: ['ar', 'rcs', '@OUTPUT@', s1_o], + ) + + # Executable needs to link with s1, s2 and s3. + s2 = static_library('t9-s2', 's2.c', link_with: s1) + s3 = static_library('t9-s3', 's3.c', link_with: s2) + e = executable('t9-e1', 'main.c', link_with: s3) + + # s2 cannot be installed because s1 is not being installed and Meson cannot + # extract object files from the custom target. + testcase expect_error('Cannot link_whole a custom or Rust target \'libt9-s1.a\' into a static library \'t10-s2\'. Instead, pass individual object files with the "objects:" keyword argument if possible. Meson had to promote link to link_whole because \'t10-s2\' is installed but not \'libt9-s1.a\', and thus has to include objects from \'libt9-s1.a\' to be usable.') + s2 = static_library('t10-s2', 's2.c', link_with: s1, install: true) + endtestcase + + # s3 cannot be installed because s1 is not being installed and Meson cannot + # extract object files from the custom target. + testcase expect_error('Cannot link_whole a custom or Rust target \'libt9-s1.a\' into a static library \'t11-s3\'. Instead, pass individual object files with the "objects:" keyword argument if possible. Meson had to promote link to link_whole because \'t11-s3\' is installed but not \'libt9-s1.a\', and thus has to include objects from \'libt9-s1.a\' to be usable.') + s2 = static_library('t11-s2', 's2.c', link_with: s1) + s3 = static_library('t11-s3', 's3.c', link_with: s2, install: true) + endtestcase + + # s1 is an installed static library, using custom target. + s1 = custom_target( + output: 'libt12-s1.a', + command: ['ar', 'rcs', '@OUTPUT@', s1_o], + install: true, + install_dir: get_option('libdir'), + ) + + # Executable needs to link with s1, s2 and s3. + s2 = static_library('t12-s2', 's2.c', link_with: s1, install: true) + s3 = static_library('t12-s3', 's3.c', link_with: s2) + e = executable('t12-e1', 'main.c', link_with: s3) + + # Executable links with s3 and s1 but not s2 because it is included in s3. + s2 = static_library('t13-s2', 's2.c', link_with: s1) + s3 = static_library('t13-s3', 's3.c', link_with: s2, install: true) + e = executable('t13-e1', 'main.c', link_with: s3) +endif diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/113 complex link cases/s1.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/113 complex link cases/s1.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/113 complex link cases/s1.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/113 complex link cases/s1.c" 2023-07-05 15:40:06.000000000 +0000 @@ -0,0 +1,3 @@ +int s1(void) { + return 1; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/113 complex link cases/s2.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/113 complex link cases/s2.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/113 complex link cases/s2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/113 complex link cases/s2.c" 2023-07-05 15:40:06.000000000 +0000 @@ -0,0 +1,5 @@ +int s1(void); + +int s2(void) { + return s1() + 1; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/113 complex link cases/s3.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/113 complex link cases/s3.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/113 complex link cases/s3.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/113 complex link cases/s3.c" 2023-07-05 15:40:06.000000000 +0000 @@ -0,0 +1,5 @@ +int s2(void); + +int s3(void) { + return s2() + 1; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/114 empty project/expected_mods.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/114 empty project/expected_mods.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/114 empty project/expected_mods.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/114 empty project/expected_mods.json" 2023-07-05 20:56:32.000000000 +0000 @@ -0,0 +1,242 @@ +{ + "stdlib": { + "modules": [ + "__future__", + "__main__", + "_abc", + "_ast", + "_bisect", + "_blake2", + "_bz2", + "_codecs", + "_collections", + "_collections_abc", + "_compat_pickle", + "_compression", + "_datetime", + "_frozen_importlib", + "_frozen_importlib_external", + "_functools", + "_hashlib", + "_imp", + "_io", + "_json", + "_locale", + "_lsprof", + "_lzma", + "_opcode", + "_operator", + "_pickle", + "_posixsubprocess", + "_random", + "_sha512", + "_signal", + "_sitebuiltins", + "_socket", + "_sre", + "_ssl", + "_stat", + "_string", + "_struct", + "_thread", + "_uuid", + "_warnings", + "_weakref", + "_weakrefset", + "abc", + "argparse", + "array", + "ast", + "base64", + "binascii", + "bisect", + "builtins", + "bz2", + "cProfile", + "calendar", + "codecs", + "collections", + "collections.abc", + "configparser", + "contextlib", + "copy", + "copyreg", + "dataclasses", + "datetime", + "dis", + "email", + "email._encoded_words", + "email._parseaddr", + "email._policybase", + "email.base64mime", + "email.charset", + "email.encoders", + "email.errors", + "email.feedparser", + "email.header", + "email.iterators", + "email.message", + "email.parser", + "email.quoprimime", + "email.utils", + "encodings", + "encodings.aliases", + "encodings.utf_8", + "enum", + "errno", + "fcntl", + "fnmatch", + "functools", + "genericpath", + "gettext", + "glob", + "hashlib", + "http", + "http.client", + "importlib", + "importlib._bootstrap", + "importlib._bootstrap_external", + "importlib.machinery", + "inspect", + "io", + "itertools", + "json", + "json.decoder", + "json.encoder", + "json.scanner", + "keyword", + "linecache", + "locale", + "lzma", + "marshal", + "math", + "netrc", + "ntpath", + "opcode", + "operator", + "os", + "os.path", + "pathlib", + "pickle", + "platform", + "posix", + "posixpath", + "profile", + "quopri", + "random", + "re", + "reprlib", + "select", + "selectors", + "shlex", + "shutil", + "signal", + "site", + "socket", + "sre_compile", + "sre_constants", + "sre_parse", + "ssl", + "stat", + "string", + "struct", + "subprocess", + "sys", + "tempfile", + "textwrap", + "threading", + "time", + "token", + "tokenize", + "types", + "typing", + "typing.io", + "typing.re", + "urllib", + "urllib.error", + "urllib.parse", + "urllib.request", + "urllib.response", + "uu", + "uuid", + "warnings", + "weakref", + "zipimport", + "zlib" + ], + "count": 162 + }, + "meson": { + "modules": [ + "mesonbuild", + "mesonbuild._pathlib", + "mesonbuild.arglist", + "mesonbuild.ast", + "mesonbuild.ast.interpreter", + "mesonbuild.ast.introspection", + "mesonbuild.ast.postprocess", + "mesonbuild.ast.printer", + "mesonbuild.ast.visitor", + "mesonbuild.backend", + "mesonbuild.backend.backends", + "mesonbuild.backend.ninjabackend", + "mesonbuild.build", + "mesonbuild.compilers", + "mesonbuild.compilers.compilers", + "mesonbuild.compilers.detect", + "mesonbuild.coredata", + "mesonbuild.dependencies", + "mesonbuild.dependencies.base", + "mesonbuild.dependencies.detect", + "mesonbuild.depfile", + "mesonbuild.envconfig", + "mesonbuild.environment", + "mesonbuild.interpreter", + "mesonbuild.interpreter.compiler", + "mesonbuild.interpreter.dependencyfallbacks", + "mesonbuild.interpreter.interpreter", + "mesonbuild.interpreter.interpreterobjects", + "mesonbuild.interpreter.mesonmain", + "mesonbuild.interpreter.primitives", + "mesonbuild.interpreter.primitives.array", + "mesonbuild.interpreter.primitives.boolean", + "mesonbuild.interpreter.primitives.dict", + "mesonbuild.interpreter.primitives.integer", + "mesonbuild.interpreter.primitives.range", + "mesonbuild.interpreter.primitives.string", + "mesonbuild.interpreter.type_checking", + "mesonbuild.interpreterbase", + "mesonbuild.interpreterbase._unholder", + "mesonbuild.interpreterbase.baseobjects", + "mesonbuild.interpreterbase.decorators", + "mesonbuild.interpreterbase.disabler", + "mesonbuild.interpreterbase.exceptions", + "mesonbuild.interpreterbase.helpers", + "mesonbuild.interpreterbase.interpreterbase", + "mesonbuild.interpreterbase.operator", + "mesonbuild.linkers", + "mesonbuild.linkers.base", + "mesonbuild.linkers.detect", + "mesonbuild.mesonlib", + "mesonbuild.mesonmain", + "mesonbuild.mintro", + "mesonbuild.mlog", + "mesonbuild.modules", + "mesonbuild.mparser", + "mesonbuild.msetup", + "mesonbuild.optinterpreter", + "mesonbuild.programs", + "mesonbuild.scripts", + "mesonbuild.scripts.meson_exe", + "mesonbuild.utils", + "mesonbuild.utils.core", + "mesonbuild.utils.platform", + "mesonbuild.utils.posix", + "mesonbuild.utils.universal", + "mesonbuild.utils.vsenv", + "mesonbuild.wrap", + "mesonbuild.wrap.wrap" + ], + "count": 68 + } +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/114 empty project/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/114 empty project/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/114 empty project/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/114 empty project/meson.build" 2023-07-05 20:56:32.000000000 +0000 @@ -0,0 +1 @@ +project('empty project') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/115 genvslite/main.cpp" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/115 genvslite/main.cpp" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/115 genvslite/main.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/115 genvslite/main.cpp" 2023-07-05 20:56:32.000000000 +0000 @@ -0,0 +1,10 @@ +#include + +int main() { +#ifdef NDEBUG + printf("Non-debug\n"); +#else + printf("Debug\n"); +#endif + return 0; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/115 genvslite/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/115 genvslite/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/115 genvslite/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/115 genvslite/meson.build" 2023-07-05 20:56:32.000000000 +0000 @@ -0,0 +1,5 @@ +project('genvslite', 'cpp', + default_options : ['b_ndebug=if-release'] + ) + +exe = executable('genvslite', 'main.cpp') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/15 prebuilt object/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/15 prebuilt object/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/15 prebuilt object/meson.build" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/15 prebuilt object/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -35,6 +35,12 @@ sl2 = static_library('lib6', sources: ct) e += executable('exe6', sources: 'main.c', objects: sl2.extract_all_objects(recursive: true)) +e += executable('exe7', sources: 'main.c', objects: ct) +e += executable('exe8', sources: 'main.c', objects: ct[0]) + +sl3 = static_library('lib9', objects: ct) +e += executable('exe9', sources: 'main.c', objects: sl2.extract_all_objects(recursive: true)) + foreach i : e test(i.name(), i) endforeach diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/33 cross file overrides always args/ubuntu-armhf-overrides.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/33 cross file overrides always args/ubuntu-armhf-overrides.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/33 cross file overrides always args/ubuntu-armhf-overrides.txt" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/33 cross file overrides always args/ubuntu-armhf-overrides.txt" 2023-08-07 22:54:24.000000000 +0000 @@ -6,7 +6,7 @@ rust = ['rustc', '--target', 'arm-unknown-linux-gnueabihf', '-C', 'linker=/usr/bin/arm-linux-gnueabihf-gcc-7'] ar = '/usr/arm-linux-gnueabihf/bin/ar' strip = '/usr/arm-linux-gnueabihf/bin/strip' -pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' +pkg-config = '/usr/bin/arm-linux-gnueabihf-pkg-config' [properties] root = '/usr/arm-linux-gnueabihf' diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/36 exe_wrapper behaviour/broken-cross.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/36 exe_wrapper behaviour/broken-cross.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/36 exe_wrapper behaviour/broken-cross.txt" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/36 exe_wrapper behaviour/broken-cross.txt" 2023-08-07 22:54:24.000000000 +0000 @@ -3,7 +3,7 @@ cpp = '/usr/bin/x86_64-w64-mingw32-g++' 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' +pkg-config = '/usr/bin/x86_64-w64-mingw32-pkg-config' windres = '/usr/bin/x86_64-w64-mingw32-windres' exe_wrapper = 'broken' diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/39 external, internal library rpath/built library/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/39 external, internal library rpath/built library/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/39 external, internal library rpath/built library/meson.build" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/39 external, internal library rpath/built library/meson.build" 2023-07-21 20:36:13.000000000 +0000 @@ -2,6 +2,8 @@ cc = meson.get_compiler('c') +import('python').find_installation().install_sources('foo.py') + if host_machine.system() != 'cygwin' # bar_in_system has undefined symbols, but still must be found bar_system_dep = cc.find_library('bar_in_system') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/63 cmake parser/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/63 cmake parser/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/63 cmake parser/meson.build" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/63 cmake parser/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -9,11 +9,11 @@ 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 : 'VAR_THAT_IS_UNSET', default_value : 'sentinel') == 'sentinel', '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') +assert(dep.get_variable(cmake : 'ENV{var}', default_value : 'sentinel') == 'sentinel', 'set(ENV) should be ignored') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/64 alias target/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/64 alias target/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/64 alias target/meson.build" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/64 alias target/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,6 +1,6 @@ project('alias target', 'c') -python3 = import('python').find_installation() +python3 = find_program('python3') exe_target = executable('prog', 'main.c', build_by_default : false) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/70 cross test passed/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/70 cross test passed/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/70 cross test passed/meson.build" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/70 cross test passed/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -6,7 +6,7 @@ e = executable('exec', 'src/main.c') -py = import('python').find_installation() +py = find_program('python3') test('root', e) test('main', py, args : [meson.current_source_dir() / 'script.py', e]) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/71 summary/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/71 summary/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/71 summary/meson.build" 2022-10-24 19:28:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/71 summary/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -11,7 +11,7 @@ 'enabled_opt': get_option('enabled_opt'), }, section: 'Configuration') summary({'missing prog': find_program('xyzzy', required: false), - 'existing prog': import('python').find_installation(), + 'existing prog': find_program(get_option('python')).full_path(), 'missing dep': dependency('', required: false), 'external dep': dependency('zlib', required: false), 'internal dep': declare_dependency(), diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/71 summary/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/71 summary/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/71 summary/meson_options.txt" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/71 summary/meson_options.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -1 +1,2 @@ option('enabled_opt', type: 'feature', value: 'auto') +option('python', type: 'string') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/73 dep files/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/73 dep files/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/73 dep files/meson.build" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/73 dep files/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,6 +1,6 @@ project('test', 'c') -python = import('python').find_installation() +python = find_program('python3') lib = library('foo', 'foo.c') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/77 nostdlib/subprojects/mylibc/libc.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/77 nostdlib/subprojects/mylibc/libc.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/77 nostdlib/subprojects/mylibc/libc.c" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/77 nostdlib/subprojects/mylibc/libc.c" 2023-05-23 15:20:02.000000000 +0000 @@ -1,5 +1,5 @@ /* Do not use this as the basis of your own libc. - * The code is probably unoptimal or wonky, as I + * The code is probably suboptimal or wonky, as I * had no prior experience with this, but instead * just fiddled with the code until it worked. */ diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/87 run native test/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/87 run native test/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/87 run native test/meson.build" 2022-06-19 19:10:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/87 run native test/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,6 +1,6 @@ project('run native test', ['c']) -executable('terget_exe', 'main.c') +executable('target_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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/90 devenv/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/90 devenv/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/90 devenv/meson.build" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/90 devenv/meson.build" 2023-08-07 22:54:24.000000000 +0000 @@ -15,3 +15,11 @@ # 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) + +env = environment({'TEST_C': ['/prefix']}, method: 'prepend') +meson.add_devenv(env) +env = environment({'TEST_C': ['/suffix']}, method: 'append') +meson.add_devenv(env) + +# Reproducer for https://github.com/mesonbuild/meson/issues/12032 +pkgconf = import('pkgconfig') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/90 devenv/test-devenv.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/90 devenv/test-devenv.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/90 devenv/test-devenv.py" 2023-02-23 22:07:07.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/90 devenv/test-devenv.py" 2023-05-23 15:20:02.000000000 +0000 @@ -6,3 +6,4 @@ assert os.environ['MESON_PROJECT_NAME'] == 'devenv' assert os.environ['TEST_A'] == '1' assert os.environ['TEST_B'] == '0+1+2+3+4' +assert os.environ['TEST_C'] == os.pathsep.join(['/prefix', '/suffix']) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/foo.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/foo.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/foo.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -int main(int argc, char *argv[]) -{ - return 0; -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/foo.dat" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/foo.dat" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/foo.dat" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/foo.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -dummy diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/foo.h" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/foo.h" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/foo.h" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/foo.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#define FOO diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar/barfile" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar/barfile" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar/barfile" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar/barfile" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -dummy diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -int main(int argc, char *argv[]) -{ - return 0; -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar.dat" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar.dat" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar.dat" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar.dat" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -dummy diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar.h" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar.h" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar.h" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/subprojects/bar/bar.h" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -#define FOO diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/subprojects/bar/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/subprojects/bar/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/91 install skip subprojects/subprojects/bar/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/91 install skip subprojects/subprojects/bar/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/foo.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/foo.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/foo.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,4 @@ +int main(int argc, char *argv[]) +{ + return 0; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/foo.dat" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/foo.dat" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/foo.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/foo.dat" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +dummy diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/foo.h" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/foo.h" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/foo.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/foo.h" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +#define FOO diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +dummy diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,4 @@ +int main(int argc, char *argv[]) +{ + return 0; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +dummy diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar.h" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar.h" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar.h" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/subprojects/bar/bar.h" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +#define FOO diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/subprojects/bar/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/subprojects/bar/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 install skip subprojects/subprojects/bar/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 install skip subprojects/subprojects/bar/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 new subproject in configured project/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 new subproject in configured project/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 new subproject in configured project/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 new subproject in configured project/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -# 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 new subproject in configured project/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 new subproject in configured project/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 new subproject in configured project/meson_options.txt" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 new subproject in configured project/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -# SPDX-license-identifier: Apache-2.0 -# Copyright © 2021 Intel Corporation -option('use-sub', type : 'boolean', value : false) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 new subproject in configured project/subprojects/sub/foo.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 new subproject in configured project/subprojects/sub/foo.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 new subproject in configured project/subprojects/sub/foo.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 new subproject in configured project/subprojects/sub/foo.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -/* SPDX-license-identifier: Apache-2.0 */ -/* Copyright © 2021 Intel Corporation */ - -int func(void) { - return 1; -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 new subproject in configured project/subprojects/sub/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 new subproject in configured project/subprojects/sub/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/92 new subproject in configured project/subprojects/sub/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/92 new subproject in configured project/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -# 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/.clang-format" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/.clang-format" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/.clang-format" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/.clang-format" 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ ---- -BasedOnStyle: Google - -... diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/.clang-format-ignore" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/.clang-format-ignore" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/.clang-format-ignore" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/.clang-format-ignore" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ - -# Ignore C files -*.c diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/.clang-format-include" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/.clang-format-include" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/.clang-format-include" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/.clang-format-include" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ - -# Only reformat in src/ -src/**/* diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -project('dummy', 'c', 'cpp') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/not-included/badformat.cpp" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/not-included/badformat.cpp" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/not-included/badformat.cpp" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/not-included/badformat.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -class { -}; diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/src/badformat.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/src/badformat.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/src/badformat.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/src/badformat.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -struct { -}; diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/src/badformat.cpp" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/src/badformat.cpp" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 clangformat/src/badformat.cpp" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 clangformat/src/badformat.cpp" 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -class { -}; diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 new subproject in configured project/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 new subproject in configured project/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 new subproject in configured project/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 new subproject in configured project/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 new subproject in configured project/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 new subproject in configured project/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 new subproject in configured project/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 new subproject in configured project/meson_options.txt" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,6 @@ +/* SPDX-license-identifier: Apache-2.0 */ +/* Copyright © 2021 Intel Corporation */ + +int func(void) { + return 1; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/.clang-format" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/.clang-format" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/.clang-format" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/.clang-format" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,4 @@ +--- +BasedOnStyle: Google + +... diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/.clang-format-ignore" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/.clang-format-ignore" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/.clang-format-ignore" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/.clang-format-ignore" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ + +# Ignore C files +*.c diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/.clang-format-include" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/.clang-format-include" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/.clang-format-include" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/.clang-format-include" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ + +# Only reformat in src/ +src/**/* diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +project('dummy', 'c', 'cpp') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/not-included/badformat.cpp" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/not-included/badformat.cpp" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/not-included/badformat.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/not-included/badformat.cpp" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,2 @@ +class { +}; diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/src/badformat.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/src/badformat.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/src/badformat.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/src/badformat.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,2 @@ +struct { +}; diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/src/badformat.cpp" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/src/badformat.cpp" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 clangformat/src/badformat.cpp" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 clangformat/src/badformat.cpp" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,2 @@ +class { +}; diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 custominc/easytogrepfor/genh.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 custominc/easytogrepfor/genh.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 custominc/easytogrepfor/genh.py" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 custominc/easytogrepfor/genh.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -f = open(sys.argv[1], 'w') -f.write('#define RETURN_VALUE 0') -f.close() diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 custominc/easytogrepfor/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 custominc/easytogrepfor/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 custominc/easytogrepfor/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 custominc/easytogrepfor/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -genh = custom_target('header', - output: 'generated.h', - command: [find_program('genh.py'), '@OUTPUT@']) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 custominc/helper.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 custominc/helper.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 custominc/helper.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 custominc/helper.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#include - -int func(void) { - return RETURN_VALUE; -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 custominc/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 custominc/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 custominc/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 custominc/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 custominc/prog.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 custominc/prog.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 custominc/prog.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 custominc/prog.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#include - -int func(void); - -int main(int argc, char **argv) { - (void)argc; - (void)(argv); - return func(); -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 custominc/prog2.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 custominc/prog2.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/94 custominc/prog2.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/94 custominc/prog2.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#include -#include - -int func(void); - -int main(int argc, char **argv) { - (void)argc; - (void)(argv); - return func() + RETURN_VALUE; -} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 custominc/easytogrepfor/genh.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 custominc/easytogrepfor/genh.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 custominc/easytogrepfor/genh.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 custominc/easytogrepfor/genh.py" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 custominc/easytogrepfor/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 custominc/easytogrepfor/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 custominc/easytogrepfor/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 custominc/easytogrepfor/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +genh = custom_target('header', + output: 'generated.h', + command: [find_program('genh.py'), '@OUTPUT@']) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 custominc/helper.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 custominc/helper.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 custominc/helper.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 custominc/helper.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,5 @@ +#include + +int func(void) { + return RETURN_VALUE; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 custominc/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 custominc/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 custominc/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 custominc/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 custominc/prog.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 custominc/prog.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 custominc/prog.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 custominc/prog.c" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 custominc/prog2.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 custominc/prog2.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 custominc/prog2.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 custominc/prog2.c" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 implicit force fallback/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 implicit force fallback/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 implicit force fallback/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 implicit force fallback/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 implicit force fallback/subprojects/something/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 implicit force fallback/subprojects/something/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/95 implicit force fallback/subprojects/something/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/95 implicit force fallback/subprojects/something/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -project('something') - -meson.override_dependency('something', declare_dependency()) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/96 compiler.links file arg/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/96 compiler.links file arg/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/96 compiler.links file arg/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/96 compiler.links file arg/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/96 compiler.links file arg/test.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/96 compiler.links file arg/test.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/96 compiler.links file arg/test.c" 2023-02-01 21:51:47.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/96 compiler.links file arg/test.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -int main(void) { return 0; } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/96 implicit force fallback/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/96 implicit force fallback/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/96 implicit force fallback/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/96 implicit force fallback/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/96 implicit force fallback/subprojects/something/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/96 implicit force fallback/subprojects/something/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/96 implicit force fallback/subprojects/something/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/96 implicit force fallback/subprojects/something/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +project('something') + +meson.override_dependency('something', declare_dependency()) diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 compiler.links file arg/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 compiler.links file arg/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 compiler.links file arg/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 compiler.links file arg/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 compiler.links file arg/test.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 compiler.links file arg/test.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 compiler.links file arg/test.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 compiler.links file arg/test.c" 2023-07-21 20:12:41.000000000 +0000 @@ -0,0 +1 @@ +int main(void) { return 0; } diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 link full name/.gitignore" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 link full name/.gitignore" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 link full name/.gitignore" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 link full name/.gitignore" 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -*.a -*.o -a.out -libtestprovider.a -build diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 link full name/libtestprovider/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 link full name/libtestprovider/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 link full name/libtestprovider/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 link full name/libtestprovider/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 link full name/libtestprovider/provider.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 link full name/libtestprovider/provider.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 link full name/libtestprovider/provider.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 link full name/libtestprovider/provider.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 link full name/proguser/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 link full name/proguser/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 link full name/proguser/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 link full name/proguser/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 link full name/proguser/receiver.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 link full name/proguser/receiver.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/97 link full name/proguser/receiver.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/97 link full name/proguser/receiver.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/custom_files/data.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/custom_files/data.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/custom_files/data.txt" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/custom_files/data.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Hello World diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/lib.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/lib.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/lib.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/main.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/main.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/main.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/meson.build" 2022-11-06 13:39:24.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,108 +0,0 @@ -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, -) -custom_target('ct-header1', - output: ['ct-header1.h'], - command: ['script.py', '@OUTPUT@'], - install_dir: get_option('includedir'), - install: true, -) -custom_target('ct-header2', - output: ['ct-header2.h', 'ct-header3.h'], - command: ['script.py', '@OUTPUT@'], - install_dir: [false, get_option('includedir')], - install: true, -) -install_emptydir(get_option('includedir') / 'subdir-devel') -install_subdir('custom_files', - install_dir: get_option('includedir'), -) - -# Those files should have 'runtime' tag -executable('app', 'main.c', - install: true, -) -executable('app-otherdir', 'main.c', - install: true, - install_dir: 'otherbin', -) -shared_library('shared', 'lib.c', - install: true, -) -both_libraries('both', 'lib.c', - install: true, -) - -# Unversioned .so file should have 'devel' tag, others should have 'runtime' tag -shared_library('versioned_shared', 'lib.c', - install: true, - version: '1.2.3', -) - -# 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/script.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/script.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/script.py" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/script.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -for f in sys.argv[1:]: - with open(f, 'w') as f: - pass diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/subdir/lib.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/subdir/lib.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/subdir/lib.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/subdir/lib.c" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/subdir/main.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/subdir/main.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/subdir/main.c" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/subdir/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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/subdir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/subdir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/subdir/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/subdir/script.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/subdir/script.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 install all targets/subdir/script.py" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 install all targets/subdir/script.py" 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -for f in sys.argv[1:]: - with open(f, 'w') as f: - pass diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 link full name/.gitignore" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 link full name/.gitignore" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 link full name/.gitignore" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 link full name/.gitignore" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,5 @@ +*.a +*.o +a.out +libtestprovider.a +build diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 link full name/libtestprovider/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 link full name/libtestprovider/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 link full name/libtestprovider/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 link full name/libtestprovider/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 link full name/libtestprovider/provider.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 link full name/libtestprovider/provider.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 link full name/libtestprovider/provider.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 link full name/libtestprovider/provider.c" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 link full name/proguser/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 link full name/proguser/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 link full name/proguser/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 link full name/proguser/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 link full name/proguser/receiver.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 link full name/proguser/receiver.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/98 link full name/proguser/receiver.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/98 link full name/proguser/receiver.c" 2023-05-23 15:20:02.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_FAILURE (-1) + +int main(void) { + if (get_checked() == CHECK_VALUE) { + fprintf(stdout,"good\n"); + return TEST_SUCCESS; + } + fprintf(stdout,"bad\n"); + return TEST_FAILURE; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 custom target name/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 custom target name/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 custom target name/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 custom target name/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 custom target name/subdir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 custom target name/subdir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 custom target name/subdir/meson.build" 2022-10-24 21:03:48.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 custom target name/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -# 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/custom_files/data.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/custom_files/data.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/custom_files/data.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/custom_files/data.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +Hello World diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/excludes/excluded/placeholder.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/excludes/excluded/placeholder.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/excludes/excluded/placeholder.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/excludes/excluded/placeholder.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +Placeholder diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/excludes/excluded.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/excludes/excluded.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/excludes/excluded.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/excludes/excluded.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +Excluded diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/excludes/installed.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/excludes/installed.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/excludes/installed.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/excludes/installed.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +Installed diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/lib.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/lib.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/lib.c" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/main.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/main.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/main.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +int main(int argc, char *argv[]) { + return 0; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/meson.build" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,116 @@ +project('install tag', 'c') + +subproject('subproject') + +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, +) +custom_target('ct-header1', + output: ['ct-header1.h'], + command: ['script.py', '@OUTPUT@'], + install_dir: get_option('includedir'), + install: true, +) +custom_target('ct-header2', + output: ['ct-header2.h', 'ct-header3.h'], + command: ['script.py', '@OUTPUT@'], + install_dir: [false, get_option('includedir')], + install: true, +) +install_emptydir(get_option('includedir') / 'subdir-devel') +install_subdir('custom_files', + install_dir: get_option('includedir'), +) + +# Those files should have 'runtime' tag +executable('app', 'main.c', + install: true, +) +executable('app-otherdir', 'main.c', + install: true, + install_dir: 'otherbin', +) +shared_library('shared', 'lib.c', + install: true, +) +both_libraries('both', 'lib.c', + install: true, +) + +# Unversioned .so file should have 'devel' tag, others should have 'runtime' tag +shared_library('versioned_shared', 'lib.c', + install: true, + version: '1.2.3', +) + +# 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', +) +install_subdir('excludes', + install_dir: get_option('datadir'), + install_tag: 'custom', + exclude_directories: 'excluded', + exclude_files: 'excluded.txt', +) + +# 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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/script.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/script.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/script.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/script.py" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subdir/lib.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subdir/lib.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subdir/lib.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subdir/lib.c" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subdir/main.c" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subdir/main.c" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subdir/main.c" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subdir/main.c" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +int main(int argc, char *argv[]) { + return 0; +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subdir/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subdir/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subdir/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subdir/meson.build" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subdir/script.py" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subdir/script.py" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subdir/script.py" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subdir/script.py" 2023-05-23 15:20:02.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/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subprojects/subproject/aaa.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subprojects/subproject/aaa.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subprojects/subproject/aaa.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subprojects/subproject/aaa.txt" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1 @@ +AAA diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subprojects/subproject/bbb.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subprojects/subproject/bbb.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subprojects/subproject/bbb.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subprojects/subproject/bbb.txt" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1 @@ +BBB diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subprojects/subproject/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subprojects/subproject/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/unit/99 install all targets/subprojects/subproject/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/unit/99 install all targets/subprojects/subproject/meson.build" 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,5 @@ +project('subproject') + +install_data('aaa.txt') + +install_data('bbb.txt', install_tag: 'data') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/warning/9 meson.options/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/warning/9 meson.options/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/warning/9 meson.options/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/warning/9 meson.options/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,3 @@ +project('options too old', meson_version : '>= 0.63') + +subproject('no-warn') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/warning/9 meson.options/meson.options" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/warning/9 meson.options/meson.options" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/warning/9 meson.options/meson.options" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/warning/9 meson.options/meson.options" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +option('foo', type : 'string') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/warning/9 meson.options/subprojects/no-warn/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/warning/9 meson.options/subprojects/no-warn/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/warning/9 meson.options/subprojects/no-warn/meson.build" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/warning/9 meson.options/subprojects/no-warn/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +project('has both no warn', meson_version : '>= 0.63') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/warning/9 meson.options/subprojects/no-warn/meson.options" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/warning/9 meson.options/subprojects/no-warn/meson.options" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/warning/9 meson.options/subprojects/no-warn/meson.options" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/warning/9 meson.options/subprojects/no-warn/meson.options" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +option('foo', type : 'string') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/warning/9 meson.options/subprojects/no-warn/meson_options.txt" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/warning/9 meson.options/subprojects/no-warn/meson_options.txt" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/warning/9 meson.options/subprojects/no-warn/meson_options.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/warning/9 meson.options/subprojects/no-warn/meson_options.txt" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1 @@ +option('foo', type : 'string') diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/warning/9 meson.options/test.json" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/warning/9 meson.options/test.json" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/warning/9 meson.options/test.json" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/warning/9 meson.options/test.json" 2023-05-23 15:20:02.000000000 +0000 @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "WARNING: Project targets '>= 0.63' but uses feature introduced in '1.1': meson.options file. Use meson_options.txt instead" + } + ] +} diff -Nru "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/windows/13 test argument extra paths/test/meson.build" "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/windows/13 test argument extra paths/test/meson.build" --- "/tmp/tmpivpdy9tj/e_LK851mFU/meson-1.0.1/test cases/windows/13 test argument extra paths/test/meson.build" 2020-08-15 16:27:05.000000000 +0000 +++ "/tmp/tmpivpdy9tj/DlqcQVr3Ph/meson-1.2.1/test cases/windows/13 test argument extra paths/test/meson.build" 2023-05-23 15:20:02.000000000 +0000 @@ -1,3 +1,3 @@ -python3 = import('python').find_installation('') +python3 = find_program('python3') test('run_exe', python3, args: [files('test_run_exe.py')[0], barexe]) diff -Nru meson-1.0.1/tools/boost_names.py meson-1.2.1/tools/boost_names.py --- meson-1.0.1/tools/boost_names.py 2021-07-20 08:56:20.000000000 +0000 +++ meson-1.2.1/tools/boost_names.py 2023-05-23 15:20:02.000000000 +0000 @@ -277,12 +277,12 @@ ''')) for mod in modules: - desc_excaped = re.sub(r"'", "\\'", mod.desc) + desc_escaped = re.sub(r"'", "\\'", mod.desc) print(textwrap.indent(textwrap.dedent(f"""\ '{mod.key}': BoostModule( name='{mod.name}', key='{mod.key}', - desc='{desc_excaped}', + desc='{desc_escaped}', libs={[x.name for x in mod.libs]}, ),\ """), ' ')) diff -Nru meson-1.0.1/unittests/allplatformstests.py meson-1.2.1/unittests/allplatformstests.py --- meson-1.0.1/unittests/allplatformstests.py 2023-02-23 22:07:07.000000000 +0000 +++ meson-1.2.1/unittests/allplatformstests.py 2023-08-07 22:54:34.000000000 +0000 @@ -41,9 +41,10 @@ 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, ExecutableSerialisation, EnvironmentVariables, + MesonException, EnvironmentException, OptionKey, windows_proof_rm ) +from mesonbuild.programs import ExternalProgram from mesonbuild.compilers.mixins.clang import ClangCompiler from mesonbuild.compilers.mixins.gnu import GnuCompiler @@ -54,9 +55,11 @@ detect_static_linker, detect_c_compiler, compiler_from_language, detect_compiler_for ) +from mesonbuild.linkers import linkers -from mesonbuild.dependencies import PkgConfigDependency +from mesonbuild.dependencies.pkgconfig import PkgConfigDependency from mesonbuild.build import Target, ConfigurationData, Executable, SharedLibrary, StaticLibrary +from mesonbuild import mtest import mesonbuild.modules.pkgconfig from mesonbuild.scripts import destdir_join @@ -353,7 +356,7 @@ 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): + if not isinstance(static_linker, linkers.ArLinker): raise SkipTest('static linker is not `ar`') # Configure self.init(testdir) @@ -396,6 +399,56 @@ self.assertTrue(compdb[3]['file'].endswith("libfile4.c")) # FIXME: We don't have access to the linker command + def test_replace_unencodable_xml_chars(self): + ''' + Test that unencodable xml chars are replaced with their + printable representation + https://github.com/mesonbuild/meson/issues/9894 + ''' + # Create base string(\nHello Meson\n) to see valid chars are not replaced + base_string_invalid = '\n\x48\x65\x6c\x6c\x6f\x20\x4d\x65\x73\x6f\x6e\n' + base_string_valid = '\nHello Meson\n' + # Create invalid input from all known unencodable chars + invalid_string = ( + '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f\x10\x11' + '\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f' + '\x80\x81\x82\x83\x84\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f' + '\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e' + '\x9f\ufdd0\ufdd1\ufdd2\ufdd3\ufdd4\ufdd5\ufdd6\ufdd7\ufdd8' + '\ufdd9\ufdda\ufddb\ufddc\ufddd\ufdde\ufddf\ufde0\ufde1' + '\ufde2\ufde3\ufde4\ufde5\ufde6\ufde7\ufde8\ufde9\ufdea' + '\ufdeb\ufdec\ufded\ufdee\ufdef\ufffe\uffff') + if sys.maxunicode >= 0x10000: + invalid_string = invalid_string + ( + '\U0001fffe\U0001ffff\U0002fffe\U0002ffff' + '\U0003fffe\U0003ffff\U0004fffe\U0004ffff' + '\U0005fffe\U0005ffff\U0006fffe\U0006ffff' + '\U0007fffe\U0007ffff\U0008fffe\U0008ffff' + '\U0009fffe\U0009ffff\U000afffe\U000affff' + '\U000bfffe\U000bffff\U000cfffe\U000cffff' + '\U000dfffe\U000dffff\U000efffe\U000effff' + '\U000ffffe\U000fffff\U0010fffe\U0010ffff') + + valid_string = base_string_valid + repr(invalid_string)[1:-1] + base_string_valid + invalid_string = base_string_invalid + invalid_string + base_string_invalid + broken_xml_stream = invalid_string.encode() + decoded_broken_stream = mtest.decode(broken_xml_stream) + self.assertEqual(decoded_broken_stream, valid_string) + + def test_replace_unencodable_xml_chars_unit(self): + ''' + Test that unencodable xml chars are replaced with their + printable representation + https://github.com/mesonbuild/meson/issues/9894 + ''' + if not shutil.which('xmllint'): + raise SkipTest('xmllint not installed') + testdir = os.path.join(self.unit_test_dir, '110 replace unencodable xml chars') + self.init(testdir) + self.run_tests() + junit_xml_logs = Path(self.logdir, 'testlog.junit.xml') + subprocess.run(['xmllint', junit_xml_logs], check=True) + def test_run_target_files_path(self): ''' Test that run_targets are run from the correct directory @@ -440,14 +493,15 @@ self.init(testdir) intro = self.introspect('--installed') expected = { + 'nested_elided/sub': 'share', + 'new_directory': 'share/new_directory', + 'sub/sub1': 'share/sub1', + 'sub1': 'share/sub1', 'sub2': 'share/sub2', + 'sub3': '/usr/share/sub3', + 'sub_elided': 'share', '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)) @@ -542,7 +596,7 @@ self.run_tests() def test_implicit_forcefallback(self): - testdir = os.path.join(self.unit_test_dir, '95 implicit force fallback') + 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']) @@ -678,7 +732,7 @@ 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) + # --suite overrides add_test_setup(exclude_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() @@ -816,6 +870,30 @@ o = self._run(self.mtest_command + ['--list', '--no-rebuild']) self.assertNotIn('Regenerating build files.', o) + def test_unexisting_test_name(self): + testdir = os.path.join(self.unit_test_dir, '4 suite selection') + self.init(testdir) + self.build() + + self.assertRaises(subprocess.CalledProcessError, self._run, self.mtest_command + ['notatest']) + + def test_select_test_using_wildcards(self): + testdir = os.path.join(self.unit_test_dir, '4 suite selection') + self.init(testdir) + self.build() + + o = self._run(self.mtest_command + ['--list', 'mainprj*']) + self.assertIn('mainprj-failing_test', o) + self.assertIn('mainprj-successful_test_no_suite', o) + self.assertNotIn('subprj', o) + + o = self._run(self.mtest_command + ['--list', '*succ*', 'subprjm*:']) + self.assertIn('mainprj-successful_test_no_suite', o) + self.assertIn('subprjmix-failing_test', o) + self.assertIn('subprjmix-successful_test', o) + self.assertIn('subprjsucc-successful_test_no_suite', o) + self.assertNotIn('subprjfail-failing_test', o) + def test_build_by_default(self): testdir = os.path.join(self.common_test_dir, '129 build by default') self.init(testdir) @@ -839,7 +917,7 @@ testdir = os.path.join("test cases/cython", '2 generated sources') env = get_fake_env(testdir, self.builddir, self.prefix) try: - detect_compiler_for(env, "cython", MachineChoice.HOST) + detect_compiler_for(env, "cython", MachineChoice.HOST, True) except EnvironmentException: raise SkipTest("Cython is not installed") self.init(testdir) @@ -850,13 +928,13 @@ name = None for target in targets: for target_sources in target["target_sources"]: - for generated_source in target_sources["generated_sources"]: + for generated_source in target_sources.get("generated_sources", []): if "includestuff.pyx.c" in generated_source: name = generated_source break - # Split the path (we only want the includestuff.cpython-blahblahblah) - name = os.path.normpath(name).split("/")[-2:] - name = "/".join(name) # Glue list into a string + # Split the path (we only want the includestuff.cpython-blahblah.so.p/includestuff.pyx.c) + name = os.path.normpath(name).split(os.sep)[-2:] + name = os.sep.join(name) # Glue list into a string self.build(target=name) def test_build_pyx_depfiles(self): @@ -864,7 +942,7 @@ testdir = os.path.join("test cases/cython", '2 generated sources') env = get_fake_env(testdir, self.builddir, self.prefix) try: - cython = detect_compiler_for(env, "cython", MachineChoice.HOST) + cython = detect_compiler_for(env, "cython", MachineChoice.HOST, True) if not version_compare(cython.version, '>=0.29.33'): raise SkipTest('Cython is too old') except EnvironmentException: @@ -957,8 +1035,8 @@ intel = IntelGnuLikeCompiler msvc = (VisualStudioCCompiler, VisualStudioCPPCompiler) clangcl = (ClangClCCompiler, ClangClCPPCompiler) - ar = mesonbuild.linkers.ArLinker - lib = mesonbuild.linkers.VisualStudioLinker + ar = linkers.ArLinker + lib = linkers.VisualStudioLinker langs = [('c', 'CC'), ('cpp', 'CXX')] if not is_windows() and platform.machine().lower() != 'e2k': langs += [('objc', 'OBJC'), ('objcpp', 'OBJCXX')] @@ -1002,39 +1080,39 @@ if isinstance(cc, gnu): self.assertIsInstance(linker, ar) if is_osx(): - self.assertIsInstance(cc.linker, mesonbuild.linkers.AppleDynamicLinker) + self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker) elif is_sunos(): - self.assertIsInstance(cc.linker, (mesonbuild.linkers.SolarisDynamicLinker, mesonbuild.linkers.GnuLikeDynamicLinkerMixin)) + self.assertIsInstance(cc.linker, (linkers.SolarisDynamicLinker, linkers.GnuLikeDynamicLinkerMixin)) else: - self.assertIsInstance(cc.linker, mesonbuild.linkers.GnuLikeDynamicLinkerMixin) + self.assertIsInstance(cc.linker, linkers.GnuLikeDynamicLinkerMixin) if isinstance(cc, clangcl): self.assertIsInstance(linker, lib) - self.assertIsInstance(cc.linker, mesonbuild.linkers.ClangClDynamicLinker) + self.assertIsInstance(cc.linker, linkers.ClangClDynamicLinker) if isinstance(cc, clang): self.assertIsInstance(linker, ar) if is_osx(): - self.assertIsInstance(cc.linker, mesonbuild.linkers.AppleDynamicLinker) + self.assertIsInstance(cc.linker, 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)) + self.assertIsInstance(cc.linker, (linkers.MSVCDynamicLinker, linkers.GnuLikeDynamicLinkerMixin)) else: - self.assertIsInstance(cc.linker, mesonbuild.linkers.GnuLikeDynamicLinkerMixin) + self.assertIsInstance(cc.linker, linkers.GnuLikeDynamicLinkerMixin) if isinstance(cc, intel): self.assertIsInstance(linker, ar) if is_osx(): - self.assertIsInstance(cc.linker, mesonbuild.linkers.AppleDynamicLinker) + self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker) elif is_windows(): - self.assertIsInstance(cc.linker, mesonbuild.linkers.XilinkDynamicLinker) + self.assertIsInstance(cc.linker, linkers.XilinkDynamicLinker) else: - self.assertIsInstance(cc.linker, mesonbuild.linkers.GnuDynamicLinker) + self.assertIsInstance(cc.linker, 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) + self.assertIsInstance(cc.linker, 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': @@ -1081,7 +1159,7 @@ for cmd in self.get_compdb(): # Get compiler split = split_args(cmd['command']) - if split[0] == 'ccache': + if split[0] in ('ccache', 'sccache'): compiler = split[1] else: compiler = split[0] @@ -1138,7 +1216,7 @@ def test_preprocessor_checks_CPPFLAGS(self): ''' - Test that preprocessor compiler checks read CPPFLAGS and also CFLAGS but + Test that preprocessor compiler checks read CPPFLAGS and also CFLAGS/CXXFLAGS but not LDFLAGS. ''' testdir = os.path.join(self.common_test_dir, '132 get define') @@ -1149,11 +1227,13 @@ # % and # confuse the MSVC preprocessor # !, ^, *, and < confuse lcc preprocessor value = 'spaces and fun@$&()-=_+{}[]:;>?,./~`' - for env_var in ['CPPFLAGS', 'CFLAGS']: + for env_var in [{'CPPFLAGS'}, {'CFLAGS', 'CXXFLAGS'}]: env = {} - env[env_var] = f'-D{define}="{value}"' + for i in env_var: + env[i] = f'-D{define}="{value}"' env['LDFLAGS'] = '-DMESON_FAIL_VALUE=cflags-read' self.init(testdir, extra_args=[f'-D{define}={value}'], override_envvars=env) + self.new_builddir() def test_custom_target_exe_data_deterministic(self): testdir = os.path.join(self.common_test_dir, '109 custom target capture') @@ -1262,6 +1342,8 @@ # This assumes all of the targets support lto for t in targets: for s in t['target_sources']: + if 'linker' in s: + continue for e in expected: self.assertIn(e, s['parameters']) @@ -1528,12 +1610,12 @@ 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 + targets = set(mesonbuild.coredata.FORBIDDEN_TARGET_NAMES) # We don't actually define a target with this name - targets.pop('build.ninja') + targets.remove('build.ninja') # Remove this to avoid multiple entries with the same name # but different case. - targets.pop('PHONY') + targets.remove('PHONY') for i in targets: self.assertPathExists(os.path.join(testdir, i)) @@ -1678,6 +1760,48 @@ self.build() self.run_tests() + def test_prebuilt_shared_lib_rpath_same_prefix(self) -> None: + (cc, _, object_suffix, shared_suffix) = self.detect_prebuild_env() + orig_tdir = os.path.join(self.unit_test_dir, '17 prebuilt shared') + + # Put the shared library in a location that shares a common prefix with + # the source directory: + # + # .../ + # foo-lib/ + # libalexandria.so + # foo/ + # meson.build + # ... + # + # This allows us to check that the .../foo-lib/libalexandria.so path is + # preserved correctly when meson processes it. + with tempfile.TemporaryDirectory() as d: + libdir = os.path.join(d, 'foo-lib') + os.mkdir(libdir) + + source = os.path.join(orig_tdir, 'alexandria.c') + objectfile = os.path.join(libdir, 'alexandria.' + object_suffix) + impfile = os.path.join(libdir, 'alexandria.lib') + if cc.get_argument_syntax() == 'msvc': + shlibfile = os.path.join(libdir, 'alexandria.' + shared_suffix) + elif is_cygwin(): + shlibfile = os.path.join(libdir, 'cygalexandria.' + shared_suffix) + else: + shlibfile = os.path.join(libdir, 'libalexandria.' + shared_suffix) + # Ensure MSVC extra files end up in the directory that gets deleted + # at the end + with chdir(libdir): + self.build_shared_lib(cc, source, objectfile, shlibfile, impfile) + + tdir = os.path.join(d, 'foo') + shutil.copytree(orig_tdir, tdir) + + # Run the test + self.init(tdir, extra_args=[f'-Dsearch_dir={libdir}']) + self.build() + self.run_tests() + def test_underscore_prefix_detection_list(self) -> None: ''' Test the underscore detection hardcoded lookup list @@ -1796,7 +1920,7 @@ check_pcfile('libvartest2.pc', relocatable=False) self.wipe() - testdir_abs = os.path.join(self.unit_test_dir, '105 pkgconfig relocatable with absolute path') + testdir_abs = os.path.join(self.unit_test_dir, '106 pkgconfig relocatable with absolute path') self.init(testdir_abs) check_pcfile('libsimple.pc', relocatable=True, levels=3) @@ -1948,6 +2072,33 @@ self.assertEqual(item['value'], ['b', 'c']) self.assertEqual(item['choices'], ['b', 'c', 'd']) + def test_options_listed_in_build_options(self) -> None: + """Detect when changed options become listed in build options.""" + testdir = os.path.join(self.unit_test_dir, '112 list build options') + + out = self.init(testdir) + for line in out.splitlines(): + if line.startswith('Message: Build options:'): + self.assertNotIn('-Dauto_features=auto', line) + self.assertNotIn('-Doptional=auto', line) + + self.wipe() + self.mac_ci_delay() + + out = self.init(testdir, extra_args=['-Dauto_features=disabled', '-Doptional=enabled']) + for line in out.splitlines(): + if line.startswith('Message: Build options:'): + self.assertIn('-Dauto_features=disabled', line) + self.assertIn('-Doptional=enabled', line) + + self.setconf('-Doptional=disabled') + out = self.build() + for line in out.splitlines(): + if line.startswith('Message: Build options:'): + self.assertIn('-Dauto_features=disabled', line) + self.assertNotIn('-Doptional=enabled', line) + self.assertIn('-Doptional=disabled', line) + def test_subproject_promotion(self): testdir = os.path.join(self.unit_test_dir, '12 promote') workdir = os.path.join(self.builddir, 'work') @@ -1974,6 +2125,7 @@ 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.new_builddir() # Ensure builddir is not parent or workdir self.init(workdir) self.build() @@ -2065,7 +2217,7 @@ 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) + comp = detect_compiler_for(env, l, MachineChoice.HOST, True) with tempfile.TemporaryDirectory() as d: comp.sanity_check(d, env) langs.append(l) @@ -2082,7 +2234,7 @@ if is_windows() and lang == 'fortran' and target_type == 'library': # non-Gfortran Windows Fortran compilers do not do shared libraries in a Fortran standard way # see "test cases/fortran/6 dynamic" - fc = detect_compiler_for(env, 'fortran', MachineChoice.HOST) + fc = detect_compiler_for(env, 'fortran', MachineChoice.HOST, True) if fc.get_id() in {'intel-cl', 'pgi'}: continue # test empty directory @@ -2155,11 +2307,11 @@ 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.''') + use shared_library() 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, '96 compiler.links file arg') + 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) @@ -2566,10 +2718,10 @@ def test_native_dep_pkgconfig(self): testdir = os.path.join(self.unit_test_dir, '45 native dep pkgconfig var') - with tempfile.NamedTemporaryFile(mode='w', delete=False) as crossfile: + with tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') as crossfile: crossfile.write(textwrap.dedent( '''[binaries] - pkgconfig = '{}' + pkg-config = '{}' [properties] @@ -2593,10 +2745,10 @@ def test_pkg_config_libdir(self): testdir = os.path.join(self.unit_test_dir, '45 native dep pkgconfig var') - with tempfile.NamedTemporaryFile(mode='w', delete=False) as crossfile: + with tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') as crossfile: crossfile.write(textwrap.dedent( '''[binaries] - pkgconfig = 'pkg-config' + pkg-config = 'pkg-config' [properties] pkg_config_libdir = ['{}'] @@ -2910,8 +3062,11 @@ ('benchmarks', list), ('buildoptions', list), ('buildsystem_files', list), + ('compilers', dict), ('dependencies', list), + ('install_plan', dict), ('installed', dict), + ('machines', dict), ('projectinfo', dict), ('targets', list), ('tests', list), @@ -2928,6 +3083,7 @@ ('depends', list), ('workdir', (str, None)), ('priority', int), + ('extra_paths', list), ] buildoptions_keylist = [ @@ -2953,9 +3109,16 @@ dependencies_typelist = [ ('name', str), + ('type', str), ('version', str), ('compile_args', list), ('link_args', list), + ('include_directories', list), + ('sources', list), + ('extra_files', list), + ('dependencies', list), + ('depends', list), + ('meson_variables', list), ] targets_typelist = [ @@ -2968,8 +3131,12 @@ ('target_sources', list), ('extra_files', list), ('subproject', (str, None)), + ('dependencies', list), + ('depends', list), ('install_filename', (list, None)), ('installed', bool), + ('vs_module_defs', (str, None)), + ('win_subsystem', (str, None)), ] targets_sources_typelist = [ @@ -2978,6 +3145,12 @@ ('parameters', list), ('sources', list), ('generated_sources', list), + ('unity_sources', (list, None)), + ] + + target_sources_linker_typelist = [ + ('linker', list), + ('parameters', list), ] # First load all files @@ -3001,7 +3174,7 @@ 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']}) + for src in group.get('sources', [])}) # Check Tests and benchmarks tests_to_find = ['test case 1', 'test case 2', 'benchmark 1'] @@ -3081,8 +3254,11 @@ 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]]) + if 'compiler' in j: + assertKeyTypes(targets_sources_typelist, j) + self.assertEqual(j['sources'], [os.path.normpath(f) for f in tgt[4]]) + else: + assertKeyTypes(target_sources_linker_typelist, j) self.assertDictEqual(targets_to_find, {}) def test_introspect_file_dump_equals_all(self): @@ -3095,9 +3271,11 @@ 'benchmarks', 'buildoptions', 'buildsystem_files', + 'compilers', 'dependencies', 'installed', 'install_plan', + 'machines', 'projectinfo', 'targets', 'tests', @@ -3170,12 +3348,13 @@ 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'] + for k in ('install_filename', 'dependencies', 'win_subsystem'): + if k in i: + del i[k] sources = [] for j in i['target_sources']: - sources += j['sources'] + sources += j.get('sources', []) i['target_sources'] = [{ 'language': 'unknown', 'compiler': [], @@ -3344,7 +3523,7 @@ def test_summary(self): testdir = os.path.join(self.unit_test_dir, '71 summary') - out = self.init(testdir, extra_args=['-Denabled_opt=enabled']) + out = self.init(testdir, extra_args=['-Denabled_opt=enabled', f'-Dpython={sys.executable}']) expected = textwrap.dedent(r''' Some Subproject 2.0 @@ -3374,7 +3553,7 @@ Stuff missing prog : NO - existing prog : ''' + sys.executable + ''' + existing prog : ''' + ExternalProgram('python3', [sys.executable], silent=True).path + ''' missing dep : NO external dep : YES 1.2.3 internal dep : YES @@ -3387,13 +3566,14 @@ Subprojects sub : YES sub2 : NO Problem encountered: This subproject failed - subsub : YES + subsub : YES (from sub2) User defined options - backend : ''' + self.backend.name + ''' + backend : ''' + self.backend_name + ''' libdir : lib prefix : /usr enabled_opt : enabled + python : ''' + sys.executable + ''' ''') expected_lines = expected.split('\n')[1:] out_start = out.find(expected_lines[0]) @@ -3931,7 +4111,7 @@ self.init(srcdir, extra_args=['-Dbuild.b_lto=true']) def test_install_skip_subprojects(self): - testdir = os.path.join(self.unit_test_dir, '91 install skip subprojects') + testdir = os.path.join(self.unit_test_dir, '92 install skip subprojects') self.init(testdir) self.build() @@ -3977,7 +4157,7 @@ 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, '92 new subproject in configured project') + srcdir = os.path.join(self.unit_test_dir, '93 new subproject in configured project') self.init(srcdir) self.build() self.setconf('-Duse-sub=true') @@ -3994,13 +4174,40 @@ self._run(cmd + python_command + [script]) self.assertEqual('This is text.', self._run(cmd + [app]).strip()) + cmd = self.meson_command + ['devenv', '-C', self.builddir, '--dump'] + o = self._run(cmd) + expected = os.pathsep.join(['/prefix', '$TEST_C', '/suffix']) + self.assertIn(f'TEST_C="{expected}"', o) + self.assertIn('export TEST_C', o) + + cmd = self.meson_command + ['devenv', '-C', self.builddir, '--dump', '--dump-format', 'sh'] + o = self._run(cmd) + expected = os.pathsep.join(['/prefix', '$TEST_C', '/suffix']) + self.assertIn(f'TEST_C="{expected}"', o) + self.assertNotIn('export', o) + + cmd = self.meson_command + ['devenv', '-C', self.builddir, '--dump', '--dump-format', 'vscode'] + o = self._run(cmd) + expected = os.pathsep.join(['/prefix', '/suffix']) + self.assertIn(f'TEST_C="{expected}"', o) + self.assertNotIn('export', o) + + fname = os.path.join(self.builddir, 'dump.env') + cmd = self.meson_command + ['devenv', '-C', self.builddir, '--dump', fname] + o = self._run(cmd) + self.assertEqual(o, '') + o = Path(fname).read_text(encoding='utf-8') + expected = os.pathsep.join(['/prefix', '$TEST_C', '/suffix']) + self.assertIn(f'TEST_C="{expected}"', o) + self.assertIn('export TEST_C', o) + 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, '93 clangformat') + testdir = os.path.join(self.unit_test_dir, '94 clangformat') newdir = os.path.join(self.builddir, 'testdir') shutil.copytree(testdir, newdir) self.new_builddir() @@ -4025,7 +4232,7 @@ self.build('clang-format-check') def test_custom_target_implicit_include(self): - testdir = os.path.join(self.unit_test_dir, '94 custominc') + testdir = os.path.join(self.unit_test_dir, '95 custominc') self.init(testdir) self.build() compdb = self.get_compdb() @@ -4049,23 +4256,23 @@ env = get_fake_env() # Get the compiler so we know which compiler class to mock. - cc = detect_compiler_for(env, 'c', MachineChoice.HOST) + cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True) 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) + cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True) 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) + cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True) 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, '98 install all targets') + testdir = os.path.join(self.unit_test_dir, '99 install all targets') self.init(testdir) self.build() @@ -4179,6 +4386,8 @@ Path(installpath, 'usr/share/out3-custom.txt'), Path(installpath, 'usr/share/custom_files'), Path(installpath, 'usr/share/custom_files/data.txt'), + Path(installpath, 'usr/share/excludes'), + Path(installpath, 'usr/share/excludes/installed.txt'), Path(installpath, 'usr/lib'), Path(installpath, 'usr/lib/libbothcustom.a'), Path(installpath, 'usr/' + shared_lib_name('bothcustom')), @@ -4200,6 +4409,9 @@ Path(installpath, 'usr/share/foo2.h'), Path(installpath, 'usr/share/out1.txt'), Path(installpath, 'usr/share/out2.txt'), + Path(installpath, 'usr/share/install tag'), + Path(installpath, 'usr/share/install tag/aaa.txt'), + Path(installpath, 'usr/share/install tag/bbb.txt'), } def do_install(tags, expected_files, expected_scripts): @@ -4216,8 +4428,22 @@ do_install('runtime,custom', expected_runtime_custom, 1) do_install(None, expected_all, 2) + + def test_install_script_dry_run(self): + testdir = os.path.join(self.common_test_dir, '53 install script') + self.init(testdir) + self.build() + + cmd = self.meson_command + ['install', '--dry-run', '--destdir', self.installdir] + outputs = self._run(cmd, workdir=self.builddir) + + installpath = Path(self.installdir) + self.assertFalse((installpath / 'usr/diiba/daaba/file.dat').exists()) + self.assertIn("DRYRUN: Writing file file.dat", outputs) + + def test_introspect_install_plan(self): - testdir = os.path.join(self.unit_test_dir, '98 install all targets') + testdir = os.path.join(self.unit_test_dir, '99 install all targets') introfile = os.path.join(self.builddir, 'meson-info', 'intro-install_plan.json') self.init(testdir) self.assertPathExists(introfile) @@ -4232,8 +4458,7 @@ structured_sources=None, objects=[], environment=env, compilers=env.coredata.compilers[MachineChoice.HOST], kwargs={}) - target.process_compilers() - target.process_compilers_late([]) + target.process_compilers_late() return target.filename shared_lib_name = lambda name: output_name(name, SharedLibrary) @@ -4245,134 +4470,184 @@ f'{self.builddir}/out1-notag.txt': { 'destination': '{datadir}/out1-notag.txt', 'tag': None, + 'subproject': None, }, f'{self.builddir}/out2-notag.txt': { 'destination': '{datadir}/out2-notag.txt', 'tag': None, + 'subproject': None, }, f'{self.builddir}/libstatic.a': { 'destination': '{libdir_static}/libstatic.a', 'tag': 'devel', + 'subproject': None, }, f'{self.builddir}/' + exe_name('app'): { 'destination': '{bindir}/' + exe_name('app'), 'tag': 'runtime', + 'subproject': None, }, f'{self.builddir}/' + exe_name('app-otherdir'): { 'destination': '{prefix}/otherbin/' + exe_name('app-otherdir'), 'tag': 'runtime', + 'subproject': None, }, f'{self.builddir}/subdir/' + exe_name('app2'): { 'destination': '{bindir}/' + exe_name('app2'), 'tag': 'runtime', + 'subproject': None, }, f'{self.builddir}/' + shared_lib_name('shared'): { 'destination': '{libdir_shared}/' + shared_lib_name('shared'), 'tag': 'runtime', + 'subproject': None, }, f'{self.builddir}/' + shared_lib_name('both'): { 'destination': '{libdir_shared}/' + shared_lib_name('both'), 'tag': 'runtime', + 'subproject': None, }, f'{self.builddir}/' + static_lib_name('both'): { 'destination': '{libdir_static}/' + static_lib_name('both'), 'tag': 'devel', + 'subproject': None, }, f'{self.builddir}/' + shared_lib_name('bothcustom'): { 'destination': '{libdir_shared}/' + shared_lib_name('bothcustom'), 'tag': 'custom', + 'subproject': None, }, f'{self.builddir}/' + static_lib_name('bothcustom'): { 'destination': '{libdir_static}/' + static_lib_name('bothcustom'), 'tag': 'custom', + 'subproject': None, }, f'{self.builddir}/subdir/' + shared_lib_name('both2'): { 'destination': '{libdir_shared}/' + shared_lib_name('both2'), 'tag': 'runtime', + 'subproject': None, }, f'{self.builddir}/subdir/' + static_lib_name('both2'): { 'destination': '{libdir_static}/' + static_lib_name('both2'), 'tag': 'devel', + 'subproject': None, }, f'{self.builddir}/out1-custom.txt': { 'destination': '{datadir}/out1-custom.txt', 'tag': 'custom', + 'subproject': None, }, f'{self.builddir}/out2-custom.txt': { 'destination': '{datadir}/out2-custom.txt', 'tag': 'custom', + 'subproject': None, }, f'{self.builddir}/out3-custom.txt': { 'destination': '{datadir}/out3-custom.txt', 'tag': 'custom', + 'subproject': None, }, f'{self.builddir}/subdir/out1.txt': { 'destination': '{datadir}/out1.txt', 'tag': None, + 'subproject': None, }, f'{self.builddir}/subdir/out2.txt': { 'destination': '{datadir}/out2.txt', 'tag': None, + 'subproject': None, }, f'{self.builddir}/out-devel.h': { 'destination': '{includedir}/out-devel.h', 'tag': 'devel', + 'subproject': None, }, f'{self.builddir}/out3-notag.txt': { 'destination': '{datadir}/out3-notag.txt', 'tag': None, + 'subproject': None, }, }, 'configure': { f'{self.builddir}/foo-notag.h': { 'destination': '{datadir}/foo-notag.h', 'tag': None, + 'subproject': None, }, f'{self.builddir}/foo2-devel.h': { 'destination': '{includedir}/foo2-devel.h', 'tag': 'devel', + 'subproject': None, }, f'{self.builddir}/foo-custom.h': { 'destination': '{datadir}/foo-custom.h', 'tag': 'custom', + 'subproject': None, }, f'{self.builddir}/subdir/foo2.h': { 'destination': '{datadir}/foo2.h', 'tag': None, + 'subproject': None, }, }, 'data': { f'{testdir}/bar-notag.txt': { 'destination': '{datadir}/bar-notag.txt', 'tag': None, + 'subproject': None, }, f'{testdir}/bar-devel.h': { 'destination': '{includedir}/bar-devel.h', 'tag': 'devel', + 'subproject': None, }, f'{testdir}/bar-custom.txt': { 'destination': '{datadir}/bar-custom.txt', 'tag': 'custom', + 'subproject': None, }, f'{testdir}/subdir/bar2-devel.h': { 'destination': '{includedir}/bar2-devel.h', 'tag': 'devel', + 'subproject': None, + }, + f'{testdir}/subprojects/subproject/aaa.txt': { + 'destination': '{datadir}/install tag/aaa.txt', + 'tag': None, + 'subproject': 'subproject', + }, + f'{testdir}/subprojects/subproject/bbb.txt': { + 'destination': '{datadir}/install tag/bbb.txt', + 'tag': 'data', + 'subproject': 'subproject', }, }, 'headers': { f'{testdir}/foo1-devel.h': { 'destination': '{includedir}/foo1-devel.h', 'tag': 'devel', + 'subproject': None, }, f'{testdir}/subdir/foo3-devel.h': { 'destination': '{includedir}/foo3-devel.h', 'tag': 'devel', + 'subproject': None, }, }, 'install_subdirs': { f'{testdir}/custom_files': { 'destination': '{datadir}/custom_files', - 'tag': 'custom' + 'tag': 'custom', + 'subproject': None, + 'exclude_dirs': [], + 'exclude_files': [], + }, + f'{testdir}/excludes': { + 'destination': '{datadir}/excludes', + 'tag': 'custom', + 'subproject': None, + 'exclude_dirs': ['excluded'], + 'exclude_files': ['excluded.txt'], } } } @@ -4420,9 +4695,9 @@ }} ''') - testdir = os.path.join(self.unit_test_dir, '101 rlib linkage') + testdir = os.path.join(self.unit_test_dir, '102 rlib linkage') gen_file = os.path.join(testdir, 'lib.rs') - with open(gen_file, 'w') as f: + with open(gen_file, 'w', encoding='utf-8') as f: f.write(template.format(0)) self.addCleanup(windows_proof_rm, gen_file) @@ -4430,7 +4705,7 @@ self.build() self.run_tests() - with open(gen_file, 'w') as f: + with open(gen_file, 'w', encoding='utf-8') as f: f.write(template.format(39)) self.build() @@ -4440,7 +4715,7 @@ self.assertIn('exit status 39', cm.exception.stdout) def test_custom_target_name(self): - testdir = os.path.join(self.unit_test_dir, '99 custom target name') + testdir = os.path.join(self.unit_test_dir, '100 custom target name') self.init(testdir) out = self.build() if self.backend is Backend.ninja: @@ -4448,52 +4723,54 @@ self.assertIn('Generating subdir/file.txt with a custom command', out) def test_symlinked_subproject(self): - testdir = os.path.join(self.unit_test_dir, '106 subproject symlink') + testdir = os.path.join(self.unit_test_dir, '107 subproject symlink') subproject_dir = os.path.join(testdir, 'subprojects') subproject = os.path.join(testdir, 'symlinked_subproject') symlinked_subproject = os.path.join(testdir, 'subprojects', 'symlinked_subproject') if not os.path.exists(subproject_dir): os.mkdir(subproject_dir) - os.symlink(subproject, symlinked_subproject) + try: + os.symlink(subproject, symlinked_subproject) + except OSError: + raise SkipTest("Symlinks are not available on this machine") self.addCleanup(os.remove, symlinked_subproject) self.init(testdir) self.build() def test_configure_same_noop(self): - testdir = os.path.join(self.unit_test_dir, '108 configure same noop') - self.init(testdir, extra_args=['-Dopt=val']) + testdir = os.path.join(self.unit_test_dir, '109 configure same noop') + args = [ + '-Dstring=val', + '-Dboolean=true', + '-Dcombo=two', + '-Dinteger=7', + '-Darray=[\'three\']', + '-Dfeature=disabled', + '--buildtype=plain', + '--prefix=/abc', + ] + self.init(testdir, extra_args=args) - filename = os.path.join(self.privatedir, 'coredata.dat') + filename = Path(self.privatedir) / 'coredata.dat' + + olddata = filename.read_bytes() oldmtime = os.path.getmtime(filename) - self.setconf(["-Dopt=val"]) - newmtime = os.path.getmtime(filename) - self.assertEqual(oldmtime, newmtime) - - def test_scripts_loaded_modules(self): - ''' - Simulate a wrapped command, as done for custom_target() that capture - output. The script will print all python modules loaded and we verify - that it contains only an acceptable subset. Loading too many modules - slows down the build when many custom targets get wrapped. - ''' - es = ExecutableSerialisation(python_command + ['-c', 'exit(0)'], env=EnvironmentVariables()) - p = Path(self.builddir, 'exe.dat') - with p.open('wb') as f: - pickle.dump(es, f) - cmd = self.meson_command + ['--internal', 'test_loaded_modules', '--unpickle', str(p)] - p = subprocess.run(cmd, stdout=subprocess.PIPE) - all_modules = json.loads(p.stdout.splitlines()[0]) - meson_modules = [m for m in all_modules if 'meson' in m] - expected_meson_modules = [ - 'mesonbuild', - 'mesonbuild._pathlib', - 'mesonbuild.utils', - 'mesonbuild.utils.core', - 'mesonbuild.mesonmain', - 'mesonbuild.mlog', - 'mesonbuild.scripts', - 'mesonbuild.scripts.meson_exe', - 'mesonbuild.scripts.test_loaded_modules' - ] - self.assertEqual(sorted(expected_meson_modules), sorted(meson_modules)) + + for opt in ('-Dstring=val', '--buildtype=plain', '-Dfeature=disabled', '-Dprefix=/abc'): + self.setconf([opt]) + newdata = filename.read_bytes() + newmtime = os.path.getmtime(filename) + self.assertEqual(oldmtime, newmtime) + self.assertEqual(olddata, newdata) + olddata = newdata + oldmtime = newmtime + + for opt in ('-Dstring=abc', '--buildtype=release', '-Dfeature=enabled', '-Dprefix=/def'): + self.setconf([opt]) + newdata = filename.read_bytes() + newmtime = os.path.getmtime(filename) + self.assertGreater(newmtime, oldmtime) + self.assertNotEqual(olddata, newdata) + olddata = newdata + oldmtime = newmtime diff -Nru meson-1.0.1/unittests/baseplatformtests.py meson-1.2.1/unittests/baseplatformtests.py --- meson-1.0.1/unittests/baseplatformtests.py 2022-12-10 16:46:15.000000000 +0000 +++ meson-1.2.1/unittests/baseplatformtests.py 2023-08-07 22:54:34.000000000 +0000 @@ -33,7 +33,7 @@ import mesonbuild.coredata import mesonbuild.modules.gnome from mesonbuild.mesonlib import ( - is_cygwin, join_args, windows_proof_rmtree, python_command + is_cygwin, join_args, split_args, windows_proof_rmtree, python_command ) import mesonbuild.modules.pkgconfig @@ -45,6 +45,11 @@ ) +# magic attribute used by unittest.result.TestResult._is_relevant_tb_level +# This causes tracebacks to hide these internal implementation details, +# e.g. for assertXXX helpers. +__unittest = True + class BasePlatformTests(TestCase): prefix = '/usr' libdir = 'lib' @@ -55,8 +60,10 @@ 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.backend_name = os.environ['MESON_UNIT_TEST_BACKEND'] + backend_type = 'vs' if self.backend_name.startswith('vs') else self.backend_name + self.backend = getattr(Backend, backend_type) + self.meson_args = ['--backend=' + self.backend_name] self.meson_native_files = [] self.meson_cross_files = [] self.meson_command = python_command + [get_meson_script()] @@ -70,6 +77,7 @@ self.uninstall_command = get_backend_commands(self.backend) # Test directories self.common_test_dir = os.path.join(src_root, 'test cases/common') + self.python_test_dir = os.path.join(src_root, 'test cases/python') 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') @@ -87,6 +95,7 @@ # 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}'] + os.environ['COLUMNS'] = '80' self.builddirs = [] self.new_builddir() @@ -198,7 +207,8 @@ extra_args = [] if not isinstance(extra_args, list): extra_args = [extra_args] - args = [srcdir, self.builddir] + build_and_src_dir_args = [self.builddir, srcdir] + args = [] if default_args: args += ['--prefix', self.prefix] if self.libdir: @@ -210,7 +220,7 @@ self.privatedir = os.path.join(self.builddir, 'meson-private') if inprocess: try: - returncode, out, err = run_configure_inprocess(['setup'] + self.meson_args + args + extra_args, override_envvars) + returncode, out, err = run_configure_inprocess(['setup'] + self.meson_args + args + extra_args + build_and_src_dir_args, override_envvars) except Exception as e: if not allow_fail: self._print_meson_log() @@ -221,8 +231,8 @@ finally: # Close log file to satisfy Windows file locking mesonbuild.mlog.shutdown() - mesonbuild.mlog.log_dir = None - mesonbuild.mlog.log_file = None + mesonbuild.mlog._logger.log_dir = None + mesonbuild.mlog._logger.log_file = None if 'MESON_SKIP_TEST' in out: raise SkipTest('Project requested skipping.') @@ -236,7 +246,7 @@ raise RuntimeError('Configure failed') else: try: - out = self._run(self.setup_command + args + extra_args, override_envvars=override_envvars, workdir=workdir) + out = self._run(self.setup_command + args + extra_args + build_and_src_dir_args, override_envvars=override_envvars, workdir=workdir) except SkipTest: raise SkipTest('Project requested skipping: ' + srcdir) except Exception: @@ -335,9 +345,10 @@ Fetch a list command-lines run by meson for compiler checks. Each command-line is returned as a list of arguments. ''' - prefix = 'Command line:' + prefix = 'Command line: `' + suffix = '` -> 0\n' with self._open_meson_log() as log: - cmds = [l[len(prefix):].split() for l in log if l.startswith(prefix)] + cmds = [split_args(l[len(prefix):-len(suffix)]) for l in log if l.startswith(prefix)] return cmds def get_meson_log_sanitychecks(self): @@ -481,3 +492,6 @@ def assertPathDoesNotExist(self, path): m = f'Path {path!r} should not exist' self.assertFalse(os.path.exists(path), msg=m) + + def assertLength(self, val, length): + assert len(val) == length, f'{val} is not length {length}' diff -Nru meson-1.0.1/unittests/cargotests.py meson-1.2.1/unittests/cargotests.py --- meson-1.0.1/unittests/cargotests.py 1970-01-01 00:00:00.000000000 +0000 +++ meson-1.2.1/unittests/cargotests.py 2023-06-28 14:48:20.000000000 +0000 @@ -0,0 +1,186 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2022-2023 Intel Corporation + +from __future__ import annotations +import unittest +import typing as T + +from mesonbuild.cargo import builder, cfg +from mesonbuild.cargo.cfg import TokenType +from mesonbuild.cargo.version import convert + + +class CargoVersionTest(unittest.TestCase): + + def test_cargo_to_meson(self) -> None: + cases: T.List[T.Tuple[str, T.List[str]]] = [ + # Basic requirements + ('>= 1', ['>= 1']), + ('> 1', ['> 1']), + ('= 1', ['= 1']), + ('< 1', ['< 1']), + ('<= 1', ['<= 1']), + + # tilde tests + ('~1', ['>= 1', '< 2']), + ('~1.1', ['>= 1.1', '< 1.2']), + ('~1.1.2', ['>= 1.1.2', '< 1.2.0']), + + # Wildcards + ('*', []), + ('1.*', ['>= 1', '< 2']), + ('2.3.*', ['>= 2.3', '< 2.4']), + + # Unqualified + ('2', ['>= 2', '< 3']), + ('2.4', ['>= 2.4', '< 3']), + ('2.4.5', ['>= 2.4.5', '< 3']), + ('0.0.0', ['< 1']), + ('0.0', ['< 1']), + ('0', ['< 1']), + ('0.0.5', ['>= 0.0.5', '< 0.0.6']), + ('0.5.0', ['>= 0.5', '< 0.6']), + ('0.5', ['>= 0.5', '< 0.6']), + + # Caret (Which is the same as unqualified) + ('^2', ['>= 2', '< 3']), + ('^2.4', ['>= 2.4', '< 3']), + ('^2.4.5', ['>= 2.4.5', '< 3']), + ('^0.0.0', ['< 1']), + ('^0.0', ['< 1']), + ('^0', ['< 1']), + ('^0.0.5', ['>= 0.0.5', '< 0.0.6']), + ('^0.5.0', ['>= 0.5', '< 0.6']), + ('^0.5', ['>= 0.5', '< 0.6']), + + # Multiple requirements + ('>= 1.2.3, < 1.4.7', ['>= 1.2.3', '< 1.4.7']), + ] + + for (data, expected) in cases: + with self.subTest(): + self.assertListEqual(convert(data), expected) + + +class CargoCfgTest(unittest.TestCase): + + def test_lex(self) -> None: + cases: T.List[T.Tuple[str, T.List[T.Tuple[TokenType, T.Optional[str]]]]] = [ + ('"unix"', [(TokenType.STRING, 'unix')]), + ('unix', [(TokenType.IDENTIFIER, 'unix')]), + ('not(unix)', [ + (TokenType.NOT, None), + (TokenType.LPAREN, None), + (TokenType.IDENTIFIER, 'unix'), + (TokenType.RPAREN, None), + ]), + ('any(unix, windows)', [ + (TokenType.ANY, None), + (TokenType.LPAREN, None), + (TokenType.IDENTIFIER, 'unix'), + (TokenType.COMMA, None), + (TokenType.IDENTIFIER, 'windows'), + (TokenType.RPAREN, None), + ]), + ('target_arch = "x86_64"', [ + (TokenType.IDENTIFIER, 'target_arch'), + (TokenType.EQUAL, None), + (TokenType.STRING, 'x86_64'), + ]), + ('all(target_arch = "x86_64", unix)', [ + (TokenType.ALL, None), + (TokenType.LPAREN, None), + (TokenType.IDENTIFIER, 'target_arch'), + (TokenType.EQUAL, None), + (TokenType.STRING, 'x86_64'), + (TokenType.COMMA, None), + (TokenType.IDENTIFIER, 'unix'), + (TokenType.RPAREN, None), + ]), + ] + for data, expected in cases: + with self.subTest(): + self.assertListEqual(list(cfg.lexer(data)), expected) + + def test_parse(self) -> None: + cases = [ + ('target_os = "windows"', cfg.Equal('', cfg.Identifier('', "target_os"), cfg.String('', "windows"))), + ('target_arch = "x86"', cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86"))), + ('target_family = "unix"', cfg.Equal('', cfg.Identifier('', "target_family"), cfg.String('', "unix"))), + ('any(target_arch = "x86", target_arch = "x86_64")', + cfg.Any( + '', [ + cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86")), + cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86_64")), + ])), + ('all(target_arch = "x86", target_os = "linux")', + cfg.All( + '', [ + cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86")), + cfg.Equal('', cfg.Identifier('', "target_os"), cfg.String('', "linux")), + ])), + ('not(all(target_arch = "x86", target_os = "linux"))', + cfg.Not( + '', + cfg.All( + '', [ + cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86")), + cfg.Equal('', cfg.Identifier('', "target_os"), cfg.String('', "linux")), + ]))), + ] + for data, expected in cases: + with self.subTest(): + self.assertEqual(cfg.parse(iter(cfg.lexer(data)), ''), expected) + + def test_ir_to_meson(self) -> None: + HOST_MACHINE = builder.identifier('host_machine', '') + + cases = [ + ('target_os = "windows"', + builder.equal(builder.method('system', HOST_MACHINE), + builder.string('windows', ''))), + ('target_arch = "x86"', + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86', ''))), + ('target_family = "unix"', + builder.equal(builder.method('system', HOST_MACHINE), + builder.string('unix', ''))), + ('not(target_arch = "x86")', + builder.not_(builder.equal( + builder.method('cpu_family', HOST_MACHINE), + builder.string('x86', '')), '')), + ('any(target_arch = "x86", target_arch = "x86_64")', + builder.or_( + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86', '')), + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86_64', '')))), + ('any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")', + builder.or_( + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86', '')), + builder.or_( + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86_64', '')), + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('aarch64', ''))))), + ('all(target_arch = "x86", target_arch = "x86_64")', + builder.and_( + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86', '')), + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86_64', '')))), + ('all(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")', + builder.and_( + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86', '')), + builder.and_( + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86_64', '')), + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('aarch64', ''))))), + ] + for data, expected in cases: + with self.subTest(): + value = cfg.ir_to_meson(cfg.parse(iter(cfg.lexer(data)), '')) + self.assertEqual(value, expected) diff -Nru meson-1.0.1/unittests/darwintests.py meson-1.2.1/unittests/darwintests.py --- meson-1.0.1/unittests/darwintests.py 2022-12-10 16:46:15.000000000 +0000 +++ meson-1.2.1/unittests/darwintests.py 2023-07-21 20:36:13.000000000 +0000 @@ -138,7 +138,7 @@ def test_objc_versions(self): # Objective-C always uses the C standard version. - # Objecttive-C++ always uses the C++ standard version. + # Objective-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') @@ -148,3 +148,8 @@ testdir = os.path.join(self.objcpp_test_dir, '1 simple') self.init(testdir) self.assertIn('-std=c++14', self.get_compdb()[0]['command']) + + def test_darwin_get_object_archs(self): + from mesonbuild.mesonlib import darwin_get_object_archs + archs = darwin_get_object_archs('/System/Library/CoreServices/Encodings/libSymbolConverter.dylib') + self.assertEqual(archs, ['x86_64', 'aarch64']) diff -Nru meson-1.0.1/unittests/datatests.py meson-1.2.1/unittests/datatests.py --- meson-1.0.1/unittests/datatests.py 2022-12-10 16:46:15.000000000 +0000 +++ meson-1.2.1/unittests/datatests.py 2023-05-23 15:20:02.000000000 +0000 @@ -219,11 +219,14 @@ name = name.replace('_', '-') self.assertIn(name, html) + @unittest.mock.patch.dict(os.environ) def test_vim_syntax_highlighting(self): ''' Ensure that vim syntax highlighting files were updated for new functions in the global namespace in build files. ''' + # Disable unit test specific syntax + del os.environ['MESON_RUNNING_IN_PROJECT_TESTS'] env = get_fake_env() interp = Interpreter(FakeBuild(env), mock=True) with open('data/syntax-highlighting/vim/syntax/meson.vim', encoding='utf-8') as f: @@ -231,11 +234,14 @@ defined = set([a.strip() for a in res.group().split('\\')][1:]) self.assertEqual(defined, set(chain(interp.funcs.keys(), interp.builtin.keys()))) + @unittest.mock.patch.dict(os.environ) 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). ''' + # Disable unit test specific syntax + del os.environ['MESON_RUNNING_IN_PROJECT_TESTS'] env = get_fake_env() interp = Interpreter(FakeBuild(env), mock=True) astint = AstInterpreter('.', '', '') diff -Nru meson-1.0.1/unittests/failuretests.py meson-1.2.1/unittests/failuretests.py --- meson-1.0.1/unittests/failuretests.py 2022-12-10 16:46:15.000000000 +0000 +++ meson-1.2.1/unittests/failuretests.py 2023-05-23 15:20:02.000000000 +0000 @@ -78,7 +78,9 @@ 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') + self.moptions = os.path.join(self.srcdir, 'meson.options') + if not os.path.exists(self.moptions): + self.moptions = os.path.join(self.srcdir, 'meson_options.txt') def tearDown(self): super().tearDown() diff -Nru meson-1.0.1/unittests/helpers.py meson-1.2.1/unittests/helpers.py --- meson-1.0.1/unittests/helpers.py 2022-12-16 18:51:36.000000000 +0000 +++ meson-1.2.1/unittests/helpers.py 2023-05-30 15:42:56.000000000 +0000 @@ -204,3 +204,11 @@ paths.discard(dirname) path = pathsep.join([str(p) for p in paths]) return path + +def xfail_if_jobname(name: str): + if os.environ.get('MESON_CI_JOBNAME') == name: + return unittest.expectedFailure + + def wrapper(func): + return func + return wrapper diff -Nru meson-1.0.1/unittests/internaltests.py meson-1.2.1/unittests/internaltests.py --- meson-1.0.1/unittests/internaltests.py 2023-02-20 12:58:43.000000000 +0000 +++ meson-1.2.1/unittests/internaltests.py 2023-08-07 22:54:34.000000000 +0000 @@ -38,6 +38,7 @@ from mesonbuild.compilers.c import ClangCCompiler, GnuCCompiler from mesonbuild.compilers.cpp import VisualStudioCPPCompiler from mesonbuild.compilers.d import DmdDCompiler +from mesonbuild.linkers import linkers 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 ( @@ -46,7 +47,7 @@ OptionType ) from mesonbuild.interpreter.type_checking import in_set_validator, NoneType -from mesonbuild.dependencies import PkgConfigDependency +from mesonbuild.dependencies.pkgconfig import PkgConfigDependency from mesonbuild.programs import ExternalProgram import mesonbuild.modules.pkgconfig @@ -223,7 +224,7 @@ def test_compiler_args_class_visualstudio(self): - linker = mesonbuild.linkers.MSVCDynamicLinker(MachineChoice.HOST, []) + linker = linkers.MSVCDynamicLinker(MachineChoice.HOST, []) # Version just needs to be > 19.0.0 cc = VisualStudioCPPCompiler([], [], '20.00', MachineChoice.HOST, False, mock.Mock(), 'x64', linker=linker) @@ -245,7 +246,7 @@ def test_compiler_args_class_gnuld(self): ## Test --start/end-group - linker = mesonbuild.linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-Wl,', []) + linker = linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-Wl,', []) gcc = 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'] @@ -273,7 +274,7 @@ def test_compiler_args_remove_system(self): ## Test --start/end-group - linker = mesonbuild.linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-Wl,', []) + linker = linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-Wl,', []) gcc = 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'] @@ -452,7 +453,7 @@ # 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) + configfile = tempfile.NamedTemporaryFile(mode='w+', delete=False, encoding='utf-8') configfilename = configfile.name config.write(configfile) configfile.flush() @@ -468,7 +469,7 @@ 'needs_exe_wrapper': 'true' if desired_value else 'false' } - configfile = tempfile.NamedTemporaryFile(mode='w+', delete=False) + configfile = tempfile.NamedTemporaryFile(mode='w+', delete=False, encoding='utf-8') configfilename = configfile.name config.write(configfile) configfile.close() @@ -551,7 +552,7 @@ 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) + found = cc._find_library_real('foo', env, [tmpdir], '', LibType.PREFER_SHARED, lib_prefix_warning=True) self.assertEqual(os.path.basename(found[0]), 'libfoo.so.54.0') def test_find_library_patterns(self): @@ -947,23 +948,23 @@ 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') + with mock.patch('mesonbuild.mlog._logger.log_file', f), \ + mock.patch('mesonbuild.mlog._logger.logged_once', set()): + mesonbuild.mlog.log('foo', once=True) + mesonbuild.mlog.log('foo', once=True) 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')) + with mock.patch('mesonbuild.mlog._logger.log_file', f), \ + mock.patch('mesonbuild.mlog._logger.logged_once', set()): + mesonbuild.mlog.log(mesonbuild.mlog.bold('foo'), once=True) + mesonbuild.mlog.log(mesonbuild.mlog.bold('foo'), once=True) actual = f.getvalue().strip() self.assertEqual(actual.count('foo'), 1, actual) - mesonbuild.mlog.log_once('foo') + mesonbuild.mlog.log('foo', once=True) actual = f.getvalue().strip() self.assertEqual(actual.count('foo'), 1, actual) @@ -1101,7 +1102,7 @@ _(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: + def test_typed_pos_args_varargs_invalid_multiple_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 @@ -1415,6 +1416,11 @@ since_values={list: '1.9'}), KwargInfo('new_dict', (ContainerTypeInfo(list, str), ContainerTypeInfo(dict, str)), default={}, since_values={dict: '1.1'}), + KwargInfo('foo', (str, int, ContainerTypeInfo(list, str), ContainerTypeInfo(dict, str), ContainerTypeInfo(list, int)), default={}, + since_values={str: '1.1', ContainerTypeInfo(list, str): '1.2', ContainerTypeInfo(dict, str): '1.3'}, + deprecated_values={int: '0.8', ContainerTypeInfo(list, int): '0.9'}), + KwargInfo('tuple', (ContainerTypeInfo(list, (str, int))), default=[], listify=True, + since_values={ContainerTypeInfo(list, str): '1.1', ContainerTypeInfo(list, int): '1.2'}), ) def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: pass @@ -1433,7 +1439,7 @@ 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 targets '1.0'.*deprecated since '0.9': "testfunc" keyword argument "output" value "foo2". dont use it.*""") + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*deprecated since '0.9': "testfunc" keyword argument "output" value "foo2" in dict keys. 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'}}) @@ -1441,7 +1447,40 @@ 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 targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "output" value "bar2". use this.*""") + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "output" value "bar2" in dict keys. use this.*""") + + with self.subTest('new string type'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'foo': 'foo'}) + self.assertRegex(out.getvalue(), r"""WARNING: Project targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "foo" of type str.*""") + + with self.subTest('new array of string type'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'foo': ['foo']}) + self.assertRegex(out.getvalue(), r"""WARNING: Project targets '1.0'.*introduced in '1.2': "testfunc" keyword argument "foo" of type array\[str\].*""") + + with self.subTest('new dict of string type'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'foo': {'plop': 'foo'}}) + self.assertRegex(out.getvalue(), r"""WARNING: Project targets '1.0'.*introduced in '1.3': "testfunc" keyword argument "foo" of type dict\[str\].*""") + + with self.subTest('deprecated int value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'foo': 1}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*deprecated since '0.8': "testfunc" keyword argument "foo" of type int.*""") + + with self.subTest('deprecated array int value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'foo': [1]}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*deprecated since '0.9': "testfunc" keyword argument "foo" of type array\[int\].*""") + + with self.subTest('new list[str] value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'tuple': ['foo', 42]}) + self.assertRegex(out.getvalue(), r"""WARNING: Project targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "tuple" of type array\[str\].*""") + self.assertRegex(out.getvalue(), r"""WARNING: Project targets '1.0'.*introduced in '1.2': "testfunc" keyword argument "tuple" of type array\[int\].*""") + + 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 targets '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 targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "input" value "bar".*""") with self.subTest('non string union'), mock.patch('sys.stdout', io.StringIO()) as out: _(None, mock.Mock(subproject=''), [], {'install_dir': False}) @@ -1541,12 +1580,12 @@ ('ppc', 'ppc'), ('macppc', 'ppc'), ('power macintosh', 'ppc'), - ('mips64el', 'mips64'), - ('mips64', 'mips64'), + ('mips64el', 'mips'), + ('mips64', 'mips'), ('mips', 'mips'), ('mipsel', 'mips'), - ('ip30', 'mips64'), - ('ip35', 'mips64'), + ('ip30', 'mips'), + ('ip35', 'mips'), ('parisc64', 'parisc'), ('sun4u', 'sparc64'), ('sun4v', 'sparc64'), @@ -1557,15 +1596,27 @@ ('aarch64_be', 'aarch64'), ] + cc = ClangCCompiler([], [], 'fake', MachineChoice.HOST, False, mock.Mock()) + 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({}) + actual = mesonbuild.environment.detect_cpu_family({'c': cc}) 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')]: + for test, expected in [('x86_64', 'x86'), ('aarch64', 'arm'), ('ppc', 'ppc64'), ('mips64', 'mips64')]: with self.subTest(test, has_define=True), mock_trial(test): + actual = mesonbuild.environment.detect_cpu_family({'c': cc}) + self.assertEqual(actual, expected) + + # machine_info_can_run calls detect_cpu_family with no compilers at all + with mock.patch( + 'mesonbuild.environment.any_compiler_has_define', + mock.Mock(side_effect=AssertionError('Should not be called')), + ): + for test, expected in [('mips64', 'mips64')]: + with self.subTest(test, has_compiler=False), mock_trial(test): actual = mesonbuild.environment.detect_cpu_family({}) self.assertEqual(actual, expected) @@ -1586,23 +1637,34 @@ ('x64', 'x86_64'), ('i86pc', 'x86_64'), ('earm', 'arm'), - ('mips64el', 'mips64'), - ('mips64', 'mips64'), + ('mips64el', 'mips'), + ('mips64', 'mips'), ('mips', 'mips'), ('mipsel', 'mips'), ('aarch64', 'aarch64'), ('aarch64_be', 'aarch64'), ] + cc = ClangCCompiler([], [], 'fake', MachineChoice.HOST, False, mock.Mock()) + 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({}) + actual = mesonbuild.environment.detect_cpu({'c': cc}) 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')]: + for test, expected in [('x86_64', 'i686'), ('aarch64', 'arm'), ('ppc', 'ppc64'), ('mips64', 'mips64')]: with self.subTest(test, has_define=True), mock_trial(test): + actual = mesonbuild.environment.detect_cpu({'c': cc}) + self.assertEqual(actual, expected) + + with mock.patch( + 'mesonbuild.environment.any_compiler_has_define', + mock.Mock(side_effect=AssertionError('Should not be called')), + ): + for test, expected in [('mips64', 'mips64')]: + with self.subTest(test, has_compiler=False), mock_trial(test): actual = mesonbuild.environment.detect_cpu({}) self.assertEqual(actual, expected) diff -Nru meson-1.0.1/unittests/linuxliketests.py meson-1.2.1/unittests/linuxliketests.py --- meson-1.0.1/unittests/linuxliketests.py 2022-12-10 16:46:15.000000000 +0000 +++ meson-1.2.1/unittests/linuxliketests.py 2023-08-07 22:54:34.000000000 +0000 @@ -45,7 +45,7 @@ from mesonbuild.compilers.cpp import AppleClangCPPCompiler from mesonbuild.compilers.objc import AppleClangObjCCompiler from mesonbuild.compilers.objcpp import AppleClangObjCPPCompiler -from mesonbuild.dependencies import PkgConfigDependency +from mesonbuild.dependencies.pkgconfig import PkgConfigDependency import mesonbuild.modules.pkgconfig PKG_CONFIG = os.environ.get('PKG_CONFIG', 'pkg-config') @@ -1024,7 +1024,7 @@ def test_cross_find_program(self): testdir = os.path.join(self.unit_test_dir, '11 cross prog') - crossfile = tempfile.NamedTemporaryFile(mode='w') + crossfile = tempfile.NamedTemporaryFile(mode='w', encoding='utf-8') print(os.path.join(testdir, 'some_cross_tool.py')) tool_path = os.path.join(testdir, 'some_cross_tool.py') @@ -1350,7 +1350,7 @@ see: https://github.com/mesonbuild/meson/issues/9000 https://stackoverflow.com/questions/48532868/gcc-library-option-with-a-colon-llibevent-a ''' - testdir = os.path.join(self.unit_test_dir, '97 link full name','libtestprovider') + testdir = os.path.join(self.unit_test_dir, '98 link full name','libtestprovider') oldprefix = self.prefix # install into installdir without using DESTDIR installdir = self.installdir @@ -1363,7 +1363,7 @@ self.new_builddir() env = {'LIBRARY_PATH': os.path.join(installdir, self.libdir), 'PKG_CONFIG_PATH': _prepend_pkg_config_path(os.path.join(installdir, self.libdir, 'pkgconfig'))} - testdir = os.path.join(self.unit_test_dir, '97 link full name','proguser') + testdir = os.path.join(self.unit_test_dir, '98 link full name','proguser') self.init(testdir,override_envvars=env) # test for link with full path @@ -1517,14 +1517,14 @@ def test_identity_cross(self): testdir = os.path.join(self.unit_test_dir, '60 identity cross') - constantsfile = tempfile.NamedTemporaryFile(mode='w') + constantsfile = tempfile.NamedTemporaryFile(mode='w', encoding='utf-8') constantsfile.write(textwrap.dedent('''\ [constants] py_ext = '.py' ''')) constantsfile.flush() - nativefile = tempfile.NamedTemporaryFile(mode='w') + nativefile = tempfile.NamedTemporaryFile(mode='w', encoding='utf-8') nativefile.write(textwrap.dedent('''\ [binaries] c = ['{}' + py_ext] @@ -1532,7 +1532,7 @@ nativefile.flush() self.meson_native_files = [constantsfile.name, nativefile.name] - crossfile = tempfile.NamedTemporaryFile(mode='w') + crossfile = tempfile.NamedTemporaryFile(mode='w', encoding='utf-8') crossfile.write(textwrap.dedent('''\ [binaries] c = ['{}' + py_ext] @@ -1549,7 +1549,7 @@ 'CC_FOR_BUILD': '"' + os.path.join(testdir, 'build_wrapper.py') + '"', 'CC': '"' + os.path.join(testdir, 'host_wrapper.py') + '"', } - crossfile = tempfile.NamedTemporaryFile(mode='w') + crossfile = tempfile.NamedTemporaryFile(mode='w', encoding='utf-8') crossfile.write('') crossfile.flush() self.meson_cross_files = [crossfile.name] @@ -1775,7 +1775,7 @@ @skipUnless(is_linux() or is_osx(), 'Test only applicable to Linux and macOS') def test_install_strip(self): - testdir = os.path.join(self.unit_test_dir, '103 strip') + testdir = os.path.join(self.unit_test_dir, '104 strip') self.init(testdir) self.build() @@ -1822,9 +1822,31 @@ self.assertFalse(cpp.compiler_args([f'-isystem{symlink}' for symlink in default_symlinks]).to_native()) def test_freezing(self): - testdir = os.path.join(self.unit_test_dir, '109 freeze') + testdir = os.path.join(self.unit_test_dir, '110 freeze') self.init(testdir) self.build() with self.assertRaises(subprocess.CalledProcessError) as e: self.run_tests() self.assertNotIn('Traceback', e.exception.output) + + @skipUnless(is_linux(), "Ninja file differs on different platforms") + def test_complex_link_cases(self): + testdir = os.path.join(self.unit_test_dir, '113 complex link cases') + self.init(testdir) + self.build() + with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as f: + content = f.read() + # Verify link dependencies, see comments in meson.build. + self.assertIn('build libt1-s3.a: STATIC_LINKER libt1-s2.a.p/s2.c.o libt1-s3.a.p/s3.c.o\n', content) + self.assertIn('build t1-e1: c_LINKER t1-e1.p/main.c.o | libt1-s1.a libt1-s3.a\n', content) + self.assertIn('build libt2-s3.a: STATIC_LINKER libt2-s2.a.p/s2.c.o libt2-s1.a.p/s1.c.o libt2-s3.a.p/s3.c.o\n', content) + self.assertIn('build t2-e1: c_LINKER t2-e1.p/main.c.o | libt2-s3.a\n', content) + self.assertIn('build t3-e1: c_LINKER t3-e1.p/main.c.o | libt3-s3.so.p/libt3-s3.so.symbols\n', content) + self.assertIn('build t4-e1: c_LINKER t4-e1.p/main.c.o | libt4-s2.so.p/libt4-s2.so.symbols libt4-s3.a\n', content) + self.assertIn('build t5-e1: c_LINKER t5-e1.p/main.c.o | libt5-s1.so.p/libt5-s1.so.symbols libt5-s3.a\n', content) + self.assertIn('build t6-e1: c_LINKER t6-e1.p/main.c.o | libt6-s2.a libt6-s3.a\n', content) + self.assertIn('build t7-e1: c_LINKER t7-e1.p/main.c.o | libt7-s3.a\n', content) + self.assertIn('build t8-e1: c_LINKER t8-e1.p/main.c.o | libt8-s1.a libt8-s2.a libt8-s3.a\n', content) + self.assertIn('build t9-e1: c_LINKER t9-e1.p/main.c.o | libt9-s1.a libt9-s2.a libt9-s3.a\n', content) + self.assertIn('build t12-e1: c_LINKER t12-e1.p/main.c.o | libt12-s1.a libt12-s2.a libt12-s3.a\n', content) + self.assertIn('build t13-e1: c_LINKER t13-e1.p/main.c.o | libt12-s1.a libt13-s3.a\n', content) diff -Nru meson-1.0.1/unittests/machinefiletests.py meson-1.2.1/unittests/machinefiletests.py --- meson-1.0.1/unittests/machinefiletests.py 2022-12-16 18:51:36.000000000 +0000 +++ meson-1.2.1/unittests/machinefiletests.py 2023-07-21 20:36:13.000000000 +0000 @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations + import subprocess import tempfile import textwrap @@ -67,7 +69,7 @@ self.current_config = 0 self.current_wrapper = 0 - def helper_create_native_file(self, values): + def helper_create_native_file(self, values: T.Dict[str, T.Dict[str, T.Union[str, int, float, bool, T.Sequence[T.Union[str, int, float, bool]]]]]) -> str: """Create a config file as a temporary file. values should be a nested dictionary structure of {section: {key: @@ -81,10 +83,10 @@ 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: + elif isinstance(v, str): f.write(f"{k}='{v}'\n") + else: + f.write("{}=[{}]\n".format(k, ', '.join([f"'{w}'" for w in v]))) return filename def helper_create_binary_wrapper(self, binary, dir_=None, extra_args=None, **kwargs): @@ -140,7 +142,7 @@ return batfile def helper_for_compiler(self, lang, cb, for_machine = MachineChoice.HOST): - """Helper for generating tests for overriding compilers for langaugages + """Helper for generating tests for overriding compilers for languages with more than one implementation, such as C, C++, ObjC, ObjC++, and D. """ env = get_fake_env() @@ -373,7 +375,7 @@ def test_java_classpath(self): if self.backend is not Backend.ninja: raise SkipTest('Jar is only supported with Ninja') - testdir = os.path.join(self.unit_test_dir, '110 classpath') + testdir = os.path.join(self.unit_test_dir, '111 classpath') self.init(testdir) self.build() one_build_path = get_classpath(os.path.join(self.builddir, 'one.jar')) @@ -622,6 +624,29 @@ else: self.fail('Did not find bindir in build options?') + @skip_if_not_language('rust') + def test_bindgen_clang_arguments(self) -> None: + if self.backend is not Backend.ninja: + raise SkipTest('Rust is only supported with Ninja') + + testcase = os.path.join(self.rust_test_dir, '12 bindgen') + config = self.helper_create_native_file({ + 'properties': {'bindgen_clang_arguments': 'sentinal'} + }) + + self.init(testcase, extra_args=['--native-file', config]) + targets: T.List[T.Dict[str, T.Any]] = self.introspect('--targets') + for t in targets: + if t['id'].startswith('rustmod-bindgen'): + args: T.List[str] = t['target_sources'][0]['compiler'] + self.assertIn('sentinal', args, msg="Did not find machine file value") + cargs_start = args.index('--') + sent_arg = args.index('sentinal') + self.assertLess(cargs_start, sent_arg, msg='sentinal argument does not come after "--"') + break + else: + self.fail('Did not find a bindgen target') + class CrossFileTests(BasePlatformTests): @@ -719,7 +744,7 @@ # 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.') + @skipIf('MESON_EXE' in os.environ, 'MESON_EXE is defined, cannot use mocking.') def test_cross_file_system_paths(self): if is_windows(): raise SkipTest('system crossfile paths not defined for Windows (yet)') @@ -729,7 +754,7 @@ 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: + with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False, encoding='utf-8') as f: f.write(cross_content) name = os.path.basename(f.name) @@ -745,7 +770,7 @@ 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: + with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False, encoding='utf-8') as f: f.write(cross_content) name = os.path.basename(f.name) diff -Nru meson-1.0.1/unittests/platformagnostictests.py meson-1.2.1/unittests/platformagnostictests.py --- meson-1.0.1/unittests/platformagnostictests.py 2022-12-10 16:46:15.000000000 +0000 +++ meson-1.2.1/unittests/platformagnostictests.py 2023-07-21 20:36:13.000000000 +0000 @@ -12,17 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. +import json import os +import pickle import tempfile import subprocess import textwrap -from unittest import skipIf +from unittest import skipIf, SkipTest from pathlib import Path from .baseplatformtests import BasePlatformTests from .helpers import is_ci -from mesonbuild.mesonlib import is_linux +from mesonbuild.mesonlib import EnvironmentVariables, ExecutableSerialisation, is_linux, python_command from mesonbuild.optinterpreter import OptionInterpreter, OptionException +from run_tests import Backend @skipIf(is_ci() and not is_linux(), "Run only on fast platforms") class PlatformAgnosticTests(BasePlatformTests): @@ -35,7 +38,7 @@ Tests that find_program() with a relative path does not find the program in current workdir. ''' - testdir = os.path.join(self.unit_test_dir, '100 relative find program') + testdir = os.path.join(self.unit_test_dir, '101 relative find program') self.init(testdir, workdir=testdir) def test_invalid_option_names(self): @@ -71,11 +74,11 @@ interp.process(fname) def test_python_dependency_without_pkgconfig(self): - testdir = os.path.join(self.unit_test_dir, '102 python without pkgconfig') + testdir = os.path.join(self.unit_test_dir, '103 python without pkgconfig') self.init(testdir, override_envvars={'PKG_CONFIG': 'notfound'}) def test_debug_function_outputs_to_meson_log(self): - testdir = os.path.join(self.unit_test_dir, '104 debug function') + testdir = os.path.join(self.unit_test_dir, '105 debug function') log_msg = 'This is an example debug output, should only end up in debug log' output = self.init(testdir) @@ -87,7 +90,7 @@ self.assertIn(log_msg, mesonlog) def test_new_subproject_reconfigure(self): - testdir = os.path.join(self.unit_test_dir, '107 new subproject on reconfigure') + testdir = os.path.join(self.unit_test_dir, '108 new subproject on reconfigure') self.init(testdir) self.build() @@ -121,3 +124,133 @@ ''')) subprocess.check_call(self.wrap_command + ['update-db'], cwd=testdir) self.init(testdir, workdir=testdir) + + def test_none_backend(self): + testdir = os.path.join(self.python_test_dir, '7 install path') + + self.init(testdir, extra_args=['--backend=none'], override_envvars={'NINJA': 'absolutely false command'}) + self.assertPathDoesNotExist(os.path.join(self.builddir, 'build.ninja')) + + self.run_tests(inprocess=True, override_envvars={}) + + out = self._run(self.meson_command + ['install', f'--destdir={self.installdir}'], workdir=self.builddir) + self.assertNotIn('Only ninja backend is supported to rebuild the project before installation.', out) + + with open(os.path.join(testdir, 'test.json'), 'rb') as f: + dat = json.load(f) + for i in dat['installed']: + self.assertPathExists(os.path.join(self.installdir, i['file'])) + + def test_change_backend(self): + if self.backend != Backend.ninja: + raise SkipTest('Only useful to test if backend is ninja.') + + testdir = os.path.join(self.python_test_dir, '7 install path') + self.init(testdir) + + # no-op change works + self.setconf(f'--backend=ninja') + self.init(testdir, extra_args=['--reconfigure', '--backend=ninja']) + + # Change backend option is not allowed + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.setconf('-Dbackend=none') + self.assertIn("ERROR: Tried modify read only option 'backend'", cm.exception.stdout) + + # Reconfigure with a different backend is not allowed + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testdir, extra_args=['--reconfigure', '--backend=none']) + self.assertIn("ERROR: Tried modify read only option 'backend'", cm.exception.stdout) + + # Wipe with a different backend is allowed + self.init(testdir, extra_args=['--wipe', '--backend=none']) + + def test_validate_dirs(self): + testdir = os.path.join(self.common_test_dir, '1 trivial') + + # Using parent as builddir should fail + self.builddir = os.path.dirname(self.builddir) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testdir) + self.assertIn('cannot be a parent of source directory', cm.exception.stdout) + + # Reconfigure of empty builddir should work + self.new_builddir() + self.init(testdir, extra_args=['--reconfigure']) + + # Reconfigure of not empty builddir should work + self.new_builddir() + Path(self.builddir, 'dummy').touch() + self.init(testdir, extra_args=['--reconfigure']) + + # Wipe of empty builddir should work + self.new_builddir() + self.init(testdir, extra_args=['--wipe']) + + # Wipe of partial builddir should work + self.new_builddir() + Path(self.builddir, 'meson-private').mkdir() + Path(self.builddir, 'dummy').touch() + self.init(testdir, extra_args=['--wipe']) + + # Wipe of not empty builddir should fail + self.new_builddir() + Path(self.builddir, 'dummy').touch() + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testdir, extra_args=['--wipe']) + self.assertIn('Directory is not empty', cm.exception.stdout) + + def test_scripts_loaded_modules(self): + ''' + Simulate a wrapped command, as done for custom_target() that capture + output. The script will print all python modules loaded and we verify + that it contains only an acceptable subset. Loading too many modules + slows down the build when many custom targets get wrapped. + + This list must not be edited without a clear rationale for why it is + acceptable to do so! + ''' + es = ExecutableSerialisation(python_command + ['-c', 'exit(0)'], env=EnvironmentVariables()) + p = Path(self.builddir, 'exe.dat') + with p.open('wb') as f: + pickle.dump(es, f) + cmd = self.meson_command + ['--internal', 'test_loaded_modules', '--unpickle', str(p)] + p = subprocess.run(cmd, stdout=subprocess.PIPE) + all_modules = json.loads(p.stdout.splitlines()[0]) + meson_modules = [m for m in all_modules if m.startswith('mesonbuild')] + expected_meson_modules = [ + 'mesonbuild', + 'mesonbuild._pathlib', + 'mesonbuild.utils', + 'mesonbuild.utils.core', + 'mesonbuild.mesonmain', + 'mesonbuild.mlog', + 'mesonbuild.scripts', + 'mesonbuild.scripts.meson_exe', + 'mesonbuild.scripts.test_loaded_modules' + ] + self.assertEqual(sorted(expected_meson_modules), sorted(meson_modules)) + + def test_setup_loaded_modules(self): + ''' + Execute a very basic meson.build and capture a list of all python + modules loaded. We verify that it contains only an acceptable subset. + Loading too many modules slows down `meson setup` startup time and + gives a perception that meson is slow. + + Adding more modules to the default startup flow is not an unreasonable + thing to do as new features are added, but keeping track of them is + good. + ''' + testdir = os.path.join(self.unit_test_dir, '114 empty project') + + self.init(testdir) + self._run(self.meson_command + ['--internal', 'regenerate', '--profile-self', testdir, self.builddir]) + with open(os.path.join(self.builddir, 'meson-logs', 'profile-startup-modules.json'), encoding='utf-8') as f: + data = json.load(f)['meson'] + + with open(os.path.join(testdir, 'expected_mods.json'), encoding='utf-8') as f: + expected = json.load(f)['meson']['modules'] + + self.assertEqual(data['modules'], expected) + self.assertEqual(data['count'], 68) diff -Nru meson-1.0.1/unittests/pythontests.py meson-1.2.1/unittests/pythontests.py --- meson-1.0.1/unittests/pythontests.py 2022-12-10 16:46:15.000000000 +0000 +++ meson-1.2.1/unittests/pythontests.py 2023-07-05 15:40:06.000000000 +0000 @@ -12,19 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os -import unittest -import pathlib -import subprocess +import glob, os, pathlib, shutil, subprocess, unittest from run_tests import ( Backend ) from .allplatformstests import git_init - from .baseplatformtests import BasePlatformTests -from mesonbuild.mesonlib import TemporaryDirectoryWinProof +from .helpers import * + +from mesonbuild.mesonlib import MachineChoice, TemporaryDirectoryWinProof +from mesonbuild.modules.python import PythonModule class PythonTests(BasePlatformTests): ''' @@ -60,3 +59,41 @@ git_init(dirstr) self.init(dirstr) subprocess.check_call(self.meson_command + ['dist', '-C', self.builddir], stdout=subprocess.DEVNULL) + + def _test_bytecompile(self, py2=False): + testdir = os.path.join(self.src_root, 'test cases', 'python', '2 extmodule') + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + + self.init(testdir, extra_args=['-Dpython2=auto', '-Dpython.bytecompile=1']) + self.build() + self.install() + + count = 0 + for root, dirs, files in os.walk(self.installdir): + for file in files: + realfile = os.path.join(root, file) + if file.endswith('.py'): + cached = glob.glob(realfile+'?') + glob.glob(os.path.join(root, '__pycache__', os.path.splitext(file)[0] + '*.pyc')) + if py2 and cc.get_id() == 'msvc': + # MSVC python installs python2/python3 into the same directory + self.assertLength(cached, 4) + else: + self.assertLength(cached, 2) + count += 1 + # there are 5 files x 2 installations + if py2 and not cc.get_id() == 'msvc': + self.assertEqual(count, 10) + else: + self.assertEqual(count, 5) + + def test_bytecompile_multi(self): + if not shutil.which('python2') and not PythonModule._get_win_pythonpath('python2'): + raise self.skipTest('python2 not installed') + self._test_bytecompile(True) + + def test_bytecompile_single(self): + if shutil.which('python2') or PythonModule._get_win_pythonpath('python2'): + raise self.skipTest('python2 installed, already tested') + self._test_bytecompile() diff -Nru meson-1.0.1/unittests/rewritetests.py meson-1.2.1/unittests/rewritetests.py --- meson-1.0.1/unittests/rewritetests.py 2022-12-10 16:46:15.000000000 +0000 +++ meson-1.2.1/unittests/rewritetests.py 2023-05-23 15:20:02.000000000 +0000 @@ -156,7 +156,7 @@ } self.assertDictEqual(out, expected) - def test_tatrget_add(self): + def test_target_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')) diff -Nru meson-1.0.1/unittests/subprojectscommandtests.py meson-1.2.1/unittests/subprojectscommandtests.py --- meson-1.0.1/unittests/subprojectscommandtests.py 2022-12-10 16:46:15.000000000 +0000 +++ meson-1.2.1/unittests/subprojectscommandtests.py 2023-05-23 15:20:02.000000000 +0000 @@ -177,6 +177,17 @@ self.assertEqual(self._git_local_commit(subp_name), self._git_remote_commit(subp_name, 'newbranch')) self.assertTrue(self._git_local(['stash', 'list'], subp_name)) + # Untracked files need to be stashed too, or (re-)applying a patch + # creating one of those untracked files will fail. + untracked = self.subprojects_dir / subp_name / 'untracked.c' + untracked.write_bytes(b'int main(void) { return 0; }') + self._subprojects_cmd(['update', '--reset']) + self.assertTrue(self._git_local(['stash', 'list'], subp_name)) + assert not untracked.exists() + # Ensure it was indeed stashed, and we can get it back. + self.assertTrue(self._git_local(['stash', 'pop'], subp_name)) + assert untracked.exists() + # 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') diff -Nru meson-1.0.1/unittests/windowstests.py meson-1.2.1/unittests/windowstests.py --- meson-1.0.1/unittests/windowstests.py 2022-12-10 16:46:15.000000000 +0000 +++ meson-1.2.1/unittests/windowstests.py 2023-08-07 22:54:24.000000000 +0000 @@ -184,6 +184,93 @@ # to the right reason). return self.build() + + @skipIf(is_cygwin(), 'Test only applicable to Windows') + def test_genvslite(self): + # The test framework itself might be forcing a specific, non-ninja backend across a set of tests, which + # includes this test. E.g. - + # > python.exe run_unittests.py --backend=vs WindowsTests + # Since that explicitly specifies a backend that's incompatible with (and essentially meaningless in + # conjunction with) 'genvslite', we should skip further genvslite testing. + if self.backend is not Backend.ninja: + raise SkipTest('Test only applies when using the Ninja backend') + + testdir = os.path.join(self.unit_test_dir, '115 genvslite') + + 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 when MSVC tools are available.') + + # We want to run the genvslite setup. I.e. - + # meson setup --genvslite vs2022 ... + # which we should expect to generate the set of _debug/_debugoptimized/_release suffixed + # build directories. Then we want to check that the solution/project build hooks (like clean, + # build, and rebuild) end up ultimately invoking the 'meson compile ...' of the appropriately + # suffixed build dir, for which we need to use 'msbuild.exe' + + # Find 'msbuild.exe' + msbuildprog = ExternalProgram('msbuild.exe') + self.assertTrue(msbuildprog.found(), msg='msbuild.exe not found') + + # Setup with '--genvslite ...' + self.new_builddir() + + # Firstly, we'd like to check that meson errors if the user explicitly specifies a non-ninja backend + # during setup. + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testdir, extra_args=['--genvslite', 'vs2022', '--backend', 'vs']) + self.assertIn("specifying a non-ninja backend conflicts with a 'genvslite' setup", cm.exception.stdout) + + # Wrap the following bulk of setup and msbuild invocation testing in a try-finally because any exception, + # failure, or success must always clean up any of the suffixed build dir folders that may have been generated. + try: + # Since this + self.init(testdir, extra_args=['--genvslite', 'vs2022']) + # We need to bear in mind that the BasePlatformTests framework creates and cleans up its own temporary + # build directory. However, 'genvslite' creates a set of suffixed build directories which we'll have + # to clean up ourselves. See 'finally' block below. + + # We intentionally skip the - + # self.build() + # step because we're wanting to test compilation/building through the solution/project's interface. + + # Execute the debug and release builds through the projects 'Build' hooks + genvslite_vcxproj_path = str(os.path.join(self.builddir+'_vs', 'genvslite@exe.vcxproj')) + # This use-case of invoking the .sln/.vcxproj build hooks, not through Visual Studio itself, but through + # 'msbuild.exe', in a VS tools command prompt environment (e.g. "x64 Native Tools Command Prompt for VS 2022"), is a + # problem: Such an environment sets the 'VSINSTALLDIR' variable which, mysteriously, has the side-effect of causing + # the spawned 'meson compile' command to fail to find 'ninja' (and even when ninja can be found elsewhere, all the + # compiler binaries that ninja wants to run also fail to be found). The PATH environment variable in the child python + # (and ninja) processes are fundamentally stripped down of all the critical search paths required to run the ninja + # compile work ... ONLY when 'VSINSTALLDIR' is set; without 'VSINSTALLDIR' set, the meson compile command does search + # for and find ninja (ironically, it finds it under the path where VSINSTALLDIR pointed!). + # For the above reason, this testing works around this bizarre behaviour by temporarily removing any 'VSINSTALLDIR' + # variable, prior to invoking the builds - + current_env = os.environ.copy() + current_env.pop('VSINSTALLDIR', None) + subprocess.check_call( + ['msbuild', '-target:Build', '-property:Configuration=debug', genvslite_vcxproj_path], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + env=current_env) + subprocess.check_call( + ['msbuild', '-target:Build', '-property:Configuration=release', genvslite_vcxproj_path], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + env=current_env) + + # Check this has actually built the appropriate exes + output_debug = subprocess.check_output(str(os.path.join(self.builddir+'_debug', 'genvslite.exe'))) + self.assertEqual( output_debug, b'Debug\r\n' ) + output_release = subprocess.check_output(str(os.path.join(self.builddir+'_release', 'genvslite.exe'))) + self.assertEqual( output_release, b'Non-debug\r\n' ) + + finally: + # Clean up our special suffixed temporary build dirs + suffixed_build_dirs = glob(self.builddir+'_*', recursive=False) + for build_dir in suffixed_build_dirs: + shutil.rmtree(build_dir) def test_install_pdb_introspection(self): testdir = os.path.join(self.platform_test_dir, '1 basic') @@ -375,6 +462,9 @@ @unittest.skipIf(is_cygwin(), "Needs visual studio") def test_vsenv_option(self): + if mesonbuild.environment.detect_msys2_arch(): + # https://github.com/msys2-contrib/cpython-mingw/issues/141 + raise SkipTest('mingw python fails with /bin being removed from PATH') if self.backend is not Backend.ninja: raise SkipTest('Only ninja backend is valid for test') env = os.environ.copy()