16d528ed9Sopenharmony_ci// Copyright 2018 The Chromium Authors. All rights reserved. 26d528ed9Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 36d528ed9Sopenharmony_ci// found in the LICENSE file. 46d528ed9Sopenharmony_ci 56d528ed9Sopenharmony_ci#include "gn/generated_file_target_generator.h" 66d528ed9Sopenharmony_ci 76d528ed9Sopenharmony_ci#include "gn/err.h" 86d528ed9Sopenharmony_ci#include "gn/filesystem_utils.h" 96d528ed9Sopenharmony_ci#include "gn/parse_tree.h" 106d528ed9Sopenharmony_ci#include "gn/scope.h" 116d528ed9Sopenharmony_ci#include "gn/target.h" 126d528ed9Sopenharmony_ci#include "gn/variables.h" 136d528ed9Sopenharmony_ci 146d528ed9Sopenharmony_ciGeneratedFileTargetGenerator::GeneratedFileTargetGenerator( 156d528ed9Sopenharmony_ci Target* target, 166d528ed9Sopenharmony_ci Scope* scope, 176d528ed9Sopenharmony_ci const FunctionCallNode* function_call, 186d528ed9Sopenharmony_ci Target::OutputType type, 196d528ed9Sopenharmony_ci Err* err) 206d528ed9Sopenharmony_ci : TargetGenerator(target, scope, function_call, err), output_type_(type) {} 216d528ed9Sopenharmony_ci 226d528ed9Sopenharmony_ciGeneratedFileTargetGenerator::~GeneratedFileTargetGenerator() = default; 236d528ed9Sopenharmony_ci 246d528ed9Sopenharmony_civoid GeneratedFileTargetGenerator::DoRun() { 256d528ed9Sopenharmony_ci target_->set_output_type(output_type_); 266d528ed9Sopenharmony_ci 276d528ed9Sopenharmony_ci if (!FillOutputs(false)) 286d528ed9Sopenharmony_ci return; 296d528ed9Sopenharmony_ci if (target_->action_values().outputs().list().size() != 1) { 306d528ed9Sopenharmony_ci *err_ = Err( 316d528ed9Sopenharmony_ci function_call_, "generated_file target must have exactly one output.", 326d528ed9Sopenharmony_ci "You must specify exactly one value in the \"outputs\" array for the " 336d528ed9Sopenharmony_ci "destination of the write\n(see \"gn help generated_file\")."); 346d528ed9Sopenharmony_ci return; 356d528ed9Sopenharmony_ci } 366d528ed9Sopenharmony_ci 376d528ed9Sopenharmony_ci if (!FillContents()) 386d528ed9Sopenharmony_ci return; 396d528ed9Sopenharmony_ci if (!FillDataKeys()) 406d528ed9Sopenharmony_ci return; 416d528ed9Sopenharmony_ci 426d528ed9Sopenharmony_ci // One of data and data_keys should be defined. 436d528ed9Sopenharmony_ci if (!contents_defined_ && !data_keys_defined_) { 446d528ed9Sopenharmony_ci *err_ = Err( 456d528ed9Sopenharmony_ci function_call_, "Either contents or data_keys should be set.", 466d528ed9Sopenharmony_ci "The generated_file target requires either the \"contents\" variable " 476d528ed9Sopenharmony_ci "or the \"data_keys\" variable be set. See \"gn help " 486d528ed9Sopenharmony_ci "generated_file\"."); 496d528ed9Sopenharmony_ci return; 506d528ed9Sopenharmony_ci } 516d528ed9Sopenharmony_ci 526d528ed9Sopenharmony_ci if (!FillRebase()) 536d528ed9Sopenharmony_ci return; 546d528ed9Sopenharmony_ci if (!FillWalkKeys()) 556d528ed9Sopenharmony_ci return; 566d528ed9Sopenharmony_ci 576d528ed9Sopenharmony_ci if (!FillOutputConversion()) 586d528ed9Sopenharmony_ci return; 596d528ed9Sopenharmony_ci} 606d528ed9Sopenharmony_ci 616d528ed9Sopenharmony_cibool GeneratedFileTargetGenerator::FillContents() { 626d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(variables::kWriteValueContents, true); 636d528ed9Sopenharmony_ci if (!value) 646d528ed9Sopenharmony_ci return true; 656d528ed9Sopenharmony_ci target_->set_contents(*value); 666d528ed9Sopenharmony_ci contents_defined_ = true; 676d528ed9Sopenharmony_ci return true; 686d528ed9Sopenharmony_ci} 696d528ed9Sopenharmony_ci 706d528ed9Sopenharmony_cibool GeneratedFileTargetGenerator::IsMetadataCollectionTarget( 716d528ed9Sopenharmony_ci std::string_view variable, 726d528ed9Sopenharmony_ci const ParseNode* origin) { 736d528ed9Sopenharmony_ci if (contents_defined_) { 746d528ed9Sopenharmony_ci *err_ = 756d528ed9Sopenharmony_ci Err(origin, std::string(variable) + " won't be used.", 766d528ed9Sopenharmony_ci "\"contents\" is defined on this target, and so setting " + 776d528ed9Sopenharmony_ci std::string(variable) + 786d528ed9Sopenharmony_ci " will have no effect as no metadata collection will occur."); 796d528ed9Sopenharmony_ci return false; 806d528ed9Sopenharmony_ci } 816d528ed9Sopenharmony_ci return true; 826d528ed9Sopenharmony_ci} 836d528ed9Sopenharmony_ci 846d528ed9Sopenharmony_cibool GeneratedFileTargetGenerator::FillOutputConversion() { 856d528ed9Sopenharmony_ci const Value* value = 866d528ed9Sopenharmony_ci scope_->GetValue(variables::kWriteOutputConversion, true); 876d528ed9Sopenharmony_ci if (!value) { 886d528ed9Sopenharmony_ci target_->set_output_conversion(Value(function_call_, "")); 896d528ed9Sopenharmony_ci return true; 906d528ed9Sopenharmony_ci } 916d528ed9Sopenharmony_ci if (!value->VerifyTypeIs(Value::STRING, err_)) 926d528ed9Sopenharmony_ci return false; 936d528ed9Sopenharmony_ci 946d528ed9Sopenharmony_ci // Otherwise, the value itself will be checked when the conversion is done. 956d528ed9Sopenharmony_ci target_->set_output_conversion(*value); 966d528ed9Sopenharmony_ci return true; 976d528ed9Sopenharmony_ci} 986d528ed9Sopenharmony_ci 996d528ed9Sopenharmony_cibool GeneratedFileTargetGenerator::FillRebase() { 1006d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(variables::kRebase, true); 1016d528ed9Sopenharmony_ci if (!value) 1026d528ed9Sopenharmony_ci return true; 1036d528ed9Sopenharmony_ci if (!IsMetadataCollectionTarget(variables::kRebase, value->origin())) 1046d528ed9Sopenharmony_ci return false; 1056d528ed9Sopenharmony_ci if (!value->VerifyTypeIs(Value::STRING, err_)) 1066d528ed9Sopenharmony_ci return false; 1076d528ed9Sopenharmony_ci 1086d528ed9Sopenharmony_ci if (value->string_value().empty()) 1096d528ed9Sopenharmony_ci return true; // Treat empty string as the default and do nothing. 1106d528ed9Sopenharmony_ci 1116d528ed9Sopenharmony_ci const BuildSettings* build_settings = scope_->settings()->build_settings(); 1126d528ed9Sopenharmony_ci SourceDir dir = scope_->GetSourceDir().ResolveRelativeDir( 1136d528ed9Sopenharmony_ci *value, err_, build_settings->root_path_utf8()); 1146d528ed9Sopenharmony_ci if (err_->has_error()) 1156d528ed9Sopenharmony_ci return false; 1166d528ed9Sopenharmony_ci 1176d528ed9Sopenharmony_ci target_->set_rebase(dir); 1186d528ed9Sopenharmony_ci return true; 1196d528ed9Sopenharmony_ci} 1206d528ed9Sopenharmony_ci 1216d528ed9Sopenharmony_cibool GeneratedFileTargetGenerator::FillDataKeys() { 1226d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(variables::kDataKeys, true); 1236d528ed9Sopenharmony_ci if (!value) 1246d528ed9Sopenharmony_ci return true; 1256d528ed9Sopenharmony_ci if (!IsMetadataCollectionTarget(variables::kDataKeys, value->origin())) 1266d528ed9Sopenharmony_ci return false; 1276d528ed9Sopenharmony_ci if (!value->VerifyTypeIs(Value::LIST, err_)) 1286d528ed9Sopenharmony_ci return false; 1296d528ed9Sopenharmony_ci 1306d528ed9Sopenharmony_ci for (const Value& v : value->list_value()) { 1316d528ed9Sopenharmony_ci // Keys must be strings. 1326d528ed9Sopenharmony_ci if (!v.VerifyTypeIs(Value::STRING, err_)) 1336d528ed9Sopenharmony_ci return false; 1346d528ed9Sopenharmony_ci target_->data_keys().push_back(v.string_value()); 1356d528ed9Sopenharmony_ci } 1366d528ed9Sopenharmony_ci 1376d528ed9Sopenharmony_ci data_keys_defined_ = true; 1386d528ed9Sopenharmony_ci return true; 1396d528ed9Sopenharmony_ci} 1406d528ed9Sopenharmony_ci 1416d528ed9Sopenharmony_cibool GeneratedFileTargetGenerator::FillWalkKeys() { 1426d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(variables::kWalkKeys, true); 1436d528ed9Sopenharmony_ci // If we define this and contents, that's an error. 1446d528ed9Sopenharmony_ci if (value && 1456d528ed9Sopenharmony_ci !IsMetadataCollectionTarget(variables::kWalkKeys, value->origin())) 1466d528ed9Sopenharmony_ci return false; 1476d528ed9Sopenharmony_ci 1486d528ed9Sopenharmony_ci // If we don't define it, we want the default value which is a list 1496d528ed9Sopenharmony_ci // containing the empty string. 1506d528ed9Sopenharmony_ci if (!value) { 1516d528ed9Sopenharmony_ci target_->walk_keys().push_back(""); 1526d528ed9Sopenharmony_ci return true; 1536d528ed9Sopenharmony_ci } 1546d528ed9Sopenharmony_ci 1556d528ed9Sopenharmony_ci // Otherwise, pull and validate the specified value. 1566d528ed9Sopenharmony_ci if (!value->VerifyTypeIs(Value::LIST, err_)) 1576d528ed9Sopenharmony_ci return false; 1586d528ed9Sopenharmony_ci for (const Value& v : value->list_value()) { 1596d528ed9Sopenharmony_ci // Keys must be strings. 1606d528ed9Sopenharmony_ci if (!v.VerifyTypeIs(Value::STRING, err_)) 1616d528ed9Sopenharmony_ci return false; 1626d528ed9Sopenharmony_ci target_->walk_keys().push_back(v.string_value()); 1636d528ed9Sopenharmony_ci } 1646d528ed9Sopenharmony_ci return true; 1656d528ed9Sopenharmony_ci} 166