diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/Template.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/Template.java index fa241652354314..28ecf533120151 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/actions/Template.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/Template.java @@ -48,6 +48,11 @@ public Artifact getTemplateArtifact() { */ protected abstract String getKey(); + @Override + public String toString() { + return getKey(); + } + private static final class ErrorTemplate extends Template { private final IOException e; private final String templateName; diff --git a/src/main/java/com/google/devtools/build/lib/query2/BUILD b/src/main/java/com/google/devtools/build/lib/query2/BUILD index 8e8486c08bf7ea..32b665d0f4a294 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/BUILD +++ b/src/main/java/com/google/devtools/build/lib/query2/BUILD @@ -28,6 +28,8 @@ java_library( "//src/main/java/com/google/devtools/build/lib/actions:commandline_item", "//src/main/java/com/google/devtools/build/lib/actions:file_metadata", "//src/main/java/com/google/devtools/build/lib/analysis:actions/parameter_file_write_action", + "//src/main/java/com/google/devtools/build/lib/analysis:actions/substitution", + "//src/main/java/com/google/devtools/build/lib/analysis:actions/template_expansion_action", "//src/main/java/com/google/devtools/build/lib/analysis:analysis_cluster", "//src/main/java/com/google/devtools/build/lib/analysis:config/build_configuration", "//src/main/java/com/google/devtools/build/lib/analysis:config/build_options", diff --git a/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphTextOutputFormatterCallback.java b/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphTextOutputFormatterCallback.java index 78fe828a0b055b..19b7fb866edec3 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphTextOutputFormatterCallback.java +++ b/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphTextOutputFormatterCallback.java @@ -29,6 +29,8 @@ import com.google.devtools.build.lib.analysis.AspectValue; import com.google.devtools.build.lib.analysis.ConfiguredTargetValue; import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction; +import com.google.devtools.build.lib.analysis.actions.Substitution; +import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction; import com.google.devtools.build.lib.buildeventstream.BuildEvent; import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos; import com.google.devtools.build.lib.events.ExtendedEventHandler; @@ -298,6 +300,23 @@ private void writeAction(ActionAnalysisMetadata action, PrintStream printStream) .append("}\n"); } + if (action instanceof TemplateExpansionAction) { + stringBuilder + .append(" Template: ") + .append(((TemplateExpansionAction) action).getTemplate()) + .append("\n"); + stringBuilder.append(" Substitutions: [\n"); + for (Substitution substitution : ((TemplateExpansionAction) action).getSubstitutions()) { + stringBuilder + .append(" {") + .append(substitution.getKey()) + .append(": ") + .append(substitution.getValue()) + .append("}\n"); + } + stringBuilder.append(" ]\n"); + } + stringBuilder.append('\n'); printStream.write(stringBuilder.toString().getBytes(UTF_8)); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD index 99aa2d00801031..78f260b2af4d70 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD +++ b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD @@ -228,6 +228,8 @@ java_library( "//src/main/java/com/google/devtools/build/lib/actions:thread_state_receiver", "//src/main/java/com/google/devtools/build/lib/actionsketch:action_sketch", "//src/main/java/com/google/devtools/build/lib/analysis:actions/parameter_file_write_action", + "//src/main/java/com/google/devtools/build/lib/analysis:actions/substitution", + "//src/main/java/com/google/devtools/build/lib/analysis:actions/template_expansion_action", "//src/main/java/com/google/devtools/build/lib/analysis:analysis_cluster", "//src/main/java/com/google/devtools/build/lib/analysis:analysis_options", "//src/main/java/com/google/devtools/build/lib/analysis:aspect_collection", diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/ActionGraphDump.java b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/ActionGraphDump.java index 5cc56c92558797..53f687918a77ae 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/ActionGraphDump.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/ActionGraphDump.java @@ -30,6 +30,8 @@ import com.google.devtools.build.lib.analysis.ConfiguredTargetValue; import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction; import com.google.devtools.build.lib.analysis.actions.SpawnAction; +import com.google.devtools.build.lib.analysis.actions.Substitution; +import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction; import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget; import com.google.devtools.build.lib.buildeventstream.BuildEvent; import com.google.devtools.build.lib.collect.nestedset.NestedSet; @@ -235,6 +237,16 @@ private void dumpSingleAction(ConfiguredTarget configuredTarget, ActionAnalysisM knownArtifacts.dataToIdAndStreamOutputProto(action.getPrimaryOutput())); } + if (action instanceof TemplateExpansionAction) { + actionBuilder.setTemplateContent(((TemplateExpansionAction) action).getTemplate().toString()); + for (Substitution substitution : ((TemplateExpansionAction) action).getSubstitutions()) { + actionBuilder.addSubstitutions( + AnalysisProtosV2.KeyValuePair.newBuilder() + .setKey(substitution.getKey()) + .setValue(substitution.getValue())); + } + } + aqueryOutputHandler.outputAction(actionBuilder.build()); } diff --git a/src/main/protobuf/analysis_v2.proto b/src/main/protobuf/analysis_v2.proto index a8289254e86168..b886fde40e7d85 100644 --- a/src/main/protobuf/analysis_v2.proto +++ b/src/main/protobuf/analysis_v2.proto @@ -104,6 +104,14 @@ message Action { // The execution platform for this action. Empty if the action has no // execution platform. string execution_platform = 14; + + // The template content of the action, if it is TemplateExpand action. + string template_content = 15; + + // The list of substitution should be performed on the template. The key is + // the string to be substituted and the value is the string to be substituted + // to. + repeated KeyValuePair substitutions = 16; } // Represents a single target (without configuration information) that is diff --git a/src/test/shell/integration/aquery_test.sh b/src/test/shell/integration/aquery_test.sh index f51ee774ece398..f69ada16fc5a2b 100755 --- a/src/test/shell/integration/aquery_test.sh +++ b/src/test/shell/integration/aquery_test.sh @@ -1406,6 +1406,89 @@ EOF expect_log "-fastbuild: 1" } +function test_aquery_include_template_substitution_for_template_expand_of_py_binary() { + local pkg="${FUNCNAME[0]}" + mkdir -p "$pkg" || fail "mkdir -p $pkg" + cat > "$pkg/BUILD" <<'EOF' +py_binary( + name='foo', + srcs=['foo.py'] +) +EOF + + # aquery returns template content and substitutions in TemplateExpand actions + # of py_binary targets. + QUERY="//$pkg:foo" + + bazel aquery --output=text ${QUERY} > output 2> "$TEST_log" \ + || fail "Expected success" + cat output >> "$TEST_log" + + assert_contains "PYTHON_BINARY = '%python_binary%'" output + assert_contains "{%python_binary%:" output + + bazel aquery --output=jsonproto ${QUERY} > output 2> "$TEST_log" \ + || fail "Expected success" + + assert_contains "\"templateContent\":" output + assert_contains "\"key\": \"%python_binary%\"" output +} + +function test_aquery_include_template_substitution_for_template_expand_action() { + local pkg="${FUNCNAME[0]}" + mkdir -p "$pkg" || fail "mkdir -p $pkg" + + cat > "$pkg/template.txt" <<'EOF' +The token should be substituted: {TOKEN1} +EOF + + cat > "$pkg/test.bzl" <<'EOF' +def test_template(**kwargs): + _test_template( + **kwargs + ) +def _test_template_impl(ctx): + ctx.actions.expand_template( + template = ctx.file.template, + output = ctx.outputs.output, + substitutions = { + "{TOKEN1}": "123456", + }, + ) +_test_template = rule( + implementation = _test_template_impl, + attrs = { + "template": attr.label( + allow_single_file = True, + ), + "output": attr.output(mandatory = True), + }, +) +EOF + + cat > "$pkg/BUILD" <<'EOF' +load('test.bzl', 'test_template') +test_template(name='foo', template='template.txt', output='output.txt') +EOF + + # aquery returns template content and substitutions of TemplateExpand actions. + QUERY="//$pkg:foo" + + bazel aquery --output=text ${QUERY} > output 2> "$TEST_log" \ + || fail "Expected success" + cat output >> "$TEST_log" + + assert_contains "Template: ARTIFACT: $pkg/template.txt" output + assert_contains "{{TOKEN1}: 123456}" output + + bazel aquery --output=jsonproto ${QUERY} > output 2> "$TEST_log" \ + || fail "Expected success" + + assert_contains "\"templateContent\": \"ARTIFACT: $pkg/template.txt\"" output + assert_contains "\"key\": \"{TOKEN1}\"" output + assert_contains "\"value\": \"123456\"" output +} + # Usage: assert_matches expected_pattern actual function assert_matches() { [[ "$2" =~ $1 ]] || fail "Expected to match '$1', was: $2"