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

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to