OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "tools/gn/ninja_build_writer.h" | |
6 | |
7 #include <fstream> | |
8 | |
9 #include "base/command_line.h" | |
10 #include "base/file_util.h" | |
11 #include "base/process/process_handle.h" | |
12 #include "base/strings/utf_string_conversions.h" | |
13 #include "build/build_config.h" | |
14 #include "tools/gn/build_settings.h" | |
15 #include "tools/gn/filesystem_utils.h" | |
16 #include "tools/gn/input_file_manager.h" | |
17 #include "tools/gn/scheduler.h" | |
18 #include "tools/gn/target.h" | |
19 | |
20 #if defined(OS_WIN) | |
21 #include <windows.h> | |
22 #endif | |
23 | |
24 namespace { | |
25 | |
26 std::string GetSelfInvocationCommand(const BuildSettings* build_settings) { | |
27 #if defined(OS_WIN) | |
28 wchar_t module[MAX_PATH]; | |
29 GetModuleFileName(NULL, module, MAX_PATH); | |
30 //result = "\"" + WideToUTF8(module) + "\""; | |
31 base::FilePath executable(module); | |
32 #elif defined(OS_MACOSX) | |
33 // FIXME(brettw) write this on Mac! | |
34 base::FilePath executable("gn"); | |
35 #else | |
36 base::FilePath executable = | |
37 base::GetProcessExecutablePath(base::GetCurrentProcessHandle()); | |
38 #endif | |
39 | |
40 /* | |
41 // Append the root path. | |
42 CommandLine* cmdline = CommandLine::ForCurrentProcess(); | |
43 result += " --root=\"" + FilePathToUTF8(settings->root_path()) + "\""; | |
44 */ | |
45 | |
46 CommandLine cmdline(executable); | |
47 cmdline.AppendSwitchPath("--root", build_settings->root_path()); | |
48 | |
49 // TODO(brettw) append other parameters. | |
50 | |
51 #if defined(OS_WIN) | |
52 return WideToUTF8(cmdline.GetCommandLineString()); | |
53 #else | |
54 return cmdline.GetCommandLineString(); | |
55 #endif | |
56 } | |
57 | |
58 } // namespace | |
59 | |
60 NinjaBuildWriter::NinjaBuildWriter( | |
61 const BuildSettings* build_settings, | |
62 const std::vector<const Settings*>& all_settings, | |
63 const std::vector<const Target*>& default_toolchain_targets, | |
64 std::ostream& out) | |
65 : build_settings_(build_settings), | |
66 all_settings_(all_settings), | |
67 default_toolchain_targets_(default_toolchain_targets), | |
68 out_(out), | |
69 path_output_(build_settings->build_dir(), ESCAPE_NINJA, true), | |
70 helper_(build_settings) { | |
71 } | |
72 | |
73 NinjaBuildWriter::~NinjaBuildWriter() { | |
74 } | |
75 | |
76 void NinjaBuildWriter::Run() { | |
77 WriteNinjaRules(); | |
78 WriteSubninjas(); | |
79 WritePhonyAndAllRules(); | |
80 } | |
81 | |
82 // static | |
83 bool NinjaBuildWriter::RunAndWriteFile( | |
84 const BuildSettings* build_settings, | |
85 const std::vector<const Settings*>& all_settings, | |
86 const std::vector<const Target*>& default_toolchain_targets) { | |
87 base::FilePath ninja_file(build_settings->GetFullPath( | |
88 SourceFile(build_settings->build_dir().value() + "build.ninja"))); | |
89 file_util::CreateDirectory(ninja_file.DirName()); | |
90 | |
91 std::ofstream file; | |
92 file.open(FilePathToUTF8(ninja_file).c_str(), | |
93 std::ios_base::out | std::ios_base::binary); | |
94 if (file.fail()) | |
95 return false; | |
96 | |
97 NinjaBuildWriter gen(build_settings, all_settings, | |
98 default_toolchain_targets, file); | |
99 gen.Run(); | |
100 return true; | |
101 } | |
102 | |
103 void NinjaBuildWriter::WriteNinjaRules() { | |
104 out_ << "rule gn\n"; | |
105 out_ << " command = " << GetSelfInvocationCommand(build_settings_) << "\n"; | |
106 out_ << " description = GN the world\n\n"; | |
107 | |
108 out_ << "build build.ninja: gn"; | |
109 | |
110 // Input build files. | |
111 std::vector<SourceFile> input_files; | |
112 g_scheduler->input_file_manager()->GetAllInputFileNames(&input_files); | |
113 for (size_t i = 0; i < input_files.size(); i++) { | |
114 out_ << " "; | |
115 path_output_.WriteFile(out_, input_files[i]); | |
116 } | |
117 | |
118 // Other files read by the build. | |
119 std::vector<SourceFile> other_files = g_scheduler->GetGenDependencies(); | |
120 for (size_t i = 0; i < other_files.size(); i++) { | |
121 out_ << " "; | |
122 path_output_.WriteFile(out_, other_files[i]); | |
123 } | |
124 | |
125 out_ << std::endl << std::endl; | |
126 } | |
127 | |
128 void NinjaBuildWriter::WriteSubninjas() { | |
129 for (size_t i = 0; i < all_settings_.size(); i++) { | |
130 out_ << "subninja "; | |
131 path_output_.WriteFile(out_, | |
132 helper_.GetNinjaFileForToolchain(all_settings_[i])); | |
133 out_ << std::endl; | |
134 } | |
135 out_ << std::endl; | |
136 } | |
137 | |
138 void NinjaBuildWriter::WritePhonyAndAllRules() { | |
139 std::string all_rules; | |
140 | |
141 // Write phony rules for the default toolchain (don't do other toolchains or | |
142 // we'll get naming conflicts). | |
143 for (size_t i = 0; i < default_toolchain_targets_.size(); i++) { | |
144 const Target* target = default_toolchain_targets_[i]; | |
145 if (target->output_type() == Target::NONE) | |
146 continue; // Nothing to generate. | |
147 | |
148 OutputFile target_file = helper_.GetTargetOutputFile(target); | |
149 if (target_file.value() != target->label().name()) { | |
150 out_ << "build " << target->label().name() << ": phony "; | |
151 path_output_.WriteFile(out_, target_file); | |
152 out_ << std::endl; | |
153 } | |
154 | |
155 if (!all_rules.empty()) | |
156 all_rules.append(" $\n "); | |
157 all_rules.append(target_file.value()); | |
158 } | |
159 | |
160 if (!all_rules.empty()) { | |
161 out_ << "\nbuild all: phony " << all_rules << std::endl; | |
162 out_ << "default all" << std::endl; | |
163 } | |
164 } | |
165 | |
OLD | NEW |