• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_data.h"
6 
7 #include "base/logging.h"
8 #include "base/strings/string_util.h"
9 #include "gn/filesystem_utils.h"
10 #include "gn/label_pattern.h"
11 #include "gn/output_file.h"
12 #include "gn/settings.h"
13 #include "gn/substitution_writer.h"
14 #include "gn/target.h"
15 
16 BundleData::BundleData() = default;
17 
18 BundleData::~BundleData() = default;
19 
GetAssetsCatalogDirectory(const SourceFile & source)20 SourceFile BundleData::GetAssetsCatalogDirectory(const SourceFile& source) {
21   SourceFile assets_catalog_dir;
22   std::string_view path = source.value();
23   while (!path.empty()) {
24     if (base::ends_with(path, ".xcassets")) {
25       assets_catalog_dir = SourceFile(path);
26     }
27 
28     const auto sep = path.find_last_of("/\\");
29     if (sep == std::string_view::npos) {
30       break;
31     }
32 
33     path = path.substr(0, sep);
34   }
35   return assets_catalog_dir;
36 }
37 
AddBundleData(const Target * target,bool is_create_bundle)38 void BundleData::AddBundleData(const Target* target, bool is_create_bundle) {
39   DCHECK_EQ(target->output_type(), Target::BUNDLE_DATA);
40   for (const auto& pattern : bundle_deps_filter_) {
41     if (pattern.Matches(target->label()))
42       return;
43   }
44   if (transparent_) {
45     DCHECK(is_create_bundle);
46     if (target->bundle_data().product_type() == product_type_) {
47       bundle_deps_.push_back(target);
48     } else {
49       forwarded_bundle_deps_.push_back(target);
50     }
51     return;
52   }
53   if (is_create_bundle) {
54     bundle_deps_.push_back(target);
55   }
56   forwarded_bundle_deps_.push_back(target);
57 }
58 
OnTargetResolved(Target * owning_target)59 void BundleData::OnTargetResolved(Target* owning_target) {
60   // Only initialize file_rules_ and assets_catalog_sources for "create_bundle"
61   // target (properties are only used by those targets).
62   if (owning_target->output_type() != Target::CREATE_BUNDLE)
63     return;
64 
65   UniqueVector<const Target*> assets_catalog_deps;
66   UniqueVector<SourceFile> assets_catalog_sources;
67 
68   for (const Target* target : bundle_deps_) {
69     SourceFiles file_rule_sources;
70     for (const SourceFile& source_file : target->sources()) {
71       SourceFile assets_catalog_dir = GetAssetsCatalogDirectory(source_file);
72       if (!assets_catalog_dir.is_null()) {
73         assets_catalog_sources.push_back(assets_catalog_dir);
74         assets_catalog_deps.push_back(target);
75       } else {
76         file_rule_sources.push_back(source_file);
77       }
78     }
79 
80     if (!file_rule_sources.empty()) {
81       DCHECK_EQ(target->action_values().outputs().list().size(), 1u);
82       file_rules_.push_back(
83           BundleFileRule(target, file_rule_sources,
84                          target->action_values().outputs().list()[0]));
85     }
86   }
87 
88   assets_catalog_deps_.insert(assets_catalog_deps_.end(),
89                               assets_catalog_deps.begin(),
90                               assets_catalog_deps.end());
91   assets_catalog_sources_.insert(assets_catalog_sources_.end(),
92                                  assets_catalog_sources.begin(),
93                                  assets_catalog_sources.end());
94 
95   GetSourceFiles(&owning_target->sources());
96 }
97 
GetSourceFiles(SourceFiles * sources) const98 void BundleData::GetSourceFiles(SourceFiles* sources) const {
99   for (const BundleFileRule& file_rule : file_rules_) {
100     sources->insert(sources->end(), file_rule.sources().begin(),
101                     file_rule.sources().end());
102   }
103   sources->insert(sources->end(), assets_catalog_sources_.begin(),
104                   assets_catalog_sources_.end());
105   if (!post_processing_script_.is_null()) {
106     sources->insert(sources->end(), post_processing_sources_.begin(),
107                     post_processing_sources_.end());
108   }
109 }
110 
GetOutputFiles(const Settings * settings,const Target * target,OutputFiles * outputs,Err * err) const111 bool BundleData::GetOutputFiles(const Settings* settings,
112                                 const Target* target,
113                                 OutputFiles* outputs,
114                                 Err* err) const {
115   SourceFiles outputs_as_sources;
116   if (!GetOutputsAsSourceFiles(settings, target, &outputs_as_sources, err))
117     return false;
118   for (const SourceFile& source_file : outputs_as_sources)
119     outputs->push_back(OutputFile(settings->build_settings(), source_file));
120   return true;
121 }
122 
GetOutputsAsSourceFiles(const Settings * settings,const Target * target,SourceFiles * outputs_as_source,Err * err) const123 bool BundleData::GetOutputsAsSourceFiles(const Settings* settings,
124                                          const Target* target,
125                                          SourceFiles* outputs_as_source,
126                                          Err* err) const {
127   for (const BundleFileRule& file_rule : file_rules_) {
128     for (const SourceFile& source : file_rule.sources()) {
129       SourceFile expanded_source_file;
130       if (!file_rule.ApplyPatternToSource(settings, target, *this, source,
131                                           &expanded_source_file, err))
132         return false;
133       outputs_as_source->push_back(expanded_source_file);
134     }
135   }
136 
137   if (!assets_catalog_sources_.empty())
138     outputs_as_source->push_back(GetCompiledAssetCatalogPath());
139 
140   if (!partial_info_plist_.is_null())
141     outputs_as_source->push_back(partial_info_plist_);
142 
143   if (!post_processing_script_.is_null()) {
144     std::vector<SourceFile> post_processing_output_files;
145     SubstitutionWriter::GetListAsSourceFiles(post_processing_outputs_,
146                                              &post_processing_output_files);
147     outputs_as_source->insert(outputs_as_source->end(),
148                               post_processing_output_files.begin(),
149                               post_processing_output_files.end());
150   }
151 
152   if (!root_dir_.is_null())
153     outputs_as_source->push_back(GetBundleRootDirOutput(settings));
154 
155   return true;
156 }
157 
GetCompiledAssetCatalogPath() const158 SourceFile BundleData::GetCompiledAssetCatalogPath() const {
159   DCHECK(!assets_catalog_sources_.empty());
160   std::string assets_car_path = resources_dir_.value() + "/Assets.car";
161   return SourceFile(std::move(assets_car_path));
162 }
163 
GetBundleRootDirOutput(const Settings * settings) const164 SourceFile BundleData::GetBundleRootDirOutput(const Settings* settings) const {
165   std::string root_dir_value = root_dir().value();
166   size_t last_separator = root_dir_value.rfind('/');
167   if (last_separator != std::string::npos)
168     root_dir_value = root_dir_value.substr(0, last_separator);
169 
170   return SourceFile(std::move(root_dir_value));
171 }
172 
GetBundleRootDirOutputAsDir(const Settings * settings) const173 SourceDir BundleData::GetBundleRootDirOutputAsDir(
174     const Settings* settings) const {
175   return SourceDir(GetBundleRootDirOutput(settings).value());
176 }
177 
GetBundleDir(const Settings * settings) const178 SourceDir BundleData::GetBundleDir(const Settings* settings) const {
179   return GetBundleRootDirOutput(settings).GetDir();
180 }
181