| // Copyright 2021 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. |
| |
| package com.google.devtools.build.lib.rules.objc; |
| |
| import static com.google.common.collect.ImmutableList.toImmutableList; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.collect.Iterables; |
| import com.google.devtools.build.docgen.annot.DocCategory; |
| import com.google.devtools.build.lib.actions.Artifact; |
| import com.google.devtools.build.lib.analysis.Expander; |
| import com.google.devtools.build.lib.analysis.starlark.StarlarkRuleContext; |
| import com.google.devtools.build.lib.packages.Type; |
| import com.google.devtools.build.lib.rules.cpp.CcCompilationContext; |
| import com.google.devtools.build.lib.rules.cpp.CcLinkingContext; |
| import com.google.devtools.build.lib.rules.cpp.CppModuleMap.UmbrellaHeaderStrategy; |
| import com.google.devtools.build.lib.rules.objc.IntermediateArtifacts.AlwaysLink; |
| import com.google.devtools.build.lib.vfs.PathFragment; |
| import javax.annotation.Nullable; |
| import net.starlark.java.annot.Param; |
| import net.starlark.java.annot.ParamType; |
| import net.starlark.java.annot.StarlarkBuiltin; |
| import net.starlark.java.annot.StarlarkMethod; |
| import net.starlark.java.eval.EvalException; |
| import net.starlark.java.eval.NoneType; |
| import net.starlark.java.eval.Sequence; |
| import net.starlark.java.eval.Starlark; |
| import net.starlark.java.eval.StarlarkList; |
| import net.starlark.java.eval.StarlarkValue; |
| |
| /** Utility methods for Objc rules in Starlark Builtins */ |
| @StarlarkBuiltin(name = "objc_internal", category = DocCategory.BUILTIN, documented = false) |
| public class ObjcStarlarkInternal implements StarlarkValue { |
| |
| public static final String NAME = "objc_internal"; |
| |
| /** |
| * Converts a possibly NoneType object to the real object if it is not NoneType or returns the |
| * default value if it is. |
| */ |
| @SuppressWarnings("unchecked") |
| public static <T> T convertFromNoneable(Object obj, @Nullable T defaultValue) { |
| if (Starlark.UNBOUND == obj || Starlark.isNullOrNone(obj)) { |
| return defaultValue; |
| } |
| return (T) obj; |
| } |
| |
| @StarlarkMethod( |
| name = "create_compilation_attributes", |
| documented = false, |
| parameters = { |
| @Param(name = "ctx", positional = false, named = true), |
| }) |
| public CompilationAttributes createCompilationAttributes(StarlarkRuleContext starlarkRuleContext) |
| throws EvalException, InterruptedException { |
| CompilationAttributes.Builder builder = new CompilationAttributes.Builder(); |
| |
| CompilationAttributes.Builder.addHeadersFromRuleContext( |
| builder, starlarkRuleContext.getRuleContext()); |
| CompilationAttributes.Builder.addIncludesFromRuleContext( |
| builder, starlarkRuleContext.getRuleContext()); |
| CompilationAttributes.Builder.addSdkAttributesFromRuleContext( |
| builder, starlarkRuleContext.getRuleContext()); |
| if (starlarkRuleContext.getRuleContext().attributes().has("copts")) { |
| Sequence<String> copts = |
| expandAndTokenize( |
| starlarkRuleContext, |
| "copts", |
| StarlarkList.immutableCopyOf( |
| starlarkRuleContext |
| .getRuleContext() |
| .attributes() |
| .get("copts", Type.STRING_LIST))); |
| CompilationAttributes.Builder.addCompileOptionsFromRuleContext( |
| builder, starlarkRuleContext.getRuleContext(), copts); |
| } |
| CompilationAttributes.Builder.addModuleOptionsFromRuleContext( |
| builder, starlarkRuleContext.getRuleContext()); |
| |
| return builder.build(); |
| } |
| |
| /** |
| * Run variable expansion and shell tokenization on a sequence of flags. |
| * |
| * <p>When expanding path variables (e.g. $(execpath ...)), the label can refer to any of which in |
| * the {@code srcs}, {@code non_arc_srcs}, {@code hdrs} or {@code data} attributes or an output of |
| * the target. |
| * |
| * @param starlarkRuleContext The rule context of the expansion. |
| * @param attributeName The attribute of the rule tied to the expansion. Used for error reporting |
| * only. |
| * @param flags The sequence of flags to expand. |
| */ |
| @StarlarkMethod( |
| name = "expand_and_tokenize", |
| documented = false, |
| parameters = { |
| @Param(name = "ctx", positional = false, named = true), |
| @Param(name = "attr", positional = false, named = true), |
| @Param(name = "flags", positional = false, defaultValue = "[]", named = true), |
| }) |
| public Sequence<String> expandAndTokenize( |
| StarlarkRuleContext starlarkRuleContext, String attributeName, Sequence<?> flags) |
| throws EvalException, InterruptedException { |
| if (flags.isEmpty()) { |
| return Sequence.cast(flags, String.class, attributeName); |
| } |
| Expander expander = |
| starlarkRuleContext |
| .getRuleContext() |
| .getExpander( |
| StarlarkRuleContext.makeLabelMap( |
| ImmutableSet.copyOf( |
| Iterables.concat( |
| starlarkRuleContext.getRuleContext().getPrerequisites("srcs"), |
| starlarkRuleContext.getRuleContext().getPrerequisites("non_arc_srcs"), |
| starlarkRuleContext.getRuleContext().getPrerequisites("hdrs"), |
| starlarkRuleContext.getRuleContext().getPrerequisites("data"))))) |
| .withDataExecLocations(); |
| ImmutableList<String> expandedFlags = |
| expander.tokenized(attributeName, Sequence.cast(flags, String.class, attributeName)); |
| return StarlarkList.immutableCopyOf(expandedFlags); |
| } |
| |
| @StarlarkMethod( |
| name = "create_intermediate_artifacts", |
| documented = false, |
| parameters = { |
| @Param(name = "ctx", positional = false, named = true), |
| }) |
| public IntermediateArtifacts createIntermediateArtifacts( |
| StarlarkRuleContext starlarkRuleContext) { |
| return new IntermediateArtifacts(starlarkRuleContext.getRuleContext()); |
| } |
| |
| @StarlarkMethod( |
| name = "j2objc_create_intermediate_artifacts", |
| documented = false, |
| parameters = { |
| @Param(name = "ctx", positional = false, named = true), |
| }) |
| public IntermediateArtifacts j2objcCreateIntermediateArtifacts( |
| StarlarkRuleContext starlarkRuleContext) { |
| return new IntermediateArtifacts( |
| starlarkRuleContext.getRuleContext(), |
| /* archiveFileNameSuffix= */ "_j2objc", |
| UmbrellaHeaderStrategy.GENERATE, |
| AlwaysLink.TRUE); |
| } |
| |
| @StarlarkMethod( |
| name = "create_compilation_artifacts", |
| documented = false, |
| parameters = { |
| @Param( |
| name = "ctx", |
| positional = false, |
| named = true, |
| defaultValue = "None", |
| allowedTypes = { |
| @ParamType(type = StarlarkRuleContext.class), |
| @ParamType(type = NoneType.class) |
| }), |
| }) |
| public CompilationArtifacts createCompilationArtifacts(Object starlarkRuleContextObject) { |
| StarlarkRuleContext starlarkRuleContext = |
| convertFromNoneable(starlarkRuleContextObject, /* defaultValue= */ null); |
| if (starlarkRuleContext != null) { |
| return CompilationSupport.compilationArtifacts(starlarkRuleContext.getRuleContext()); |
| } else { |
| return new CompilationArtifacts(); |
| } |
| } |
| |
| @StarlarkMethod( |
| name = "j2objc_create_compilation_artifacts", |
| documented = false, |
| parameters = { |
| @Param(name = "srcs", positional = false, named = true), |
| @Param(name = "non_arc_srcs", positional = false, named = true), |
| @Param(name = "hdrs", positional = false, named = true), |
| @Param(name = "intermediate_artifacts", positional = false, named = true), |
| }) |
| public CompilationArtifacts j2objcCreateCompilationArtifacts( |
| Sequence<?> srcs, |
| Sequence<?> nonArcSrcs, |
| Sequence<?> hdrs, |
| Object intermediateArtifactsObject) |
| throws EvalException { |
| IntermediateArtifacts intermediateArtifacts = |
| convertFromNoneable(intermediateArtifactsObject, /* defaultValue= */ null); |
| return new CompilationArtifacts( |
| Sequence.cast(srcs, Artifact.class, "srcs"), |
| Sequence.cast(nonArcSrcs, Artifact.class, "non_arc_srcs"), |
| Sequence.cast(hdrs, Artifact.class, "hdrs"), |
| intermediateArtifacts); |
| } |
| |
| @StarlarkMethod( |
| name = "create_compilation_context", |
| documented = false, |
| parameters = { |
| @Param(name = "public_hdrs", positional = false, defaultValue = "[]", named = true), |
| @Param(name = "public_textual_hdrs", positional = false, defaultValue = "[]", named = true), |
| @Param(name = "private_hdrs", positional = false, defaultValue = "[]", named = true), |
| @Param(name = "providers", positional = false, defaultValue = "[]", named = true), |
| @Param( |
| name = "direct_cc_compilation_contexts", |
| positional = false, |
| defaultValue = "[]", |
| named = true), |
| @Param( |
| name = "cc_compilation_contexts", |
| positional = false, |
| defaultValue = "[]", |
| named = true), |
| @Param( |
| name = "implementation_cc_compilation_contexts", |
| positional = false, |
| defaultValue = "[]", |
| named = true), |
| @Param(name = "defines", positional = false, defaultValue = "[]", named = true), |
| @Param(name = "includes", positional = false, defaultValue = "[]", named = true), |
| }) |
| public ObjcCompilationContext createCompilationContext( |
| Sequence<?> publicHdrs, |
| Sequence<?> publicTextualHdrs, |
| Sequence<?> privateHdrs, |
| Sequence<?> providers, |
| Sequence<?> directCcCompilationContexts, |
| Sequence<?> ccCompilationContexts, |
| Sequence<?> implementationCcCompilationContexts, |
| Sequence<?> defines, |
| Sequence<?> includes) |
| throws InterruptedException, EvalException { |
| return ObjcCompilationContext.builder() |
| .addPublicHeaders(Sequence.cast(publicHdrs, Artifact.class, "public_hdrs")) |
| .addPublicTextualHeaders( |
| Sequence.cast(publicTextualHdrs, Artifact.class, "public_textual_hdrs")) |
| .addPrivateHeaders(Sequence.cast(privateHdrs, Artifact.class, "private_hdrs")) |
| .addObjcProviders(Sequence.cast(providers, ObjcProvider.class, "providers")) |
| .addDirectCcCompilationContexts( |
| Sequence.cast( |
| directCcCompilationContexts, CcCompilationContext.class, "cc_compilation_contexts")) |
| .addCcCompilationContexts( |
| Sequence.cast( |
| ccCompilationContexts, CcCompilationContext.class, "cc_compilation_contexts")) |
| .addImplementationCcCompilationContexts( |
| Sequence.cast( |
| implementationCcCompilationContexts, |
| CcCompilationContext.class, |
| "implementation_cc_compilation_contexts")) |
| .addDefines(Sequence.cast(defines, String.class, "defines")) |
| .addIncludes( |
| Sequence.cast(includes, String.class, "includes").stream() |
| .map(PathFragment::create) |
| .collect(toImmutableList())) |
| .build(); |
| } |
| |
| @StarlarkMethod( |
| name = "subtract_linking_contexts", |
| documented = false, |
| parameters = { |
| @Param(name = "ctx", positional = false, named = true), |
| @Param(name = "linking_contexts", positional = false, defaultValue = "[]", named = true), |
| @Param( |
| name = "avoid_dep_linking_contexts", |
| positional = false, |
| defaultValue = "[]", |
| named = true), |
| }) |
| public CcLinkingContext subtractLinkingContexts( |
| StarlarkRuleContext starlarkRuleContext, |
| Sequence<?> linkingContexts, |
| Sequence<?> avoidDepLinkingContexts) |
| throws InterruptedException, EvalException { |
| return MultiArchBinarySupport.ccLinkingContextSubtractSubtrees( |
| starlarkRuleContext.getRuleContext(), |
| Sequence.cast(linkingContexts, CcLinkingContext.class, "linking_contexts"), |
| Sequence.cast( |
| avoidDepLinkingContexts, CcLinkingContext.class, "avoid_dep_linking_contexts")); |
| } |
| } |