[swift] Update `gn check ...` to consider the generated header
The compilation of a Swift module generates an Objective-C header
to allow the interop between Swift and Objective-C. Update checker
to consider this generated header as part of the source_set. This
ensure that missing deps on swift_source_set(...) targets will be
reported by `gn check ...` in Chromium.
This would prevent regressions caused by missing deps such
as found and fixed by https://crrev.com/c/5348787.
Fixed: 361
Change-Id: I5394097030e0b08d5ebda58066b16fe2a5bddebf
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/16840
Reviewed-by: David Turner <digit@google.com>
Commit-Queue: Sylvain Defresne <sdefresne@chromium.org>
Reviewed-by: Takuto Ikuta <tikuta@google.com>
diff --git a/src/gn/header_checker.cc b/src/gn/header_checker.cc
index 1a93417..197084b 100644
--- a/src/gn/header_checker.cc
+++ b/src/gn/header_checker.cc
@@ -17,6 +17,7 @@
#include "gn/err.h"
#include "gn/filesystem_utils.h"
#include "gn/scheduler.h"
+#include "gn/swift_values.h"
#include "gn/target.h"
#include "gn/trace.h"
#include "util/worker_pool.h"
@@ -214,16 +215,6 @@
files_to_public[source].is_public = default_public;
}
- // If the target includes some .swift files, it may also use a header file
- // to provide bridging Objective-C code. This header needs to be considered
- // as a source file with the default visibility.
- if (target->has_swift_values()) {
- const SourceFile& bridge_header = target->swift_values().bridge_header();
- if (!bridge_header.is_null()) {
- files_to_public[bridge_header].is_public = default_public;
- }
- }
-
// Add in the public files, forcing them to public. This may overwrite some
// entries, and it may add new ones.
if (default_public) // List only used when default is not public.
@@ -232,6 +223,27 @@
files_to_public[source].is_public = true;
}
+ // If target generates a swiftmodule, then
+ // - it may use a bridge header which has default visibility
+ // - it may generate public header which must be considered public
+ if (target->builds_swift_module()) {
+ const SourceFile& bridge_header = target->swift_values().bridge_header();
+ if (!bridge_header.is_null()) {
+ files_to_public[bridge_header].is_public = default_public;
+ }
+
+ std::vector<SourceFile> outputs;
+ target->swift_values().GetOutputsAsSourceFiles(target, &outputs);
+
+ for (const SourceFile& output : outputs) {
+ if (output.GetType() == SourceFile::SOURCE_H) {
+ PublicGeneratedPair* pair = &files_to_public[output];
+ pair->is_public = true;
+ pair->is_generated = true;
+ }
+ }
+ }
+
// Add in outputs from actions. These are treated as public (since if other
// targets can't use them, then there wouldn't be any point in outputting).
std::vector<SourceFile> outputs;
diff --git a/src/gn/header_checker.h b/src/gn/header_checker.h
index 55c9259..fd053dd 100644
--- a/src/gn/header_checker.h
+++ b/src/gn/header_checker.h
@@ -74,11 +74,10 @@
FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, CheckInclude);
FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, PublicFirst);
FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, CheckIncludeAllowCircular);
+ FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, CheckIncludeSwiftModule);
FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, SourceFileForInclude);
FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest,
SourceFileForInclude_FileNotFound);
- FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest,
- SourceFileForInclude_SwiftBridgeHeader);
FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, Friend);
~HeaderChecker();
diff --git a/src/gn/header_checker_unittest.cc b/src/gn/header_checker_unittest.cc
index 2a168fd..00a82d3 100644
--- a/src/gn/header_checker_unittest.cc
+++ b/src/gn/header_checker_unittest.cc
@@ -314,6 +314,54 @@
EXPECT_EQ(errors.size(), 0);
}
+// Check that CheckInclude() support swift targets.
+TEST_F(HeaderCheckerTest, CheckIncludeSwiftModule) {
+ // A target S that build a swift module.
+ Target s(setup_.settings(), Label(SourceDir("//s"), "s"));
+ s.set_output_type(Target::SOURCE_SET);
+
+ Err err;
+ s.SetToolchain(setup_.toolchain(), &err);
+ ASSERT_FALSE(err.has_error());
+
+ const SourceFile bridge_header("//bridge.h");
+ const SourceFile generated_header("//out/Debug/gen/s/s.h");
+
+ // S contains Swift sources and has bridge header set.
+ s.swift_values().module_name() = "s";
+ s.swift_values().bridge_header() = SourceFile("//bridge.h");
+ s.sources().push_back(SourceFile("//some_file.swift"));
+ s.source_types_used().Set(SourceFile::SOURCE_SWIFT);
+ s.visibility().SetPublic();
+
+ s.OnResolved(&err);
+ ASSERT_FALSE(err.has_error());
+ targets_.push_back(&s);
+
+ auto checker = CreateChecker();
+
+ InputFile input_file(SourceFile("//some_file.cc"));
+ input_file.SetContents(std::string());
+ LocationRange range; // Dummy value.
+
+ std::vector<Err> errors;
+ std::set<std::pair<const Target*, const Target*>> no_dependency_cache;
+
+ // Check that unrelated target D cannot include header generated by S.
+ errors.clear();
+ no_dependency_cache.clear();
+ checker->CheckInclude(&d_, input_file, generated_header, range,
+ &no_dependency_cache, &errors);
+ EXPECT_GT(errors.size(), 0);
+
+ // Check that unrelated target D cannot include S's bridge header.
+ errors.clear();
+ no_dependency_cache.clear();
+ checker->CheckInclude(&d_, input_file, bridge_header, range,
+ &no_dependency_cache, &errors);
+ EXPECT_GT(errors.size(), 0);
+}
+
TEST_F(HeaderCheckerTest, SourceFileForInclude) {
using base::FilePath;
const std::vector<SourceDir> kIncludeDirs = {
@@ -391,16 +439,6 @@
EXPECT_FALSE(err.has_error());
}
-TEST_F(HeaderCheckerTest, SourceFileForInclude_SwiftBridgeHeader) {
- const SourceFile bridge_header("//a/bridge_header.h");
- a_.swift_values().bridge_header() = bridge_header;
- auto checker = CreateChecker();
-
- HeaderChecker::FileMap file_map;
- checker->AddTargetToFileMap(&a_, &file_map);
- EXPECT_NE(file_map.find(bridge_header), file_map.end());
-}
-
TEST_F(HeaderCheckerTest, Friend) {
// Note: we have a public dependency chain A -> B -> C set up already.
InputFile input_file(SourceFile("//some_file.cc"));
diff --git a/src/gn/json_project_writer_unittest.cc b/src/gn/json_project_writer_unittest.cc
index cab6dd7..b581051 100644
--- a/src/gn/json_project_writer_unittest.cc
+++ b/src/gn/json_project_writer_unittest.cc
@@ -251,7 +251,7 @@
"framework_switch": "-framework ",
"lib_dir_switch": "-L",
"lib_switch": "-l",
- "outputs": [ "{{target_out_dir}}/{{module_name}}.swiftmodule" ],
+ "outputs": [ "{{target_gen_dir}}/{{target_output_name}}.h", "{{target_out_dir}}/{{module_name}}.swiftmodule" ],
"partial_outputs": [ "{{target_out_dir}}/{{source_name_part}}.o" ],
"weak_framework_switch": "-weak_framework "
}
@@ -476,7 +476,7 @@
"framework_switch": "-framework ",
"lib_dir_switch": "-L",
"lib_switch": "-l",
- "outputs": [ "{{target_out_dir}}/{{module_name}}.swiftmodule" ],
+ "outputs": [ "{{target_gen_dir}}/{{target_output_name}}.h", "{{target_out_dir}}/{{module_name}}.swiftmodule" ],
"partial_outputs": [ "{{target_out_dir}}/{{source_name_part}}.o" ],
"weak_framework_switch": "-weak_framework "
}
@@ -725,7 +725,7 @@
"framework_switch": "-framework ",
"lib_dir_switch": "-L",
"lib_switch": "-l",
- "outputs": [ "{{target_out_dir}}/{{module_name}}.swiftmodule" ],
+ "outputs": [ "{{target_gen_dir}}/{{target_output_name}}.h", "{{target_out_dir}}/{{module_name}}.swiftmodule" ],
"partial_outputs": [ "{{target_out_dir}}/{{source_name_part}}.o" ],
"weak_framework_switch": "-weak_framework "
}
diff --git a/src/gn/ninja_binary_target_writer_unittest.cc b/src/gn/ninja_binary_target_writer_unittest.cc
index 5fd066b..ab12c68 100644
--- a/src/gn/ninja_binary_target_writer_unittest.cc
+++ b/src/gn/ninja_binary_target_writer_unittest.cc
@@ -38,6 +38,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -72,6 +73,7 @@
"defines =\n"
"include_dirs =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -99,6 +101,7 @@
"defines =\n"
"include_dirs =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libbar\n"
"\n"
@@ -136,6 +139,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -171,6 +175,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
diff --git a/src/gn/ninja_c_binary_target_writer.cc b/src/gn/ninja_c_binary_target_writer.cc
index 5be23d8..9b656bf 100644
--- a/src/gn/ninja_c_binary_target_writer.cc
+++ b/src/gn/ninja_c_binary_target_writer.cc
@@ -504,33 +504,14 @@
const std::vector<OutputFile>& input_deps,
const std::vector<OutputFile>& order_only_deps,
std::vector<OutputFile>* object_files) {
- DCHECK(target_->source_types_used().SwiftSourceUsed());
- object_files->reserve(object_files->size() + target_->sources().size());
-
- // If the target contains .swift source files, they needs to be compiled as
- // a single unit but still can produce more than one object file (if the
- // whole module optimization is disabled).
- const Tool* tool =
- target_->toolchain()->GetToolForSourceType(SourceFile::SOURCE_SWIFT);
- DCHECK(!tool->outputs().list().empty());
+ DCHECK(target_->builds_swift_module());
std::vector<OutputFile> outputs;
- SubstitutionWriter::ApplyListToLinkerAsOutputFile(target_, tool,
- tool->outputs(), &outputs);
+ target_->swift_values().GetOutputs(target_, &outputs);
- // Expand partial outputs too (if any).
- for (const SourceFile& source : target_->sources()) {
- if (!source.IsSwiftType())
- continue;
-
- SubstitutionWriter::ApplyListToCompilerAsOutputFile(
- target_, source, tool->partial_outputs(), &outputs);
- }
-
+ const BuildSettings* build_settings = settings_->build_settings();
for (const OutputFile& output : outputs) {
- const SourceFile output_as_source =
- output.AsSourceFile(target_->settings()->build_settings());
-
+ const SourceFile output_as_source = output.AsSourceFile(build_settings);
if (output_as_source.IsObjectType()) {
object_files->push_back(output);
}
@@ -541,9 +522,11 @@
swift_order_only_deps.Append(order_only_deps.begin(), order_only_deps.end());
for (const Target* swiftmodule :
- resolved().GetSwiftModuleDependencies(target_))
+ resolved().GetSwiftModuleDependencies(target_)) {
swift_order_only_deps.push_back(swiftmodule->dependency_output_file());
+ }
+ const Tool* tool = target_->swift_values().GetTool(target_);
WriteCompilerBuildLine(target_->sources(), input_deps,
swift_order_only_deps.vector(), tool->name(), outputs,
/*can_write_source_info=*/false,
diff --git a/src/gn/ninja_c_binary_target_writer_unittest.cc b/src/gn/ninja_c_binary_target_writer_unittest.cc
index d64e4a6..3815ab4 100644
--- a/src/gn/ninja_c_binary_target_writer_unittest.cc
+++ b/src/gn/ninja_c_binary_target_writer_unittest.cc
@@ -50,6 +50,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -82,6 +83,7 @@
"defines =\n"
"include_dirs =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libshlib\n"
"\n"
@@ -118,6 +120,7 @@
"defines =\n"
"include_dirs =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libstlib\n"
"\n"
@@ -143,6 +146,7 @@
"defines =\n"
"include_dirs =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libstlib\n"
"\n"
@@ -205,6 +209,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libbar\n"
"\n"
@@ -253,6 +258,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libbar\n"
"\n"
@@ -284,6 +290,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libbar\n"
"\n"
@@ -336,6 +343,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libshlib\n"
"\n"
@@ -403,6 +411,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = gen_obj\n"
"\n"
@@ -439,6 +448,7 @@
"defines =\n"
"include_dirs =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libgen_lib\n"
"\n"
@@ -480,6 +490,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = final_target\n"
"\n"
@@ -524,6 +535,7 @@
"defines =\n"
"include_dirs =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libshlib\n"
"\n"
@@ -586,6 +598,7 @@
"defines =\n"
"include_dirs =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libshlib\n"
"\n"
@@ -631,6 +644,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = shlib\n"
"\n"
@@ -689,6 +703,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = inter\n"
"\n"
@@ -724,6 +739,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = exe\n"
"\n"
@@ -765,6 +781,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libbar\n"
"\n"
@@ -804,6 +821,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libbar\n"
"\n"
@@ -841,6 +859,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = exe\n"
"\n"
@@ -1195,6 +1214,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -1230,6 +1250,7 @@
"defines =\n"
"include_dirs =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libbar\n"
"\n"
@@ -1268,6 +1289,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -1322,6 +1344,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -1378,6 +1401,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/bar\n"
"target_out_dir = obj/bar\n"
"target_output_name = bar\n"
"\n"
@@ -1554,6 +1578,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/exe\n"
"target_out_dir = obj/exe\n"
"target_output_name = exe\n"
"\n"
@@ -1721,6 +1746,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/exe\n"
"target_out_dir = obj/exe\n"
"target_output_name = exe\n"
"\n"
@@ -1797,6 +1823,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/bar\n"
"target_out_dir = obj/bar\n"
"target_output_name = bar\n"
"\n"
@@ -1899,6 +1926,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/exe\n"
"target_out_dir = obj/exe\n"
"target_output_name = binary\n"
"\n"
@@ -1994,6 +2022,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/exe\n"
"target_out_dir = obj/exe\n"
"target_output_name = binary\n"
"\n"
@@ -2091,6 +2120,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/exe\n"
"target_out_dir = obj/exe\n"
"target_output_name = binary\n"
"\n"
@@ -2200,6 +2230,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/exe\n"
"target_out_dir = obj/exe\n"
"target_output_name = binary\n"
"\n"
@@ -2249,6 +2280,7 @@
"cflags =\n"
"cflags_cc =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = libbar\n"
"\n"
@@ -2295,11 +2327,12 @@
"module_name = Foo\n"
"module_dirs =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = foo\n"
"\n"
- "build obj/foo/Foo.swiftmodule obj/foo/file1.o obj/foo/file2.o: swift"
- " ../../foo/file1.swift ../../foo/file2.swift\n"
+ "build gen/foo/foo.h obj/foo/Foo.swiftmodule obj/foo/file1.o "
+ "obj/foo/file2.o: swift ../../foo/file1.swift ../../foo/file2.swift\n"
" restat = 1\n"
"\n"
"build obj/foo/foo.stamp: stamp"
@@ -2331,11 +2364,12 @@
"module_name = Bar\n"
"module_dirs = -Iobj/foo\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/bar\n"
"target_out_dir = obj/bar\n"
"target_output_name = bar\n"
"\n"
- "build obj/bar/Bar.swiftmodule obj/bar/bar.o: swift ../../bar/bar.swift"
- " || obj/foo/foo.stamp\n"
+ "build gen/bar/bar.h obj/bar/Bar.swiftmodule obj/bar/bar.o: swift "
+ "../../bar/bar.swift || obj/foo/foo.stamp\n"
" restat = 1\n"
"\n"
"build obj/bar/bar.stamp: stamp obj/bar/bar.o "
@@ -2375,11 +2409,12 @@
"module_name = Bar\n"
"module_dirs = -Iobj/foo\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/bar\n"
"target_out_dir = obj/bar\n"
"target_output_name = bar\n"
"\n"
- "build obj/bar/Bar.swiftmodule obj/bar/bar.o: swift ../../bar/bar.swift"
- " || obj/bar/group.stamp obj/foo/foo.stamp\n"
+ "build gen/bar/bar.h obj/bar/Bar.swiftmodule obj/bar/bar.o: swift "
+ "../../bar/bar.swift || obj/bar/group.stamp obj/foo/foo.stamp\n"
" restat = 1\n"
"\n"
"build obj/bar/bar.stamp: stamp obj/bar/bar.o "
@@ -2406,6 +2441,7 @@
"defines =\n"
"include_dirs =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/bar\n"
"target_out_dir = obj/bar\n"
"target_output_name = bar\n"
"\n"
@@ -2695,6 +2731,7 @@
const char expected[] = R"(defines =
include_dirs =
root_out_dir = .
+target_gen_dir = gen/launchpad
target_out_dir = obj/launchpad
target_output_name = main
@@ -2745,6 +2782,7 @@
"defines =\n"
"include_dirs =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
diff --git a/src/gn/ninja_rust_binary_target_writer_unittest.cc b/src/gn/ninja_rust_binary_target_writer_unittest.cc
index 706f075..e3468a9 100644
--- a/src/gn/ninja_rust_binary_target_writer_unittest.cc
+++ b/src/gn/ninja_rust_binary_target_writer_unittest.cc
@@ -60,6 +60,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -114,6 +115,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/baz\n"
"target_out_dir = obj/baz\n"
"target_output_name = libprivatelib\n"
"\n"
@@ -155,6 +157,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/far\n"
"target_out_dir = obj/far\n"
"target_output_name = libfarlib\n"
"\n"
@@ -196,6 +199,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/bar\n"
"target_out_dir = obj/bar\n"
"target_output_name = libpubliclib\n"
"\n"
@@ -251,6 +255,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/main\n"
"target_out_dir = obj/main\n"
"target_output_name = main\n"
"\n"
@@ -303,6 +308,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/faz\n"
"target_out_dir = obj/faz\n"
"target_output_name = libprivate_inside\n"
"\n"
@@ -343,6 +349,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/baz\n"
"target_out_dir = obj/baz\n"
"target_output_name = libinside\n"
"\n"
@@ -386,6 +393,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/bar\n"
"target_out_dir = obj/bar\n"
"target_output_name = libmylib\n"
"\n"
@@ -458,6 +466,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -509,6 +518,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/bar\n"
"target_out_dir = obj/bar\n"
"target_output_name = libmymacro\n"
"\n"
@@ -568,6 +578,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/bar\n"
"target_out_dir = obj/bar\n"
"target_output_name = libmylib\n"
"\n"
@@ -610,6 +621,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -701,6 +713,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -803,6 +816,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -850,6 +864,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -891,6 +906,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/baz\n"
"target_out_dir = obj/baz\n"
"target_output_name = libbaz\n"
"\n"
@@ -1062,6 +1078,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/exe\n"
"target_out_dir = obj/exe\n"
"target_output_name = exe\n"
"\n"
@@ -1129,6 +1146,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -1195,6 +1213,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -1294,6 +1313,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = librlibcrate\n"
"\n"
@@ -1377,6 +1397,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/bar\n"
"target_out_dir = obj/bar\n"
"target_output_name = libmymacro\n"
"\n"
@@ -1423,6 +1444,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -1468,6 +1490,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/bar\n"
"target_out_dir = obj/bar\n"
"target_output_name = libmylib\n"
"\n"
@@ -1516,6 +1539,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -1570,6 +1594,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -1620,6 +1645,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -1664,6 +1690,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/bar\n"
"target_out_dir = obj/bar\n"
"target_output_name = libmylib\n"
"\n"
@@ -1704,6 +1731,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -1781,6 +1809,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
@@ -1865,6 +1894,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/linked\n"
"target_out_dir = obj/linked\n"
"target_output_name = exe\n"
"\n"
@@ -1918,6 +1948,7 @@
"rustflags =\n"
"rustenv =\n"
"root_out_dir = .\n"
+ "target_gen_dir = gen/foo\n"
"target_out_dir = obj/foo\n"
"target_output_name = bar\n"
"\n"
diff --git a/src/gn/swift_values.cc b/src/gn/swift_values.cc
index 6faa9af..08f32ac 100644
--- a/src/gn/swift_values.cc
+++ b/src/gn/swift_values.cc
@@ -4,11 +4,14 @@
#include "gn/swift_values.h"
+#include <algorithm>
+
#include "gn/deps_iterator.h"
#include "gn/err.h"
#include "gn/settings.h"
#include "gn/substitution_writer.h"
#include "gn/target.h"
+#include "gn/tool.h"
SwiftValues::SwiftValues() = default;
@@ -16,49 +19,76 @@
// static
bool SwiftValues::OnTargetResolved(Target* target, Err* err) {
- return FillModuleOutputFile(target, err);
-}
-
-// static
-bool SwiftValues::FillModuleOutputFile(Target* target, Err* err) {
if (!target->builds_swift_module())
return true;
- const Tool* tool =
- target->toolchain()->GetToolForSourceType(SourceFile::SOURCE_SWIFT);
+ return target->swift_values().FillModuleOutputFile(target, err);
+}
- std::vector<OutputFile> outputs;
+const Tool* SwiftValues::GetTool(const Target* target) const {
+ DCHECK(target->builds_swift_module());
+ return target->toolchain()->GetToolForSourceType(SourceFile::SOURCE_SWIFT);
+}
+
+void SwiftValues::GetOutputs(const Target* target,
+ std::vector<OutputFile>* result) const {
+ const Tool* tool = GetTool(target);
+
+ // Expand tool's outputs().
SubstitutionWriter::ApplyListToLinkerAsOutputFile(target, tool,
- tool->outputs(), &outputs);
+ tool->outputs(), result);
- bool swiftmodule_output_found = false;
- SwiftValues& swift_values = target->swift_values();
- for (const OutputFile& output : outputs) {
- const SourceFile output_as_source =
- output.AsSourceFile(target->settings()->build_settings());
- if (!output_as_source.IsSwiftModuleType()) {
+ // Expand tool's partial_outputs() for each .swift source file.
+ for (const SourceFile& source : target->sources()) {
+ if (!source.IsSwiftType()) {
continue;
}
- if (swiftmodule_output_found) {
- *err = Err(tool->defined_from(), "Incorrect outputs for tool",
- "The outputs of tool " + std::string(tool->name()) +
- " must list exactly one .swiftmodule file");
- return false;
- }
-
- swift_values.module_output_file_ = output;
- swift_values.module_output_dir_ = output_as_source.GetDir();
-
- swiftmodule_output_found = true;
+ SubstitutionWriter::ApplyListToCompilerAsOutputFile(
+ target, source, tool->partial_outputs(), result);
}
+}
- if (!swiftmodule_output_found) {
+void SwiftValues::GetOutputsAsSourceFiles(
+ const Target* target,
+ std::vector<SourceFile>* result) const {
+ std::vector<OutputFile> outputs;
+ GetOutputs(target, &outputs);
+
+ result->reserve(outputs.size());
+
+ const BuildSettings* build_settings = target->settings()->build_settings();
+ for (const OutputFile& output : outputs) {
+ result->push_back(output.AsSourceFile(build_settings));
+ }
+}
+
+bool SwiftValues::FillModuleOutputFile(Target* target, Err* err) {
+ std::vector<OutputFile> outputs;
+ GetOutputs(target, &outputs);
+
+ // Keep only .swiftmodule output files.
+ const BuildSettings* build_settings = target->settings()->build_settings();
+ const auto iter = std::remove_if(
+ outputs.begin(), outputs.end(),
+ [build_settings](const OutputFile& output) -> bool {
+ SourceFile output_as_source_file = output.AsSourceFile(build_settings);
+ return !output_as_source_file.IsSwiftModuleType();
+ });
+ outputs.erase(iter, outputs.end());
+
+ // A target should generate exactly one .swiftmodule file.
+ if (outputs.size() != 1) {
+ const Tool* tool = GetTool(target);
*err = Err(tool->defined_from(), "Incorrect outputs for tool",
"The outputs of tool " + std::string(tool->name()) +
" must list exactly one .swiftmodule file");
return false;
}
+ module_output_file_ = outputs.front();
+ module_output_dir_ =
+ module_output_file_.AsSourceFile(build_settings).GetDir();
+
return true;
}
diff --git a/src/gn/swift_values.h b/src/gn/swift_values.h
index 198ca85..1dde1c2 100644
--- a/src/gn/swift_values.h
+++ b/src/gn/swift_values.h
@@ -14,6 +14,7 @@
class Err;
class Target;
+class Tool;
// Holds values specific to target that compile .swift files.
class SwiftValues {
@@ -43,9 +44,20 @@
// Computed when the target is resolved.
const SourceDir& module_output_dir() const { return module_output_dir_; }
+ // Returns the tool used for target.
+ const Tool* GetTool(const Target* target) const;
+
+ // Expands the toolchain's outputs and partial outputs for the target.
+ void GetOutputs(const Target* target, std::vector<OutputFile>* result) const;
+
+ // Expands the toolchain's outputs and partial outputs for the target,
+ // returning the values as SourceFile list.
+ void GetOutputsAsSourceFiles(const Target* target,
+ std::vector<SourceFile>* result) const;
+
private:
// Fill informations about .swiftmodule generated by this target.
- static bool FillModuleOutputFile(Target* target, Err* err);
+ bool FillModuleOutputFile(Target* target, Err* err);
// Name of the optional bridge header used to import Objective-C classes.
// Filled from the target, may be empty even if the target include .swift
diff --git a/src/gn/test_with_scope.cc b/src/gn/test_with_scope.cc
index 21a4c22..4f33a59 100644
--- a/src/gn/test_with_scope.cc
+++ b/src/gn/test_with_scope.cc
@@ -237,6 +237,7 @@
"swiftc --module-name {{module_name}} {{module_dirs}} {{inputs}}",
swift_tool.get());
swift_tool->set_outputs(SubstitutionList::MakeForTest(
+ "{{target_gen_dir}}/{{target_output_name}}.h",
"{{target_out_dir}}/{{module_name}}.swiftmodule"));
swift_tool->set_partial_outputs(SubstitutionList::MakeForTest(
"{{target_out_dir}}/{{source_name_part}}.o"));