1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gn/bundle_file_rule.h"
6
7 #include "base/strings/stringprintf.h"
8 #include "gn/output_file.h"
9 #include "gn/settings.h"
10 #include "gn/substitution_pattern.h"
11 #include "gn/substitution_writer.h"
12 #include "gn/target.h"
13 #include "gn/variables.h"
14
15 namespace {
16
ErrMissingPropertyForExpansion(const Settings * settings,const Target * target,const BundleFileRule * bundle_file_rule,const char * property_name)17 Err ErrMissingPropertyForExpansion(const Settings* settings,
18 const Target* target,
19 const BundleFileRule* bundle_file_rule,
20 const char* property_name) {
21 std::string label = bundle_file_rule->target()->label().GetUserVisibleName(
22 settings->default_toolchain_label());
23
24 return Err(target->defined_from(),
25 base::StringPrintf("Property %s is required.", property_name),
26 base::StringPrintf(
27 "In order to expand {{%s}} in %s, the "
28 "property needs to be defined in the create_bundle target.",
29 property_name, label.c_str()));
30 }
31
32 } // namespace
33
BundleFileRule(const Target * bundle_data_target,const std::vector<SourceFile> sources,const SubstitutionPattern & pattern)34 BundleFileRule::BundleFileRule(const Target* bundle_data_target,
35 const std::vector<SourceFile> sources,
36 const SubstitutionPattern& pattern)
37 : target_(bundle_data_target), sources_(sources), pattern_(pattern) {
38 // target_ may be null during testing.
39 DCHECK(!target_ || target_->output_type() == Target::BUNDLE_DATA);
40 }
41
42 BundleFileRule::BundleFileRule(const BundleFileRule& other) = default;
43
44 BundleFileRule::~BundleFileRule() = default;
45
ApplyPatternToSource(const Settings * settings,const Target * target,const BundleData & bundle_data,const SourceFile & source_file,SourceFile * expanded_source_file,Err * err) const46 bool BundleFileRule::ApplyPatternToSource(const Settings* settings,
47 const Target* target,
48 const BundleData& bundle_data,
49 const SourceFile& source_file,
50 SourceFile* expanded_source_file,
51 Err* err) const {
52 std::string output_path;
53 for (const auto& subrange : pattern_.ranges()) {
54 if (subrange.type == &SubstitutionLiteral) {
55 output_path.append(subrange.literal);
56 } else if (subrange.type == &SubstitutionBundleRootDir) {
57 if (bundle_data.root_dir().is_null()) {
58 *err = ErrMissingPropertyForExpansion(settings, target, this,
59 variables::kBundleRootDir);
60 return false;
61 }
62 output_path.append(bundle_data.root_dir().value());
63 } else if (subrange.type == &SubstitutionBundleContentsDir) {
64 if (bundle_data.contents_dir().is_null()) {
65 *err = ErrMissingPropertyForExpansion(settings, target, this,
66 variables::kBundleContentsDir);
67 return false;
68 }
69 output_path.append(bundle_data.contents_dir().value());
70 } else if (subrange.type == &SubstitutionBundleResourcesDir) {
71 if (bundle_data.resources_dir().is_null()) {
72 *err = ErrMissingPropertyForExpansion(settings, target, this,
73 variables::kBundleResourcesDir);
74 return false;
75 }
76 output_path.append(bundle_data.resources_dir().value());
77 } else if (subrange.type == &SubstitutionBundleExecutableDir) {
78 if (bundle_data.executable_dir().is_null()) {
79 *err = ErrMissingPropertyForExpansion(settings, target, this,
80 variables::kBundleExecutableDir);
81 return false;
82 }
83 output_path.append(bundle_data.executable_dir().value());
84 } else {
85 output_path.append(SubstitutionWriter::GetSourceSubstitution(
86 target_, target_->settings(), source_file, subrange.type,
87 SubstitutionWriter::OUTPUT_ABSOLUTE, SourceDir()));
88 }
89 }
90 *expanded_source_file = SourceFile(std::move(output_path));
91 return true;
92 }
93
ApplyPatternToSourceAsOutputFile(const Settings * settings,const Target * target,const BundleData & bundle_data,const SourceFile & source_file,OutputFile * expanded_output_file,Err * err) const94 bool BundleFileRule::ApplyPatternToSourceAsOutputFile(
95 const Settings* settings,
96 const Target* target,
97 const BundleData& bundle_data,
98 const SourceFile& source_file,
99 OutputFile* expanded_output_file,
100 Err* err) const {
101 SourceFile expanded_source_file;
102 if (!ApplyPatternToSource(settings, target, bundle_data, source_file,
103 &expanded_source_file, err)) {
104 return false;
105 }
106
107 *expanded_output_file =
108 OutputFile(settings->build_settings(), expanded_source_file);
109 return true;
110 }
111