On Sun, 2025-09-07 at 14:43 -0400, Matt Whitlock wrote: > There has been a substantive discussion unfolding at > https://github.com/gentoo/gentoo/pull/43693#pullrequestreview-3194144355 that > has evolved into a more general discussion that Eli suggested should be moved > to this mailing list. Allow me to summarize the issues and findings thus > far... > > The current state of affairs is as follows: > > * multilib_toolchain_setup() in multilib.eclass, when switching to a > non-default ABI, sets the CHOST toolchain variables to the values returned by > the corresponding tc-get_*() functions in toolchain-funcs.eclass, except that > it appends $(get_abi_*FLAGS) where appropriate to switch various tools to the > non-default ABI. Then it overrides CHOST to the value of CHOST_${ABI}. For > example, on an amd64 system, when switching to the x86_32 ABI, CHOST becomes > "i686-pc-linux-gnu". Additionally, in the non-cross-compiling case, > multilib_toolchain_setup() overrides CBUILD to that same value (so that > ${CHOST} == ${CBUILD} is still true).
Agreed.
> * setup_meson_src_configure() in meson.eclass generates a Meson "native file"
> that specifies toolchain tools and flags for the CBUILD machine. In the case
> of cross-compiling (i.e., ${CHOST} != ${CBUILD}), it also generates a Meson
> "cross file" that specifies toolchain tools and flags for the CHOST machine.
Agreed.
> Although the above may seem reasonable at first glance, there are some issues:
>
> * In the case that a build-time helper executable links with a library that
> is listed in BDEPEND, the link will fail in a non-default ABI phase if the
> library has not been installed for the non-default ABI. There is no way to
> require libraries in BDEPEND to be installed for non-default ABIs, as using
> ${MULTILIB_USEDEP} in BDEPEND would break cross-compiles since the ABI flags
> listed in MULTILIB_USEDEP are for the CHOST machine, not the CBUILD machine.
> The reasonable answer is that build-time helper executables should only ever
> be built for the default ABI.
I didn't see what you meant earlier, but I do now. I must admit that this is
not something I had considered before. I agree that is the right answer.
> --- a/eclass/multilib.eclass
> +++ b/eclass/multilib.eclass
> @@ -526,8 +526,12 @@ multilib_toolchain_setup() {
> export _DEFAULT_ABI_SAVED="true"
>
> # Set CBUILD only if not cross-compiling.
> + #
> + # It must use the default ABI since build-time helper
> + # executables might link with libraries that are installed
> + # only for the default ABI.
> if [[ ${CBUILD} == "${CHOST}" ]]; then
> - export CBUILD=$(get_abi_CHOST $1)
> + export CBUILD=$(get_abi_CHOST ${DEFAULT_ABI})
> fi
>
> * The above won't work out of the box, as now tc-is-cross-compiler() will
> return true in non-default ABI phases (since ${CHOST} will no longer match
> ${CBUILD}), and thus the tc-getBUILD_*() functions will no longer fall back
> on the CHOST toolchain variables in the case that the CBUILD toolchain
> variables are unset. We wouldn't want that anyway, as the CHOST toolchain is
> being altered with a non-default ABI flag, but we need the CBUILD toolchain
> to use the default ABI. So, let's have multilib_toolchain_setup() set up the
> CBUILD toolchain variables as well:
>
> --- a/eclass/multilib.eclass
> +++ b/eclass/multilib.eclass
> @@ -487,6 +487,17 @@ multilib_toolchain_setup() {
> local save_restore_variables=(
> CBUILD
> CHOST
> + BUILD_AR
> + BUILD_CC
> + BUILD_CXX
> + BUILD_LD
> + BUILD_NM
> + BUILD_OBJCOPY
> + BUILD_PKG_CONFIG
> + BUILD_RANLIB
> + BUILD_READELF
> + BUILD_STRINGS
> + BUILD_STRIP
> AR
> CC
> CXX
> @@ -536,6 +551,20 @@ multilib_toolchain_setup() {
> # Make sure ${save_restore_variables[@]} list matches below.
> export CHOST=$(get_abi_CHOST ${DEFAULT_ABI})
>
> + # Derive the build-machine toolchain variables before we
> + # override the host-machine toolchain variables.
> + export BUILD_AR="$(tc-getBUILD_AR)" # Avoid 'ar', use
> "${CBUILD}-ar"
> + export BUILD_CC="$(tc-getBUILD_CC)" # Default ABI
> + export BUILD_CXX="$(tc-getBUILD_CXX)" # Default ABI
> + export BUILD_LD="$(tc-getBUILD_LD)" # Default ABI
> + export BUILD_NM="$(tc-getBUILD_NM)" # Avoid 'nm', use
> "${CBUILD}-nm"
> + export BUILD_OBJCOPY="$(tc-getBUILD_OBJCOPY)" # Avoid
> 'objcopy', use "${CBUILD}-objcopy"
> + export BUILD_PKG_CONFIG="$(tc-getBUILD_PKG_CONFIG)"
> + export BUILD_RANLIB="$(tc-getBUILD_RANLIB)" # Avoid 'ranlib',
> use "${CBUILD}-ranlib"
> + export BUILD_READELF="$(tc-getBUILD_READELF)" # Avoid
> 'readelf', use "${CBUILD}-readelf"
> + export BUILD_STRINGS="$(tc-getBUILD_STRINGS)" # Avoid
> 'strings', use "${CBUILD}-strings"
> + export BUILD_STRIP="$(tc-getBUILD_STRIP)" # Avoid 'strip', use
> "${CBUILD}-strip"
> +
> export AR="$(tc-getAR)" # Avoid 'ar', use '${CHOST}-ar'
> export CC="$(tc-getCC) $(get_abi_CFLAGS)"
> export CXX="$(tc-getCXX) $(get_abi_CFLAGS)"
>
> * This works great for Autotools and CMake build systems, but it may subtly
> break packages using meson.eclass because now all non-default-ABI builds are
> configured in Meson's cross mode with "needs_exe_wrapper = true" specified in
> the cross file. Normally this is reasonable, as in the true cross-compiling
> case we cannot expect host-machine executables to run on the build machine
> without some help, but it is overly pessimistic in the non-cross,
> non-default-ABI case. We would prefer not to disable build-time feature tests
> that rely on being able to execute just-built binaries on the build machine.
> One solution would be to set "needs_exe_wrapper = false" in the case that
> ${CBUILD} == ${CHOST_${DEFAULT_ABI}}.
>
> --- a/eclass/meson.eclass
> +++ b/eclass/meson.eclass
> @@ -147,6 +147,7 @@
> _meson_create_cross_file() {
> local system cpu_family cpu
> _meson_get_machine_info "${CHOST}"
> + local -n CHOST_default="CHOST_${DEFAULT_ABI}"
>
> local fn=${T}/meson.${CHOST}.${ABI}.ini
>
> @@ -181,7 +182,7 @@ _meson_create_cross_file() {
> objcpp_link_args = $(_meson_env_array "${OBJCXXFLAGS} ${LDFLAGS}")
>
> [properties]
> - needs_exe_wrapper = true
> + needs_exe_wrapper = $([[ "${CBUILD:-${CHOST}}" != "${CHOST_default}" ]]
> && echo true || echo false)
> sys_root = '${SYSROOT}'
> pkg_config_libdir =
> '${PKG_CONFIG_LIBDIR:-${EPREFIX}/usr/$(get_libdir)/pkgconfig}'
>
> * There is one other loose end to tie up in meson.eclass: the native file is
> named "meson.${CBUILD}.${ABI}.ini", but this actually makes no sense, as
> ${ABI} belongs to the CHOST machine, not the CBUILD machine. It would make
> the most sense simply to omit the ABI from the native file name since there
> will only ever be one native ABI.
>
> @@ -205,7 +206,7 @@ _meson_create_native_file() {
> local system cpu_family cpu
> _meson_get_machine_info "${CBUILD}"
>
> - local fn=${T}/meson.${CBUILD}.${ABI}.ini
> + local fn=${T}/meson.${CBUILD}.ini
>
> cat > "${fn}" <<-EOF
> [binaries]
>
> A Pull Request containing all of these proposed changes is at:
> https://github.com/gentoo/gentoo/pull/43693
My head's a little fuzzy right now, but I think this makes sense. My only
concern is the precise CHOST can vary in the field, so the profile default
might not match. A better way would be for multilib.eclass to preserve the
original CHOST value in another variable before changing it. BUILD_CHOST? XD
signature.asc
Description: This is a digitally signed message part
