blob: 550d89cc883c8d61c26ff911cfe45d08684350c0 [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.
"""Builds the Objective-C provider"""
objc_internal = _builtins.internal.objc_internal
CcInfo = _builtins.toplevel.CcInfo
apple_common = _builtins.toplevel.apple_common
def _create_context_and_provider(
ctx,
compilation_attributes,
compilation_artifacts,
intermediate_artifacts,
alwayslink,
has_module_map,
extra_import_libraries,
deps,
runtime_deps,
attr_linkopts):
objc_providers = []
cc_compilation_contexts = []
cc_linking_contexts = []
# List of CcLinkingContext to be merged into ObjcProvider, to be done for
# deps that don't have ObjcProviders. TODO(waltl): remove after objc link
# info migration.
cc_linking_contexts_for_merging = []
for dep in deps:
if apple_common.Objc in dep:
objc_providers.append(dep[apple_common.Objc])
elif CcInfo in dep:
# We only use CcInfo's linking info if there is no ObjcProvider.
# This is required so that objc_library archives do not get treated
# as if they are from cc targets.
cc_linking_contexts_for_merging.append(dep[CcInfo].linking_context)
if CcInfo in dep:
cc_compilation_contexts.append(dep[CcInfo].compilation_context)
cc_linking_contexts.append(dep[CcInfo].linking_context)
runtime_objc_providers = []
for runtime_dep in runtime_deps:
if apple_common.Objc in runtime_dep:
runtime_objc_providers.append(runtime_dep[apple_common.Objc])
if CcInfo in runtime_dep:
cc_compilation_contexts.append(runtime_dep[CcInfo].compilation_context)
link_order_keys = [
"imported_library",
"cc_library",
"library",
"force_load_library",
"linkopt",
]
objc_provider_kwargs = {
"imported_library": [depset(direct = extra_import_libraries, order = "topological")],
"weak_sdk_framework": [],
"sdk_dylib": [],
"linkopt": [],
"library": [],
"providers": objc_providers,
"cc_library": [],
"sdk_framework": [],
"force_load_library": [],
"umbrella_header": [],
"module_map": [],
"source": [],
}
objc_compilation_context_kwargs = {
"providers": objc_providers + runtime_objc_providers,
"cc_compilation_contexts": cc_compilation_contexts,
"public_hdrs": [],
"private_hdrs": [],
"public_textual_hdrs": [],
"defines": [],
"includes": [],
}
# Merge cc_linking_context's library and linkopt information into
# objc_provider.
all_non_sdk_linkopts = []
for cc_linking_context in cc_linking_contexts_for_merging:
if not ctx.fragments.objc.linking_info_migration:
linkopts = []
for linker_input in cc_linking_context.linker_inputs.to_list():
linkopts.extend(linker_input.user_link_flags)
non_sdk_linkopts = _add_linkopts(objc_provider_kwargs, linkopts)
all_non_sdk_linkopts.extend(non_sdk_linkopts)
libraries_to_link = []
for linker_input in cc_linking_context.linker_inputs.to_list():
libraries_to_link.extend(linker_input.libraries)
objc_provider_kwargs["cc_library"].append(
depset(direct = libraries_to_link, order = "topological"),
)
non_sdk_linkopts = _add_linkopts(
objc_provider_kwargs,
objc_internal.expand_toolchain_and_ctx_variables(ctx = ctx, flags = attr_linkopts),
)
all_non_sdk_linkopts.extend(non_sdk_linkopts)
if compilation_attributes != None:
sdk_dir = apple_common.apple_toolchain().sdk_dir()
usr_include_dir = sdk_dir + "/usr/include/"
sdk_includes = []
for sdk_include in compilation_attributes.sdk_includes.to_list():
sdk_includes.append(usr_include_dir + sdk_include)
objc_provider_kwargs["sdk_framework"].extend(
compilation_attributes.sdk_frameworks.to_list(),
)
objc_provider_kwargs["weak_sdk_framework"].extend(
compilation_attributes.weak_sdk_frameworks.to_list(),
)
objc_provider_kwargs["sdk_dylib"].extend(compilation_attributes.sdk_dylibs.to_list())
objc_compilation_context_kwargs["public_hdrs"].extend(compilation_attributes.hdrs.to_list())
objc_compilation_context_kwargs["public_textual_hdrs"].extend(
compilation_attributes.textual_hdrs.to_list(),
)
objc_compilation_context_kwargs["defines"].extend(compilation_attributes.defines)
objc_compilation_context_kwargs["includes"].extend(
compilation_attributes.header_search_paths(
genfiles_dir = ctx.genfiles_dir.path,
).to_list(),
)
objc_compilation_context_kwargs["includes"].extend(sdk_includes)
if compilation_artifacts != None:
all_sources = []
all_sources.extend(compilation_artifacts.srcs)
all_sources.extend(compilation_artifacts.non_arc_srcs)
all_sources.extend(compilation_artifacts.private_hdrs)
if compilation_artifacts.archive != None:
objc_provider_kwargs["library"] = [
depset([compilation_artifacts.archive], order = "topological"),
]
objc_provider_kwargs["source"].extend(all_sources)
objc_compilation_context_kwargs["public_hdrs"].extend(
compilation_artifacts.additional_hdrs.to_list(),
)
objc_compilation_context_kwargs["private_hdrs"].extend(compilation_artifacts.private_hdrs)
uses_cpp = False
arc_and_non_arc_srcs = []
arc_and_non_arc_srcs.extend(compilation_artifacts.srcs)
arc_and_non_arc_srcs.extend(compilation_artifacts.non_arc_srcs)
for source_file in arc_and_non_arc_srcs:
uses_cpp = uses_cpp or _is_cpp_source(source_file)
if uses_cpp:
objc_provider_kwargs["flag"] = ["uses_cpp"]
if alwayslink:
direct = []
if compilation_artifacts != None:
if compilation_artifacts.archive != None:
direct.append(compilation_artifacts.archive)
direct.extend(extra_import_libraries)
objc_provider_kwargs["force_load_library"] = [
depset(
direct = direct,
transitive = objc_provider_kwargs["force_load_library"],
order = "topological",
),
]
if has_module_map:
module_map = intermediate_artifacts.swift_module_map
umbrella_header = module_map.umbrella_header()
if umbrella_header != None:
objc_provider_kwargs["umbrella_header"].append(umbrella_header)
objc_provider_kwargs["module_map"].append(module_map.file())
objc_provider_kwargs_built = {}
for k, v in objc_provider_kwargs.items():
if k == "providers":
objc_provider_kwargs_built[k] = v
elif k in link_order_keys:
objc_provider_kwargs_built[k] = depset(transitive = v, order = "topological")
else:
objc_provider_kwargs_built[k] = depset(v)
objc_compilation_context = objc_internal.create_compilation_context(
**objc_compilation_context_kwargs
)
# The non-straightfoward way we initialize the sdk related
# information in linkopts (sdk_framework, weak_sdk_framework,
# sdk_dylib):
#
# - Filter them out of cc_linking_contexts_for_merging and self's
# linkopts. Add them to corresponding fields in
# objc_provider_kwargs. This also has the side effect that it
# deduplicates those fields.
#
# - Use the sdk fields in objc_provider_kwargs to construct
# cc_linking_context's linkopts.
all_linkopts = all_non_sdk_linkopts
for sdk_framework in objc_provider_kwargs["sdk_framework"]:
all_linkopts.append("-framework")
all_linkopts.append(sdk_framework)
for weak_sdk_framework in objc_provider_kwargs["weak_sdk_framework"]:
all_linkopts.append("-weak_framework")
all_linkopts.append(weak_sdk_framework)
for sdk_dylib in objc_provider_kwargs["sdk_dylib"]:
if sdk_dylib.startswith("lib"):
sdk_dylib = sdk_dylib[3:]
all_linkopts.append("-l%s" % sdk_dylib)
objc_linking_context = struct(
cc_linking_contexts = cc_linking_contexts,
linkopts = all_linkopts,
)
return (
apple_common.new_objc_provider(**objc_provider_kwargs_built),
objc_compilation_context,
objc_linking_context,
)
def _is_cpp_source(source_file):
return source_file.extension in ["cc", "cpp", "mm", "cxx", "C"]
def _add_linkopts(objc_provider_kwargs, linkopts):
non_sdk_linkopts = []
sdk_frameworks = {}
weak_sdk_frameworks = {}
sdk_dylib = {}
i = 0
skip_next = False
for arg in linkopts:
if skip_next:
skip_next = False
i += 1
continue
if arg == "-framework" and i < len(linkopts) - 1:
sdk_frameworks[linkopts[i + 1]] = True
skip_next = True
elif arg == "-weak_framework" and i < len(linkopts) - 1:
weak_sdk_frameworks[linkopts[i + 1]] = True
skip_next = True
elif arg.startswith("-Wl,-framework,"):
sdk_frameworks[arg[len("-Wl,-framework,"):]] = True
elif arg.startswith("-Wl,-weak_framework,"):
weak_sdk_frameworks[arg[len("-Wl,-weak_framework,"):]] = True
elif arg.startswith("-l"):
sdk_dylib[arg[2:]] = True
else:
non_sdk_linkopts.append(arg)
i += 1
objc_provider_kwargs["sdk_framework"].extend(sdk_frameworks.keys())
objc_provider_kwargs["weak_sdk_framework"].extend(weak_sdk_frameworks.keys())
objc_provider_kwargs["sdk_dylib"].extend(sdk_dylib.keys())
objc_provider_kwargs["linkopt"].append(
depset(
direct = non_sdk_linkopts,
order = "topological",
),
)
return non_sdk_linkopts
objc_common = struct(
create_context_and_provider = _create_context_and_provider,
)