Skip to content

Commit

Permalink
Add Apple static library linking Starlark API
Browse files Browse the repository at this point in the history
Introduces new Apple static library linking API refactoring existing
`apple_static_library` Starlark rule, and exposing linking logic under:
  - `apple_common.link_multi_arch_static_library`

RELNOTES: Introduces experimental static library linking API under apple_common.link_multi_arch_static_library
PiperOrigin-RevId: 431539590
  • Loading branch information
Googler authored and copybara-github committed Feb 28, 2022
1 parent 478bf55 commit 8778455
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.packages.BuiltinProvider;
import com.google.devtools.build.lib.packages.Provider;
import com.google.devtools.build.lib.packages.StarlarkInfo;
import com.google.devtools.build.lib.packages.StructImpl;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import net.starlark.java.syntax.Location;

/**
* The providers and artifact outputs returned by the {@code apple_common.link_multi_arch_binary}
Expand All @@ -41,6 +47,16 @@ static TargetTriplet create(String architecture, String platform, String environ
abstract String platform();

abstract String environment();

/** Returns a Starlark Dict representation of a {@link TargetTriplet} */
public final StructImpl toStarlarkStruct() {
Provider constructor = new BuiltinProvider<StructImpl>("target_triplet", StructImpl.class) {};
HashMap<String, Object> fields = new HashMap<>();
fields.put("architecture", architecture());
fields.put("environment", environment());
fields.put("platform", platform());
return StarlarkInfo.create(constructor, fields, Location.BUILTIN);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@
import com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag;
import com.google.devtools.build.lib.starlarkbuildapi.SplitTransitionProviderApi;
import com.google.devtools.build.lib.starlarkbuildapi.apple.AppleCommonApi;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkFunction;
import net.starlark.java.eval.StarlarkInt;
import net.starlark.java.eval.StarlarkList;
import net.starlark.java.eval.StarlarkThread;
Expand Down Expand Up @@ -285,6 +287,29 @@ public StructImpl linkMultiArchBinary(
}
}

@Override
public StructImpl linkMultiArchStaticLibrary(
StarlarkRuleContext starlarkRuleContext, StarlarkThread thread)
throws EvalException, InterruptedException {
try {
RuleContext ruleContext = starlarkRuleContext.getRuleContext();
StarlarkFunction linkMultiArchLibrary =
(StarlarkFunction)
ruleContext.getStarlarkDefinedBuiltin("link_multi_arch_static_library");
Dict<String, StructImpl> splitTargetTriplets =
MultiArchBinarySupport.getSplitTargetTripletFromCtads(
ruleContext.getSplitPrerequisiteConfiguredTargetAndTargets(
ObjcRuleClasses.CHILD_CONFIG_ATTR));
return (StructImpl)
ruleContext.callStarlarkOrThrowRuleError(
linkMultiArchLibrary,
ImmutableList.of(ruleContext.getStarlarkRuleContext(), splitTargetTriplets),
new HashMap<>());
} catch (RuleErrorException exception) {
throw new EvalException(exception);
}
}

@Override
public DottedVersion dottedVersion(String version) throws EvalException {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.google.devtools.build.lib.packages.BuiltinProvider;
import com.google.devtools.build.lib.packages.Info;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.packages.StructImpl;
import com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions;
import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
import com.google.devtools.build.lib.rules.apple.AppleConfiguration.ConfigurationDistinguisher;
Expand All @@ -52,6 +53,7 @@
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import net.starlark.java.eval.Dict;

/** Support utility for creating multi-arch Apple binaries. */
public class MultiArchBinarySupport {
Expand Down Expand Up @@ -562,4 +564,25 @@ public static AppleLinkingOutputs.TargetTriplet getTargetTriplet(BuildConfigurat
cpuPlatform.getTargetPlatform(),
cpuPlatform.getTargetEnvironment());
}

/**
* Transforms a {@link Map<Optional<String>, List<ConfiguredTargetAndData>>}, to a Starlark Dict
* keyed by split transition keys with {@link AppleLinkingOutputs.TargetTriplet} Starlark struct
* definition.
*
* @param ctads a {@link Map<Optional<String>, List<ConfiguredTargetAndData>>} from rule context
* @return a Starlark {@link Dict<String, StructImpl>} representing split transition keys with
* their target triplet (architecture, platform, environment)
*/
public static Dict<String, StructImpl> getSplitTargetTripletFromCtads(
Map<Optional<String>, List<ConfiguredTargetAndData>> ctads) {
Dict.Builder<String, StructImpl> result = Dict.builder();
for (Optional<String> splitTransitionKey : ctads.keySet()) {
TargetTriplet targetTriplet =
getTargetTriplet(
Iterables.getOnlyElement(ctads.get(splitTransitionKey)).getConfiguration());
result.put(splitTransitionKey.get(), targetTriplet.toStarlarkStruct());
}
return result.buildImmutable();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,22 @@ StructApi linkMultiArchBinary(
StarlarkThread thread)
throws EvalException, InterruptedException;

@StarlarkMethod(
name = "link_multi_arch_static_library",
doc =
"Links a (potentially multi-architecture) static library targeting Apple platforms."
+ " This method comprises a part of the <code>apple_static_library</code> rule logic,"
+ " and is exposed as an API to iterate on XCFrameworks support on Starlark.\n"
+ "<p>This API is <b>highly experimental</b> and subject to change at any time."
+ " Do not depend on the stability of this function at this time.",
parameters = {
@Param(name = "ctx", named = true, positional = false, doc = "The Starlark rule context."),
},
useStarlarkThread = true)
StructApi linkMultiArchStaticLibrary(
StarlarkRuleContextT starlarkRuleContext, StarlarkThread thread)
throws EvalException, InterruptedException;

@StarlarkMethod(
name = "dotted_version",
doc = "Creates a new <a href=\"DottedVersion.html\">DottedVersion</a> instance.",
Expand Down
2 changes: 2 additions & 0 deletions src/main/starlark/builtins_bzl/common/exports.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ load("@_builtins//:common/objc/objc_import.bzl", "objc_import")
load("@_builtins//:common/objc/objc_library.bzl", "objc_library")
load("@_builtins//:common/objc/apple_static_library.bzl", "apple_static_library")
load("@_builtins//:common/objc/compilation_support.bzl", "compilation_support")
load("@_builtins//:common/objc/linking_support.bzl", "linking_support")
load("@_builtins//:common/proto/proto_common.bzl", "proto_common")
load("@_builtins//:common/proto/proto_library.bzl", "proto_library")
load("@_builtins//:common/java/proto/java_lite_proto_library.bzl", "java_lite_proto_library")
Expand Down Expand Up @@ -58,4 +59,5 @@ exported_rules = {
exported_to_java = {
"register_compile_and_archive_actions_for_j2objc": compilation_support.register_compile_and_archive_actions_for_j2objc,
"create_proto_compile_action": proto_common.create_proto_compile_action,
"link_multi_arch_static_library": linking_support.link_multi_arch_static_library,
}
92 changes: 24 additions & 68 deletions src/main/starlark/builtins_bzl/common/objc/apple_static_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.

"""objc_library Starlark implementation replacing native"""
"""apple_static_library Starlark implementation"""

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/linking_support.bzl", "linking_support")
load("@_builtins//:common/objc/semantics.bzl", "semantics")
load("@_builtins//:common/objc/transitions.bzl", "apple_crosstool_transition")

objc_internal = _builtins.internal.objc_internal
Expand All @@ -33,65 +33,10 @@ def _apple_static_library_impl(ctx):
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)}
linking_outputs = linking_support.link_multi_arch_static_library(ctx = ctx)
libraries_to_lipo = [output.library for output in linking_outputs.outputs]

rule_intermediate_artifacts = objc_internal.create_intermediate_artifacts(ctx = ctx)
output_archive = rule_intermediate_artifacts.combined_architecture_archive
_register_combine_architectures_action(
ctx,
Expand All @@ -100,13 +45,21 @@ def _apple_static_library_impl(ctx):
platform,
)

runfiles = ctx.runfiles(files = files_to_build, collect_default = True, collect_data = True)
files_to_build = [output_archive]
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),
linking_outputs.objc,
linking_outputs.output_groups,
apple_common.AppleStaticLibrary(
archive = output_archive,
objc = linking_outputs.objc,
),
]

def _validate_minimum_os(ctx):
Expand All @@ -116,7 +69,7 @@ def _validate_minimum_os(ctx):
else:
return

minimum_os_version = apple_common.dotted_version(ctx.attr.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":
Expand Down Expand Up @@ -179,8 +132,11 @@ apple_static_library = rule(
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(
"additional_linker_inputs": attr.label_list(
flags = ["DIRECT_COMPILE_TIME_INPUT"],
allow_files = True,
),
"_child_configuration_dummy": attr.label(
cfg = apple_common.multi_arch_split,
default = "@" + semantics.get_repo() + "//tools/cpp:current_cc_toolchain",
),
Expand Down
Loading

0 comments on commit 8778455

Please sign in to comment.