Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(190)

Side by Side Diff: tools/gn/ninja_create_bundle_target_writer.cc

Issue 2060273002: [GN] Add support for code signing to "create_bundle" targets. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@ios-strings-binary
Patch Set: Rename NinjaCreateBundleTargetWriter.OrderOnlyDeps test Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/gn/ninja_create_bundle_target_writer.h" 5 #include "tools/gn/ninja_create_bundle_target_writer.h"
6 6
7 #include "base/macros.h"
8 #include "base/strings/string_util.h"
7 #include "tools/gn/filesystem_utils.h" 9 #include "tools/gn/filesystem_utils.h"
8 #include "tools/gn/ninja_utils.h" 10 #include "tools/gn/ninja_utils.h"
9 #include "tools/gn/output_file.h" 11 #include "tools/gn/output_file.h"
10 #include "tools/gn/scheduler.h" 12 #include "tools/gn/scheduler.h"
11 #include "tools/gn/substitution_writer.h" 13 #include "tools/gn/substitution_writer.h"
12 #include "tools/gn/target.h" 14 #include "tools/gn/target.h"
13 #include "tools/gn/toolchain.h" 15 #include "tools/gn/toolchain.h"
14 16
15 namespace { 17 namespace {
16 18
17 void FailWithMissingToolError(Toolchain::ToolType tool, const Target* target) { 19 void FailWithMissingToolError(Toolchain::ToolType tool, const Target* target) {
18 const std::string& tool_name = Toolchain::ToolTypeToName(tool); 20 const std::string& tool_name = Toolchain::ToolTypeToName(tool);
19 g_scheduler->FailWithError(Err( 21 g_scheduler->FailWithError(Err(
20 nullptr, tool_name + " tool not defined", 22 nullptr, tool_name + " tool not defined",
21 "The toolchain " + 23 "The toolchain " +
22 target->toolchain()->label().GetUserVisibleName(false) + "\n" 24 target->toolchain()->label().GetUserVisibleName(false) + "\n"
23 "used by target " + target->label().GetUserVisibleName(false) + "\n" 25 "used by target " + target->label().GetUserVisibleName(false) + "\n"
24 "doesn't define a \"" + tool_name + "\" tool.")); 26 "doesn't define a \"" + tool_name + "\" tool."));
25 } 27 }
26 28
29 bool EnsureAllToolsAvailable(const Target* target) {
30 const Toolchain::ToolType kRequiredTools[] = {
31 Toolchain::TYPE_COPY_BUNDLE_DATA, Toolchain::TYPE_COMPILE_XCASSETS,
32 Toolchain::TYPE_STAMP,
33 };
34
35 for (size_t i = 0; i < arraysize(kRequiredTools); ++i) {
36 if (!target->toolchain()->GetTool(kRequiredTools[i])) {
37 FailWithMissingToolError(kRequiredTools[i], target);
38 return false;
39 }
40 }
41
42 return true;
43 }
44
27 } // namespace 45 } // namespace
28 46
29 NinjaCreateBundleTargetWriter::NinjaCreateBundleTargetWriter( 47 NinjaCreateBundleTargetWriter::NinjaCreateBundleTargetWriter(
30 const Target* target, 48 const Target* target,
31 std::ostream& out) 49 std::ostream& out)
32 : NinjaTargetWriter(target, out) {} 50 : NinjaTargetWriter(target, out) {}
33 51
34 NinjaCreateBundleTargetWriter::~NinjaCreateBundleTargetWriter() {} 52 NinjaCreateBundleTargetWriter::~NinjaCreateBundleTargetWriter() {}
35 53
36 void NinjaCreateBundleTargetWriter::Run() { 54 void NinjaCreateBundleTargetWriter::Run() {
37 if (!target_->toolchain()->GetTool(Toolchain::TYPE_COPY_BUNDLE_DATA)) { 55 if (!EnsureAllToolsAvailable(target_))
38 FailWithMissingToolError(Toolchain::TYPE_COPY_BUNDLE_DATA, target_);
39 return; 56 return;
40 }
41 57
42 if (!target_->toolchain()->GetTool(Toolchain::TYPE_COMPILE_XCASSETS)) { 58 std::string code_signing_rule_name = WriteCodeSigningRuleDefinition();
43 FailWithMissingToolError(Toolchain::TYPE_COMPILE_XCASSETS, target_);
44 return;
45 }
46 59
47 if (!target_->toolchain()->GetTool(Toolchain::TYPE_STAMP)) {
48 FailWithMissingToolError(Toolchain::TYPE_STAMP, target_);
49 return;
50 }
51
52 std::vector<OutputFile> output_files;
53 OutputFile input_dep = 60 OutputFile input_dep =
54 WriteInputDepsStampAndGetDep(std::vector<const Target*>()); 61 WriteInputDepsStampAndGetDep(std::vector<const Target*>());
55 62
63 std::vector<OutputFile> output_files;
64 WriteCopyBundleDataRules(input_dep, &output_files);
65 WriteCompileAssetsCatalogRule(input_dep, &output_files);
66 WriteCodeSigningRules(code_signing_rule_name, input_dep, &output_files);
67
68 std::vector<OutputFile> order_only_deps;
69 for (const auto& pair : target_->data_deps())
70 order_only_deps.push_back(pair.ptr->dependency_output_file());
71 WriteStampForTarget(output_files, order_only_deps);
72
73 // Write a phony target for the outer bundle directory. This allows other
74 // targets to treat the entire bundle as a single unit, even though it is
75 // a directory, so that it can be depended upon as a discrete build edge.
76 out_ << "build ";
77 path_output_.WriteFile(
78 out_,
79 OutputFile(settings_->build_settings(),
80 target_->bundle_data().GetBundleRootDirOutput(settings_)));
81 out_ << ": phony " << target_->dependency_output_file().value();
82 out_ << std::endl;
83 }
84
85 std::string NinjaCreateBundleTargetWriter::WriteCodeSigningRuleDefinition() {
86 if (target_->bundle_data().code_signing_script().is_null())
87 return std::string();
88
89 std::string target_label = target_->label().GetUserVisibleName(true);
90 std::string custom_rule_name(target_label);
91 base::ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name);
92 custom_rule_name.append("_code_signing_rule");
93
94 out_ << "rule " << custom_rule_name << std::endl;
95 out_ << " command = ";
96 path_output_.WriteFile(out_, settings_->build_settings()->python_path());
97 out_ << " ";
98 path_output_.WriteFile(out_, target_->bundle_data().code_signing_script());
99
100 const SubstitutionList& args = target_->bundle_data().code_signing_args();
101 EscapeOptions args_escape_options;
102 args_escape_options.mode = ESCAPE_NINJA_COMMAND;
103
104 for (const auto& arg : args.list()) {
105 out_ << " ";
106 SubstitutionWriter::WriteWithNinjaVariables(arg, args_escape_options, out_);
107 }
108 out_ << std::endl;
109 out_ << " description = CODE SIGNING " << target_label << std::endl;
110 out_ << " restat = 1" << std::endl;
111 out_ << std::endl;
112
113 return custom_rule_name;
114 }
115
116 void NinjaCreateBundleTargetWriter::WriteCopyBundleDataRules(
117 const OutputFile& input_dep,
118 std::vector<OutputFile>* output_files) {
56 for (const BundleFileRule& file_rule : target_->bundle_data().file_rules()) { 119 for (const BundleFileRule& file_rule : target_->bundle_data().file_rules()) {
57 for (const SourceFile& source_file : file_rule.sources()) { 120 for (const SourceFile& source_file : file_rule.sources()) {
58 OutputFile output_file = file_rule.ApplyPatternToSourceAsOutputFile( 121 OutputFile output_file = file_rule.ApplyPatternToSourceAsOutputFile(
59 settings_, target_->bundle_data(), source_file); 122 settings_, target_->bundle_data(), source_file);
60 output_files.push_back(output_file); 123 output_files->push_back(output_file);
61 124
62 out_ << "build "; 125 out_ << "build ";
63 path_output_.WriteFile(out_, output_file); 126 path_output_.WriteFile(out_, output_file);
64 out_ << ": " 127 out_ << ": "
65 << GetNinjaRulePrefixForToolchain(settings_) 128 << GetNinjaRulePrefixForToolchain(settings_)
66 << Toolchain::ToolTypeToName(Toolchain::TYPE_COPY_BUNDLE_DATA) 129 << Toolchain::ToolTypeToName(Toolchain::TYPE_COPY_BUNDLE_DATA)
67 << " "; 130 << " ";
68 path_output_.WriteFile(out_, source_file); 131 path_output_.WriteFile(out_, source_file);
69 if (!input_dep.value().empty()) { 132 if (!input_dep.value().empty()) {
70 out_ << " || "; 133 out_ << " | ";
71 path_output_.WriteFile(out_, input_dep); 134 path_output_.WriteFile(out_, input_dep);
72 } 135 }
73 out_ << std::endl; 136 out_ << std::endl;
74 } 137 }
75 } 138 }
139 }
76 140
77 if (!target_->bundle_data().asset_catalog_sources().empty()) { 141 void NinjaCreateBundleTargetWriter::WriteCompileAssetsCatalogRule(
78 OutputFile output_file( 142 const OutputFile& input_dep,
79 settings_->build_settings(), 143 std::vector<OutputFile>* output_files) {
80 target_->bundle_data().GetCompiledAssetCatalogPath()); 144 if (target_->bundle_data().asset_catalog_sources().empty())
81 output_files.push_back(output_file); 145 return;
82 146
83 out_ << "build "; 147 OutputFile output_file(settings_->build_settings(),
84 path_output_.WriteFile(out_, output_file); 148 target_->bundle_data().GetCompiledAssetCatalogPath());
85 out_ << ": " 149 output_files->push_back(output_file);
86 << GetNinjaRulePrefixForToolchain(settings_)
87 << Toolchain::ToolTypeToName(Toolchain::TYPE_COMPILE_XCASSETS);
88 150
89 std::set<SourceFile> asset_catalog_bundles; 151 out_ << "build ";
90 for (const auto& source : target_->bundle_data().asset_catalog_sources()) { 152 path_output_.WriteFile(out_, output_file);
91 SourceFile asset_catalog_bundle; 153 out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
92 CHECK(IsSourceFileFromAssetCatalog(source, &asset_catalog_bundle)); 154 << Toolchain::ToolTypeToName(Toolchain::TYPE_COMPILE_XCASSETS);
93 if (asset_catalog_bundles.find(asset_catalog_bundle) !=
94 asset_catalog_bundles.end())
95 continue;
96 out_ << " ";
97 path_output_.WriteFile(out_, asset_catalog_bundle);
98 asset_catalog_bundles.insert(asset_catalog_bundle);
99 }
100 155
101 out_ << " |"; 156 std::set<SourceFile> asset_catalog_bundles;
102 for (const auto& source : target_->bundle_data().asset_catalog_sources()) { 157 for (const auto& source : target_->bundle_data().asset_catalog_sources()) {
103 out_ << " "; 158 SourceFile asset_catalog_bundle;
104 path_output_.WriteFile(out_, source); 159 CHECK(IsSourceFileFromAssetCatalog(source, &asset_catalog_bundle));
105 } 160 if (asset_catalog_bundles.find(asset_catalog_bundle) !=
106 if (!input_dep.value().empty()) { 161 asset_catalog_bundles.end())
107 out_ << " || "; 162 continue;
108 path_output_.WriteFile(out_, input_dep); 163 out_ << " ";
109 } 164 path_output_.WriteFile(out_, asset_catalog_bundle);
110 out_ << std::endl; 165 asset_catalog_bundles.insert(asset_catalog_bundle);
111 } 166 }
112 167
113 out_ << std::endl; 168 out_ << " |";
169 for (const auto& source : target_->bundle_data().asset_catalog_sources()) {
170 out_ << " ";
171 path_output_.WriteFile(
172 out_, OutputFile(settings_->build_settings(), source));
173 }
114 174
115 std::vector<OutputFile> order_only_deps; 175 if (!input_dep.value().empty()) {
116 for (const auto& pair : target_->data_deps()) 176 out_ << " ";
117 order_only_deps.push_back(pair.ptr->dependency_output_file()); 177 path_output_.WriteFile(out_, input_dep);
118 WriteStampForTarget(output_files, order_only_deps); 178 }
119
120 // Write a phony target for the outer bundle directory. This allows other
121 // targets to treat the entire bundle as a single unit, even though it is
122 // a directory, so that it can be depended upon as a discrete build edge.
123 out_ << "build ";
124 path_output_.WriteFile(
125 out_,
126 OutputFile(settings_->build_settings(),
127 target_->bundle_data().GetBundleRootDirOutput(settings_)));
128 out_ << ": phony " << target_->dependency_output_file().value();
129 out_ << std::endl; 179 out_ << std::endl;
130 } 180 }
181
182 void NinjaCreateBundleTargetWriter::WriteCodeSigningRules(
183 const std::string& code_signing_rule_name,
184 const OutputFile& input_dep,
185 std::vector<OutputFile>* output_files) {
186 if (code_signing_rule_name.empty())
187 return;
188
189 OutputFile code_signing_input_stamp_file =
190 WriteCodeSigningInputDepsStamp(input_dep, output_files);
191
192 out_ << "build";
193 std::vector<OutputFile> code_signing_output_files;
194 SubstitutionWriter::GetListAsOutputFiles(
195 settings_, target_->bundle_data().code_signing_outputs(),
196 &code_signing_output_files);
197 path_output_.WriteFiles(out_, code_signing_output_files);
198
199 // Since the code signature step depends on all the files from the bundle,
200 // the create_bundle stamp can just depends on the output of the signature.
201 output_files->swap(code_signing_output_files);
202
203 out_ << ": " << code_signing_rule_name;
204 if (!code_signing_input_stamp_file.value().empty()) {
205 out_ << " | ";
206 path_output_.WriteFile(out_, code_signing_input_stamp_file);
207 }
208 out_ << std::endl;
209 }
210
211 OutputFile NinjaCreateBundleTargetWriter::WriteCodeSigningInputDepsStamp(
212 const OutputFile& input_dep,
213 std::vector<OutputFile>* output_files) {
214 std::vector<SourceFile> code_signing_input_files;
215 code_signing_input_files.push_back(
216 target_->bundle_data().code_signing_script());
217 code_signing_input_files.insert(
218 code_signing_input_files.end(),
219 target_->bundle_data().code_signing_sources().begin(),
220 target_->bundle_data().code_signing_sources().end());
221 for (const OutputFile& output_file : *output_files) {
222 code_signing_input_files.push_back(
223 output_file.AsSourceFile(settings_->build_settings()));
224 }
225 if (!input_dep.value().empty()) {
226 code_signing_input_files.push_back(
227 input_dep.AsSourceFile(settings_->build_settings()));
228 }
229
230 DCHECK(!code_signing_input_files.empty());
231 if (code_signing_input_files.size() == 1)
232 return OutputFile(settings_->build_settings(), code_signing_input_files[0]);
233
234 OutputFile code_signing_input_stamp_file =
235 OutputFile(RebasePath(GetTargetOutputDir(target_).value(),
236 settings_->build_settings()->build_dir(),
237 settings_->build_settings()->root_path_utf8()));
238 code_signing_input_stamp_file.value().append(target_->label().name());
239 code_signing_input_stamp_file.value().append(".codesigning.inputdeps.stamp");
240
241 out_ << "build ";
242 path_output_.WriteFile(out_, code_signing_input_stamp_file);
243 out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
244 << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
245
246 for (const SourceFile& source : code_signing_input_files) {
247 out_ << " ";
248 path_output_.WriteFile(out_, source);
249 }
250 out_ << std::endl;
251 return code_signing_input_stamp_file;
252 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698