Add a `module_name` flag to source_set.

This overrides the default module name, allowing you to have targets
//foo:baz and //bar:baz not clash on their module names.

Fixed: chromium:465206266
Change-Id: Ibb916df2889a2294b181acb9d35710576a6a6964
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/20502
Reviewed-by: Takuto Ikuta <tikuta@google.com>
Commit-Queue: Matt Stark <msta@google.com>
diff --git a/docs/reference.md b/docs/reference.md
index fd24565..d5dfa0f 100644
--- a/docs/reference.md
+++ b/docs/reference.md
@@ -4138,6 +4138,7 @@
         modules referenced by the current target. The "_no_self" version doesn't
         include the module for the current target, and can be used to compile
         the pcm itself.
+
     {{source}}
         The relative path and name of the current input file.
         Example: "../../base/my_file.cc"
@@ -6270,7 +6271,7 @@
 ### <a name="var_module_name"></a>**module_name**: [string] The name for the compiled module.&nbsp;[Back to Top](#gn-reference)
 
 ```
-  Valid for binary targets that contain Swift sources.
+  Valid for binary targets that contain Swift sources, and for C++ modules.
 
   If module_name is not set, then this rule will use the target name.
 ```
diff --git a/src/gn/binary_target_generator.cc b/src/gn/binary_target_generator.cc
index a738dc9..1517734 100644
--- a/src/gn/binary_target_generator.cc
+++ b/src/gn/binary_target_generator.cc
@@ -70,6 +70,9 @@
   if (!ValidateSources())
     return;
 
+  if (!FillModuleName())
+    return;
+
   if (target_->source_types_used().RustSourceUsed()) {
     RustValuesGenerator rustgen(target_, scope_, function_call_, err_);
     rustgen.Run();
@@ -271,3 +274,13 @@
   }
   return true;
 }
+
+bool BinaryTargetGenerator::FillModuleName() {
+  const Value* value = scope_->GetValue(variables::kModuleName, true);
+  if (!value)
+    return true;
+  if (!value->VerifyTypeIs(Value::STRING, err_))
+    return false;
+  target_->set_module_name(value->string_value());
+  return true;
+}
diff --git a/src/gn/binary_target_generator.h b/src/gn/binary_target_generator.h
index 0bafd68..b6d4c2e 100644
--- a/src/gn/binary_target_generator.h
+++ b/src/gn/binary_target_generator.h
@@ -32,6 +32,7 @@
   bool FillAllowCircularIncludesFrom();
   bool FillPool();
   bool ValidateSources();
+  bool FillModuleName();
 
   Target::OutputType output_type_;
 
diff --git a/src/gn/ninja_c_binary_target_writer_unittest.cc b/src/gn/ninja_c_binary_target_writer_unittest.cc
index 2072142..f324d53 100644
--- a/src/gn/ninja_c_binary_target_writer_unittest.cc
+++ b/src/gn/ninja_c_binary_target_writer_unittest.cc
@@ -2565,6 +2565,7 @@
 
   Target target(&module_settings, Label(SourceDir("//blah/"), "a"));
   target.set_output_type(Target::STATIC_LIBRARY);
+  target.set_module_name("blah_a");
   target.visibility().SetPublic();
   target.sources().push_back(SourceFile("//blah/a.modulemap"));
   target.sources().push_back(SourceFile("//blah/a.cc"));
@@ -2584,8 +2585,8 @@
 include_dirs =
 cflags =
 cflags_cc =
-cc_module_name = a
-module_deps = -fmodule-file=a=obj/blah/liba.a.pcm
+cc_module_name = blah_a
+module_deps = -fmodule-file=blah_a=obj/blah/liba.a.pcm
 module_deps_no_self =
 root_out_dir = withmodules
 target_out_dir = obj/blah
@@ -2631,8 +2632,8 @@
 cflags =
 cflags_cc =
 cc_module_name = b
-module_deps = -fmodule-file=a=obj/blah/liba.a.pcm -fmodule-file=b=obj/stuff/libb.b.pcm
-module_deps_no_self = -fmodule-file=a=obj/blah/liba.a.pcm
+module_deps = -fmodule-file=blah_a=obj/blah/liba.a.pcm -fmodule-file=b=obj/stuff/libb.b.pcm
+module_deps_no_self = -fmodule-file=blah_a=obj/blah/liba.a.pcm
 root_out_dir = withmodules
 target_out_dir = obj/stuff
 target_output_name = libb
@@ -2675,8 +2676,8 @@
 cflags =
 cflags_cc =
 cc_module_name = c
-module_deps = -fmodule-file=a=obj/blah/liba.a.pcm -fmodule-file=b=obj/stuff/libb.b.pcm -fmodule-file=c=obj/stuff/libc.c.pcm
-module_deps_no_self = -fmodule-file=a=obj/blah/liba.a.pcm -fmodule-file=b=obj/stuff/libb.b.pcm
+module_deps = -fmodule-file=blah_a=obj/blah/liba.a.pcm -fmodule-file=b=obj/stuff/libb.b.pcm -fmodule-file=c=obj/stuff/libc.c.pcm
+module_deps_no_self = -fmodule-file=blah_a=obj/blah/liba.a.pcm -fmodule-file=b=obj/stuff/libb.b.pcm
 root_out_dir = withmodules
 target_out_dir = obj/things
 target_output_name = libc
@@ -2715,8 +2716,8 @@
 cflags =
 cflags_cc =
 cc_module_name = c
-module_deps = -fmodule-file=a=obj/blah/liba.a.pcm -fmodule-file=b=obj/stuff/libb.b.pcm
-module_deps_no_self = -fmodule-file=a=obj/blah/liba.a.pcm -fmodule-file=b=obj/stuff/libb.b.pcm
+module_deps = -fmodule-file=blah_a=obj/blah/liba.a.pcm -fmodule-file=b=obj/stuff/libb.b.pcm
+module_deps_no_self = -fmodule-file=blah_a=obj/blah/liba.a.pcm -fmodule-file=b=obj/stuff/libb.b.pcm
 root_out_dir = withmodules
 target_out_dir = obj/zap
 target_output_name = c
diff --git a/src/gn/target.h b/src/gn/target.h
index 63a52ee..c8c4933 100644
--- a/src/gn/target.h
+++ b/src/gn/target.h
@@ -7,6 +7,7 @@
 
 #include <set>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/gtest_prod_util.h"
@@ -411,7 +412,13 @@
   }
 
   // The module name for the target.
-  std::string module_name() const { return label().name(); }
+  std::string module_name() const {
+    return module_name_override_.empty() ? label().name()
+                                         : module_name_override_;
+  }
+  void set_module_name(std::string module_name) {
+    module_name_override_ = std::move(module_name);
+  }
 
   // Computes and returns the outputs of this target expressed as SourceFiles.
   //
@@ -500,6 +507,8 @@
   std::string output_extension_;
   bool output_extension_set_ = false;
 
+  std::string module_name_override_;
+
   FileList sources_;
   SourceFileTypeSet source_types_used_;
   bool all_headers_public_ = true;
diff --git a/src/gn/variables.cc b/src/gn/variables.cc
index 2c6f8e4..4573279 100644
--- a/src/gn/variables.cc
+++ b/src/gn/variables.cc
@@ -1476,6 +1476,17 @@
   }
 )";
 
+const char kModuleName[] = "module_name";
+const char kModuleName_HelpShort[] =
+    "module_name: [string] The name for the compiled module.";
+const char kModuleName_Help[] =
+    R"(module_name: [string] The name for the compiled module.
+
+  Valid for binary targets that contain Swift sources, and for C++ modules.
+
+  If module_name is not set, then this rule will use the target name.
+)";
+
 const char kOutputExtension[] = "output_extension";
 const char kOutputExtension_HelpShort[] =
     "output_extension: [string] Value to use for the output's file extension.";
@@ -2450,6 +2461,7 @@
     INSERT_VARIABLE(Libs)
     INSERT_VARIABLE(LibDirs)
     INSERT_VARIABLE(Metadata)
+    INSERT_VARIABLE(ModuleName)
     INSERT_VARIABLE(OutputDir)
     INSERT_VARIABLE(OutputExtension)
     INSERT_VARIABLE(OutputName)
diff --git a/src/gn/variables.h b/src/gn/variables.h
index 1f3c7fe..2d46db4 100644
--- a/src/gn/variables.h
+++ b/src/gn/variables.h
@@ -230,6 +230,10 @@
 extern const char kMetadata_HelpShort[];
 extern const char kMetadata_Help[];
 
+extern const char kModuleName[];
+extern const char kModuleName_HelpShort[];
+extern const char kModuleName_Help[];
+
 extern const char kOutputDir[];
 extern const char kOutputDir_HelpShort[];
 extern const char kOutputDir_Help[];