[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"));