public inbox for gentoo-dev@lists.gentoo.org
 help / color / mirror / Atom feed
From: James Le Cuirot <chewi@gentoo.org>
To: gentoo-dev <gentoo-dev@lists.gentoo.org>
Cc: James Le Cuirot <chewi@gentoo.org>
Subject: [gentoo-dev] [PATCH 2/3 v2] cargo.eclass: Handle LDFLAGS and RUSTFLAGS better
Date: Wed, 24 Jul 2024 23:18:25 +0100	[thread overview]
Message-ID: <20240724221830.31469-5-chewi@gentoo.org> (raw)
In-Reply-To: <20240724221830.31469-3-chewi@gentoo.org>

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.

We would also like to configure the build host linker properly when
cross-compiling, but strangely there is no equivalent linker variable
for the build host. It can only be set via RUSTFLAGS. For consistency,
we now use RUSTFLAGS for the target host linker as well.

Some ebuilds already set RUSTFLAGS, so some consideration was given to
how to handle these. When set, Cargo prioritises RUSTFLAGS over
CARGO_BUILD_RUSTFLAGS and CARGO_TARGET_*_RUSTFLAGS, so we need it unset
to allow different flags for the build and target hosts. We can still
include its contents in the latter variables for convenience though.

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.

Unfortunately, I have not yet encountered a package that makes use of
CARGO_BUILD_RUSTFLAGS while cross-compiling, but as far as I can tell,
it should work.

Signed-off-by: James Le Cuirot <chewi@gentoo.org>
---
 eclass/cargo.eclass | 45 ++++++++++++++++++++++++++++++++-------------
 1 file changed, 32 insertions(+), 13 deletions(-)

diff --git a/eclass/cargo.eclass b/eclass/cargo.eclass
index b6d5fe21f0a7b..9ccd482e6b2d1 100644
--- a/eclass/cargo.eclass
+++ b/eclass/cargo.eclass
@@ -527,27 +527,46 @@ 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() {
 	filter-lto
 	tc-export AR CC CXX PKG_CONFIG

+	# 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}
+
+	# 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.
+	local LD_A=( ${HOST_CC} ${BUILD_LDFLAGS} )
+	declare -x CARGO_BUILD_RUSTFLAGS="${RUSTFLAGS} ${CARGO_BUILD_RUSTFLAGS} -C linker=${LD_A[0]}"
+	[[ ${#LD_A[@]} -gt 1 ]] && declare CARGO_BUILD_RUSTFLAGS+="$(printf -- ' -C link-arg=%s' "${LD_A[@]:1}")"
+
 	if tc-is-cross-compiler; then
 		declare -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=${CARGO_BUILD_TARGET//-/_} LD_A=( $(tc-getCC) ${LDFLAGS} )
+		declare -x CARGO_TARGET_"${TRIPLE^^}"_RUSTFLAGS="${RUSTFLAGS} ${CARGO_TARGET_RUSTFLAGS} -C linker=${LD_A[0]}"
+		[[ ${#LD_A[@]} -gt 1 ]] && declare CARGO_TARGET_"${TRIPLE^^}"_RUSTFLAGS+="$(printf -- ' -C link-arg=%s' "${LD_A[@]:1}")"
+	else
+		CARGO_BUILD_RUSTFLAGS+=" ${CARGO_TARGET_RUSTFLAGS}"
 	fi

-	"${@}"
+	(
+		# Bare RUSTFLAGS will override the above, even if empty, so unset it
+		# locally. Do this in a subshell so that it remains set afterwards.
+		unset RUSTFLAGS
+
+		"${@}"
+	)
 }

 # @FUNCTION: cargo_src_compile
--
2.45.2


  reply	other threads:[~2024-07-24 22:19 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-24 22:18 [gentoo-dev] [PATCH 1/3 v2] cargo.eclass: Add cargo_env helper and use it in compile, test, install James Le Cuirot
2024-07-24 22:18 ` James Le Cuirot [this message]
2024-07-24 22:18 ` [gentoo-dev] [PATCH 3/3 v2] cargo.eclass: Explicitly tell rustc not to strip binaries James Le Cuirot

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=20240724221830.31469-5-chewi@gentoo.org \
    --to=chewi@gentoo.org \
    --cc=gentoo-dev@lists.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