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}