diff --git a/rules/framework.bzl b/rules/framework.bzl index e79fc95f..18d010ae 100644 --- a/rules/framework.bzl +++ b/rules/framework.bzl @@ -6,6 +6,7 @@ load("//rules:library.bzl", "PrivateHeadersInfo", "apple_library") load("//rules:plists.bzl", "process_infoplists") load("//rules:providers.bzl", "AvoidDepsInfo", "FrameworkInfo") load("//rules:transition_support.bzl", "transition_support") +load("//rules:utils.bzl", "is_bazel_7") load("//rules/internal:objc_provider_utils.bzl", "objc_provider_utils") load("@bazel_skylib//lib:partial.bzl", "partial") load("@bazel_skylib//lib:paths.bzl", "paths") @@ -532,6 +533,18 @@ def _get_symlinked_framework_clean_action(ctx, framework_files, compilation_cont else: ctx.actions.write(framework_manifest, "# Empty framework\n") +def _get_cc_info_linker_inputs(*, deps): + linker_inputs = [] + + for dep in deps: + if not CcInfo in dep: + continue + + for linker_input in dep[CcInfo].linking_context.linker_inputs.to_list(): + linker_inputs.append(linker_input) + + return depset(linker_inputs) + def _create_swiftmodule(attrs): kwargs = {} @@ -984,7 +997,9 @@ def _apple_framework_packaging_impl(ctx): split_slice_key = "{}_{}{}".format(platform, split_slice_varint, arch) deps = _attrs_for_split_slice(ctx.split_attr.deps, split_slice_key) + dep_cc_infos = [dep[CcInfo] for dep in deps if CcInfo in dep] transitive_deps = _attrs_for_split_slice(ctx.split_attr.transitive_deps, split_slice_key) + transitive_dep_cc_infos = [dep[CcInfo] for dep in transitive_deps if CcInfo in dep] vfs = _attrs_for_split_slice(ctx.split_attr.vfs, split_slice_key) current_apple_platform = transition_support.current_apple_platform(apple_fragment = ctx.fragments.apple, xcode_config = ctx.attr._xcode_config) @@ -1002,15 +1017,15 @@ def _apple_framework_packaging_impl(ctx): )) objc_provider_utils.add_to_dict_if_present(compilation_context_fields, "defines", depset( direct = [], - transitive = [getattr(dep[CcInfo].compilation_context, "defines") for dep in deps if CcInfo in dep], + transitive = [getattr(cc_info.compilation_context, "defines") for cc_info in dep_cc_infos], )) objc_provider_utils.add_to_dict_if_present(compilation_context_fields, "includes", depset( direct = [], - transitive = [getattr(dep[CcInfo].compilation_context, "includes") for dep in deps if CcInfo in dep], + transitive = [getattr(cc_info.compilation_context, "includes") for cc_info in dep_cc_infos], )) objc_provider_utils.add_to_dict_if_present(compilation_context_fields, "framework_includes", depset( direct = [], - transitive = [getattr(dep[CcInfo].compilation_context, "framework_includes") for dep in deps if CcInfo in dep], + transitive = [getattr(cc_info.compilation_context, "framework_includes") for cc_info in dep_cc_infos], )) # Compute cc_info and swift_info @@ -1029,17 +1044,23 @@ def _apple_framework_packaging_impl(ctx): # If not virtualizing the framework - then it runs a "clean" _get_symlinked_framework_clean_action(ctx, framework_files, compilation_context_fields) + # Construct the `CcInfo` provider, the linking context here used instead of ObjcProvider in Bazel 7+. cc_info_provider = CcInfo( compilation_context = cc_common.create_compilation_context( **compilation_context_fields ), + linking_context = cc_common.create_linking_context( + linker_inputs = _get_cc_info_linker_inputs(deps = deps) if is_bazel_7 else depset([]), + ), ) if virtualize_frameworks: cc_info = cc_common.merge_cc_infos(direct_cc_infos = [cc_info_provider]) else: - dep_cc_infos = [dep[CcInfo] for dep in transitive_deps if CcInfo in dep] - cc_info = cc_common.merge_cc_infos(direct_cc_infos = [cc_info_provider], cc_infos = dep_cc_infos) + cc_info = cc_common.merge_cc_infos( + direct_cc_infos = [cc_info_provider], + cc_infos = transitive_dep_cc_infos, + ) # Propagate the avoid deps information upwards avoid_deps = [] @@ -1070,6 +1091,7 @@ def _apple_framework_packaging_impl(ctx): providers = [dep[apple_common.Objc] for dep in deps if apple_common.Objc in dep], transitive = [dep[apple_common.Objc] for dep in transitive_deps if apple_common.Objc in dep], ) + return [ avoid_deps_info, framework_info, diff --git a/rules/import_middleman.bzl b/rules/import_middleman.bzl index f1f5f59f..6cf923c6 100644 --- a/rules/import_middleman.bzl +++ b/rules/import_middleman.bzl @@ -174,7 +174,6 @@ def _file_collector_rule_impl(ctx): # This should be correctly configured upstream: see setup in rules_ios fail("using import_middleman ({}) on wrong transition ({},{},is_device={})".format(ctx.attr.name, platform, arch, ctx.fragments.apple.single_arch_platform.is_device)) - virtualize_frameworks = feature_names.virtualize_frameworks in ctx.features merge_keys = [ "sdk_dylib", "sdk_framework", diff --git a/rules/internal/framework_middleman.bzl b/rules/internal/framework_middleman.bzl index b4d14d64..a7e47c0e 100644 --- a/rules/internal/framework_middleman.bzl +++ b/rules/internal/framework_middleman.bzl @@ -1,4 +1,5 @@ load("@bazel_skylib//lib:partial.bzl", "partial") +load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain") load( "@build_bazel_rules_apple//apple/internal:providers.bzl", "AppleResourceInfo", @@ -40,6 +41,14 @@ def _framework_middleman(ctx): dynamic_framework_providers = [] apple_embeddable_infos = [] cc_providers = [] + cc_toolchain = find_cpp_toolchain(ctx) + cc_features = cc_common.configure_features( + ctx = ctx, + cc_toolchain = cc_toolchain, + language = "objc", + requested_features = ctx.features, + unsupported_features = ctx.disabled_features, + ) def _process_dep(lib_dep): if AppleEmbeddableInfo in lib_dep: @@ -72,13 +81,35 @@ def _framework_middleman(ctx): "dynamic_framework_file", ]) - # Add the frameworks to the linker command + # Add the frameworks to the objc provider dynamic_framework_provider = objc_provider_utils.merge_dynamic_framework_providers(dynamic_framework_providers) objc_provider_fields["dynamic_framework_file"] = depset( transitive = [dynamic_framework_provider.framework_files, objc_provider_fields.get("dynamic_framework_file", depset([]))], ) objc_provider = apple_common.new_objc_provider(**objc_provider_fields) - cc_info_provider = cc_common.merge_cc_infos(direct_cc_infos = [], cc_infos = cc_providers) + + # Add the framework info to the cc info linking context + # TODO: Not sure this does anything? + framework_cc_info = CcInfo( + linking_context = cc_common.create_linking_context( + linker_inputs = depset([ + cc_common.create_linker_input( + owner = ctx.label, + libraries = depset([ + cc_common.create_library_to_link( + actions = ctx.actions, + cc_toolchain = cc_toolchain, + feature_configuration = cc_features, + dynamic_library = dynamic_library, + ) + for dynamic_library in dynamic_framework_provider.framework_files.to_list() + ]), + ), + ]), + ), + ) + cc_info_provider = cc_common.merge_cc_infos(direct_cc_infos = [framework_cc_info], cc_infos = cc_providers) + providers = [ dynamic_framework_provider, cc_info_provider, @@ -120,6 +151,8 @@ def _framework_middleman(ctx): framework_middleman = rule( implementation = _framework_middleman, + toolchains = use_cpp_toolchain(), + fragments = ["cpp"], attrs = { "framework_deps": attr.label_list( cfg = transition_support.apple_platform_split_transition, @@ -156,6 +189,14 @@ framework_middleman = rule( default = "@bazel_tools//tools/allowlists/function_transition_allowlist", doc = "Needed to allow this rule to have an incoming edge configuration transition.", ), + "_cc_toolchain": attr.label( + providers = [cc_common.CcToolchainInfo], + default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"), + doc = """\ +The C++ toolchain from which linking flags and other tools needed by the Swift +toolchain (such as `clang`) will be retrieved. +""", + ), }, doc = """ This is a volatile internal rule to make frameworks work with @@ -194,6 +235,8 @@ def _dep_middleman(ctx): def _collect_providers(lib_dep): if apple_common.Objc in lib_dep: objc_providers.append(lib_dep[apple_common.Objc]) + if CcInfo in lib_dep: + cc_providers.append(lib_dep[CcInfo]) def _process_avoid_deps(avoid_dep_libs): for dep in avoid_dep_libs: @@ -207,6 +250,8 @@ def _dep_middleman(ctx): for lib in dep[apple_common.Objc].static_framework_file.to_list(): avoid_libraries[lib.basename] = True + # TODO: Do we need to handle CcInfo in avoid deps? + for dep in ctx.attr.deps: _collect_providers(dep) @@ -250,14 +295,16 @@ def _dep_middleman(ctx): objc_provider = apple_common.new_objc_provider(**objc_provider_fields) cc_info_provider = cc_common.merge_cc_infos(direct_cc_infos = [], cc_infos = cc_providers) - providers = [ + + return [ cc_info_provider, objc_provider, ] - return providers dep_middleman = rule( implementation = _dep_middleman, + toolchains = use_cpp_toolchain(), + fragments = ["cpp"], attrs = { "deps": attr.label_list( cfg = transition_support.apple_platform_split_transition, diff --git a/rules/internal/objc_provider_utils.bzl b/rules/internal/objc_provider_utils.bzl index cba49ae4..2fa7cfeb 100644 --- a/rules/internal/objc_provider_utils.bzl +++ b/rules/internal/objc_provider_utils.bzl @@ -52,6 +52,7 @@ def _merge_dynamic_framework_providers(dynamic_framework_providers): _add_to_dict_if_present(fields, key, set) fields["objc"] = apple_common.new_objc_provider() + fields["cc_info"] = CcInfo() return apple_common.new_dynamic_framework_provider(**fields)