diff --git a/python/private/cc/py_extension_macro.bzl b/python/private/cc/py_extension_macro.bzl index 7845a09ea2..724a8a5631 100644 --- a/python/private/cc/py_extension_macro.bzl +++ b/python/private/cc/py_extension_macro.bzl @@ -159,7 +159,7 @@ def py_extension( "//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 " + _PY_CC_LIBS_ACTUAL_CANONICAL_TARGET + ")"], "//conditions:default": [], }) additional_linker_inputs = additional_linker_inputs + select({ diff --git a/python/private/current_py_cc_libs.bzl b/python/private/current_py_cc_libs.bzl index 58ab4b1bd8..a3e7576aa5 100644 --- a/python/private/current_py_cc_libs.bzl +++ b/python/private/current_py_cc_libs.bzl @@ -28,8 +28,8 @@ def _current_py_cc_libs_impl(ctx): 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] + cc_infos += [p for p in py_cc_toolchain.headers.providers_map.values() if hasattr(p, "linking_context")] + for cc_info in cc_infos: for input in cc_info.linking_context.linker_inputs.to_list(): for lib in input.libraries: if lib.static_library: diff --git a/python/private/get_local_runtime_info.py b/python/private/get_local_runtime_info.py index 787fad5635..101dea689c 100644 --- a/python/private/get_local_runtime_info.py +++ b/python/private/get_local_runtime_info.py @@ -204,7 +204,12 @@ def _get_python_library_info(base_executable) -> dict[str, Any]: # # See: https://docs.python.org/3/extending/windows.html # https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation - interface_path = os.path.join(root_dir, libname[:-3] + "lib") + lib_filename = libname[:-3] + "lib" + for s_dir in search_directories: + candidate = os.path.join(s_dir, lib_filename) + if os.path.exists(candidate): + interface_path = candidate + break elif libname.endswith(".so"): # It's possible, though unlikely, that interface stubs (.ifso) exist. interface_path = os.path.join(root_dir, libname[:-2] + "ifso") diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index 775aa0d9d2..bb84ff9280 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -522,6 +522,12 @@ bzl_library( deps = ["//python/private:envsubst"], ) +bzl_library( + name = "index_sources", + srcs = ["index_sources.bzl"], + deps = [":hash"], +) + bzl_library( name = "argparse", srcs = ["argparse.bzl"], @@ -542,12 +548,6 @@ bzl_library( srcs = ["hash.bzl"], ) -bzl_library( - name = "index_sources", - srcs = ["index_sources.bzl"], - deps = [":hash"], -) - bzl_library( name = "labels", srcs = ["labels.bzl"], diff --git a/tests/integration/local_toolchains/BUILD.bazel b/tests/integration/local_toolchains/BUILD.bazel index 20ee7bcfe6..cfaf93753b 100644 --- a/tests/integration/local_toolchains/BUILD.bazel +++ b/tests/integration/local_toolchains/BUILD.bazel @@ -13,9 +13,8 @@ # limitations under the License. load("@bazel_skylib//rules:common_settings.bzl", "string_flag") -load("@rules_cc//cc:cc_library.bzl", "cc_library") load("@rules_python//python:py_test.bzl", "py_test") -load(":py_extension.bzl", "py_extension") +load("@rules_python//python/cc:py_extension.bzl", "py_extension") py_test( name = "local_runtime_test", @@ -60,24 +59,14 @@ string_flag( ) # Build rules to generate a python extension. -cc_library( - name = "echo_ext_cc", - testonly = True, - srcs = ["echo_ext.cc"], - deps = [ - "@rules_python//python/cc:current_py_cc_headers", - ], - alwayslink = True, -) - py_extension( name = "echo_ext", testonly = True, + srcs = ["echo_ext.cc"], copts = select({ "@rules_cc//cc/compiler:msvc-cl": [], "//conditions:default": ["-fvisibility=hidden"], }), - deps = [":echo_ext_cc"], ) py_test( diff --git a/tests/integration/local_toolchains/py_extension.bzl b/tests/integration/local_toolchains/py_extension.bzl deleted file mode 100644 index 5d37fd7824..0000000000 --- a/tests/integration/local_toolchains/py_extension.bzl +++ /dev/null @@ -1,154 +0,0 @@ -# Copyright 2025 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Macro to build a python C/C++ extension. - -There are variants of py_extension in many other projects, such as: -* https://github.com/protocolbuffers/protobuf/tree/main/python/py_extension.bzl -* https://github.com/google/riegeli/blob/master/python/riegeli/py_extension.bzl -* https://github.com/pybind/pybind11_bazel/blob/master/build_defs.bzl - -The issue for a generic verion is: -* https://github.com/bazel-contrib/rules_python/issues/824 -""" - -load("@bazel_skylib//rules:copy_file.bzl", "copy_file") -load("@rules_cc//cc:cc_binary.bzl", "cc_binary") -load("@rules_python//python:defs.bzl", "py_library") - -def py_extension( - *, - name, - deps = None, - linkopts = None, - imports = None, - visibility = None, - **kwargs): - """Creates a Python module implemented in C++. - - A Python extension has 2 essential parts: - 1. An internal shared object / pyd package for the extension, `name.pyd`/`name.so` - 2. The py_library target for the extension.` - - Python modules can depend on a py_extension. - - Args: - name: `str`. Name for this target. This is typically the module name. - deps: `list`. Required. C++ libraries to link into the module. - linkopts: `list`. Linking options for the shared library. - imports: `list`. Additional imports for the py_library rule. - visibility: `str`. Visibility for target. - **kwargs: Additional options for the cc_library rule. - """ - if not name: - fail("py_extension requires a name") - if not deps: - fail("py_extension requires a non-empty deps attribute") - if "linkshared" in kwargs: - fail("py_extension attribute linkshared not allowed") - - if not linkopts: - linkopts = [] - - testonly = kwargs.get("testonly") - tags = kwargs.pop("tags", []) - - cc_binary_so_name = name + ".so" - cc_binary_dll_name = name + ".dll" - cc_binary_pyd_name = name + ".pyd" - linker_script_name = name + ".lds" - linker_script_name_rule = name + "_lds" - shared_objects_name = name + "__shared_objects" - - # On Unix, restrict symbol visibility. - exported_symbol = "PyInit_" + name - - # Generate linker script used on non-macOS unix platforms. - native.genrule( - name = linker_script_name_rule, - outs = [linker_script_name], - cmd = "\n".join([ - "cat <<'EOF' >$@", - "{", - " global: " + exported_symbol + ";", - " local: *;", - "};", - "EOF", - ]), - ) - - for cc_binary_name in [cc_binary_dll_name, cc_binary_so_name]: - cur_linkopts = linkopts - cur_deps = deps - if cc_binary_name == cc_binary_so_name: - cur_linkopts = linkopts + select({ - "@platforms//os:macos": [ - # Avoid undefined symbol errors for CPython symbols that - # will be resolved at runtime. - "-undefined", - "dynamic_lookup", - # On macOS, the linker does not support version scripts. Use - # the `-exported_symbol` option instead to restrict symbol - # visibility. - "-Wl,-exported_symbol", - # On macOS, the symbol starts with an underscore. - "-Wl,_" + exported_symbol, - ], - # On non-macOS unix, use a version script to restrict symbol - # visibility. - "//conditions:default": [ - "-Wl,--version-script", - "-Wl,$(location :" + linker_script_name + ")", - ], - }) - cur_deps = cur_deps + select({ - "@platforms//os:macos": [], - "//conditions:default": [linker_script_name], - }) - - cc_binary( - name = cc_binary_name, - linkshared = True, - visibility = ["//visibility:private"], - deps = cur_deps, - tags = tags + ["manual"], - linkopts = cur_linkopts, - **kwargs - ) - - copy_file( - name = cc_binary_pyd_name + "__pyd_copy", - src = ":" + cc_binary_dll_name, - out = cc_binary_pyd_name, - visibility = visibility, - tags = ["manual"], - testonly = testonly, - ) - - native.filegroup( - name = shared_objects_name, - data = select({ - "@platforms//os:windows": [":" + cc_binary_pyd_name], - "//conditions:default": [":" + cc_binary_so_name], - }), - testonly = testonly, - ) - py_library( - name = name, - data = [":" + shared_objects_name], - imports = imports, - tags = tags, - testonly = testonly, - visibility = visibility, - )