Description
Noticed this while building greenlet, which uses c++.
Starting with 52cd70b
The LDCXXSHARED variable gets read out of the sysconfig vars from the python build:
br-user@02db68569e9b:/tmp/tmp.SWYRHhln2t/buildroot$ /tmp/tmp.SWYRHhln2t/buildroot/output/host/bin/python3 -m sysconfig | grep LDC
LDCXXSHARED = "/tmp/tmp.SWYRHhln2t/buildroot/output/host/bin/ccache /usr/bin/g++ -shared -L/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib -Wl,-rpath,/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib -Wl,--enable-new-dtags"
This feeds the value of linker_so_cxx
:
compiler.set_executables(
preprocessor=cpp,
compiler=cc_cmd,
compiler_so=cc_cmd + ' ' + ccshared,
compiler_cxx=cxx_cmd,
compiler_so_cxx=cxx_cmd + ' ' + ccshared,
linker_so=ldshared,
linker_so_cxx=ldcxxshared,
linker_exe=cc,
linker_exe_cxx=cxx,
archiver=archiver,
)
When linking is performed:
distutils/distutils/compilers/C/unix.py
Lines 289 to 295 in 24bd317
linker=['/tmp/tmp.SWYRHhln2t/buildroot/output/host/bin/ccache', '/usr/bin/g++', '-shared', '-L/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib', '-Wl,-rpath,/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib', '-Wl,--enable-new-dtags', '-L/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib', '-Wl,-rpath,/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib', '-O2', '-I/tmp/tmp.SWYRHhln2t/buildroot/output/host/include', '-I/tmp/tmp.SWYRHhln2t/buildroot/output/host/include']
However, this ultimately fails:
/tmp/tmp.SWYRHhln2t/buildroot/output/host/bin/ccache /usr/bin/g++ -O2 -I/tmp/tmp.SWYRHhln2t/buildroot/output/host/include -I/tmp/tmp.SWYRHhln2t/buildroot/output/host/include /usr/bin/g++ -shared -L/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib -Wl,-rpath,/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib -Wl,--enable-new-dtags -L/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib -Wl,-rpath,/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib -O2 -I/tmp/tmp.SWYRHhln2t/buildroot/output/host/include -I/tmp/tmp.SWYRHhln2t/buildroot/output/host/include -g build/temp.linux-x86_64-cpython-313/src/greenlet/greenlet.o -L/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib -o build/lib.linux-x86_64-cpython-313/greenlet/_greenlet.cpython-313-x86_64-linux-gnu.so
/usr/bin/ld: cannot use executable file '/usr/bin/g++' as input to a link
collect2: error: ld returned 1 exit status
error: command '/tmp/tmp.SWYRHhln2t/buildroot/output/host/bin/ccache' failed with exit code 1
linker=['/tmp/tmp.SWYRHhln2t/buildroot/output/host/bin/ccache', '/usr/bin/g++', '-O2', '-I/tmp/tmp.SWYRHhln2t/buildroot/output/host/include', '-I/tmp/tmp.SWYRHhln2t/buildroot/output/host/include', '/usr/bin/g++', '-shared', '-L/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib', '-Wl,-rpath,/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib', '-Wl,--enable-new-dtags', '-L/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib', '-Wl,-rpath,/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib', '-O2', '-I/tmp/tmp.SWYRHhln2t/buildroot/output/host/include', '-I/tmp/tmp.SWYRHhln2t/buildroot/output/host/include']
ld_args=['-g', 'build/temp.linux-x86_64-cpython-313/src/greenlet/greenlet.o', '-L/tmp/tmp.SWYRHhln2t/buildroot/output/host/lib', '-o', 'build/lib.linux-x86_64-cpython-313/greenlet/_greenlet.cpython-313-x86_64-linux-gnu.so']
The linking command has a spurious /usr/bin/g++
in the invocation, causing problems.
This looks to be because LDCXXSHARED
is always generated using CXX
in the CPython build:
https://github.com/python/cpython/blob/e42bda9441119c7952ada23e88e6f4ab79df86c2/configure.ac#L3469
However, when parsing this out in unix.py
:
distutils/distutils/compilers/C/unix.py
Lines 301 to 304 in 24bd317
self.linker_exe
is used instead of self.linker_exe_cxx
. self.linker_exe
is driven by CC
where as self.linker_exe_cxx
is driven by CXX
.
br-user@02db68569e9b:/tmp/tmp.SWYRHhln2t/buildroot$ /tmp/tmp.SWYRHhln2t/buildroot/output/host/bin/python3 -m sysconfig | egrep "(CXX|CC) ="
CC = "/tmp/tmp.SWYRHhln2t/buildroot/output/host/bin/ccache /usr/bin/gcc"
CXX = "/tmp/tmp.SWYRHhln2t/buildroot/output/host/bin/ccache /usr/bin/g++"
LINKCC = "/tmp/tmp.SWYRHhln2t/buildroot/output/host/bin/ccache /usr/bin/gcc"
Since the LDCXXSHARED value is prefixed with CXX and not CC, only the first item from the list is dropped via _linker_params
, which is the path to ccache, and the spurious /usr/bin/g++
ref is left around.
So, I think maybe the linker_exe_cxx
attribute should be used instead so the proper prefix is parsed out of the flag:
if target_lang == "c++" and self.compiler_cxx:
env, linker_ne = _split_env(linker)
aix, linker_na = _split_aix(linker_ne)
_, compiler_cxx_ne = _split_env(self.compiler_cxx)
_, linker_exe_ne = _split_env(self.linker_exe_cxx)
There may also be issues with c++ executables:
distutils/distutils/compilers/C/unix.py
Lines 290 to 291 in 24bd317
There is no branch to use self.linker_exe_cxx
when target_lang == "c++"