diff --git a/.gitignore b/.gitignore index 863b0e9c3f..5a34cd4503 100644 --- a/.gitignore +++ b/.gitignore @@ -32,11 +32,11 @@ *~ # Bazel directories -/bazel-* -/bazel-bin -/bazel-genfiles -/bazel-out -/bazel-testlogs +bazel-* +bazel-bin +bazel-genfiles +bazel-out +bazel-testlogs user.bazelrc # vim swap files @@ -51,4 +51,4 @@ user.bazelrc # MODULE.bazel.lock is ignored for now as per recommendation from upstream. # See https://github.com/bazelbuild/bazel/issues/20369 -MODULE.bazel.lock +MODULE.bazel.lock \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d73613a07..15b3a3ea17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,6 +78,7 @@ END_UNRELEASED_TEMPLATE multiple times. * (tools/wheelmaker.py) Extras are now preserved in Requires-Dist metadata when using requires_file to specify the requirements. +* (toolchains) Local toolchains now supports Windows. {#v0-0-0-added} ### Added diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index 9cc8ffc62c..34273898df 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -212,6 +212,7 @@ bzl_library( deps = [ ":enum_bzl", ":repo_utils.bzl", + "@bazel_skylib//lib:paths", ], ) diff --git a/python/private/get_local_runtime_info.py b/python/private/get_local_runtime_info.py index 19db3a2935..57a5a4d33f 100644 --- a/python/private/get_local_runtime_info.py +++ b/python/private/get_local_runtime_info.py @@ -36,6 +36,9 @@ # https://stackoverflow.com/questions/47423246/get-pythons-lib-path # For now, it seems LIBDIR has what is needed, so just use that. "LIBDIR", + # LIBDEST is the directory for platform-specific files; it's usually + # a subdirectory of LIBDIR. We use it in case LIBDIR isn't set. + "LIBDEST", # The versioned libpythonX.Y.so.N file. Usually? # It might be a static archive (.a) file instead. "INSTSONAME", @@ -45,6 +48,9 @@ # The platform-specific filename suffix for library files. # Includes the dot, e.g. `.so` "SHLIB_SUFFIX", + # A flag for whether this is a free threaded implementation. + # Set to t when free threading is enabled, '' or None otherwise. + "abi_thread", ] data.update(zip(config_vars, sysconfig.get_config_vars(*config_vars))) print(json.dumps(data)) diff --git a/python/private/local_runtime_repo.bzl b/python/private/local_runtime_repo.bzl index ec0643e497..2eb2d8c81e 100644 --- a/python/private/local_runtime_repo.bzl +++ b/python/private/local_runtime_repo.bzl @@ -14,6 +14,7 @@ """Create a repository for a locally installed Python runtime.""" +load("@bazel_skylib//lib:paths.bzl", "paths") load(":enum.bzl", "enum") load(":repo_utils.bzl", "REPO_DEBUG_ENV_VAR", "repo_utils") @@ -112,6 +113,17 @@ def _local_runtime_repo_impl(rctx): info["INSTSONAME"], ] + if repo_utils.get_platforms_os_name(rctx) == "windows": + # Fall back to assuming no threading when no information is available + if info.get("abi_thread") == None: + info["abi_thread"] = "" + + # Windows requires these library definitions to be linked in with the headers + shared_lib_names.append("python{major}{minor}{abi_thread}.lib".format(**info)) + shared_lib_names.append("python{major}{abi_thread}.lib".format(**info)) + + interpreter_path = interpreter_path.replace("\\", "/") + # In some cases, the value may be empty. Not clear why. shared_lib_names = [v for v in shared_lib_names if v] @@ -119,6 +131,9 @@ def _local_runtime_repo_impl(rctx): shared_lib_names = {v: None for v in shared_lib_names}.keys() shared_lib_dir = info["LIBDIR"] + if shared_lib_dir == None: + shared_lib_dir = paths.dirname(info["LIBDEST"]) + "/libs" + # The specific files are symlinked instead of the whole directory # because it can point to a directory that has more than just # the Python runtime shared libraries, e.g. /usr/lib, or a Python diff --git a/python/private/local_runtime_repo_setup.bzl b/python/private/local_runtime_repo_setup.bzl index 37eab59575..96f8571dff 100644 --- a/python/private/local_runtime_repo_setup.bzl +++ b/python/private/local_runtime_repo_setup.bzl @@ -15,6 +15,7 @@ """Setup code called by the code generated by `local_runtime_repo`.""" load("@bazel_skylib//lib:selects.bzl", "selects") +load("@rules_cc//cc:cc_import.bzl", "cc_import") load("@rules_cc//cc:cc_library.bzl", "cc_library") load("@rules_python//python:py_runtime.bzl", "py_runtime") load("@rules_python//python:py_runtime_pair.bzl", "py_runtime_pair") @@ -58,6 +59,20 @@ def define_local_runtime_toolchain_impl( major_minor = "{}.{}".format(major, minor) major_minor_micro = "{}.{}".format(major_minor, micro) + version_dict = {"major": major, "minor": minor} + + cc_import( + name = "interface", + interface_library = "lib/python{major}{minor}.lib".format(**version_dict), + system_provided = True, + ) + + cc_import( + name = "abi3_interface", + interface_library = "lib/python3.lib", + system_provided = True, + ) + cc_library( name = "_python_headers", # NOTE: Keep in sync with watch_tree() called in local_runtime_repo @@ -67,6 +82,10 @@ def define_local_runtime_toolchain_impl( allow_empty = True, ), includes = ["include"], + deps = select({ + "@platforms//os:windows": [":interface", ":abi3_interface"], + "//conditions:default": None, + }), ) cc_library(