// Copyright 2017 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.genrule; import static com.google.devtools.build.lib.packages.Attribute.attr; import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST; import static com.google.devtools.build.lib.packages.BuildType.LICENSE; import static com.google.devtools.build.lib.packages.BuildType.OUTPUT_LIST; import static com.google.devtools.build.lib.syntax.Type.BOOLEAN; import static com.google.devtools.build.lib.syntax.Type.STRING; 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.analysis.TemplateVariableInfo; import com.google.devtools.build.lib.analysis.config.HostTransition; import com.google.devtools.build.lib.packages.Attribute; import com.google.devtools.build.lib.packages.Attribute.ComputedDefault; import com.google.devtools.build.lib.packages.Attribute.LabelLateBoundDefault; import com.google.devtools.build.lib.packages.AttributeMap; import com.google.devtools.build.lib.packages.BuildType; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; import com.google.devtools.build.lib.rules.cpp.CppConfiguration; import com.google.devtools.build.lib.rules.cpp.CppRuleClasses; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.FileTypeSet; /** * Rule definition for the genrule rule, intended to be inherited by specific GenRule * implementations. Implementations will need to include any needed additional dependencies, such * as a setup script target. */ public class GenRuleBaseRule implements RuleDefinition { /** * Late-bound dependency on the C++ toolchain iff the genrule has make variables that need * that toolchain. */ public static LabelLateBoundDefault> ccToolchainAttribute(RuleDefinitionEnvironment env) { return LabelLateBoundDefault.fromTargetConfiguration( CppConfiguration.class, env.getToolsLabel(CppRuleClasses.CROSSTOOL_LABEL), // null guards are needed for LateBoundAttributeTest (rule, attributes, cppConfig) -> attributes != null && attributes.get("cmd", Type.STRING) != null && GenRuleBase.requiresCrosstool(attributes.get("cmd", Type.STRING)) ? CppRuleClasses.ccToolchainAttribute(env).resolve(rule, attributes, cppConfig) : null); } /** Computed dependency on the C++ toolchain type. */ public static ComputedDefault ccToolchainTypeAttribute(RuleDefinitionEnvironment env) { return new ComputedDefault("cmd") { @Override public Object getDefault(AttributeMap rule) { return GenRuleBase.requiresCrosstool(rule.get("cmd", Type.STRING)) ? CppRuleClasses.ccToolchainTypeAttribute(env) : null; } }; } @Override public RuleClass build( RuleClass.Builder builder, RuleDefinitionEnvironment env) { return builder /* A list of inputs for this rule, such as source files to process.
This attributes is not suitable to list tools executed by the cmd
; use
the tools
attribute for them instead.
The build system ensures these prerequisites are built before running the genrule
command; they are built using the same configuration as the original build request. The
names of the files of these prerequisites are available to the command as a
space-separated list in $(SRCS)
; alternatively the path of an individual
srcs
target //x:y
can be obtained using $(location
//x:y)
, or using $<
provided it's the only entry in
//srcs
.
The build system ensures these prerequisites are built before running the genrule command;
they are built using the host
configuration, since these tools are executed as part of the build. The path of an
individual tools
target //x:y
can be obtained using
$(location //x:y)
.
Any *_binary
or tool to be executed by cmd
must appear in this
list, not in srcs
, to ensure they are built in the correct configuration.
Output files must not cross package boundaries. Output filenames are interpreted as relative to the package.
If the executable
flag is set, outs
must contain exactly one
label.
$(location label)
and of
$(locations label)
.
Note that outs
are not included in this substitution. Output files
are always generated into a predictable location (available via $(@D)
,
$@
, $(OUTS)
or $(location output_name)
;
see below).
$(JAVA)
, $(JAVAC)
and
$(JAVABASE)
expand under the host configuration, so Java invocations
that run as part of a build step can correctly load shared libraries and other
dependencies.
The command may refer to *_binary
targets; it should use a label for this. The following
variables are available within the cmd
sublanguage:
If set to 1, this option causes output files to be written into the bin
directory instead of the genfiles
directory.
If set to 1, this option force this genrule
to run with the
standalone
strategy, without sandboxing.
This is equivalent to providing 'local' as a tag (tags=["local"]
). The
local strategy is applied if either one is specified.
The --genrule_strategy
option value local
overrides this attribute.
*/
.add(attr("local", BOOLEAN).value(false))
/*
A progress message.
A progress message that will be printed as this build step is executed. By default, the
message is "Generating output" (or something equally bland) but you may provide a
more specific one. Use this attribute instead of echo
or other print
statements in your cmd
command, as this allows the build tool to control
whether such progress messages are printed or not.
common attributes
*/
.add(attr("output_licenses", LICENSE))
/*
Declare output to be executable.
Setting this flag to 1 means the output is an executable file and can be run using the
run
command. The genrule must produce exactly one output in this case.
If this attribute is set, run
will try executing the file regardless of
its content.
Declaring data dependencies for the generated executable is not supported.
*/ .add( attr("executable", BOOLEAN) .value(false) .nonconfigurable( "Used in computed default for $is_executable, which is itself non-configurable" + " (and thus expects its dependencies to be non-configurable), because" + " $is_executable is called from RunCommand.isExecutable, which has no" + " configuration context")) .add( attr("$is_executable", BOOLEAN) .nonconfigurable("Called from RunCommand.isExecutable, which takes a Target") .value( new Attribute.ComputedDefault() { @Override public Object getDefault(AttributeMap rule) { return (rule.get("outs", BuildType.OUTPUT_LIST).size() == 1) && rule.get("executable", BOOLEAN); } })) // This is a misfeature, so don't document it. We would like to get rid of it, but that // would require a cleanup of existing rules. .add(attr("heuristic_label_expansion", BOOLEAN).value(false)) .removeAttribute("data") .removeAttribute("deps") .build(); } @Override public RuleDefinition.Metadata getMetadata() { return RuleDefinition.Metadata.builder() .name("$genrule_base") .type(RuleClassType.ABSTRACT) .ancestors(BaseRuleClasses.RuleBase.class) .build(); } }