From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id BD3E3159C96 for ; Thu, 25 Jul 2024 18:07:28 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 214022BC049; Thu, 25 Jul 2024 18:06:36 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id BCDA82BC046 for ; Thu, 25 Jul 2024 18:06:35 +0000 (UTC) From: James Le Cuirot To: gentoo-dev Cc: rust@gentoo.org, python@gentoo.org, James Le Cuirot Subject: [gentoo-dev] [PATCH 3/6] cargo.eclass: Handle LDFLAGS and RUSTFLAGS better Date: Thu, 25 Jul 2024 19:02:16 +0100 Message-ID: <20240725180612.19453-4-chewi@gentoo.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240725180612.19453-1-chewi@gentoo.org> References: <20240725180612.19453-1-chewi@gentoo.org> Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-dev@lists.gentoo.org Reply-to: gentoo-dev@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Archives-Salt: a0eb0386-e174-4bcf-9c84-b386d94c68a1 X-Archives-Hash: a0179b039a6f229f906064cafa83b3eb LDFLAGS are not currently honoured by Cargo builds at all. It would be particularly advantageous to honour -fuse-ld because alternative linkers like mold are known to be significantly faster at handling Rust. As things stand, the eclass sets the linker to CC when cross-compiling, but it does so erroneously due to a shell quoting issue. If CC includes arguments, an error occurs when setting the CARGO_TARGET_*_LINKER variable. Even with the right quoting, Cargo still fails because this variable is not allowed to include arguments. They have to be specified via RUSTFLAGS instead. The build host linker is frequently invoked due to the use of build scripts by some crates. We would therefore also like to configure the build host linker properly when cross-compiling, but unfortunately there is currently no way to do this without using a Rust nightly feature. The build host linker is now configured in the cargo_gen_config function because this configuration is static. Conversely, the target host linker is configured with environment variables in the cargo_env function because the target may change. Some ebuilds already set RUSTFLAGS, so some consideration was given to how to handle these. When set, Cargo prioritises RUSTFLAGS and similar over specific configuration for the build and target hosts, so these must be unset. We can still include their contents in that configuration for convenience though. CARGO_BUILD_RUSTFLAGS can be used by ebuilds to set flags only for the build host. It should not be necessary for ebuilds to figure out which Rust ABI is applicable in order to set flags only for the target host, so the helper reads from a simple CARGO_TARGET_RUSTFLAGS variable without the triple for convenience. Signed-off-by: James Le Cuirot --- eclass/cargo.eclass | 65 +++++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/eclass/cargo.eclass b/eclass/cargo.eclass index d598af8825adf..6ea37ec5e4e4b 100644 --- a/eclass/cargo.eclass +++ b/eclass/cargo.eclass @@ -109,7 +109,7 @@ ECARGO_VENDOR="${ECARGO_HOME}/gentoo" # # If you enable CARGO_OPTIONAL, you have to set BDEPEND on virtual/rust # for your package and call at least cargo_gen_config manually before using -# other src_functions of this eclass. +# other src_functions or cargo_env of this eclass. # Note that cargo_gen_config is automatically called by cargo_src_unpack. # @ECLASS_VARIABLE: myfeatures @@ -259,6 +259,19 @@ cargo_crate_uris() { cargo_gen_config() { debug-print-function ${FUNCNAME} "$@" + # The default linker is "cc" so override by setting linker to CC in the + # RUSTFLAGS. The given linker cannot include any arguments, so split these + # into link-args along with LDFLAGS. Also include external RUSTFLAGS. + # Note that as of Rust 1.80, the build host RUSTFLAGS are ignored when + # cross-compiling unless you use the unstable host-config feature available + # with USE=nightly. There is no simple way around this. + tc-export_build_env + local LD_A=( $(tc-getBUILD_CC) ${BUILD_LDFLAGS} ) + local BUILD_RUSTFLAGS="-C linker=${LD_A[0]}" + [[ ${#LD_A[@]} -gt 1 ]] && BUILD_RUSTFLAGS+="$(printf -- ' -C link-arg=%s' "${LD_A[@]:1}")" + BUILD_RUSTFLAGS+=" ${RUSTFLAGS} ${CARGO_BUILD_RUSTFLAGS}" + tc-is-cross-compiler || BUILD_RUSTFLAGS+=" ${CARGO_TARGET_RUSTFLAGS}" + mkdir -p "${ECARGO_HOME}" || die cat > "${ECARGO_HOME}/config.toml" <<- _EOF_ || die "Failed to create cargo config" @@ -273,6 +286,7 @@ cargo_gen_config() { offline = true [build] + rustflags = "${BUILD_RUSTFLAGS}" jobs = $(makeopts_jobs) incremental = false @@ -527,27 +541,41 @@ cargo_src_configure() { # @USAGE: Command with its arguments # @DESCRIPTION: # Run the given command under an environment needed for performing tasks with -# Cargo such as building. +# Cargo such as building. RUSTFLAGS is used for both the build and target host. +# CARGO_BUILD_RUSTFLAGS and CARGO_TARGET_RUSTFLAGS are used for just the build +# host and target host respectively. Ensure these are set consistently between +# Cargo invocations, otherwise rebuilds will occur. cargo_env() { + [[ ${_CARGO_GEN_CONFIG_HAS_RUN} ]] || \ + die "FATAL: please call cargo_gen_config before using ${FUNCNAME}" + filter-lto tc-export AR CC CXX PKG_CONFIG + # Set vars for cc-rs crate. + local -x \ + HOST_AR=$(tc-getBUILD_AR) + HOST_CC=$(tc-getBUILD_CC) + HOST_CXX=$(tc-getBUILD_CXX) + HOST_CFLAGS=${BUILD_CFLAGS} + HOST_CXXFLAGS=${BUILD_CXXFLAGS} + if tc-is-cross-compiler; then - declare -x CARGO_BUILD_TARGET=$(rust_abi) + local -x CARGO_BUILD_TARGET=$(rust_abi) local TRIPLE=${CARGO_BUILD_TARGET//-/_} - declare -x CARGO_TARGET_"${TRIPLE^^}"_LINKER=$(tc-getCC) - - # Set vars for cc-rs crate. - tc-export_build_env - declare -x \ - HOST_AR=$(tc-getBUILD_AR) - HOST_CC=$(tc-getBUILD_CC) - HOST_CXX=$(tc-getBUILD_CXX) - HOST_CFLAGS=${BUILD_CFLAGS} - HOST_CXXFLAGS=${BUILD_CXXFLAGS} + local TRIPLE=${TRIPLE^^} LD_A=( $(tc-getCC) ${LDFLAGS} ) + local -x CARGO_TARGET_"${TRIPLE}"_RUSTFLAGS="-C linker=${LD_A[0]}" + [[ ${#LD_A[@]} -gt 1 ]] && local CARGO_TARGET_"${TRIPLE}"_RUSTFLAGS+="$(printf -- ' -C link-arg=%s' "${LD_A[@]:1}")" + local CARGO_TARGET_"${TRIPLE}"_RUSTFLAGS+=" ${RUSTFLAGS} ${CARGO_TARGET_RUSTFLAGS}" fi - "${@}" + ( + # These variables will override the above, even if empty, so unset them + # locally. Do this in a subshell so that they remain set afterwards. + unset CARGO_BUILD_RUSTFLAGS CARGO_ENCODED_RUSTFLAGS RUSTFLAGS + + "${@}" + ) } # @FUNCTION: cargo_src_compile @@ -556,9 +584,6 @@ cargo_env() { cargo_src_compile() { debug-print-function ${FUNCNAME} "$@" - [[ ${_CARGO_GEN_CONFIG_HAS_RUN} ]] || \ - die "FATAL: please call cargo_gen_config before using ${FUNCNAME}" - set -- cargo build $(usex debug "" --release) ${ECARGO_ARGS[@]} "$@" einfo "${@}" cargo_env "${@}" || die "cargo build failed" @@ -573,9 +598,6 @@ cargo_src_compile() { cargo_src_install() { debug-print-function ${FUNCNAME} "$@" - [[ ${_CARGO_GEN_CONFIG_HAS_RUN} ]] || \ - die "FATAL: please call cargo_gen_config before using ${FUNCNAME}" - set -- cargo install $(has --path ${@} || echo --path ./) \ --root "${ED}/usr" \ ${GIT_CRATES[@]:+--frozen} \ @@ -594,9 +616,6 @@ cargo_src_install() { cargo_src_test() { debug-print-function ${FUNCNAME} "$@" - [[ ${_CARGO_GEN_CONFIG_HAS_RUN} ]] || \ - die "FATAL: please call cargo_gen_config before using ${FUNCNAME}" - set -- cargo test $(usex debug "" --release) ${ECARGO_ARGS[@]} "$@" einfo "${@}" cargo_env "${@}" || die "cargo test failed" -- 2.45.2