| Index: tools/gn/ninja_create_bundle_target_writer.cc
|
| diff --git a/tools/gn/ninja_create_bundle_target_writer.cc b/tools/gn/ninja_create_bundle_target_writer.cc
|
| index 84da2ff2d4bc985a58511a8df4ae1e163d6e22e6..26701e50db59e6a886ae516aadaaf9ac5480129b 100644
|
| --- a/tools/gn/ninja_create_bundle_target_writer.cc
|
| +++ b/tools/gn/ninja_create_bundle_target_writer.cc
|
| @@ -4,6 +4,8 @@
|
|
|
| #include "tools/gn/ninja_create_bundle_target_writer.h"
|
|
|
| +#include "base/macros.h"
|
| +#include "base/strings/string_util.h"
|
| #include "tools/gn/filesystem_utils.h"
|
| #include "tools/gn/ninja_utils.h"
|
| #include "tools/gn/output_file.h"
|
| @@ -24,6 +26,22 @@ void FailWithMissingToolError(Toolchain::ToolType tool, const Target* target) {
|
| "doesn't define a \"" + tool_name + "\" tool."));
|
| }
|
|
|
| +bool EnsureAllToolsAvailable(const Target* target) {
|
| + const Toolchain::ToolType kRequiredTools[] = {
|
| + Toolchain::TYPE_COPY_BUNDLE_DATA, Toolchain::TYPE_COMPILE_XCASSETS,
|
| + Toolchain::TYPE_STAMP,
|
| + };
|
| +
|
| + for (size_t i = 0; i < arraysize(kRequiredTools); ++i) {
|
| + if (!target->toolchain()->GetTool(kRequiredTools[i])) {
|
| + FailWithMissingToolError(kRequiredTools[i], target);
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| } // namespace
|
|
|
| NinjaCreateBundleTargetWriter::NinjaCreateBundleTargetWriter(
|
| @@ -34,30 +52,75 @@ NinjaCreateBundleTargetWriter::NinjaCreateBundleTargetWriter(
|
| NinjaCreateBundleTargetWriter::~NinjaCreateBundleTargetWriter() {}
|
|
|
| void NinjaCreateBundleTargetWriter::Run() {
|
| - if (!target_->toolchain()->GetTool(Toolchain::TYPE_COPY_BUNDLE_DATA)) {
|
| - FailWithMissingToolError(Toolchain::TYPE_COPY_BUNDLE_DATA, target_);
|
| + if (!EnsureAllToolsAvailable(target_))
|
| return;
|
| - }
|
| -
|
| - if (!target_->toolchain()->GetTool(Toolchain::TYPE_COMPILE_XCASSETS)) {
|
| - FailWithMissingToolError(Toolchain::TYPE_COMPILE_XCASSETS, target_);
|
| - return;
|
| - }
|
|
|
| - if (!target_->toolchain()->GetTool(Toolchain::TYPE_STAMP)) {
|
| - FailWithMissingToolError(Toolchain::TYPE_STAMP, target_);
|
| - return;
|
| - }
|
| + std::string code_signing_rule_name = WriteCodeSigningRuleDefinition();
|
|
|
| - std::vector<OutputFile> output_files;
|
| OutputFile input_dep =
|
| WriteInputDepsStampAndGetDep(std::vector<const Target*>());
|
|
|
| + std::vector<OutputFile> output_files;
|
| + WriteCopyBundleDataRules(input_dep, &output_files);
|
| + WriteCompileAssetsCatalogRule(input_dep, &output_files);
|
| + WriteCodeSigningRules(code_signing_rule_name, input_dep, &output_files);
|
| +
|
| + std::vector<OutputFile> order_only_deps;
|
| + for (const auto& pair : target_->data_deps())
|
| + order_only_deps.push_back(pair.ptr->dependency_output_file());
|
| + WriteStampForTarget(output_files, order_only_deps);
|
| +
|
| + // Write a phony target for the outer bundle directory. This allows other
|
| + // targets to treat the entire bundle as a single unit, even though it is
|
| + // a directory, so that it can be depended upon as a discrete build edge.
|
| + out_ << "build ";
|
| + path_output_.WriteFile(
|
| + out_,
|
| + OutputFile(settings_->build_settings(),
|
| + target_->bundle_data().GetBundleRootDirOutput(settings_)));
|
| + out_ << ": phony " << target_->dependency_output_file().value();
|
| + out_ << std::endl;
|
| +}
|
| +
|
| +std::string NinjaCreateBundleTargetWriter::WriteCodeSigningRuleDefinition() {
|
| + if (target_->bundle_data().code_signing_script().is_null())
|
| + return std::string();
|
| +
|
| + std::string target_label = target_->label().GetUserVisibleName(true);
|
| + std::string custom_rule_name(target_label);
|
| + base::ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name);
|
| + custom_rule_name.append("_code_signing_rule");
|
| +
|
| + out_ << "rule " << custom_rule_name << std::endl;
|
| + out_ << " command = ";
|
| + path_output_.WriteFile(out_, settings_->build_settings()->python_path());
|
| + out_ << " ";
|
| + path_output_.WriteFile(out_, target_->bundle_data().code_signing_script());
|
| +
|
| + const SubstitutionList& args = target_->bundle_data().code_signing_args();
|
| + EscapeOptions args_escape_options;
|
| + args_escape_options.mode = ESCAPE_NINJA_COMMAND;
|
| +
|
| + for (const auto& arg : args.list()) {
|
| + out_ << " ";
|
| + SubstitutionWriter::WriteWithNinjaVariables(arg, args_escape_options, out_);
|
| + }
|
| + out_ << std::endl;
|
| + out_ << " description = CODE SIGNING " << target_label << std::endl;
|
| + out_ << " restat = 1" << std::endl;
|
| + out_ << std::endl;
|
| +
|
| + return custom_rule_name;
|
| +}
|
| +
|
| +void NinjaCreateBundleTargetWriter::WriteCopyBundleDataRules(
|
| + const OutputFile& input_dep,
|
| + std::vector<OutputFile>* output_files) {
|
| for (const BundleFileRule& file_rule : target_->bundle_data().file_rules()) {
|
| for (const SourceFile& source_file : file_rule.sources()) {
|
| OutputFile output_file = file_rule.ApplyPatternToSourceAsOutputFile(
|
| settings_, target_->bundle_data(), source_file);
|
| - output_files.push_back(output_file);
|
| + output_files->push_back(output_file);
|
|
|
| out_ << "build ";
|
| path_output_.WriteFile(out_, output_file);
|
| @@ -67,64 +130,123 @@ void NinjaCreateBundleTargetWriter::Run() {
|
| << " ";
|
| path_output_.WriteFile(out_, source_file);
|
| if (!input_dep.value().empty()) {
|
| - out_ << " || ";
|
| + out_ << " | ";
|
| path_output_.WriteFile(out_, input_dep);
|
| }
|
| out_ << std::endl;
|
| }
|
| }
|
| +}
|
|
|
| - if (!target_->bundle_data().asset_catalog_sources().empty()) {
|
| - OutputFile output_file(
|
| - settings_->build_settings(),
|
| - target_->bundle_data().GetCompiledAssetCatalogPath());
|
| - output_files.push_back(output_file);
|
| -
|
| - out_ << "build ";
|
| - path_output_.WriteFile(out_, output_file);
|
| - out_ << ": "
|
| - << GetNinjaRulePrefixForToolchain(settings_)
|
| - << Toolchain::ToolTypeToName(Toolchain::TYPE_COMPILE_XCASSETS);
|
| -
|
| - std::set<SourceFile> asset_catalog_bundles;
|
| - for (const auto& source : target_->bundle_data().asset_catalog_sources()) {
|
| - SourceFile asset_catalog_bundle;
|
| - CHECK(IsSourceFileFromAssetCatalog(source, &asset_catalog_bundle));
|
| - if (asset_catalog_bundles.find(asset_catalog_bundle) !=
|
| - asset_catalog_bundles.end())
|
| - continue;
|
| - out_ << " ";
|
| - path_output_.WriteFile(out_, asset_catalog_bundle);
|
| - asset_catalog_bundles.insert(asset_catalog_bundle);
|
| - }
|
| +void NinjaCreateBundleTargetWriter::WriteCompileAssetsCatalogRule(
|
| + const OutputFile& input_dep,
|
| + std::vector<OutputFile>* output_files) {
|
| + if (target_->bundle_data().asset_catalog_sources().empty())
|
| + return;
|
|
|
| - out_ << " |";
|
| - for (const auto& source : target_->bundle_data().asset_catalog_sources()) {
|
| - out_ << " ";
|
| - path_output_.WriteFile(out_, source);
|
| - }
|
| - if (!input_dep.value().empty()) {
|
| - out_ << " || ";
|
| - path_output_.WriteFile(out_, input_dep);
|
| - }
|
| - out_ << std::endl;
|
| + OutputFile output_file(settings_->build_settings(),
|
| + target_->bundle_data().GetCompiledAssetCatalogPath());
|
| + output_files->push_back(output_file);
|
| +
|
| + out_ << "build ";
|
| + path_output_.WriteFile(out_, output_file);
|
| + out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
|
| + << Toolchain::ToolTypeToName(Toolchain::TYPE_COMPILE_XCASSETS);
|
| +
|
| + std::set<SourceFile> asset_catalog_bundles;
|
| + for (const auto& source : target_->bundle_data().asset_catalog_sources()) {
|
| + SourceFile asset_catalog_bundle;
|
| + CHECK(IsSourceFileFromAssetCatalog(source, &asset_catalog_bundle));
|
| + if (asset_catalog_bundles.find(asset_catalog_bundle) !=
|
| + asset_catalog_bundles.end())
|
| + continue;
|
| + out_ << " ";
|
| + path_output_.WriteFile(out_, asset_catalog_bundle);
|
| + asset_catalog_bundles.insert(asset_catalog_bundle);
|
| + }
|
| +
|
| + out_ << " |";
|
| + for (const auto& source : target_->bundle_data().asset_catalog_sources()) {
|
| + out_ << " ";
|
| + path_output_.WriteFile(
|
| + out_, OutputFile(settings_->build_settings(), source));
|
| }
|
|
|
| + if (!input_dep.value().empty()) {
|
| + out_ << " ";
|
| + path_output_.WriteFile(out_, input_dep);
|
| + }
|
| out_ << std::endl;
|
| +}
|
|
|
| - std::vector<OutputFile> order_only_deps;
|
| - for (const auto& pair : target_->data_deps())
|
| - order_only_deps.push_back(pair.ptr->dependency_output_file());
|
| - WriteStampForTarget(output_files, order_only_deps);
|
| +void NinjaCreateBundleTargetWriter::WriteCodeSigningRules(
|
| + const std::string& code_signing_rule_name,
|
| + const OutputFile& input_dep,
|
| + std::vector<OutputFile>* output_files) {
|
| + if (code_signing_rule_name.empty())
|
| + return;
|
| +
|
| + OutputFile code_signing_input_stamp_file =
|
| + WriteCodeSigningInputDepsStamp(input_dep, output_files);
|
| +
|
| + out_ << "build";
|
| + std::vector<OutputFile> code_signing_output_files;
|
| + SubstitutionWriter::GetListAsOutputFiles(
|
| + settings_, target_->bundle_data().code_signing_outputs(),
|
| + &code_signing_output_files);
|
| + path_output_.WriteFiles(out_, code_signing_output_files);
|
| +
|
| + // Since the code signature step depends on all the files from the bundle,
|
| + // the create_bundle stamp can just depends on the output of the signature.
|
| + output_files->swap(code_signing_output_files);
|
| +
|
| + out_ << ": " << code_signing_rule_name;
|
| + if (!code_signing_input_stamp_file.value().empty()) {
|
| + out_ << " | ";
|
| + path_output_.WriteFile(out_, code_signing_input_stamp_file);
|
| + }
|
| + out_ << std::endl;
|
| +}
|
| +
|
| +OutputFile NinjaCreateBundleTargetWriter::WriteCodeSigningInputDepsStamp(
|
| + const OutputFile& input_dep,
|
| + std::vector<OutputFile>* output_files) {
|
| + std::vector<SourceFile> code_signing_input_files;
|
| + code_signing_input_files.push_back(
|
| + target_->bundle_data().code_signing_script());
|
| + code_signing_input_files.insert(
|
| + code_signing_input_files.end(),
|
| + target_->bundle_data().code_signing_sources().begin(),
|
| + target_->bundle_data().code_signing_sources().end());
|
| + for (const OutputFile& output_file : *output_files) {
|
| + code_signing_input_files.push_back(
|
| + output_file.AsSourceFile(settings_->build_settings()));
|
| + }
|
| + if (!input_dep.value().empty()) {
|
| + code_signing_input_files.push_back(
|
| + input_dep.AsSourceFile(settings_->build_settings()));
|
| + }
|
| +
|
| + DCHECK(!code_signing_input_files.empty());
|
| + if (code_signing_input_files.size() == 1)
|
| + return OutputFile(settings_->build_settings(), code_signing_input_files[0]);
|
| +
|
| + OutputFile code_signing_input_stamp_file =
|
| + OutputFile(RebasePath(GetTargetOutputDir(target_).value(),
|
| + settings_->build_settings()->build_dir(),
|
| + settings_->build_settings()->root_path_utf8()));
|
| + code_signing_input_stamp_file.value().append(target_->label().name());
|
| + code_signing_input_stamp_file.value().append(".codesigning.inputdeps.stamp");
|
|
|
| - // Write a phony target for the outer bundle directory. This allows other
|
| - // targets to treat the entire bundle as a single unit, even though it is
|
| - // a directory, so that it can be depended upon as a discrete build edge.
|
| out_ << "build ";
|
| - path_output_.WriteFile(
|
| - out_,
|
| - OutputFile(settings_->build_settings(),
|
| - target_->bundle_data().GetBundleRootDirOutput(settings_)));
|
| - out_ << ": phony " << target_->dependency_output_file().value();
|
| + path_output_.WriteFile(out_, code_signing_input_stamp_file);
|
| + out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
|
| + << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
|
| +
|
| + for (const SourceFile& source : code_signing_input_files) {
|
| + out_ << " ";
|
| + path_output_.WriteFile(out_, source);
|
| + }
|
| out_ << std::endl;
|
| + return code_signing_input_stamp_file;
|
| }
|
|
|