From: James Le Cuirot <chewi@gentoo.org>
To: gentoo-dev <gentoo-dev@lists.gentoo.org>
Cc: rust@gentoo.org, James Le Cuirot <chewi@gentoo.org>
Subject: [gentoo-dev] [PATCH 1/2] cargo.eclass: Change RUSTFLAGS approach following recent build failures
Date: Wed, 7 Aug 2024 16:52:11 +0100 [thread overview]
Message-ID: <20240807160221.1035675-2-chewi@gentoo.org> (raw)
In-Reply-To: <20240807160221.1035675-1-chewi@gentoo.org>
Cargo turned out to be even worse at handling flags than I thought.
Target-specific flags set by projects were overriding our own, and Cargo
was bailing out when faced with merging a string of flags with an array
of flags.
After weighing up the poor set of options, I've found that it is better
to always set flags via a target-specific environment variable for
reasons set out in comments added here. This approach was previously
just used for cross-compiling, but now we do it unconditionally.
It has the downside of overriding generic [build] flags set by projects,
but these were already being overridden by users and ebuilds setting
RUSTFLAGS themselves.
Closes: https://bugs.gentoo.org/937453
Closes: https://bugs.gentoo.org/937470
Signed-off-by: James Le Cuirot <chewi@gentoo.org>
---
eclass/cargo.eclass | 65 +++++++++++++++++++++++++++------------------
1 file changed, 39 insertions(+), 26 deletions(-)
diff --git a/eclass/cargo.eclass b/eclass/cargo.eclass
index c360c2a6c419..6d4cf1b425eb 100644
--- a/eclass/cargo.eclass
+++ b/eclass/cargo.eclass
@@ -259,19 +259,6 @@ 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 MY_BUILD_RUSTFLAGS="-C strip=none -C linker=${LD_A[0]}"
- [[ ${#LD_A[@]} -gt 1 ]] && MY_BUILD_RUSTFLAGS+="$(printf -- ' -C link-arg=%s' "${LD_A[@]:1}")"
- MY_BUILD_RUSTFLAGS+=" ${RUSTFLAGS} ${BUILD_RUSTFLAGS}"
- tc-is-cross-compiler || MY_BUILD_RUSTFLAGS+=" ${TARGET_RUSTFLAGS}"
-
mkdir -p "${ECARGO_HOME}" || die
cat > "${ECARGO_HOME}/config.toml" <<- _EOF_ || die "Failed to create cargo config"
@@ -286,7 +273,6 @@ cargo_gen_config() {
offline = true
[build]
- rustflags = "${MY_BUILD_RUSTFLAGS}"
jobs = $(makeopts_jobs)
incremental = false
@@ -541,10 +527,11 @@ 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. RUSTFLAGS is used for both the build and target host.
-# BUILD_RUSTFLAGS and 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 such as building. RUSTFLAGS are appended to additional flags set here.
+# Ensure these are set consistently between Cargo invocations, otherwise
+# rebuilds will occur. Project-specific rustflags set against [build] will not
+# take affect due to Cargo limitations, so add these to your ebuild's RUSTFLAGS
+# if they seem important.
cargo_env() {
[[ ${_CARGO_GEN_CONFIG_HAS_RUN} ]] || \
die "FATAL: please call cargo_gen_config before using ${FUNCNAME}"
@@ -569,14 +556,40 @@ cargo_env() {
HOST_CFLAGS=${BUILD_CFLAGS}
HOST_CXXFLAGS=${BUILD_CXXFLAGS}
- if tc-is-cross-compiler; then
- local -x CARGO_BUILD_TARGET=$(rust_abi)
- local TRIPLE=${CARGO_BUILD_TARGET//-/_}
- local TRIPLE=${TRIPLE^^} LD_A=( $(tc-getCC) ${LDFLAGS} )
- local -x CARGO_TARGET_"${TRIPLE}"_RUSTFLAGS="-C strip=none -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} ${TARGET_RUSTFLAGS}"
- fi
+ # Unfortunately, Cargo is *really* bad at handling flags. In short, it uses
+ # the first of the RUSTFLAGS env var, any target-specific config, and then
+ # any generic [build] config. It can merge within the latter two types from
+ # different sources, but it will not merge across these different types, so
+ # if a project sets flags under [target.'cfg(all())'], it will override any
+ # flags we set under [build] and vice-versa.
+ #
+ # It has been common for users and ebuilds to set RUSTFLAGS, which would
+ # have overridden whatever a project sets anyway, so the least-worst option
+ # is to include those RUSTFLAGS in target-specific config here, which will
+ # merge with any the project sets. Only flags in generic [build] config set
+ # by the project will be lost, and ebuilds will need to add those to
+ # RUSTFLAGS themselves if they are important.
+ #
+ # We could potentially inspect a project's generic [build] config and
+ # reapply those flags ourselves, but that would require a proper toml parser
+ # like tomlq, it might lead to confusion where projects also have
+ # target-specific config, and converting arrays to strings may not work
+ # well. Nightly features to inspect the config might help here in future.
+ #
+ # As of Rust 1.80, it is not possible to set separate flags for the build
+ # host and the target host when cross-compiling. The flags given are applied
+ # to the target host only with no flags being applied to the build host. The
+ # nightly host-config feature will improve this situation later.
+ #
+ # 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.
+ local -x CARGO_BUILD_TARGET=$(rust_abi)
+ local TRIPLE=${CARGO_BUILD_TARGET//-/_}
+ local TRIPLE=${TRIPLE^^} LD_A=( $(tc-getCC) ${LDFLAGS} )
+ local -x CARGO_TARGET_"${TRIPLE}"_RUSTFLAGS="-C strip=none -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}"
(
# These variables will override the above, even if empty, so unset them
--
2.45.2
next prev parent reply other threads:[~2024-08-07 16:03 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-07 15:52 [gentoo-dev] [PATCH 0/2] cargo.eclass: Change RUSTFLAGS approach following recent build failures James Le Cuirot
2024-08-07 15:52 ` James Le Cuirot [this message]
2024-08-07 15:52 ` [gentoo-dev] [PATCH 2/2] cargo.eclass: Preserve project-specific [build] flags by reading config James Le Cuirot
2024-08-07 17:39 ` Michał Górny
2024-08-07 20:19 ` James Le Cuirot
2024-08-07 22:42 ` Ionen Wolkens
2024-08-08 2:17 ` Michał Górny
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240807160221.1035675-2-chewi@gentoo.org \
--to=chewi@gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
--cc=rust@gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox