aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationAttributes.java
diff options
context:
space:
mode:
authorGravatar Sergio Campama <kaipi@google.com>2016-06-06 15:12:55 +0000
committerGravatar Yun Peng <pcloudy@google.com>2016-06-06 16:42:02 +0000
commit146ecf9883883a97cf9c25b0b8e478fc3e5e2c22 (patch)
treeececc5639768aa48fcb4e9945f5f4fcbfd8e0389 /src/main/java/com/google/devtools/build/lib/rules/objc/CompilationAttributes.java
parent4f72b2c7afb8d27971ca41142e6c15f4a22ddf16 (diff)
Separates the proto compilation action from the other linking sources, to isolate them from the linking target's defines and copts flags. Refactors CompilationAttributes into its own class with the Builder pattern.
-- MOS_MIGRATED_REVID=124137672
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/objc/CompilationAttributes.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/CompilationAttributes.java480
1 files changed, 480 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationAttributes.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationAttributes.java
new file mode 100644
index 0000000000..f41b101c2f
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationAttributes.java
@@ -0,0 +1,480 @@
+// Copyright 2016 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.devtools.build.lib.rules.objc.ObjcProvider.TOP_LEVEL_MODULE_MAP;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.PrerequisiteArtifacts;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.packages.BuildType;
+import com.google.devtools.build.lib.rules.cpp.CcCommon;
+import com.google.devtools.build.lib.rules.cpp.CppModuleMap;
+import com.google.devtools.build.lib.syntax.Type;
+import com.google.devtools.build.lib.util.Pair;
+import com.google.devtools.build.lib.vfs.PathFragment;
+
+import java.util.List;
+
+/**
+ * Provides a way to access attributes that are common to all compilation rules.
+ */
+// TODO(bazel-team): Delete and move into support-specific attributes classes once ObjcCommon is
+// gone.
+final class CompilationAttributes {
+ static class Builder {
+ private final NestedSetBuilder<Artifact> hdrs = NestedSetBuilder.stableOrder();
+ private final NestedSetBuilder<Artifact> textualHdrs = NestedSetBuilder.stableOrder();
+ private final NestedSetBuilder<PathFragment> includes = NestedSetBuilder.stableOrder();
+ private final NestedSetBuilder<PathFragment> sdkIncludes = NestedSetBuilder.stableOrder();
+ private final NestedSetBuilder<String> copts = NestedSetBuilder.stableOrder();
+ private final NestedSetBuilder<String> linkopts = NestedSetBuilder.stableOrder();
+ private final NestedSetBuilder<CppModuleMap> moduleMapsForDirectDeps =
+ NestedSetBuilder.stableOrder();
+ private final NestedSetBuilder<SdkFramework> sdkFrameworks = NestedSetBuilder.stableOrder();
+ private final NestedSetBuilder<SdkFramework> weakSdkFrameworks = NestedSetBuilder.stableOrder();
+ private final NestedSetBuilder<String> sdkDylibs = NestedSetBuilder.stableOrder();
+ private Optional<Artifact> bridgingHeader = Optional.absent();
+ private Optional<PathFragment> packageFragment = Optional.absent();
+ private boolean enableModules;
+
+ /**
+ * Adds the default values available through the rule's context.
+ */
+ static Builder fromRuleContext(RuleContext ruleContext) {
+ Builder builder = new Builder();
+
+ addHeadersFromRuleContext(builder, ruleContext);
+ addIncludesFromRuleContext(builder, ruleContext);
+ addSdkAttributesFromRuleContext(builder, ruleContext);
+ addCompileOptionsFromRuleContext(builder, ruleContext);
+ addModuleOptionsFromRuleContext(builder, ruleContext);
+
+ return builder;
+ }
+
+ /**
+ * Adds headers to be made available for dependents.
+ */
+ public Builder addHdrs(NestedSet<Artifact> hdrs) {
+ this.hdrs.addTransitive(hdrs);
+ return this;
+ }
+
+ /**
+ * Adds headers that cannot be compiled individually.
+ */
+ public Builder addTextualHdrs(NestedSet<Artifact> textualHdrs) {
+ this.textualHdrs.addTransitive(textualHdrs);
+ return this;
+ }
+
+ /**
+ * Adds include paths to be made available for compilation.
+ */
+ public Builder addIncludes(NestedSet<PathFragment> includes) {
+ this.includes.addTransitive(includes);
+ return this;
+ }
+
+ /**
+ * Adds paths for SDK includes.
+ */
+ public Builder addSdkIncludes(NestedSet<PathFragment> sdkIncludes) {
+ this.sdkIncludes.addTransitive(sdkIncludes);
+ return this;
+ }
+
+ /**
+ * Adds compile-time options.
+ */
+ public Builder addCopts(NestedSet<String> copts) {
+ this.copts.addTransitive(copts);
+ return this;
+ }
+
+ /**
+ * Adds link-time options.
+ */
+ public Builder addLinkopts(NestedSet<String> linkopts) {
+ this.linkopts.addTransitive(linkopts);
+ return this;
+ }
+
+ /**
+ * Adds clang module maps for direct dependencies of the rule. These are needed to generate
+ * module maps.
+ */
+ public Builder addModuleMapsForDirectDeps(NestedSet<CppModuleMap> moduleMapsForDirectDeps) {
+ this.moduleMapsForDirectDeps.addTransitive(moduleMapsForDirectDeps);
+ return this;
+ }
+
+ /**
+ * Adds SDK frameworks to link against.
+ */
+ public Builder addSdkFrameworks(NestedSet<SdkFramework> sdkFrameworks) {
+ this.sdkFrameworks.addTransitive(sdkFrameworks);
+ return this;
+ }
+
+ /**
+ * Adds SDK frameworks to be linked weakly.
+ */
+ public Builder addWeakSdkFrameworks(NestedSet<SdkFramework> weakSdkFrameworks) {
+ this.weakSdkFrameworks.addTransitive(weakSdkFrameworks);
+ return this;
+ }
+
+ /**
+ * Adds SDK Dylibs to link against.
+ */
+ public Builder addSdkDylibs(NestedSet<String> sdkDylibs) {
+ this.sdkDylibs.addTransitive(sdkDylibs);
+ return this;
+ }
+
+ /**
+ * Sets the bridging header to be used when compiling Swift sources.
+ */
+ public Builder setBridgingHeader(Artifact bridgingHeader) {
+ Preconditions.checkState(
+ !this.bridgingHeader.isPresent(),
+ "bridgingHeader is already set to %s",
+ this.bridgingHeader);
+ this.bridgingHeader = Optional.of(bridgingHeader);
+ return this;
+ }
+
+ /**
+ * Sets the package path from which to base the header search paths.
+ */
+ public Builder setPackageFragment(PathFragment packageFragment) {
+ Preconditions.checkState(
+ !this.packageFragment.isPresent(),
+ "packageFragment is already set to %s",
+ this.packageFragment);
+ this.packageFragment = Optional.of(packageFragment);
+ return this;
+ }
+
+ /**
+ * Enables the usage of clang modules maps during compilation.
+ */
+ public Builder enableModules() {
+ this.enableModules = true;
+ return this;
+ }
+
+ /**
+ * Builds a {@code CompilationAttributes} object.
+ */
+ public CompilationAttributes build() {
+ return new CompilationAttributes(
+ this.hdrs.build(),
+ this.textualHdrs.build(),
+ this.bridgingHeader,
+ this.includes.build(),
+ this.sdkIncludes.build(),
+ this.sdkFrameworks.build(),
+ this.weakSdkFrameworks.build(),
+ this.sdkDylibs.build(),
+ this.packageFragment,
+ this.copts.build(),
+ this.linkopts.build(),
+ this.moduleMapsForDirectDeps.build(),
+ this.enableModules);
+ }
+
+ private static void addHeadersFromRuleContext(Builder builder, RuleContext ruleContext) {
+ if (ruleContext.attributes().has("hdrs", BuildType.LABEL_LIST)) {
+ NestedSetBuilder<Artifact> headers = NestedSetBuilder.stableOrder();
+ for (Pair<Artifact, Label> header : CcCommon.getHeaders(ruleContext)) {
+ headers.add(header.first);
+ }
+ builder.addHdrs(headers.build());
+ }
+
+ if (ruleContext.attributes().has("textual_hdrs", BuildType.LABEL_LIST)) {
+ builder.addTextualHdrs(
+ PrerequisiteArtifacts.nestedSet(ruleContext, "textual_hdrs", Mode.TARGET));
+ }
+
+ if (ruleContext.attributes().has("bridging_header", BuildType.LABEL)) {
+ Artifact header = ruleContext.getPrerequisiteArtifact("bridging_header", Mode.TARGET);
+ if (header != null) {
+ builder.setBridgingHeader(header);
+ }
+ }
+ }
+
+ private static void addIncludesFromRuleContext(Builder builder, RuleContext ruleContext) {
+ if (ruleContext.attributes().has("includes", Type.STRING_LIST)) {
+ NestedSetBuilder<PathFragment> includes = NestedSetBuilder.stableOrder();
+ includes.addAll(
+ Iterables.transform(
+ ruleContext.attributes().get("includes", Type.STRING_LIST),
+ PathFragment.TO_PATH_FRAGMENT));
+ builder.addIncludes(includes.build());
+ }
+
+ if (ruleContext.attributes().has("sdk_includes", Type.STRING_LIST)) {
+ NestedSetBuilder<PathFragment> sdkIncludes = NestedSetBuilder.stableOrder();
+ sdkIncludes.addAll(
+ Iterables.transform(
+ ruleContext.attributes().get("sdk_includes", Type.STRING_LIST),
+ PathFragment.TO_PATH_FRAGMENT));
+ builder.addSdkIncludes(sdkIncludes.build());
+ }
+ }
+
+ private static void addSdkAttributesFromRuleContext(Builder builder, RuleContext ruleContext) {
+ if (ruleContext.attributes().has("sdk_frameworks", Type.STRING_LIST)) {
+ NestedSetBuilder<SdkFramework> frameworks = NestedSetBuilder.stableOrder();
+ // TODO(bazel-team): Move the inclusion of the default frameworks to CompilationSupport.
+ frameworks.addAll(ObjcRuleClasses.AUTOMATIC_SDK_FRAMEWORKS);
+ for (String explicit : ruleContext.attributes().get("sdk_frameworks", Type.STRING_LIST)) {
+ frameworks.add(new SdkFramework(explicit));
+ }
+ builder.addSdkFrameworks(frameworks.build());
+ }
+
+ if (ruleContext.attributes().has("weak_sdk_frameworks", Type.STRING_LIST)) {
+ NestedSetBuilder<SdkFramework> weakFrameworks = NestedSetBuilder.stableOrder();
+ for (String frameworkName :
+ ruleContext.attributes().get("weak_sdk_frameworks", Type.STRING_LIST)) {
+ weakFrameworks.add(new SdkFramework(frameworkName));
+ }
+ builder.addWeakSdkFrameworks(weakFrameworks.build());
+ }
+
+ if (ruleContext.attributes().has("sdk_dylibs", Type.STRING_LIST)) {
+ NestedSetBuilder<String> sdkDylibs = NestedSetBuilder.stableOrder();
+ sdkDylibs.addAll(ruleContext.attributes().get("sdk_dylibs", Type.STRING_LIST));
+ builder.addSdkDylibs(sdkDylibs.build());
+ }
+ }
+
+ private static void addCompileOptionsFromRuleContext(Builder builder, RuleContext ruleContext) {
+ if (ruleContext.attributes().has("copts", Type.STRING_LIST)) {
+ NestedSetBuilder<String> copts = NestedSetBuilder.stableOrder();
+ copts.addAll(ruleContext.getTokenizedStringListAttr("copts"));
+ builder.addCopts(copts.build());
+ }
+
+ if (ruleContext.attributes().has("linkopts", Type.STRING_LIST)) {
+ NestedSetBuilder<String> linkopts = NestedSetBuilder.stableOrder();
+ linkopts.addAll(ruleContext.getTokenizedStringListAttr("linkopts"));
+ builder.addLinkopts(linkopts.build());
+ }
+ }
+
+ private static void addModuleOptionsFromRuleContext(Builder builder, RuleContext ruleContext) {
+ NestedSetBuilder<CppModuleMap> moduleMaps = NestedSetBuilder.stableOrder();
+ ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext);
+ if (objcConfiguration.moduleMapsEnabled()) {
+ // Make sure all dependencies that have headers are included here. If a module map is
+ // missing, its private headers will be treated as public!
+ if (ruleContext.attributes().has("deps", BuildType.LABEL_LIST)) {
+ Iterable<ObjcProvider> providers =
+ ruleContext.getPrerequisites("deps", Mode.TARGET, ObjcProvider.class);
+ for (ObjcProvider provider : providers) {
+ moduleMaps.addTransitive(provider.get(TOP_LEVEL_MODULE_MAP));
+ }
+ }
+ if (ruleContext.attributes().has("non_propagated_deps", BuildType.LABEL_LIST)) {
+ Iterable<ObjcProvider> providers =
+ ruleContext.getPrerequisites("non_propagated_deps", Mode.TARGET, ObjcProvider.class);
+ for (ObjcProvider provider : providers) {
+ moduleMaps.addTransitive(provider.get(TOP_LEVEL_MODULE_MAP));
+ }
+ }
+ }
+
+ builder.addModuleMapsForDirectDeps(moduleMaps.build());
+
+ PathFragment packageFragment =
+ ruleContext.getLabel().getPackageIdentifier().getPathFragment();
+ if (packageFragment != null) {
+ builder.setPackageFragment(packageFragment);
+ }
+
+ if (ruleContext.attributes().has("enable_modules", Type.BOOLEAN)
+ && ruleContext.attributes().get("enable_modules", Type.BOOLEAN)) {
+ builder.enableModules();
+ }
+ }
+ }
+
+ private final NestedSet<Artifact> hdrs;
+ private final NestedSet<Artifact> textualHdrs;
+ private final Optional<Artifact> bridgingHeader;
+ private final NestedSet<PathFragment> includes;
+ private final NestedSet<PathFragment> sdkIncludes;
+ private final NestedSet<SdkFramework> sdkFrameworks;
+ private final NestedSet<SdkFramework> weakSdkFrameworks;
+ private final NestedSet<String> sdkDylibs;
+ private final Optional<PathFragment> packageFragment;
+ private final NestedSet<String> copts;
+ private final NestedSet<String> linkopts;
+ private final NestedSet<CppModuleMap> moduleMapsForDirectDeps;
+ private final boolean enableModules;
+
+ private CompilationAttributes(
+ NestedSet<Artifact> hdrs,
+ NestedSet<Artifact> textualHdrs,
+ Optional<Artifact> bridgingHeader,
+ NestedSet<PathFragment> includes,
+ NestedSet<PathFragment> sdkIncludes,
+ NestedSet<SdkFramework> sdkFrameworks,
+ NestedSet<SdkFramework> weakSdkFrameworks,
+ NestedSet<String> sdkDylibs,
+ Optional<PathFragment> packageFragment,
+ NestedSet<String> copts,
+ NestedSet<String> linkopts,
+ NestedSet<CppModuleMap> moduleMapsForDirectDeps,
+ boolean enableModules) {
+ this.hdrs = hdrs;
+ this.textualHdrs = textualHdrs;
+ this.bridgingHeader = bridgingHeader;
+ this.includes = includes;
+ this.sdkIncludes = sdkIncludes;
+ this.sdkFrameworks = sdkFrameworks;
+ this.weakSdkFrameworks = weakSdkFrameworks;
+ this.sdkDylibs = sdkDylibs;
+ this.packageFragment = packageFragment;
+ this.copts = copts;
+ this.linkopts = linkopts;
+ this.moduleMapsForDirectDeps = moduleMapsForDirectDeps;
+ this.enableModules = enableModules;
+ }
+
+ /**
+ * Returns the headers to be made available for dependents.
+ */
+ public NestedSet<Artifact> hdrs() {
+ return this.hdrs;
+ }
+
+ /**
+ * Returns the headers that cannot be compiled individually.
+ */
+ public NestedSet<Artifact> textualHdrs() {
+ return this.textualHdrs;
+ }
+
+ /**
+ * Returns the bridging header to be used when compiling Swift sources.
+ */
+ public Optional<Artifact> bridgingHeader() {
+ return this.bridgingHeader;
+ }
+
+ /**
+ * Returns the include paths to be made available for compilation.
+ */
+ public NestedSet<PathFragment> includes() {
+ return this.includes;
+ }
+
+ /**
+ * Returns the paths for SDK includes.
+ */
+ public NestedSet<PathFragment> sdkIncludes() {
+ return this.sdkIncludes;
+ }
+
+ /**
+ * Returns the SDK frameworks to link against.
+ */
+ public NestedSet<SdkFramework> sdkFrameworks() {
+ return this.sdkFrameworks;
+ }
+
+ /**
+ * Returns the SDK frameworks to be linked weakly.
+ */
+ public NestedSet<SdkFramework> weakSdkFrameworks() {
+ return this.weakSdkFrameworks;
+ }
+
+ /**
+ * Returns the SDK Dylibs to link against.
+ */
+ public NestedSet<String> sdkDylibs() {
+ return this.sdkDylibs;
+ }
+
+ /**
+ * Returns the exec paths of all header search paths that should be added to this target and
+ * dependers on this target, obtained from the {@code includes} attribute.
+ */
+ public NestedSet<PathFragment> headerSearchPaths(PathFragment genfilesFragment) {
+ NestedSetBuilder<PathFragment> paths = NestedSetBuilder.stableOrder();
+ if (packageFragment.isPresent()) {
+ List<PathFragment> rootFragments =
+ ImmutableList.of(
+ packageFragment.get(), genfilesFragment.getRelative(packageFragment.get()));
+
+ Iterable<PathFragment> relativeIncludes =
+ Iterables.filter(includes(), Predicates.not(PathFragment.IS_ABSOLUTE));
+ for (PathFragment include : relativeIncludes) {
+ for (PathFragment rootFragment : rootFragments) {
+ paths.add(rootFragment.getRelative(include).normalize());
+ }
+ }
+ }
+ return paths.build();
+ }
+
+ /**
+ * Returns the compile-time options.
+ */
+ public NestedSet<String> copts() {
+ return this.copts;
+ }
+
+ /**
+ * Returns the link-time options.
+ */
+ public NestedSet<String> linkopts() {
+ return this.linkopts;
+ }
+
+ /**
+ * Returns the clang module maps of direct dependencies of this rule. These are needed to generate
+ * this rule's module map.
+ */
+ public NestedSet<CppModuleMap> moduleMapsForDirectDeps() {
+ return this.moduleMapsForDirectDeps;
+ }
+
+ /**
+ * Returns whether this target uses language features that require clang modules, such as
+ * {@literal @}import.
+ */
+ public boolean enableModules() {
+ return this.enableModules;
+ }
+}