diff --git a/ci/ciimage/arch/install.sh b/ci/ciimage/arch/install.sh index a6ef5e0a918e..b886bcaecc6d 100755 --- a/ci/ciimage/arch/install.sh +++ b/ci/ciimage/arch/install.sh @@ -14,7 +14,8 @@ pkgs=( itstool glib2-devel gtk3 java-environment=8 gtk-doc llvm clang sdl2 graphviz doxygen vulkan-validation-layers openssh mercurial gtk-sharp-2 qt5-tools libwmf cmake netcdf-fortran openmpi nasm gnustep-base gettext - python-lxml hotdoc rust-bindgen qt6-base qt6-tools qt6-declarative wayland wayland-protocols + python-lxml hotdoc rust-bindgen qt6-base qt6-tools qt6-declarative wayland + wayland-protocols zig # cuda ) diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index 1c5f9a33a4f3..3565c9b94f43 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -5,97 +5,98 @@ These are return values of the `get_id` (Compiler family) and `get_argument_syntax` (Argument syntax) method in a compiler object. -| Value | Compiler family | Argument syntax | -| ----- | --------------- | --------------- | -| arm | ARM compiler | | -| armclang | ARMCLANG compiler | | -| ccomp | The CompCert formally-verified C compiler | | -| ccrx | Renesas RX Family C/C++ compiler | | -| clang | The Clang compiler | gcc | -| clang-cl | The Clang compiler (MSVC compatible driver) | msvc | -| dmd | D lang reference compiler | | -| emscripten| Emscripten WASM compiler | | -| flang | Classic Flang Fortran compiler | | -| g95 | The G95 Fortran compiler | | -| gcc | The GNU Compiler Collection | gcc | -| intel | Intel compiler (Linux and Mac) | gcc | -| intel-cl | Intel compiler (Windows) | msvc | -| intel-llvm | Intel oneAPI LLVM-based compiler | | -| intel-llvm-cl | Intel oneAPI LLVM-based compiler (Windows) | msvc | -| lcc | Elbrus C/C++/Fortran Compiler | | -| llvm | LLVM-based compiler (Swift, D) | | -| llvm-flang| Flang Fortran compiler (LLVM-based) | | -| mono | Xamarin C# compiler | | -| mwccarm | Metrowerks C/C++ compiler for Embedded ARM | | -| mwcceppc | Metrowerks C/C++ compiler for Embedded PowerPC | | -| msvc | Microsoft Visual Studio | msvc | -| nagfor | The NAG Fortran compiler | | -| nvidia_hpc| NVidia HPC SDK compilers | | -| nvcc | NVidia CUDA compiler | | -| open64 | The Open64 Fortran Compiler | | -| pathscale | The Pathscale Fortran compiler | | -| pgi | Portland PGI C/C++/Fortran compilers | | -| rustc | Rust compiler | | -| sun | Sun Fortran compiler | | -| c2000 | Texas Instruments C/C++ Compiler (C2000) | | -| c6000 | Texas Instruments C/C++ Compiler (C6000) | | -| ti | Texas Instruments C/C++ Compiler | | -| valac | Vala compiler | | -| xc16 | Microchip XC16 C compiler | | -| cython | The Cython compiler | | -| nasm | The NASM compiler (Since 0.64.0) | | -| yasm | The YASM compiler (Since 0.64.0) | | -| ml | Microsoft Macro Assembler for x86 and x86_64 (Since 0.64.0) | msvc | -| armasm | Microsoft Macro Assembler for ARM and AARCH64 (Since 0.64.0) | | -| mwasmarm | Metrowerks Assembler for Embedded ARM | | -| mwasmeppc | Metrowerks Assembler for Embedded PowerPC | | -| tasking | TASKING VX-toolset | | +| Value | Compiler family | Argument syntax | +| ------------- | ------------------------------------------------------------ | --------------- | +| arm | ARM compiler | | +| armclang | ARMCLANG compiler | | +| ccomp | The CompCert formally-verified C compiler | | +| ccrx | Renesas RX Family C/C++ compiler | | +| clang | The Clang compiler | gcc | +| clang-cl | The Clang compiler (MSVC compatible driver) | msvc | +| dmd | D lang reference compiler | | +| emscripten | Emscripten WASM compiler | | +| flang | Classic Flang Fortran compiler | | +| g95 | The G95 Fortran compiler | | +| gcc | The GNU Compiler Collection | gcc | +| intel | Intel compiler (Linux and Mac) | gcc | +| intel-cl | Intel compiler (Windows) | msvc | +| intel-llvm | Intel oneAPI LLVM-based compiler | | +| intel-llvm-cl | Intel oneAPI LLVM-based compiler (Windows) | msvc | +| lcc | Elbrus C/C++/Fortran Compiler | | +| llvm | LLVM-based compiler (Swift, D) | | +| llvm-flang | Flang Fortran compiler (LLVM-based) | | +| mono | Xamarin C# compiler | | +| mwccarm | Metrowerks C/C++ compiler for Embedded ARM | | +| mwcceppc | Metrowerks C/C++ compiler for Embedded PowerPC | | +| msvc | Microsoft Visual Studio | msvc | +| nagfor | The NAG Fortran compiler | | +| nvidia_hpc | NVidia HPC SDK compilers | | +| nvcc | NVidia CUDA compiler | | +| open64 | The Open64 Fortran Compiler | | +| pathscale | The Pathscale Fortran compiler | | +| pgi | Portland PGI C/C++/Fortran compilers | | +| rustc | Rust compiler | | +| sun | Sun Fortran compiler | | +| c2000 | Texas Instruments C/C++ Compiler (C2000) | | +| c6000 | Texas Instruments C/C++ Compiler (C6000) | | +| ti | Texas Instruments C/C++ Compiler | | +| valac | Vala compiler | | +| xc16 | Microchip XC16 C compiler | | +| cython | The Cython compiler | | +| nasm | The NASM compiler (Since 0.64.0) | | +| yasm | The YASM compiler (Since 0.64.0) | | +| ml | Microsoft Macro Assembler for x86 and x86_64 (Since 0.64.0) | msvc | +| armasm | Microsoft Macro Assembler for ARM and AARCH64 (Since 0.64.0) | | +| mwasmarm | Metrowerks Assembler for Embedded ARM | | +| mwasmeppc | Metrowerks Assembler for Embedded PowerPC | | +| tasking | TASKING VX-toolset | | +| zig | Zig compiler | | ## Linker ids These are return values of the `get_linker_id` method in a compiler object. -| Value | Linker family | -| ----- | --------------- | -| ld.bfd | The GNU linker | -| ld.gold | The GNU gold linker | -| ld.lld | The LLVM linker, with the GNU interface | -| ld.mold | The fast MOLD linker | -| ld.solaris | Solaris and illumos | -| ld.wasm | emscripten's wasm-ld linker | -| ld.zigcc | The Zig linker (C/C++ frontend; GNU-like) | -| ld64 | Apple ld64 | -| ld64.lld | The LLVM linker, with the ld64 interface | -| link | MSVC linker | -| lld-link | The LLVM linker, with the MSVC interface | -| xilink | Used with Intel-cl only, MSVC like | -| optlink | optlink (used with DMD) | -| rlink | The Renesas linker, used with CCrx only | -| xc16-ar | The Microchip linker, used with XC16 only | -| ar2000 | The Texas Instruments linker, used with C2000 only | -| ti-ar | The Texas Instruments linker | -| ar6000 | The Texas Instruments linker, used with C6000 only | -| armlink | The ARM linker (arm and armclang compilers) | -| pgi | Portland/Nvidia PGI | -| nvlink | Nvidia Linker used with cuda | -| ccomp | CompCert used as the linker driver | -| mwldarm | The Metrowerks Linker with the ARM interface, used with mwccarm only | +| Value | Linker family | +| ---------- | ------------------------------------------------------------------------- | +| ld.bfd | The GNU linker | +| ld.gold | The GNU gold linker | +| ld.lld | The LLVM linker, with the GNU interface | +| ld.mold | The fast MOLD linker | +| ld.solaris | Solaris and illumos | +| ld.wasm | emscripten's wasm-ld linker | +| ld.zigcc | The Zig linker (C/C++ frontend; GNU-like) | +| ld64 | Apple ld64 | +| ld64.lld | The LLVM linker, with the ld64 interface | +| link | MSVC linker | +| lld-link | The LLVM linker, with the MSVC interface | +| xilink | Used with Intel-cl only, MSVC like | +| optlink | optlink (used with DMD) | +| rlink | The Renesas linker, used with CCrx only | +| xc16-ar | The Microchip linker, used with XC16 only | +| ar2000 | The Texas Instruments linker, used with C2000 only | +| ti-ar | The Texas Instruments linker | +| ar6000 | The Texas Instruments linker, used with C6000 only | +| armlink | The ARM linker (arm and armclang compilers) | +| pgi | Portland/Nvidia PGI | +| nvlink | Nvidia Linker used with cuda | +| ccomp | CompCert used as the linker driver | +| mwldarm | The Metrowerks Linker with the ARM interface, used with mwccarm only | | mwldeppc | The Metrowerks Linker with the PowerPC interface, used with mwcceppc only | -| tasking | TASKING VX-toolset | +| tasking | TASKING VX-toolset | For languages that don't have separate dynamic linkers such as C# and Java, the `get_linker_id` will return the compiler name. ## Script environment variables -| Value | Comment | -| ----- | ------- | -| MESONINTROSPECT | Command to run to run the introspection command, may be of the form `python /path/to/meson introspect`, user is responsible for splitting the path if necessary. | -| MESONREWRITE | Command to run to run the rewriting command, only set when running `dist` scripts | -| MESON_BUILD_ROOT | Absolute path to the build dir | -| MESON_DIST_ROOT | Points to the root of the staging directory, only set when running `dist` scripts | -| MESON_SOURCE_ROOT | Absolute path to the source dir | -| MESON_SUBDIR | Current subdirectory, only set for `run_command` | +| Value | Comment | +| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| MESONINTROSPECT | Command to run to run the introspection command, may be of the form `python /path/to/meson introspect`, user is responsible for splitting the path if necessary. | +| MESONREWRITE | Command to run to run the rewriting command, only set when running `dist` scripts | +| MESON_BUILD_ROOT | Absolute path to the build dir | +| MESON_DIST_ROOT | Points to the root of the staging directory, only set when running `dist` scripts | +| MESON_SOURCE_ROOT | Absolute path to the source dir | +| MESON_SUBDIR | Current subdirectory, only set for `run_command` | ## CPU families @@ -103,45 +104,45 @@ These are returned by the `cpu_family` method of `build_machine`, `host_machine` and `target_machine`. For cross compilation they are set in the cross file. -| Value | Comment | -| ----- | ------- | -| aarch64 | 64 bit ARM processor | -| alpha | DEC Alpha processor | -| arc | 32 bit ARC processor | -| arm | 32 bit ARM processor | -| avr | Atmel AVR processor | -| c2000 | 32 bit C2000 processor | -| c6000 | 32 bit C6000 processor | -| csky | 32 bit CSky processor | -| dspic | 16 bit Microchip dsPIC | -| e2k | MCST Elbrus processor | -| ft32 | 32 bit Bridgetek MCU | -| ia64 | Itanium processor | -| loongarch64 | 64 bit Loongson processor| -| m68k | Motorola 68000 processor | -| microblaze | MicroBlaze processor | -| mips | 32 bit MIPS processor | -| mips64 | 64 bit MIPS processor | -| msp430 | 16 bit MSP430 processor | -| parisc | HP PA-RISC processor | -| pic24 | 16 bit Microchip PIC24 | -| ppc | 32 bit PPC processors | -| ppc64 | 64 bit PPC processors | -| riscv32 | 32 bit RISC-V Open ISA | -| riscv64 | 64 bit RISC-V Open ISA | -| rl78 | Renesas RL78 | -| rx | Renesas RX 32 bit MCU | -| s390 | IBM zSystem s390 | -| s390x | IBM zSystem s390x | -| sh4 | SuperH SH-4 | -| sparc | 32 bit SPARC | -| sparc64 | SPARC v9 processor | -| sw_64 | 64 bit sunway processor | -| wasm32 | 32 bit Webassembly | -| wasm64 | 64 bit Webassembly | -| x86 | 32 bit x86 processor | -| x86_64 | 64 bit x86 processor | -| tricore | Tricore 32 bit processor | +| Value | Comment | +| ----------- | ------------------------- | +| aarch64 | 64 bit ARM processor | +| alpha | DEC Alpha processor | +| arc | 32 bit ARC processor | +| arm | 32 bit ARM processor | +| avr | Atmel AVR processor | +| c2000 | 32 bit C2000 processor | +| c6000 | 32 bit C6000 processor | +| csky | 32 bit CSky processor | +| dspic | 16 bit Microchip dsPIC | +| e2k | MCST Elbrus processor | +| ft32 | 32 bit Bridgetek MCU | +| ia64 | Itanium processor | +| loongarch64 | 64 bit Loongson processor | +| m68k | Motorola 68000 processor | +| microblaze | MicroBlaze processor | +| mips | 32 bit MIPS processor | +| mips64 | 64 bit MIPS processor | +| msp430 | 16 bit MSP430 processor | +| parisc | HP PA-RISC processor | +| pic24 | 16 bit Microchip PIC24 | +| ppc | 32 bit PPC processors | +| ppc64 | 64 bit PPC processors | +| riscv32 | 32 bit RISC-V Open ISA | +| riscv64 | 64 bit RISC-V Open ISA | +| rl78 | Renesas RL78 | +| rx | Renesas RX 32 bit MCU | +| s390 | IBM zSystem s390 | +| s390x | IBM zSystem s390x | +| sh4 | SuperH SH-4 | +| sparc | 32 bit SPARC | +| sparc64 | SPARC v9 processor | +| sw_64 | 64 bit sunway processor | +| wasm32 | 32 bit Webassembly | +| wasm64 | 64 bit Webassembly | +| x86 | 32 bit x86 processor | +| x86_64 | 64 bit x86 processor | +| tricore | Tricore 32 bit processor | Any cpu family not listed in the above list is not guaranteed to @@ -156,21 +157,21 @@ also check the `.endian()` value of the machine for this information. These are provided by the `.system()` method call. -| Value | Comment | -| ----- | ------- | -| android | By convention only, subject to change | -| cygwin | Cygwin or MSYS2 environment on Windows | -| darwin | Either OSX or iOS | -| dragonfly | DragonFly BSD | -| emscripten | Emscripten's JavaScript environment | -| freebsd | FreeBSD and its derivatives | -| gnu | GNU Hurd | -| haiku | | -| linux | | -| netbsd | | -| openbsd | | -| windows | Native Windows (not Cygwin or MSYS2) | -| sunos | illumos and Solaris | +| Value | Comment | +| ---------- | -------------------------------------- | +| android | By convention only, subject to change | +| cygwin | Cygwin or MSYS2 environment on Windows | +| darwin | Either OSX or iOS | +| dragonfly | DragonFly BSD | +| emscripten | Emscripten's JavaScript environment | +| freebsd | FreeBSD and its derivatives | +| gnu | GNU Hurd | +| haiku | | +| linux | | +| netbsd | | +| openbsd | | +| windows | Native Windows (not Cygwin or MSYS2) | +| sunos | illumos and Solaris | Any string not listed above is not guaranteed to remain stable in future releases. @@ -179,20 +180,20 @@ future releases. Native names as returned by the `.kernel()` method. -| Value | Comment | -| ----- | ------- | -| linux | | -| freebsd | | -| openbsd | | -| netbsd | | -| gnu | GNU Hurd | -| nt | | -| xnu | Kernel of various Apple OSes | -| illumos | Kernel derived from OpenSolaris by community efforts | -| solaris | Kernel derived from OpenSolaris by Oracle | -| dragonfly | | -| haiku| | -| none | For e.g. bare metal embedded | +| Value | Comment | +| --------- | ---------------------------------------------------- | +| linux | | +| freebsd | | +| openbsd | | +| netbsd | | +| gnu | GNU Hurd | +| nt | | +| xnu | Kernel of various Apple OSes | +| illumos | Kernel derived from OpenSolaris by community efforts | +| solaris | Kernel derived from OpenSolaris by Oracle | +| dragonfly | | +| haiku | | +| none | For e.g. bare metal embedded | ## Subsystem names (since 1.2.0) @@ -201,15 +202,15 @@ A more specific description of the system in question. Most values are meant to be used in cross files only, as those platforms can not run Meson natively. -| Value | Comment | -| ----- | ------- | -| macos | Apple macOS (formerly OSX) | -| ios | Apple iOS | -| ios-simulator | | -| tvos | Apple tvOS | -| tvos-simulator | | -| watchos | Apple watchOS | -| watchos-simulator | | +| Value | Comment | +| ----------------- | -------------------------- | +| macos | Apple macOS (formerly OSX) | +| ios | Apple iOS | +| ios-simulator | | +| tvos | Apple tvOS | +| tvos-simulator | | +| watchos | Apple watchOS | +| watchos-simulator | | ## Language arguments parameter names @@ -233,6 +234,7 @@ to your build target. | NASM | nasm_args | N/A | | MASM | masm_args | N/A | | Linear ASM | linearasm_args | N/A | +| Zig | zig_args | zig_link_args | All these `_*` options are specified per machine. See in [specifying options per @@ -251,7 +253,7 @@ It is **highly** recommended that you use [the command line arguments](#language-arguments-parameter-names) instead. | Name | Comment | -| ----- | ------- | +| ----------- | ---------------------------------------- | | CFLAGS | Flags for the C compiler | | CXXFLAGS | Flags for the C++ compiler | | CUFLAGS | Flags for the CUDA compiler | @@ -280,7 +282,7 @@ which are supported by GCC, Clang, and other compilers. | Name | -|-----------------------------| +| --------------------------- | | alias | | aligned | | alloc_size | @@ -350,10 +352,10 @@ which are supported by GCC, Clang, and other compilers. These values are supported using the MSVC style `__declspec` annotation, which are supported by MSVC, GCC, Clang, and other compilers. -| Name | -|----------------------| -| dllexport | -| dllimport | +| Name | +| --------- | +| dllexport | +| dllimport | ## Dependency lookup methods @@ -361,14 +363,14 @@ which are supported by MSVC, GCC, Clang, and other compilers. These are the values that can be passed to `dependency` function's `method` keyword argument. -| Name | Comment | -| ----- | ------- | -| auto | Automatic method selection | -| pkg-config | Use Pkg-Config | -| cmake | Look up as a CMake module | -| config-tool | Use a custom dep tool such as `cups-config` | -| system | System provided (e.g. OpenGL) | -| extraframework | A macOS/iOS framework | +| Name | Comment | +| -------------- | ------------------------------------------- | +| auto | Automatic method selection | +| pkg-config | Use Pkg-Config | +| cmake | Look up as a CMake module | +| config-tool | Use a custom dep tool such as `cups-config` | +| system | System provided (e.g. OpenGL) | +| extraframework | A macOS/iOS framework | ## Compiler and Linker selection variables @@ -377,20 +379,20 @@ N.B. these settings are specified per machine, and so the environment variables actually come in pairs. See the [environment variables per machine](#Environment-variables-per-machine) section for details. -| Language | Compiler | Linker | Note | -|---------------|----------|-----------|---------------------------------------------| -| C | CC | CC_LD | | -| C++ | CXX | CXX_LD | | -| D | DC | DC_LD | Before 0.54 D_LD* | -| Fortran | FC | FC_LD | Before 0.54 F_LD* | -| Objective-C | OBJC | OBJC_LD | | -| Objective-C++ | OBJCXX | OBJCXX_LD | Before 0.54 OBJCPP_LD* | -| Rust | RUSTC | RUSTC_LD | Before 0.54 RUST_LD* | -| Vala | VALAC | | Use CC_LD. Vala transpiles to C | -| C# | CSC | CSC | The linker is the compiler | -| Cython | CYTHON | | | -| nasm | NASM | | Uses the C linker | -| archiver | | AR | | +| Language | Compiler | Linker | Note | +| ------------- | -------- | --------- | ------------------------------- | +| C | CC | CC_LD | | +| C++ | CXX | CXX_LD | | +| D | DC | DC_LD | Before 0.54 D_LD* | +| Fortran | FC | FC_LD | Before 0.54 F_LD* | +| Objective-C | OBJC | OBJC_LD | | +| Objective-C++ | OBJCXX | OBJCXX_LD | Before 0.54 OBJCPP_LD* | +| Rust | RUSTC | RUSTC_LD | Before 0.54 RUST_LD* | +| Vala | VALAC | | Use CC_LD. Vala transpiles to C | +| C# | CSC | CSC | The linker is the compiler | +| Cython | CYTHON | | | +| nasm | NASM | | Uses the C linker | +| archiver | | AR | | *The old environment variables are still supported, but are deprecated and will be removed in a future version of Meson. diff --git a/docs/markdown/snippets/zig_language_support.md b/docs/markdown/snippets/zig_language_support.md new file mode 100644 index 000000000000..7e8cfe6dd1a5 --- /dev/null +++ b/docs/markdown/snippets/zig_language_support.md @@ -0,0 +1,5 @@ +## Basic support for the Zig language + +Meson now supports the compilation of basic Zig +programs. Support for more advanced scenarios +is not implemented yet. diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 8d9796db95c6..3031e77f89fa 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -59,7 +59,7 @@ class TargetIntrospectionData(TypedDict): # Languages that can mix with C or C++ but don't support unity builds yet # because the syntax we use for unity builds is specific to C/++/ObjC/++. # Assembly files cannot be unitified and neither can LLVM IR files -LANGS_CANT_UNITY = ('d', 'fortran', 'vala') +LANGS_CANT_UNITY = ('d', 'fortran', 'vala', 'zig') @dataclass(eq=False) class RegenInfo: diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 24758866c6b5..a9a5fc8bb68a 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -958,10 +958,9 @@ def generate_target(self, target) -> None: outname = self.get_target_filename(target) obj_list = [] is_unity = target.is_unity - header_deps = [] + header_deps = self.get_generated_headers(target) unity_src = [] unity_deps = [] # Generated sources that must be built before compiling a Unity target. - header_deps += self.get_generated_headers(target) if is_unity: # Warn about incompatible sources if a unity build is enabled @@ -1086,6 +1085,8 @@ def generate_target(self, target) -> None: if is_compile_target: # Skip the link stage for this special type of target return + if target.uses_zig(): + pass linker, stdlib_args = self.determine_linker_and_stdlib_args(target) if not isinstance(target, build.StaticLibrary): @@ -1412,7 +1413,7 @@ def add_build(self, build: NinjaBuildElement) -> None: if build.rulename in self.ruledict: build.rule = self.ruledict[build.rulename] else: - mlog.warning(f"build statement for {build.outfilenames} references nonexistent rule {build.rulename}") + raise MesonBugException(f"build statement for {build.outfilenames} references nonexistent rule {build.rulename}") def write_rules(self, outfile: T.TextIO) -> None: for b in self.build_elements: @@ -2357,7 +2358,11 @@ def generate_dynamic_link_rules(self) -> None: continue rule = '{}_LINKER{}'.format(langname, self.get_rule_suffix(for_machine)) command = compiler.get_linker_exelist() - args = ['$ARGS'] + NinjaCommandArg.list(compiler.get_linker_output_args('$out'), Quoting.none) + ['$in', '$LINK_ARGS'] + args: T.List[str] = [] + if langname == 'zig': + args.append('$MODE') + args += ['$ARGS'] + args += NinjaCommandArg.list(compiler.get_linker_output_args('$out'), Quoting.none) + ['$in', '$LINK_ARGS'] description = 'Linking target $out' if num_pools > 0: pool = 'pool = link_pool' @@ -2432,6 +2437,13 @@ def generate_rust_compile_rules(self, compiler) -> None: self.add_rule(NinjaRule(rule, command, [], description, deps=depstyle, depfile=depfile)) + def generate_zig_compile_rules(self, compiler: Compiler) -> None: + rule = self.compiler_to_rule_name(compiler) + command = compiler.get_exelist() + ['$ARGS', '$in'] + command += NinjaCommandArg.list(compiler.get_output_args('$out'), Quoting.none) + description = 'Compiling Zig source $in' + self.add_rule(NinjaRule(rule, command, [], description)) + def generate_swift_compile_rules(self, compiler) -> None: rule = self.compiler_to_rule_name(compiler) full_exe = self.environment.get_build_command() + [ @@ -2517,6 +2529,9 @@ def generate_compile_rule_for(self, langname: str, compiler: Compiler) -> None: if langname == 'rust': self.generate_rust_compile_rules(compiler) return + if langname == 'zig': + self.generate_zig_compile_rules(compiler) + return if langname == 'swift': if self.environment.machines.matches_build_machine(compiler.for_machine): self.generate_swift_compile_rules(compiler) @@ -2983,14 +2998,14 @@ def generate_common_compile_args_per_src_type(self, target: build.BuildTarget) - src_type_to_args[src_type_str] = commands.to_native() return src_type_to_args - def generate_single_compile(self, target: build.BuildTarget, src, + def generate_single_compile(self, target: build.BuildTarget, src: mesonlib.FileOrString, is_generated: bool = False, header_deps=None, order_deps: T.Optional[T.List[FileOrString]] = None, extra_args: T.Optional[T.List[str]] = None, unity_sources: T.Optional[T.List[FileOrString]] = None, ) -> T.Tuple[str, str]: """ - Compiles C/C++, ObjC/ObjC++, Fortran, and D sources + Compiles C/C++, ObjC/ObjC++, Fortran, D, and Zig sources """ header_deps = header_deps if header_deps is not None else [] order_deps = order_deps if order_deps is not None else [] @@ -3619,6 +3634,8 @@ def generate_link(self, target: build.BuildTarget, outname, obj_list, linker: T. elem.add_item('ARGS', compile_args) elem.add_item('LINK_ARGS', commands) + if linker.id == 'zig': + elem.add_item('MODE', 'build-exe' if isinstance(target, build.Executable) else 'build-lib') self.create_target_linker_introspection(target, linker, commands) return elem diff --git a/mesonbuild/build.py b/mesonbuild/build.py index c72857d2c1ae..768d7090b456 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1662,6 +1662,9 @@ def get_used_stdlib_args(self, link_language: str) -> T.List[str]: def uses_rust(self) -> bool: return 'rust' in self.compilers + def uses_zig(self) -> bool: + return 'zig' in self.compilers + def uses_rust_abi(self) -> bool: return self.uses_rust() and self.rust_crate_type in {'dylib', 'rlib', 'proc-macro'} diff --git a/mesonbuild/compilers/__init__.py b/mesonbuild/compilers/__init__.py index 1d2d34c47fe3..9c428ca0d94e 100644 --- a/mesonbuild/compilers/__init__.py +++ b/mesonbuild/compilers/__init__.py @@ -41,6 +41,7 @@ 'detect_rust_compiler', 'detect_d_compiler', 'detect_swift_compiler', + 'detect_zig_compiler', ] # Bring symbols from each module into compilers sub-package namespace @@ -83,4 +84,5 @@ detect_rust_compiler, detect_d_compiler, detect_swift_compiler, + detect_zig_compiler, ) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 424bcc19bf6a..b7bb85245705 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2022 The Meson development team -# Copyright © 2023-2024 Intel Corporation +# Copyright © 2023-2025 Intel Corporation from __future__ import annotations @@ -70,6 +70,7 @@ 'nasm': ('asm', 'nasm',), 'masm': ('masm',), 'linearasm': ('sa',), + 'zig': ('zig',), } all_languages = lang_suffixes.keys() c_cpp_suffixes = {'h'} @@ -86,7 +87,7 @@ # 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(). -clink_langs = ('d', 'cuda') + clib_langs +clink_langs = ('zig', 'd', 'cuda') + clib_langs SUFFIX_TO_LANG = dict(itertools.chain(*( [(suffix, lang) for suffix in v] for lang, v in lang_suffixes.items()))) @@ -110,6 +111,7 @@ 'rust': 'RUSTFLAGS', 'cython': 'CYTHONFLAGS', 'cs': 'CSFLAGS', # This one might not be standard. + 'zig': 'ZIGFLAGS', # This is not standard } # All these are only for C-linkable languages; see `clink_langs` above. diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index d4ad4badeefd..bfdca308ba02 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -79,6 +79,7 @@ defaults['gcc_static_linker'] = ['gcc-ar'] defaults['clang_static_linker'] = ['llvm-ar'] defaults['nasm'] = ['nasm', 'yasm'] +defaults['zig'] = ['zig'] def compiler_from_language(env: 'Environment', lang: str, for_machine: MachineChoice) -> T.Optional[Compiler]: @@ -99,6 +100,7 @@ def compiler_from_language(env: 'Environment', lang: str, for_machine: MachineCh 'nasm': detect_nasm_compiler, 'masm': detect_masm_compiler, 'linearasm': detect_linearasm_compiler, + 'zig': detect_zig_compiler, } return lang_map[lang](env, for_machine) if lang in lang_map else None @@ -1401,6 +1403,28 @@ def detect_linearasm_compiler(env: Environment, for_machine: MachineChoice) -> C _handle_exceptions(popen_exceptions, [comp]) raise EnvironmentException('Unreachable code (exception to make mypy happy)') +def detect_zig_compiler(env: Environment, for_machine: MachineChoice) -> Compiler: + from .zig import ZigCompiler + from ..linkers.linkers import ZigDynamicLinker + exelist = env.lookup_binary_entry(for_machine, 'zig') + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + if exelist is None: + exelist = defaults['zig'] + + try: + _, ver, _ = Popen_safe([exelist[0], 'version']) + except OSError: + raise EnvironmentException('Could not execute Zig compiler "{}"'.format(' '.join(exelist))) + + version = search_version(ver) + linker = ZigDynamicLinker(exelist, for_machine, '', [], version=version) + comp = ZigCompiler(exelist, version, for_machine, info, linker, env.exe_wrapper, is_cross) + env.coredata.add_lang_args(comp.language, ZigCompiler, for_machine, env) + + return comp + + # GNU/Clang defines and version # ============================= diff --git a/mesonbuild/compilers/mixins/islinker.py b/mesonbuild/compilers/mixins/islinker.py index 8d17a94b2d16..b725046538d6 100644 --- a/mesonbuild/compilers/mixins/islinker.py +++ b/mesonbuild/compilers/mixins/islinker.py @@ -118,3 +118,7 @@ def thread_flags(self, env: 'Environment') -> T.List[str]: def thread_link_flags(self, env: 'Environment') -> T.List[str]: return [] + + def headerpad_args(self) -> T.List[str]: + # Only used by the Apple linker + return [] diff --git a/mesonbuild/compilers/zig.py b/mesonbuild/compilers/zig.py new file mode 100644 index 000000000000..f3c00d01c28c --- /dev/null +++ b/mesonbuild/compilers/zig.py @@ -0,0 +1,143 @@ +# Copyright 2012-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations + +import os +import subprocess +import textwrap +import typing as T + +from ..mesonlib import MachineChoice, EnvironmentException, MesonException +from .compilers import Compiler + +if T.TYPE_CHECKING: + from .._typing import ImmutableListProtocol + from ..envconfig import MachineInfo + from ..environment import Environment + from ..linkers.linkers import DynamicLinker + from ..programs import ExternalProgram + + +_OPTIMIZATION_ARGS: T.Mapping[str, ImmutableListProtocol[str]] = { + '0': [], + 'g': ['-O', 'Debug'], + '1': ['-O', 'ReleaseSafe'], + '2': ['-O', 'ReleaseSafe'], + '3': ['-O', 'ReleaseFast'], + 's': ['-O', 'ReleaseSmall'], +} + + +class ZigCompiler(Compiler): + language = 'zig' + + # TODO: lto + # TODO: threads? That seems more like code sanitizers than actual threading + # TODO: rpath + # TODO: darwin specific things + # TODO: emit header? + # TODO: structured_sources? + # TODO: tests? + # TODO: good solution for the need to link with libc + # TODO: demonstrate linking with rust + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, info: 'MachineInfo', + linker: DynamicLinker, exe_wrapper: T.Optional['ExternalProgram'] = None, is_cross: bool = False): + super().__init__([], exelist + ['build-obj'], version, for_machine, info, linker, is_cross=is_cross) + self.id = 'zig' + self.exe_wrapper = exe_wrapper + + def depfile_for_object(self, objfile: str) -> T.Optional[str]: + # not implemented currently: https://github.com/ziglang/zig/issues/16850 + return None + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i[:2] == '-I' or i[:2] == '-L': + parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) + + return parameter_list + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + return [] + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return _OPTIMIZATION_ARGS[optimization_level].copy() + + def get_output_args(self, outputname: str) -> T.List[str]: + return [f'-femit-bin={outputname}'] + + def get_pic_args(self) -> T.List[str]: + return ['-fPIC'] + + def get_win_subsystem_args(self, value: str) -> T.List[str]: + return ['--subsystem', value] + + def get_colorout_args(self, colortype: str) -> T.List[str]: + if colortype == 'auto': + return ['--color', 'auto'] + elif colortype == 'always': + return ['--color', 'on'] + elif colortype == 'never': + return ['--color', 'off'] + else: + raise MesonException(f'Invalid color type for zig {colortype}') + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if not path: + path = '.' + if is_system: + return ['-isystem' + path] + return ['-I' + path] + + def needs_static_linker(self) -> bool: + return True + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + source_name = os.path.join(work_dir, 'sanity.zig') + output_name = os.path.join(work_dir, 'zigtest') + + with open(source_name, 'w', encoding='utf-8') as ofile: + ofile.write(textwrap.dedent( + '''pub fn main() !void { + } + ''')) + + # Compile the source file to an executable + # Drop the added `build-obj` + pc = subprocess.Popen(self.exelist[:-1] + ['build-exe', source_name] + self.get_output_args(output_name), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=work_dir) + _stdo, _stde = pc.communicate() + stdo = _stdo.decode('utf-8', errors='replace') + stde = _stde.decode('utf-8', errors='replace') + + # Check if the build was successful + if pc.returncode != 0: + raise EnvironmentException(f'Zig compiler {self.name_string()} can not compile programs.\n{stdo}\n{stde}') + + if self.is_cross: + if self.exe_wrapper is None: + # Can't check if the binaries run so we have to assume they do + return + cmdlist = self.exe_wrapper.get_command() + [output_name] + else: + cmdlist = [output_name] + + # Check if the built executable is runnable + pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + if pe.wait() != 0: + raise EnvironmentException(f'Executables created by Zig compiler {self.name_string()} are not runnable.') diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 4055b21761c5..cc73049858ff 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -98,6 +98,7 @@ 'rust': 'RUSTC', 'vala': 'VALAC', 'nasm': 'NASM', + 'zig': 'ZIGC', # Linkers 'c_ld': 'CC_LD', diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 176fb3348204..4fb638b1f6bf 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -1738,3 +1738,25 @@ def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: for a in args: l.extend(self._apply_prefix('-Wl--whole-archive=' + a)) return l + +class ZigDynamicLinker(DynamicLinker): + + id = 'zig' + + def get_output_args(self, outputname: str) -> T.List[str]: + return [f'-femit-bin={outputname}'] + + def import_library_args(self, implibname: str) -> T.List[str]: + return [f'-emit-implib={implibname}'] + + def get_search_args(self, dirname: str) -> T.List[str]: + return [f'-L{dirname}'] + + def get_allow_undefined_args(self) -> T.List[str]: + return ['-fallow-shlib-undefined'] + + def no_undefined_args(self) -> T.List[str]: + return ['f-no-allow-shlib-undefined'] + + def get_std_shared_lib_args(self) -> T.List[str]: + return ['-dynamic'] diff --git a/run_project_tests.py b/run_project_tests.py index 0dc287191f21..8de3af716244 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -75,12 +75,14 @@ class ArgumentType(CompilerArgumentType): only: T.List[str] v: bool -ALL_TESTS = ['cmake', 'common', 'native', 'warning-meson', 'failing-meson', 'failing-build', 'failing-test', - 'keyval', 'platform-osx', 'platform-windows', 'platform-linux', - 'java', 'C#', 'vala', 'cython', 'rust', 'd', 'objective c', 'objective c++', - 'fortran', 'swift', 'cuda', 'python3', 'python', 'fpga', 'frameworks', 'nasm', 'wasm', 'wayland', - 'format', - ] +ALL_TESTS = [ + 'cmake', 'common', 'native', 'warning-meson', 'failing-meson', + 'failing-build', 'failing-test', 'keyval', 'platform-osx', + 'platform-windows', 'platform-linux', 'java', 'C#', 'vala', 'cython', + 'rust', 'd', 'objective c', 'objective c++', 'fortran', 'swift', 'cuda', + 'python3', 'python', 'fpga', 'frameworks', 'nasm', 'wasm', 'wayland', + 'format', 'zig', +] class BuildStep(Enum): @@ -1143,6 +1145,7 @@ def __init__(self, category: str, subdir: str, skip: bool = False, stdout_mandat TestCategory('wasm', 'wasm', shutil.which('emcc') is None or backend is not Backend.ninja), TestCategory('wayland', 'wayland', should_skip_wayland()), TestCategory('format', 'format'), + TestCategory('zig', 'zig', shutil.which('zig') is None or backend is not Backend.ninja), ] categories = [t.category for t in all_tests] diff --git a/test cases/zig/1 basic/meson.build b/test cases/zig/1 basic/meson.build new file mode 100644 index 000000000000..29d6e62d41e2 --- /dev/null +++ b/test cases/zig/1 basic/meson.build @@ -0,0 +1,5 @@ +project('zigtest-exe', 'zig') + +executable('zigtest', 'src/main.zig', + zig_args: ['-fstrip'] +) diff --git a/test cases/zig/1 basic/src/main.zig b/test cases/zig/1 basic/src/main.zig new file mode 100644 index 000000000000..cfda5798e3df --- /dev/null +++ b/test cases/zig/1 basic/src/main.zig @@ -0,0 +1,5 @@ +const std = @import("std"); + +pub fn main() !void { + std.debug.print("Hello from {s}!", .{"meson"}); +} diff --git a/test cases/zig/2 sharedlib/meson.build b/test cases/zig/2 sharedlib/meson.build new file mode 100644 index 000000000000..1031a68bd6b3 --- /dev/null +++ b/test cases/zig/2 sharedlib/meson.build @@ -0,0 +1,10 @@ +project('zigtest-shared-lib', 'zig') + +lib = shared_library('hello', 'src/hello.zig', + version: '1.0.0', + install: true +) +executable('zigtest-shared-lib', 'src/main.zig', + link_with: lib, + install: true +) diff --git a/test cases/zig/2 sharedlib/src/hello.zig b/test cases/zig/2 sharedlib/src/hello.zig new file mode 100644 index 000000000000..73930bb8fc4b --- /dev/null +++ b/test cases/zig/2 sharedlib/src/hello.zig @@ -0,0 +1,3 @@ +export fn hello() *const [5:0]u8 { + return "meson"; +} diff --git a/test cases/zig/2 sharedlib/src/main.zig b/test cases/zig/2 sharedlib/src/main.zig new file mode 100644 index 000000000000..1899d2365431 --- /dev/null +++ b/test cases/zig/2 sharedlib/src/main.zig @@ -0,0 +1,7 @@ +const std = @import("std"); + +extern fn hello() *const [5:0]u8; + +pub fn main() !void { + std.debug.print("Hello from {s}!", .{hello()}); +} diff --git a/test cases/zig/2 sharedlib/test.json b/test cases/zig/2 sharedlib/test.json new file mode 100644 index 000000000000..781d400fd343 --- /dev/null +++ b/test cases/zig/2 sharedlib/test.json @@ -0,0 +1,8 @@ +{ + "installed": [ + {"type": "exe", "file": "usr/bin/zigtest-shared-lib"}, + {"type": "shared_lib", "file": "usr/lib/hello", "version": "1.0.0"}, + {"type": "shared_lib", "file": "usr/lib/hello", "version": "1"}, + {"type": "shared_lib", "file": "usr/lib/hello"} + ] +} diff --git a/test cases/zig/3 staticlib/meson.build b/test cases/zig/3 staticlib/meson.build new file mode 100644 index 000000000000..d38b3e88bbaa --- /dev/null +++ b/test cases/zig/3 staticlib/meson.build @@ -0,0 +1,6 @@ +project('zigtest-static-lib', 'zig') + +lib = static_library('hello', 'src/hello.zig') +executable('zigtest-static-lib', 'src/main.zig', + link_with: lib +) diff --git a/test cases/zig/3 staticlib/src/hello.zig b/test cases/zig/3 staticlib/src/hello.zig new file mode 100644 index 000000000000..73930bb8fc4b --- /dev/null +++ b/test cases/zig/3 staticlib/src/hello.zig @@ -0,0 +1,3 @@ +export fn hello() *const [5:0]u8 { + return "meson"; +} diff --git a/test cases/zig/3 staticlib/src/main.zig b/test cases/zig/3 staticlib/src/main.zig new file mode 100644 index 000000000000..1899d2365431 --- /dev/null +++ b/test cases/zig/3 staticlib/src/main.zig @@ -0,0 +1,7 @@ +const std = @import("std"); + +extern fn hello() *const [5:0]u8; + +pub fn main() !void { + std.debug.print("Hello from {s}!", .{hello()}); +} diff --git a/test cases/zig/4 polyglot/meson.build b/test cases/zig/4 polyglot/meson.build new file mode 100644 index 000000000000..5aefede14418 --- /dev/null +++ b/test cases/zig/4 polyglot/meson.build @@ -0,0 +1,13 @@ +project('zigtest-polyglot', 'c', 'zig') + +lib = library('hello', 'src/hello.c') +executable('zigtest-polyglot', 'src/main.zig', + link_with: lib +) + +executable('all-in-one', 'src/hello.c', 'src/main.zig') + +fs = import('fs') + +copied = fs.copyfile('src/hello.c', 'copy.c') +executable('generated-c-static-zig', 'src/main.zig', copied) diff --git a/test cases/zig/4 polyglot/src/hello.c b/test cases/zig/4 polyglot/src/hello.c new file mode 100644 index 000000000000..72956619cfbe --- /dev/null +++ b/test cases/zig/4 polyglot/src/hello.c @@ -0,0 +1,4 @@ +const char *hello(void) +{ + return "meson"; +} diff --git a/test cases/zig/4 polyglot/src/main.zig b/test cases/zig/4 polyglot/src/main.zig new file mode 100644 index 000000000000..1899d2365431 --- /dev/null +++ b/test cases/zig/4 polyglot/src/main.zig @@ -0,0 +1,7 @@ +const std = @import("std"); + +extern fn hello() *const [5:0]u8; + +pub fn main() !void { + std.debug.print("Hello from {s}!", .{hello()}); +} diff --git a/test cases/zig/5 deps/meson.build b/test cases/zig/5 deps/meson.build new file mode 100644 index 000000000000..452b3db82d60 --- /dev/null +++ b/test cases/zig/5 deps/meson.build @@ -0,0 +1,11 @@ +project('zigtest-deps', 'zig') + +curl_dep = dependency('libcurl') + +executable( + 'zigtest-deps', + 'src/main.zig', + zig_args : '-lc', # XXX: I don't like this solution at all. + link_args : '-lc', + dependencies : curl_dep, +) diff --git a/test cases/zig/5 deps/src/main.zig b/test cases/zig/5 deps/src/main.zig new file mode 100644 index 000000000000..f80042ba96b4 --- /dev/null +++ b/test cases/zig/5 deps/src/main.zig @@ -0,0 +1,12 @@ +const std = @import("std"); + +const cUrl = @cImport({ + @cInclude("curl/curl.h"); +}); + +pub fn main() !void { + const handle: ?*cUrl.CURL = cUrl.curl_easy_init(); + std.debug.print("Hello curl {s} from {s}!", .{cUrl.curl_version(), "meson"}); + + cUrl.curl_easy_cleanup(handle); +} diff --git a/test cases/zig/6 incdirs/include/test.h b/test cases/zig/6 incdirs/include/test.h new file mode 100644 index 000000000000..1826c8e0275b --- /dev/null +++ b/test cases/zig/6 incdirs/include/test.h @@ -0,0 +1,9 @@ +#ifndef _ZIGTEST_TEST_H +#define _ZIGTEST_TEST_H + +inline const char *hello(void) +{ + return "meson"; +} + +#endif diff --git a/test cases/zig/6 incdirs/meson.build b/test cases/zig/6 incdirs/meson.build new file mode 100644 index 000000000000..5f3d0098eb7a --- /dev/null +++ b/test cases/zig/6 incdirs/meson.build @@ -0,0 +1,5 @@ +project('zigtest-includedirs', 'zig') + +executable('zigtest-includedirs', 'src/main.zig', + include_directories: include_directories('include') +) diff --git a/test cases/zig/6 incdirs/src/main.zig b/test cases/zig/6 incdirs/src/main.zig new file mode 100644 index 000000000000..22e39085c13d --- /dev/null +++ b/test cases/zig/6 incdirs/src/main.zig @@ -0,0 +1,9 @@ +const std = @import("std"); + +const cHello = @cImport({ + @cInclude("test.h"); +}); + +pub fn main() !void { + std.debug.print("Hello from {s}!", .{cHello.hello()}); +}