Reported on IRC.
Reported-by: sin-ack <[email protected]>
Signed-off-by: Eric Joldasov <[email protected]>
---
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 <[email protected]>
# @AUTHOR:
# Eric Joldasov <[email protected]>
# @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