summaryrefslogtreecommitdiff
path: root/eclass
diff options
context:
space:
mode:
authorV3n3RiX <venerix@koprulu.sector>2024-12-16 02:01:58 +0000
committerV3n3RiX <venerix@koprulu.sector>2024-12-16 02:01:58 +0000
commite07c6f9648d478943b5ecd6f1c42cc91cae0f547 (patch)
tree2c56c6944fb4016ee510ee97a1a158baf49edfe4 /eclass
parent16a4365c3b854e62b50726456ddb29bb78fd5038 (diff)
gentoo auto-resync : 16:12:2024 - 02:01:58
Diffstat (limited to 'eclass')
-rw-r--r--eclass/Manifest.gzbin39355 -> 39840 bytes
-rwxr-xr-xeclass/tests/zig-utils.sh320
-rw-r--r--eclass/toolchain.eclass12
-rw-r--r--eclass/zig-utils.eclass538
-rw-r--r--eclass/zig.eclass558
5 files changed, 1426 insertions, 2 deletions
diff --git a/eclass/Manifest.gz b/eclass/Manifest.gz
index c45c90c387a2..86a7a86682d6 100644
--- a/eclass/Manifest.gz
+++ b/eclass/Manifest.gz
Binary files differ
diff --git a/eclass/tests/zig-utils.sh b/eclass/tests/zig-utils.sh
new file mode 100755
index 000000000000..14af1d2105e3
--- /dev/null
+++ b/eclass/tests/zig-utils.sh
@@ -0,0 +1,320 @@
+#!/bin/bash
+# Copyright 2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+source tests-common.sh || exit
+
+inherit zig-utils
+
+# Set ZIG_TEST_COMPILATION env-var to "1" if you want to test binary
+# compilation and running under QEMU. Assumes "zig" is present in PATH
+# and qemu binfmt is enabled.
+#
+# If CPU is marked with ":no-run", it means program compiled for it
+# successfully but crashed when running under QEMU.
+if [[ "${ZIG_TEST_COMPILATION:-0}" -eq 1 ]]; then
+ MY_WORKDIR="$(mktemp -d)"
+ my_cleanup() {
+ popd > /dev/null
+ rm -rf "${MY_WORKDIR}"
+ }
+ trap 'my_cleanup' EXIT
+
+ pushd "${MY_WORKDIR}" > /dev/null || die
+ cat <<- _EOF_ > main.zig || die
+ const std = @import("std");
+
+ pub fn main() !void {
+ const stdout = std.io.getStdOut();
+ try stdout.writeAll("Hello, Gentoo!\n");
+ }
+ _EOF_
+
+ zig_test_compile_and_run() {
+ eindent
+ einfo "${1}: ${2}"
+ eoutdent
+
+ if [[ "${2}" == native* ]]; then
+ return 0
+ fi
+
+ if [[ "${1}" == arm* ]]; then
+ # Bunch of unimplemented Zig
+ # routines for more "bare-bone" arm.
+ case "${2}" in
+ # Some errors in inline assembly, likely too low baseline
+ generic-soft_float | generic+soft_float) return 0;;
+ # undefined symbol: __sync_fetch_and_add_1
+ # compiler-rt not implemented in upstream for it yet:
+ # https://github.com/ziglang/zig/issues/4959
+ generic+v5te-soft_float) return 0;;
+ *) ;;
+ esac
+ fi
+
+ local ret=0
+
+ local args=(
+ -target "${1}"
+ -mcpu "${2//:no-run/}"
+ main.zig
+ )
+ if ! zig build-exe "${args[@]}" > /dev/null; then
+ eerror "Failed to compile for: ${1}, ${2}"
+ ((++ret))
+ return ${ret}
+ fi
+
+ # Can't run macOS binaries in Linux user-mode QEMU emulators
+ if [[ "${1}" == *macos* || "${2}" == *":no-run" ]]; then
+ return ${ret}
+ fi
+
+ if ! ./main > /dev/null; then
+ eerror "Failed to run for: ${1}, ${2}"
+ ((++ret))
+ fi
+
+ return ${ret}
+ }
+else
+ zig_test_compile_and_run() { :; }
+fi
+
+test-convert_c_env_to_zig_tuple() {
+ local ret=0
+
+ local -n map=${1}
+
+ local c_tuple
+ for key in "${!map[@]}"; do
+ local expected="${map["${key}"]}"
+
+ local c_tuple
+ local c_flags
+ if [[ "${key}" == *:* ]]; then
+ c_tuple="${key%%:*}"
+ c_flags="${key##*:}"
+ else
+ c_tuple="${key}"
+ c_flags=""
+ fi
+
+ local actual="$(zig-utils_c_env_to_zig_target "${c_tuple}" "${c_flags}")"
+ if [[ "${expected}" != "${actual}" ]]; then
+ eerror "Translating ${c_tuple}: expected ${expected}, found ${actual}"
+ ((++ret))
+ continue
+ fi
+
+ local zig_cpu="$(zig-utils_c_env_to_zig_cpu "${c_tuple}" "${c_flags}")"
+ if ! zig_test_compile_and_run "${expected}" "${zig_cpu}"; then
+ ((++ret))
+ continue
+ fi
+ done
+
+ return ${ret}
+}
+
+test-convert_c_env_to_zig_cpu() {
+ local ret=0
+
+ local -n map=${1}
+ local chost=${2}
+
+ local c_flags
+ for c_flags in "${!map[@]}"; do
+ local expected="${map["${c_flags}"]}"
+ local actual="$(zig-utils_c_env_to_zig_cpu "${chost}" "${c_flags}")"
+ if [[ "${expected//:no-run/}" != "${actual}" ]]; then
+ eerror "Translating ${c_flags}: expected ${expected//:no-run/}, found ${actual}"
+ ((++ret))
+ continue
+ fi
+
+ local zig_target="$(zig-utils_c_env_to_zig_target "${chost}" "${c_flags}")"
+ if ! zig_test_compile_and_run "${zig_target}" "${expected}"; then
+ ((++ret))
+ continue
+ fi
+ done
+
+ return ${ret}
+}
+
+tbegin '"C tuple to Zig tuple"'
+declare -A c_to_zig_map=(
+ # Just remove "vendor" field
+ [aarch64-unknown-linux-gnu]=aarch64-linux-gnu
+ [arm-unknown-linux-musleabi]=arm-linux-musleabi
+ [x86_64-pc-linux-gnu]=x86_64-linux-gnu
+ [loongarch64-unknown-linux-gnu]=loongarch64-linux-gnu
+ [powerpc64le-unknown-linux-gnu]=powerpc64le-linux-gnu
+
+ # ARM big-endian
+ [armeb-unknown-linux-gnueabi]=armeb-linux-gnueabi
+
+ # https://bugs.gentoo.org/924920
+ [armv7a-unknown-linux-gnueabihf]=arm-linux-gnueabihf
+
+ # ARM to Thumb
+ [arm-unknown-linux-musleabi:"-march=armv7e-m"]=thumb-linux-musleabi
+
+ # ARM families
+ [armv6j-unknown-linux-gnueabihf]=arm-linux-gnueabihf
+ [armv6j-linux-gnueabihf]=arm-linux-gnueabihf
+ [armv7a-softfp-linux-gnueabi]=arm-linux-gnueabi
+ [armv7a-linux-gnueabi]=arm-linux-gnueabi
+
+ # X86 (32-bit) families
+ [i486-pc-linux-gnu]=x86-linux-gnu
+ [i686-linux-gnu]=x86-linux-gnu
+
+ # MacOS
+ [x86_64-apple-darwin15]=x86_64-macos-none
+ [arm64-apple-darwin24]=aarch64-macos-none
+)
+test-convert_c_env_to_zig_tuple c_to_zig_map
+tend ${?}
+
+tbegin '"CFLAGS to Zig CPU for ARM"'
+CHOST="armv7a-unknown-linux-musleabihf"
+c_to_zig_map=(
+ [" "]="generic-soft_float"
+ ["-mcpu=native"]="native-soft_float"
+ ["-mcpu=cortex-a9"]="cortex_a9-soft_float"
+
+ ["-mcpu=cortex-a9 -march=iwmmxt2"]="cortex_a9+iwmmxt2-soft_float"
+
+ ["-march=armv7e-m"]="generic+v7em-soft_float"
+ ["-march=armv5te"]="generic+v5te-soft_float"
+ ["-march=armv6j -mfpu=vfp"]="generic+v6j+vfp2-soft_float"
+ ["-march=armv7-a -mfpu=vfpv3-d16"]="generic+v7a+vfp3d16-soft_float"
+ ["-march=armv7-a -mfpu=crypto-neon-fp-armv8"]="generic+v7a+crypto+neon+fp_armv8-soft_float"
+
+ # https://bugs.gentoo.org/924920
+ ["-march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard"]=generic+v7a+vfp3d16-soft_float
+)
+test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}"
+tend ${?}
+
+tbegin '"CFLAGS to Zig CPU for AARCH64"'
+CHOST="aarch64-unknown-linux-gnu"
+c_to_zig_map=(
+ [" "]="generic"
+ ["-mcpu=native"]="native"
+ ["-mcpu=cortex-a78"]="cortex_a78"
+
+ ["-march=armv8.3-a"]="generic+v8_3a"
+ ["-mcpu=cortex-a78 -march=armv8.3-a"]="cortex_a78+v8_3a"
+)
+test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}"
+tend ${?}
+
+tbegin '"CFLAGS to Zig CPU for X86"'
+CHOST="i686-pc-linux-gnu"
+c_to_zig_map=(
+ [" "]="i686"
+ ["-march=native"]="native"
+
+ ["-march=i486"]="i486"
+ ["-march=i586"]="i586"
+ ["-march=i686"]="i686"
+ ["-O2 -pipe -march=pentium-m"]="pentium_m"
+)
+test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}"
+tend ${?}
+
+tbegin '"CFLAGS to Zig CPU for X86-64"'
+CHOST="x86_64-pc-linux-gnu"
+c_to_zig_map=(
+ [" "]="x86_64"
+ ["-march=native"]="native"
+
+ ["-march=x86-64-v2"]="x86_64_v2"
+ ["-march=x86-64"]="x86_64"
+ ["-march=znver2"]="znver2"
+)
+test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}"
+tend ${?}
+
+tbegin '"CFLAGS to Zig CPU for RISCV32"'
+CHOST="riscv32-unknown-linux-gnu"
+c_to_zig_map=(
+ [" "]="generic_rv32"
+ ["-mcpu=native"]="native"
+ ["-mcpu=sifive-e31"]="sifive_e31"
+
+ ["-mabi=ilp32d -march=rv32imafdc"]="generic_rv32+i+m+a+f+d+c+d"
+ ["-mcpu=native -mabi=ilp32 -march=rv32imac"]="native+i+m+a+c"
+)
+test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}"
+tend ${?}
+
+tbegin '"CFLAGS to Zig CPU for RISCV64"'
+CHOST="riscv64-unknown-linux-gnu"
+c_to_zig_map=(
+ [" "]="generic_rv64"
+ ["-mcpu=native"]="native"
+ ["-mcpu=sifive-u74"]="sifive_u74"
+
+ ["-mabi=lp64 -march=rv64imac"]="generic_rv64+i+m+a+c"
+ ["-mabi=lp64d -march=rv64gc"]="generic_rv64+i+m+a+f+d+zicsr+zifencei+c+d"
+ ["-march=rv64gcv"]="generic_rv64+i+m+a+f+d+zicsr+zifencei+c+v"
+ ["-march=rv64imafdc -mcpu=sifive-u74"]="sifive_u74+i+m+a+f+d+c"
+ ["-mcpu=native -mabi=lp64 -march=rv64imac"]="native+i+m+a+c"
+)
+test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}"
+tend ${?}
+
+tbegin '"CFLAGS to Zig CPU for LoongArch64"'
+CHOST="loongarch64-unknown-linux-gnu"
+c_to_zig_map=(
+ [" "]="generic_la64"
+ ["-march=native"]="native"
+ ["-march=la664"]="la664"
+
+ ["-march=loongarch64 -mabi=lp64d"]="loongarch64+d"
+ ["-mabi=lp64f"]="generic_la64+f"
+)
+test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}"
+tend ${?}
+
+tbegin '"CFLAGS to Zig CPU for PowerPC"'
+CHOST="powerpc-unknown-linux-gnu"
+c_to_zig_map=(
+ [" "]="ppc"
+ ["-mcpu=native"]="native"
+
+ ["-mcpu=G5"]="g5"
+
+ # qemu: uncaught target signal 4 (Illegal instruction) - core dumped
+ ["-mcpu=power7"]="pwr7:no-run"
+ ["-mcpu=power8"]="pwr8:no-run"
+
+ ["-mcpu=powerpc"]="ppc"
+ ["-mcpu=powerpcle"]="ppc"
+)
+test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}"
+tend ${?}
+
+tbegin '"CFLAGS to Zig CPU for PowerPC64"'
+CHOST="powerpc64-unknown-linux-gnu"
+c_to_zig_map=(
+ [" "]="ppc64"
+ ["-mcpu=native"]="native"
+
+ # qemu: uncaught target signal 4 (Illegal instruction) - core dumped
+ ["-mcpu=power10"]="pwr10:no-run"
+
+ ["-mcpu=power9"]="pwr9"
+ ["-mcpu=powerpc64"]="ppc64"
+ ["-mcpu=powerpc64le"]="ppc64le"
+)
+test-convert_c_env_to_zig_cpu c_to_zig_map "${CHOST}"
+tend ${?}
+
+texit
diff --git a/eclass/toolchain.eclass b/eclass/toolchain.eclass
index 6eef2a0ec03e..55b2127a4f11 100644
--- a/eclass/toolchain.eclass
+++ b/eclass/toolchain.eclass
@@ -979,6 +979,9 @@ toolchain_setup_ada() {
latest_ada_bootstrap="${latest_ada_bootstrap#dev-lang/ada-bootstrap-}"
latest_ada_bootstrap=$(ver_cut 1 ${latest_ada_bootstrap})
ada_bootstrap="${latest_ada_bootstrap}"
+
+ export ADA_INCLUDE_PATH="${BROOT}/usr/lib/ada-bootstrap/usr/lib/gcc/${CHOST}/${ada_bootstrap}/adainclude::${ADA_INCLUDE_PATH}"
+ export ADA_OBJECTS_PATH="${BROOT}/usr/lib/ada-bootstrap/usr/lib/gcc/${CHOST}/${ada_bootstrap}/adalib:${ADA_OBJECTS_PATH}"
fi
ada_bootstrap_type=ada-bootstrap
@@ -1320,8 +1323,13 @@ toolchain_src_configure() {
confgcc+=( --enable-lto )
# Build compiler itself using LTO
- if tc_version_is_at_least 9.1 && _tc_use_if_iuse lto ; then
- BUILD_CONFIG_TARGETS+=( bootstrap-lto )
+ if tc_use_if_iuse lto ; then
+ # GCC 11 at least has a -Wlto-type-mismatch issue with Ada
+ if ! tc_version_is_at_least 12.1 && is_ada ; then
+ :;
+ elif tc_version_is_at_least 9.1 ; then
+ BUILD_CONFIG_TARGETS+=( bootstrap-lto )
+ fi
fi
if tc_version_is_at_least 12 && _tc_use_if_iuse cet && [[ -z ${CLANG_DISABLE_CET_HACK} && ${CTARGET} == x86_64-*-gnu* ]] ; then
diff --git a/eclass/zig-utils.eclass b/eclass/zig-utils.eclass
new file mode 100644
index 000000000000..ca72e89ed6ea
--- /dev/null
+++ b/eclass/zig-utils.eclass
@@ -0,0 +1,538 @@
+# Copyright 2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: zig-utils.eclass
+# @MAINTAINER:
+# Eric Joldasov <bratishkaerik@landless-city.net>
+# @AUTHOR:
+# Eric Joldasov <bratishkaerik@landless-city.net>
+# @SUPPORTED_EAPIS: 8
+# @BLURB: Prepare Zig toolchain and set global variables
+# @DESCRIPTION:
+# Prepare Zig toolchain and set global variables.
+# Supports Zig 0.13+.
+# Does not set any default function, ebuilds must call them manually.
+# Generally, only "zig-utils_setup" is needed.
+#
+# Intended to be used by ebuilds that call "zig build-exe/lib/obj"
+# or "zig test" directly and by "dev-lang/zig".
+# For ebuilds with ZBS (Zig Build System), it's usually better
+# to inherit zig.eclass instead, as it has default phases-functions.
+
+if [[ -z ${_ZIG_UTILS_ECLASS} ]]; then
+_ZIG_UTILS_ECLASS=1
+
+case ${EAPI} in
+ 8) ;;
+ *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
+esac
+
+inherit edo flag-o-matic linux-info
+
+# @ECLASS_VARIABLE: ZIG_SLOT
+# @PRE_INHERIT
+# @REQUIRED
+# @DESCRIPTION:
+# Zig slot that will be used in "ezig" function. Also, if
+# ZIG_OPTIONAL is empty, adds dev-lang/zig and dev-lang/zig-bin
+# dependency to BDEPEND. Must be >= "0.13".
+#
+# Example:
+# @CODE
+# ZIG_SLOT="0.13"
+# @CODE
+#
+# When a new Zig release occurs, it is advisable for maintainers to
+# check whether their ebuild supports that new version. If yes, they
+# they should bump ZIG_SLOT to the latest version; if not supported,
+# they need to patch any issues with new version and again bump
+# ZIG_SLOT. This helps to reduce dependencies on outdated Zig
+# versions.
+#
+# This policy of "1 exclusive Zig slot" will work until it
+# stabilizes enough (probably near 1.0), then it will be re-evaluated
+# and most likely changed to more common in other eclasses ZIG_MIN/
+# ZIG_MAX form.
+
+# @ECLASS_VARIABLE: ZIG_OPTIONAL
+# @PRE_INHERIT
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# If set to a non-empty value, all logic in zig-utils and
+# zig eclasses will be considered optional. No dependencies
+# will be added and no phase functions will be exported.
+#
+# For zig-utils.eclass users:
+# You have to add Zig dependency in your BDEPEND manually and call
+# at least "zig-utils_setup" before using "ezig".
+#
+# For zig.eclass users: see documentation in zig.eclass
+# instead.
+if [[ ! ${ZIG_OPTIONAL} ]]; then
+ BDEPEND="
+ || (
+ dev-lang/zig:${ZIG_SLOT}
+ dev-lang/zig-bin:${ZIG_SLOT}
+ )
+ "
+fi
+
+# @ECLASS_VARIABLE: ZIG_TARGET
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# Zig target tuple to use. Has the following format:
+# arch-os[.os_version_range]-abi[.abi_version]
+# Can be passed as:
+# * "-target " option in "zig test" or "zig build-exe/lib/obj",
+# * "-Dtarget=" option in "zig build"
+# (if project uses "std.Build.standardTargetOptions").
+#
+# Can be set by user in make.conf. If not set, then auto-generated by
+# "zig-utils_setup".
+#
+# Example:
+# @CODE
+# # Autodetected by Zig:
+# ZIG_TARGET="native"
+# # Machine running Linux x86_64 system, with glibc:
+# ZIG_TARGET="x86_64-linux-gnu"
+# # Similar to above, but versions are passed explicitly:
+# ZIG_TARGET="x86_64-linux.6.1.12...6.6.16-gnu.2.38"
+# # Machine running Linux PPC64 little-endian system, with musl
+# ZIG_TARGET="powerpc64le-linux-musl"
+# @CODE
+#
+# Note for eclass users: it is discouraged to overwrite ZIG_TARGET
+# value by ebuilds. In most cases, if you need to hardcode value for
+# -Dtarget, it's better to change "build.zig" code instead to use
+# appropriate values. For example, if some build-time executable
+# intented for host is compiled for cross-platform target, change in
+# build.zig "target" for that executable to be "b.graph.host".
+#
+# In rare cases, if you really need to hardcode ZIG_TARGET, use this
+# syntax before calling `zig-utils_setup` (or `zig_pkg_setup`) to
+# allow user override:
+# @CODE
+# pkg_setup() {
+# : "${ZIG_TARGET:=aarch64-freestanding-none}"
+# zig_pkg_setup
+# }
+# @CODE
+
+# @ECLASS_VARIABLE: ZIG_CPU
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# Zig target CPU and features to use. Has the following format:
+# family_name(\+enable_feature|\-disable_feature)*
+# Can be passed as:
+# * "-mcpu " option in "zig test" or "zig build-exe/lib/obj",
+# * "-Dcpu=" option in "zig build"
+# (if project uses "std.Build.standardTargetOptions").
+#
+# Can be set by user in make.conf. If not set, then auto-generated by
+# "zig-utils_setup".
+#
+# Example:
+# @CODE
+# # Autodetected by Zig:
+# ZIG_CPU="native"
+# # AMD Zen 2 processor
+# ZIG_CPU="znver2"
+# # x86_64 processor, X87 support enabled, SSE2 support disabled
+# ZIG_CPU="x86_64+x87-sse2"
+# @CODE
+#
+# Note for eclass users: it is discouraged to overwrite ZIG_CPU
+# value by ebuilds. In most cases, if you need to hardcode value for
+# -Dcpu, it's better to change "build.zig" code instead to use
+# appropriate values. For example, if some build-time executable
+# intented for host is compiled for cross-platform target, change in
+# build.zig "target" for that executable to be "b.graph.host".
+#
+# In rare cases, if you really need to hardcode ZIG_CPU, use this
+# syntax before calling `zig-utils_setup` (or `zig_pkg_setup`) to
+# allow user override:
+# @CODE
+# pkg_setup() {
+# : "${ZIG_CPU:=apple_m1}"
+# zig_pkg_setup
+# }
+# @CODE
+
+# @ECLASS_VARIABLE: ZIG_EXE
+# @OUTPUT_VARIABLE
+# @DESCRIPTION:
+# Absolute path to the used Zig executable.
+# Set by "zig-utils_setup"/"zig-utils_find_installation".
+#
+# Please note that when passing one flag several times with different
+# values:
+# * (only "zig build") in "-Dbar=false -Dbar" form:
+# errors due to conflict of flags,
+# * (only "zig build") in "-Dbar=false -Dbar=true" form:
+# "bar" becomes a list, which is likely not what you want,
+# * in "-fbar -fno-bar" form:
+# latest value overwrites values before.
+# Example above shows only boolean option, but it is same with other
+# types of options (enums, "std.zig.BuildId", "std.SemanticVersion",
+# integers, strings, etc.).
+
+# @ECLASS_VARIABLE: ZIG_VER
+# @OUTPUT_VARIABLE
+# @DESCRIPTION:
+# Zig version as reported in dev-lang/zig-${PV} PV part.
+# Set by "zig-utils_setup"/"zig-utils_find_installation".
+#
+# Example:
+# @CODE
+# 0.13.0
+# @CODE
+
+# @FUNCTION: zig-utils_c_env_to_zig_target
+# @USAGE: <C-style target tuple> <CFLAGS>
+# @DESCRIPTION:
+# Translates C-style target tuple (like CHOST) and CFLAGS to Zig-style
+# target tuple. For full information "zig-utils_c_env_to_zig_cpu" is
+# needed, because some information is located in different places in C
+# and Zig, for example:
+# * Moved from C target to Zig CPU: x86 and ARM families,
+# * Moved from CFLAGS to Zig tuple: ARM Thumb mode.
+#
+# Mostly used during cross-compilation to get target triple if user
+# did not set ZIG_TARGET variable, and always during bootstraping Zig.
+#
+# See ZIG_TARGET description for more information.
+zig-utils_c_env_to_zig_target() {
+ if [[ ${#} -ne 2 ]]; then
+ die "${FUNCNAME[0]}: expected 2 arguments, got ${#}"
+ fi
+ local c_tuple="${1}"
+ local c_arch="${c_tuple%%-*}"
+ local c_abi="${c_tuple##*-}"
+
+ local c_flags="${2}"
+ local c_flags_march="$(CFLAGS="${c_flags}" get-flag march)"
+
+ local arch os abi
+
+ case "${c_arch}" in
+ i?86) arch=x86;;
+ arm64) arch=aarch64;;
+ arm*)
+ if [[ "${c_flags_march}" == *-m ]]; then
+ arch=thumb
+ else
+ arch=arm
+ fi
+
+ if [[ "${c_arch}" == *eb ]]; then
+ arch+="eb"
+ fi
+ ;;
+ *) arch="${c_arch}";;
+ esac
+
+ case "${c_tuple}" in
+ *-linux*) os=linux;;
+ *-apple*) os=macos;;
+ esac
+
+ case "${c_abi}" in
+ darwin*) abi=none;;
+ *) abi="${c_abi}";;
+ esac
+
+ echo "${arch}-${os}-${abi}"
+}
+
+# @FUNCTION: zig-utils_c_env_to_zig_cpu
+# @USAGE: <C-style target tuple> <CFLAGS>
+# @DESCRIPTION:
+# Translates C-style target tuple (like CHOST) and CFLAGS to Zig-style
+# target CPU and features. For full information
+# "zig-utils_c_env_to_zig_target" is needed, because some information
+# is located in different places in C and Zig, for example:
+# * Moved from C target to Zig CPU: x86 and ARM families,
+# * Moved from CFLAGS to Zig tuple: ARM Thumb mode.
+#
+# Used to get target CPU if user did not set ZIG_CPU variable.
+#
+# See ZIG_CPU description for more information.
+zig-utils_c_env_to_zig_cpu() {
+ if [[ ${#} -ne 2 ]]; then
+ die "${FUNCNAME[0]}: expected 2 arguments, got ${#}"
+ fi
+ local c_tuple="${1}"
+ local c_arch="${c_tuple%%-*}"
+
+ local c_flags="${2}"
+ local c_flags_mabi="$(CFLAGS="${c_flags}" get-flag mabi)"
+ local c_flags_march="$(CFLAGS="${c_flags}" get-flag march)"
+ local c_flags_mcpu="$(CFLAGS="${c_flags}" get-flag mcpu)"
+ local c_flags_mfpu="$(CFLAGS="${c_flags}" get-flag mfpu)"
+
+ local base_cpu features=""
+
+ case "${c_arch}" in
+ x86_64 | i?86)
+ local c_cpu="${c_flags_march}"
+ case "${c_cpu}" in
+ "") base_cpu="${c_arch}";;
+ *) base_cpu="${c_cpu//[-.]/_}";;
+ esac
+ ;;
+ aarch64 | aarch64_be | arm*)
+ local c_cpu="${c_flags_mcpu}"
+ case "${c_cpu}" in
+ "") base_cpu=generic;;
+ *) base_cpu="${c_cpu//[-.]/_}";;
+ esac
+
+ case "${c_flags_march}" in
+ "") ;;
+ armv*)
+ local c_arm_family="${c_flags_march##arm}"
+ c_arm_family="${c_arm_family//./_}"
+ c_arm_family="${c_arm_family//-/}"
+ features+="+${c_arm_family}"
+ ;;
+ *) features+="+${c_flags_march}";;
+ esac
+
+ if [[ "${c_arch}" != aarch64* && "${c_arch}" != arm64 ]]; then
+ if [[ "${c_flags_mfpu}" == crypto-* ]]; then
+ c_flags_mfpu="${c_flags_mfpu##crypto-}"
+ features+="+crypto"
+ fi
+ if [[ "${c_flags_mfpu}" == neon-* ]]; then
+ c_flags_mfpu="${c_flags_mfpu##neon-}"
+ features+="+neon"
+ fi
+
+ case "${c_flags_mfpu}" in
+ "" | auto) ;;
+ neon) features+="+neon";;
+ fp16) features+="+fp16";;
+ fp-armv8) features+="+fp_armv8";;
+
+ vfp | vfpv2) features+="+vfp2";;
+
+ vfp3 | vfpv3) features+="+vfp3";;
+ vfpv3-fp16) features+="+vfp3sp";;
+ vfpv3-d16) features+="+vfp3d16";;
+ vfpv3-d16-fp16) features+="+vfp3d16sp";;
+ vfpv3xd) features+="+vfp3d16sp";;
+ vfpv3xd-fp16) features+="+vfp3d16sp+fp16";;
+
+ vfpv4) features+="+vfp4";;
+ vfpv4-fp16) features+="+vfp4sp";;
+ vfpv4-d16) features+="+vfp4d16";;
+ fpv4-sp-fp16) features+="+vfp4d16sp";;
+
+ fpv5-d16) features+="+fp_armv8d16+fp64";;
+ *) die -n "Unknown ARM FPU: ${c_flags_mfpu}";;
+ esac
+
+ local is_softfloat="$(CTARGET="${c_tuple}" tc-tuple-is-softfloat)"
+ case "${is_softfloat}" in
+ only | yes) features+="+soft_float";;
+ softfp | no) features+="-soft_float";;
+ *) die -n "tc-tuple-is-softfloat returned unexpected value: ${is_softfloat}"
+ esac
+ fi
+ ;;
+ riscv32 | riscv64)
+ local c_cpu="${c_flags_mcpu}"
+ case "${c_cpu}" in
+ "")
+ case "${c_arch}" in
+ riscv32) base_cpu=generic_rv32;;
+ riscv64) base_cpu=generic_rv64;;
+ esac
+ ;;
+ *) base_cpu="${c_cpu//[-.]/_}";;
+ esac
+
+ local base_isa="${c_flags_march:0:4}"
+ local extensions="${c_flags_march:4}"
+
+ case "${base_isa}" in
+ "" | rv32 | rv64) ;;
+ *) die -n "Unknown RISC-V architecture: ${base_isa}";;
+ esac
+
+ local extension
+ while read -n 1 extension; do
+ case "${extension}" in
+ "") ;;
+ g) features+="+i+m+a+f+d+zicsr+zifencei";;
+ _) die -n "Can't translate multi-letter RISC-V extensions yet";;
+ *) features+="+${extension}";;
+ esac
+ done <<< "${extensions}"
+
+ case "${c_flags_mabi}" in
+ ilp32d | lp64d) features+="+d";;
+ ilp32e | lp64e) features+="+e";;
+ ilp32f | lp64f) features+="+f";;
+ "" | ilp32 | lp64) ;;
+ *) die -n "Unknown RISC-V ABI: ${c_flags_mabi}";;
+ esac
+ ;;
+ loongarch64)
+ local c_cpu="${c_flags_march}"
+ case "${c_cpu}" in
+ "") base_cpu=generic_la64;;
+ *) base_cpu="${c_cpu//[-.]/_}";;
+ esac
+
+ case "${c_flags_mabi}" in
+ lp64d) features+="+d";;
+ lp64f) features+="+f";;
+ lp64s | "") ;;
+ *) die -n "Unknown LoongArch ABI: ${c_flags_mabi}";;
+ esac
+ ;;
+ powerpc | powerpcle | powerpc64 | powerpc64le)
+ local c_cpu="${c_flags_mcpu}"
+ case "${c_cpu}" in
+ "")
+ case "${c_arch}" in
+ powerpc | powerpcle) base_cpu=ppc;;
+ powerpc64 | powerpc64le) base_cpu=ppc64;;
+ esac
+ ;;
+ G*) base_cpu="${c_cpu//G/g}";;
+ powerpcle) base_cpu=ppc;;
+ powerpc*) base_cpu="${c_cpu//powerpc/ppc}";;
+ power*) base_cpu="${c_cpu//power/pwr}";;
+ *) base_cpu="${c_cpu//[-.]/_}";;
+ esac
+ ;;
+ *) base_cpu=generic;;
+ esac
+
+ echo "${base_cpu}${features}"
+}
+
+# @FUNCTION: zig-utils_find_installation
+# @DESCRIPTION:
+# Detects suitable Zig installation and sets ZIG_VER and ZIG_EXE
+# variables.
+#
+# See ZIG_EXE and ZIG_VER descriptions for more information.
+zig-utils_find_installation() {
+ # Adapted from https://github.com/gentoo/gentoo/pull/28986
+ # Many thanks to Florian Schmaus (Flowdalic)!
+
+ [[ -n "${ZIG_SLOT}" ]] || die "${FUNCNAME[0]}: ZIG_SLOT must be set"
+ if ver_test "${ZIG_SLOT}" -lt "0.13"; then
+ die "${ECLASS}: ZIG_SLOT must be >= 0.13, found ${ZIG_SLOT}"
+ fi
+
+ einfo "Searching Zig ${ZIG_SLOT}..."
+
+ local zig_supported_versions=(
+ "9999"
+ "0.13.1"
+ "0.13.0"
+ )
+
+ local base_path="${BROOT}/usr/bin"
+
+ local selected_path selected_ver
+ for selected_ver in "${zig_supported_versions[@]}"; do
+ # Check if candidate satisfies ZIG_SLOT condition.
+ if [[ "${selected_ver}" != "${ZIG_SLOT}"* ]]; then
+ continue
+ fi
+
+ # Prefer "dev-lang/zig" over "dev-lang/zig-bin"
+ local candidate_path
+ for candidate_path in "${base_path}"/zig{,-bin}-"${selected_ver}"; do
+ if [[ -x "${candidate_path}" ]]; then
+ selected_path="${candidate_path}"
+ break 2
+ fi
+ done
+ done
+
+ if [[ -z "${selected_path}" ]]; then
+ die "Could not find (suitable) Zig at \"${base_path}\""
+ fi
+
+ declare -g ZIG_EXE="${selected_path}"
+ declare -g ZIG_VER="${selected_ver}"
+ # Sanity check, comment from upstream:
+ # > Check libc++ linkage to make sure Zig was built correctly,
+ # > but only for "env" and "version" to avoid affecting the
+ # > startup time for build-critical commands
+ # > (check takes about ~10 μs)
+ "${ZIG_EXE}" version > /dev/null ||
+ die "Sanity check failed for \"${ZIG_EXE}\""
+}
+
+# @FUNCTION: zig-utils_setup
+# @DESCRIPTION:
+# Checks if running Linux kernel version is supported by Zig.
+# Populates ZIG_TARGET, ZIG_CPU, ZIG_EXE and ZIG_VER global
+# variables with detected values, or, if user set them already,
+# leaves as-is.
+zig-utils_setup() {
+ # Should be first because it sets ZIG_VER which might be used
+ # in the future when setting ZIG_TARGET and ZIG_CPU variables
+ # for incompatible versions.
+ if [[ -z "${ZIG_EXE}" ]]; then
+ zig-utils_find_installation
+ fi
+
+ : "${ZIG_CPU:=$(zig-utils_c_env_to_zig_cpu "${CHOST}" "${CFLAGS}")}"
+ if tc-is-cross-compiler; then
+ : "${ZIG_TARGET:=$(zig-utils_c_env_to_zig_target "${CHOST}" "${CFLAGS}")}"
+ else
+ : "${ZIG_TARGET:=native}"
+ fi
+ declare -g ZIG_CPU ZIG_TARGET
+
+ einfo "ZIG_EXE: \"${ZIG_EXE}\""
+ einfo "ZIG_VER: ${ZIG_VER}"
+ einfo "ZIG_TARGET: ${ZIG_TARGET}"
+ einfo "ZIG_CPU: ${ZIG_CPU}"
+}
+
+# @FUNCTION: ezig
+# @USAGE: [<args>...]
+# @DESCRIPTION:
+# Runs ZIG_EXE with supplied arguments. Dies if ZIG_EXE is not set or
+# if command exits with error. Respects `nonfatal`.
+#
+# Always disables progress tree. By default enables ANSI escape codes
+# (colors, etc.), user can set NO_COLOR environment variable to
+# disable them.
+#
+# Note that color support also determines how compile errors will be
+# printed: source code lines and reference traces are not available
+# when colors are disabled.
+ezig() {
+ # Sync description above and comments below with upstream's
+ # "std.io.tty.detectConfig".
+ debug-print-function "${FUNCNAME[0]}" "${@}"
+
+ if [[ -z "${ZIG_EXE}" ]] ; then
+ die "${FUNCNAME[0]}: ZIG_EXE is not set. Was 'zig-utils_setup' called before using ezig?"
+ fi
+
+ # Progress tree is helpful indicator in TTY, but unfortunately
+ # they make Portage logs harder to read in plaintext.
+ #
+ # We don't have global toggle for all Zig commands to disable
+ # progress tree, however we can emulate this using 2 steps.
+
+ # Disable progress tree and colors. Errors are now less detailed.
+ local -x TERM=dumb
+ # Re-enable colors. Errors are now yet again detailed for reading.
+ local -x CLICOLOR_FORCE=1
+ # User's NO_COLOR has more priority and can disable colors again.
+ "${ZIG_EXE}" "${@}" || die -n "Failed to run command: ${ZIG_EXE} ${@}"
+}
+fi
diff --git a/eclass/zig.eclass b/eclass/zig.eclass
new file mode 100644
index 000000000000..e838616ef72a
--- /dev/null
+++ b/eclass/zig.eclass
@@ -0,0 +1,558 @@
+# Copyright 2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: zig.eclass
+# @MAINTAINER:
+# Eric Joldasov <bratishkaerik@landless-city.net>
+# @AUTHOR:
+# Alfred Wingate <parona@protonmail.com>
+# Violet Purcell <vimproved@inventati.org>
+# Eric Joldasov <bratishkaerik@landless-city.net>
+# @SUPPORTED_EAPIS: 8
+# @PROVIDES: zig-utils
+# @BLURB: Functions for working with ZBS (Zig Build System)
+# @DESCRIPTION:
+# Functions for working with Zig build system and package manager.
+# Supports Zig 0.13+. Exports default functions for convenience.
+#
+# Note that zig.eclass is mostly tailored for projects that:
+# 1) Install something in build.zig steps: "artifacts" (executable,
+# libraries, objects), source codes, assets, tests, scripts etc. But
+# many authors also use it to write Zig "modules", build logic
+# and/or bindings/wrappers for C/C++ libraries. They install nothing
+# and are only used at build-time, so it's unneccessary and mostly
+# useless to make ebuilds for them.
+# 2) Have required `target`, `cpu` and optional `optimize` options in
+# build.zig that accept standard Zig-style target and optimize mode.
+# They are usually created by calling `b.standardTargetOptions` and
+# `b.standardOptimizeOption` functions.
+#
+# For end-user executables, usually it's recommended to patch to call
+# these options and upstream it, but in some cases authors have good
+# reasons to not have them, f.e. if it is built only for WASM
+# platform with ReleaseSmall, and is not intended to run in /usr/bin/.
+# In this case, declare dummy options using `b.option` and ignore
+# their values, or else eclass wouldn't work.
+#
+# Another case is when upstream has `target` option but it has
+# custom format and does not accept usual Zig targets, but rather
+# something specific to the project like "linux-baseline-lts", or
+# combine CPU and target in one option.
+# In this case, it's best to rename that option to something like
+# `target-custom`, then declare `target` option and make converter
+# from one value to other.
+#
+# For non-executable binaries like C libraries, objects etc. our
+# policy is stricter, all 3 options are required and should not
+# be ignored, with no exceptions.
+
+if [[ -z ${_ZIG_ECLASS} ]]; then
+_ZIG_ECLASS=1
+
+case ${EAPI} in
+ 8) ;;
+ *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
+esac
+
+inherit multiprocessing zig-utils
+
+# @ECLASS_VARIABLE: ZIG_OPTIONAL
+# @PRE_INHERIT
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# If set to a non-empty value, all logic in zig-utils and
+# zig eclasses will be considered optional. No dependencies
+# will be added and no phase functions will be exported.
+#
+# For zig.eclass users:
+# You need to add Zig and pkgconfig dependencies in your BDEPEND, set
+# QA_FLAGS_IGNORED and call all phase functions manually. If you want
+# to use "ezig build" directly, call "zig_pkg_setup" before it.
+#
+# For zig-utils.eclass users: see documentation in
+# zig-utils.eclass instead.
+if [[ ! ${ZIG_OPTIONAL} ]]; then
+ BDEPEND="virtual/pkgconfig"
+
+ # See https://github.com/ziglang/zig/issues/3382
+ # Zig Build System does not support CFLAGS/LDFLAGS/etc.
+ QA_FLAGS_IGNORED=".*"
+fi
+
+# @ECLASS_VARIABLE: ZBS_DEPENDENCIES
+# @PRE_INHERIT
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# Bash associative array with all tarballs that will be fetched by
+# "ezig fetch" in zig_src_unpack phase. Value is URL where
+# tarball is located, key is name under which it would be downloaded
+# and renamed. So generally it has effect of "value -> key".
+#
+# Note: if Zig Build System dependency can't be represented in SRC_URI
+# (like direct Git commit URIs), you should do the following
+# (zig-ebuilder does archiving automatically for you):
+# 1. Archive each folder with dependency content in some tarball,
+# so f.e. if you have 2 Git dependencies, create 2 tarballs.
+# 2. Archive all previous tarballs into one combined tarball (also
+# called tarball-tarball from now on), no subdirs, so that eclass
+# can firstly unpack this tarball with "unpack",
+# and secondly unpack its content with "zig fetch".
+# 3. (zig-ebuilder can't do this) Host this tarball somewhere
+# and put URL of this tarball in SRC_URI, and archives in
+# ZBS_DEPENDENCIES, keys must be names of archives, values empty.
+#
+# Example:
+# @CODE
+# declare -r -A ZBS_DEPENDENCIES=(
+# [tarball_a-<long-hash>.tar.gz]='URL_A'
+# [tarball_b-<long-hash>.tar.gz]='URL_B'
+#
+# # If there are Git dependencies:
+# [git_c-<long-hash>.tar.gz]=''
+# # Tarball-tarball should contain inside above tarball flatly.
+# )
+# @CODE
+
+# @ECLASS_VARIABLE: ZBS_DEPENDENCIES_SRC_URI
+# @OUTPUT_VARIABLE
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# Content of ZBS_DEPENDENCIES converted at inherit-time, to be used in
+# SRC_URI. Note that elements with empty keys will be skipped.
+# Example:
+# @CODE
+# SRC_URI="
+# <URL to project sources, patches, non-Zig resources etc.>
+#
+# # If there are Git dependencies:
+# # <URL to tarball-tarball>
+#
+# ${ZBS_DEPENDENCIES_SRC_URI}
+# "
+# @CODE
+
+# @FUNCTION: _zig_set_zbs_uris
+# @INTERNAL
+# @DESCRIPTION:
+# Sets ZBS_DEPENDENCIES_SRC_URI variable based on ZBS_DEPENDENCIES.
+_zig_set_zbs_uris() {
+ # Thanks to Alfred Wingate "parona" for inspiration here:
+ # https://gitlab.com/Parona/parona-overlay/-/blob/874dcfe03116574a33ed51f469cc993e98db1fa2/eclass/zig.eclass
+
+ ZBS_DEPENDENCIES_SRC_URI=
+
+ local dependency
+ for dependency in "${!ZBS_DEPENDENCIES[@]}"; do
+ local uri="${ZBS_DEPENDENCIES[${dependency}]}"
+ if [[ -n "${uri}" ]]; then
+ ZBS_DEPENDENCIES_SRC_URI+=" ${uri} -> ${dependency}"
+ fi
+ done
+}
+_zig_set_zbs_uris
+
+# @ECLASS_VARIABLE: my_zbs_args
+# @DESCRIPTION:
+# Bash array with ebuild-specified arguments to pass to the
+# "zig build" after "src_configure".
+# It's appended to the ZBS_ARGS during "src_configure". Note: if you
+# need to override default optimize mode of this eclass (ReleaseSafe)
+# with your default, please use "--release=small" etc. syntax so that
+# user can still override it in ZBS_ARGS_EXTRA.
+#
+# Example:
+# @CODE
+# src_configure() {
+# local my_zbs_args=(
+# -Dpie=true
+# )
+#
+# zig_src_configure
+# }
+# @CODE
+: "${my_zbs_args:=}"
+
+# @ECLASS_VARIABLE: ZBS_ARGS_EXTRA
+# @USER_VARIABLE
+# @DESCRIPTION:
+# Bash string with user-specified arguments to pass to the "zig build"
+# after "src_configure".
+# It's appended to the ZBS_ARGS during "zig_src_configure".
+#
+# If this does not have amount of jobs, eclass will try to take amount
+# of jobs from MAKEOPTS, and if it also does not have them, it will
+# default to $(nproc).
+#
+# Example:
+# @CODE
+# ZBS_ARGS_EXTRA="-j8 --release=small"
+# @CODE
+: "${ZBS_ARGS_EXTRA:=}"
+
+# @ECLASS_VARIABLE: ZBS_VERBOSE
+# @USER_VARIABLE
+# @DESCRIPTION:
+# If enabled, eclass will add "--summary all --verbose" options to
+# "ezig build", so that it prints every command before executing,
+# and summarry tree at the end of step. If not, will do nothing.
+# Enabled by default. Set to OFF to disable these verbose messages.
+#
+# Note: this variable does not control other options starting with
+# "--verbose-", such as "--verbose-link" or "--verbose-cimport". If
+# you need them, add them manually to ZBS_ARGS_EXTRA.
+: "${ZBS_VERBOSE:=ON}"
+
+# @ECLASS_VARIABLE: BUILD_DIR
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# Directory where all "ezig build" calls will be proceeded.
+# Defaults to "${WORKDIR}/${P}-build" if not set.
+: "${BUILD_DIR:=${WORKDIR}/${P}-build}"
+
+# @ECLASS_VARIABLE: ZBS_ECLASS_DIR
+# @DESCRIPTION:
+# Directory where various files used by this eclass are stored.
+# They can be supplied by the ebuild or by eclass.
+# Currently, it's used only for Zig packages, which are stored in "p/"
+# subdirectory.
+# Defaults to "${WORKDIR}/zig-eclass" if not set.
+# Should be set before calling "zig_src_unpack" or
+# "zig_live_fetch".
+: "${ZBS_ECLASS_DIR:=${WORKDIR}/zig-eclass}"
+
+# @FUNCTION: zig_get_jobs
+# @DESCRIPTION:
+# Returns number of jobs from ZBS_ARGS_EXTRA or MAKEOPTS.
+# If there is none, defaults to number of available processing units.
+zig_get_jobs() {
+ local all_args="${MAKEOPTS} ${ZBS_ARGS_EXTRA}"
+ local default_jobs="$(get_nproc)"
+ local jobs="$(makeopts_jobs "${all_args}" "${default_jobs}")"
+
+ if [[ "${jobs}" == "0" ]]; then
+ # Zig build system does not allow "-j0", and does not have
+ # option for unlimited parallelism. Pass our default number
+ # of jobs here.
+ echo "${default_jobs}"
+ else
+ echo "${jobs}"
+ fi
+}
+
+# @FUNCTION: zig_init_base_args
+# @DESCRIPTION:
+# Stores basic args for future "ezig build" calls in ZBS_ARGS_BASE.
+# Package manager option is managed by "zig_src_prepare",
+# ebuild and user options are added by "zig_src_configure".
+#
+# This function is used by "zig_pkg_setup", and it is neccessary
+# that args are available as early as possible, so that ebuilds
+# could use them in steps like "src_unpack" if neccessary, while
+# still having verbosity and amount of jobs from user respected.
+#
+#
+# TODO: currently this function enables "--search-prefix" (1) and
+# "--sysroot" (2) only when cross-compiling, should be fixed to
+# unconditionally enabling it.
+#
+# For solving (1) this patch should be reworked and upstreamed:
+# https://paste.sr.ht/~bratishkaerik/2ddffe2bf0f8f9d6dfb60403c2e9560334edaa88
+#
+# (2)
+# "--sysroot" should be passed together with "--search-prefix" above,
+# if we pass only "--sysroot" it gives these errors:
+# @CODE
+# error: unable to find dynamic system library 'zstd' using strategy 'paths_first'. searched paths: none
+# @CODE
+zig_init_base_args() {
+ [[ "${ZBS_ARGS_BASE}" ]] && return
+
+ # Sync with the output format of `zig libc`.
+ # TODO maybe add to upstream to use ZON format instead...
+ # Will also help "https://github.com/ziglang/zig/issues/20327",
+ # and hopefully will respect our settings too.
+ cat <<- _EOF_ > "${T}/zig_libc.txt" || die "Failed to provide Zig libc info"
+ # Note: they are not prepended by "--sysroot" value,
+ # so repeat it here.
+ # Also, no quotes here, they are interpreted verbatim.
+ include_dir=${ESYSROOT}/usr/include/
+ sys_include_dir=${ESYSROOT}/usr/include/
+ crt_dir=${ESYSROOT}/usr/$(get_libdir)/
+ # Windows with MSVC only.
+ msvc_lib_dir=
+ # Windows with MSVC only.
+ kernel32_lib_dir=
+ # Haiku only.
+ gcc_dir=
+ _EOF_
+
+ declare -g -a ZBS_ARGS_BASE=(
+ -j$(zig_get_jobs)
+
+ -Dtarget="${ZIG_TARGET}"
+ -Dcpu="${ZIG_CPU}"
+ --release=safe
+
+ --prefix-exe-dir bin/
+ --prefix-lib-dir "$(get_libdir)/"
+ --prefix-include-dir include/
+
+ # Should be relative path to make other calls easier,
+ # so remove leading slash here.
+ --prefix "${EPREFIX:+${EPREFIX#/}/}usr/"
+
+ --libc "${T}/zig_libc.txt"
+ )
+ if [[ "${ZBS_VERBOSE}" != OFF ]]; then
+ ZBS_ARGS_BASE+=( --summary all --verbose )
+ fi
+
+ if tc-is-cross-compiler; then
+ ZBS_ARGS_BASE+=(
+ --search-prefix "${ESYSROOT}/usr/"
+ --sysroot "${ESYSROOT}/"
+ )
+ fi
+}
+
+# @FUNCTION: zig_pkg_setup
+# @DESCRIPTION:
+# Sets up environmental variables for Zig toolchain
+# and basic args for Zig Build System.
+zig_pkg_setup() {
+ [[ "${MERGE_TYPE}" != binary ]] || return 0
+
+ zig-utils_setup
+ zig_init_base_args
+
+ mkdir "${T}/zig-cache/" || die
+
+ # Environment variables set by this eclass.
+
+ # Used by Zig Build System to find `pkg-config`.
+ # UPSTREAM Used only by 9999 for now, should land in future
+ # 0.14 release.
+ export PKG_CONFIG="${PKG_CONFIG:-"$(tc-getPKG_CONFIG)"}"
+ # Used by whole Zig toolchain (most of the sub-commands)
+ # to find local and global cache directories.
+ export ZIG_LOCAL_CACHE_DIR="${T}/zig-cache/local/"
+ export ZIG_GLOBAL_CACHE_DIR="${T}/zig-cache/global/"
+}
+
+# @FUNCTION: zig_live_fetch
+# @USAGE: [<args>...]
+# @DESCRIPTION:
+# Fetches packages, if they exist, to the "ZBS_ECLASS_DIR/p/".
+# Adds build file path to ZBS_BASE_ARGS.
+# If you have some lazy dependency which is not triggered in default
+# configuration, pass options like you would pass them for regular
+# "ezig build". Try to cover all of them before "src_configure".
+# **Note**: this function will be deprecated once/if
+# https://github.com/ziglang/zig/pull/19975 lands.
+#
+# Example:
+# @CODE
+# src_unpack() {
+# # If there are no lazy dependency:
+# zig_live_fetch
+#
+# # If there are lazy dependencies that can be triggered together:
+# zig_live_fetch -Denable-wayland -Denable-xwayland
+#
+# # If there are 2 lazy dependencies that can't be triggered
+# # together in one call because they conflict:
+# zig_live_fetch -Dmain-backend=opengl
+# zig_live_fetch -Dmain-backend=vulkan
+# }
+# @CODE
+zig_live_fetch() {
+ # This function will likely be called in src_unpack,
+ # before [zig_]src_prepare, so this directory might not
+ # exist yet.
+ mkdir -p "${BUILD_DIR}" > /dev/null || die
+ pushd "${BUILD_DIR}" > /dev/null || die
+
+ ZBS_ARGS_BASE+=( --build-file "${S}/build.zig" )
+
+ local args=(
+ "${ZBS_ARGS_BASE[@]}"
+
+ --global-cache-dir "${ZBS_ECLASS_DIR}/"
+
+ # Function arguments
+ "${@}"
+ )
+
+ einfo "ZBS: live-fetching with:"
+ einfo "${args[@]}"
+ ezig build --help "${args[@]}" > /dev/null
+
+ popd > /dev/null || die
+}
+
+# @FUNCTION: zig_src_unpack
+# @DESCRIPTION:
+# Unpacks every archive in SRC_URI and ZBS_DEPENDENCIES,
+# in that order. Adds build file path to ZBS_BASE_ARGS.
+zig_src_unpack() {
+ # Thanks to Alfred Wingate "parona" for inspiration here:
+ # https://gitlab.com/Parona/parona-overlay/-/blob/874dcfe03116574a33ed51f469cc993e98db1fa2/eclass/zig.eclass
+
+ ZBS_ARGS_BASE+=( --build-file "${S}/build.zig" )
+
+ if [[ "${#ZBS_DEPENDENCIES_SRC_URI}" -eq 0 ]]; then
+ default_src_unpack
+ return
+ fi
+
+ local zig_deps=()
+ for dependency in "${!ZBS_DEPENDENCIES[@]}"; do
+ zig_deps+=("${dependency}")
+ done
+
+ # First unpack non-Zig dependencies, so that
+ # tarball with all Git dependencies tarballs is unpacked early.
+ local dist
+ for dist in ${A}; do
+ if ! has "${dist}" "${zig_deps[@]}"; then
+ unpack "${dist}"
+ fi
+ done
+
+ # Now unpack all Zig dependencies, including those that are
+ # now unpacked from tarball-tarball.
+ local zig_dep
+ for zig_dep in "${zig_deps[@]}"; do
+ # Hide now-spammy hash from stdout
+ ezig fetch --global-cache-dir "${ZBS_ECLASS_DIR}/" \
+ "${DISTDIR}/${zig_dep}" > /dev/null
+ done
+ einfo "ZBS: ${#zig_deps[@]} dependencies unpacked"
+}
+
+# @FUNCTION: zig_src_prepare
+# @DESCRIPTION:
+# Calls default "src_prepare" function, creates BUILD_DIR directory
+# and enables system mode (by adding to ZBS_BASE_ARGS).
+#
+# System mode is toggled here and not in "src_unpack" because they
+# could have been fetched by "live_fetch" in live ebuilds instead.
+zig_src_prepare() {
+ default_src_prepare
+
+ mkdir -p "${BUILD_DIR}" || die
+ einfo "BUILD_DIR: \"${BUILD_DIR}\""
+
+ local system_dir="${ZBS_ECLASS_DIR}/p/"
+ mkdir -p "${system_dir}" || die
+ ZBS_ARGS_BASE+=(
+ # Disable network access after ensuring all dependencies
+ # are unpacked (by "src_unpack" or "live_fetch")
+ --system "${system_dir}"
+ )
+}
+
+# @FUNCTION: zig_src_configure
+# @DESCRIPTION:
+# Creates ZBS_ARGS array which can be used in all future phases,
+# by combining ZBS_ARGS_BASE set previously, my_zbs_args from ebuild,
+# and ZBS_ARGS_EXTRA by user, in this order.
+#
+# Specific flags currently only add support for the cross-compilation.
+# They are likely to be extended in the future.
+zig_src_configure() {
+ # Handle quoted whitespace.
+ eval "local -a ZBS_ARGS_EXTRA=( ${ZBS_ARGS_EXTRA} )"
+
+ # Since most arguments in array are also cached by ZBS, we
+ # want to reuse array as much as possible, so prevent
+ # modification of it.
+ declare -g -a -r ZBS_ARGS=(
+ # Base arguments from pkg_setup/setup_base_args
+ "${ZBS_ARGS_BASE[@]}"
+
+ # Arguments from ebuild
+ "${my_zbs_args[@]}"
+
+ # Arguments from user
+ "${ZBS_ARGS_EXTRA[@]}"
+ )
+
+ einfo "ZBS: configured with:"
+ einfo "${ZBS_ARGS[@]}"
+}
+
+# @FUNCTION: zig_src_compile
+# @USAGE: [<args>...]
+# @DESCRIPTION:
+# Calls "ezig build" with previously set ZBS_ARGS.
+# Args passed to this function will be passed after ZBS_ARGS.
+zig_src_compile() {
+ pushd "${BUILD_DIR}" > /dev/null || die
+
+ local args=( "${ZBS_ARGS[@]}" "${@}" )
+ einfo "ZBS: compiling with: ${args[@]}"
+ nonfatal ezig build "${args[@]}" || die "ZBS: compilation failed"
+
+ popd > /dev/null || die
+}
+
+# @FUNCTION: zig_src_test
+# @USAGE: [<args>...]
+# @DESCRIPTION:
+# If "test" step exist, calls "ezig build test" with previously set
+# ZBS_ARGS.
+# Args passed to this function will be passed after ZBS_ARGS.
+# Note: currently step detection might give false positives in
+# very rare cases, it will be improved in the future.
+zig_src_test() {
+ pushd "${BUILD_DIR}" > /dev/null || die
+
+ local args=( "${ZBS_ARGS[@]}" "${@}" )
+
+ # UPSTREAM std.testing.tmpDir and a lot of other functions
+ # do not respect --cache-dir or ZIG_LOCAL_CACHE_DIR:
+ # https://github.com/ziglang/zig/issues/19874
+ mkdir ".zig-cache/" || die
+
+ # UPSTREAM Currently, step name can have any characters in it,
+ # including whitespaces, so splitting names and descriptions
+ # by whitespaces is not enough for some cases.
+ # We probably need something like "--list-steps names_only".
+ # In practice, almost nobody sets such names.
+ if grep -q '^[ ]*test[ ]' < <(
+ nonfatal ezig build --list-steps "${args[@]}" ||
+ die "ZBS: listing steps failed"
+ ); then
+ einfo "ZBS: testing with: ${args[@]}"
+ nonfatal ezig build test "${args[@]}" ||
+ die "ZBS: tests failed"
+ else
+ einfo "Test step not found, skipping."
+ fi
+
+ popd > /dev/null || die
+}
+
+# @FUNCTION: zig_src_install
+# @USAGE: [<args>...]
+# @DESCRIPTION:
+# Calls "ezig build" with DESTDIR and previously set ZBS_ARGS.
+# Args passed to this function will be passed after ZBS_ARGS.
+# Also installs documentation via "einstalldocs".
+zig_src_install() {
+ pushd "${BUILD_DIR}" > /dev/null || die
+ local args=( "${ZBS_ARGS[@]}" "${@}" )
+ einfo "ZBS: installing with: ${args[@]}"
+ DESTDIR="${D}" nonfatal ezig build "${args[@]}" ||
+ die "ZBS: installing failed"
+ popd > /dev/null || die
+
+ einstalldocs
+}
+
+fi
+
+if [[ ! ${ZIG_OPTIONAL} ]]; then
+ EXPORT_FUNCTIONS pkg_setup src_unpack src_prepare src_configure src_compile src_test src_install
+fi