blob: 95efb8dc7b477dd75ce58eee4be738e4c90a71b9 [file] [log] [blame]
# Copyright 2020 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.
"""objc_library Starlark implementation replacing native"""
load("@_builtins//:common/objc/semantics.bzl", "semantics")
load("@_builtins//:common/objc/compilation_support.bzl", "compilation_support")
load("@_builtins//:common/objc/attrs.bzl", "common_attrs")
load("@_builtins//:common/objc/transitions.bzl", "apple_crosstool_transition")
objc_internal = _builtins.internal.objc_internal
CcInfo = _builtins.toplevel.CcInfo
cc_common = _builtins.toplevel.cc_common
transition = _builtins.toplevel.transition
coverage_common = _builtins.toplevel.coverage_common
apple_common = _builtins.toplevel.apple_common
def _apple_static_library_impl(ctx):
_validate_minimum_os(ctx)
if not hasattr(apple_common.platform_type, ctx.attr.platform_type):
fail("Unsupported platform type \"{}\"".format(ctx.attr.platform_type))
platform_type = getattr(apple_common.platform_type, ctx.attr.platform_type)
platform = ctx.fragments.apple.multi_arch_platform(platform_type)
cpu_to_deps_map = ctx.split_attr.deps
cpu_to_avoid_deps_map = ctx.split_attr.avoid_deps
child_configs_and_toolchains = ctx.split_attr._child_configuration_dummmy
rule_intermediate_artifacts = objc_internal.create_intermediate_artifacts(ctx = ctx)
libraries_to_lipo = []
files_to_build = [rule_intermediate_artifacts.combined_architecture_archive]
sdk_dylib = []
sdk_framework = []
weak_sdk_framework = []
for key, child_toolchain in ctx.split_attr._child_configuration_dummmy.items():
intermediate_artifacts = objc_internal.create_intermediate_artifacts(ctx = ctx)
deps = cpu_to_deps_map[key]
common_variables = compilation_support.build_common_variables(
ctx = ctx,
toolchain = child_toolchain[cc_common.CcToolchainInfo],
use_pch = True,
deps = cpu_to_deps_map[key],
)
avoid_objc_providers = []
avoid_cc_providers = []
if len(cpu_to_avoid_deps_map.keys()):
for dep in cpu_to_avoid_deps_map[key]:
if apple_common.Objc in dep:
avoid_objc_providers.append(dep[apple_common.Objc])
if CcInfo in dep:
avoid_cc_providers.append(dep[CcInfo])
objc_provider = common_variables.objc_provider.subtract_subtrees(avoid_objc_providers = avoid_objc_providers, avoid_cc_providers = avoid_cc_providers)
name = ctx.label.name + "-" + key + "-fl"
linking_outputs = compilation_support.register_fully_link_action(common_variables, objc_provider, name)
libraries_to_lipo.append(linking_outputs.library_to_link.static_library)
sdk_dylib.append(objc_provider.sdk_dylib)
sdk_framework.append(objc_provider.sdk_framework)
weak_sdk_framework.append(objc_provider.weak_sdk_framework)
objc_provider = apple_common.new_objc_provider(
sdk_dylib = depset(transitive = sdk_dylib),
sdk_framework = depset(transitive = sdk_framework),
weak_sdk_framework = depset(transitive = weak_sdk_framework),
)
header_tokens = []
for key, deps in cpu_to_deps_map.items():
for dep in deps:
if CcInfo in dep:
header_tokens.append(dep[CcInfo].compilation_context.validation_artifacts)
output_groups = {"_validation": depset(transitive = header_tokens)}
output_archive = rule_intermediate_artifacts.combined_architecture_archive
_register_combine_architectures_action(
ctx,
libraries_to_lipo,
output_archive,
platform,
)
runfiles = ctx.runfiles(files = files_to_build, collect_default = True, collect_data = True)
return [
DefaultInfo(files = depset(files_to_build), runfiles = runfiles),
objc_provider,
OutputGroupInfo(**output_groups),
apple_common.AppleStaticLibrary(archive = output_archive, objc = objc_provider),
]
def _validate_minimum_os(ctx):
if len(ctx.attr.minimum_os_version) == 0:
if ctx.fragments.apple.mandatory_minimum_version():
fail("'minimum_os_version' must be explicitly specified")
else:
return
minimum_os_version = apple_common.dotted_version(ctx.attr.minimum_os_version)
components = ctx.attr.minimum_os_version.split(".")
for i in range(len(components) - 1, 0, -1):
if components[i] == "0":
components.pop()
else:
break
if len(components) > 2:
fail("Invalid version string. Cannot have more than two components")
for component in components:
if not component.isdigit():
fail("Invalid version string. Must be numeric")
def _register_combine_architectures_action(ctx, artifacts, output_binary, platform):
if len(artifacts) > 1:
xcode_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig]
env = {}
env.update(apple_common.apple_host_system_env(xcode_config))
env.update(apple_common.target_apple_env(xcode_config, platform))
execution_requirements = {}
execution_requirements.update(xcode_config.execution_info())
arguments = ctx.actions.args()
arguments.add("lipo")
arguments.add("-create")
arguments.add_all(artifacts)
arguments.add("-o")
arguments.add(output_binary)
ctx.actions.run(
mnemonic = "ObjcCombiningArchitectures",
inputs = artifacts,
outputs = [output_binary],
env = env,
execution_requirements = execution_requirements,
arguments = [arguments],
executable = ctx.executable._xcrunwrapper,
)
else:
ctx.actions.symlink(
output = output_binary,
target_file = artifacts[0],
)
apple_static_library = rule(
implementation = _apple_static_library_impl,
attrs = common_attrs.union(
{
"data": attr.label_list(allow_files = True),
"deps": attr.label_list(
cfg = apple_common.multi_arch_split,
providers = [apple_common.Objc],
flags = ["DIRECT_COMPILE_TIME_INPUT"],
allow_rules = ["cc_library", "cc_inc_library"],
),
"avoid_deps": attr.label_list(
cfg = apple_common.multi_arch_split,
providers = [apple_common.Objc],
flags = ["DIRECT_COMPILE_TIME_INPUT"],
allow_rules = ["cc_library", "cc_inc_library"],
),
"linkopts": attr.string_list(),
"additional_linker_inputs": attr.label_list(flags = ["DIRECT_COMPILE_TIME_INPUT"], allow_files = True),
"_child_configuration_dummmy": attr.label(
cfg = apple_common.multi_arch_split,
default = "@" + semantics.get_repo() + "//tools/cpp:current_cc_toolchain",
),
"_cc_toolchain": attr.label(
default = "@" + semantics.get_repo() + "//tools/cpp:current_cc_toolchain",
),
},
common_attrs.LICENSES,
common_attrs.X_C_RUNE_RULE,
common_attrs.SDK_FRAMEWORK_DEPENDER_RULE,
common_attrs.PLATFORM_RULE,
),
outputs = {
"lipo_archive": "%{name}_lipo.a",
},
cfg = apple_crosstool_transition,
fragments = ["objc", "apple", "cpp"],
toolchains = ["@" + semantics.get_repo() + "//tools/cpp:toolchain_type"],
incompatible_use_toolchain_transition = True,
)