Index: tools/gn/ninja_binary_target_writer.cc |
diff --git a/tools/gn/ninja_binary_target_writer.cc b/tools/gn/ninja_binary_target_writer.cc |
index 60d3a6a37b40c313afbbb5c78392f60f97af560a..9241021fdcf6c169caa0f0b6ba17b5c8602a91d8 100644 |
--- a/tools/gn/ninja_binary_target_writer.cc |
+++ b/tools/gn/ninja_binary_target_writer.cc |
@@ -79,7 +79,6 @@ Toolchain::ToolType GetToolTypeForTarget(const Target* target) { |
case Target::EXECUTABLE: |
return Toolchain::TYPE_LINK; |
default: |
- NOTREACHED(); |
return Toolchain::TYPE_NONE; |
} |
} |
@@ -103,7 +102,10 @@ void NinjaBinaryTargetWriter::Run() { |
std::vector<OutputFile> obj_files; |
WriteSources(&obj_files); |
- WriteLinkerStuff(obj_files); |
+ if (target_->output_type() == Target::SOURCE_SET) |
+ WriteSourceSetStamp(obj_files); |
+ else |
+ WriteLinkerStuff(obj_files); |
} |
void NinjaBinaryTargetWriter::WriteCompilerVars() { |
@@ -309,40 +311,26 @@ void NinjaBinaryTargetWriter::WriteLinkCommand( |
<< helper_.GetRulePrefix(GetToolchain()) |
<< Toolchain::ToolTypeToName(tool_type_); |
+ std::set<OutputFile> extra_object_files; |
+ std::vector<const Target*> linkable_deps; |
+ std::vector<const Target*> non_linkable_deps; |
+ GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps); |
+ |
// Object files. |
for (size_t i = 0; i < object_files.size(); i++) { |
out_ << " "; |
path_output_.WriteFile(out_, object_files[i]); |
} |
- |
- // Library inputs (deps and inherited static libraries). |
- // |
- // Static libraries since they're just a collection of the object files so |
- // don't need libraries linked with them, but we still need to go through |
- // the list and find non-linkable data deps in the "deps" section. We'll |
- // collect all non-linkable deps and put it in the implicit deps below. |
- std::vector<const Target*> extra_data_deps; |
- const std::vector<const Target*>& deps = target_->deps(); |
- const std::set<const Target*>& inherited = target_->inherited_libraries(); |
- for (size_t i = 0; i < deps.size(); i++) { |
- if (inherited.find(deps[i]) != inherited.end()) |
- continue; |
- if (target_->output_type() != Target::STATIC_LIBRARY && |
- deps[i]->IsLinkable()) { |
- out_ << " "; |
- path_output_.WriteFile(out_, helper_.GetTargetOutputFile(deps[i])); |
- } else { |
- extra_data_deps.push_back(deps[i]); |
- } |
+ for (std::set<OutputFile>::iterator i = extra_object_files.begin(); |
+ i != extra_object_files.end(); ++i) { |
+ out_ << " "; |
+ path_output_.WriteFile(out_, *i); |
} |
- for (std::set<const Target*>::const_iterator i = inherited.begin(); |
- i != inherited.end(); ++i) { |
- if (target_->output_type() == Target::STATIC_LIBRARY) { |
- extra_data_deps.push_back(*i); |
- } else { |
- out_ << " "; |
- path_output_.WriteFile(out_, helper_.GetTargetOutputFile(*i)); |
- } |
+ |
+ // Libs. |
+ for (size_t i = 0; i < linkable_deps.size(); i++) { |
+ out_ << " "; |
+ path_output_.WriteFile(out_, helper_.GetTargetOutputFile(linkable_deps[i])); |
} |
// External link deps from GYP. This is indexed by a label with no toolchain. |
@@ -357,22 +345,123 @@ void NinjaBinaryTargetWriter::WriteLinkCommand( |
} |
// Append data dependencies as implicit dependencies. |
+ WriteImplicitDependencies(non_linkable_deps); |
+ |
+ out_ << std::endl; |
+} |
+ |
+void NinjaBinaryTargetWriter::WriteSourceSetStamp( |
+ const std::vector<OutputFile>& object_files) { |
+ // The stamp rule for source sets is generally not used, since targets that |
+ // 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. |
+ out_ << "build "; |
+ path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_)); |
+ out_ << ": " |
+ << helper_.GetRulePrefix(target_->settings()->toolchain()) |
+ << "stamp"; |
+ |
+ std::set<OutputFile> extra_object_files; |
+ std::vector<const Target*> linkable_deps; |
+ std::vector<const Target*> non_linkable_deps; |
+ GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps); |
+ |
+ // The classifier should never put extra object files in a source set: |
+ // any source sets that we depend on should appear in our non-linkable |
+ // deps instead. |
+ DCHECK(extra_object_files.empty()); |
+ |
+ for (size_t i = 0; i < object_files.size(); i++) { |
+ out_ << " "; |
+ path_output_.WriteFile(out_, object_files[i]); |
+ } |
+ |
+ // Append data dependencies as implicit dependencies. |
+ WriteImplicitDependencies(non_linkable_deps); |
+ |
+ out_ << std::endl; |
+} |
+ |
+void NinjaBinaryTargetWriter::GetDeps( |
+ std::set<OutputFile>* extra_object_files, |
+ std::vector<const Target*>* linkable_deps, |
+ std::vector<const Target*>* non_linkable_deps) const { |
+ const std::vector<const Target*>& deps = target_->deps(); |
+ const std::set<const Target*>& inherited = target_->inherited_libraries(); |
+ |
+ // Normal deps. |
+ for (size_t i = 0; i < deps.size(); i++) { |
+ if (inherited.find(deps[i]) != inherited.end()) |
+ continue; // Don't add dupes. |
+ ClassifyDependency(deps[i], extra_object_files, |
+ linkable_deps, non_linkable_deps); |
+ } |
+ |
+ // Inherited libraries. |
+ for (std::set<const Target*>::const_iterator i = inherited.begin(); |
+ i != inherited.end(); ++i) { |
+ ClassifyDependency(*i, extra_object_files, |
+ linkable_deps, non_linkable_deps); |
+ } |
+ |
+ // Data deps. |
const std::vector<const Target*>& datadeps = target_->datadeps(); |
+ for (size_t i = 0; i < datadeps.size(); i++) |
+ non_linkable_deps->push_back(datadeps[i]); |
+} |
+ |
+void NinjaBinaryTargetWriter::ClassifyDependency( |
+ const Target* dep, |
+ std::set<OutputFile>* extra_object_files, |
+ std::vector<const Target*>* linkable_deps, |
+ std::vector<const Target*>* non_linkable_deps) const { |
+ // Only these types of outputs have libraries linked into them. Child deps of |
+ // static libraries get pushed up the dependency tree until one of these is |
+ // reached, and source sets don't link at all. |
+ bool can_link_libs = |
+ (target_->output_type() == Target::EXECUTABLE || |
+ target_->output_type() == Target::SHARED_LIBRARY); |
+ |
+ if (dep->output_type() == Target::SOURCE_SET) { |
+ if (target_->output_type() == Target::SOURCE_SET) { |
+ // When a source set depends on another source set, add it as a data |
+ // dependency so if the user says "ninja second_source_set" it will |
+ // also compile the first (what you would expect) even though we'll |
+ // never do anything with the first one's files. |
+ non_linkable_deps->push_back(dep); |
+ } else { |
+ // Linking in a source set, copy its object files. |
+ for (size_t i = 0; i < dep->sources().size(); i++) { |
+ SourceFileType input_file_type = GetSourceFileType( |
+ dep->sources()[i], dep->settings()->target_os()); |
+ if (input_file_type != SOURCE_UNKNOWN && |
+ input_file_type != SOURCE_H) { |
+ // Note we need to specify the target as the source_set target |
+ // itself, since this is used to prefix the object file name. |
+ extra_object_files->insert(helper_.GetOutputFileForSource( |
+ dep, dep->sources()[i], input_file_type)); |
+ } |
+ } |
+ } |
+ } else if (can_link_libs && dep->IsLinkable()) { |
+ linkable_deps->push_back(dep); |
+ } else { |
+ non_linkable_deps->push_back(dep); |
+ } |
+} |
+ |
+void NinjaBinaryTargetWriter::WriteImplicitDependencies( |
+ const std::vector<const Target*>& non_linkable_deps) { |
const std::vector<SourceFile>& data = target_->data(); |
- if (!extra_data_deps.empty() || !datadeps.empty() || !data.empty()) { |
+ if (!non_linkable_deps.empty() || !data.empty()) { |
out_ << " ||"; |
- // Non-linkable deps in the deps section above. |
- for (size_t i = 0; i < extra_data_deps.size(); i++) { |
+ // Non-linkable targets. |
+ for (size_t i = 0; i < non_linkable_deps.size(); i++) { |
out_ << " "; |
path_output_.WriteFile(out_, |
- helper_.GetTargetOutputFile(extra_data_deps[i])); |
- } |
- |
- // Data deps. |
- for (size_t i = 0; i < datadeps.size(); i++) { |
- out_ << " "; |
- path_output_.WriteFile(out_, helper_.GetTargetOutputFile(datadeps[i])); |
+ helper_.GetTargetOutputFile(non_linkable_deps[i])); |
} |
// Data files. |
@@ -382,6 +471,4 @@ void NinjaBinaryTargetWriter::WriteLinkCommand( |
path_output_.WriteFile(out_, data[i]); |
} |
} |
- |
- out_ << std::endl; |
} |