Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(936)

Unified Diff: tools/gn/ninja_binary_target_writer.cc

Issue 1207903002: Windows precompiled header support in GN (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Scott's grammar nits Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/gn/ninja_binary_target_writer.h ('k') | tools/gn/ninja_binary_target_writer_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 680c0d9db459ac6366cfaef01448e0d2d106c992..7b81bfa517f91a8bbff08db1965302bc16b8449e 100644
--- a/tools/gn/ninja_binary_target_writer.cc
+++ b/tools/gn/ninja_binary_target_writer.cc
@@ -4,6 +4,7 @@
#include "tools/gn/ninja_binary_target_writer.h"
+#include <cstring>
#include <set>
#include <sstream>
@@ -12,12 +13,33 @@
#include "tools/gn/deps_iterator.h"
#include "tools/gn/err.h"
#include "tools/gn/escape.h"
+#include "tools/gn/filesystem_utils.h"
#include "tools/gn/ninja_utils.h"
#include "tools/gn/settings.h"
+#include "tools/gn/source_file_type.h"
#include "tools/gn/string_utils.h"
#include "tools/gn/substitution_writer.h"
#include "tools/gn/target.h"
+// Represents a set of tool types. Must be first since it is also shared by
+// some helper functions in the anonymous namespace below.
+class NinjaBinaryTargetWriter::SourceFileTypeSet {
+ public:
+ SourceFileTypeSet() {
+ memset(flags_, 0, sizeof(bool) * static_cast<int>(SOURCE_NUMTYPES));
+ }
+
+ void Set(SourceFileType type) {
+ flags_[static_cast<int>(type)] = true;
+ }
+ bool Get(SourceFileType type) const {
+ return flags_[static_cast<int>(type)];
+ }
+
+ private:
+ bool flags_[static_cast<int>(SOURCE_NUMTYPES)];
+};
+
namespace {
// Returns the proper escape options for writing compiler and linker flags.
@@ -65,31 +87,231 @@ struct IncludeWriter {
PathOutput& path_output_;
};
+// Computes the set of output files resulting from compiling the given source
+// file. If the file can be compiled and the tool exists, fills the outputs in
+// and writes the tool type to computed_tool_type. If the file is not
+// compilable, returns false.
+//
+// The target that the source belongs to is passed as an argument. In the case
+// of linking to source sets, this can be different than the target this class
+// is currently writing.
+//
+// The function can succeed with a "NONE" tool type for object files which are
+// just passed to the output. The output will always be overwritten, not
+// appended to.
+bool GetOutputFilesForSource(const Target* target,
+ const SourceFile& source,
+ Toolchain::ToolType* computed_tool_type,
+ std::vector<OutputFile>* outputs) {
+ outputs->clear();
+ *computed_tool_type = Toolchain::TYPE_NONE;
+
+ SourceFileType file_type = GetSourceFileType(source);
+ if (file_type == SOURCE_UNKNOWN)
+ return false;
+ if (file_type == SOURCE_O) {
+ // Object files just get passed to the output and not compiled.
+ outputs->push_back(
+ OutputFile(target->settings()->build_settings(), source));
+ return true;
+ }
+
+ *computed_tool_type =
+ target->toolchain()->GetToolTypeForSourceType(file_type);
+ if (*computed_tool_type == Toolchain::TYPE_NONE)
+ return false; // No tool for this file (it's a header file or something).
+ const Tool* tool = target->toolchain()->GetTool(*computed_tool_type);
+ if (!tool)
+ return false; // Tool does not apply for this toolchain.file.
+
+ // Figure out what output(s) this compiler produces.
+ SubstitutionWriter::ApplyListToCompilerAsOutputFile(
+ target, source, tool->outputs(), outputs);
+ return !outputs->empty();
+}
+
+// Returns the language-specific prefix/suffix for precomiled header files.
+const char* GetPCHLangForToolType(Toolchain::ToolType type) {
+ switch (type) {
+ case Toolchain::TYPE_CC:
+ return "c";
+ case Toolchain::TYPE_CXX:
+ return "cc";
+ case Toolchain::TYPE_OBJC:
+ return "m";
+ case Toolchain::TYPE_OBJCXX:
+ return "mm";
+ default:
+ NOTREACHED() << "Not a valid PCH tool type type";
+ return "";
+ }
+}
+
+// Returns the object files for the precompiled header of the given type (flag
+// type and tool type must match).
+void GetWindowsPCHObjectFiles(const Target* target,
+ Toolchain::ToolType tool_type,
+ std::vector<OutputFile>* outputs) {
+ outputs->clear();
+
+ // Compute the tool. This must use the tool type passed in rather than the
+ // detected file type of the precompiled source file since the same
+ // precompiled source file will be used for separate C/C++ compiles.
+ const Tool* tool = target->toolchain()->GetTool(tool_type);
+ if (!tool)
+ return;
+ SubstitutionWriter::ApplyListToCompilerAsOutputFile(
+ target, target->config_values().precompiled_source(),
+ tool->outputs(), outputs);
+
+ if (outputs->empty())
+ return;
+ if (outputs->size() > 1)
+ outputs->resize(1); // Only link the first output from the compiler tool.
+
+ // Need to annotate the obj files with the language type. For example:
+ // obj/foo/target_name.precompile.obj ->
+ // obj/foo/target_name.precompile.cc.obj
+ const char* lang_suffix = GetPCHLangForToolType(tool_type);
+ std::string& output_value = (*outputs)[0].value();
+ size_t extension_offset = FindExtensionOffset(output_value);
+ if (extension_offset == std::string::npos) {
+ NOTREACHED() << "No extension found";
+ } else {
+ DCHECK(extension_offset >= 1);
+ DCHECK(output_value[extension_offset - 1] == '.');
+ output_value.insert(extension_offset - 1, ".");
+ output_value.insert(extension_offset, lang_suffix);
+ }
+}
+
+// Appends the object files generated by the given source set to the given
+// output vector.
+void AddSourceSetObjectFiles(const Target* source_set,
+ UniqueVector<OutputFile>* obj_files) {
+ std::vector<OutputFile> tool_outputs; // Prevent allocation in loop.
+ NinjaBinaryTargetWriter::SourceFileTypeSet used_types;
+
+ // Compute object files for all sources. Only link the first output from
+ // the tool if there are more than one.
+ for (const auto& source : source_set->sources()) {
+ Toolchain::ToolType tool_type = Toolchain::TYPE_NONE;
+ if (GetOutputFilesForSource(source_set, source, &tool_type, &tool_outputs))
+ obj_files->push_back(tool_outputs[0]);
+
+ used_types.Set(GetSourceFileType(source));
+ }
+
+ // Precompiled header object files.
+ if (source_set->config_values().has_precompiled_headers()) {
+ if (used_types.Get(SOURCE_C)) {
+ GetWindowsPCHObjectFiles(source_set, Toolchain::TYPE_CC, &tool_outputs);
+ obj_files->Append(tool_outputs.begin(), tool_outputs.end());
+ }
+ if (used_types.Get(SOURCE_CPP)) {
+ GetWindowsPCHObjectFiles(source_set, Toolchain::TYPE_CXX, &tool_outputs);
+ obj_files->Append(tool_outputs.begin(), tool_outputs.end());
+ }
+ if (used_types.Get(SOURCE_M)) {
+ GetWindowsPCHObjectFiles(source_set, Toolchain::TYPE_OBJC, &tool_outputs);
+ obj_files->Append(tool_outputs.begin(), tool_outputs.end());
+ }
+ if (used_types.Get(SOURCE_MM)) {
+ GetWindowsPCHObjectFiles(source_set, Toolchain::TYPE_OBJCXX,
+ &tool_outputs);
+ obj_files->Append(tool_outputs.begin(), tool_outputs.end());
+ }
+ }
+}
+
} // namespace
NinjaBinaryTargetWriter::NinjaBinaryTargetWriter(const Target* target,
std::ostream& out)
: NinjaTargetWriter(target, out),
- tool_(target->toolchain()->GetToolForTargetFinalOutput(target)) {
+ tool_(target->toolchain()->GetToolForTargetFinalOutput(target)),
+ rule_prefix_(GetNinjaRulePrefixForToolchain(settings_)) {
}
NinjaBinaryTargetWriter::~NinjaBinaryTargetWriter() {
}
void NinjaBinaryTargetWriter::Run() {
- WriteCompilerVars();
+ // Figure out what source types are needed.
+ SourceFileTypeSet used_types;
+ for (const auto& source : target_->sources())
+ used_types.Set(GetSourceFileType(source));
+
+ WriteCompilerVars(used_types);
+
+ // 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,
+ // but changes in the inputs deps won't cause the file to be recompiled.
+ //
+ // This is important to prevent changes in unrelated actions that are
+ // upstream of this target from causing everything to be recompiled
+ //
+ // Why can we get away with this rather than using implicit deps ("|", which
+ // will force rebuilds when the inputs change)? For source code, the
+ // computed dependencies of all headers will be computed by the compiler,
+ // which will cause source rebuilds if any "real" upstream dependencies
+ // change.
+ //
+ // If a .cc file is generated by an input dependency, Ninja will see the
+ // input to the build rule doesn't exist, and that it is an output from a
+ // previous step, and build the previous step first. This is a "real"
+ // dependency and doesn't need | or || to express.
+ //
+ // The only case where this rule matters is for the first build where no .d
+ // files exist, and Ninja doesn't know what that source file depends on. In
+ // this case it's sufficient to ensure that the upstream dependencies are
+ // built first. This is exactly what Ninja's order-only dependencies
+ // expresses.
+ OutputFile order_only_dep =
+ WriteInputDepsStampAndGetDep(std::vector<const Target*>());
+
+ std::vector<OutputFile> pch_obj_files;
+ WritePrecompiledHeaderCommands(used_types, order_only_dep, &pch_obj_files);
+ // Treat all precompiled object files as explicit dependencies of all
+ // compiles. Some notes:
+ //
+ // - Technically only the language-specific one is required for any specific
+ // compile, but that's more difficult to express and the additional logic
+ // doesn't buy much reduced parallelism. Just list them all (there's
+ // usually only one anyway).
+ //
+ // - Technically the .pch file is the input to the compile, not the
+ // precompiled header's corresponding object file that we're using here.
+ // But Ninja's depslog doesn't support multiple outputs from the
+ // precompiled header compile step (it outputs both the .pch file and a
+ // corresponding .obj file). So we consistently list the .obj file and the
+ // .pch file we really need comes along with it.
std::vector<OutputFile> obj_files;
std::vector<SourceFile> other_files;
- WriteSources(&obj_files, &other_files);
+ WriteSources(pch_obj_files, order_only_dep, &obj_files, &other_files);
- if (target_->output_type() == Target::SOURCE_SET)
+ // Also link all pch object files.
+ obj_files.insert(obj_files.end(), pch_obj_files.begin(), pch_obj_files.end());
+
+ if (target_->output_type() == Target::SOURCE_SET) {
WriteSourceSetStamp(obj_files);
- else
+#ifndef NDEBUG
+ // Verify that the function that separately computes a source set's object
+ // files match the object files just computed.
+ UniqueVector<OutputFile> computed_obj;
+ AddSourceSetObjectFiles(target_, &computed_obj);
+ DCHECK_EQ(obj_files.size(), computed_obj.size());
+ for (const auto& obj : obj_files)
+ DCHECK_NE(static_cast<size_t>(-1), computed_obj.IndexOf(obj));
+#endif
+ } else {
WriteLinkerStuff(obj_files, other_files);
+ }
}
-void NinjaBinaryTargetWriter::WriteCompilerVars() {
+void NinjaBinaryTargetWriter::WriteCompilerVars(
+ const SourceFileTypeSet& used_types) {
const SubstitutionBits& subst = target_->toolchain()->substitution_bits();
// Defines.
@@ -113,36 +335,134 @@ void NinjaBinaryTargetWriter::WriteCompilerVars() {
out_ << std::endl;
}
- // C flags and friends.
- EscapeOptions flag_escape_options = GetFlagOptions();
-#define WRITE_FLAGS(name, subst_enum) \
- if (subst.used[subst_enum]) { \
- out_ << kSubstitutionNinjaNames[subst_enum] << " ="; \
- RecursiveTargetConfigStringsToStream(target_, &ConfigValues::name, \
- flag_escape_options, out_); \
- out_ << std::endl; \
+ bool has_precompiled_headers =
+ target_->config_values().has_precompiled_headers();
+
+ // Some toolchains pass cflags to the assembler since it's the same command,
+ // and cflags_c might also be sent to the objective C compiler.
+ //
+ // TODO(brettw) remove the SOURCE_M from the CFLAGS_C writing once the Chrome
+ // Mac build is updated not to pass cflags_c to .m files.
+ EscapeOptions opts = GetFlagOptions();
+ if (used_types.Get(SOURCE_C) || used_types.Get(SOURCE_CPP) ||
+ used_types.Get(SOURCE_M) || used_types.Get(SOURCE_MM) ||
+ used_types.Get(SOURCE_ASM)) {
+ WriteOneFlag(SUBSTITUTION_CFLAGS, false, Toolchain::TYPE_NONE,
+ &ConfigValues::cflags, opts);
+ }
+ if (used_types.Get(SOURCE_C) || used_types.Get(SOURCE_M) ||
+ used_types.Get(SOURCE_ASM)) {
+ WriteOneFlag(SUBSTITUTION_CFLAGS_C, has_precompiled_headers,
+ Toolchain::TYPE_CC, &ConfigValues::cflags_c, opts);
+ }
+ if (used_types.Get(SOURCE_CPP)) {
+ WriteOneFlag(SUBSTITUTION_CFLAGS_CC, has_precompiled_headers,
+ Toolchain::TYPE_CXX, &ConfigValues::cflags_cc, opts);
+ }
+ if (used_types.Get(SOURCE_M)) {
+ WriteOneFlag(SUBSTITUTION_CFLAGS_OBJC, has_precompiled_headers,
+ Toolchain::TYPE_OBJC, &ConfigValues::cflags_objc, opts);
+ }
+ if (used_types.Get(SOURCE_MM)) {
+ WriteOneFlag(SUBSTITUTION_CFLAGS_OBJCC, has_precompiled_headers,
+ Toolchain::TYPE_OBJCXX, &ConfigValues::cflags_objcc, opts);
+ }
+
+ WriteSharedVars(subst);
+}
+
+void NinjaBinaryTargetWriter::WriteOneFlag(
+ SubstitutionType subst_enum,
+ bool has_precompiled_headers,
+ Toolchain::ToolType tool_type,
+ const std::vector<std::string>& (ConfigValues::* getter)() const,
+ EscapeOptions flag_escape_options) {
+ if (!target_->toolchain()->substitution_bits().used[subst_enum])
+ return;
+
+ out_ << kSubstitutionNinjaNames[subst_enum] << " =";
+
+ if (has_precompiled_headers) {
+ const Tool* tool = target_->toolchain()->GetTool(tool_type);
+ if (tool && tool->precompiled_header_type() == Tool::PCH_MSVC) {
+ // Name the .pch file.
+ out_ << " /Fp";
+ path_output_.WriteFile(out_, GetWindowsPCHFile(tool_type));
+
+ // Enables precompiled headers and names the .h file. It's a string
+ // rather than a file name (so no need to rebase or use path_output_).
+ out_ << " /Yu" << target_->config_values().precompiled_header();
}
+ }
+
+ RecursiveTargetConfigStringsToStream(target_, getter,
+ flag_escape_options, out_);
+ out_ << std::endl;
+}
- WRITE_FLAGS(cflags, SUBSTITUTION_CFLAGS)
- WRITE_FLAGS(cflags_c, SUBSTITUTION_CFLAGS_C)
- WRITE_FLAGS(cflags_cc, SUBSTITUTION_CFLAGS_CC)
- WRITE_FLAGS(cflags_objc, SUBSTITUTION_CFLAGS_OBJC)
- WRITE_FLAGS(cflags_objcc, SUBSTITUTION_CFLAGS_OBJCC)
+void NinjaBinaryTargetWriter::WritePrecompiledHeaderCommands(
+ const SourceFileTypeSet& used_types,
+ const OutputFile& order_only_dep,
+ std::vector<OutputFile>* object_files) {
+ if (!target_->config_values().has_precompiled_headers())
+ return;
-#undef WRITE_FLAGS
+ const Tool* tool_c = target_->toolchain()->GetTool(Toolchain::TYPE_CC);
+ if (tool_c &&
+ tool_c->precompiled_header_type() == Tool::PCH_MSVC &&
+ used_types.Get(SOURCE_C)) {
+ WriteWindowsPCHCommand(SUBSTITUTION_CFLAGS_C,
+ Toolchain::TYPE_CC,
+ order_only_dep, object_files);
+ }
+ const Tool* tool_cxx = target_->toolchain()->GetTool(Toolchain::TYPE_CXX);
+ if (tool_cxx &&
+ tool_cxx->precompiled_header_type() == Tool::PCH_MSVC &&
+ used_types.Get(SOURCE_CPP)) {
+ WriteWindowsPCHCommand(SUBSTITUTION_CFLAGS_CC,
+ Toolchain::TYPE_CXX,
+ order_only_dep, object_files);
+ }
+}
- WriteSharedVars(subst);
+void NinjaBinaryTargetWriter::WriteWindowsPCHCommand(
+ SubstitutionType flag_type,
+ Toolchain::ToolType tool_type,
+ const OutputFile& order_only_dep,
+ std::vector<OutputFile>* object_files) {
+ // Compute the object file (it will be language-specific).
+ std::vector<OutputFile> outputs;
+ GetWindowsPCHObjectFiles(target_, tool_type, &outputs);
+ if (outputs.empty())
+ return;
+ object_files->insert(object_files->end(), outputs.begin(), outputs.end());
+
+ // Build line to compile the file.
+ WriteCompilerBuildLine(target_->config_values().precompiled_source(),
+ std::vector<OutputFile>(), order_only_dep, tool_type,
+ outputs);
+
+ // This build line needs a custom language-specific flags value. It needs to
+ // include the switch to generate the .pch file in addition to the normal
+ // ones. Rule-specific variables are just indented underneath the rule line,
+ // and this defines the new one in terms of the old value.
+ out_ << " " << kSubstitutionNinjaNames[flag_type] << " =";
+ out_ << " ${" << kSubstitutionNinjaNames[flag_type] << "}";
+
+ // Append the command to generate the .pch file.
+ out_ << " /Yc" << target_->config_values().precompiled_header();
+
+ // Write two blank lines to help separate the PCH build lines from the
+ // regular source build lines.
+ out_ << std::endl << std::endl;
}
void NinjaBinaryTargetWriter::WriteSources(
+ const std::vector<OutputFile>& extra_deps,
+ const OutputFile& order_only_dep,
std::vector<OutputFile>* object_files,
std::vector<SourceFile>* other_files) {
- object_files->reserve(target_->sources().size());
-
- OutputFile input_dep =
- WriteInputDepsStampAndGetDep(std::vector<const Target*>());
-
- std::string rule_prefix = GetNinjaRulePrefixForToolchain(settings_);
+ object_files->reserve(object_files->size() + target_->sources().size());
std::vector<OutputFile> tool_outputs; // Prevent reallocation in loop.
for (const auto& source : target_->sources()) {
@@ -154,41 +474,8 @@ void NinjaBinaryTargetWriter::WriteSources(
}
if (tool_type != Toolchain::TYPE_NONE) {
- out_ << "build";
- path_output_.WriteFiles(out_, tool_outputs);
-
- out_ << ": " << rule_prefix << Toolchain::ToolTypeToName(tool_type);
- out_ << " ";
- path_output_.WriteFile(out_, source);
- if (!input_dep.value().empty()) {
- // Write out the input dependencies as an order-only dependency. This
- // will cause Ninja to make sure the inputs are up-to-date before
- // compiling this source, but changes in the inputs deps won't cause
- // the file to be recompiled.
- //
- // This is important to prevent changes in unrelated actions that
- // are upstream of this target from causing everything to be recompiled.
- //
- // Why can we get away with this rather than using implicit deps ("|",
- // which will force rebuilds when the inputs change)? For source code,
- // the computed dependencies of all headers will be computed by the
- // compiler, which will cause source rebuilds if any "real" upstream
- // dependencies change.
- //
- // If a .cc file is generated by an input dependency, Ninja will see
- // the input to the build rule doesn't exist, and that it is an output
- // from a previous step, and build the previous step first. This is a
- // "real" dependency and doesn't need | or || to express.
- //
- // The only case where this rule matters is for the first build where
- // no .d files exist, and Ninja doesn't know what that source file
- // depends on. In this case it's sufficient to ensure that the upstream
- // dependencies are built first. This is exactly what Ninja's order-
- // only dependencies expresses.
- out_ << " || ";
- path_output_.WriteFile(out_, input_dep);
- }
- out_ << std::endl;
+ WriteCompilerBuildLine(source, extra_deps, order_only_dep, tool_type,
+ tool_outputs);
}
// It's theoretically possible for a compiler to produce more than one
@@ -198,6 +485,34 @@ void NinjaBinaryTargetWriter::WriteSources(
out_ << std::endl;
}
+void NinjaBinaryTargetWriter::WriteCompilerBuildLine(
+ const SourceFile& source,
+ const std::vector<OutputFile>& extra_deps,
+ const OutputFile& order_only_dep,
+ Toolchain::ToolType tool_type,
+ const std::vector<OutputFile>& outputs) {
+ out_ << "build";
+ path_output_.WriteFiles(out_, outputs);
+
+ out_ << ": " << rule_prefix_ << Toolchain::ToolTypeToName(tool_type);
+ out_ << " ";
+ path_output_.WriteFile(out_, source);
+
+ if (!extra_deps.empty()) {
+ out_ << " |";
+ for (const OutputFile& dep : extra_deps) {
+ out_ << " ";
+ path_output_.WriteFile(out_, dep);
+ }
+ }
+
+ if (!order_only_dep.value().empty()) {
+ out_ << " || ";
+ path_output_.WriteFile(out_, order_only_dep);
+ }
+ out_ << std::endl;
+}
+
void NinjaBinaryTargetWriter::WriteLinkerStuff(
const std::vector<OutputFile>& object_files,
const std::vector<SourceFile>& other_files) {
@@ -208,8 +523,7 @@ void NinjaBinaryTargetWriter::WriteLinkerStuff(
out_ << "build";
path_output_.WriteFiles(out_, output_files);
- out_ << ": "
- << GetNinjaRulePrefixForToolchain(settings_)
+ out_ << ": " << rule_prefix_
<< Toolchain::ToolTypeToName(
target_->toolchain()->GetToolTypeForTargetFinalOutput(target_));
@@ -219,18 +533,12 @@ void NinjaBinaryTargetWriter::WriteLinkerStuff(
GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps);
// Object files.
- for (const auto& obj : object_files) {
- out_ << " ";
- path_output_.WriteFile(out_, obj);
- }
- for (const auto& obj : extra_object_files) {
- out_ << " ";
- path_output_.WriteFile(out_, obj);
- }
+ path_output_.WriteFiles(out_, object_files);
+ path_output_.WriteFiles(out_, extra_object_files);
+ // Dependencies.
std::vector<OutputFile> implicit_deps;
std::vector<OutputFile> solibs;
-
for (const Target* cur : linkable_deps) {
// All linkable deps should have a link output file.
DCHECK(!cur->link_output_file().value().empty())
@@ -442,18 +750,8 @@ void NinjaBinaryTargetWriter::ClassifyDependency(
// just forward the dependency, otherwise the files in the source
// set can easily get linked more than once which will cause
// multiple definition errors.
- if (can_link_libs) {
- // Linking in a source set to an executable, shared library, or
- // complete static library, so copy its object files.
- std::vector<OutputFile> tool_outputs; // Prevent allocation in loop.
- for (const auto& source : dep->sources()) {
- Toolchain::ToolType tool_type = Toolchain::TYPE_NONE;
- if (GetOutputFilesForSource(dep, source, &tool_type, &tool_outputs)) {
- // Only link the first output if there are more than one.
- extra_object_files->push_back(tool_outputs[0]);
- }
- }
- }
+ if (can_link_libs)
+ AddSourceSetObjectFiles(dep, 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
@@ -481,33 +779,15 @@ void NinjaBinaryTargetWriter::WriteOrderOnlyDependencies(
}
}
-bool NinjaBinaryTargetWriter::GetOutputFilesForSource(
- const Target* target,
- const SourceFile& source,
- Toolchain::ToolType* computed_tool_type,
- std::vector<OutputFile>* outputs) const {
- outputs->clear();
- *computed_tool_type = Toolchain::TYPE_NONE;
-
- SourceFileType file_type = GetSourceFileType(source);
- if (file_type == SOURCE_UNKNOWN)
- return false;
- if (file_type == SOURCE_O) {
- // Object files just get passed to the output and not compiled.
- outputs->push_back(OutputFile(settings_->build_settings(), source));
- return true;
- }
-
- *computed_tool_type =
- target->toolchain()->GetToolTypeForSourceType(file_type);
- if (*computed_tool_type == Toolchain::TYPE_NONE)
- return false; // No tool for this file (it's a header file or something).
- const Tool* tool = target->toolchain()->GetTool(*computed_tool_type);
- if (!tool)
- return false; // Tool does not apply for this toolchain.file.
-
- // Figure out what output(s) this compiler produces.
- SubstitutionWriter::ApplyListToCompilerAsOutputFile(
- target, source, tool->outputs(), outputs);
- return !outputs->empty();
+OutputFile NinjaBinaryTargetWriter::GetWindowsPCHFile(
+ Toolchain::ToolType tool_type) const {
+ // Use "obj/{dir}/{target_name}_{lang}.pch" which ends up
+ // looking like "obj/chrome/browser/browser.cc.pch"
+ OutputFile ret = GetTargetOutputDirAsOutputFile(target_);
+ ret.value().append(target_->label().name());
+ ret.value().push_back('_');
+ ret.value().append(GetPCHLangForToolType(tool_type));
+ ret.value().append(".pch");
+
+ return ret;
}
« no previous file with comments | « tools/gn/ninja_binary_target_writer.h ('k') | tools/gn/ninja_binary_target_writer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698