Skip to content

Commit d5a595c

Browse files
fix: Add libs/python3.lib to libpython target for SABI builds on Windows (#1820)
When targeting the Python Stable ABI on Windows (by setting the Py_LIMITED_API macro to a Python minimum version hex), the unversioned python3.lib needs to be linked instead of the versioned one (e.g. python38.lib for Python 3.8). Python's own config sets the library to link by default in a header called pyconfig.h (https://github.com/python/cpython/blob/9cc9e277254023c0ca08e1a9e379fd89475ca9c2/PC/pyconfig.h#L270), which prompts the linker to search for python3.lib if a stable ABI extension is built using `@rules_python` toolchains. Since this library is not exported on Windows in the `python_repository()` rule, building Python C++ extensions with rules_python toolchains fails in the linking step, because the library is never copied. Consequently, it is added now to allow Python SABI extensions to be built (and linked) on Windows with `@rules_python`. Since Python takes responsibility for linking the correct lib on Windows, and never both at the same time, no other changes are made. --------- Co-authored-by: Richard Levasseur <[email protected]> Co-authored-by: Richard Levasseur <[email protected]>
1 parent 25aeb40 commit d5a595c

File tree

4 files changed

+40
-4
lines changed

4 files changed

+40
-4
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ Other changes:
9595
([2169](https://github.com/bazelbuild/rules_python/issues/2169)).
9696
* (workspace) Corrected protobuf's name to com_google_protobuf, the name is
9797
hardcoded in Bazel, WORKSPACE mode.
98+
* (repositories): Add libs/python3.lib and pythonXY.dll to the `libpython` target
99+
defined by a repository template. This enables stable ABI builds of Python extensions
100+
on Windows (by defining Py_LIMITED_API).
98101

99102
{#v0-0-0-added}
100103
### Added

python/private/hermetic_runtime_repo_setup.bzl

+18-3
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ def define_hermetic_runtime_toolchain_impl(
8989
}),
9090
system_provided = True,
9191
)
92+
cc_import(
93+
name = "abi3_interface",
94+
interface_library = select({
95+
_IS_FREETHREADED: "libs/python3t.lib",
96+
"//conditions:default": "libs/python3.lib",
97+
}),
98+
system_provided = True,
99+
)
92100

93101
native.filegroup(
94102
name = "includes",
@@ -97,7 +105,7 @@ def define_hermetic_runtime_toolchain_impl(
97105
cc_library(
98106
name = "python_headers",
99107
deps = select({
100-
"@bazel_tools//src/conditions:windows": [":interface"],
108+
"@bazel_tools//src/conditions:windows": [":interface", ":abi3_interface"],
101109
"//conditions:default": None,
102110
}),
103111
hdrs = [":includes"],
@@ -156,15 +164,22 @@ def define_hermetic_runtime_toolchain_impl(
156164
"lib/libpython{major}.{minor}t.dylib".format(**version_dict),
157165
],
158166
":is_freethreaded_windows": [
159-
"python3.dll",
167+
"python3t.dll",
168+
"python{major}{minor}t.dll".format(**version_dict),
160169
"libs/python{major}{minor}t.lib".format(**version_dict),
170+
"libs/python3t.lib",
161171
],
162172
"@platforms//os:linux": [
163173
"lib/libpython{major}.{minor}.so".format(**version_dict),
164174
"lib/libpython{major}.{minor}.so.1.0".format(**version_dict),
165175
],
166176
"@platforms//os:macos": ["lib/libpython{major}.{minor}.dylib".format(**version_dict)],
167-
"@platforms//os:windows": ["python3.dll", "libs/python{major}{minor}.lib".format(**version_dict)],
177+
"@platforms//os:windows": [
178+
"python3.dll",
179+
"python{major}{minor}.dll".format(**version_dict),
180+
"libs/python{major}{minor}.lib".format(**version_dict),
181+
"libs/python3.lib",
182+
],
168183
}),
169184
)
170185

tests/cc/current_py_cc_libs/BUILD.bazel

+18
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,21 @@ cc_test(
3333
"@rules_python//python/cc:current_py_cc_libs",
3434
],
3535
)
36+
37+
# This is technically a headers test, but since the pyconfig.h header
38+
# designates the appropriate lib to link on Win+MSVC, this test verifies that
39+
# the expected Windows libraries are all present in the expected location.
40+
# Since we define the Py_LIMITED_API macro, we expect the linker to go search
41+
# for libs/python3.lib.
42+
# buildifier: disable=native-cc
43+
cc_test(
44+
name = "python_libs_linking_windows_test",
45+
srcs = ["python_libs_linking_test.cc"],
46+
defines = ["Py_LIMITED_API=0x030A0000"],
47+
env = {"HELLO": "world"},
48+
target_compatible_with = ["@platforms//os:windows"],
49+
deps = [
50+
"@rules_python//python/cc:current_py_cc_headers",
51+
"@rules_python//python/cc:current_py_cc_libs",
52+
],
53+
)

tests/cc/current_py_cc_libs/python_libs_linking_test.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ int main(int argc, char** argv) {
1212
// To make it actually run, more custom initialization is necessary.
1313
// See https://docs.python.org/3/c-api/intro.html#embedding-python
1414
Py_Initialize();
15-
PyRun_SimpleString("print('Hello, world')\n");
15+
Py_BytesMain(argc, argv);
1616
Py_Finalize();
1717
return 0;
1818
}

0 commit comments

Comments
 (0)