Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sys-devel/sysroot-wrappers: Drop in favour of setting CPP/CC/CXX #2177

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build_library/board_options.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ fi

BOARD="${FLAGS_board}"
BOARD_ROOT="/build/${BOARD}"
: "${SYSROOT=${BOARD_ROOT}}"
ARCH=$(get_board_arch ${BOARD})

# What cross-build are we targeting?
Expand Down
4 changes: 3 additions & 1 deletion build_library/toolchain_util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ _configure_sysroot() {
"${sudo[@]}" tee "${ROOT}/etc/portage/make.conf" <<EOF
$(portageq envvar -v CHOST CBUILD ROOT DISTDIR PKGDIR)
HOSTCC=\${CBUILD}-gcc
CPP="\${CHOST}-gcc -E --sysroot=\${SYSROOT}"
CC="\${CHOST}-gcc --sysroot=\${SYSROOT}"
CXX="\${CHOST}-g++ --sysroot=\${SYSROOT}"
PKG_CONFIG_PATH="\${SYSROOT}/usr/lib/pkgconfig/"
# Enable provenance reporting by default. Produced files are in /usr/share/SLSA
GENERATE_SLSA_PROVENANCE="true"
Expand Down Expand Up @@ -423,7 +426,6 @@ install_cross_toolchain() {
# Setup environment and wrappers for our shiny new toolchain
binutils_set_latest_profile "${cross_chost}"
gcc_set_latest_profile "${cross_chost}"
"${sudo[@]}" CC_QUIET=1 sysroot-config --install-links "${cross_chost}"
}

# Build/install toolchain dependencies into the cross sysroot for a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ RDEPEND="${RDEPEND}
dev-embedded/u-boot-tools
!arm64? ( sys-boot/syslinux )
sys-devel/crossdev
sys-devel/sysroot-wrappers
sys-fs/dosfstools
"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,6 @@ cros_post_src_install_set_up_var_lib_selinux() {
# Source hooks for SLSA build provenance report generation
source "${BASH_SOURCE[0]}.slsa-provenance"

# Insert our sysroot wrappers into the path
SYSROOT_WRAPPERS_BIN="/usr/lib64/sysroot-wrappers/bin"
if [[ "$PATH" != *"$SYSROOT_WRAPPERS_BIN"* ]]; then
export PATH="$SYSROOT_WRAPPERS_BIN:$PATH"
fi

# Improve the chance that ccache is valid across versions by making all
# paths under $S relative to $S, avoiding encoding the package version
# contained in the path into __FILE__ expansions and debug info.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Adapted from cross-boss. Only needed for the dev profile because we don't
# build the SDK with sysroot flags and we don't install build tools to the
# production image.
cros_pre_pkg_preinst_strip_sysroot() {
local FILES FILE

# Gather all the non-binary files with the --sysroot or --with-sysroot flag.
mapfile -t -d '' < <(find "${D}" -type f -exec grep -lZEIe "--sysroot=${ROOT}\b|--with-sysroot=${EROOT}\b" {} +) FILES
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm uneasy seeing some variables passed to grep as a regexp. I hope we won't see some weird paths in ${ROOT} or ${EROOT}. Maybe we could escape those paths somehow? Ideally, we could pass -F instead of -E to grep, but then \b won't work…

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also curious if there are files that quote (either with single quotes or double quotes) the value of the flag (--sysroot="/quoted/path").

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll see whether I can use fixed strings, although these values are only ever going to be things like /build/arm64-usr.

We control the --sysroot flag, so it will never have quotes. Similarly, the --with-sysroot flag comes from Portage itself.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could use fixed strings. There is a "risk" that this would pick up more files (with --sysroot=/build/amd64-usr/foo out of the blue), but your sed invocation should be careful enough to ignore the non-matching lines.


# Only continue if there are any.
[[ ${#FILES[@]} -eq 0 ]] && return

einfo "Stripping sysroot flags from:"
for FILE in "${FILES[@]}"; do
einfo " - ${FILE#${D}}"
done
chewi marked this conversation as resolved.
Show resolved Hide resolved

# Carefully strip the sysroot flags.
local sedargs=( -i -r )
local flag
for flag in --{,with-}sysroot="${EROOT}"; do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be the following instead? To match the flags you check with grep?

Suggested change
for flag in --{,with-}sysroot="${EROOT}"; do
for flag in "--sysroot=${ROOT}" "--with-sysroot=${EROOT}"; do

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think ROOT and EROOT are basically the same thing in our case, because we don't use eprefix, but still.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well spotted. This line is different in cross-boss, so it isn't an issue there. It's not really an issue for Flatcar either because we don't use prefix here, but still!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this some more and realised both should be ESYSROOT to match what we set the flag too. I guess I just forgot to update this in cross-boss way back. It's academic most of the time, but it does make a difference in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's funny how Flatcar is forcing me to rethink things I've been doing fine for years. I'd forgotten that I didn't use ESYSROOT here because it's not defined in the pkg phases. I'm not sure whether the dev image is prepared in the same ROOT location as the binary packages it's built from, but I'd rather assume it's not. That means I need to change this hook from pre_pkg_preinst to post_src_install, and that means it needs to apply to the generic profile, not just the dev profile. While I'm happy to make this change for cross-boss, I'm now leaning towards just making a symlink for Flatcar. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the dev container image. I know they are both built in a ROOT, but I'm not sure whether that location is exactly the same for both images. Probably not. If not, then ESYSROOT will differ from EROOT, and the stripping therefore won't work if only applied when installing the binary packages.

The symlink wouldn't be in the binary packages, so it wouldn't appear in the production image. It would just be added to the dev container image before finalising it.

I think setting these variables and adding a single symlink only to the dev container image is probably still cleaner on balance, but I admit that I have been wavering here. I would like it to be cleaner, not just for Flatcar, but for cross-boss as well, so this has inspired me to look further into alternatives.

The specs-based solution isn't viable without changes to gcc, which might be hard sell to upstream, so I came up with a much simpler gcc patch (about 5 new lines in one place) that doesn't use specs at all. With that, things literally just work with no special flags or other adjustments needed. It's not like Gentoo doesn't patch gcc already. I'm running it past the Gentoo toolchain folks, and I'm currently testing out a full @system build with cross-boss.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the dev container image. I know they are both built in a ROOT, but I'm not sure whether that location is exactly the same for both images. Probably not.

It happens to be the same ROOT for both, and they are built sequentially but we shouldn't depend on that.

If not, then ESYSROOT will differ from EROOT, and the stripping therefore won't work if only applied when installing the binary packages.

I don't follow this conclusion. At a given time ESYSROOT should be equal to EROOT, from man emerge:

SYSROOT = [path]
    (...) The value must either be / or equal to ROOT. When cross-compiling, only the latter is valid.

Unless you mean that the value of ROOT will be different between binpkg generation and installation.

The symlink wouldn't be in the binary packages, so it wouldn't appear in the production image. It would just be added to the dev container image before finalising it.

Oh, sorry I didn't clarify. To me the dev container image is a production artifact that is shipped to users.

The specs-based solution isn't viable without changes to gcc, which might be hard sell to upstream, so I came up with a much simpler gcc patch (about 5 new lines in one place) that doesn't use specs at all.

What does the gcc patch look like?

Copy link
Contributor Author

@chewi chewi Aug 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't follow this conclusion. At a given time ESYSROOT should be equal to EROOT, from man emerge:

I wrote that line. 😀 It actually doesn't work for three reasons. As you say, ROOT can change between building and installation. Also, Portage doesn't set ESYSROOT during the pkg phases, and it doesn't preserve its value in binary packages.

Here's the gcc patch. I'll probably add something to the man page too.

diff -Naur a/gcc/gcc.cc b/gcc/gcc.cc
--- a/gcc/gcc.cc	2024-08-01 23:34:33.525082176 +0100
+++ b/gcc/gcc.cc	2024-08-01 23:43:31.557156041 +0100
@@ -5527,6 +5527,16 @@
 	      "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1);
   free (tooldir_prefix);

+  if (*cross_compile == '1' && !target_system_root_changed)
+    {
+      const char *esysroot = env.get("ESYSROOT");
+      if (esysroot && esysroot[0] != '\0' && strcmp(esysroot, "/") != 0 && (!target_system_root || strcmp(esysroot, target_system_root) != 0))
+	{
+	  target_system_root = esysroot;
+	  target_system_root_changed = 1;
+	}
+    }
+
 #if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS)
   /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix,
      then consider it to relocate with the rest of the GCC installation

My @system build successfully completed. There were no traces of the sysroot flag.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i see, that's basically the sysroot-wrappers approach but baked into gcc

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's got the initial thumbs up from Sam at Gentoo. I'm now doing a two-phase Jenkins build with it to really put it through its paces. If that works, I'll press ahead and open a new PR to supersede this one.

sedargs+=(
-e "s:(, *)?\" *${flag} *\"::g"
-e "s:(, *)?' *${flag} *'::g"
-e "s:,? ?${flag}\b::g"
)
done
sed "${sedargs[@]}" "${FILES[@]}" || die
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

93 changes: 65 additions & 28 deletions sdk_container/src/third_party/portage-stable/eclass/cargo.eclass
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -248,7 +248,7 @@ cargo_crate_uris() {

# @FUNCTION: cargo_gen_config
# @DESCRIPTION:
# Generate the $CARGO_HOME/config necessary to use our local registry and settings.
# Generate the $CARGO_HOME/config.toml necessary to use our local registry and settings.
# Cargo can also be configured through environment variables in addition to the TOML syntax below.
# For each configuration key below of the form foo.bar the environment variable CARGO_FOO_BAR
# can also be used to define the value.
Expand All @@ -259,9 +259,22 @@ 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 strip=none -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" <<- _EOF_ || die "Failed to create cargo config"
cat > "${ECARGO_HOME}/config.toml" <<- _EOF_ || die "Failed to create cargo config"
[source.gentoo]
directory = "${ECARGO_VENDOR}"

Expand All @@ -273,6 +286,7 @@ cargo_gen_config() {
offline = true

[build]
rustflags = "${BUILD_RUSTFLAGS}"
jobs = $(makeopts_jobs)
incremental = false

Expand Down Expand Up @@ -523,36 +537,65 @@ cargo_src_configure() {
[[ ${ECARGO_ARGS[@]} ]] && einfo "Configured with: ${ECARGO_ARGS[@]}"
}

# @FUNCTION: cargo_src_compile
# @FUNCTION: cargo_env
# @USAGE: Command with its arguments
# @DESCRIPTION:
# Build the package using cargo build.
cargo_src_compile() {
debug-print-function ${FUNCNAME} "$@"

# 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.
# 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}"

# Shadow flag variables so that filtering below remains local.
local flag
for flag in $(all-flag-vars); do
local -x "${flag}=${!flag}"
done

# Rust extensions are incompatible with C/C++ LTO compiler see e.g.
# https://bugs.gentoo.org/910220
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
export CARGO_BUILD_TARGET=$(rust_abi)
local -x CARGO_BUILD_TARGET=$(rust_abi)
local TRIPLE=${CARGO_BUILD_TARGET//-/_}
export CARGO_TARGET_"${TRIPLE^^}"_LINKER=$(tc-getCC)

# Set vars for cc-rs crate.
tc-export_build_env
export \
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 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} ${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
# @DESCRIPTION:
# Build the package using cargo build.
cargo_src_compile() {
debug-print-function ${FUNCNAME} "$@"

set -- cargo build $(usex debug "" --release) ${ECARGO_ARGS[@]} "$@"
einfo "${@}"
"${@}" || die "cargo build failed"
cargo_env "${@}" || die "cargo build failed"
}

# @FUNCTION: cargo_src_install
Expand All @@ -564,16 +607,13 @@ 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} \
$(usex debug --debug "") \
${ECARGO_ARGS[@]} "$@"
einfo "${@}"
"${@}" || die "cargo install failed"
cargo_env "${@}" || die "cargo install failed"

rm -f "${ED}/usr/.crates.toml" || die
rm -f "${ED}/usr/.crates2.json" || die
Expand All @@ -585,12 +625,9 @@ 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 "${@}"
"${@}" || die "cargo test failed"
cargo_env "${@}" || die "cargo test failed"
}

fi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1244,7 +1244,9 @@ distutils_pep517_install() {
die "mydistutilsargs are banned in PEP517 mode (use DISTUTILS_ARGS)"
fi

local config_settings=
local cmd=() config_settings=
has cargo ${INHERITED} && cmd+=( cargo_env )

case ${DISTUTILS_USE_PEP517} in
maturin)
# `maturin pep517 build-wheel --help` for options
Expand Down Expand Up @@ -1381,9 +1383,12 @@ distutils_pep517_install() {
;;
esac

# https://pyo3.rs/latest/building-and-distribution.html#cross-compiling
tc-is-cross-compiler && local -x PYO3_CROSS_LIB_DIR=${SYSROOT}/$(python_get_stdlib)

local build_backend=$(_distutils-r1_get_backend)
einfo " Building the wheel for ${PWD#${WORKDIR}/} via ${build_backend}"
local cmd=(
cmd+=(
"${EPYTHON}" -m gpep517 build-wheel
--prefix="${EPREFIX}/usr"
--backend "${build_backend}"
Expand Down Expand Up @@ -1782,16 +1787,6 @@ distutils-r1_run_phase() {
# bug fixes from Cython (this works only when setup.py is using
# cythonize() but it's better than nothing)
local -x CYTHON_FORCE_REGEN=1

# Rust extensions are incompatible with C/C++ LTO compiler
# see e.g. https://bugs.gentoo.org/910220
if has cargo ${INHERITED}; then
local x
for x in $(all-flag-vars); do
local -x "${x}=${!x}"
done
filter-lto
fi
fi

# silence warnings when pydevd is loaded on Python 3.11+
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,17 @@ _python_export() {
export PYTHON=${BROOT-${EPREFIX}}/usr/bin/${impl}
debug-print "${FUNCNAME}: PYTHON = ${PYTHON}"
;;
PYTHON_STDLIB)
[[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
PYTHON_STDLIB=$(
"${PYTHON}" - "${EPREFIX}/usr" <<-EOF || die
import sys, sysconfig
print(sysconfig.get_path("stdlib", vars={"installed_base": sys.argv[1]}))
EOF
)
export PYTHON_STDLIB
debug-print "${FUNCNAME}: PYTHON_STDLIB = ${PYTHON_STDLIB}"
;;
PYTHON_SITEDIR)
[[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
PYTHON_SITEDIR=$(
Expand Down Expand Up @@ -466,6 +477,18 @@ _python_export() {
done
}

# @FUNCTION: python_get_stdlib
# @USAGE: [<impl>]
# @DESCRIPTION:
# Obtain and print the 'stdlib' path for the given implementation. If no
# implementation is provided, ${EPYTHON} will be used.
python_get_stdlib() {
debug-print-function ${FUNCNAME} "${@}"

_python_export "${@}" PYTHON_STDLIB
echo "${PYTHON_STDLIB}"
}

# @FUNCTION: python_get_sitedir
# @USAGE: [<impl>]
# @DESCRIPTION:
Expand Down
5 changes: 5 additions & 0 deletions setup_board
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ PORT_LOGDIR="${BOARD_ROOT}/var/log/portage"
PORTAGE_TMPDIR="${BOARD_ROOT}/var/tmp"
PORTAGE_BINHOST="${BOARD_BINHOST}"

# Tell the toolchain to use our sysroot.
CPP="\${CHOST}-gcc -E --sysroot=\${SYSROOT}"
CC="\${CHOST}-gcc --sysroot=\${SYSROOT}"
CXX="\${CHOST}-g++ --sysroot=\${SYSROOT}"

# Generally there isn't any need to add packages to @world by default.
# You can use --select to override this.
EMERGE_DEFAULT_OPTS="--oneshot --verbose"
Expand Down
1 change: 0 additions & 1 deletion update_chroot
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ info "Updating basic system packages"
sudo -E ${EMERGE_CMD} "${EMERGE_FLAGS[@]}" \
sys-apps/portage \
sys-devel/crossdev \
sys-devel/sysroot-wrappers \
sys-libs/nss-usrfiles \
"${TOOLCHAIN_PKGS[@]}"

Expand Down
Loading