Index: tools/gn/ninja_helper.cc |
diff --git a/tools/gn/ninja_helper.cc b/tools/gn/ninja_helper.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c27c0e40c76cd91588394b967fe0c039743336d4 |
--- /dev/null |
+++ b/tools/gn/ninja_helper.cc |
@@ -0,0 +1,165 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "tools/gn/ninja_helper.h" |
+ |
+#include "base/logging.h" |
+#include "tools/gn/filesystem_utils.h" |
+#include "tools/gn/string_utils.h" |
+#include "tools/gn/target.h" |
+ |
+namespace { |
+ |
+const char kLibDirWithSlash[] = "lib"; |
+const char kObjectDirNoSlash[] = "obj"; |
+ |
+} // namespace |
+ |
+NinjaHelper::NinjaHelper(const BuildSettings* build_settings) |
+ : build_settings_(build_settings) { |
+ build_to_src_no_last_slash_ = build_settings->build_to_source_dir_string(); |
+ if (!build_to_src_no_last_slash_.empty() && |
+ build_to_src_no_last_slash_[build_to_src_no_last_slash_.size() - 1] == |
+ '/') |
+ build_to_src_no_last_slash_.resize(build_to_src_no_last_slash_.size() - 1); |
+ |
+ build_to_src_system_no_last_slash_ = build_to_src_no_last_slash_; |
+ ConvertPathToSystem(&build_to_src_system_no_last_slash_); |
+} |
+ |
+NinjaHelper::~NinjaHelper() { |
+} |
+ |
+std::string NinjaHelper::GetTopleveOutputDir() const { |
+ return kObjectDirNoSlash; |
+} |
+ |
+std::string NinjaHelper::GetTargetOutputDir(const Target* target) const { |
+ return kObjectDirNoSlash + target->label().dir().SourceAbsoluteWithOneSlash(); |
+} |
+ |
+OutputFile NinjaHelper::GetNinjaFileForTarget(const Target* target) const { |
+ OutputFile ret(target->settings()->toolchain_output_subdir()); |
+ ret.value().append(kObjectDirNoSlash); |
+ AppendStringPiece(&ret.value(), |
+ target->label().dir().SourceAbsoluteWithOneSlash()); |
+ ret.value().append(target->label().name()); |
+ ret.value().append(".ninja"); |
+ return ret; |
+} |
+ |
+OutputFile NinjaHelper::GetNinjaFileForToolchain( |
+ const Settings* settings) const { |
+ OutputFile ret; |
+ ret.value().append(settings->toolchain_output_subdir().value()); |
+ ret.value().append("toolchain.ninja"); |
+ return ret; |
+} |
+ |
+// In Python, GypPathToUniqueOutput does the qualification. The only case where |
+// the Python version doesn't qualify the name is for target outputs, which we |
+// handle in a separate function. |
+OutputFile NinjaHelper::GetOutputFileForSource( |
+ const Target* target, |
+ const SourceFile& source, |
+ SourceFileType type) const { |
+ // Extract the filename and remove the extension (keep the dot). |
+ base::StringPiece filename = FindFilename(&source.value()); |
+ std::string name(filename.data(), filename.size()); |
+ size_t extension_offset = FindExtensionOffset(name); |
+ CHECK(extension_offset != std::string::npos); |
+ name.resize(extension_offset); |
+ |
+ // Append the new extension. |
+ switch (type) { |
+ case SOURCE_ASM: |
+ case SOURCE_C: |
+ case SOURCE_CC: |
+ case SOURCE_M: |
+ case SOURCE_MM: |
+ name.append(target->settings()->IsWin() ? "obj" : "o"); |
+ break; |
+ |
+ case SOURCE_RC: |
+ name.append("res"); |
+ break; |
+ |
+ case SOURCE_H: |
+ case SOURCE_UNKNOWN: |
+ NOTREACHED(); |
+ return OutputFile(); |
+ } |
+ |
+ // Use the scheme <path>/<target>.<name>.<extension> so that all output |
+ // names are unique to different targets. |
+ OutputFile ret(kObjectDirNoSlash); |
+ |
+ // Find the directory, assume it starts with two slashes, and trim to one. |
+ base::StringPiece dir = FindDir(&source.value()); |
+ CHECK(dir.size() >= 2 && dir[0] == '/' && dir[1] == '/') |
+ << "Source file isn't in the source repo: " << dir; |
+ AppendStringPiece(&ret.value(), dir.substr(1)); |
+ |
+ ret.value().append(target->label().name()); |
+ ret.value().append("."); |
+ ret.value().append(name); |
+ return ret; |
+} |
+ |
+OutputFile NinjaHelper::GetTargetOutputFile(const Target* target) const { |
+ OutputFile ret; |
+ if (target->output_type() == Target::NONE) { |
+ NOTREACHED(); |
+ return ret; |
+ } |
+ |
+ const char* extension; |
+ if (target->output_type() == Target::NONE || |
+ target->output_type() == Target::COPY_FILES || |
+ target->output_type() == Target::CUSTOM) { |
+ extension = "stamp"; |
+ } else { |
+ extension = GetExtensionForOutputType(target->output_type(), |
+ target->settings()->target_os()); |
+ } |
+ |
+ // Everything goes into the toolchain directory (which will be empty for the |
+ // default toolchain, and will end in a slash otherwise). |
+ ret.value().append(target->settings()->toolchain_output_subdir().value()); |
+ |
+ // Binaries and loadable libraries go into the toolchain root. |
+ if (target->output_type() == Target::EXECUTABLE || |
+ target->output_type() == Target::LOADABLE_MODULE || |
+ (target->settings()->IsMac() && |
+ (target->output_type() == Target::SHARED_LIBRARY || |
+ target->output_type() == Target::STATIC_LIBRARY)) || |
+ (target->settings()->IsWin() && |
+ target->output_type() == Target::SHARED_LIBRARY)) { |
+ // Generate a name like "<toolchain>/<name>.<extension>". |
+ ret.value().append(target->label().name()); |
+ ret.value().push_back('.'); |
+ ret.value().append(extension); |
+ return ret; |
+ } |
+ |
+ // Libraries go into the library subdirectory like |
+ // "<toolchain>/lib/<name>.<extension>". |
+ if (target->output_type() == Target::SHARED_LIBRARY) { |
+ ret.value().append(kLibDirWithSlash); |
+ ret.value().append(target->label().name()); |
+ ret.value().push_back('.'); |
+ ret.value().append(extension); |
+ return ret; |
+ } |
+ |
+ // Everything else goes next to the target's .ninja file like |
+ // "<toolchain>/obj/<path>/<name>.<extension>". |
+ ret.value().append(kObjectDirNoSlash); |
+ AppendStringPiece(&ret.value(), |
+ target->label().dir().SourceAbsoluteWithOneSlash()); |
+ ret.value().append(target->label().name()); |
+ ret.value().push_back('.'); |
+ ret.value().append(extension); |
+ return ret; |
+} |