Skip to content

Commit

Permalink
Bazel sh_* rules are documented and cleared up.
Browse files Browse the repository at this point in the history
 - Unused attribute bash_version is removed from all sh_* rules.
 - ShTest.java is deleted. Shell binary and test rules have the same implementation.

--
MOS_MIGRATED_REVID=88434794
  • Loading branch information
Googler authored and hanwen committed Mar 13, 2015
1 parent 2aeeee2 commit ffb89f4
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
// limitations under the License.
package com.google.devtools.build.lib.bazel.rules.sh;

import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.Type.STRING;

import com.google.devtools.build.lib.analysis.BlazeRule;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
Expand All @@ -33,9 +30,6 @@
public final class BazelShBinaryRule implements RuleDefinition {
@Override
public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
return builder.add(
attr("bash_version", STRING)
.value(BazelShRuleClasses.DEFAULT_BASH_VERSION)
.allowedValues(BazelShRuleClasses.BASH_VERSION_ALLOWED_VALUES)).build();
return builder.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,29 +33,16 @@ public final class BazelShLibraryRule implements RuleDefinition {
@Override
public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
return builder
/* <!-- #BLAZE_RULE(sh_library).ATTRIBUTE(deps) -->
The list of other targets to be aggregated in to this "library" target.
<i>(List of <a href="build-ref.html#labels">labels</a>; optional)</i><br/>
See general comments about <code>deps</code>
at <a href="#common-attributes">Attributes common to all build rules</a>.
You should use this attribute to list other
<code>sh_library</code> or <code>proto_library</code> rules that provide
interpreted program source code depended on by the code in
<code>srcs</code>. If you depend on a <code>proto_library</code> target,
the proto sources in that target will be included in this library, but
no generated files will be built.
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */

/* <!-- #BLAZE_RULE(sh_library).ATTRIBUTE(srcs) -->
The list of input files.
<i>(List of <a href="build-ref.html#labels">labels</a>,
optional)</i><br/>
You should use this attribute to list interpreted program
source files that belong to this package, such as additional
files containing Bourne shell subroutines, loaded via the shell's
<code>source</code> or <code>.</code> command.
${SYNOPSIS}
<p>
This attribute should be used to list shell script source files that belong to
this library. Scripts can load other scripts using the shell's <code>source</code>
or <code>.</code> command.
</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
.override(attr("srcs", LABEL_LIST).legacyAllowAnyFileType())
.override(attr("srcs", LABEL_LIST).allowedFileTypes(BazelShRuleClasses.SH_FILES))
.build();
}
}
Expand All @@ -69,31 +56,24 @@ public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
"library" consisting of related scripts&mdash;programs in an
interpreted language that does not require compilation or linking,
such as the Bourne shell&mdash;and any data those programs need at
run-time. Such "libraries" can then be used from
run-time. Such "libraries" can then be used from
the <code>data</code> attribute of one or
more <code>sh_binary</code> rules.
</p>
<p>
Historically, a second use was to aggregate a collection of data files
together, to ensure that they are available at runtime in
the <code>.runfiles</code> area of one or more <code>*_binary</code>
rules (not necessarily <code>sh_binary</code>).
However, the <a href="#filegroup"><code>filegroup()</code></a> rule
should be used now; it is intended to replace this use of
<code>sh_library</code>.
You can use the <a href="#filegroup"><code>filegroup</code></a> rule to aggregate data files.
</p>
<p>
In interpreted programming languages, there's not always a clear
distinction between "code" and "data": after all, the program is
just "data" from the interpreter's point of view. For this reason
(and historical accident) this rule has three attributes which are
all essentially equivalent: <code>srcs</code>, <code>deps</code>
and <code>data</code>.
The recommended usage of each attribute is mentioned below. The
current implementation does not distinguish the elements of these lists.
All three attributes accept rules, source files and derived files.
just "data" from the interpreter's point of view. For this reason
this rule has three attributes which are all essentially equivalent:
<code>srcs</code>, <code>deps</code> and <code>data</code>.
The current implementation does not distinguish between the elements of these lists.
All three attributes accept rules, source files and generated files.
It is however good practice to use the attributes for their usual purpose (as with other rules).
</p>
${ATTRIBUTE_DEFINITION}
Expand All @@ -104,7 +84,7 @@ public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
sh_library(
name = "foo",
data = [
":foo_service_script", # a sh_binary with srcs
":foo_service_script", # an sh_binary with srcs
":deploy_foo", # another sh_binary with srcs
],
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,22 @@
package com.google.devtools.build.lib.bazel.rules.sh;

import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fromTemplates;
import static com.google.devtools.build.lib.packages.Type.LABEL_LIST;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.BlazeRule;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.packages.Attribute.AllowedValueSet;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction;
import com.google.devtools.build.lib.packages.PredicateWithMessage;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder;
import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.FileTypeSet;

import java.util.Collection;
import java.util.Map;
Expand All @@ -42,7 +43,9 @@
public final class BazelShRuleClasses {

static final Collection<String> ALLOWED_RULES_IN_DEPS_WITH_WARNING = ImmutableSet.of(
"filegroup", "Fileset", "genrule", "sh_binary", "sh_test", "test_suite");
"filegroup", "genrule", "sh_binary", "sh_test", "test_suite");

static final FileTypeSet SH_FILES = FileTypeSet.of(FileType.of(".sh"));

/**
* Common attributes for shell rules.
Expand All @@ -54,21 +57,38 @@ public static final class ShRule implements RuleDefinition {
@Override
public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
return builder
.add(attr("srcs", LABEL_LIST).mandatory().legacyAllowAnyFileType())
/* <!-- #BLAZE_RULE($sh_target).ATTRIBUTE(srcs) -->
The file containing the shell script.
${SYNOPSIS}
<p>
This attribute must be a singleton list, whose element is the shell script.
This script must be executable, and may be a source file or a generated file.
All other files required at runtime (whether scripts or data) belong in the
<code>data</code> attribute.
</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(attr("srcs", LABEL_LIST)
.mandatory()
.allowedFileTypes(SH_FILES))
/* <!-- #BLAZE_RULE($sh_target).ATTRIBUTE(deps) -->
The list of "library" targets to be aggregated into this target.
${SYNOPSIS}
See general comments about <code>deps</code>
at <a href="#common-attributes.deps">Attributes common to all build rules</a>.
<p>
This attribute should be used to list other <code>sh_library</code> rules that provide
interpreted program source code depended on by the code in <code>srcs</code>. The files
provided by these rules will be present among the <code>runfiles</code> of this target.
</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.override(builder.copy("deps")
.allowedRuleClasses("sh_library", "proto_library")
.allowedRuleClasses("sh_library")
.allowedRuleClassesWithWarning(ALLOWED_RULES_IN_DEPS_WITH_WARNING)
.allowedFileTypes())
.build();
}
}

/**
* Defines the file name of an sh_binary's implicit .sar (script package) output.
*/
static final ImplicitOutputsFunction SAR_PACKAGE_FILENAME =
fromTemplates("%{name}.sar");

/**
* Convenience structure for the bash dependency combinations defined
* by BASH_BINARY_BINDINGS.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
// limitations under the License.
package com.google.devtools.build.lib.bazel.rules.sh;

import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.Type.STRING;

import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.BlazeRule;
import com.google.devtools.build.lib.analysis.RuleDefinition;
Expand All @@ -31,14 +28,10 @@
@BlazeRule(name = "sh_test",
type = RuleClassType.TEST,
ancestors = { ShRule.class, BaseRuleClasses.TestBaseRule.class },
factoryClass = ShTest.class)
factoryClass = ShBinary.class)
public final class BazelShTestRule implements RuleDefinition {
@Override
public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
return builder
.add(attr("bash_version", STRING)
.value(BazelShRuleClasses.DEFAULT_BASH_VERSION)
.allowedValues(BazelShRuleClasses.BASH_VERSION_ALLOWED_VALUES))
.build();
return builder.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,19 @@ public ConfiguredTarget create(RuleContext ruleContext) {
}

Artifact symlink = ruleContext.createOutputArtifact();
// Note that src is used as the executable script too
Artifact src = srcs.get(0);
Artifact executableScript = getExecutableScript(ruleContext, src);
// The interpretation of this deceptively simple yet incredibly generic rule is complicated
// by the distinction between targets and (not properly encapsulated) artifacts. It depends
// on the notion of other rule's "files-to-build" sets, which are undocumented, making it
// impossible to give a precise definition of what this rule does in all cases (e.g. what
// happens when srcs = ['x', 'y'] but 'x' is an empty filegroup?). This is a pervasive
// problem in Blaze.
ruleContext.registerAction(
new ExecutableSymlinkAction(ruleContext.getActionOwner(), executableScript, symlink));
new ExecutableSymlinkAction(ruleContext.getActionOwner(), src, symlink));

NestedSet<Artifact> filesToBuild = NestedSetBuilder.<Artifact>stableOrder()
.add(src)
.add(executableScript) // May be the same as src, in which case set semantics apply.
.add(symlink)
.build();
Runfiles runfiles = new Runfiles.Builder()
Expand All @@ -69,14 +68,4 @@ public ConfiguredTarget create(RuleContext ruleContext) {
.addProvider(RunfilesProvider.class, RunfilesProvider.simple(runfiles))
.build();
}

/**
* Hook for sh_test to provide the executable.
*
* @param ruleContext
* @param src
*/
protected Artifact getExecutableScript(RuleContext ruleContext, Artifact src) {
return src;
}
}

This file was deleted.

0 comments on commit ffb89f4

Please sign in to comment.