diff --git a/CHANGELOG.md b/CHANGELOG.md index bd94003bb7..d4105751eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,9 @@ A brief description of the categories of changes: * (gazelle): Update error messages when unable to resolve a dependency to be more human-friendly. * (flags) The {obj}`--python_version` flag now also returns {obj}`config_common.FeatureFlagInfo`. +* (toolchains) {obj}`py_cc_toolchain.libs` and {obj}`PyCcToolchainInfo.libs` is + optional. This is to support situations where only the Python headers are + available. ### Fixed * (whl_library): Remove `--no-index` and add `--no-build-isolation` to the diff --git a/python/private/py_cc_toolchain_info.bzl b/python/private/py_cc_toolchain_info.bzl index ae46bf4d4d..c5cdbd9d84 100644 --- a/python/private/py_cc_toolchain_info.bzl +++ b/python/private/py_cc_toolchain_info.bzl @@ -41,9 +41,9 @@ Information about the header files, struct with fields: represents). """, "libs": """\ -:type: struct +:type: struct | None -Information about C libraries, struct with fields: +If available, information about C libraries, struct with fields: * providers_map: A dict of string to provider instances. The key should be a fully qualified name (e.g. `@rules_foo//bar:baz.bzl#MyInfo`) of the provider to uniquely identify its type. diff --git a/python/private/py_cc_toolchain_rule.bzl b/python/private/py_cc_toolchain_rule.bzl index 1599415ac7..2c52a2ec84 100644 --- a/python/private/py_cc_toolchain_rule.bzl +++ b/python/private/py_cc_toolchain_rule.bzl @@ -23,6 +23,16 @@ load("@rules_cc//cc:defs.bzl", "CcInfo") load(":py_cc_toolchain_info.bzl", "PyCcToolchainInfo") def _py_cc_toolchain_impl(ctx): + if ctx.attr.libs: + libs = struct( + providers_map = { + "CcInfo": ctx.attr.libs[CcInfo], + "DefaultInfo": ctx.attr.libs[DefaultInfo], + }, + ) + else: + libs = None + py_cc_toolchain = PyCcToolchainInfo( headers = struct( providers_map = { @@ -30,12 +40,7 @@ def _py_cc_toolchain_impl(ctx): "DefaultInfo": ctx.attr.headers[DefaultInfo], }, ), - libs = struct( - providers_map = { - "CcInfo": ctx.attr.libs[CcInfo], - "DefaultInfo": ctx.attr.libs[DefaultInfo], - }, - ), + libs = libs, python_version = ctx.attr.python_version, ) extra_kwargs = {} @@ -59,7 +64,6 @@ py_cc_toolchain = rule( doc = ("Target that provides the Python runtime libraries for linking. " + "Typically this is a cc_library target of `.so` files."), providers = [CcInfo], - mandatory = True, ), "python_version": attr.string( doc = "The Major.minor Python version, e.g. 3.11", diff --git a/tests/cc/py_cc_toolchain/py_cc_toolchain_tests.bzl b/tests/cc/py_cc_toolchain/py_cc_toolchain_tests.bzl index fcc520e291..0419a04a45 100644 --- a/tests/cc/py_cc_toolchain/py_cc_toolchain_tests.bzl +++ b/tests/cc/py_cc_toolchain/py_cc_toolchain_tests.bzl @@ -16,15 +16,16 @@ load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite") load("@rules_testing//lib:truth.bzl", "matching", "subjects") +load("//python/cc:py_cc_toolchain.bzl", "py_cc_toolchain") load("//tests/support:cc_info_subject.bzl", "cc_info_subject") load("//tests/support:py_cc_toolchain_info_subject.bzl", "PyCcToolchainInfoSubject") _tests = [] -def _py_cc_toolchain_test(name): +def _test_py_cc_toolchain(name): analysis_test( name = name, - impl = _py_cc_toolchain_test_impl, + impl = _test_py_cc_toolchain_impl, target = "//tests/support/cc_toolchains:fake_py_cc_toolchain_impl", attrs = { "header": attr.label( @@ -34,7 +35,7 @@ def _py_cc_toolchain_test(name): }, ) -def _py_cc_toolchain_test_impl(env, target): +def _test_py_cc_toolchain_impl(env, target): env.expect.that_target(target).has_provider(platform_common.ToolchainInfo) toolchain = PyCcToolchainInfoSubject.new( @@ -80,7 +81,26 @@ def _py_cc_toolchain_test_impl(env, target): matching.str_matches("/libpython3."), ) -_tests.append(_py_cc_toolchain_test) +_tests.append(_test_py_cc_toolchain) + +def _test_libs_optional(name): + py_cc_toolchain( + name = name + "_subject", + libs = None, + headers = "//tests/support/cc_toolchains:fake_headers", + python_version = "4.5", + ) + analysis_test( + name = name, + target = name + "_subject", + impl = _test_libs_optional_impl, + ) + +def _test_libs_optional_impl(env, target): + libs = target[platform_common.ToolchainInfo].py_cc_toolchain.libs + env.expect.that_bool(libs == None).equals(True) + +_tests.append(_test_libs_optional) def py_cc_toolchain_test_suite(name): test_suite(