public inbox for gentoo-dev@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-dev] [PATCH 0/4] Zig eclasses: small fixes
@ 2025-02-16 12:03 Eric Joldasov
  2025-02-16 12:03 ` [gentoo-dev] [PATCH 1/4] zig-utils.eclass: add function to get the rightmost flag from CFLAGS Eric Joldasov
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Eric Joldasov @ 2025-02-16 12:03 UTC (permalink / raw
  To: gentoo-dev

Eric Joldasov (3):
  zig-utils.eclass: add function to get the rightmost flag from CFLAGS
  zig-utils.eclass: fix translating `-march=unset` and `-march=native`
    on ARM
  zig.eclass: allow unset `my_zbs_args`

sin-ack (1):
  zig.eclass: always use absolute path for `--prefix` argument

 dev-lang/zig/zig-0.13.0-r2.ebuild | 13 ++++---
 dev-lang/zig/zig-9999.ebuild      | 13 ++++---
 eclass/tests/zig-utils.sh         |  8 +++-
 eclass/zig-utils.eclass           | 61 +++++++++++++++++++++++++++----
 eclass/zig.eclass                 | 32 +++++++++++-----
 5 files changed, 97 insertions(+), 30 deletions(-)

-- 
2.48.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [gentoo-dev] [PATCH 1/4] zig-utils.eclass: add function to get the rightmost flag from CFLAGS
  2025-02-16 12:03 [gentoo-dev] [PATCH 0/4] Zig eclasses: small fixes Eric Joldasov
@ 2025-02-16 12:03 ` Eric Joldasov
  2025-02-16 12:03 ` [gentoo-dev] [PATCH 2/4] zig-utils.eclass: fix translating `-march=unset` and `-march=native` on ARM Eric Joldasov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Eric Joldasov @ 2025-02-16 12:03 UTC (permalink / raw
  To: gentoo-dev

Similar to `get-flag` from toolchain.eclass, but searches from the end,
uses only CFLAGS, and returns value only.

Signed-off-by: Eric Joldasov <bratishkaerik@landless-city.net>
---
 eclass/zig-utils.eclass | 43 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 36 insertions(+), 7 deletions(-)

diff --git a/eclass/zig-utils.eclass b/eclass/zig-utils.eclass
index 5502d997935e..d92fd0724b17 100644
--- a/eclass/zig-utils.eclass
+++ b/eclass/zig-utils.eclass
@@ -1,559 +1,588 @@
 # Copyright 2024-2025 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_NEEDS_LLVM
 # @PRE_INHERIT
 # @DEFAULT_UNSET
 # @DESCRIPTION:
 # If set to a non-empty value, the package will BDEPEND on a Zig package
 # with LLVM enabled.  This is currently required for packages that require
 # C/C++ source files to be compiled with Zig.
 
 # @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
 	_ZIG_USEDEP=""
 	if [[ ${ZIG_NEEDS_LLVM} ]]; then
 		_ZIG_USEDEP="[llvm(+)]"
 	fi
 
 	# NOTE: zig-bin is always built with LLVM support, so no USE needed.
 	BDEPEND="
 		|| (
 			dev-lang/zig:${ZIG_SLOT}${_ZIG_USEDEP}
 			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: _get-c-option
+# @INTERNAL
+# @USAGE: <option-name>
+# @DESCRIPTION:
+# Gets value of some compiler option from CFLAGS, starting from the end.
+# Must be a full name, without "-" and "=..." part.
+#
+# Example:
+# @CODE
+# CFLAGS="-march=i686 -march=i586"
+# _get-c-option march # returns i586
+# @CODE
+_get-c-option() {
+	if [[ ${#} -ne 1 ]]; then
+		die "${FUNCNAME[0]}: expected 1 argument, got ${#}"
+	fi
+
+	local prefix="-${1}="
+	local c_flags=( ${CFLAGS} )
+	for (( i=${#c_flags[@]} - 1; i >= 0; i -= 1 )); do
+		local c_flag="${c_flags[i]}"
+		if [[ "${c_flag}" == ${prefix}* ]]; then
+			echo "${c_flag#${prefix}}"
+			return
+	    fi
+	done
+	echo ""
+}
+
 # @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 -x CFLAGS="${2}"
+	local c_flags_march="$(_get-c-option 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 -x CFLAGS="${2}"
+	local c_flags_mabi="$(_get-c-option mabi)"
+	local c_flags_march="$(_get-c-option march)"
+	local c_flags_mcpu="$(_get-c-option mcpu)"
+	local c_flags_mfpu="$(_get-c-option 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 -x ZIG_GLOBAL_CACHE_DIR="${T}/zig-detect"
 	mkdir -p "${ZIG_GLOBAL_CACHE_DIR}" || die
 	touch "${ZIG_GLOBAL_CACHE_DIR}/empty.zig" || die
 
 	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
 				if [[ ${ZIG_NEEDS_LLVM} ]]; then
 					"${candidate_path}" test -fllvm -OReleaseSmall "${ZIG_GLOBAL_CACHE_DIR}/empty.zig" &> /dev/null || continue
 				fi
 				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
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [gentoo-dev] [PATCH 2/4] zig-utils.eclass: fix translating `-march=unset` and `-march=native` on ARM
  2025-02-16 12:03 [gentoo-dev] [PATCH 0/4] Zig eclasses: small fixes Eric Joldasov
  2025-02-16 12:03 ` [gentoo-dev] [PATCH 1/4] zig-utils.eclass: add function to get the rightmost flag from CFLAGS Eric Joldasov
@ 2025-02-16 12:03 ` Eric Joldasov
  2025-02-16 12:03 ` [gentoo-dev] [PATCH 3/4] zig.eclass: allow unset `my_zbs_args` Eric Joldasov
  2025-02-16 12:03 ` [gentoo-dev] [PATCH 4/4] zig.eclass: always use absolute path for `--prefix` argument Eric Joldasov
  3 siblings, 0 replies; 5+ messages in thread
From: Eric Joldasov @ 2025-02-16 12:03 UTC (permalink / raw
  To: gentoo-dev; +Cc: sin-ack

Reported on IRC.

Reported-by: sin-ack <sin-ack@protonmail.com>
Signed-off-by: Eric Joldasov <bratishkaerik@landless-city.net>
---
 eclass/tests/zig-utils.sh |  8 +++++++-
 eclass/zig-utils.eclass   | 18 +++++++++++++++++-
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/eclass/tests/zig-utils.sh b/eclass/tests/zig-utils.sh
index 14af1d2105e3..3c98134b9006 100755
--- a/eclass/tests/zig-utils.sh
+++ b/eclass/tests/zig-utils.sh
@@ -1,320 +1,326 @@
 #!/bin/bash
-# Copyright 2024 Gentoo Authors
+# Copyright 2024-2025 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
+
+	["-march=armv7-a -march=unset"]="generic-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"
+
+	["-march=native"]="native"
+	["-march=native -mtune=native"]="generic"
+	["-mcpu=cortex-a78 -march=native"]="cortex_a78"
 )
 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/zig-utils.eclass b/eclass/zig-utils.eclass
index d92fd0724b17..e9d91b8f5f52 100644
--- a/eclass/zig-utils.eclass
+++ b/eclass/zig-utils.eclass
@@ -1,588 +1,604 @@
 # Copyright 2024-2025 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_NEEDS_LLVM
 # @PRE_INHERIT
 # @DEFAULT_UNSET
 # @DESCRIPTION:
 # If set to a non-empty value, the package will BDEPEND on a Zig package
 # with LLVM enabled.  This is currently required for packages that require
 # C/C++ source files to be compiled with Zig.
 
 # @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
 	_ZIG_USEDEP=""
 	if [[ ${ZIG_NEEDS_LLVM} ]]; then
 		_ZIG_USEDEP="[llvm(+)]"
 	fi
 
 	# NOTE: zig-bin is always built with LLVM support, so no USE needed.
 	BDEPEND="
 		|| (
 			dev-lang/zig:${ZIG_SLOT}${_ZIG_USEDEP}
 			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: _get-c-option
 # @INTERNAL
 # @USAGE: <option-name>
 # @DESCRIPTION:
 # Gets value of some compiler option from CFLAGS, starting from the end.
 # Must be a full name, without "-" and "=..." part.
 #
 # Example:
 # @CODE
 # CFLAGS="-march=i686 -march=i586"
 # _get-c-option march # returns i586
 # @CODE
 _get-c-option() {
 	if [[ ${#} -ne 1 ]]; then
 		die "${FUNCNAME[0]}: expected 1 argument, got ${#}"
 	fi
 
 	local prefix="-${1}="
 	local c_flags=( ${CFLAGS} )
 	for (( i=${#c_flags[@]} - 1; i >= 0; i -= 1 )); do
 		local c_flag="${c_flags[i]}"
 		if [[ "${c_flag}" == ${prefix}* ]]; then
 			echo "${c_flag#${prefix}}"
 			return
 	    fi
 	done
 	echo ""
 }
 
 # @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 -x CFLAGS="${2}"
 	local c_flags_march="$(_get-c-option 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 -x CFLAGS="${2}"
 	local c_flags_mabi="$(_get-c-option mabi)"
 	local c_flags_march="$(_get-c-option march)"
 	local c_flags_mcpu="$(_get-c-option mcpu)"
 	local c_flags_mfpu="$(_get-c-option mfpu)"
+	local c_flags_mtune="$(_get-c-option mtune)"
 
 	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
-				"") ;;
+				"" | unset) ;;
 				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}"
 					;;
+				native)
+					# GCC docs: This option has no effect if
+					# the compiler is unable to recognize the
+					# architecture of the host system.
+					#
+					# When -march=native is given and no other
+					# -mcpu or -mtune is given then ... -march=native
+					# is treated as -mcpu=native.
+					if [[ -z "${c_flags_mcpu}${c_flags_mtune}" ]]; then
+						base_cpu=native
+					else
+						: # Zig can not detect CPU features (architecture
+						# in our case) separately from model, so we ignore it.
+					fi
+					;;
 				*) 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 -x ZIG_GLOBAL_CACHE_DIR="${T}/zig-detect"
 	mkdir -p "${ZIG_GLOBAL_CACHE_DIR}" || die
 	touch "${ZIG_GLOBAL_CACHE_DIR}/empty.zig" || die
 
 	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
 				if [[ ${ZIG_NEEDS_LLVM} ]]; then
 					"${candidate_path}" test -fllvm -OReleaseSmall "${ZIG_GLOBAL_CACHE_DIR}/empty.zig" &> /dev/null || continue
 				fi
 				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
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [gentoo-dev] [PATCH 3/4] zig.eclass: allow unset `my_zbs_args`
  2025-02-16 12:03 [gentoo-dev] [PATCH 0/4] Zig eclasses: small fixes Eric Joldasov
  2025-02-16 12:03 ` [gentoo-dev] [PATCH 1/4] zig-utils.eclass: add function to get the rightmost flag from CFLAGS Eric Joldasov
  2025-02-16 12:03 ` [gentoo-dev] [PATCH 2/4] zig-utils.eclass: fix translating `-march=unset` and `-march=native` on ARM Eric Joldasov
@ 2025-02-16 12:03 ` Eric Joldasov
  2025-02-16 12:03 ` [gentoo-dev] [PATCH 4/4] zig.eclass: always use absolute path for `--prefix` argument Eric Joldasov
  3 siblings, 0 replies; 5+ messages in thread
From: Eric Joldasov @ 2025-02-16 12:03 UTC (permalink / raw
  To: gentoo-dev

Previously it was defined as empty string when not setting this variable,
which caused error during building because Zig treat it as a name of
non-existant step "".

Also fix DEFAULT_UNSET comment on `BUILD_DIR` and `my_zbs_args`.

Closes: https://bugs.gentoo.org/948168
Signed-off-by: Eric Joldasov <bratishkaerik@landless-city.net>
---
 eclass/zig.eclass | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/eclass/zig.eclass b/eclass/zig.eclass
index 2a0178e66d71..26b55bf05d7f 100644
--- a/eclass/zig.eclass
+++ b/eclass/zig.eclass
@@ -1,559 +1,558 @@
-# Copyright 2024 Gentoo Authors
+# Copyright 2024-2025 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
+# @DEFAULT_UNSET
 # @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.
 	# Ignore failures like rare random "error.BrokenPipe" here.
 	# If they are real, they would appear in "ezig build test" anyway.
 	if grep -q '^[ ]*test[ ]' < <(
 		nonfatal ezig build --list-steps "${args[@]}"
 	); 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
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [gentoo-dev] [PATCH 4/4] zig.eclass: always use absolute path for `--prefix` argument
  2025-02-16 12:03 [gentoo-dev] [PATCH 0/4] Zig eclasses: small fixes Eric Joldasov
                   ` (2 preceding siblings ...)
  2025-02-16 12:03 ` [gentoo-dev] [PATCH 3/4] zig.eclass: allow unset `my_zbs_args` Eric Joldasov
@ 2025-02-16 12:03 ` Eric Joldasov
  3 siblings, 0 replies; 5+ messages in thread
From: Eric Joldasov @ 2025-02-16 12:03 UTC (permalink / raw
  To: gentoo-dev; +Cc: sin-ack

From: sin-ack <sin-ack@protonmail.com>

Needed for correctness when `build.zig` uses them to manipulate default
pathes in compiled artifact. Without `DESTDIR` it would try to install
to root directly, so to fix this we set `DESTDIR` where appliable.

Co-authored-by: Eric Joldasov <bratishkaerik@landless-city.net>
Signed-off-by: Eric Joldasov <bratishkaerik@landless-city.net>
---
 dev-lang/zig/zig-0.13.0-r2.ebuild | 13 +++++++------
 dev-lang/zig/zig-9999.ebuild      | 13 +++++++------
 eclass/zig.eclass                 | 27 +++++++++++++++++++++------
 3 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/dev-lang/zig/zig-0.13.0-r2.ebuild b/dev-lang/zig/zig-0.13.0-r2.ebuild
index b970092ce4e4..b03ee38a13ef 100644
--- a/dev-lang/zig/zig-0.13.0-r2.ebuild
+++ b/dev-lang/zig/zig-0.13.0-r2.ebuild
@@ -1,248 +1,249 @@
 # Copyright 2019-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 EAPI=8
 
 LLVM_COMPAT=( 18 )
 LLVM_OPTIONAL=1
 
 ZIG_SLOT="$(ver_cut 1-2)"
 ZIG_OPTIONAL=1
 
 inherit check-reqs cmake flag-o-matic edo llvm-r1 toolchain-funcs zig
 
 DESCRIPTION="A robust, optimal, and maintainable programming language"
 HOMEPAGE="https://ziglang.org/ https://github.com/ziglang/zig/"
 if [[ ${PV} == 9999 ]]; then
 	EGIT_REPO_URI="https://github.com/ziglang/zig.git"
 	inherit git-r3
 else
 	VERIFY_SIG_METHOD=minisig
 	VERIFY_SIG_OPENPGP_KEY_PATH=/usr/share/minisig-keys/zig-software-foundation.pub
 	inherit verify-sig
 
 	SRC_URI="
 		https://ziglang.org/download/${PV}/${P}.tar.xz
 		verify-sig? ( https://ziglang.org/download/${PV}/${P}.tar.xz.minisig )
 		https://codeberg.org/BratishkaErik/distfiles/releases/download/dev-lang%2Fzig-${PV}/${P}-llvm-18.1.8-r6-fix.patch
 	"
 	KEYWORDS="~amd64 ~arm ~arm64"
 
 	BDEPEND="verify-sig? ( sec-keys/minisig-keys-zig-software-foundation )"
 fi
 
 # project itself: MIT
 # There are bunch of projects under "lib/" folder that are needed for cross-compilation.
 # Files that are unnecessary for cross-compilation are removed by upstream
 # and therefore their licenses (if any special) are not included.
 # lib/libunwind: Apache-2.0-with-LLVM-exceptions || ( UoI-NCSA MIT )
 # lib/libcxxabi: Apache-2.0-with-LLVM-exceptions || ( UoI-NCSA MIT )
 # lib/libcxx: Apache-2.0-with-LLVM-exceptions || ( UoI-NCSA MIT )
 # lib/libc/wasi: || ( Apache-2.0-with-LLVM-exceptions Apache-2.0 MIT BSD-2 ) public-domain
 # lib/libc/musl: MIT BSD-2
 # lib/libc/mingw: ZPL public-domain BSD-2 ISC HPND
 # lib/libc/glibc: BSD HPND ISC inner-net LGPL-2.1+
 LICENSE="MIT Apache-2.0-with-LLVM-exceptions || ( UoI-NCSA MIT ) || ( Apache-2.0-with-LLVM-exceptions Apache-2.0 MIT BSD-2 ) public-domain BSD-2 ZPL ISC HPND BSD inner-net LGPL-2.1+"
 SLOT="${ZIG_SLOT}"
 IUSE="doc +llvm"
 REQUIRED_USE="
 	!llvm? ( !doc )
 	llvm? ( ${LLVM_REQUIRED_USE} )
 "
 
 # Used by both "cmake" and "zig" eclasses.
 BUILD_DIR="${WORKDIR}/${P}_build"
 
 # Zig requires zstd and zlib compression support in LLVM, if using LLVM backend.
 # (non-LLVM backends don't require these)
 # They are not required "on their own", so please don't add them here.
 # You can check https://github.com/ziglang/zig-bootstrap in future, to see
 # options that are passed to LLVM CMake building (excluding "static" ofc).
 DEPEND="
 	llvm? (
 		$(llvm_gen_dep '
 			llvm-core/clang:${LLVM_SLOT}
 			llvm-core/lld:${LLVM_SLOT}
 			llvm-core/llvm:${LLVM_SLOT}[zstd]
 		')
 	)
 "
 BDEPEND+="
 	${DEPEND}
 "
 RDEPEND="${DEPEND}"
 IDEPEND="app-eselect/eselect-zig"
 
 DOCS=( "README.md" "doc/build.zig.zon.md" )
 
 PATCHES=(
 	"${FILESDIR}/zig-0.13.0-test-std-kernel-version.patch"
 	"${FILESDIR}/zig-0.13.0-skip-test-stack_iterator.patch"
 	"${DISTDIR}/${P}-llvm-18.1.8-r6-fix.patch"
 )
 
 # zig.eclass does not set this for us since we use ZIG_OPTIONAL=1
 QA_FLAGS_IGNORED="usr/.*/zig/${PV}/bin/zig"
 
 # Since commit https://github.com/ziglang/zig/commit/e7d28344fa3ee81d6ad7ca5ce1f83d50d8502118
 # Zig uses self-hosted compiler only
 CHECKREQS_MEMORY="4G"
 
 pkg_setup() {
 	# Skip detecting zig executable.
 	ZIG_EXE="not-applicable" ZIG_VER="${PV}" zig_pkg_setup
 
-	export ZIG_SYS_INSTALL_DEST="${EPREFIX}/usr/$(get_libdir)/zig/${PV}"
+	declare -r -g ZIG_SYS_INSTALL_DEST="${EPREFIX}/usr/$(get_libdir)/zig/${PV}"
 
 	if use llvm; then
 		tc-is-cross-compiler && die "USE=llvm is not yet supported when cross-compiling"
 		llvm-r1_pkg_setup
 	fi
 
 	check-reqs_pkg_setup
 }
 
 src_unpack() {
 	if [[ ${PV} == 9999 ]]; then
 		git-r3_src_unpack
 	else
 		if use verify-sig; then
 			verify-sig_verify_detached "${DISTDIR}"/${P}.tar.xz{,.minisig}
 		fi
 	fi
 	zig_src_unpack
 }
 
 src_prepare() {
 	if use llvm; then
 		cmake_src_prepare
 	else
 		# Sync with zig_src_prepare
 		default_src_prepare
 		mkdir -p "${BUILD_DIR}" || die
 		einfo "BUILD_DIR: \"${BUILD_DIR}\""
 		# "--system" mode is not used during bootstrap.
 	fi
 
 	# Remove "limit memory usage" flags, it's already verified by
 	# CHECKREQS_MEMORY and causes unneccessary errors. Upstream set them
 	# according to CI OOM failures, which are not applicable to normal Gentoo build.
 	sed -i -e '/\.max_rss = .*,/d' build.zig || die
 }
 
 src_configure() {
 	# Has no effect on final binary and only causes failures during bootstrapping.
 	filter-lto
 
 	# Used during bootstrapping. stage1/stage2 have limited functionality
 	# and can't resolve native target, so we pass target in exact form.
 	declare -r -g ZIG_HOST_AS_TARGET="$(zig-utils_c_env_to_zig_target "${CBUILD:-${CHOST}}" "${CFLAGS}"})"
 
 	# Note that if we are building with CMake, "my_zbs_args"
 	# are used only after compiling zig2.
 	local my_zbs_args=(
 		--zig-lib-dir "${S}/lib/"
-		# Will be a subdir under ZIG_SYS_INSTALL_DEST.
+
+		--prefix "${ZIG_SYS_INSTALL_DEST}/"
 		--prefix-lib-dir lib/
 
 		# These are built separately
 		-Dno-langref
 		-Dstd-docs=false
 
 		--release=fast
 	)
 	if use llvm; then
 		my_zbs_args+=(
 			-Denable-llvm=true
 			-Dstatic-llvm=false
 			-Dconfig_h="${BUILD_DIR}/config.h"
 		)
 	else
 		my_zbs_args+=(
 			-Denable-llvm=false
 		)
 	fi
 
 	zig_src_configure
 
 	if use llvm; then
 		# Build for native only, it's for zig2 (build-time executable)
 		# LLVM from BDEPEND
 		local mycmakeargs=(
 			-DZIG_SHARED_LLVM=ON
 			-DZIG_USE_LLVM_CONFIG=ON
 
 			-DZIG_TARGET_TRIPLE=native
 			-DZIG_TARGET_MCPU=native
 			-DZIG_HOST_TARGET_TRIPLE="${ZIG_HOST_AS_TARGET}"
 
 			-DCMAKE_PREFIX_PATH="$(get_llvm_prefix -b)"
 			-DCMAKE_INSTALL_PREFIX="${ZIG_SYS_INSTALL_DEST}"
 		)
 
 		cmake_src_configure
 	fi
 }
 
 src_compile() {
 	if use llvm; then
 		cmake_build zig2
 	else
 		cd "${BUILD_DIR}" || die
 		ln -s "${S}/stage1/" . || die
 		ln -s "${S}/src/" . || die
 		ln -s "${S}/lib/" . || die
 
 		local native_cc="$(tc-getBUILD_CC)"
 		"${native_cc}" -o bootstrap "${S}/bootstrap.c" || die "Zig's bootstrap.c compilation failed"
 		ZIG_HOST_TARGET_TRIPLE="${ZIG_HOST_AS_TARGET}" CC="${native_cc}" edo ./bootstrap
 	fi
 
 	cd "${BUILD_DIR}" || die
-	ZIG_EXE="./zig2" zig_src_compile --prefix "${BUILD_DIR}/stage3/"
+	ZIG_EXE="./zig2" zig_src_compile --prefix stage3/
 
 	./stage3/bin/zig env || die "Zig compilation failed"
 
 	if use doc; then
-		ZIG_EXE="./stage3/bin/zig" zig_src_compile langref --prefix "${S}/docgen/"
+		ZIG_EXE="./stage3/bin/zig" zig_src_compile langref --prefix docgen/
 	fi
 }
 
 src_test() {
 	cd "${BUILD_DIR}" || die
 	ZIG_EXE="./stage3/bin/zig" zig_src_test -Dskip-non-native
 }
 
 src_install() {
-	use doc && local HTML_DOCS=( "docgen/doc/langref.html" )
+	use doc && local HTML_DOCS=( "${BUILD_DIR}/docgen/doc/langref.html" )
 
-	ZIG_EXE="./zig2" zig_src_install --prefix "${ZIG_SYS_INSTALL_DEST}"
+	ZIG_EXE="./zig2" zig_src_install
 
 	cd "${D}/${ZIG_SYS_INSTALL_DEST}" || die
 	mv lib/zig/ lib2/ || die
 	rm -rf lib/ || die
 	mv lib2/ lib/ || die
 	dosym -r "${ZIG_SYS_INSTALL_DEST}/bin/zig" /usr/bin/zig-${PV}
 }
 
 pkg_postinst() {
 	eselect zig update ifunset || die
 
 	elog "Starting from 0.12.0, Zig no longer installs"
 	elog "precompiled standard library documentation."
 	elog "Instead, you can call \`zig std\` to compile it on-the-fly."
 	elog "It reflects all edits in standard library automatically."
 	elog "See \`zig std --help\` for more information."
 	elog "More details here: https://ziglang.org/download/0.12.0/release-notes.html#Redesign-How-Autodoc-Works"
 
 	if ! use llvm; then
 		elog "Currently, Zig built without LLVM support lacks some"
 		elog "important features such as most optimizations, @cImport, etc."
 		elog "They are listed under \"Building from Source without LLVM\""
 		elog "section of the README file from \"/usr/share/doc/${PF}\" ."
 	fi
 }
 
 pkg_postrm() {
 	eselect zig update ifunset || die
 }
diff --git a/dev-lang/zig/zig-9999.ebuild b/dev-lang/zig/zig-9999.ebuild
index 4f0358a96629..bd3b15d8f125 100644
--- a/dev-lang/zig/zig-9999.ebuild
+++ b/dev-lang/zig/zig-9999.ebuild
@@ -1,241 +1,242 @@
 # Copyright 2019-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 EAPI=8
 
 LLVM_COMPAT=( 19 )
 LLVM_OPTIONAL=1
 
 ZIG_SLOT="$(ver_cut 1-2)"
 ZIG_OPTIONAL=1
 
 inherit check-reqs cmake flag-o-matic edo llvm-r1 toolchain-funcs zig
 
 DESCRIPTION="A robust, optimal, and maintainable programming language"
 HOMEPAGE="https://ziglang.org/ https://github.com/ziglang/zig/"
 if [[ ${PV} == 9999 ]]; then
 	EGIT_REPO_URI="https://github.com/ziglang/zig.git"
 	inherit git-r3
 else
 	VERIFY_SIG_METHOD=minisig
 	VERIFY_SIG_OPENPGP_KEY_PATH=/usr/share/minisig-keys/zig-software-foundation.pub
 	inherit verify-sig
 
 	SRC_URI="
 		https://ziglang.org/download/${PV}/${P}.tar.xz
 		verify-sig? ( https://ziglang.org/download/${PV}/${P}.tar.xz.minisig )
 	"
 	KEYWORDS="~amd64 ~arm ~arm64"
 
 	BDEPEND="verify-sig? ( sec-keys/minisig-keys-zig-software-foundation )"
 fi
 
 # project itself: MIT
 # There are bunch of projects under "lib/" folder that are needed for cross-compilation.
 # Files that are unnecessary for cross-compilation are removed by upstream
 # and therefore their licenses (if any special) are not included.
 # lib/libunwind: Apache-2.0-with-LLVM-exceptions || ( UoI-NCSA MIT )
 # lib/libcxxabi: Apache-2.0-with-LLVM-exceptions || ( UoI-NCSA MIT )
 # lib/libcxx: Apache-2.0-with-LLVM-exceptions || ( UoI-NCSA MIT )
 # lib/libc/wasi: || ( Apache-2.0-with-LLVM-exceptions Apache-2.0 MIT BSD-2 ) public-domain
 # lib/libc/musl: MIT BSD-2
 # lib/libc/mingw: ZPL public-domain BSD-2 ISC HPND
 # lib/libc/glibc: BSD HPND ISC inner-net LGPL-2.1+
 LICENSE="MIT Apache-2.0-with-LLVM-exceptions || ( UoI-NCSA MIT ) || ( Apache-2.0-with-LLVM-exceptions Apache-2.0 MIT BSD-2 ) public-domain BSD-2 ZPL ISC HPND BSD inner-net LGPL-2.1+"
 SLOT="${ZIG_SLOT}"
 IUSE="doc +llvm"
 REQUIRED_USE="
 	!llvm? ( !doc )
 	llvm? ( ${LLVM_REQUIRED_USE} )
 "
 
 # Used by both "cmake" and "zig" eclasses.
 BUILD_DIR="${WORKDIR}/${P}_build"
 
 # Zig requires zstd and zlib compression support in LLVM, if using LLVM backend.
 # (non-LLVM backends don't require these)
 # They are not required "on their own", so please don't add them here.
 # You can check https://github.com/ziglang/zig-bootstrap in future, to see
 # options that are passed to LLVM CMake building (excluding "static" ofc).
 DEPEND="
 	llvm? (
 		$(llvm_gen_dep '
 			llvm-core/clang:${LLVM_SLOT}
 			llvm-core/lld:${LLVM_SLOT}
 			llvm-core/llvm:${LLVM_SLOT}[zstd]
 		')
 	)
 "
 BDEPEND+="
 	${DEPEND}
 "
 RDEPEND="${DEPEND}"
 IDEPEND="app-eselect/eselect-zig"
 
 DOCS=( "README.md" "doc/build.zig.zon.md" )
 
 # zig.eclass does not set this for us since we use ZIG_OPTIONAL=1
 QA_FLAGS_IGNORED="usr/.*/zig/${PV}/bin/zig"
 
 # Since commit https://github.com/ziglang/zig/commit/e7d28344fa3ee81d6ad7ca5ce1f83d50d8502118
 # Zig uses self-hosted compiler only
 CHECKREQS_MEMORY="4G"
 
 pkg_setup() {
 	# Skip detecting zig executable.
 	ZIG_EXE="not-applicable" ZIG_VER="${PV}" zig_pkg_setup
 
-	export ZIG_SYS_INSTALL_DEST="${EPREFIX}/usr/$(get_libdir)/zig/${PV}"
+	declare -r -g ZIG_SYS_INSTALL_DEST="${EPREFIX}/usr/$(get_libdir)/zig/${PV}"
 
 	if use llvm; then
 		tc-is-cross-compiler && die "USE=llvm is not yet supported when cross-compiling"
 		llvm-r1_pkg_setup
 	fi
 
 	check-reqs_pkg_setup
 }
 
 src_unpack() {
 	if [[ ${PV} == 9999 ]]; then
 		git-r3_src_unpack
 	else
 		if use verify-sig; then
 			verify-sig_verify_detached "${DISTDIR}"/${P}.tar.xz{,.minisig}
 		fi
 	fi
 	zig_src_unpack
 }
 
 src_prepare() {
 	if use llvm; then
 		cmake_src_prepare
 	else
 		# Sync with zig_src_prepare
 		default_src_prepare
 		mkdir -p "${BUILD_DIR}" || die
 		einfo "BUILD_DIR: \"${BUILD_DIR}\""
 		# "--system" mode is not used during bootstrap.
 	fi
 
 	# Remove "limit memory usage" flags, it's already verified by
 	# CHECKREQS_MEMORY and causes unneccessary errors. Upstream set them
 	# according to CI OOM failures, which are not applicable to normal Gentoo build.
 	sed -i -e '/\.max_rss = .*,/d' build.zig || die
 }
 
 src_configure() {
 	# Has no effect on final binary and only causes failures during bootstrapping.
 	filter-lto
 
 	# Used during bootstrapping. stage1/stage2 have limited functionality
 	# and can't resolve native target, so we pass target in exact form.
 	declare -r -g ZIG_HOST_AS_TARGET="$(zig-utils_c_env_to_zig_target "${CBUILD:-${CHOST}}" "${CFLAGS}"})"
 
 	# Note that if we are building with CMake, "my_zbs_args"
 	# are used only after compiling zig2.
 	local my_zbs_args=(
 		--zig-lib-dir "${S}/lib/"
-		# Will be a subdir under ZIG_SYS_INSTALL_DEST.
+
+		--prefix "${ZIG_SYS_INSTALL_DEST}/"
 		--prefix-lib-dir lib/
 
 		# These are built separately
 		-Dno-langref
 		-Dstd-docs=false
 
 		--release=fast
 	)
 	if use llvm; then
 		my_zbs_args+=(
 			-Denable-llvm=true
 			-Dstatic-llvm=false
 			-Dconfig_h="${BUILD_DIR}/config.h"
 		)
 	else
 		my_zbs_args+=(
 			-Denable-llvm=false
 		)
 	fi
 
 	zig_src_configure
 
 	if use llvm; then
 		# Build for native only, it's for zig2 (build-time executable)
 		# LLVM from BDEPEND
 		local mycmakeargs=(
 			-DZIG_SHARED_LLVM=ON
 			-DZIG_USE_LLVM_CONFIG=ON
 
 			-DZIG_TARGET_TRIPLE=native
 			-DZIG_TARGET_MCPU=native
 			-DZIG_HOST_TARGET_TRIPLE="${ZIG_HOST_AS_TARGET}"
 
 			-DCMAKE_PREFIX_PATH="$(get_llvm_prefix -b)"
 			-DCMAKE_INSTALL_PREFIX="${ZIG_SYS_INSTALL_DEST}"
 		)
 
 		cmake_src_configure
 	fi
 }
 
 src_compile() {
 	if use llvm; then
 		cmake_build zig2
 	else
 		cd "${BUILD_DIR}" || die
 		ln -s "${S}/stage1/" . || die
 		ln -s "${S}/src/" . || die
 		ln -s "${S}/lib/" . || die
 
 		local native_cc="$(tc-getBUILD_CC)"
 		"${native_cc}" -o bootstrap "${S}/bootstrap.c" || die "Zig's bootstrap.c compilation failed"
 		ZIG_HOST_TARGET_TRIPLE="${ZIG_HOST_AS_TARGET}" CC="${native_cc}" edo ./bootstrap
 	fi
 
 	cd "${BUILD_DIR}" || die
-	ZIG_EXE="./zig2" zig_src_compile --prefix "${BUILD_DIR}/stage3/"
+	ZIG_EXE="./zig2" zig_src_compile --prefix stage3/
 
 	./stage3/bin/zig env || die "Zig compilation failed"
 
 	if use doc; then
-		ZIG_EXE="./stage3/bin/zig" zig_src_compile langref --prefix "${S}/docgen/"
+		ZIG_EXE="./stage3/bin/zig" zig_src_compile langref --prefix docgen/
 	fi
 }
 
 src_test() {
 	cd "${BUILD_DIR}" || die
 	ZIG_EXE="./stage3/bin/zig" zig_src_test -Dskip-non-native
 }
 
 src_install() {
-	use doc && local HTML_DOCS=( "docgen/doc/langref.html" )
+	use doc && local HTML_DOCS=( "${BUILD_DIR}/docgen/doc/langref.html" )
 
-	ZIG_EXE="./zig2" zig_src_install --prefix "${ZIG_SYS_INSTALL_DEST}"
+	ZIG_EXE="./zig2" zig_src_install
 
 	cd "${D}/${ZIG_SYS_INSTALL_DEST}" || die
 	mv lib/zig/ lib2/ || die
 	rm -rf lib/ || die
 	mv lib2/ lib/ || die
 	dosym -r "${ZIG_SYS_INSTALL_DEST}/bin/zig" /usr/bin/zig-${PV}
 }
 
 pkg_postinst() {
 	eselect zig update ifunset || die
 
 	elog "Starting from 0.12.0, Zig no longer installs"
 	elog "precompiled standard library documentation."
 	elog "Instead, you can call \`zig std\` to compile it on-the-fly."
 	elog "It reflects all edits in standard library automatically."
 	elog "See \`zig std --help\` for more information."
 	elog "More details here: https://ziglang.org/download/0.12.0/release-notes.html#Redesign-How-Autodoc-Works"
 
 	if ! use llvm; then
 		elog "Currently, Zig built without LLVM support lacks some"
 		elog "important features such as most optimizations, @cImport, etc."
 		elog "They are listed under \"Building from Source without LLVM\""
 		elog "section of the README file from \"/usr/share/doc/${PF}\" ."
 	fi
 }
 
 pkg_postrm() {
 	eselect zig update ifunset || die
 }
diff --git a/eclass/zig.eclass b/eclass/zig.eclass
index 26b55bf05d7f..0de7ee9eb47a 100644
--- a/eclass/zig.eclass
+++ b/eclass/zig.eclass
@@ -1,558 +1,573 @@
 # Copyright 2024-2025 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
 # @DEFAULT_UNSET
 # @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.
+# Note: `--prefix` and other relative arguments will
+# process here as relative to BUILD_DIR.
 #
 # Example:
 # @CODE
 # src_configure() {
 # 	local my_zbs_args=(
 # 		-Dpie=true
 # 	)
 #
 # 	zig_src_configure
 # }
 # @CODE
 
 # @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
 # @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
 
+		# We want absolute path here so that it would appear correctly
+		# when embedded to binaries with build.zig, but without DESTDIR
+		# it would try to escape sandbox and install directly to root.
+		#
+		# Therefore, we set DESTDIR each time to be:
+		# 1) BUILD_DIR in phases before `src_install`,
+		# 2) D during `src_install`.
+		--prefix "${EPREFIX}/usr/"
 		--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.
+# They can be used to call custom steps or override some
+# options temporarily like `--prefix`.
+# Note that `--prefix` and other relative arguments will
+# process here as relative to BUILD_DIR.
 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"
+	DESTDIR="${BUILD_DIR}" 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.
+# Note that `--prefix` and other relative arguments will
+# process here as relative to BUILD_DIR.
 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.
 	# Ignore failures like rare random "error.BrokenPipe" here.
 	# If they are real, they would appear in "ezig build test" anyway.
 	if grep -q '^[ ]*test[ ]' < <(
 		nonfatal ezig build --list-steps "${args[@]}"
 	); then
 		einfo "ZBS: testing with: ${args[@]}"
-		nonfatal ezig build test "${args[@]}" ||
+		DESTDIR="${BUILD_DIR}" 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".
+# Note that `--prefix` and other relative arguments will
+# process here as relative to D.
 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
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-02-16 12:09 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-16 12:03 [gentoo-dev] [PATCH 0/4] Zig eclasses: small fixes Eric Joldasov
2025-02-16 12:03 ` [gentoo-dev] [PATCH 1/4] zig-utils.eclass: add function to get the rightmost flag from CFLAGS Eric Joldasov
2025-02-16 12:03 ` [gentoo-dev] [PATCH 2/4] zig-utils.eclass: fix translating `-march=unset` and `-march=native` on ARM Eric Joldasov
2025-02-16 12:03 ` [gentoo-dev] [PATCH 3/4] zig.eclass: allow unset `my_zbs_args` Eric Joldasov
2025-02-16 12:03 ` [gentoo-dev] [PATCH 4/4] zig.eclass: always use absolute path for `--prefix` argument Eric Joldasov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox