Index: tools/gn/ninja_build_writer.cc |
diff --git a/tools/gn/ninja_build_writer.cc b/tools/gn/ninja_build_writer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a63765cd3aafadcb7d785d3a53db279a54456b7c |
--- /dev/null |
+++ b/tools/gn/ninja_build_writer.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_build_writer.h" |
+ |
+#include <fstream> |
+ |
+#include "base/command_line.h" |
+#include "base/file_util.h" |
+#include "base/process/process_handle.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "build/build_config.h" |
+#include "tools/gn/build_settings.h" |
+#include "tools/gn/filesystem_utils.h" |
+#include "tools/gn/input_file_manager.h" |
+#include "tools/gn/scheduler.h" |
+#include "tools/gn/target.h" |
+ |
+#if defined(OS_WIN) |
+#include <windows.h> |
+#endif |
+ |
+namespace { |
+ |
+std::string GetSelfInvocationCommand(const BuildSettings* build_settings) { |
+#if defined(OS_WIN) |
+ wchar_t module[MAX_PATH]; |
+ GetModuleFileName(NULL, module, MAX_PATH); |
+ //result = "\"" + WideToUTF8(module) + "\""; |
+ base::FilePath executable(module); |
+#elif defined(OS_MACOSX) |
+ // FIXME(brettw) write this on Mac! |
+ base::FilePath executable("gn"); |
+#else |
+ base::FilePath executable = |
+ base::GetProcessExecutablePath(base::GetCurrentProcessHandle()); |
+#endif |
+ |
+/* |
+ // Append the root path. |
+ CommandLine* cmdline = CommandLine::ForCurrentProcess(); |
+ result += " --root=\"" + FilePathToUTF8(settings->root_path()) + "\""; |
+*/ |
+ |
+ CommandLine cmdline(executable); |
+ cmdline.AppendSwitchPath("--root", build_settings->root_path()); |
+ |
+ // TODO(brettw) append other parameters. |
+ |
+#if defined(OS_WIN) |
+ return WideToUTF8(cmdline.GetCommandLineString()); |
+#else |
+ return cmdline.GetCommandLineString(); |
+#endif |
+} |
+ |
+} // namespace |
+ |
+NinjaBuildWriter::NinjaBuildWriter( |
+ const BuildSettings* build_settings, |
+ const std::vector<const Settings*>& all_settings, |
+ const std::vector<const Target*>& default_toolchain_targets, |
+ std::ostream& out) |
+ : build_settings_(build_settings), |
+ all_settings_(all_settings), |
+ default_toolchain_targets_(default_toolchain_targets), |
+ out_(out), |
+ path_output_(build_settings->build_dir(), ESCAPE_NINJA, true), |
+ helper_(build_settings) { |
+} |
+ |
+NinjaBuildWriter::~NinjaBuildWriter() { |
+} |
+ |
+void NinjaBuildWriter::Run() { |
+ WriteNinjaRules(); |
+ WriteSubninjas(); |
+ WritePhonyAndAllRules(); |
+} |
+ |
+// static |
+bool NinjaBuildWriter::RunAndWriteFile( |
+ const BuildSettings* build_settings, |
+ const std::vector<const Settings*>& all_settings, |
+ const std::vector<const Target*>& default_toolchain_targets) { |
+ base::FilePath ninja_file(build_settings->GetFullPath( |
+ SourceFile(build_settings->build_dir().value() + "build.ninja"))); |
+ file_util::CreateDirectory(ninja_file.DirName()); |
+ |
+ std::ofstream file; |
+ file.open(FilePathToUTF8(ninja_file).c_str(), |
+ std::ios_base::out | std::ios_base::binary); |
+ if (file.fail()) |
+ return false; |
+ |
+ NinjaBuildWriter gen(build_settings, all_settings, |
+ default_toolchain_targets, file); |
+ gen.Run(); |
+ return true; |
+} |
+ |
+void NinjaBuildWriter::WriteNinjaRules() { |
+ out_ << "rule gn\n"; |
+ out_ << " command = " << GetSelfInvocationCommand(build_settings_) << "\n"; |
+ out_ << " description = GN the world\n\n"; |
+ |
+ out_ << "build build.ninja: gn"; |
+ |
+ // Input build files. |
+ std::vector<SourceFile> input_files; |
+ g_scheduler->input_file_manager()->GetAllInputFileNames(&input_files); |
+ for (size_t i = 0; i < input_files.size(); i++) { |
+ out_ << " "; |
+ path_output_.WriteFile(out_, input_files[i]); |
+ } |
+ |
+ // Other files read by the build. |
+ std::vector<SourceFile> other_files = g_scheduler->GetGenDependencies(); |
+ for (size_t i = 0; i < other_files.size(); i++) { |
+ out_ << " "; |
+ path_output_.WriteFile(out_, other_files[i]); |
+ } |
+ |
+ out_ << std::endl << std::endl; |
+} |
+ |
+void NinjaBuildWriter::WriteSubninjas() { |
+ for (size_t i = 0; i < all_settings_.size(); i++) { |
+ out_ << "subninja "; |
+ path_output_.WriteFile(out_, |
+ helper_.GetNinjaFileForToolchain(all_settings_[i])); |
+ out_ << std::endl; |
+ } |
+ out_ << std::endl; |
+} |
+ |
+void NinjaBuildWriter::WritePhonyAndAllRules() { |
+ std::string all_rules; |
+ |
+ // Write phony rules for the default toolchain (don't do other toolchains or |
+ // we'll get naming conflicts). |
+ for (size_t i = 0; i < default_toolchain_targets_.size(); i++) { |
+ const Target* target = default_toolchain_targets_[i]; |
+ if (target->output_type() == Target::NONE) |
+ continue; // Nothing to generate. |
+ |
+ OutputFile target_file = helper_.GetTargetOutputFile(target); |
+ if (target_file.value() != target->label().name()) { |
+ out_ << "build " << target->label().name() << ": phony "; |
+ path_output_.WriteFile(out_, target_file); |
+ out_ << std::endl; |
+ } |
+ |
+ if (!all_rules.empty()) |
+ all_rules.append(" $\n "); |
+ all_rules.append(target_file.value()); |
+ } |
+ |
+ if (!all_rules.empty()) { |
+ out_ << "\nbuild all: phony " << all_rules << std::endl; |
+ out_ << "default all" << std::endl; |
+ } |
+} |
+ |