From: sin-ack <sin-...@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 <bratishkae...@landless-city.net>
Signed-off-by: Eric Joldasov <bratishkae...@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 <bratishkae...@landless-city.net>
 # @AUTHOR:
 # Alfred Wingate <par...@protonmail.com>
 # Violet Purcell <vimpro...@inventati.org>
 # Eric Joldasov <bratishkae...@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


Reply via email to