Refactor ModuleType from an enum to a bitset. This will significantly reduce the tech debt and reduce the difficulty in adding support for autogenerated nontextual modules. This also removes unneccesary modulemap, as it no longer serves a purpose now that we have double modulemaps. Bug: b:500845363 Change-Id: I192a62ccbdc7937328b84de6af5e9f186a6a6964 Reviewed-on: https://gn-review.googlesource.com/c/gn/+/21840 Reviewed-by: Takuto Ikuta <tikuta@google.com> Commit-Queue: Matt Stark <msta@google.com>
diff --git a/src/gn/binary_target_generator.cc b/src/gn/binary_target_generator.cc index 39eb47c..3fa160d 100644 --- a/src/gn/binary_target_generator.cc +++ b/src/gn/binary_target_generator.cc
@@ -295,15 +295,10 @@ const Value* generate_modulemap_val = scope_->GetValue(variables::kGenerateModulemap, true); + Target::ModuleType type; + type.set(Target::HAS_MODULEMAP); if (target_->source_types_used().Get(SourceFile::SOURCE_MODULEMAP)) { - target_->set_module_type(Target::EXPLICIT_MODULEMAP); - return true; - } - - if (target_->all_headers_public() - ? !target_->source_types_used().Get(SourceFile::SOURCE_H) - : target_->public_headers().empty()) { - target_->set_module_type(Target::UNNECESSARY_MODULEMAP); + target_->set_module_type(type); return true; } @@ -316,13 +311,26 @@ return false; } auto value = generate_modulemap_val->string_value(); + type.set(Target::MODULEMAP_IS_GENERATED); if (value == "textual") { - target_->set_module_type(Target::GENERATED_TEXTUAL_MODULEMAP); - } else if (value != "none") { + type.set(Target::MODULEMAP_IS_TEXTUAL); + } else if (value == "none" || value == "") { + return true; + } else { *err_ = Err(*generate_modulemap_val, "Invalid value for generate_modulemap. Expected \"textual\" or " "\"none\""); return false; } + + // Even if generate_modulemap was explicitly set, if we're compiling non-c++ + // code, we shouldn't mark it as a module. + if (target_->source_types_used().Get(SourceFile::SOURCE_CPP) || + (target_->all_headers_public() + ? target_->source_types_used().Get(SourceFile::SOURCE_H) + : !target_->public_headers().empty())) { + target_->set_module_type(type); + } + return true; }
diff --git a/src/gn/binary_target_generator_unittest.cc b/src/gn/binary_target_generator_unittest.cc index c1e4215..ba1ae5a 100644 --- a/src/gn/binary_target_generator_unittest.cc +++ b/src/gn/binary_target_generator_unittest.cc
@@ -12,7 +12,7 @@ using BinaryTargetGeneratorTest = TestWithScheduler; -TEST_F(BinaryTargetGeneratorTest, UnnecessaryModuleMapAllPublic) { +TEST_F(BinaryTargetGeneratorTest, NonModuleTarget) { TestWithScope setup; Scope::ItemVector items_; setup.scope()->set_item_collector(&items_); @@ -21,7 +21,7 @@ TestParseInput input( R"(static_library("foo") { generate_modulemap = "textual" - sources = [ "//foo.cc" ] + sources = [ "//foo.c" ] })"); ASSERT_FALSE(input.has_error()); @@ -33,7 +33,7 @@ Target* target = items_[0]->AsTarget(); ASSERT_TRUE(target); - EXPECT_EQ(Target::UNNECESSARY_MODULEMAP, target->module_type()); + EXPECT_TRUE(target->module_type().none()); } TEST_F(BinaryTargetGeneratorTest, GeneratedModuleMapAllPublic) { @@ -57,7 +57,9 @@ Target* target = items_[0]->AsTarget(); ASSERT_TRUE(target); - EXPECT_EQ(Target::GENERATED_TEXTUAL_MODULEMAP, target->module_type()); + EXPECT_TRUE(target->module_type().test(Target::HAS_MODULEMAP)); + EXPECT_TRUE(target->module_type().test(Target::MODULEMAP_IS_GENERATED)); + EXPECT_TRUE(target->module_type().test(Target::MODULEMAP_IS_TEXTUAL)); } TEST_F(BinaryTargetGeneratorTest, GeneratedModuleMap) { @@ -82,5 +84,7 @@ Target* target = items_[0]->AsTarget(); ASSERT_TRUE(target); - EXPECT_EQ(Target::GENERATED_TEXTUAL_MODULEMAP, target->module_type()); + EXPECT_TRUE(target->module_type().test(Target::HAS_MODULEMAP)); + EXPECT_TRUE(target->module_type().test(Target::MODULEMAP_IS_GENERATED)); + EXPECT_TRUE(target->module_type().test(Target::MODULEMAP_IS_TEXTUAL)); }
diff --git a/src/gn/compile_commands_writer_unittest.cc b/src/gn/compile_commands_writer_unittest.cc index 8069d0f..81ec2e2 100644 --- a/src/gn/compile_commands_writer_unittest.cc +++ b/src/gn/compile_commands_writer_unittest.cc
@@ -643,7 +643,9 @@ module_target.visibility().SetPublic(); module_target.sources().push_back(SourceFile("//foo/foo.modulemap")); module_target.source_types_used().Set(SourceFile::SOURCE_MODULEMAP); - module_target.set_module_type(Target::EXPLICIT_MODULEMAP); + Target::ModuleType module_type; + module_type.set(Target::HAS_MODULEMAP); + module_target.set_module_type(module_type); module_target.SetToolchain(&module_toolchain); ASSERT_TRUE(module_target.OnResolved(&err));
diff --git a/src/gn/ninja_binary_target_writer.cc b/src/gn/ninja_binary_target_writer.cc index 7355920..b93bd28 100644 --- a/src/gn/ninja_binary_target_writer.cc +++ b/src/gn/ninja_binary_target_writer.cc
@@ -47,7 +47,7 @@ for (const auto& pair : *current) { const Target* target = pair.ptr; if (visited.insert(target).second) { - if (target->module_type() == Target::NO_MODULEMAP) { + if (target->module_type().none()) { stack.push_back(&target->public_deps()); // If you declare `public_deps = ...` on a group, it shows up as a // private dep. Probably because groups don't distinguish between
diff --git a/src/gn/ninja_c_binary_target_writer_unittest.cc b/src/gn/ninja_c_binary_target_writer_unittest.cc index dce8dfd..41dd35d 100644 --- a/src/gn/ninja_c_binary_target_writer_unittest.cc +++ b/src/gn/ninja_c_binary_target_writer_unittest.cc
@@ -20,6 +20,11 @@ using NinjaCBinaryTargetWriterTest = TestWithScheduler; +constexpr Target::ModuleType kExplicitModulemap = 1 << Target::HAS_MODULEMAP; +constexpr Target::ModuleType kGeneratedTextualModulemap = + 1 << Target::HAS_MODULEMAP | 1 << Target::MODULEMAP_IS_GENERATED | + 1 << Target::MODULEMAP_IS_TEXTUAL; + TEST_F(NinjaCBinaryTargetWriterTest, SourceSet) { Err err; TestWithScope setup; @@ -2271,7 +2276,7 @@ target.sources().push_back(SourceFile("//foo/bar.modulemap")); target.source_types_used().Set(SourceFile::SOURCE_CPP); target.source_types_used().Set(SourceFile::SOURCE_MODULEMAP); - target.set_module_type(Target::EXPLICIT_MODULEMAP); + target.set_module_type(kExplicitModulemap); ASSERT_TRUE(target.OnResolved(&err)); std::ostringstream out; @@ -2313,7 +2318,7 @@ target.sources().push_back(SourceFile("//foo/bar.modulemap")); target.source_types_used().Set(SourceFile::SOURCE_CPP); target.source_types_used().Set(SourceFile::SOURCE_MODULEMAP); - target.set_module_type(Target::EXPLICIT_MODULEMAP); + target.set_module_type(kExplicitModulemap); ASSERT_TRUE(target.OnResolved(&err)); std::ostringstream out; @@ -2574,7 +2579,7 @@ target.sources().push_back(SourceFile("//blah/a.h")); target.source_types_used().Set(SourceFile::SOURCE_CPP); target.source_types_used().Set(SourceFile::SOURCE_MODULEMAP); - target.set_module_type(Target::EXPLICIT_MODULEMAP); + target.set_module_type(kExplicitModulemap); target.SetToolchain(&module_toolchain); ASSERT_TRUE(target.OnResolved(&err)); @@ -2622,7 +2627,7 @@ target2.sources().push_back(SourceFile("//stuff/b.h")); target2.source_types_used().Set(SourceFile::SOURCE_CPP); target2.source_types_used().Set(SourceFile::SOURCE_MODULEMAP); - target2.set_module_type(Target::EXPLICIT_MODULEMAP); + target2.set_module_type(kExplicitModulemap); target2.public_deps().push_back(LabelTargetPair(&target)); target2.SetToolchain(&module_toolchain); ASSERT_TRUE(target2.OnResolved(&err)); @@ -2668,7 +2673,7 @@ target3.visibility().SetPublic(); target3.sources().push_back(SourceFile("//stuff/c.modulemap")); target3.source_types_used().Set(SourceFile::SOURCE_MODULEMAP); - target3.set_module_type(Target::EXPLICIT_MODULEMAP); + target3.set_module_type(kExplicitModulemap); target3.public_deps().push_back(LabelTargetPair(&target2)); target3.SetToolchain(&module_toolchain); ASSERT_TRUE(target3.OnResolved(&err)); @@ -2938,7 +2943,7 @@ target.public_headers().push_back(SourceFile("//foo/public_header.h")); target.set_all_headers_public(false); target.source_types_used().Set(SourceFile::SOURCE_CPP); - target.set_module_type(Target::GENERATED_TEXTUAL_MODULEMAP); + target.set_module_type(kGeneratedTextualModulemap); target.SetToolchain(setup.toolchain()); ASSERT_TRUE(target.OnResolved(&err)); @@ -2990,7 +2995,7 @@ target_no_public.sources().push_back(SourceFile("//foo/header1.h")); target_no_public.source_types_used().Set(SourceFile::SOURCE_CPP); target_no_public.source_types_used().Set(SourceFile::SOURCE_H); - target_no_public.set_module_type(Target::GENERATED_TEXTUAL_MODULEMAP); + target_no_public.set_module_type(kGeneratedTextualModulemap); target_no_public.SetToolchain(setup.toolchain()); ASSERT_TRUE(target_no_public.OnResolved(&err)); @@ -3020,7 +3025,7 @@ transitive.sources().push_back(SourceFile("//foo/invisible.h")); transitive.source_types_used().Set(SourceFile::SOURCE_H); transitive.set_output_type(Target::SOURCE_SET); - transitive.set_module_type(Target::GENERATED_TEXTUAL_MODULEMAP); + transitive.set_module_type(kGeneratedTextualModulemap); transitive.SetToolchain(setup.toolchain()); ASSERT_TRUE(transitive.OnResolved(&err)); @@ -3033,7 +3038,7 @@ private_dep.sources().push_back(SourceFile("//foo/private_dep.h")); private_dep.source_types_used().Set(SourceFile::SOURCE_H); private_dep.public_deps().push_back(LabelTargetPair(&transitive)); - private_dep.set_module_type(Target::GENERATED_TEXTUAL_MODULEMAP); + private_dep.set_module_type(kGeneratedTextualModulemap); private_dep.SetToolchain(setup.toolchain()); ASSERT_TRUE(private_dep.OnResolved(&err)); @@ -3045,7 +3050,7 @@ public_dep.sources().push_back(SourceFile("//foo/public_dep.h")); public_dep.private_deps().push_back(LabelTargetPair(&transitive)); public_dep.public_deps().push_back(LabelTargetPair(&transitive)); - public_dep.set_module_type(Target::GENERATED_TEXTUAL_MODULEMAP); + public_dep.set_module_type(kGeneratedTextualModulemap); public_dep.SetToolchain(setup.toolchain()); ASSERT_TRUE(public_dep.OnResolved(&err)); @@ -3070,7 +3075,7 @@ root.source_types_used().Set(SourceFile::SOURCE_H); root.public_deps().push_back(LabelTargetPair(&group_dep)); root.private_deps().push_back(LabelTargetPair(&private_dep)); - root.set_module_type(Target::GENERATED_TEXTUAL_MODULEMAP); + root.set_module_type(kGeneratedTextualModulemap); root.SetToolchain(setup.toolchain()); ASSERT_TRUE(root.OnResolved(&err));
diff --git a/src/gn/ninja_module_writer_util.cc b/src/gn/ninja_module_writer_util.cc index eab5554..621b4b2 100644 --- a/src/gn/ninja_module_writer_util.cc +++ b/src/gn/ninja_module_writer_util.cc
@@ -8,6 +8,7 @@ #include <set> #include <utility> +#include "base/strings/stringprintf.h" #include "gn/resolved_target_data.h" #include "gn/substitution_writer.h" #include "gn/target.h" @@ -47,31 +48,27 @@ std::set<ClangModuleDep> ret; auto add_if_new = [&ret](const Target* t, bool is_self) { + if (!t->module_type().test(Target::HAS_MODULEMAP)) + return; + std::optional<OutputFile> pcm = std::nullopt; - switch (t->module_type()) { - case Target::GENERATED_TEXTUAL_MODULEMAP: - ret.emplace(t->modulemap_file(), t->module_name(), std::nullopt, - is_self); - break; - case Target::EXPLICIT_MODULEMAP: { - auto modulemap = t->modulemap_file(); - CHECK(modulemap != nullptr); - const char* tool_type; - std::vector<OutputFile> modulemap_outputs; - CHECK(t->GetOutputFilesForSource(*modulemap, &tool_type, - &modulemap_outputs)); - CHECK(modulemap_outputs.size() == 1u); - ret.emplace(modulemap, t->module_name(), - std::move(modulemap_outputs[0]), is_self); - break; - } - default: - break; + auto modulemap = t->modulemap_file(); + CHECK(modulemap != nullptr); + if (!t->module_type().test(Target::MODULEMAP_IS_TEXTUAL)) { + const char* tool_type; + std::vector<OutputFile> modulemap_outputs; + CHECK(t->GetOutputFilesForSource(*modulemap, &tool_type, + &modulemap_outputs)); + CHECK(modulemap_outputs.size() == 1u); + pcm = std::move(modulemap_outputs[0]); } + + ret.emplace(modulemap, t->module_name(), pcm, is_self); }; - if (target->source_types_used().Get(SourceFile::SOURCE_MODULEMAP)) + if (target->module_type().test(Target::HAS_MODULEMAP)) { add_if_new(target, true); + } for (const auto& pair : resolved.GetModuleDepsInformation(target)) add_if_new(pair.target(), false);
diff --git a/src/gn/ninja_target_writer.cc b/src/gn/ninja_target_writer.cc index e9c4bf4..9b45628 100644 --- a/src/gn/ninja_target_writer.cc +++ b/src/gn/ninja_target_writer.cc
@@ -166,7 +166,7 @@ NinjaBinaryTargetWriter writer(target, rules); writer.SetResolvedTargetData(resolved); writer.SetNinjaOutputs(ninja_outputs); - if (target->module_type() == Target::GENERATED_TEXTUAL_MODULEMAP) { + if (target->module_type().test(Target::MODULEMAP_IS_GENERATED)) { const SourceFile* modulemap = target->modulemap_file(); CHECK(modulemap);
diff --git a/src/gn/target.cc b/src/gn/target.cc index 956d66c..fbb440c 100644 --- a/src/gn/target.cc +++ b/src/gn/target.cc
@@ -1399,40 +1399,32 @@ void Target::set_module_type(ModuleType type) { module_type_ = type; - switch (type) { - case GENERATED_TEXTUAL_MODULEMAP: { - auto source_dir = - GetBuildDirForTargetAsOutputFile(this, BuildDirType::GEN) - .AsSourceDir(settings()->build_settings()); + if (module_type_.test(MODULEMAP_IS_GENERATED)) { + auto source_dir = GetBuildDirForTargetAsOutputFile(this, BuildDirType::GEN) + .AsSourceDir(settings()->build_settings()); - generated_modulemap_file_ = SourceFile( - base::StringPrintf("%s%s.modulemap", source_dir.value().c_str(), - label().name().c_str())); - break; - } - default: - break; + generated_modulemap_file_ = SourceFile(base::StringPrintf( + "%s%s.modulemap", source_dir.value().c_str(), label().name().c_str())); } } const SourceFile* Target::modulemap_file() const { - switch (module_type_) { - case GENERATED_TEXTUAL_MODULEMAP: - return &generated_modulemap_file_; - case EXPLICIT_MODULEMAP: - for (const SourceFile& sf : sources_) { - if (sf.IsModuleMapType()) { - return &sf; - } - } - default: - return nullptr; + if (module_type_.test(MODULEMAP_IS_GENERATED)) { + return &generated_modulemap_file_; } + if (module_type_.any()) { + for (const SourceFile& sf : sources_) { + if (sf.IsModuleMapType()) { + return &sf; + } + } + } + return nullptr; } const SourceFile* Target::private_modulemap_file() const { if (private_modulemap_file_.is_null() && - module_type_ == GENERATED_TEXTUAL_MODULEMAP) { + module_type_.test(MODULEMAP_IS_GENERATED)) { auto public_modulemap = modulemap_file(); std::string private_name = public_modulemap->GetName(); // foo.modulemap -> foo.private.modulemap
diff --git a/src/gn/target.h b/src/gn/target.h index 210df0c..c06f5fc 100644 --- a/src/gn/target.h +++ b/src/gn/target.h
@@ -5,6 +5,7 @@ #ifndef TOOLS_GN_TARGET_H_ #define TOOLS_GN_TARGET_H_ +#include <bitset> #include <set> #include <string> #include <utility> @@ -60,13 +61,14 @@ DEPS_LINKED, // Iterates through all non-data dependencies. }; - enum ModuleType { - NO_MODULEMAP, - EXPLICIT_MODULEMAP, - // The target didn't have any public headers, so no modulemap is needed. - UNNECESSARY_MODULEMAP, - GENERATED_TEXTUAL_MODULEMAP, + enum ModuleTypeBits { + HAS_MODULEMAP, + MODULEMAP_IS_GENERATED, + MODULEMAP_IS_TEXTUAL, + + N_MODULE_TYPE_BITS, }; + using ModuleType = std::bitset<N_MODULE_TYPE_BITS>; using FileList = std::vector<SourceFile>; using StringVector = std::vector<std::string>; @@ -538,7 +540,7 @@ bool output_extension_set_ = false; std::string module_name_; - ModuleType module_type_ = NO_MODULEMAP; + ModuleType module_type_; // Only filled if the module type is GENERATED_* SourceFile generated_modulemap_file_; // For performance reasons we cache private_modulemap_file.