aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/apple
diff options
context:
space:
mode:
authorGravatar Chris Parsons <cparsons@google.com>2015-11-25 00:30:11 +0000
committerGravatar Philipp Wollermann <philwo@google.com>2015-11-25 10:00:26 +0000
commitcd0881d8b56024ad2157a893609233761946ba11 (patch)
tree8d51323cabe62793907a23787d835960d652ab80 /src/main/java/com/google/devtools/build/lib/rules/apple
parentf0d78494f35c21426dec1608717e3c4aad72ec40 (diff)
Implementation for xcode_version and xcode_config rules.
-- MOS_MIGRATED_REVID=108659943
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/apple')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java16
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java135
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigProvider.java53
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigRule.java91
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersion.java46
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProvider.java64
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRule.java72
8 files changed, 473 insertions, 6 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java
index 9c2dca458f..f9e9e47626 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java
@@ -39,6 +39,8 @@ public class AppleCommandLineOptions extends FragmentOptions {
"If specified, uses xcode of the given version for relevant build actions. "
+ "If unspecified, uses the executor default version of xcode."
)
+ // TODO(bazel-team): This should be of String type, to allow referencing an alias based
+ // on an xcode_config target.
public DottedVersion xcodeVersion;
@Option(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
index b751a13f6f..b63f4f30de 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
@@ -70,11 +70,13 @@ public class AppleConfiguration extends BuildConfiguration.Fragment {
}
/**
- * Returns the value of the xcode version override build flag, if specified. This is directly
- * derived from --xcode_version_override. Format "x(.y)(.z)" (for example, "7", or "6.4",
- * or "7.0.1").
+ * Returns the value of the xcode version build flag if available. This is obtained directly from
+ * the {@code --xcode_version} build flag.
+ *
+ * <p>Most rules should avoid using this flag value, and instead obtain the appropriate xcode
+ * version from {@link XcodeConfigProvider#getXcodeVersion}.
*/
- public Optional<DottedVersion> getXcodeVersionOverride() {
+ public Optional<DottedVersion> getXcodeVersionOverrideFlag() {
return xcodeVersionOverride;
}
@@ -83,6 +85,7 @@ public class AppleConfiguration extends BuildConfiguration.Fragment {
* for actions pertaining to building ios applications. Keys are variable names and values are
* their corresponding values.
*/
+ // TODO(bazel-team): Repurpose for non-ios platforms.
// TODO(bazel-team): Separate host system and target platform environment
public Map<String, String> getEnvironmentForIosAction() {
ImmutableMap.Builder<String, String> mapBuilder = ImmutableMap.builder();
@@ -98,9 +101,10 @@ public class AppleConfiguration extends BuildConfiguration.Fragment {
*/
public Map<String, String> appleHostSystemEnv() {
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
- if (getXcodeVersionOverride().isPresent()) {
+ // TODO(bazel-team): Use the xcode version from transitive target info instead of the flag.
+ if (getXcodeVersionOverrideFlag().isPresent()) {
builder.put(AppleConfiguration.XCODE_VERSION_ENV_NAME,
- getXcodeVersionOverride().get().toString());
+ getXcodeVersionOverrideFlag().get().toString());
}
return builder.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java
new file mode 100644
index 0000000000..9528bdafea
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java
@@ -0,0 +1,135 @@
+// Copyright 2015 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.apple;
+
+import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
+
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+/**
+ * Implementation for the {@code xcode_config} rule.
+ */
+public class XcodeConfig implements RuleConfiguredTargetFactory {
+
+ @Override
+ public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException {
+ AppleConfiguration configuration = ruleContext.getFragment(AppleConfiguration.class);
+ Optional<DottedVersion> versionOverrideFlag = configuration.getXcodeVersionOverrideFlag();
+
+ DottedVersion targetVersion = resolveExplicitlyDefinedVersion(ruleContext);
+
+ XcodeConfigProvider xcodeConfigProvider;
+ if (targetVersion == null) {
+ if (versionOverrideFlag.isPresent()) {
+ xcodeConfigProvider = new XcodeConfigProvider(versionOverrideFlag.get());
+ } else {
+ xcodeConfigProvider = XcodeConfigProvider.hostSystemDefault();
+ }
+ } else {
+ xcodeConfigProvider = new XcodeConfigProvider(targetVersion);
+ }
+
+ return new RuleConfiguredTargetBuilder(ruleContext)
+ .addProvider(RunfilesProvider.class, RunfilesProvider.EMPTY)
+ .addProvider(XcodeConfigProvider.class, xcodeConfigProvider)
+ .build();
+ }
+
+ /**
+ * Returns the xcode version number corresponding to the {@code --xcode_version} flag, if there
+ * is an available {@code xcode_version} target which recognizes the flag value as either
+ * an official version or an alias. Returns null if no such target is found.
+ */
+ @Nullable private DottedVersion resolveExplicitlyDefinedVersion(RuleContext ruleContext) {
+ AppleConfiguration configuration = ruleContext.getFragment(AppleConfiguration.class);
+ Optional<DottedVersion> versionOverrideFlag = configuration.getXcodeVersionOverrideFlag();
+ if (versionOverrideFlag.isPresent()) {
+ // The version override flag is not necessarily an actual version - it may be a version
+ // alias.
+ DottedVersion explicitVerison =
+ aliasesToVersionMap(ruleContext).get(versionOverrideFlag.get().toString());
+ if (explicitVerison != null) {
+ return explicitVerison;
+ }
+ } else { // No override specified. Use default.
+ XcodeVersionProvider defaultProvider = ruleContext.getPrerequisite(
+ XcodeConfigRule.DEFAULT_ATTR_NAME, Mode.TARGET, XcodeVersionProvider.class);
+
+ if (defaultProvider != null) {
+ return defaultProvider.getVersion();
+ }
+ }
+
+ boolean requireDefinedVersions = ruleContext.attributes().get(
+ XcodeConfigRule.REQUIRE_DEFINED_VERSIONS_ATTR_NAME, BOOLEAN);
+ if (requireDefinedVersions) {
+ ruleContext.ruleError(
+ "xcode version config required an explicitly defined version, but none was available");
+ }
+
+ return null;
+ }
+
+ private static Map<String, DottedVersion> aliasesToVersionMap(RuleContext ruleContext) {
+ Iterable<XcodeVersionProvider> xcodeVersionProviders =
+ ruleContext.getPrerequisites(XcodeConfigRule.VERSIONS_ATTR_NAME, Mode.TARGET,
+ XcodeVersionProvider.class);
+
+ Map<String, DottedVersion> aliasesToVersionMap = Maps.newLinkedHashMap();
+ for (XcodeVersionProvider versionProvider : xcodeVersionProviders) {
+ for (String alias : versionProvider.getAliases()) {
+ if (aliasesToVersionMap.put(alias, versionProvider.getVersion()) != null) {
+ ruleErrorDuplicateAlias(alias, ruleContext);
+ }
+ }
+ if (aliasesToVersionMap.put(
+ versionProvider.getVersion().toString(), versionProvider.getVersion()) != null) {
+ ruleErrorDuplicateAlias(versionProvider.getVersion().toString(), ruleContext);
+ }
+ }
+ return aliasesToVersionMap;
+ }
+
+ private static void ruleErrorDuplicateAlias(String alias, RuleContext ruleContext) {
+ Iterable<XcodeVersionProvider> xcodeVersionProviders =
+ ruleContext.getPrerequisites(XcodeConfigRule.VERSIONS_ATTR_NAME, Mode.TARGET,
+ XcodeVersionProvider.class);
+
+ ImmutableList.Builder<Label> labelsContainingAlias = ImmutableList.builder();
+ for (XcodeVersionProvider versionProvider : xcodeVersionProviders) {
+ if (versionProvider.getAliases().contains(alias)
+ || versionProvider.getVersion().toString().equals(alias)) {
+ labelsContainingAlias.add(versionProvider.getLabel());
+ }
+ }
+ ruleContext.ruleError(String.format(
+ "'%s' is registered to multiple labels (%s) in a single xcode version "
+ + "configuration", alias, Joiner.on(", ").join(labelsContainingAlias.build())));
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigProvider.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigProvider.java
new file mode 100644
index 0000000000..5241e04867
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigProvider.java
@@ -0,0 +1,53 @@
+// Copyright 2015 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.apple;
+
+import com.google.common.base.Optional;
+import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+
+/**
+ * Provides a version of xcode based on a combination of the {@code --xcode_version} build flag
+ * and a {@code xcode_config} target. This version of xcode should be used for selecting apple
+ * toolchains and SDKs.
+ */
+@Immutable
+public final class XcodeConfigProvider implements TransitiveInfoProvider {
+ private final Optional<DottedVersion> xcodeVersion;
+
+ XcodeConfigProvider(DottedVersion xcodeVersion) {
+ this.xcodeVersion = Optional.of(xcodeVersion);
+ }
+
+ private XcodeConfigProvider() {
+ this.xcodeVersion = Optional.absent();
+ }
+
+ /**
+ * Returns a {@link XcodeConfigProvider} with no xcode version specified. The host system
+ * default xcode should be used. See {@link #getXcodeVersion}.
+ */
+ static XcodeConfigProvider hostSystemDefault() {
+ return new XcodeConfigProvider();
+ }
+
+ /**
+ * Returns either an explicit xcode version which should be used in actions which require an
+ * apple toolchain, or {@link Optional#absent} if the host system default should be used.
+ */
+ public Optional<DottedVersion> getXcodeVersion() {
+ return xcodeVersion;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigRule.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigRule.java
new file mode 100644
index 0000000000..b48a651e18
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigRule.java
@@ -0,0 +1,91 @@
+// Copyright 2015 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.apple;
+
+import static com.google.devtools.build.lib.packages.Attribute.attr;
+import static com.google.devtools.build.lib.packages.BuildType.LABEL;
+import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
+import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
+
+import com.google.devtools.build.lib.analysis.BaseRuleClasses;
+import com.google.devtools.build.lib.analysis.RuleDefinition;
+import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.packages.RuleClass;
+import com.google.devtools.build.lib.packages.RuleClass.Builder;
+
+/**
+ * Rule definition for {@code xcode_config} rule.
+ */
+public class XcodeConfigRule implements RuleDefinition {
+
+ static final String DEFAULT_ATTR_NAME = "default";
+ static final String VERSIONS_ATTR_NAME = "versions";
+ static final String REQUIRE_DEFINED_VERSIONS_ATTR_NAME = "require_defined_version";
+
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
+ return builder
+ .requiresConfigurationFragments(AppleConfiguration.class)
+ /* <!-- #BLAZE_RULE(proto_library).ATTRIBUTE(version) -->
+ The default official version of xcode to use.
+ ${SYNOPSIS}
+ The version specified by the provided <code>xcode_version</code> target is to be used if
+ no <code>xcode_version</code> build flag is specified.
+ <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
+ .add(attr(DEFAULT_ATTR_NAME, LABEL)
+ .allowedRuleClasses("xcode_version")
+ .allowedFileTypes())
+ /* <!-- #BLAZE_RULE(proto_library).ATTRIBUTE(version) -->
+ Accepted <code>xcode_version<code> targets that may be used.
+ ${SYNOPSIS}
+ If the value of the <code>xcode_version</code> build flag matches one of the aliases
+ or version number of any of the given <code>xcode_version</code> targets, the matching
+ target will be used.
+ <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
+ .add(attr(VERSIONS_ATTR_NAME, LABEL_LIST)
+ .allowedRuleClasses("xcode_version")
+ .allowedFileTypes())
+ /* <!-- #BLAZE_RULE(proto_library).ATTRIBUTE(version) -->
+ Whether to require the build's xcode version match one of the declared targets.
+ ${SYNOPSIS}
+ If true, this will raise an error if either the <code>xcode_version</code> flag value
+ or <code>default</code> attribute value do not match one of the versions declared
+ among <code>xcode_verison</code> targets.
+ <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
+ .add(attr(REQUIRE_DEFINED_VERSIONS_ATTR_NAME, BOOLEAN).value(false))
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("xcode_config")
+ .ancestors(BaseRuleClasses.BaseRule.class)
+ .factoryClass(XcodeConfig.class)
+ .build();
+ }
+}
+
+/*<!-- #BLAZE_RULE (NAME = xcode_config, TYPE = OTHER, FAMILY = Workspace)[GENERIC_RULE] -->
+
+${ATTRIBUTE_SIGNATURE}
+
+<p>A single target of this rule can be referenced by the <code>--xcode_config</code> build flag to
+translate the <code>--xcode_version</code> flag into an accepted official xcode version. This
+allows selection of a an official xcode version from a number of registered aliases.</p>
+
+${ATTRIBUTE_DEFINITION}
+
+<!-- #END_BLAZE_RULE -->*/
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersion.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersion.java
new file mode 100644
index 0000000000..2b363e6c62
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersion.java
@@ -0,0 +1,46 @@
+// Copyright 2015 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.apple;
+
+import static com.google.devtools.build.lib.syntax.Type.STRING;
+import static com.google.devtools.build.lib.syntax.Type.STRING_LIST;
+
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
+
+import java.util.List;
+
+/**
+ * Implementation for the {@code xcode_version} rule.
+ */
+public class XcodeVersion implements RuleConfiguredTargetFactory {
+
+ @Override
+ public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException {
+ DottedVersion version = DottedVersion.fromString(
+ ruleContext.attributes().get(XcodeVersionRule.VERSION_ATTR_NAME, STRING));
+ List<String> aliases =
+ ruleContext.attributes().get(XcodeVersionRule.ALIASES_ATTR_NAME, STRING_LIST);
+
+ return new RuleConfiguredTargetBuilder(ruleContext)
+ .addProvider(RunfilesProvider.class, RunfilesProvider.EMPTY)
+ .addProvider(XcodeVersionProvider.class,
+ new XcodeVersionProvider(ruleContext.getLabel(), version, aliases))
+ .build();
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProvider.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProvider.java
new file mode 100644
index 0000000000..f7b15b60d6
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProvider.java
@@ -0,0 +1,64 @@
+// Copyright 2015 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.apple;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+
+import java.util.List;
+
+/**
+ * Provides the information in a single {@code xcode_version} target. A single target of this rule
+ * contains an official version label decided by Apple and a number of supported aliases one might
+ * use to reference this version.
+ *
+ * <p>For example, one may want to reference official xcode version 7.0.1 using the "7" or
+ * "7.0" aliases.
+ */
+@Immutable
+public final class XcodeVersionProvider implements TransitiveInfoProvider {
+ private final Label label;
+ private final DottedVersion version;
+ private final ImmutableList<String> aliases;
+
+ XcodeVersionProvider(Label label, DottedVersion version, List<String> aliases) {
+ this.label = label;
+ this.version = version;
+ this.aliases = ImmutableList.copyOf(aliases);
+ }
+
+ /**
+ * Returns the label of the owning target of this provider.
+ */
+ public Label getLabel() {
+ return label;
+ }
+
+ /**
+ * Returns the official xcode version the owning {@code xcode_version} target is referencing.
+ */
+ public DottedVersion getVersion() {
+ return version;
+ }
+
+ /**
+ * Returns the accepted string aliases for this xcode version.
+ */
+ public List<String> getAliases() {
+ return aliases;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRule.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRule.java
new file mode 100644
index 0000000000..0248fce3d7
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRule.java
@@ -0,0 +1,72 @@
+// Copyright 2015 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.apple;
+
+import static com.google.devtools.build.lib.packages.Attribute.attr;
+import static com.google.devtools.build.lib.syntax.Type.STRING;
+import static com.google.devtools.build.lib.syntax.Type.STRING_LIST;
+
+import com.google.devtools.build.lib.analysis.BaseRuleClasses;
+import com.google.devtools.build.lib.analysis.RuleDefinition;
+import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.packages.RuleClass;
+import com.google.devtools.build.lib.packages.RuleClass.Builder;
+
+/**
+ * Rule definition for {@code xcode_version} rule.
+ */
+public class XcodeVersionRule implements RuleDefinition {
+
+ static final String VERSION_ATTR_NAME = "version";
+ static final String ALIASES_ATTR_NAME = "aliases";
+
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
+ return builder
+ .requiresConfigurationFragments(AppleConfiguration.class)
+ /* <!-- #BLAZE_RULE(proto_library).ATTRIBUTE(version) -->
+ The official version number of a version of Xcode.
+ <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
+ .add(attr(VERSION_ATTR_NAME, STRING).mandatory())
+ /* <!-- #BLAZE_RULE(proto_library).ATTRIBUTE(version) -->
+ Accepted aliases for this version of Xcode.
+ ${SYNOPSIS}
+ If the value of the <code>xcode_version</code> build flag matches any of the given
+ alias strings, this xcode version will be used.
+ <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
+ .add(attr(ALIASES_ATTR_NAME, STRING_LIST))
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("xcode_version")
+ .ancestors(BaseRuleClasses.BaseRule.class)
+ .factoryClass(XcodeVersion.class)
+ .build();
+ }
+}
+
+/*<!-- #BLAZE_RULE (NAME = xcode_version, TYPE = OTHER, FAMILY = Workspace)[GENERIC_RULE] -->
+
+${ATTRIBUTE_SIGNATURE}
+
+<p>Represents a single official xcode version with acceptable aliases for that xcode version.
+See the <code>xcode_config</code> rule.</p>
+
+${ATTRIBUTE_DEFINITION}
+
+<!-- #END_BLAZE_RULE -->*/