FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(extension_testcapi): Locate python3.lib on single-config generators by hjmjohnson · Pull Request #453 · python-cmake-buildsystem/python-cmake-buildsystem · GitHub

fix(extension_testcapi): Locate python3.lib on single-config generators - #453

Open
hjmjohnson wants to merge 1 commit into
python-cmake-buildsystem:masterfrom
hjmjohnson:fix-testcapi-python3lib-single-config
Open

fix(extension_testcapi): Locate python3.lib on single-config generators#453
hjmjohnson wants to merge 1 commit into
python-cmake-buildsystem:masterfrom
hjmjohnson:fix-testcapi-python3lib-single-config

Conversation

Copy link
Copy Markdown

Fixes #452.

Problem

Linking _testcapi fails on Windows with single-config generators (Ninja, NMake Makefiles):

LINK : fatal error LNK1104: cannot open file 'python3.lib'

Multi-config generators (Visual Studio) are unaffected.

_testcapi has translation units compiled with Py_LIMITED_API, so PC/pyconfig.h emits pragma comment(lib,"python3.lib") and the stable-ABI import library must be on the linker search path. That path was reconstructed by hand:

set(libpython_output_dir "${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. libpython3-shared sets LIBRARY_OUTPUT_DIRECTORY and RUNTIME_OUTPUT_DIRECTORY but no ARCHIVE_OUTPUT_DIRECTORY, so under Ninja python3.lib is written straight to CMakeBuild/libpython/ — one level above where the $<CONFIG> form looked.

Change

-    set(libpython_output_dir "${PROJECT_BINARY_DIR}/CMakeBuild/libpython/$<CONFIG>")
-    target_link_directories(extension_testcapi PRIVATE ${libpython_output_dir})
+    target_link_directories(extension_testcapi PRIVATE $<TARGET_LINKER_FILE_DIR:libpython3-shared>)

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-shared is already a hard dependency of extension_testcapi on 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.pyd fails with LNK1104, aborting the build at ~721/737.
After: _testcapi.pyd links 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).

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.

Copy link
Copy Markdown
Author

Verified on both generator classes. Branch under test: e815ed7989aa9b544d153d4c80199ec0b121fe82.

Environment: Windows 11, MSVC 19.38.33130 (VS 2022 17.8), CMake 4.4.2, Python 3.12.10, Release. Both builds consume this branch through 3D Slicer's SuperBuild via -DSlicer_python_GIT_REPOSITORY=... -DSlicer_python_GIT_TAG=fix-testcapi-python3lib-single-config.

Single-config (Ninja) — the failure this fixes

Before, at [721/737]:

FAILED: Lib/lib-dynload/_testcapi.pyd libs/_testcapi.lib
LINK : fatal error LNK1104: cannot open file 'python3.lib'

After:

288256  python-build/Lib/lib-dynload/_testcapi.pyd
  1766  python-build/libs/_testcapi.lib

Multi-config (Visual Studio 17 2022, x64) — the regression check

CMAKE_CONFIGURATION_TYPES=Debug;Release;MinSizeRel;RelWithDebInfo

extension_testcapi.vcxproj -> C:\...\python-build\Lib\lib-dynload\Release\_testcapi.pyd
-- Installing: C:/.../python-install/libs/_testcapi.lib
-- Installing: C:/.../python-install/Lib/lib-dynload/_testcapi.pyd

287744  python-build/Lib/lib-dynload/Release/_testcapi.pyd
  1766  python-build/libs/Release/_testcapi.lib

No link errors in either build.

Why the change is the right shape

The two builds put the import library in different places, and $<TARGET_LINKER_FILE_DIR:libpython3-shared> follows it to both:

generator python3.lib actually written to
Ninja CMakeBuild/libpython/python3.lib
Visual Studio CMakeBuild/libpython/Release/python3.lib

That is the whole defect in one table: the hardcoded .../CMakeBuild/libpython/$<CONFIG> matched the second row only, because $<CONFIG> expands under every generator while only multi-config generators add the configuration directory to a target's archive output. Asking the target removes the assumption instead of re-encoding it.

Happy to add a CI job covering a single-config Windows generator if that would be useful — the gap is that _testcapi is only ever linked under Visual Studio today.

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

_testcapi fails to link on single-config generators: cannot open file 'python3.lib' (LNK1104)

1 participant


Back | FazBrowse Home | New Git URL