Commit 4c75ba48 authored by sdefresne's avatar sdefresne Committed by Commit bot

Fix dependencies rules for create_bundle and bundle_data ninja steps.

Record the "bundle_data" target corresponding to a BundleFileRule object
so that the dependencies can be correctly computed when generating the
ninja steps for the "create_bundle" target.

Change the "stamp" step of "bundle_data" target in the generated ninja
to depends on the target dependencies and source files.

Change the "copy_bundle_data" steps of "create_bundle" target in the
generated ninja to depends on the "bundle_data" target that defined
the corresponding source files.

Change the "compile_xcassets" step of "create_bundle" target in the
generated ninja to depends on all the "bundle_data" targets that defined
the corresponding source files.

Change the rule used to determine whether a "bundle_data" source file
is part of an assets catalog (some file where incorrectly omitted causing
them to be incorrectly copied to the final bundle).

All those changes will allow the "copy_bundle_data" and "compile_xcassets"
steps to only depends on the targets that generate them (if any) and will
reduce the number of file copied into the final bundle during incremental
builds.

Fix unit tests with new expectations.

BUG=623501

Review-Url: https://codereview.chromium.org/2105613003
Cr-Commit-Position: refs/heads/master@{#403304}
parent 9303ce61
......@@ -297,6 +297,7 @@ test("gn_unittests") {
"ninja_action_target_writer_unittest.cc",
"ninja_binary_target_writer_unittest.cc",
"ninja_build_writer_unittest.cc",
"ninja_bundle_data_target_writer_unittest.cc",
"ninja_copy_target_writer_unittest.cc",
"ninja_create_bundle_target_writer_unittest.cc",
"ninja_group_target_writer_unittest.cc",
......
......@@ -14,33 +14,38 @@
namespace {
// Return directory of |path| without the trailing directory separator.
base::StringPiece FindDirNoTrailingSeparator(const base::StringPiece& path) {
base::StringPiece FindDirNoTrailingSeparator(base::StringPiece path) {
base::StringPiece::size_type pos = path.find_last_of("/\\");
if (pos == base::StringPiece::npos)
return base::StringPiece();
return base::StringPiece(path.data(), pos);
}
} // namespace
bool IsSourceFileFromAssetCatalog(const SourceFile& source,
bool IsSourceFileFromAssetsCatalog(base::StringPiece source,
SourceFile* asset_catalog) {
// Check that the file matches the following pattern:
// Check whether |source| matches one of the following pattern:
// .*\.xcassets/Contents.json
// .*\.xcassets/[^/]*\.appiconset/[^/]*
// .*\.xcassets/[^/]*\.imageset/[^/]*
base::StringPiece dir;
dir = FindDirNoTrailingSeparator(source.value());
if (!dir.ends_with(".imageset"))
return false;
// .*\.xcassets/[^/]*\.launchimage/[^/]*
bool is_file_from_asset_catalog = false;
base::StringPiece dir = FindDirNoTrailingSeparator(source);
if (source.ends_with("/Contents.json") && dir.ends_with(".xcassets")) {
is_file_from_asset_catalog = true;
} else if (dir.ends_with(".appiconset") || dir.ends_with(".imageset") ||
dir.ends_with(".launchimage")) {
dir = FindDirNoTrailingSeparator(dir);
if (!dir.ends_with(".xcassets"))
return false;
if (asset_catalog) {
is_file_from_asset_catalog = dir.ends_with(".xcassets");
}
if (is_file_from_asset_catalog && asset_catalog) {
std::string asset_catalog_path = dir.as_string();
*asset_catalog = SourceFile(SourceFile::SWAP_IN, &asset_catalog_path);
}
return true;
return is_file_from_asset_catalog;
}
} // namespace
BundleData::BundleData() {}
BundleData::~BundleData() {}
......@@ -51,16 +56,21 @@ void BundleData::AddBundleData(const Target* target) {
}
void BundleData::OnTargetResolved(Target* owning_target) {
// Only initialize file_rules_ and asset_catalog_sources for "create_bundle"
// Only initialize file_rules_ and assets_catalog_sources for "create_bundle"
// target (properties are only used by those targets).
if (owning_target->output_type() != Target::CREATE_BUNDLE)
return;
UniqueVector<const Target*> assets_catalog_deps;
UniqueVector<SourceFile> assets_catalog_sources;
for (const Target* target : bundle_deps_) {
SourceFiles file_rule_sources;
for (const SourceFile& source_file : target->sources()) {
if (IsSourceFileFromAssetCatalog(source_file, nullptr)) {
asset_catalog_sources_.push_back(source_file);
SourceFile assets_catalog;
if (IsSourceFileFromAssetsCatalog(source_file.value(), &assets_catalog)) {
assets_catalog_sources.push_back(assets_catalog);
assets_catalog_deps.push_back(target);
} else {
file_rule_sources.push_back(source_file);
}
......@@ -68,11 +78,19 @@ void BundleData::OnTargetResolved(Target* owning_target) {
if (!file_rule_sources.empty()) {
DCHECK_EQ(target->action_values().outputs().list().size(), 1u);
file_rules_.push_back(BundleFileRule(
file_rule_sources, target->action_values().outputs().list()[0]));
file_rules_.push_back(
BundleFileRule(target, file_rule_sources,
target->action_values().outputs().list()[0]));
}
}
assets_catalog_deps_.insert(assets_catalog_deps_.end(),
assets_catalog_deps.begin(),
assets_catalog_deps.end());
assets_catalog_sources_.insert(assets_catalog_sources_.end(),
assets_catalog_sources.begin(),
assets_catalog_sources.end());
GetSourceFiles(&owning_target->sources());
}
......@@ -81,8 +99,8 @@ void BundleData::GetSourceFiles(SourceFiles* sources) const {
sources->insert(sources->end(), file_rule.sources().begin(),
file_rule.sources().end());
}
sources->insert(sources->end(), asset_catalog_sources_.begin(),
asset_catalog_sources_.end());
sources->insert(sources->end(), assets_catalog_sources_.begin(),
assets_catalog_sources_.end());
if (!code_signing_script_.is_null()) {
sources->insert(sources->end(), code_signing_sources_.begin(),
code_signing_sources_.end());
......@@ -107,7 +125,7 @@ void BundleData::GetOutputsAsSourceFiles(
}
}
if (!asset_catalog_sources_.empty())
if (!assets_catalog_sources_.empty())
outputs_as_source->push_back(GetCompiledAssetCatalogPath());
if (!code_signing_script_.is_null()) {
......@@ -124,7 +142,7 @@ void BundleData::GetOutputsAsSourceFiles(
}
SourceFile BundleData::GetCompiledAssetCatalogPath() const {
DCHECK(!asset_catalog_sources_.empty());
DCHECK(!assets_catalog_sources_.empty());
std::string assets_car_path = resources_dir_.value() + "/Assets.car";
return SourceFile(SourceFile::SWAP_IN, &assets_car_path);
}
......
......@@ -19,19 +19,6 @@ class OutputFile;
class Settings;
class Target;
// Returns true if |source| correspond to the path of a file in an asset
// catalog. If defined |asset_catalog| is set to its path.
//
// An asset catalog is an OS X bundle with the ".xcassets" extension. It
// contains one directory per assets each of them with the ".imageset"
// extension.
//
// All asset catalogs are compiled by Xcode into single Assets.car file as
// part of the creation of an application or framework bundle. BundleData
// emulates this with the "compile_xcassets" tool.
bool IsSourceFileFromAssetCatalog(const SourceFile& source,
SourceFile* asset_catalog);
// BundleData holds the information required by "create_bundle" target.
class BundleData {
public:
......@@ -64,7 +51,7 @@ class BundleData {
SourceFiles* outputs_as_source) const;
// Returns the path to the compiled asset catalog. Only valid if
// asset_catalog_sources() is not empty.
// assets_catalog_sources() is not empty.
SourceFile GetCompiledAssetCatalogPath() const;
// Returns the path to the top-level directory of the bundle. This is
......@@ -83,9 +70,14 @@ class BundleData {
SourceDir GetBundleRootDirOutputAsDir(const Settings* settings) const;
// Returns the list of inputs for the compilation of the asset catalog.
SourceFiles& asset_catalog_sources() { return asset_catalog_sources_; }
const SourceFiles& asset_catalog_sources() const {
return asset_catalog_sources_;
SourceFiles& assets_catalog_sources() { return assets_catalog_sources_; }
const SourceFiles& assets_catalog_sources() const {
return assets_catalog_sources_;
}
// Returns the list of dependencies for the compilation of the asset catalog.
std::vector<const Target*> assets_catalog_deps() const {
return assets_catalog_deps_;
}
BundleFileRules& file_rules() { return file_rules_; }
......@@ -132,7 +124,8 @@ class BundleData {
const UniqueTargets& bundle_deps() const { return bundle_deps_; }
private:
SourceFiles asset_catalog_sources_;
SourceFiles assets_catalog_sources_;
std::vector<const Target*> assets_catalog_deps_;
BundleFileRules file_rules_;
UniqueTargets bundle_deps_;
......
......@@ -10,9 +10,13 @@
#include "tools/gn/substitution_writer.h"
#include "tools/gn/target.h"
BundleFileRule::BundleFileRule(const std::vector<SourceFile> sources,
BundleFileRule::BundleFileRule(const Target* bundle_data_target,
const std::vector<SourceFile> sources,
const SubstitutionPattern& pattern)
: sources_(sources), pattern_(pattern) {}
: target_(bundle_data_target), sources_(sources), pattern_(pattern) {
// target_ may be null during testing.
DCHECK(!target_ || target_->output_type() == Target::BUNDLE_DATA);
}
BundleFileRule::BundleFileRule(const BundleFileRule& other) = default;
......
......@@ -13,12 +13,14 @@
class BundleData;
class Settings;
class SourceFile;
class Target;
class OutputFile;
// BundleFileRule contains the information found in a "bundle_data" target.
class BundleFileRule {
public:
BundleFileRule(const std::vector<SourceFile> sources,
BundleFileRule(const Target* bundle_data_target,
const std::vector<SourceFile> sources,
const SubstitutionPattern& pattern);
BundleFileRule(const BundleFileRule& other);
~BundleFileRule();
......@@ -33,10 +35,15 @@ class BundleFileRule {
const BundleData& bundle_data,
const SourceFile& source_file) const;
// Returns the associated target (of type Target::BUNDLE_DATA). May be
// null during testing.
const Target* target() const { return target_; }
// Returns the list of SourceFiles.
const std::vector<SourceFile>& sources() const { return sources_; }
private:
const Target* target_;
std::vector<SourceFile> sources_;
SubstitutionPattern pattern_;
};
......
......@@ -264,6 +264,7 @@
'loader_unittest.cc',
'ninja_action_target_writer_unittest.cc',
'ninja_binary_target_writer_unittest.cc',
'ninja_bundle_data_target_writer_unittest.cc',
'ninja_copy_target_writer_unittest.cc',
'ninja_create_bundle_target_writer_unittest.cc',
'ninja_group_target_writer_unittest.cc',
......
......@@ -5,6 +5,8 @@
#include "tools/gn/ninja_bundle_data_target_writer.h"
#include "tools/gn/output_file.h"
#include "tools/gn/settings.h"
#include "tools/gn/target.h"
NinjaBundleDataTargetWriter::NinjaBundleDataTargetWriter(const Target* target,
std::ostream& out)
......@@ -13,7 +15,20 @@ NinjaBundleDataTargetWriter::NinjaBundleDataTargetWriter(const Target* target,
NinjaBundleDataTargetWriter::~NinjaBundleDataTargetWriter() {}
void NinjaBundleDataTargetWriter::Run() {
std::vector<OutputFile> files;
files.push_back(WriteInputDepsStampAndGetDep(std::vector<const Target*>()));
WriteStampForTarget(files, std::vector<OutputFile>());
std::vector<OutputFile> output_files;
for (const SourceFile& source_file : target_->sources()) {
output_files.push_back(
OutputFile(settings_->build_settings(), source_file));
}
std::vector<const Target*> extra_hard_deps;
OutputFile input_dep = WriteInputDepsStampAndGetDep(extra_hard_deps);
if (!input_dep.value().empty())
output_files.push_back(input_dep);
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);
}
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "tools/gn/ninja_bundle_data_target_writer.h"
#include <algorithm>
#include <sstream>
#include "testing/gtest/include/gtest/gtest.h"
#include "tools/gn/target.h"
#include "tools/gn/test_with_scope.h"
TEST(NinjaBundleDataTargetWriter, Run) {
Err err;
TestWithScope setup;
setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
bundle_data.set_output_type(Target::BUNDLE_DATA);
bundle_data.sources().push_back(SourceFile("//foo/input1.txt"));
bundle_data.sources().push_back(SourceFile("//foo/input2.txt"));
bundle_data.sources().push_back(
SourceFile("//foo/Foo.xcassets/Contents.json"));
bundle_data.sources().push_back(
SourceFile("//foo/Foo.xcassets/foo.imageset/Contents.json"));
bundle_data.sources().push_back(
SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29.png"));
bundle_data.sources().push_back(
SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png"));
bundle_data.sources().push_back(
SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png"));
bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
"{{bundle_resources_dir}}/{{source_file_part}}");
bundle_data.SetToolchain(setup.toolchain());
bundle_data.visibility().SetPublic();
ASSERT_TRUE(bundle_data.OnResolved(&err));
std::ostringstream out;
NinjaBundleDataTargetWriter writer(&bundle_data, out);
writer.Run();
const char expected[] =
"build obj/foo/data.stamp: stamp "
"../../foo/input1.txt "
"../../foo/input2.txt "
"../../foo/Foo.xcassets/Contents.json "
"../../foo/Foo.xcassets/foo.imageset/Contents.json "
"../../foo/Foo.xcassets/foo.imageset/FooIcon-29.png "
"../../foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png "
"../../foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png\n";
std::string out_str = out.str();
EXPECT_EQ(expected, out_str);
}
......@@ -57,13 +57,10 @@ void NinjaCreateBundleTargetWriter::Run() {
std::string code_signing_rule_name = WriteCodeSigningRuleDefinition();
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);
WriteCopyBundleDataSteps(&output_files);
WriteCompileAssetsCatalogStep(&output_files);
WriteCodeSigningStep(code_signing_rule_name, &output_files);
std::vector<OutputFile> order_only_deps;
for (const auto& pair : target_->data_deps())
......@@ -113,10 +110,18 @@ std::string NinjaCreateBundleTargetWriter::WriteCodeSigningRuleDefinition() {
return custom_rule_name;
}
void NinjaCreateBundleTargetWriter::WriteCopyBundleDataRules(
const OutputFile& input_dep,
void NinjaCreateBundleTargetWriter::WriteCopyBundleDataSteps(
std::vector<OutputFile>* output_files) {
for (const BundleFileRule& file_rule : target_->bundle_data().file_rules()) {
for (const BundleFileRule& file_rule : target_->bundle_data().file_rules())
WriteCopyBundleFileRuleSteps(file_rule, output_files);
}
void NinjaCreateBundleTargetWriter::WriteCopyBundleFileRuleSteps(
const BundleFileRule& file_rule,
std::vector<OutputFile>* output_files) {
// Note that we don't write implicit deps for copy steps. "copy_bundle_data"
// steps as this is most likely implemented using hardlink in the common case.
// See NinjaCopyTargetWriter::WriteCopyRules() for a detailed explanation.
for (const SourceFile& source_file : file_rule.sources()) {
OutputFile output_file = file_rule.ApplyPatternToSourceAsOutputFile(
settings_, target_->bundle_data(), source_file);
......@@ -124,26 +129,22 @@ void NinjaCreateBundleTargetWriter::WriteCopyBundleDataRules(
out_ << "build ";
path_output_.WriteFile(out_, output_file);
out_ << ": "
<< GetNinjaRulePrefixForToolchain(settings_)
<< Toolchain::ToolTypeToName(Toolchain::TYPE_COPY_BUNDLE_DATA)
<< " ";
out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
<< Toolchain::ToolTypeToName(Toolchain::TYPE_COPY_BUNDLE_DATA) << " ";
path_output_.WriteFile(out_, source_file);
if (!input_dep.value().empty()) {
out_ << " | ";
path_output_.WriteFile(out_, input_dep);
}
out_ << std::endl;
}
}
}
void NinjaCreateBundleTargetWriter::WriteCompileAssetsCatalogRule(
const OutputFile& input_dep,
void NinjaCreateBundleTargetWriter::WriteCompileAssetsCatalogStep(
std::vector<OutputFile>* output_files) {
if (target_->bundle_data().asset_catalog_sources().empty())
if (target_->bundle_data().assets_catalog_sources().empty())
return;
OutputFile input_dep = WriteCompileAssetsCatalogInputDepsStamp(
target_->bundle_data().assets_catalog_deps());
DCHECK(!input_dep.value().empty());
OutputFile output_file(settings_->build_settings(),
target_->bundle_data().GetCompiledAssetCatalogPath());
output_files->push_back(output_file);
......@@ -154,40 +155,53 @@ void NinjaCreateBundleTargetWriter::WriteCompileAssetsCatalogRule(
<< 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;
for (const auto& source : target_->bundle_data().assets_catalog_sources()) {
out_ << " ";
path_output_.WriteFile(out_, asset_catalog_bundle);
asset_catalog_bundles.insert(asset_catalog_bundle);
path_output_.WriteFile(out_, source);
asset_catalog_bundles.insert(source);
}
out_ << " |";
for (const auto& source : target_->bundle_data().asset_catalog_sources()) {
out_ << " ";
path_output_.WriteFile(
out_, OutputFile(settings_->build_settings(), source));
}
out_ << " | ";
path_output_.WriteFile(out_, input_dep);
out_ << std::endl;
}
if (!input_dep.value().empty()) {
OutputFile
NinjaCreateBundleTargetWriter::WriteCompileAssetsCatalogInputDepsStamp(
const std::vector<const Target*>& dependencies) {
DCHECK(!dependencies.empty());
if (dependencies.size() == 1)
return dependencies[0]->dependency_output_file();
OutputFile xcassets_input_stamp_file =
OutputFile(RebasePath(GetTargetOutputDir(target_).value(),
settings_->build_settings()->build_dir(),
settings_->build_settings()->root_path_utf8()));
xcassets_input_stamp_file.value().append(target_->label().name());
xcassets_input_stamp_file.value().append(".xcassets.inputdeps.stamp");
out_ << "build ";
path_output_.WriteFile(out_, xcassets_input_stamp_file);
out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
<< Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
for (const Target* target : dependencies) {
out_ << " ";
path_output_.WriteFile(out_, input_dep);
path_output_.WriteFile(out_, target->dependency_output_file());
}
out_ << std::endl;
return xcassets_input_stamp_file;
}
void NinjaCreateBundleTargetWriter::WriteCodeSigningRules(
void NinjaCreateBundleTargetWriter::WriteCodeSigningStep(
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);
WriteCodeSigningInputDepsStamp(output_files);
DCHECK(!code_signing_input_stamp_file.value().empty());
out_ << "build";
std::vector<OutputFile> code_signing_output_files;
......@@ -197,19 +211,17 @@ void NinjaCreateBundleTargetWriter::WriteCodeSigningRules(
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.
// the create_bundle stamp can just depends on the output of the signature
// script (dependencies are transitive).
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(
......@@ -222,15 +234,32 @@ OutputFile NinjaCreateBundleTargetWriter::WriteCodeSigningInputDepsStamp(
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()));
std::vector<const Target*> dependencies;
for (const auto& label_target_pair : target_->private_deps()) {
if (label_target_pair.ptr->output_type() == Target::BUNDLE_DATA)
continue;
dependencies.push_back(label_target_pair.ptr);
}
for (const auto& label_target_pair : target_->public_deps()) {
if (label_target_pair.ptr->output_type() == Target::BUNDLE_DATA)
continue;
dependencies.push_back(label_target_pair.ptr);
}
DCHECK(!code_signing_input_files.empty());
if (code_signing_input_files.size() == 1)
if (code_signing_input_files.size() == 1 && dependencies.empty())
return OutputFile(settings_->build_settings(), code_signing_input_files[0]);
// Remove possible duplicates (if a target is listed in both deps and
// public_deps.
std::sort(dependencies.begin(), dependencies.end(),
[](const Target* lhs, const Target* rhs) -> bool {
return lhs->label() < rhs->label();
});
dependencies.erase(std::unique(dependencies.begin(), dependencies.end()),
dependencies.end());
OutputFile code_signing_input_stamp_file =
OutputFile(RebasePath(GetTargetOutputDir(target_).value(),
settings_->build_settings()->build_dir(),
......@@ -247,6 +276,10 @@ OutputFile NinjaCreateBundleTargetWriter::WriteCodeSigningInputDepsStamp(
out_ << " ";
path_output_.WriteFile(out_, source);
}
for (const Target* target : dependencies) {
out_ << " ";
path_output_.WriteFile(out_, target->dependency_output_file());
}
out_ << std::endl;
return code_signing_input_stamp_file;
}
......@@ -8,6 +8,8 @@
#include "base/macros.h"
#include "tools/gn/ninja_target_writer.h"
class BundleFileRule;
// Writes a .ninja file for a bundle_data target type.
class NinjaCreateBundleTargetWriter : public NinjaTargetWriter {
public:
......@@ -23,33 +25,37 @@ class NinjaCreateBundleTargetWriter : public NinjaTargetWriter {
// defined, otherwise returns an empty string.
std::string WriteCodeSigningRuleDefinition();
// Writes the rule to copy files into the bundle.
// Writes the steps to copy files into the bundle.
//
// input_dep is a file expressing the shared dependencies. It will be a
// stamp file if there is more than one.
void WriteCopyBundleDataRules(const OutputFile& input_dep,
std::vector<OutputFile>* output_files);
// The list of newly created files will be added to |output_files|.
void WriteCopyBundleDataSteps(std::vector<OutputFile>* output_files);
// Writes the rule to compile assets catalogs.
// Writes the step to copy files BundleFileRule into the bundle.
//
// input_dep is a file expressing the shared dependencies. It will be a
// stamp file if there is more than one.
void WriteCompileAssetsCatalogRule(const OutputFile& input_dep,
// The list of newly created files will be added to |output_files|.
void WriteCopyBundleFileRuleSteps(const BundleFileRule& file_rule,
std::vector<OutputFile>* output_files);
// Writes the code signing rule (if a script is defined).
// Writes the step to compile assets catalogs.
//
// The list of newly created files will be added to |output_files|.
void WriteCompileAssetsCatalogStep(std::vector<OutputFile>* output_files);
// Writes the stamp file for the assets catalog compilation input
// dependencies.
OutputFile WriteCompileAssetsCatalogInputDepsStamp(
const std::vector<const Target*>& dependencies);
// Writes the code signing step (if a script is defined).
//
// input_dep is a file expressing the shared dependencies. It will be a
// stamp file if there is more than one. As the code signing may include
// a manifest of the file, this will depends on all files in output_files
// too.
void WriteCodeSigningRules(const std::string& code_signing_rule_name,
const OutputFile& input_dep,
// The list of newly created files will be added to |output_files|. As the
// code signing may depends on the full bundle structure, this step will
// depends on all files generated via other rules.
void WriteCodeSigningStep(const std::string& code_signing_rule_name,
std::vector<OutputFile>* output_files);
// Writes the stamp file for the code signing input dependencies.
OutputFile WriteCodeSigningInputDepsStamp(
const OutputFile& input_dep,
std::vector<OutputFile>* output_files);
DISALLOW_COPY_AND_ASSIGN(NinjaCreateBundleTargetWriter);
......
......@@ -14,48 +14,54 @@
namespace {
void SetupBundleDataDir(BundleData* bundle_data, const std::string& root_dir) {
std::string bundle_root_dir = root_dir + "/bar.bundle";
std::string bundle_root_dir = root_dir + "/bar.bundle/Contents";
bundle_data->root_dir() = SourceDir(bundle_root_dir);
bundle_data->resources_dir() = SourceDir(bundle_root_dir + "/Resources");
bundle_data->executable_dir() = SourceDir(bundle_root_dir + "/Executable");
bundle_data->plugins_dir() = SourceDir(bundle_root_dir + "/PlugIns");
bundle_data->executable_dir() = SourceDir(bundle_root_dir + "/MacOS");
bundle_data->plugins_dir() = SourceDir(bundle_root_dir + "/Plug Ins");
}
} // namespace
// Tests multiple files with an output pattern.
TEST(NinjaCreateBundleTargetWriter, Run) {
TestWithScope setup;
Err err;
TestWithScope setup;
setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
Target target(setup.settings(), Label(SourceDir("//baz/"), "bar"));
target.set_output_type(Target::CREATE_BUNDLE);
SetupBundleDataDir(&target.bundle_data(), "//out/Debug");
std::vector<SourceFile> sources;
sources.push_back(SourceFile("//foo/input1.txt"));
sources.push_back(SourceFile("//foo/input2.txt"));
target.bundle_data().file_rules().push_back(BundleFileRule(
sources, SubstitutionPattern::MakeForTest(
"{{bundle_resources_dir}}/{{source_file_part}}")));
target.SetToolchain(setup.toolchain());
ASSERT_TRUE(target.OnResolved(&err));
Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
bundle_data.set_output_type(Target::BUNDLE_DATA);
bundle_data.sources().push_back(SourceFile("//foo/input1.txt"));
bundle_data.sources().push_back(SourceFile("//foo/input2.txt"));
bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
"{{bundle_resources_dir}}/{{source_file_part}}");
bundle_data.SetToolchain(setup.toolchain());
bundle_data.visibility().SetPublic();
ASSERT_TRUE(bundle_data.OnResolved(&err));
Target create_bundle(
setup.settings(),
Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
setup.toolchain()->label().name()));
SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
create_bundle.set_output_type(Target::CREATE_BUNDLE);
create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
create_bundle.SetToolchain(setup.toolchain());
ASSERT_TRUE(create_bundle.OnResolved(&err));
std::ostringstream out;
NinjaCreateBundleTargetWriter writer(&target, out);
NinjaCreateBundleTargetWriter writer(&create_bundle, out);
writer.Run();
const char expected[] =
"build bar.bundle/Resources/input1.txt: copy_bundle_data "
"build bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
"../../foo/input1.txt\n"
"build bar.bundle/Resources/input2.txt: copy_bundle_data "
"build bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
"../../foo/input2.txt\n"
"build obj/baz/bar.stamp: stamp "
"bar.bundle/Resources/input1.txt "
"bar.bundle/Resources/input2.txt\n"
"bar.bundle/Contents/Resources/input1.txt "
"bar.bundle/Contents/Resources/input2.txt\n"
"build bar.bundle: phony obj/baz/bar.stamp\n";
std::string out_str = out.str();
EXPECT_EQ(expected, out_str);
......@@ -63,41 +69,48 @@ TEST(NinjaCreateBundleTargetWriter, Run) {
// Tests multiple files from asset catalog.
TEST(NinjaCreateBundleTargetWriter, AssetCatalog) {
TestWithScope setup;
Err err;
TestWithScope setup;
setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
Target target(setup.settings(), Label(SourceDir("//baz/"), "bar"));
target.set_output_type(Target::CREATE_BUNDLE);
SetupBundleDataDir(&target.bundle_data(), "//out/Debug");
std::vector<SourceFile>& asset_catalog_sources =
target.bundle_data().asset_catalog_sources();
asset_catalog_sources.push_back(
Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
bundle_data.set_output_type(Target::BUNDLE_DATA);
bundle_data.sources().push_back(
SourceFile("//foo/Foo.xcassets/Contents.json"));
bundle_data.sources().push_back(
SourceFile("//foo/Foo.xcassets/foo.imageset/Contents.json"));
asset_catalog_sources.push_back(
bundle_data.sources().push_back(
SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29.png"));
asset_catalog_sources.push_back(
bundle_data.sources().push_back(
SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png"));
asset_catalog_sources.push_back(
bundle_data.sources().push_back(
SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png"));
target.SetToolchain(setup.toolchain());
ASSERT_TRUE(target.OnResolved(&err));
bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
"{{bundle_resources_dir}}/{{source_file_part}}");
bundle_data.SetToolchain(setup.toolchain());
bundle_data.visibility().SetPublic();
ASSERT_TRUE(bundle_data.OnResolved(&err));
Target create_bundle(
setup.settings(),
Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
setup.toolchain()->label().name()));
SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
create_bundle.set_output_type(Target::CREATE_BUNDLE);
create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
create_bundle.SetToolchain(setup.toolchain());
ASSERT_TRUE(create_bundle.OnResolved(&err));
std::ostringstream out;
NinjaCreateBundleTargetWriter writer(&target, out);
NinjaCreateBundleTargetWriter writer(&create_bundle, out);
writer.Run();
const char expected[] =
"build bar.bundle/Resources/Assets.car: compile_xcassets "
"../../foo/Foo.xcassets | "
"../../foo/Foo.xcassets/foo.imageset/Contents.json "
"../../foo/Foo.xcassets/foo.imageset/FooIcon-29.png "
"../../foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png "
"../../foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png\n"
"build obj/baz/bar.stamp: stamp bar.bundle/Resources/Assets.car\n"
"build bar.bundle/Contents/Resources/Assets.car: compile_xcassets "
"../../foo/Foo.xcassets | obj/foo/data.stamp\n"
"build obj/baz/bar.stamp: stamp "
"bar.bundle/Contents/Resources/Assets.car\n"
"build bar.bundle: phony obj/baz/bar.stamp\n";
std::string out_str = out.str();
EXPECT_EQ(expected, out_str);
......@@ -105,43 +118,27 @@ TEST(NinjaCreateBundleTargetWriter, AssetCatalog) {
// Tests that the phony target for the top-level bundle directory is generated
// correctly.
TEST(NinjaCreateBundleTargetWriter, BundleRootDirOutput) {
TestWithScope setup;
TEST(NinjaCreateBundleTargetWriter, PhonyTarget) {
Err err;
TestWithScope setup;
setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
Target target(setup.settings(), Label(SourceDir("//baz/"), "bar"));
target.set_output_type(Target::CREATE_BUNDLE);
const std::string bundle_root_dir("//out/Debug/bar.bundle/Contents");
target.bundle_data().root_dir() = SourceDir(bundle_root_dir);
target.bundle_data().resources_dir() =
SourceDir(bundle_root_dir + "/Resources");
target.bundle_data().executable_dir() = SourceDir(bundle_root_dir + "/MacOS");
target.bundle_data().plugins_dir() = SourceDir(bundle_root_dir + "/Plug Ins");
std::vector<SourceFile> sources;
sources.push_back(SourceFile("//foo/input1.txt"));
sources.push_back(SourceFile("//foo/input2.txt"));
target.bundle_data().file_rules().push_back(BundleFileRule(
sources, SubstitutionPattern::MakeForTest(
"{{bundle_resources_dir}}/{{source_file_part}}")));
target.SetToolchain(setup.toolchain());
ASSERT_TRUE(target.OnResolved(&err));
Target create_bundle(
setup.settings(),
Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
setup.toolchain()->label().name()));
SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
create_bundle.set_output_type(Target::CREATE_BUNDLE);
create_bundle.SetToolchain(setup.toolchain());
ASSERT_TRUE(create_bundle.OnResolved(&err));
std::ostringstream out;
NinjaCreateBundleTargetWriter writer(&target, out);
NinjaCreateBundleTargetWriter writer(&create_bundle, out);
writer.Run();
const char expected[] =
"build bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
"../../foo/input1.txt\n"
"build bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
"../../foo/input2.txt\n"
"build obj/baz/bar.stamp: stamp "
"bar.bundle/Contents/Resources/input1.txt "
"bar.bundle/Contents/Resources/input2.txt\n"
"build obj/baz/bar.stamp: stamp\n"
"build bar.bundle: phony obj/baz/bar.stamp\n";
std::string out_str = out.str();
EXPECT_EQ(expected, out_str);
......@@ -149,148 +146,178 @@ TEST(NinjaCreateBundleTargetWriter, BundleRootDirOutput) {
// Tests complex target with multiple bundle_data sources, including
// some asset catalog.
TEST(NinjaCreateBundleTargetWriter, ImplicitDeps) {
TestWithScope setup;
TEST(NinjaCreateBundleTargetWriter, Complex) {
Err err;
TestWithScope setup;
setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
Target target(setup.settings(), Label(SourceDir("//baz/"), "bar"));
target.set_output_type(Target::CREATE_BUNDLE);
SetupBundleDataDir(&target.bundle_data(), "//out/Debug");
std::vector<SourceFile> sources1;
sources1.push_back(SourceFile("//foo/input1.txt"));
sources1.push_back(SourceFile("//foo/input2.txt"));
target.bundle_data().file_rules().push_back(BundleFileRule(
sources1, SubstitutionPattern::MakeForTest(
"{{bundle_resources_dir}}/{{source_file_part}}")));
std::vector<SourceFile> sources2;
sources2.push_back(SourceFile("//qux/Info.plist"));
target.bundle_data().file_rules().push_back(BundleFileRule(
sources2,
SubstitutionPattern::MakeForTest("{{bundle_root_dir}}/Info.plist")));
std::vector<SourceFile> empty_source;
target.bundle_data().file_rules().push_back(BundleFileRule(
empty_source, SubstitutionPattern::MakeForTest(
"{{bundle_plugins_dir}}/{{source_file_part}}")));
std::vector<SourceFile>& asset_catalog_sources =
target.bundle_data().asset_catalog_sources();
asset_catalog_sources.push_back(
Target bundle_data0(setup.settings(),
Label(SourceDir("//qux/"), "info_plist"));
bundle_data0.set_output_type(Target::BUNDLE_DATA);
bundle_data0.sources().push_back(SourceFile("//qux/qux-Info.plist"));
bundle_data0.action_values().outputs() =
SubstitutionList::MakeForTest("{{bundle_root_dir}}/Info.plist");
bundle_data0.SetToolchain(setup.toolchain());
bundle_data0.visibility().SetPublic();
ASSERT_TRUE(bundle_data0.OnResolved(&err));
Target bundle_data1(setup.settings(), Label(SourceDir("//foo/"), "data"));
bundle_data1.set_output_type(Target::BUNDLE_DATA);
bundle_data1.sources().push_back(SourceFile("//foo/input1.txt"));
bundle_data1.sources().push_back(SourceFile("//foo/input2.txt"));
bundle_data1.action_values().outputs() = SubstitutionList::MakeForTest(
"{{bundle_resources_dir}}/{{source_file_part}}");
bundle_data1.SetToolchain(setup.toolchain());
bundle_data1.visibility().SetPublic();
ASSERT_TRUE(bundle_data1.OnResolved(&err));
Target bundle_data2(setup.settings(), Label(SourceDir("//foo/"), "assets"));
bundle_data2.set_output_type(Target::BUNDLE_DATA);
bundle_data2.sources().push_back(
SourceFile("//foo/Foo.xcassets/Contents.json"));
bundle_data2.sources().push_back(
SourceFile("//foo/Foo.xcassets/foo.imageset/Contents.json"));
asset_catalog_sources.push_back(
bundle_data2.sources().push_back(
SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29.png"));
asset_catalog_sources.push_back(
bundle_data2.sources().push_back(
SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png"));
asset_catalog_sources.push_back(
bundle_data2.sources().push_back(
SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png"));
target.SetToolchain(setup.toolchain());
ASSERT_TRUE(target.OnResolved(&err));
bundle_data2.action_values().outputs() = SubstitutionList::MakeForTest(
"{{bundle_resources_dir}}/{{source_file_part}}");
bundle_data2.SetToolchain(setup.toolchain());
bundle_data2.visibility().SetPublic();
ASSERT_TRUE(bundle_data2.OnResolved(&err));
Target bundle_data3(setup.settings(), Label(SourceDir("//quz/"), "assets"));
bundle_data3.set_output_type(Target::BUNDLE_DATA);
bundle_data3.sources().push_back(
SourceFile("//quz/Quz.xcassets/Contents.json"));
bundle_data3.sources().push_back(
SourceFile("//quz/Quz.xcassets/quz.imageset/Contents.json"));
bundle_data3.sources().push_back(
SourceFile("//quz/Quz.xcassets/quz.imageset/QuzIcon-29.png"));
bundle_data3.sources().push_back(
SourceFile("//quz/Quz.xcassets/quz.imageset/QuzIcon-29@2x.png"));
bundle_data3.sources().push_back(
SourceFile("//quz/Quz.xcassets/quz.imageset/QuzIcon-29@3x.png"));
bundle_data3.action_values().outputs() = SubstitutionList::MakeForTest(
"{{bundle_resources_dir}}/{{source_file_part}}");
bundle_data3.SetToolchain(setup.toolchain());
bundle_data3.visibility().SetPublic();
ASSERT_TRUE(bundle_data3.OnResolved(&err));
Target create_bundle(
setup.settings(),
Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
setup.toolchain()->label().name()));
SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
create_bundle.set_output_type(Target::CREATE_BUNDLE);
create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data0));
create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data1));
create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data2));
create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data3));
create_bundle.SetToolchain(setup.toolchain());
ASSERT_TRUE(create_bundle.OnResolved(&err));
std::ostringstream out;
NinjaCreateBundleTargetWriter writer(&target, out);
NinjaCreateBundleTargetWriter writer(&create_bundle, out);
writer.Run();
const char expected[] =
"build bar.bundle/Resources/input1.txt: copy_bundle_data "
"build bar.bundle/Contents/Info.plist: copy_bundle_data "
"../../qux/qux-Info.plist\n"
"build bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
"../../foo/input1.txt\n"
"build bar.bundle/Resources/input2.txt: copy_bundle_data "
"build bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
"../../foo/input2.txt\n"
"build bar.bundle/Info.plist: copy_bundle_data "
"../../qux/Info.plist\n"
"build bar.bundle/Resources/Assets.car: compile_xcassets "
"../../foo/Foo.xcassets | "
"../../foo/Foo.xcassets/foo.imageset/Contents.json "
"../../foo/Foo.xcassets/foo.imageset/FooIcon-29.png "
"../../foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png "
"../../foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png\n"
"build obj/baz/bar.xcassets.inputdeps.stamp: stamp "
"obj/foo/assets.stamp "
"obj/quz/assets.stamp\n"
"build bar.bundle/Contents/Resources/Assets.car: compile_xcassets "
"../../foo/Foo.xcassets "
"../../quz/Quz.xcassets | obj/baz/bar.xcassets.inputdeps.stamp\n"
"build obj/baz/bar.stamp: stamp "
"bar.bundle/Resources/input1.txt "
"bar.bundle/Resources/input2.txt "
"bar.bundle/Info.plist "
"bar.bundle/Resources/Assets.car\n"
"bar.bundle/Contents/Info.plist "
"bar.bundle/Contents/Resources/input1.txt "
"bar.bundle/Contents/Resources/input2.txt "
"bar.bundle/Contents/Resources/Assets.car\n"
"build bar.bundle: phony obj/baz/bar.stamp\n";
std::string out_str = out.str();
EXPECT_EQ(expected, out_str);
}
// Tests multiple files with an output pattern.
// Tests code signing steps.
TEST(NinjaCreateBundleTargetWriter, CodeSigning) {
TestWithScope setup;
Err err;
TestWithScope setup;
setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
// Simulate a binary build by another target. Since no toolchain is defined
// use an action instead of an executable target for simplicity.
Target binary(setup.settings(), Label(SourceDir("//baz/"), "quz"));
binary.set_output_type(Target::EXECUTABLE);
binary.visibility().SetPublic();
binary.sources().push_back(SourceFile("//baz/quz.c"));
binary.set_output_name("obj/baz/quz/bin");
binary.set_output_prefix_override(true);
binary.SetToolchain(setup.toolchain());
ASSERT_TRUE(binary.OnResolved(&err));
Target target(setup.settings(),
Label(SourceDir("//baz/"), "bar",
setup.toolchain()->label().dir(),
Target executable(setup.settings(), Label(SourceDir("//baz/"), "quz"));
executable.set_output_type(Target::EXECUTABLE);
executable.sources().push_back(SourceFile("//baz/quz.c"));
executable.SetToolchain(setup.toolchain());
executable.visibility().SetPublic();
ASSERT_TRUE(executable.OnResolved(&err));
Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
bundle_data.set_output_type(Target::BUNDLE_DATA);
bundle_data.sources().push_back(SourceFile("//foo/input1.txt"));
bundle_data.sources().push_back(SourceFile("//foo/input2.txt"));
bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
"{{bundle_resources_dir}}/{{source_file_part}}");
bundle_data.SetToolchain(setup.toolchain());
bundle_data.visibility().SetPublic();
ASSERT_TRUE(bundle_data.OnResolved(&err));
Target create_bundle(
setup.settings(),
Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
setup.toolchain()->label().name()));
target.set_output_type(Target::CREATE_BUNDLE);
SetupBundleDataDir(&target.bundle_data(), "//out/Debug");
std::vector<SourceFile> sources;
sources.push_back(SourceFile("//foo/input1.txt"));
sources.push_back(SourceFile("//foo/input2.txt"));
target.bundle_data().file_rules().push_back(BundleFileRule(
sources, SubstitutionPattern::MakeForTest(
"{{bundle_resources_dir}}/{{source_file_part}}")));
target.bundle_data().set_code_signing_script(
SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
create_bundle.set_output_type(Target::CREATE_BUNDLE);
create_bundle.bundle_data().set_code_signing_script(
SourceFile("//build/codesign.py"));
target.bundle_data().code_signing_sources().push_back(
SourceFile("//out/Debug/obj/baz/quz/bin"));
target.bundle_data().code_signing_outputs() = SubstitutionList::MakeForTest(
"//out/Debug/bar.bundle/quz",
create_bundle.bundle_data().code_signing_sources().push_back(
SourceFile("//out/Debug/quz"));
create_bundle.bundle_data().code_signing_outputs() =
SubstitutionList::MakeForTest(
"//out/Debug/bar.bundle/Contents/quz",
"//out/Debug/bar.bundle/_CodeSignature/CodeResources");
target.bundle_data().code_signing_args() = SubstitutionList::MakeForTest(
"-b=obj/baz/quz/bin",
"bar.bundle");
target.public_deps().push_back(LabelTargetPair(&binary));
target.SetToolchain(setup.toolchain());
ASSERT_TRUE(target.OnResolved(&err));
create_bundle.bundle_data().code_signing_args() =
SubstitutionList::MakeForTest("-b=quz", "bar.bundle");
create_bundle.public_deps().push_back(LabelTargetPair(&executable));
create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
create_bundle.SetToolchain(setup.toolchain());
ASSERT_TRUE(create_bundle.OnResolved(&err));
std::ostringstream out;
NinjaCreateBundleTargetWriter writer(&target, out);
NinjaCreateBundleTargetWriter writer(&create_bundle, out);
writer.Run();
const char expected[] =
"rule __baz_bar___toolchain_default__code_signing_rule\n"
" command = ../../build/codesign.py -b=obj/baz/quz/bin bar.bundle\n"
" command = ../../build/codesign.py -b=quz bar.bundle\n"
" description = CODE SIGNING //baz:bar(//toolchain:default)\n"
" restat = 1\n"
"\n"
"build bar.bundle/Resources/input1.txt: copy_bundle_data "
"build bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
"../../foo/input1.txt\n"
"build bar.bundle/Resources/input2.txt: copy_bundle_data "
"build bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
"../../foo/input2.txt\n"
"build obj/baz/bar.codesigning.inputdeps.stamp: stamp "
"../../build/codesign.py "
"obj/baz/quz/bin "
"bar.bundle/Resources/input1.txt "
"bar.bundle/Resources/input2.txt\n"
"build bar.bundle/quz bar.bundle/_CodeSignature/CodeResources: "
"quz "
"bar.bundle/Contents/Resources/input1.txt "
"bar.bundle/Contents/Resources/input2.txt "
"./quz\n"
"build bar.bundle/Contents/quz bar.bundle/_CodeSignature/CodeResources: "
"__baz_bar___toolchain_default__code_signing_rule "
"| obj/baz/bar.codesigning.inputdeps.stamp\n"
"build obj/baz/bar.stamp: stamp "
"bar.bundle/quz "
"bar.bundle/Contents/quz "
"bar.bundle/_CodeSignature/CodeResources\n"
"build bar.bundle: phony obj/baz/bar.stamp\n";
std::string out_str = out.str();
......
......@@ -284,6 +284,7 @@ TEST(RuntimeDeps, CreateBundle) {
InitTargetWithType(setup, &module_data, Target::BUNDLE_DATA);
module_data.private_deps().push_back(LabelTargetPair(&loadable_module));
module_data.bundle_data().file_rules().push_back(BundleFileRule(
nullptr,
std::vector<SourceFile>{SourceFile(build_dir + "loadable_module.so")},
SubstitutionPattern::MakeForTest("{{bundle_resources_dir}}")));
ASSERT_TRUE(module_data.OnResolved(&err));
......@@ -305,7 +306,7 @@ TEST(RuntimeDeps, CreateBundle) {
InitTargetWithType(setup, &dylib_data, Target::BUNDLE_DATA);
dylib_data.private_deps().push_back(LabelTargetPair(&dylib));
dylib_data.bundle_data().file_rules().push_back(BundleFileRule(
std::vector<SourceFile>{SourceFile(build_dir + "dylib")},
nullptr, std::vector<SourceFile>{SourceFile(build_dir + "dylib")},
SubstitutionPattern::MakeForTest("{{bundle_executable_dir}}")));
ASSERT_TRUE(dylib_data.OnResolved(&err));
......
......@@ -907,7 +907,7 @@ TEST(Target, PullRecursiveBundleData) {
ASSERT_EQ(a.bundle_data().file_rules().size(), 2u);
ASSERT_EQ(a.bundle_data().file_rules()[0].sources().size(), 2u);
ASSERT_EQ(a.bundle_data().file_rules()[1].sources().size(), 3u);
ASSERT_EQ(a.bundle_data().asset_catalog_sources().size(), 4u);
ASSERT_EQ(a.bundle_data().assets_catalog_sources().size(), 1u);
ASSERT_EQ(a.bundle_data().bundle_deps().size(), 2u);
// C gets its data from D.
......@@ -918,6 +918,6 @@ TEST(Target, PullRecursiveBundleData) {
// E does not have any bundle_data information but gets a list of
// bundle_deps to propagate them during target resolution.
ASSERT_TRUE(e.bundle_data().file_rules().empty());
ASSERT_TRUE(e.bundle_data().asset_catalog_sources().empty());
ASSERT_TRUE(e.bundle_data().assets_catalog_sources().empty());
ASSERT_EQ(e.bundle_data().bundle_deps().size(), 2u);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment