16d528ed9Sopenharmony_ci// Copyright (c) 2013 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/target_generator.h" 66d528ed9Sopenharmony_ci 76d528ed9Sopenharmony_ci#include <stddef.h> 86d528ed9Sopenharmony_ci 96d528ed9Sopenharmony_ci#include <memory> 106d528ed9Sopenharmony_ci#include <utility> 116d528ed9Sopenharmony_ci 126d528ed9Sopenharmony_ci#include "gn/action_target_generator.h" 136d528ed9Sopenharmony_ci#include "gn/binary_target_generator.h" 146d528ed9Sopenharmony_ci#include "gn/build_settings.h" 156d528ed9Sopenharmony_ci#include "gn/bundle_data_target_generator.h" 166d528ed9Sopenharmony_ci#include "gn/config.h" 176d528ed9Sopenharmony_ci#include "gn/copy_target_generator.h" 186d528ed9Sopenharmony_ci#include "gn/create_bundle_target_generator.h" 196d528ed9Sopenharmony_ci#include "gn/err.h" 206d528ed9Sopenharmony_ci#include "gn/filesystem_utils.h" 216d528ed9Sopenharmony_ci#include "gn/functions.h" 226d528ed9Sopenharmony_ci#include "gn/generated_file_target_generator.h" 236d528ed9Sopenharmony_ci#include "gn/group_target_generator.h" 246d528ed9Sopenharmony_ci#include "gn/innerapis_publicinfo_generator.h" 256d528ed9Sopenharmony_ci#include "gn/metadata.h" 266d528ed9Sopenharmony_ci#include "gn/ohos_components.h" 276d528ed9Sopenharmony_ci#include "gn/ohos_variables.h" 286d528ed9Sopenharmony_ci#include "gn/parse_tree.h" 296d528ed9Sopenharmony_ci#include "gn/scheduler.h" 306d528ed9Sopenharmony_ci#include "gn/scope.h" 316d528ed9Sopenharmony_ci#include "gn/token.h" 326d528ed9Sopenharmony_ci#include "gn/value.h" 336d528ed9Sopenharmony_ci#include "gn/value_extractors.h" 346d528ed9Sopenharmony_ci#include "gn/variables.h" 356d528ed9Sopenharmony_ci 366d528ed9Sopenharmony_ciTargetGenerator::TargetGenerator(Target* target, 376d528ed9Sopenharmony_ci Scope* scope, 386d528ed9Sopenharmony_ci const FunctionCallNode* function_call, 396d528ed9Sopenharmony_ci Err* err) 406d528ed9Sopenharmony_ci : target_(target), 416d528ed9Sopenharmony_ci scope_(scope), 426d528ed9Sopenharmony_ci function_call_(function_call), 436d528ed9Sopenharmony_ci err_(err) {} 446d528ed9Sopenharmony_ci 456d528ed9Sopenharmony_ciTargetGenerator::~TargetGenerator() = default; 466d528ed9Sopenharmony_ci 476d528ed9Sopenharmony_civoid TargetGenerator::Run() { 486d528ed9Sopenharmony_ci // All target types use these. 496d528ed9Sopenharmony_ci if (!FillDependentConfigs()) 506d528ed9Sopenharmony_ci return; 516d528ed9Sopenharmony_ci 526d528ed9Sopenharmony_ci if (!FillData()) 536d528ed9Sopenharmony_ci return; 546d528ed9Sopenharmony_ci 556d528ed9Sopenharmony_ci if (!FillDependencies()) 566d528ed9Sopenharmony_ci return; 576d528ed9Sopenharmony_ci 586d528ed9Sopenharmony_ci if (!FillMetadata()) 596d528ed9Sopenharmony_ci return; 606d528ed9Sopenharmony_ci 616d528ed9Sopenharmony_ci if (!FillTestonly()) 626d528ed9Sopenharmony_ci return; 636d528ed9Sopenharmony_ci 646d528ed9Sopenharmony_ci if (!FillAssertNoDeps()) 656d528ed9Sopenharmony_ci return; 666d528ed9Sopenharmony_ci 676d528ed9Sopenharmony_ci if (!Visibility::FillItemVisibility(target_, scope_, err_)) 686d528ed9Sopenharmony_ci return; 696d528ed9Sopenharmony_ci 706d528ed9Sopenharmony_ci if (!FillWriteRuntimeDeps()) 716d528ed9Sopenharmony_ci return; 726d528ed9Sopenharmony_ci 736d528ed9Sopenharmony_ci // Do type-specific generation. 746d528ed9Sopenharmony_ci DoRun(); 756d528ed9Sopenharmony_ci} 766d528ed9Sopenharmony_ci 776d528ed9Sopenharmony_ci// static 786d528ed9Sopenharmony_civoid TargetGenerator::GenerateTarget(Scope* scope, 796d528ed9Sopenharmony_ci const FunctionCallNode* function_call, 806d528ed9Sopenharmony_ci const std::vector<Value>& args, 816d528ed9Sopenharmony_ci const std::string& output_type, 826d528ed9Sopenharmony_ci Err* err) { 836d528ed9Sopenharmony_ci // Name is the argument to the function. 846d528ed9Sopenharmony_ci if (args.size() != 1u || args[0].type() != Value::STRING) { 856d528ed9Sopenharmony_ci *err = Err(function_call, "Target generator requires one string argument.", 866d528ed9Sopenharmony_ci "Otherwise I'm not sure what to call this target."); 876d528ed9Sopenharmony_ci return; 886d528ed9Sopenharmony_ci } 896d528ed9Sopenharmony_ci 906d528ed9Sopenharmony_ci // The location of the target is the directory name with no slash at the end. 916d528ed9Sopenharmony_ci // FIXME(brettw) validate name. 926d528ed9Sopenharmony_ci const Label& toolchain_label = ToolchainLabelForScope(scope); 936d528ed9Sopenharmony_ci Label label(scope->GetSourceDir(), args[0].string_value(), 946d528ed9Sopenharmony_ci toolchain_label.dir(), toolchain_label.name()); 956d528ed9Sopenharmony_ci 966d528ed9Sopenharmony_ci if (g_scheduler->verbose_logging()) 976d528ed9Sopenharmony_ci g_scheduler->Log("Defining target", label.GetUserVisibleName(true)); 986d528ed9Sopenharmony_ci 996d528ed9Sopenharmony_ci std::unique_ptr<Target> target = std::make_unique<Target>( 1006d528ed9Sopenharmony_ci scope->settings(), label, scope->build_dependency_files()); 1016d528ed9Sopenharmony_ci target->set_defined_from(function_call); 1026d528ed9Sopenharmony_ci 1036d528ed9Sopenharmony_ci // Create and call out to the proper generator. 1046d528ed9Sopenharmony_ci if (output_type == functions::kBundleData) { 1056d528ed9Sopenharmony_ci BundleDataTargetGenerator generator(target.get(), scope, function_call, 1066d528ed9Sopenharmony_ci err); 1076d528ed9Sopenharmony_ci generator.Run(); 1086d528ed9Sopenharmony_ci } else if (output_type == functions::kCreateBundle) { 1096d528ed9Sopenharmony_ci CreateBundleTargetGenerator generator(target.get(), scope, function_call, 1106d528ed9Sopenharmony_ci err); 1116d528ed9Sopenharmony_ci generator.Run(); 1126d528ed9Sopenharmony_ci } else if (output_type == functions::kCopy) { 1136d528ed9Sopenharmony_ci CopyTargetGenerator generator(target.get(), scope, function_call, err); 1146d528ed9Sopenharmony_ci generator.Run(); 1156d528ed9Sopenharmony_ci } else if (output_type == functions::kAction) { 1166d528ed9Sopenharmony_ci ActionTargetGenerator generator(target.get(), scope, function_call, 1176d528ed9Sopenharmony_ci Target::ACTION, err); 1186d528ed9Sopenharmony_ci generator.Run(); 1196d528ed9Sopenharmony_ci } else if (output_type == functions::kActionForEach) { 1206d528ed9Sopenharmony_ci ActionTargetGenerator generator(target.get(), scope, function_call, 1216d528ed9Sopenharmony_ci Target::ACTION_FOREACH, err); 1226d528ed9Sopenharmony_ci generator.Run(); 1236d528ed9Sopenharmony_ci } else if (output_type == functions::kExecutable) { 1246d528ed9Sopenharmony_ci BinaryTargetGenerator generator(target.get(), scope, function_call, 1256d528ed9Sopenharmony_ci Target::EXECUTABLE, err); 1266d528ed9Sopenharmony_ci generator.Run(); 1276d528ed9Sopenharmony_ci } else if (output_type == functions::kGroup) { 1286d528ed9Sopenharmony_ci GroupTargetGenerator generator(target.get(), scope, function_call, err); 1296d528ed9Sopenharmony_ci generator.Run(); 1306d528ed9Sopenharmony_ci } else if (output_type == functions::kLoadableModule) { 1316d528ed9Sopenharmony_ci BinaryTargetGenerator generator(target.get(), scope, function_call, 1326d528ed9Sopenharmony_ci Target::LOADABLE_MODULE, err); 1336d528ed9Sopenharmony_ci generator.Run(); 1346d528ed9Sopenharmony_ci } else if (output_type == functions::kSharedLibrary) { 1356d528ed9Sopenharmony_ci BinaryTargetGenerator generator(target.get(), scope, function_call, 1366d528ed9Sopenharmony_ci Target::SHARED_LIBRARY, err); 1376d528ed9Sopenharmony_ci generator.Run(); 1386d528ed9Sopenharmony_ci } else if (output_type == functions::kSourceSet) { 1396d528ed9Sopenharmony_ci BinaryTargetGenerator generator(target.get(), scope, function_call, 1406d528ed9Sopenharmony_ci Target::SOURCE_SET, err); 1416d528ed9Sopenharmony_ci generator.Run(); 1426d528ed9Sopenharmony_ci } else if (output_type == functions::kStaticLibrary) { 1436d528ed9Sopenharmony_ci BinaryTargetGenerator generator(target.get(), scope, function_call, 1446d528ed9Sopenharmony_ci Target::STATIC_LIBRARY, err); 1456d528ed9Sopenharmony_ci generator.Run(); 1466d528ed9Sopenharmony_ci } else if (output_type == functions::kGeneratedFile) { 1476d528ed9Sopenharmony_ci GeneratedFileTargetGenerator generator(target.get(), scope, function_call, 1486d528ed9Sopenharmony_ci Target::GENERATED_FILE, err); 1496d528ed9Sopenharmony_ci generator.Run(); 1506d528ed9Sopenharmony_ci } else if (output_type == functions::kRustLibrary) { 1516d528ed9Sopenharmony_ci BinaryTargetGenerator generator(target.get(), scope, function_call, 1526d528ed9Sopenharmony_ci Target::RUST_LIBRARY, err); 1536d528ed9Sopenharmony_ci generator.Run(); 1546d528ed9Sopenharmony_ci } else if (output_type == functions::kRustProcMacro) { 1556d528ed9Sopenharmony_ci BinaryTargetGenerator generator(target.get(), scope, function_call, 1566d528ed9Sopenharmony_ci Target::RUST_PROC_MACRO, err); 1576d528ed9Sopenharmony_ci generator.Run(); 1586d528ed9Sopenharmony_ci } else { 1596d528ed9Sopenharmony_ci *err = Err(function_call, "Not a known target type", 1606d528ed9Sopenharmony_ci "I am very confused by the target type \"" + output_type + "\""); 1616d528ed9Sopenharmony_ci } 1626d528ed9Sopenharmony_ci 1636d528ed9Sopenharmony_ci if (err->has_error()) 1646d528ed9Sopenharmony_ci return; 1656d528ed9Sopenharmony_ci 1666d528ed9Sopenharmony_ci // Save this target for the file. 1676d528ed9Sopenharmony_ci Scope::ItemVector* collector = scope->GetItemCollector(); 1686d528ed9Sopenharmony_ci if (!collector) { 1696d528ed9Sopenharmony_ci *err = Err(function_call, "Can't define a target in this context."); 1706d528ed9Sopenharmony_ci return; 1716d528ed9Sopenharmony_ci } 1726d528ed9Sopenharmony_ci InnerApiPublicInfoGenerator* instance = InnerApiPublicInfoGenerator::getInstance(); 1736d528ed9Sopenharmony_ci if (instance != nullptr) { 1746d528ed9Sopenharmony_ci instance->GeneratedInnerapiPublicInfo(target.get(), label, scope, output_type, err); 1756d528ed9Sopenharmony_ci } 1766d528ed9Sopenharmony_ci collector->push_back(std::move(target)); 1776d528ed9Sopenharmony_ci} 1786d528ed9Sopenharmony_ci 1796d528ed9Sopenharmony_ciconst BuildSettings* TargetGenerator::GetBuildSettings() const { 1806d528ed9Sopenharmony_ci return scope_->settings()->build_settings(); 1816d528ed9Sopenharmony_ci} 1826d528ed9Sopenharmony_ci 1836d528ed9Sopenharmony_cibool TargetGenerator::FillSources() { 1846d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(variables::kSources, true); 1856d528ed9Sopenharmony_ci if (!value) 1866d528ed9Sopenharmony_ci return true; 1876d528ed9Sopenharmony_ci 1886d528ed9Sopenharmony_ci Target::FileList dest_sources; 1896d528ed9Sopenharmony_ci if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value, 1906d528ed9Sopenharmony_ci scope_->GetSourceDir(), &dest_sources, err_)) 1916d528ed9Sopenharmony_ci return false; 1926d528ed9Sopenharmony_ci target_->sources() = std::move(dest_sources); 1936d528ed9Sopenharmony_ci return true; 1946d528ed9Sopenharmony_ci} 1956d528ed9Sopenharmony_ci 1966d528ed9Sopenharmony_cibool TargetGenerator::FillPublic() { 1976d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(variables::kPublic, true); 1986d528ed9Sopenharmony_ci if (!value) 1996d528ed9Sopenharmony_ci return true; 2006d528ed9Sopenharmony_ci 2016d528ed9Sopenharmony_ci // If the public headers are defined, don't default to public. 2026d528ed9Sopenharmony_ci target_->set_all_headers_public(false); 2036d528ed9Sopenharmony_ci 2046d528ed9Sopenharmony_ci Target::FileList dest_public; 2056d528ed9Sopenharmony_ci if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value, 2066d528ed9Sopenharmony_ci scope_->GetSourceDir(), &dest_public, err_)) 2076d528ed9Sopenharmony_ci return false; 2086d528ed9Sopenharmony_ci target_->public_headers() = std::move(dest_public); 2096d528ed9Sopenharmony_ci return true; 2106d528ed9Sopenharmony_ci} 2116d528ed9Sopenharmony_ci 2126d528ed9Sopenharmony_cibool TargetGenerator::FillConfigs() { 2136d528ed9Sopenharmony_ci return FillGenericConfigs(variables::kConfigs, &target_->configs()); 2146d528ed9Sopenharmony_ci} 2156d528ed9Sopenharmony_ci 2166d528ed9Sopenharmony_cibool TargetGenerator::FillDependentConfigs() { 2176d528ed9Sopenharmony_ci if (!FillGenericConfigs(variables::kAllDependentConfigs, 2186d528ed9Sopenharmony_ci &target_->all_dependent_configs())) 2196d528ed9Sopenharmony_ci return false; 2206d528ed9Sopenharmony_ci 2216d528ed9Sopenharmony_ci if (!FillGenericConfigs(variables::kPublicConfigs, 2226d528ed9Sopenharmony_ci &target_->public_configs())) 2236d528ed9Sopenharmony_ci return false; 2246d528ed9Sopenharmony_ci 2256d528ed9Sopenharmony_ci return true; 2266d528ed9Sopenharmony_ci} 2276d528ed9Sopenharmony_ci 2286d528ed9Sopenharmony_cibool TargetGenerator::FillData() { 2296d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(variables::kData, true); 2306d528ed9Sopenharmony_ci if (!value) 2316d528ed9Sopenharmony_ci return true; 2326d528ed9Sopenharmony_ci if (!value->VerifyTypeIs(Value::LIST, err_)) 2336d528ed9Sopenharmony_ci return false; 2346d528ed9Sopenharmony_ci 2356d528ed9Sopenharmony_ci const std::vector<Value>& input_list = value->list_value(); 2366d528ed9Sopenharmony_ci std::vector<std::string>& output_list = target_->data(); 2376d528ed9Sopenharmony_ci output_list.reserve(input_list.size()); 2386d528ed9Sopenharmony_ci 2396d528ed9Sopenharmony_ci const SourceDir& dir = scope_->GetSourceDir(); 2406d528ed9Sopenharmony_ci const std::string& root_path = 2416d528ed9Sopenharmony_ci scope_->settings()->build_settings()->root_path_utf8(); 2426d528ed9Sopenharmony_ci 2436d528ed9Sopenharmony_ci for (size_t i = 0; i < input_list.size(); i++) { 2446d528ed9Sopenharmony_ci const Value& input = input_list[i]; 2456d528ed9Sopenharmony_ci if (!input.VerifyTypeIs(Value::STRING, err_)) 2466d528ed9Sopenharmony_ci return false; 2476d528ed9Sopenharmony_ci const std::string input_str = input.string_value(); 2486d528ed9Sopenharmony_ci 2496d528ed9Sopenharmony_ci // Treat each input as either a file or a directory, depending on the 2506d528ed9Sopenharmony_ci // last character. 2516d528ed9Sopenharmony_ci bool as_dir = !input_str.empty() && input_str[input_str.size() - 1] == '/'; 2526d528ed9Sopenharmony_ci 2536d528ed9Sopenharmony_ci std::string resolved = 2546d528ed9Sopenharmony_ci dir.ResolveRelativeAs(!as_dir, input, err_, root_path, &input_str); 2556d528ed9Sopenharmony_ci if (err_->has_error()) 2566d528ed9Sopenharmony_ci return false; 2576d528ed9Sopenharmony_ci 2586d528ed9Sopenharmony_ci output_list.push_back(resolved); 2596d528ed9Sopenharmony_ci } 2606d528ed9Sopenharmony_ci return true; 2616d528ed9Sopenharmony_ci} 2626d528ed9Sopenharmony_ci 2636d528ed9Sopenharmony_cibool TargetGenerator::FillDependencies() { 2646d528ed9Sopenharmony_ci if (!FillGenericDepsWithWholeArchive(variables::kDeps, &target_->private_deps(), 2656d528ed9Sopenharmony_ci &target_->whole_archive_deps(), &target_->no_whole_archive_deps())) 2666d528ed9Sopenharmony_ci return false; 2676d528ed9Sopenharmony_ci if (!FillGenericDepsWithWholeArchive(variables::kPublicDeps, &target_->public_deps(), 2686d528ed9Sopenharmony_ci &target_->whole_archive_deps(), &target_->no_whole_archive_deps())) 2696d528ed9Sopenharmony_ci return false; 2706d528ed9Sopenharmony_ci if (scope_->settings()->build_settings()->is_ohos_components_enabled()) { 2716d528ed9Sopenharmony_ci if (!FillOhosComponentDeps(variables::kExternalDeps, &target_->private_deps(), 2726d528ed9Sopenharmony_ci &target_->whole_archive_deps(), &target_->no_whole_archive_deps())) 2736d528ed9Sopenharmony_ci return false; 2746d528ed9Sopenharmony_ci if (!FillOhosComponentDeps(variables::kPublicExternalDeps, &target_->public_deps(), 2756d528ed9Sopenharmony_ci &target_->whole_archive_deps(), &target_->no_whole_archive_deps())) 2766d528ed9Sopenharmony_ci return false; 2776d528ed9Sopenharmony_ci } 2786d528ed9Sopenharmony_ci if (!FillGenericDeps(variables::kDataDeps, &target_->data_deps())) 2796d528ed9Sopenharmony_ci return false; 2806d528ed9Sopenharmony_ci if (!FillGenericDeps(variables::kGenDeps, &target_->gen_deps())) 2816d528ed9Sopenharmony_ci return false; 2826d528ed9Sopenharmony_ci 2836d528ed9Sopenharmony_ci // "data_deps" was previously named "datadeps". For backwards-compat, read 2846d528ed9Sopenharmony_ci // the old one if no "data_deps" were specified. 2856d528ed9Sopenharmony_ci if (!scope_->GetValue(variables::kDataDeps, false)) { 2866d528ed9Sopenharmony_ci if (!FillGenericDeps("datadeps", &target_->data_deps())) 2876d528ed9Sopenharmony_ci return false; 2886d528ed9Sopenharmony_ci } 2896d528ed9Sopenharmony_ci 2906d528ed9Sopenharmony_ci return true; 2916d528ed9Sopenharmony_ci} 2926d528ed9Sopenharmony_ci 2936d528ed9Sopenharmony_cibool TargetGenerator::FillMetadata() { 2946d528ed9Sopenharmony_ci // Need to get a mutable value to mark all values in the scope as used. This 2956d528ed9Sopenharmony_ci // cannot be done on a const Scope. 2966d528ed9Sopenharmony_ci Value* value = scope_->GetMutableValue(variables::kMetadata, 2976d528ed9Sopenharmony_ci Scope::SEARCH_CURRENT, true); 2986d528ed9Sopenharmony_ci 2996d528ed9Sopenharmony_ci if (!value) 3006d528ed9Sopenharmony_ci return true; 3016d528ed9Sopenharmony_ci 3026d528ed9Sopenharmony_ci if (!value->VerifyTypeIs(Value::SCOPE, err_)) 3036d528ed9Sopenharmony_ci return false; 3046d528ed9Sopenharmony_ci 3056d528ed9Sopenharmony_ci Scope* scope_value = value->scope_value(); 3066d528ed9Sopenharmony_ci 3076d528ed9Sopenharmony_ci scope_value->GetCurrentScopeValues(&target_->metadata().contents()); 3086d528ed9Sopenharmony_ci scope_value->MarkAllUsed(); 3096d528ed9Sopenharmony_ci 3106d528ed9Sopenharmony_ci // Metadata values should always hold lists of Values, such that they can be 3116d528ed9Sopenharmony_ci // collected and concatenated. Any additional specific type verification is 3126d528ed9Sopenharmony_ci // done at walk time. 3136d528ed9Sopenharmony_ci for (const auto& iter : target_->metadata().contents()) { 3146d528ed9Sopenharmony_ci if (!iter.second.VerifyTypeIs(Value::LIST, err_)) 3156d528ed9Sopenharmony_ci return false; 3166d528ed9Sopenharmony_ci } 3176d528ed9Sopenharmony_ci 3186d528ed9Sopenharmony_ci target_->metadata().set_source_dir(scope_->GetSourceDir()); 3196d528ed9Sopenharmony_ci target_->metadata().set_origin(value->origin()); 3206d528ed9Sopenharmony_ci return true; 3216d528ed9Sopenharmony_ci} 3226d528ed9Sopenharmony_ci 3236d528ed9Sopenharmony_cibool TargetGenerator::FillTestonly() { 3246d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(variables::kTestonly, true); 3256d528ed9Sopenharmony_ci if (value) { 3266d528ed9Sopenharmony_ci if (!value->VerifyTypeIs(Value::BOOLEAN, err_)) 3276d528ed9Sopenharmony_ci return false; 3286d528ed9Sopenharmony_ci target_->set_testonly(value->boolean_value()); 3296d528ed9Sopenharmony_ci } 3306d528ed9Sopenharmony_ci return true; 3316d528ed9Sopenharmony_ci} 3326d528ed9Sopenharmony_ci 3336d528ed9Sopenharmony_cibool TargetGenerator::FillAssertNoDeps() { 3346d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(variables::kAssertNoDeps, true); 3356d528ed9Sopenharmony_ci if (value) { 3366d528ed9Sopenharmony_ci return ExtractListOfLabelPatterns(scope_->settings()->build_settings(), 3376d528ed9Sopenharmony_ci *value, scope_->GetSourceDir(), 3386d528ed9Sopenharmony_ci &target_->assert_no_deps(), err_); 3396d528ed9Sopenharmony_ci } 3406d528ed9Sopenharmony_ci return true; 3416d528ed9Sopenharmony_ci} 3426d528ed9Sopenharmony_ci 3436d528ed9Sopenharmony_cibool TargetGenerator::FillOutputs(bool allow_substitutions) { 3446d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(variables::kOutputs, true); 3456d528ed9Sopenharmony_ci if (!value) 3466d528ed9Sopenharmony_ci return true; 3476d528ed9Sopenharmony_ci 3486d528ed9Sopenharmony_ci SubstitutionList& outputs = target_->action_values().outputs(); 3496d528ed9Sopenharmony_ci if (!outputs.Parse(*value, err_)) 3506d528ed9Sopenharmony_ci return false; 3516d528ed9Sopenharmony_ci 3526d528ed9Sopenharmony_ci if (!allow_substitutions) { 3536d528ed9Sopenharmony_ci // Verify no substitutions were actually used. 3546d528ed9Sopenharmony_ci if (!outputs.required_types().empty()) { 3556d528ed9Sopenharmony_ci *err_ = 3566d528ed9Sopenharmony_ci Err(*value, "Source expansions not allowed here.", 3576d528ed9Sopenharmony_ci "The outputs of this target used source {{expansions}} but this " 3586d528ed9Sopenharmony_ci "target type\ndoesn't support them. Just express the outputs " 3596d528ed9Sopenharmony_ci "literally."); 3606d528ed9Sopenharmony_ci return false; 3616d528ed9Sopenharmony_ci } 3626d528ed9Sopenharmony_ci } 3636d528ed9Sopenharmony_ci 3646d528ed9Sopenharmony_ci // Check the substitutions used are valid for this purpose. 3656d528ed9Sopenharmony_ci if (!EnsureValidSubstitutions(outputs.required_types(), 3666d528ed9Sopenharmony_ci &IsValidSourceSubstitution, value->origin(), 3676d528ed9Sopenharmony_ci err_)) 3686d528ed9Sopenharmony_ci return false; 3696d528ed9Sopenharmony_ci 3706d528ed9Sopenharmony_ci // Validate that outputs are in the output dir. 3716d528ed9Sopenharmony_ci CHECK(outputs.list().size() == value->list_value().size()); 3726d528ed9Sopenharmony_ci for (size_t i = 0; i < outputs.list().size(); i++) { 3736d528ed9Sopenharmony_ci if (!EnsureSubstitutionIsInOutputDir(outputs.list()[i], 3746d528ed9Sopenharmony_ci value->list_value()[i])) 3756d528ed9Sopenharmony_ci return false; 3766d528ed9Sopenharmony_ci } 3776d528ed9Sopenharmony_ci return true; 3786d528ed9Sopenharmony_ci} 3796d528ed9Sopenharmony_ci 3806d528ed9Sopenharmony_cibool TargetGenerator::FillCheckIncludes() { 3816d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(variables::kCheckIncludes, true); 3826d528ed9Sopenharmony_ci if (!value) 3836d528ed9Sopenharmony_ci return true; 3846d528ed9Sopenharmony_ci if (!value->VerifyTypeIs(Value::BOOLEAN, err_)) 3856d528ed9Sopenharmony_ci return false; 3866d528ed9Sopenharmony_ci target_->set_check_includes(value->boolean_value()); 3876d528ed9Sopenharmony_ci return true; 3886d528ed9Sopenharmony_ci} 3896d528ed9Sopenharmony_ci 3906d528ed9Sopenharmony_cibool TargetGenerator::FillOutputExtension() { 3916d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(variables::kOutputExtension, true); 3926d528ed9Sopenharmony_ci if (!value) 3936d528ed9Sopenharmony_ci return true; 3946d528ed9Sopenharmony_ci if (!value->VerifyTypeIs(Value::STRING, err_)) 3956d528ed9Sopenharmony_ci return false; 3966d528ed9Sopenharmony_ci target_->set_output_extension(value->string_value()); 3976d528ed9Sopenharmony_ci return true; 3986d528ed9Sopenharmony_ci} 3996d528ed9Sopenharmony_ci 4006d528ed9Sopenharmony_cibool TargetGenerator::EnsureSubstitutionIsInOutputDir( 4016d528ed9Sopenharmony_ci const SubstitutionPattern& pattern, 4026d528ed9Sopenharmony_ci const Value& original_value) { 4036d528ed9Sopenharmony_ci if (pattern.ranges().empty()) { 4046d528ed9Sopenharmony_ci // Pattern is empty, error out (this prevents weirdness below). 4056d528ed9Sopenharmony_ci *err_ = Err(original_value, "This has an empty value in it."); 4066d528ed9Sopenharmony_ci return false; 4076d528ed9Sopenharmony_ci } 4086d528ed9Sopenharmony_ci 4096d528ed9Sopenharmony_ci if (pattern.ranges()[0].type == &SubstitutionLiteral) { 4106d528ed9Sopenharmony_ci // If the first thing is a literal, it must start with the output dir. 4116d528ed9Sopenharmony_ci if (!EnsureStringIsInOutputDir(GetBuildSettings()->build_dir(), 4126d528ed9Sopenharmony_ci pattern.ranges()[0].literal, 4136d528ed9Sopenharmony_ci original_value.origin(), err_)) 4146d528ed9Sopenharmony_ci return false; 4156d528ed9Sopenharmony_ci } else { 4166d528ed9Sopenharmony_ci // Otherwise, the first subrange must be a pattern that expands to 4176d528ed9Sopenharmony_ci // something in the output directory. 4186d528ed9Sopenharmony_ci if (!SubstitutionIsInOutputDir(pattern.ranges()[0].type)) { 4196d528ed9Sopenharmony_ci *err_ = 4206d528ed9Sopenharmony_ci Err(original_value, "File is not inside output directory.", 4216d528ed9Sopenharmony_ci "The given file should be in the output directory. Normally you\n" 4226d528ed9Sopenharmony_ci "would specify\n\"$target_out_dir/foo\" or " 4236d528ed9Sopenharmony_ci "\"{{source_gen_dir}}/foo\"."); 4246d528ed9Sopenharmony_ci return false; 4256d528ed9Sopenharmony_ci } 4266d528ed9Sopenharmony_ci } 4276d528ed9Sopenharmony_ci 4286d528ed9Sopenharmony_ci return true; 4296d528ed9Sopenharmony_ci} 4306d528ed9Sopenharmony_ci 4316d528ed9Sopenharmony_cibool TargetGenerator::FillGenericConfigs(const char* var_name, 4326d528ed9Sopenharmony_ci UniqueVector<LabelConfigPair>* dest) { 4336d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(var_name, true); 4346d528ed9Sopenharmony_ci if (value) { 4356d528ed9Sopenharmony_ci ExtractListOfUniqueLabels(scope_->settings()->build_settings(), *value, 4366d528ed9Sopenharmony_ci scope_->GetSourceDir(), 4376d528ed9Sopenharmony_ci ToolchainLabelForScope(scope_), dest, err_); 4386d528ed9Sopenharmony_ci } 4396d528ed9Sopenharmony_ci return !err_->has_error(); 4406d528ed9Sopenharmony_ci} 4416d528ed9Sopenharmony_ci 4426d528ed9Sopenharmony_cibool TargetGenerator::FillGenericDeps(const char* var_name, 4436d528ed9Sopenharmony_ci LabelTargetVector* dest) { 4446d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(var_name, true); 4456d528ed9Sopenharmony_ci if (value) { 4466d528ed9Sopenharmony_ci ExtractListOfLabels(scope_->settings()->build_settings(), *value, 4476d528ed9Sopenharmony_ci scope_->GetSourceDir(), ToolchainLabelForScope(scope_), 4486d528ed9Sopenharmony_ci dest, err_); 4496d528ed9Sopenharmony_ci } 4506d528ed9Sopenharmony_ci return !err_->has_error(); 4516d528ed9Sopenharmony_ci} 4526d528ed9Sopenharmony_ci 4536d528ed9Sopenharmony_cibool TargetGenerator::FillGenericDepsWithWholeArchive(const char* var_name, LabelTargetVector* dest, 4546d528ed9Sopenharmony_ci LabelTargetVector* whole_dest, LabelTargetVector* no_whole_dest) { 4556d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(var_name, true); 4566d528ed9Sopenharmony_ci if (value) { 4576d528ed9Sopenharmony_ci ExtractListOfLabelsMapping(target_->label().GetUserVisibleName(false), scope_->settings()->build_settings(), 4586d528ed9Sopenharmony_ci *value, scope_->GetSourceDir(), ToolchainLabelForScope(scope_), 4596d528ed9Sopenharmony_ci dest, whole_dest, no_whole_dest, err_); 4606d528ed9Sopenharmony_ci } 4616d528ed9Sopenharmony_ci return !err_->has_error(); 4626d528ed9Sopenharmony_ci} 4636d528ed9Sopenharmony_ci 4646d528ed9Sopenharmony_cibool TargetGenerator::FillOhosComponentDeps(const char* var_name, LabelTargetVector* dest, 4656d528ed9Sopenharmony_ci LabelTargetVector* whole_dest, LabelTargetVector* no_whole_dest) 4666d528ed9Sopenharmony_ci{ 4676d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(var_name, true); 4686d528ed9Sopenharmony_ci if (value) { 4696d528ed9Sopenharmony_ci // Append to private deps 4706d528ed9Sopenharmony_ci ExtractListOfExternalDeps(scope_->settings()->build_settings(), *value, 4716d528ed9Sopenharmony_ci scope_->GetSourceDir(), ToolchainLabelForScope(scope_), 4726d528ed9Sopenharmony_ci dest, whole_dest, no_whole_dest, err_); 4736d528ed9Sopenharmony_ci } 4746d528ed9Sopenharmony_ci return !err_->has_error(); 4756d528ed9Sopenharmony_ci} 4766d528ed9Sopenharmony_ci 4776d528ed9Sopenharmony_cibool TargetGenerator::FillWriteRuntimeDeps() { 4786d528ed9Sopenharmony_ci const Value* value = scope_->GetValue(variables::kWriteRuntimeDeps, true); 4796d528ed9Sopenharmony_ci if (!value) 4806d528ed9Sopenharmony_ci return true; 4816d528ed9Sopenharmony_ci 4826d528ed9Sopenharmony_ci // Compute the file name and make sure it's in the output dir. 4836d528ed9Sopenharmony_ci SourceFile source_file = scope_->GetSourceDir().ResolveRelativeFile( 4846d528ed9Sopenharmony_ci *value, err_, GetBuildSettings()->root_path_utf8()); 4856d528ed9Sopenharmony_ci if (err_->has_error()) 4866d528ed9Sopenharmony_ci return false; 4876d528ed9Sopenharmony_ci if (!EnsureStringIsInOutputDir(GetBuildSettings()->build_dir(), 4886d528ed9Sopenharmony_ci source_file.value(), value->origin(), err_)) 4896d528ed9Sopenharmony_ci return false; 4906d528ed9Sopenharmony_ci OutputFile output_file(GetBuildSettings(), source_file); 4916d528ed9Sopenharmony_ci target_->set_write_runtime_deps_output(output_file); 4926d528ed9Sopenharmony_ci 4936d528ed9Sopenharmony_ci return true; 4946d528ed9Sopenharmony_ci}