Revert "Rust: link_output, depend_output and runtime_outputs for dylibs"

This reverts commit 0ee833e823f2e11be136728169906d0710bee910.

Reason for revert: breaks Chromium build: https://crrev.com/c/5762050

Original change's description:
> Rust: link_output, depend_output and runtime_outputs for dylibs
>
> Ensure that the rust_dylib and rust_cdylib tool() definition
> support the `link_output`, `depend_output` and `runtime_outputs`
> argument, when generating shared libraries from Rust sources,
> just like the `solink` tool used for C++ sources.
>
> Bug: 377
> Change-Id: I2286f42661b9ebbff5d5b8455c2be49aaf45afa9
> Reviewed-on: https://gn-review.googlesource.com/c/gn/+/17401
> Reviewed-by: Takuto Ikuta <[email protected]>
> Commit-Queue: David Turner <[email protected]>

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: 377
Change-Id: I3926c0d744da32fd14397148caf042793755ad25
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/17480
Reviewed-by: Dirk Pranke <[email protected]>
Commit-Queue: Dirk Pranke <[email protected]>
Reviewed-by: Nico Weber <[email protected]>
Reviewed-by: Sylvain Defresne <[email protected]>
diff --git a/docs/reference.md b/docs/reference.md
index b99c339..a9fad5b 100644
--- a/docs/reference.md
+++ b/docs/reference.md
@@ -3890,13 +3890,13 @@
 
     link_output  [string with substitutions]
     depend_output  [string with substitutions]
-        Valid for: "solink", "rust_dylib" or "rust_cdylib" only (optional)
+        Valid for: "solink" only (optional)
 
-        These two files specify which of the outputs from the tool should
-        be used for linking and dependency tracking. These should match entries
-        in the "outputs". If unspecified, the first item in the "outputs" array
-        will be used for all. See "Separate linking and dependencies for shared
-        libraries" below for more.
+        These two files specify which of the outputs from the solink tool
+        should be used for linking and dependency tracking. These should match
+        entries in the "outputs". If unspecified, the first item in the
+        "outputs" array will be used for all. See "Separate linking and
+        dependencies for shared libraries" below for more.
 
         On Windows, where the tools produce a .dll shared library and a .lib
         import library, you will want the first two to be the import library
@@ -4142,8 +4142,8 @@
     {{solibs}}
         Extra libraries from shared library dependencies not specified in the
         {{inputs}}. This is the list of link_output files from shared libraries
-        (if the solink, rust_dylib and rust_cdylib tools specify a "link_output"
-        variable separate from the "depend_output").
+        (if the solink tool specifies a "link_output" variable separate from
+        the "depend_output").
 
         These should generally be treated the same as libs by your tool.
 
diff --git a/src/gn/c_tool.cc b/src/gn/c_tool.cc
index e0bea41..767b324 100644
--- a/src/gn/c_tool.cc
+++ b/src/gn/c_tool.cc
@@ -220,7 +220,8 @@
   if (!ValidateLinkAndDependOutput(depend_output(), "depend_output", err)) {
     return false;
   }
-  if (link_output().empty() != depend_output().empty()) {
+  if ((!link_output().empty() && depend_output().empty()) ||
+      (link_output().empty() && !depend_output().empty())) {
     *err = Err(defined_from(),
                "Both link_output and depend_output should either "
                "be specified or they should both be empty.");
diff --git a/src/gn/c_tool.h b/src/gn/c_tool.h
index 86a60e8..c1b5883 100644
--- a/src/gn/c_tool.h
+++ b/src/gn/c_tool.h
@@ -83,6 +83,14 @@
     depend_output_ = std::move(dep_out);
   }
 
+  // Other functions ----------------------------------------------------------
+
+  // Returns true if this tool has separate outputs for dependency tracking
+  // and linking.
+  bool has_separate_solink_files() const {
+    return !link_output_.empty() || !depend_output_.empty();
+  }
+
  private:
   // Initialization functions -------------------------------------------------
   //
@@ -92,8 +100,9 @@
   bool ValidateOutputSubstitution(const Substitution* sub_type) const;
   bool ValidateRuntimeOutputs(Err* err);
   // Validates either link_output or depend_output. To generalize to either,
-  // pass the associated pattern, and the variable name that should appear in
-  // error messages.
+  // pass
+  // the associated pattern, and the variable name that should appear in error
+  // messages.
   bool ValidateLinkAndDependOutput(const SubstitutionPattern& pattern,
                                    const char* variable_name,
                                    Err* err);
diff --git a/src/gn/function_toolchain.cc b/src/gn/function_toolchain.cc
index a97a19c..1df3845 100644
--- a/src/gn/function_toolchain.cc
+++ b/src/gn/function_toolchain.cc
@@ -509,13 +509,13 @@
 
     link_output  [string with substitutions]
     depend_output  [string with substitutions]
-        Valid for: "solink", "rust_dylib" or "rust_cdylib" only (optional)
+        Valid for: "solink" only (optional)
 
-        These two files specify which of the outputs from the tool should
-        be used for linking and dependency tracking. These should match entries
-        in the "outputs". If unspecified, the first item in the "outputs" array
-        will be used for all. See "Separate linking and dependencies for shared
-        libraries" below for more.
+        These two files specify which of the outputs from the solink tool
+        should be used for linking and dependency tracking. These should match
+        entries in the "outputs". If unspecified, the first item in the
+        "outputs" array will be used for all. See "Separate linking and
+        dependencies for shared libraries" below for more.
 
         On Windows, where the tools produce a .dll shared library and a .lib
         import library, you will want the first two to be the import library
@@ -760,8 +760,8 @@
     {{solibs}}
         Extra libraries from shared library dependencies not specified in the
         {{inputs}}. This is the list of link_output files from shared libraries
-        (if the solink, rust_dylib and rust_cdylib tools specify a "link_output"
-        variable separate from the "depend_output").
+        (if the solink tool specifies a "link_output" variable separate from
+        the "depend_output").
 
         These should generally be treated the same as libs by your tool.
 
diff --git a/src/gn/function_toolchain_unittest.cc b/src/gn/function_toolchain_unittest.cc
index 91d2235..74cbef9 100644
--- a/src/gn/function_toolchain_unittest.cc
+++ b/src/gn/function_toolchain_unittest.cc
@@ -117,100 +117,6 @@
   }
 }
 
-TEST_F(FunctionToolchain, RustRuntimeOutputs) {
-  TestWithScope setup;
-
-  // These runtime outputs are a subset of the outputs so are OK.
-  {
-    TestParseInput input(
-        R"(toolchain("good") {
-          tool("rust_dylib") {
-            command = "rust_dylib"
-            outputs = [ "foo" ]
-            runtime_outputs = [ "foo" ]
-          }
-        })");
-    ASSERT_FALSE(input.has_error());
-
-    Err err;
-    input.parsed()->Execute(setup.scope(), &err);
-    ASSERT_FALSE(err.has_error()) << err.message();
-
-    // It should have generated a toolchain.
-    ASSERT_EQ(1u, setup.items().size());
-    const Toolchain* toolchain = setup.items()[0]->AsToolchain();
-    ASSERT_TRUE(toolchain);
-
-    // The toolchain should have a link tool with the two outputs.
-    const Tool* link = toolchain->GetTool(RustTool::kRsToolDylib);
-    ASSERT_TRUE(link);
-    ASSERT_EQ(1u, link->outputs().list().size());
-    EXPECT_EQ("foo", link->outputs().list()[0].AsString());
-    ASSERT_EQ(1u, link->runtime_outputs().list().size());
-    EXPECT_EQ("foo", link->runtime_outputs().list()[0].AsString());
-  }
-
-  // This one is not a subset so should throw an error.
-  {
-    TestParseInput input(
-        R"(toolchain("bad") {
-          tool("rust_dylib") {
-            outputs = [ "foo" ]
-            runtime_outputs = [ "bar" ]
-          }
-        })");
-    ASSERT_FALSE(input.has_error());
-
-    Err err;
-    input.parsed()->Execute(setup.scope(), &err);
-    ASSERT_TRUE(err.has_error()) << err.message();
-  }
-}
-
-TEST_F(FunctionToolchain, RustLinkDependAndRuntimeOutputs) {
-  TestWithScope setup;
-
-  // These runtime outputs are a subset of the outputs so are OK.
-  {
-    TestParseInput input(
-        R"(toolchain("good") {
-          tool("rust_dylib") {
-            command = "rust_dylib"
-            outputs = [ "interface", "lib", "unstripped", "stripped" ]
-            depend_output = "interface"
-            link_output = "lib"
-            runtime_outputs = [ "stripped" ]
-          }
-        })");
-    ASSERT_FALSE(input.has_error());
-
-    Err err;
-    input.parsed()->Execute(setup.scope(), &err);
-    ASSERT_FALSE(err.has_error()) << err.message();
-
-    // It should have generated a toolchain.
-    ASSERT_EQ(1u, setup.items().size());
-    const Toolchain* toolchain = setup.items()[0]->AsToolchain();
-    ASSERT_TRUE(toolchain);
-
-    // The toolchain should have a link tool with the two outputs.
-    const Tool* link = toolchain->GetTool(RustTool::kRsToolDylib);
-    ASSERT_TRUE(link);
-    ASSERT_EQ(4u, link->outputs().list().size());
-    EXPECT_EQ("interface", link->outputs().list()[0].AsString());
-    EXPECT_EQ("lib", link->outputs().list()[1].AsString());
-    EXPECT_EQ("unstripped", link->outputs().list()[2].AsString());
-    EXPECT_EQ("stripped", link->outputs().list()[3].AsString());
-    ASSERT_EQ(1u, link->runtime_outputs().list().size());
-    EXPECT_EQ("stripped", link->runtime_outputs().list()[0].AsString());
-
-    const RustTool* rust_tool = link->AsRust();
-    ASSERT_TRUE(rust_tool);
-    EXPECT_EQ("interface", rust_tool->depend_output().AsString());
-    EXPECT_EQ("lib", rust_tool->link_output().AsString());
-  }
-}
-
 TEST_F(FunctionToolchain, Command) {
   TestWithScope setup;
 
diff --git a/src/gn/rust_tool.cc b/src/gn/rust_tool.cc
index 1b0898c..f799d73 100644
--- a/src/gn/rust_tool.cc
+++ b/src/gn/rust_tool.cc
@@ -54,56 +54,6 @@
 
 void RustTool::SetComplete() {
   SetToolComplete();
-  link_output_.FillRequiredTypes(&substitution_bits_);
-  depend_output_.FillRequiredTypes(&substitution_bits_);
-}
-
-bool RustTool::ValidateRuntimeOutputs(Err* err) {
-  if (runtime_outputs().list().empty())
-    return true;  // Empty is always OK.
-
-  if (name_ != kRsToolDylib && name_ != kRsToolCDylib) {
-    *err = Err(
-        defined_from(), "This tool specifies runtime_outputs.",
-        "This is only valid for linker tools (rust_staticlib doesn't count).");
-    return false;
-  }
-
-  for (const SubstitutionPattern& pattern : runtime_outputs().list()) {
-    if (!IsPatternInOutputList(outputs(), pattern)) {
-      *err = Err(defined_from(), "This tool's runtime_outputs is bad.",
-                 "It must be a subset of the outputs. The bad one is:\n  " +
-                     pattern.AsString());
-      return false;
-    }
-  }
-  return true;
-}
-
-// Validates either link_output or depend_output. To generalize to either, pass
-// the associated pattern, and the variable name that should appear in error
-// messages.
-bool RustTool::ValidateLinkAndDependOutput(const SubstitutionPattern& pattern,
-                                           const char* variable_name,
-                                           Err* err) {
-  if (pattern.empty())
-    return true;  // Empty is always OK.
-
-  // It should only be specified for certain tool types.
-  if (name_ != kRsToolDylib && name_ != kRsToolCDylib) {
-    *err = Err(defined_from(),
-               "This tool specifies a " + std::string(variable_name) + ".",
-               "This is only valid for solink and solink_module tools.");
-    return false;
-  }
-
-  if (!IsPatternInOutputList(outputs(), pattern)) {
-    *err = Err(defined_from(), "This tool's link_output is bad.",
-               "It must match one of the outputs.");
-    return false;
-  }
-
-  return true;
 }
 
 std::string_view RustTool::GetSysroot() const {
@@ -181,31 +131,6 @@
         !ReadString(scope, "dynamic_link_switch", &dynamic_link_switch_, err)) {
       return false;
     }
-
-    if (name_ == kRsToolDylib || name_ == kRsToolCDylib) {
-      if (!ReadPattern(scope, "link_output", &link_output_, err) ||
-          !ReadPattern(scope, "depend_output", &depend_output_, err)) {
-        return false;
-      }
-
-      // Validate link_output and depend_output.
-      if (!ValidateLinkAndDependOutput(link_output(), "link_output", err)) {
-        return false;
-      }
-      if (!ValidateLinkAndDependOutput(depend_output(), "depend_output", err)) {
-        return false;
-      }
-      if (link_output().empty() != depend_output().empty()) {
-        *err = Err(defined_from(),
-                   "Both link_output and depend_output should either "
-                   "be specified or they should both be empty.");
-        return false;
-      }
-    }
-
-    if (!ValidateRuntimeOutputs(err)) {
-      return false;
-    }
   }
 
   return true;
diff --git a/src/gn/rust_tool.h b/src/gn/rust_tool.h
index 76e8bf1..857e205 100644
--- a/src/gn/rust_tool.h
+++ b/src/gn/rust_tool.h
@@ -52,19 +52,6 @@
     dynamic_link_switch_ = std::move(s);
   }
 
-  // Should match files in the outputs() if nonempty.
-  const SubstitutionPattern& link_output() const { return link_output_; }
-  void set_link_output(SubstitutionPattern link_out) {
-    DCHECK(!complete_);
-    link_output_ = std::move(link_out);
-  }
-
-  const SubstitutionPattern& depend_output() const { return depend_output_; }
-  void set_depend_output(SubstitutionPattern dep_out) {
-    DCHECK(!complete_);
-    depend_output_ = std::move(dep_out);
-  }
-
  private:
   std::string rust_sysroot_;
   std::string dynamic_link_switch_;
@@ -75,22 +62,6 @@
                               SubstitutionList* field,
                               Err* err);
 
-  // Initialization functions -------------------------------------------------
-  //
-  // Initialization methods used by InitTool(). If successful, will set the
-  // field and return true, otherwise will return false. Must be called before
-  // SetComplete().
-  bool ValidateRuntimeOutputs(Err* err);
-  // Validates either link_output or depend_output. To generalize to either,
-  // pass the associated pattern, and the variable name that should appear in
-  // error messages.
-  bool ValidateLinkAndDependOutput(const SubstitutionPattern& pattern,
-                                   const char* variable_name,
-                                   Err* err);
-
-  SubstitutionPattern link_output_;
-  SubstitutionPattern depend_output_;
-
   RustTool(const RustTool&) = delete;
   RustTool& operator=(const RustTool&) = delete;
 };
diff --git a/src/gn/target.cc b/src/gn/target.cc
index fb8dbef..b6c6ca0 100644
--- a/src/gn/target.cc
+++ b/src/gn/target.cc
@@ -14,7 +14,6 @@
 #include "gn/deps_iterator.h"
 #include "gn/filesystem_utils.h"
 #include "gn/functions.h"
-#include "gn/rust_tool.h"
 #include "gn/scheduler.h"
 #include "gn/substitution_writer.h"
 #include "gn/tool.h"
@@ -826,56 +825,42 @@
               this, tool, tool->outputs().list()[0]);
       break;
     case RUST_PROC_MACRO:
-    case SHARED_LIBRARY: {
+    case SHARED_LIBRARY:
       CHECK(tool->outputs().list().size() >= 1);
       check_tool_outputs = true;
-
-      const SubstitutionPattern* link_output_ptr = nullptr;
-      const SubstitutionPattern* depend_output_ptr = nullptr;
-      const SubstitutionList* runtime_outputs_ptr = nullptr;
-
       if (const CTool* ctool = tool->AsC()) {
-        link_output_ptr =
-            ctool->link_output().empty() ? nullptr : &ctool->link_output();
-        depend_output_ptr =
-            ctool->depend_output().empty() ? nullptr : &ctool->depend_output();
-        runtime_outputs_ptr = &ctool->runtime_outputs();
-      } else if (const RustTool* rust_tool = tool->AsRust()) {
-        link_output_ptr = rust_tool->link_output().empty()
-                              ? nullptr
-                              : &rust_tool->link_output();
-        depend_output_ptr = rust_tool->depend_output().empty()
-                                ? nullptr
-                                : &rust_tool->depend_output();
-        runtime_outputs_ptr = &rust_tool->runtime_outputs();
-      }
-
-      if (!link_output_ptr && !depend_output_ptr) {
+        if (ctool->link_output().empty() && ctool->depend_output().empty()) {
+          // Default behavior, use the first output file for both.
+          link_output_file_ = dependency_output_file_ =
+              SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
+                  this, tool, tool->outputs().list()[0]);
+        } else {
+          // Use the tool-specified ones.
+          if (!ctool->link_output().empty()) {
+            link_output_file_ =
+                SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
+                    this, tool, ctool->link_output());
+          }
+          if (!ctool->depend_output().empty()) {
+            dependency_output_file_ =
+                SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
+                    this, tool, ctool->depend_output());
+          }
+        }
+        if (tool->runtime_outputs().list().empty()) {
+          // Default to the link output for the runtime output.
+          runtime_outputs_.push_back(link_output_file_);
+        } else {
+          SubstitutionWriter::ApplyListToLinkerAsOutputFile(
+              this, tool, tool->runtime_outputs(), &runtime_outputs_);
+        }
+      } else if (tool->AsRust()) {
         // Default behavior, use the first output file for both.
         link_output_file_ = dependency_output_file_ =
             SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
                 this, tool, tool->outputs().list()[0]);
-      } else {
-        if (link_output_ptr) {
-          link_output_file_ =
-              SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
-                  this, tool, *link_output_ptr);
-        }
-        if (depend_output_ptr) {
-          dependency_output_file_ =
-              SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
-                  this, tool, *depend_output_ptr);
-        }
-      }
-      if (!runtime_outputs_ptr || runtime_outputs_ptr->list().empty()) {
-        // Default to the link output for the runtime output.
-        runtime_outputs_.push_back(link_output_file_);
-      } else {
-        SubstitutionWriter::ApplyListToLinkerAsOutputFile(
-            this, tool, *runtime_outputs_ptr, &runtime_outputs_);
       }
       break;
-    }
     case UNKNOWN:
     default:
       NOTREACHED();
diff --git a/src/gn/target_unittest.cc b/src/gn/target_unittest.cc
index 5cc2182..8af8f6f 100644
--- a/src/gn/target_unittest.cc
+++ b/src/gn/target_unittest.cc
@@ -553,48 +553,6 @@
   EXPECT_EQ("./liba.so", target.runtime_outputs()[0].value());
 }
 
-TEST_F(TargetTest, RustLinkAndDepOutputs) {
-  TestWithScope setup;
-  Err err;
-
-  Toolchain toolchain(setup.settings(), Label(SourceDir("//tc/"), "tc"));
-
-  std::unique_ptr<Tool> tool = Tool::CreateTool(RustTool::kRsToolDylib);
-  RustTool* rust_tool = tool->AsRust();
-  rust_tool->set_output_prefix("lib");
-  rust_tool->set_default_output_extension(".so");
-
-  const char kLinkPattern[] =
-      "{{root_out_dir}}/{{target_output_name}}{{output_extension}}";
-  SubstitutionPattern link_output =
-      SubstitutionPattern::MakeForTest(kLinkPattern);
-  rust_tool->set_link_output(link_output);
-
-  const char kDependPattern[] =
-      "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.TOC";
-  SubstitutionPattern depend_output =
-      SubstitutionPattern::MakeForTest(kDependPattern);
-  rust_tool->set_depend_output(depend_output);
-
-  rust_tool->set_outputs(
-      SubstitutionList::MakeForTest(kLinkPattern, kDependPattern));
-
-  toolchain.SetTool(std::move(tool));
-
-  Target target(setup.settings(), Label(SourceDir("//a/"), "a"));
-  target.source_types_used().Set(SourceFile::SOURCE_RS);
-  target.rust_values().set_crate_type(RustValues::CRATE_DYLIB);
-  target.set_output_type(Target::SHARED_LIBRARY);
-  target.SetToolchain(&toolchain);
-  ASSERT_TRUE(target.OnResolved(&err));
-
-  EXPECT_EQ("./liba.so", target.link_output_file().value());
-  EXPECT_EQ("./liba.so.TOC", target.dependency_output_file().value());
-
-  ASSERT_EQ(1u, target.runtime_outputs().size());
-  EXPECT_EQ("./liba.so", target.runtime_outputs()[0].value());
-}
-
 // Tests that runtime_outputs works without an explicit link_output for
 // solink tools.
 //
@@ -651,59 +609,6 @@
   EXPECT_EQ("//out/Debug/a.pdb", computed_outputs[2].value());
 }
 
-TEST_F(TargetTest, RustRuntimeOuputs) {
-  TestWithScope setup;
-  Err err;
-
-  Toolchain toolchain(setup.settings(), Label(SourceDir("//tc/"), "tc"));
-
-  std::unique_ptr<Tool> tool = Tool::CreateTool(RustTool::kRsToolCDylib);
-  RustTool* rust_tool = tool->AsRust();
-  rust_tool->set_output_prefix("");
-  rust_tool->set_default_output_extension(".dll");
-
-  // Say the linker makes a DLL< an import library, and a symbol file we want
-  // to treat as a runtime output.
-  const char kLibPattern[] =
-      "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.lib";
-  const char kDllPattern[] =
-      "{{root_out_dir}}/{{target_output_name}}{{output_extension}}";
-  const char kPdbPattern[] = "{{root_out_dir}}/{{target_output_name}}.pdb";
-  SubstitutionPattern pdb_pattern =
-      SubstitutionPattern::MakeForTest(kPdbPattern);
-
-  rust_tool->set_outputs(
-      SubstitutionList::MakeForTest(kLibPattern, kDllPattern, kPdbPattern));
-
-  // Say we only want the DLL and symbol file treaded as runtime outputs.
-  rust_tool->set_runtime_outputs(
-      SubstitutionList::MakeForTest(kDllPattern, kPdbPattern));
-
-  toolchain.SetTool(std::move(tool));
-
-  Target target(setup.settings(), Label(SourceDir("//a/"), "a"));
-  target.source_types_used().Set(SourceFile::SOURCE_RS);
-  target.rust_values().set_crate_type(RustValues::CRATE_CDYLIB);
-  target.set_output_type(Target::SHARED_LIBRARY);
-  target.SetToolchain(&toolchain);
-  ASSERT_TRUE(target.OnResolved(&err));
-
-  EXPECT_EQ("./a.dll.lib", target.link_output_file().value());
-  EXPECT_EQ("./a.dll.lib", target.dependency_output_file().value());
-
-  ASSERT_EQ(2u, target.runtime_outputs().size());
-  EXPECT_EQ("./a.dll", target.runtime_outputs()[0].value());
-  EXPECT_EQ("./a.pdb", target.runtime_outputs()[1].value());
-
-  // Test GetOutputsAsSourceFiles().
-  std::vector<SourceFile> computed_outputs;
-  EXPECT_TRUE(target.GetOutputsAsSourceFiles(LocationRange(), true,
-                                             &computed_outputs, &err));
-  ASSERT_EQ(3u, computed_outputs.size());
-  EXPECT_EQ("//out/Debug/a.dll.lib", computed_outputs[0].value());
-  EXPECT_EQ("//out/Debug/a.dll", computed_outputs[1].value());
-  EXPECT_EQ("//out/Debug/a.pdb", computed_outputs[2].value());
-}
 // Tests Target::GetOutputFilesForSource for binary targets (these require a
 // tool definition). Also tests GetOutputsAsSourceFiles() for source sets.
 TEST_F(TargetTest, GetOutputFilesForSource_Binary) {