From f50ab1356c17b32dd1fc39cf53f5e91af5504dda Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Mon, 3 Aug 2026 04:08:13 +0000 Subject: [PATCH 1/3] Simplify _current_py_cc_libs_impl by removing static and DLL library filtering Commit 0d6016ffe5307e2e7c30a90319f14f8efa801d2b accidentally added complex filtering logic for static libraries, DLLs, and runfiles to _current_py_cc_libs_impl. Simplify the rule implementation to return py_cc_toolchain.libs.providers_map.values() directly. --- python/private/current_py_cc_libs.bzl | 34 +-------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/python/private/current_py_cc_libs.bzl b/python/private/current_py_cc_libs.bzl index 58ab4b1bd8..ca68346bcb 100644 --- a/python/private/current_py_cc_libs.bzl +++ b/python/private/current_py_cc_libs.bzl @@ -18,39 +18,7 @@ load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") def _current_py_cc_libs_impl(ctx): py_cc_toolchain = ctx.toolchains["//python/cc:toolchain_type"].py_cc_toolchain - providers = [p for p in py_cc_toolchain.libs.providers_map.values() if not hasattr(p, "data_runfiles")] - default_runfiles = None - data_runfiles = None - files = [] - for p in py_cc_toolchain.libs.providers_map.values(): - if hasattr(p, "data_runfiles"): - default_runfiles = p.default_runfiles - data_runfiles = p.data_runfiles - - cc_infos = [p for p in py_cc_toolchain.libs.providers_map.values() if hasattr(p, "linking_context")] - if cc_infos: - cc_info = cc_infos[0] - for input in cc_info.linking_context.linker_inputs.to_list(): - for lib in input.libraries: - if lib.static_library: - files.append(lib.static_library) - if lib.interface_library: - files.append(lib.interface_library) - elif lib.dynamic_library: - files.append(lib.dynamic_library) - - # On Windows MSVC, user_link_flags passes $(locations @rules_python//python/cc:current_py_cc_libs) - # to link.exe. MSVC link.exe accepts import libraries (.lib) but fails with - # LNK1107 if passed raw DLL binaries (.dll). We filter out .dll files so - # DefaultInfo.files only contains linkable library files (.lib / .a). - link_files = [f for f in files if not f.path.endswith(".dll")] - - providers.append(DefaultInfo( - files = depset(link_files), - default_runfiles = default_runfiles, - data_runfiles = data_runfiles, - )) - return providers + return py_cc_toolchain.libs.providers_map.values() current_py_cc_libs = rule( implementation = _current_py_cc_libs_impl, From 259ee7f7bb43ef5078d72a203412046c6d84713a Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Mon, 3 Aug 2026 05:44:59 +0000 Subject: [PATCH 2/3] fix(py_extension): extract Windows .lib files via py_extension_libs toolchain rule Windows toolchain libraries use system_provided=True in cc_import, which leaves DefaultInfo empty and causes $(locations //python/cc:current_py_cc_libs) to expand to no files. Introduce a private py_extension_libs rule in py_extension_rule.bzl that uses toolchain resolution to extract linkable .lib files from CcInfo.linking_context and returns them in DefaultInfo for MSVC link.exe. --- python/private/cc/py_extension_macro.bzl | 22 ++++++++++++++-------- python/private/cc/py_extension_rule.bzl | 24 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/python/private/cc/py_extension_macro.bzl b/python/private/cc/py_extension_macro.bzl index 7845a09ea2..a7ed42eaba 100644 --- a/python/private/cc/py_extension_macro.bzl +++ b/python/private/cc/py_extension_macro.bzl @@ -8,7 +8,7 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library") load("@rules_cc//cc:cc_shared_library.bzl", "cc_shared_library") load("//python/private:common_labels.bzl", "labels") load("//python/private:util.bzl", "add_tag", "copy_propagating_kwargs") -load(":py_extension_rule.bzl", "py_extension_wrapper") +load(":py_extension_rule.bzl", "py_extension_libs", "py_extension_wrapper") _EMPTY_CANONICAL_TARGET = str(Label("//python/private/cc:empty")) @@ -18,9 +18,6 @@ _PY_CC_HEADERS_ALIAS_CANONICAL_TARGET = str(Label(_PY_CC_HEADERS_ALIAS_BASE_TARG _PY_CC_LIBS_ALIAS_BASE_TARGET = "//python/private/cc:current_py_cc_libs_private_alias" _PY_CC_LIBS_ALIAS_CANONICAL_TARGET = str(Label(_PY_CC_LIBS_ALIAS_BASE_TARGET)) -_PY_CC_LIBS_ACTUAL_BASE_TARGET = "//python/cc:current_py_cc_libs" -_PY_CC_LIBS_ACTUAL_CANONICAL_TARGET = str(Label(_PY_CC_LIBS_ACTUAL_BASE_TARGET)) - def py_extension( name, srcs = None, @@ -148,22 +145,31 @@ def py_extension( "//conditions:default": [], }) + win_libs_name = "_" + name + "_win_libs" + + # On Windows, create a private target using toolchain resolution to extract .lib files + # from CcInfo in py_cc_toolchain because system_provided=True in cc_import leaves DefaultInfo empty. + py_extension_libs( + name = win_libs_name, + visibility = ["//visibility:private"], + ) + # Windows-specific CPython linking requirements: # 1. Windows requires .lib files when linking, so they must be added to deps. # 2. CPython import libraries (python3xx.lib) are declared with system_provided = True # in cc_import, suppressing automatic propagation of the .lib file path to link.exe. - # We explicitly pass $(locations ...) to provide the path of the CPython import library to MSVC link.exe. - # 3. We pass current_py_cc_libs as an additional linker input to ensure the .lib file is available to the link action. + # We explicitly pass $(locations ...) from win_libs_name to provide the path to MSVC link.exe. + # 3. We pass win_libs_name as an additional linker input to ensure the .lib file is available to the link action. deps = deps + select({ labels.PLATFORMS_OS_WINDOWS: [_PY_CC_LIBS_ALIAS_CANONICAL_TARGET], "//conditions:default": [], }) user_link_flags = user_link_flags + select({ - labels.PLATFORMS_OS_WINDOWS: ["$(locations " + _PY_CC_LIBS_ACTUAL_BASE_TARGET + ")"], + labels.PLATFORMS_OS_WINDOWS: ["$(locations :" + win_libs_name + ")"], "//conditions:default": [], }) additional_linker_inputs = additional_linker_inputs + select({ - labels.PLATFORMS_OS_WINDOWS: [_PY_CC_LIBS_ACTUAL_CANONICAL_TARGET], + labels.PLATFORMS_OS_WINDOWS: [":" + win_libs_name], "//conditions:default": [], }) diff --git a/python/private/cc/py_extension_rule.bzl b/python/private/cc/py_extension_rule.bzl index 1c5ee11a06..2b3a8284b7 100644 --- a/python/private/cc/py_extension_rule.bzl +++ b/python/private/cc/py_extension_rule.bzl @@ -133,3 +133,27 @@ def _get_platform(ctx): ), ) return py_cc_toolchain.platform_tag + +def _py_extension_libs_impl(ctx): + py_toolchain = ctx.toolchains[PY_CC_TOOLCHAIN_TYPE] + py_cc_toolchain = py_toolchain.py_cc_toolchain + cc_info = py_cc_toolchain.libs.providers_map["CcInfo"] + files = [] + for input in cc_info.linking_context.linker_inputs.to_list(): + for lib in input.libraries: + if lib.interface_library: + files.append(lib.interface_library) + elif lib.static_library: + files.append(lib.static_library) + elif lib.dynamic_library: + files.append(lib.dynamic_library) + link_files = [f for f in files if not f.path.endswith(".dll")] + return [DefaultInfo(files = depset(link_files))] + +py_extension_libs = rule( + implementation = _py_extension_libs_impl, + toolchains = [PY_CC_TOOLCHAIN_TYPE], + doc = """\ +Private internal helper rule for extracting Windows C/C++ library files from toolchain. +""", +) From efe13fe97312b9bf485eb8dd7efa6060945b5036 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Mon, 3 Aug 2026 05:47:09 +0000 Subject: [PATCH 3/3] fix(py_extension): add manual tag to win_libs_name py_extension_libs target Add tags = ["manual"] to the internal py_extension_libs helper target in py_extension_macro.bzl to prevent it from being implicitly built when wildcard target patterns are built. --- python/private/cc/py_extension_macro.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/python/private/cc/py_extension_macro.bzl b/python/private/cc/py_extension_macro.bzl index a7ed42eaba..b57e9a438e 100644 --- a/python/private/cc/py_extension_macro.bzl +++ b/python/private/cc/py_extension_macro.bzl @@ -151,6 +151,7 @@ def py_extension( # from CcInfo in py_cc_toolchain because system_provided=True in cc_import leaves DefaultInfo empty. py_extension_libs( name = win_libs_name, + tags = ["manual"], visibility = ["//visibility:private"], )