Repository navigation
fix(extension_testcapi): Locate python3.lib on single-config generators - #453
hjmjohnson wants to merge 1 commit into
Conversation
Linking _testcapi failed on Windows with the Ninja and NMake generators:
LINK : fatal error LNK1104: cannot open file 'python3.lib'
_testcapi contains translation units that define Py_LIMITED_API
(vectorcall_limited.c, heaptype_relative.c). PC/pyconfig.h then emits
`pragma comment(lib,"python3.lib")`, so the stable-ABI import library
must be on the linker's search path.
The search path was built by hand as
${PROJECT_BINARY_DIR}/CMakeBuild/libpython/$<CONFIG>
$<CONFIG> expands for every generator, but only multi-config generators
append the configuration to a target's archive output directory. Since
libpython3-shared sets LIBRARY_OUTPUT_DIRECTORY and
RUNTIME_OUTPUT_DIRECTORY but no ARCHIVE_OUTPUT_DIRECTORY, on a
single-config generator python3.lib lands directly in the libpython
binary directory -- one level above where the $<CONFIG> form looked.
Visual Studio agreed with the hardcoded path, which is why this went
unnoticed.
Use $<TARGET_LINKER_FILE_DIR:libpython3-shared> so the directory comes
from the target itself and stays correct for both generator classes.
The target is already a hard dependency of extension_testcapi on the
next line, so it is guaranteed to exist here.
|
Verified on both generator classes. Branch under test: Environment: Windows 11, MSVC 19.38.33130 (VS 2022 17.8), CMake 4.4.2, Python 3.12.10, Single-config (Ninja) — the failure this fixesBefore, at After: Multi-config (Visual Studio 17 2022, x64) — the regression check
No link errors in either build. Why the change is the right shapeThe two builds put the import library in different places, and
That is the whole defect in one table: the hardcoded Happy to add a CI job covering a single-config Windows generator if that would be useful — the gap is that |
Fixes #452.
Problem
Linking
_testcapifails on Windows with single-config generators (Ninja, NMake Makefiles):Multi-config generators (Visual Studio) are unaffected.
_testcapihas translation units compiled withPy_LIMITED_API, soPC/pyconfig.hemitspragma comment(lib,"python3.lib")and the stable-ABI import library must be on the linker search path. That path was reconstructed by hand:$<CONFIG>expands for every generator, but only multi-config generators append the configuration to a target's archive output directory.libpython3-sharedsetsLIBRARY_OUTPUT_DIRECTORYandRUNTIME_OUTPUT_DIRECTORYbut noARCHIVE_OUTPUT_DIRECTORY, so under Ninjapython3.libis written straight toCMakeBuild/libpython/— one level above where the$<CONFIG>form looked.Change
The directory now comes from the target itself, so it is correct for both generator classes and cannot drift if the output location changes later.
libpython3-sharedis already a hard dependency ofextension_testcapion the next line, so it is guaranteed to exist here.No behaviour change for multi-config generators:
$<TARGET_LINKER_FILE_DIR:libpython3-shared>resolves to the same per-configuration directory the hardcoded path produced.Verification
Windows 11, MSVC 19.38 (VS 2022 17.8), CMake 4.4.2, Ninja, Python 3.12.10,
CMAKE_BUILD_TYPE=Release.Before:
_testcapi.pydfails withLNK1104, aborting the build at ~721/737.After:
_testcapi.pydlinks and installs (Lib/lib-dynload/_testcapi.pyd,libs/_testcapi.lib), and the build proceeds.Found while building 3D Slicer's SuperBuild, which vendors this project and must use Ninja because it is the only generator honouring
CMAKE_<LANG>_COMPILER_LAUNCHER(ccache).