| Index: tools/gn/target_generator.cc
|
| diff --git a/tools/gn/target_generator.cc b/tools/gn/target_generator.cc
|
| index 12d09fca1527092d16ff2b249a47e72ce739fe14..4821da6097c0b47d06064495fde83500004b11cc 100644
|
| --- a/tools/gn/target_generator.cc
|
| +++ b/tools/gn/target_generator.cc
|
| @@ -217,25 +217,69 @@ void TargetGenerator::FillDependencies() {
|
| return;
|
| }
|
|
|
| -void TargetGenerator::FillOutputs() {
|
| +void TargetGenerator::FillOutputs(bool allow_substitutions) {
|
| const Value* value = scope_->GetValue(variables::kOutputs, true);
|
| if (!value)
|
| return;
|
|
|
| - std::vector<std::string>& outputs = target_->action_values().outputs();
|
| - if (!ExtractListOfStringValues(*value, &outputs, err_))
|
| + SubstitutionList& outputs = target_->action_values().outputs();
|
| + if (!outputs.Parse(*value, err_))
|
| + return;
|
| +
|
| + if (!allow_substitutions) {
|
| + // Verify no substitutions were actually used.
|
| + if (!outputs.required_types().empty()) {
|
| + *err_ = Err(*value, "Source expansions not allowed here.",
|
| + "The outputs of this target used source {{expansions}} but this "
|
| + "targe type\ndoesn't support them. Just express the outputs "
|
| + "literally.");
|
| + return;
|
| + }
|
| + }
|
| +
|
| + // Check the substitutions used are valid for this purpose.
|
| + if (!EnsureValidSourcesSubstitutions(outputs.required_types(),
|
| + value->origin(), err_))
|
| return;
|
|
|
| // Validate that outputs are in the output dir.
|
| - bool allow_templates = target_->output_type() == Target::ACTION_FOREACH ||
|
| - target_->output_type() == Target::COPY_FILES;
|
| - CHECK(outputs.size() == value->list_value().size());
|
| - for (size_t i = 0; i < outputs.size(); i++) {
|
| + CHECK(outputs.list().size() == value->list_value().size());
|
| + for (size_t i = 0; i < outputs.list().size(); i++) {
|
| + if (!EnsureSubstitutionIsInOutputDir(outputs.list()[i],
|
| + value->list_value()[i]))
|
| + return;
|
| + }
|
| +}
|
| +
|
| +bool TargetGenerator::EnsureSubstitutionIsInOutputDir(
|
| + const SubstitutionPattern& pattern,
|
| + const Value& original_value) {
|
| + if (pattern.ranges().empty()) {
|
| + // Pattern is empty, error out (this prevents weirdness below).
|
| + *err_ = Err(original_value, "This has an empty value in it.");
|
| + return false;
|
| + }
|
| +
|
| + if (pattern.ranges()[0].type == SUBSTITUTION_LITERAL) {
|
| + // If the first thing is a literal, it must start with the output dir.
|
| if (!EnsureStringIsInOutputDir(
|
| GetBuildSettings()->build_dir(),
|
| - outputs[i], value->list_value()[i], allow_templates, err_))
|
| - return;
|
| + pattern.ranges()[0].literal, original_value, err_))
|
| + return false;
|
| + } else {
|
| + // Otherwise, the first subrange must be a pattern that expands to
|
| + // something in the output directory.
|
| + if (!SubstitutionIsInOutputDir(pattern.ranges()[0].type)) {
|
| + *err_ = Err(original_value,
|
| + "File is not inside output directory.",
|
| + "The given file should be in the output directory. Normally you\n"
|
| + "would specify\n\"$target_out_dir/foo\" or "
|
| + "\"{{source_gen_dir}}/foo\".");
|
| + return false;
|
| + }
|
| }
|
| +
|
| + return true;
|
| }
|
|
|
| void TargetGenerator::FillGenericConfigs(const char* var_name,
|
|
|