Add structure to return classified deps

Change NinjaBinaryTargetWriter::GetDeps() to return its output via
a structure (instead of using multiple output parameters) and also
rename the method to GetClassifiedDeps().

Using a structure to return the output will make it easier to add
other kinds of deps (notably swift requires a new type of deps for
the .swiftmodule files).

Bug: 121
Change-Id: I4c8f479f6619e0377244955331e265b03548af65
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/9540
Reviewed-by: Brett Wilson <brettw@chromium.org>
Commit-Queue: Sylvain Defresne <sdefresne@chromium.org>
diff --git a/src/gn/ninja_binary_target_writer.cc b/src/gn/ninja_binary_target_writer.cc
index da7733b..098a595 100644
--- a/src/gn/ninja_binary_target_writer.cc
+++ b/src/gn/ninja_binary_target_writer.cc
@@ -108,53 +108,44 @@
   // depend on this will reference the object files directly. However, writing
   // this rule allows the user to type the name of the target and get a build
   // which can be convenient for development.
-  UniqueVector<OutputFile> extra_object_files;
-  UniqueVector<const Target*> linkable_deps;
-  UniqueVector<const Target*> non_linkable_deps;
-  UniqueVector<const Target*> framework_deps;
-  GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps,
-          &framework_deps);
+  ClassifiedDeps classified_deps = GetClassifiedDeps();
 
   // The classifier should never put extra object files in a source sets: any
   // source sets that we depend on should appear in our non-linkable deps
   // instead.
-  DCHECK(extra_object_files.empty());
+  DCHECK(classified_deps.extra_object_files.empty());
 
   std::vector<OutputFile> order_only_deps;
-  for (auto* dep : non_linkable_deps)
+  for (auto* dep : classified_deps.non_linkable_deps)
     order_only_deps.push_back(dep->dependency_output_file());
 
   WriteStampForTarget(object_files, order_only_deps);
 }
 
-void NinjaBinaryTargetWriter::GetDeps(
-    UniqueVector<OutputFile>* extra_object_files,
-    UniqueVector<const Target*>* linkable_deps,
-    UniqueVector<const Target*>* non_linkable_deps,
-    UniqueVector<const Target*>* framework_deps) const {
+NinjaBinaryTargetWriter::ClassifiedDeps
+NinjaBinaryTargetWriter::GetClassifiedDeps() const {
+  ClassifiedDeps classified_deps;
+
   // Normal public/private deps.
   for (const auto& pair : target_->GetDeps(Target::DEPS_LINKED)) {
-    ClassifyDependency(pair.ptr, extra_object_files, linkable_deps,
-                       non_linkable_deps, framework_deps);
+    ClassifyDependency(pair.ptr, &classified_deps);
   }
 
   // Inherited libraries.
   for (auto* inherited_target : target_->inherited_libraries().GetOrdered()) {
-    ClassifyDependency(inherited_target, extra_object_files, linkable_deps,
-                       non_linkable_deps, framework_deps);
+    ClassifyDependency(inherited_target, &classified_deps);
   }
 
   // Data deps.
   for (const auto& data_dep_pair : target_->data_deps())
-    non_linkable_deps->push_back(data_dep_pair.ptr);
+    classified_deps.non_linkable_deps.push_back(data_dep_pair.ptr);
+
+  return classified_deps;
 }
 
 void NinjaBinaryTargetWriter::ClassifyDependency(
     const Target* dep,
-    UniqueVector<OutputFile>* extra_object_files,
-    UniqueVector<const Target*>* linkable_deps,
-    UniqueVector<const Target*>* non_linkable_deps,
-    UniqueVector<const Target*>* framework_deps) const {
+    ClassifiedDeps* classified_deps) const {
   // Only the following types of outputs have libraries linked into them:
   //  EXECUTABLE
   //  SHARED_LIBRARY
@@ -180,28 +171,28 @@
     // set can easily get linked more than once which will cause
     // multiple definition errors.
     if (can_link_libs)
-      AddSourceSetFiles(dep, extra_object_files);
+      AddSourceSetFiles(dep, &classified_deps->extra_object_files);
 
     // Add the source set itself as a non-linkable dependency on the current
     // target. This will make sure that anything the source set's stamp file
     // depends on (like data deps) are also built before the current target
     // can be complete. Otherwise, these will be skipped since this target
     // will depend only on the source set's object files.
-    non_linkable_deps->push_back(dep);
+    classified_deps->non_linkable_deps.push_back(dep);
   } else if (target_->output_type() == Target::RUST_LIBRARY &&
              dep->IsLinkable()) {
     // Rust libraries aren't final, but need to have the link lines of all
     // transitive deps specified.
-    linkable_deps->push_back(dep);
+    classified_deps->linkable_deps.push_back(dep);
   } else if (target_->complete_static_lib() && dep->IsFinal()) {
-    non_linkable_deps->push_back(dep);
+    classified_deps->non_linkable_deps.push_back(dep);
   } else if (can_link_libs && dep->IsLinkable()) {
-    linkable_deps->push_back(dep);
+    classified_deps->linkable_deps.push_back(dep);
   } else if (dep->output_type() == Target::CREATE_BUNDLE &&
              dep->bundle_data().is_framework()) {
-    framework_deps->push_back(dep);
+    classified_deps->framework_deps.push_back(dep);
   } else {
-    non_linkable_deps->push_back(dep);
+    classified_deps->non_linkable_deps.push_back(dep);
   }
 }
 
diff --git a/src/gn/ninja_binary_target_writer.h b/src/gn/ninja_binary_target_writer.h
index a9d10d5..142ca9e 100644
--- a/src/gn/ninja_binary_target_writer.h
+++ b/src/gn/ninja_binary_target_writer.h
@@ -24,6 +24,14 @@
   void Run() override;
 
  protected:
+  // Structure used to return the classified deps from |GetDeps| method.
+  struct ClassifiedDeps {
+    UniqueVector<OutputFile> extra_object_files;
+    UniqueVector<const Target*> linkable_deps;
+    UniqueVector<const Target*> non_linkable_deps;
+    UniqueVector<const Target*> framework_deps;
+  };
+
   // Writes to the output stream a stamp rule for inputs, and
   // returns the file to be appended to source rules that encodes the
   // implicit dependencies for the current target.
@@ -39,20 +47,14 @@
 
   // Gets all target dependencies and classifies them, as well as accumulates
   // object files from source sets we need to link.
-  void GetDeps(UniqueVector<OutputFile>* extra_object_files,
-               UniqueVector<const Target*>* linkable_deps,
-               UniqueVector<const Target*>* non_linkable_deps,
-               UniqueVector<const Target*>* framework_deps) const;
+  ClassifiedDeps GetClassifiedDeps() const;
 
   // Classifies the dependency as linkable or nonlinkable with the current
-  // target, adding it to the appropriate vector. If the dependency is a source
-  // set we should link in, the source set's object files will be appended to
-  // |extra_object_files|.
+  // target, adding it to the appropriate vector of |classified_deps|. If the
+  // dependency is a source set we should link in, the source set's object
+  // files will be appended to |classified_deps.extra_object_files|.
   void ClassifyDependency(const Target* dep,
-                          UniqueVector<OutputFile>* extra_object_files,
-                          UniqueVector<const Target*>* linkable_deps,
-                          UniqueVector<const Target*>* non_linkable_deps,
-                          UniqueVector<const Target*>* framework_deps) const;
+                          ClassifiedDeps* classified_deps) const;
 
   OutputFile WriteStampAndGetDep(const UniqueVector<const SourceFile*>& files,
                                  const std::string& stamp_ext) const;
diff --git a/src/gn/ninja_c_binary_target_writer.cc b/src/gn/ninja_c_binary_target_writer.cc
index 721b67c..80448a8 100644
--- a/src/gn/ninja_c_binary_target_writer.cc
+++ b/src/gn/ninja_c_binary_target_writer.cc
@@ -458,21 +458,16 @@
   out_ << ": " << rule_prefix_
        << Tool::GetToolTypeForTargetFinalOutput(target_);
 
-  UniqueVector<OutputFile> extra_object_files;
-  UniqueVector<const Target*> linkable_deps;
-  UniqueVector<const Target*> non_linkable_deps;
-  UniqueVector<const Target*> framework_deps;
-  GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps,
-          &framework_deps);
+  ClassifiedDeps classified_deps = GetClassifiedDeps();
 
   // Object files.
   path_output_.WriteFiles(out_, object_files);
-  path_output_.WriteFiles(out_, extra_object_files);
+  path_output_.WriteFiles(out_, classified_deps.extra_object_files);
 
   // Dependencies.
   std::vector<OutputFile> implicit_deps;
   std::vector<OutputFile> solibs;
-  for (const Target* cur : linkable_deps) {
+  for (const Target* cur : classified_deps.linkable_deps) {
     // All linkable deps should have a link output file.
     DCHECK(!cur->link_output_file().value().empty())
         << "No link output file for "
@@ -521,10 +516,8 @@
   // always necessary to relink the current target if one of the framework
   // is regenerated, but it ensure that if one of the framework API changes,
   // any dependent target will relink it (see crbug.com/1037607).
-  if (!framework_deps.empty()) {
-    for (const Target* dep : framework_deps) {
-      implicit_deps.push_back(dep->dependency_output_file());
-    }
+  for (const Target* dep : classified_deps.framework_deps) {
+    implicit_deps.push_back(dep->dependency_output_file());
   }
 
   // The input dependency is only needed if there are no object files, as the
@@ -564,7 +557,7 @@
   // the sources, there is already an implicit order-only dependency. However,
   // it's extra work to separate these out and there's no disadvantage to
   // listing them again.
-  WriteOrderOnlyDependencies(non_linkable_deps);
+  WriteOrderOnlyDependencies(classified_deps.non_linkable_deps);
 
   // End of the link "build" line.
   out_ << std::endl;
diff --git a/src/gn/ninja_rust_binary_target_writer.cc b/src/gn/ninja_rust_binary_target_writer.cc
index 70b0f1d..59960a1 100644
--- a/src/gn/ninja_rust_binary_target_writer.cc
+++ b/src/gn/ninja_rust_binary_target_writer.cc
@@ -118,12 +118,7 @@
   WriteCompilerVars();
 
   // Classify our dependencies.
-  UniqueVector<const Target*> linkable_deps;
-  UniqueVector<const Target*> non_linkable_deps;
-  UniqueVector<const Target*> framework_deps;
-  UniqueVector<OutputFile> extra_obj_files;
-  GetDeps(&extra_obj_files, &linkable_deps, &non_linkable_deps,
-          &framework_deps);
+  ClassifiedDeps classified_deps = GetClassifiedDeps();
 
   // The input dependencies will be an order-only dependency. This will cause
   // Ninja to make sure the inputs are up to date before compiling this source,
@@ -140,23 +135,25 @@
   // for ninja dependency tracking.
   UniqueVector<OutputFile> implicit_deps;
   AppendSourcesAndInputsToImplicitDeps(&implicit_deps);
-  implicit_deps.Append(extra_obj_files.begin(), extra_obj_files.end());
+  implicit_deps.Append(classified_deps.extra_object_files.begin(),
+                       classified_deps.extra_object_files.end());
 
   std::vector<OutputFile> rustdeps;
   std::vector<OutputFile> nonrustdeps;
-  nonrustdeps.insert(nonrustdeps.end(), extra_obj_files.begin(),
-                     extra_obj_files.end());
-  for (const auto* framework_dep : framework_deps) {
+  nonrustdeps.insert(nonrustdeps.end(),
+                     classified_deps.extra_object_files.begin(),
+                     classified_deps.extra_object_files.end());
+  for (const auto* framework_dep : classified_deps.framework_deps) {
     order_only_deps.push_back(framework_dep->dependency_output_file());
   }
-  for (const auto* non_linkable_dep : non_linkable_deps) {
+  for (const auto* non_linkable_dep : classified_deps.non_linkable_deps) {
     if (non_linkable_dep->source_types_used().RustSourceUsed() &&
         non_linkable_dep->output_type() != Target::SOURCE_SET) {
       rustdeps.push_back(non_linkable_dep->dependency_output_file());
     }
     order_only_deps.push_back(non_linkable_dep->dependency_output_file());
   }
-  for (const auto* linkable_dep : linkable_deps) {
+  for (const auto* linkable_dep : classified_deps.linkable_deps) {
     if (linkable_dep->source_types_used().RustSourceUsed()) {
       rustdeps.push_back(linkable_dep->link_output_file());
     } else {
@@ -192,8 +189,10 @@
                          implicit_deps.vector(), order_only_deps, tool_->name(),
                          tool_outputs);
 
-  std::vector<const Target*> extern_deps(linkable_deps.vector());
-  std::copy(non_linkable_deps.begin(), non_linkable_deps.end(),
+  std::vector<const Target*> extern_deps(
+      classified_deps.linkable_deps.vector());
+  std::copy(classified_deps.non_linkable_deps.begin(),
+            classified_deps.non_linkable_deps.end(),
             std::back_inserter(extern_deps));
   WriteExterns(extern_deps);
   WriteRustdeps(transitive_rustlibs, rustdeps, nonrustdeps);