Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / tools / gn / function_toolchain.cc
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/err.h"
6 #include "tools/gn/functions.h"
7 #include "tools/gn/parse_tree.h"
8 #include "tools/gn/scheduler.h"
9 #include "tools/gn/scope.h"
10 #include "tools/gn/settings.h"
11 #include "tools/gn/toolchain.h"
12 #include "tools/gn/value_extractors.h"
13 #include "tools/gn/variables.h"
14
15 namespace functions {
16
17 namespace {
18
19 // This is jsut a unique value to take the address of to use as the key for
20 // the toolchain property on a scope.
21 const int kToolchainPropertyKey = 0;
22
23 // Reads the given string from the scope (if present) and puts the result into
24 // dest. If the value is not a string, sets the error and returns false.
25 bool ReadString(Scope& scope, const char* var, std::string* dest, Err* err) {
26   const Value* v = scope.GetValue(var, true);
27   if (!v)
28     return true;  // Not present is fine.
29
30   if (!v->VerifyTypeIs(Value::STRING, err))
31     return false;
32   *dest = v->string_value();
33   return true;
34 }
35
36 }  // namespace
37
38 // toolchain -------------------------------------------------------------------
39
40 const char kToolchain[] = "toolchain";
41 const char kToolchain_HelpShort[] =
42     "toolchain: Defines a toolchain.";
43 const char kToolchain_Help[] =
44     "toolchain: Defines a toolchain.\n"
45     "\n"
46     "  A toolchain is a set of commands and build flags used to compile the\n"
47     "  source code. You can have more than one toolchain in use at once in\n"
48     "  a build.\n"
49     "\n"
50     "  A toolchain specifies the commands to run for various input file\n"
51     "  types via the \"tool\" call (see \"gn help tool\") and specifies\n"
52     "  arguments to be passed to the toolchain build via the\n"
53     "  \"toolchain_args\" call (see \"gn help toolchain_args\").\n"
54     "\n"
55     "  In addition, a toolchain can specify dependencies via the \"deps\"\n"
56     "  variable like a target. These dependencies will be resolved before any\n"
57     "  target in the toolchain is compiled. To avoid circular dependencies\n"
58     "  these must be targets defined in another toolchain.\n"
59     "\n"
60     "Invoking targets in toolchains:\n"
61     "\n"
62     "  By default, when a target depends on another, there is an implicit\n"
63     "  toolchain label that is inherited, so the dependee has the same one\n"
64     "  as the dependent.\n"
65     "\n"
66     "  You can override this and refer to any other toolchain by explicitly\n"
67     "  labeling the toolchain to use. For example:\n"
68     "    datadeps = [ \"//plugins:mine(//toolchains:plugin_toolchain)\" ]\n"
69     "  The string \"//build/toolchains:plugin_toolchain\" is a label that\n"
70     "  identifies the toolchain declaration for compiling the sources.\n"
71     "\n"
72     "  To load a file in an alternate toolchain, GN does the following:\n"
73     "\n"
74     "   1. Loads the file with the toolchain definition in it (as determined\n"
75     "      by the toolchain label).\n"
76     "   2. Re-runs the master build configuration file, applying the\n"
77     "      arguments specified by the toolchain_args section of the toolchain\n"
78     "      definition (see \"gn help toolchain_args\").\n"
79     "   3. Loads the destination build file in the context of the\n"
80     "      configuration file in the previous step.\n"
81     "\n"
82     "Example:\n"
83     "  toolchain(\"plugin_toolchain\") {\n"
84     "    tool(\"cc\") {\n"
85     "      command = \"gcc $in\"\n"
86     "    }\n"
87     "\n"
88     "    toolchain_args() {\n"
89     "      is_plugin = true\n"
90     "      is_32bit = true\n"
91     "      is_64bit = false\n"
92     "    }\n"
93     "  }\n";
94
95 Value RunToolchain(Scope* scope,
96                    const FunctionCallNode* function,
97                    const std::vector<Value>& args,
98                    BlockNode* block,
99                    Err* err) {
100   if (!EnsureNotProcessingImport(function, scope, err) ||
101       !EnsureNotProcessingBuildConfig(function, scope, err))
102     return Value();
103
104   // Note that we don't want to use MakeLabelForScope since that will include
105   // the toolchain name in the label, and toolchain labels don't themselves
106   // have toolchain names.
107   const SourceDir& input_dir = scope->GetSourceDir();
108   Label label(input_dir, args[0].string_value());
109   if (g_scheduler->verbose_logging())
110     g_scheduler->Log("Definining toolchain", label.GetUserVisibleName(false));
111
112   // This object will actually be copied into the one owned by the toolchain
113   // manager, but that has to be done in the lock.
114   scoped_ptr<Toolchain> toolchain(new Toolchain(scope->settings(), label));
115   toolchain->set_defined_from(function);
116   toolchain->visibility().SetPublic();
117
118   Scope block_scope(scope);
119   block_scope.SetProperty(&kToolchainPropertyKey, toolchain.get());
120   block->ExecuteBlockInScope(&block_scope, err);
121   block_scope.SetProperty(&kToolchainPropertyKey, NULL);
122   if (err->has_error())
123     return Value();
124
125   // Read deps (if any).
126   const Value* deps_value = block_scope.GetValue(variables::kDeps, true);
127   if (deps_value) {
128     ExtractListOfLabels(
129         *deps_value, block_scope.GetSourceDir(),
130         ToolchainLabelForScope(&block_scope), &toolchain->deps(), err);
131     if (err->has_error())
132       return Value();
133   }
134
135
136   if (!block_scope.CheckForUnusedVars(err))
137     return Value();
138
139   // Save this toolchain.
140   Scope::ItemVector* collector = scope->GetItemCollector();
141   if (!collector) {
142     *err = Err(function, "Can't define a toolchain in this context.");
143     return Value();
144   }
145   collector->push_back(new scoped_ptr<Item>(toolchain.PassAs<Item>()));
146   return Value();
147 }
148
149 // tool ------------------------------------------------------------------------
150
151 const char kTool[] = "tool";
152 const char kTool_HelpShort[] =
153     "tool: Specify arguments to a toolchain tool.";
154 const char kTool_Help[] =
155     "tool: Specify arguments to a toolchain tool.\n"
156     "\n"
157     "  tool(<command type>) { <command flags> }\n"
158     "\n"
159     "  Used inside a toolchain definition to define a command to run for a\n"
160     "  given file type. See also \"gn help toolchain\".\n"
161     "\n"
162     "Command types\n"
163     "\n"
164     "  The following values may be passed to the tool() function for the type\n"
165     "  of the command:\n"
166     "\n"
167     "  \"cc\", \"cxx\", \"objc\", \"objcxx\", \"asm\", \"alink\", \"solink\",\n"
168     "  \"link\", \"stamp\", \"copy\"\n"
169     "\n"
170     "Tool-specific notes\n"
171     "\n"
172     "  copy\n"
173     "    The copy command should be a native OS command since it does not\n"
174     "    implement toolchain dependencies (which would enable a copy tool to\n"
175     "    be compiled by a previous step).\n"
176     "\n"
177     "    It is legal for the copy to not update the timestamp of the output\n"
178     "    file (as long as it's greater than or equal to the input file). This\n"
179     "    allows the copy command to be implemented as a hard link which can\n"
180     "    be more efficient.\n"
181     "\n"
182     "Command flags\n"
183     "\n"
184     "  These variables may be specified in the { } block after the tool call.\n"
185     "  They are passed directly to Ninja. See the ninja documentation for how\n"
186     "  they work. Don't forget to backslash-escape $ required by Ninja to\n"
187     "  prevent GN from doing variable expansion.\n"
188     "\n"
189     "    command, depfile, depsformat, description, pool, restat, rspfile,\n"
190     "    rspfile_content\n"
191     "\n"
192     "  (Note that GN uses \"depsformat\" for Ninja's \"deps\" variable to\n"
193     "  avoid confusion with dependency lists.)\n"
194     "\n"
195     "  Additionally, lib_prefix and lib_dir_prefix may be used for the link\n"
196     "  tools. These strings will be prepended to the libraries and library\n"
197     "  search directories, respectively, because linkers differ on how to\n"
198     "  specify them.\n"
199     "\n"
200     "  Note: On Mac libraries with names ending in \".framework\" will be\n"
201     "  added to the link like with a \"-framework\" switch and the lib prefix\n"
202     "  will be ignored.\n"
203     "\n"
204     "Ninja variables available to tool invocations\n"
205     "\n"
206     "  When writing tool commands, you use the various built-in Ninja\n"
207     "  variables like \"$in\" and \"$out\" (note that the $ must be escaped\n"
208     "  for it to be passed to Ninja, so write \"\\$in\" in the command\n"
209     "  string).\n"
210     "\n"
211     "  GN defines the following variables for binary targets to access the\n"
212     "  various computed information needed for compiling:\n"
213     "\n"
214     "    - Compiler flags: \"cflags\", \"cflags_c\", \"cflags_cc\",\n"
215     "          \"cflags_objc\", \"cflags_objcc\"\n"
216     "\n"
217     "    - Linker flags: \"ldflags\", \"libs\"\n"
218     "\n"
219     "  GN sets these other variables with target information that can be\n"
220     "  used for computing names for supplimetary files:\n"
221     "\n"
222     "    - \"target_name\": The name of the current target with no\n"
223     "      path information. For example \"mylib\".\n"
224     "\n"
225     "    - \"target_out_dir\": The value of \"target_out_dir\" from the BUILD\n"
226     "      file for this target (see \"gn help target_out_dir\"), relative\n"
227     "      to the root build directory with no trailing slash.\n"
228     "\n"
229     "    - \"root_out_dir\": The value of \"root_out_dir\" from the BUILD\n"
230     "      file for this target (see \"gn help root_out_dir\"), relative\n"
231     "      to the root build directory with no trailing slash.\n"
232     "\n"
233     "Example\n"
234     "\n"
235     "  toolchain(\"my_toolchain\") {\n"
236     "    # Put these at the top to apply to all tools below.\n"
237     "    lib_prefix = \"-l\"\n"
238     "    lib_dir_prefix = \"-L\"\n"
239     "\n"
240     "    tool(\"cc\") {\n"
241     "      command = \"gcc \\$in -o \\$out\"\n"
242     "      description = \"GCC \\$in\"\n"
243     "    }\n"
244     "    tool(\"cxx\") {\n"
245     "      command = \"g++ \\$in -o \\$out\"\n"
246     "      description = \"G++ \\$in\"\n"
247     "    }\n"
248     "  }\n";
249
250 Value RunTool(Scope* scope,
251               const FunctionCallNode* function,
252               const std::vector<Value>& args,
253               BlockNode* block,
254               Err* err) {
255   // Find the toolchain definition we're executing inside of. The toolchain
256   // function will set a property pointing to it that we'll pick up.
257   Toolchain* toolchain = reinterpret_cast<Toolchain*>(
258       scope->GetProperty(&kToolchainPropertyKey, NULL));
259   if (!toolchain) {
260     *err = Err(function->function(), "tool() called outside of toolchain().",
261         "The tool() function can only be used inside a toolchain() "
262         "definition.");
263     return Value();
264   }
265
266   if (!EnsureSingleStringArg(function, args, err))
267     return Value();
268   const std::string& tool_name = args[0].string_value();
269   Toolchain::ToolType tool_type = Toolchain::ToolNameToType(tool_name);
270   if (tool_type == Toolchain::TYPE_NONE) {
271     *err = Err(args[0], "Unknown tool type");
272     return Value();
273   }
274
275   // Run the tool block.
276   Scope block_scope(scope);
277   block->ExecuteBlockInScope(&block_scope, err);
278   if (err->has_error())
279     return Value();
280
281   // Extract the stuff we need.
282   Toolchain::Tool t;
283   if (!ReadString(block_scope, "command", &t.command, err) ||
284       !ReadString(block_scope, "depfile", &t.depfile, err) ||
285       // TODO(brettw) delete this once we rename "deps" -> "depsformat" in
286       // the toolchain definitions. This will avoid colliding with the
287       // toolchain's "deps" list. For now, accept either.
288       !ReadString(block_scope, "deps", &t.depsformat, err) ||
289       !ReadString(block_scope, "depsformat", &t.depsformat, err) ||
290       !ReadString(block_scope, "description", &t.description, err) ||
291       !ReadString(block_scope, "lib_dir_prefix", &t.lib_dir_prefix, err) ||
292       !ReadString(block_scope, "lib_prefix", &t.lib_prefix, err) ||
293       !ReadString(block_scope, "pool", &t.pool, err) ||
294       !ReadString(block_scope, "restat", &t.restat, err) ||
295       !ReadString(block_scope, "rspfile", &t.rspfile, err) ||
296       !ReadString(block_scope, "rspfile_content", &t.rspfile_content, err))
297     return Value();
298
299   // Make sure there weren't any vars set in this tool that were unused.
300   if (!block_scope.CheckForUnusedVars(err))
301     return Value();
302
303   toolchain->SetTool(tool_type, t);
304   return Value();
305 }
306
307 // toolchain_args --------------------------------------------------------------
308
309 extern const char kToolchainArgs[] = "toolchain_args";
310 extern const char kToolchainArgs_HelpShort[] =
311     "toolchain_args: Set build arguments for toolchain build setup.";
312 extern const char kToolchainArgs_Help[] =
313     "toolchain_args: Set build arguments for toolchain build setup.\n"
314     "\n"
315     "  Used inside a toolchain definition to pass arguments to an alternate\n"
316     "  toolchain's invocation of the build.\n"
317     "\n"
318     "  When you specify a target using an alternate toolchain, the master\n"
319     "  build configuration file is re-interpreted in the context of that\n"
320     "  toolchain (see \"gn help toolchain\"). The toolchain_args function\n"
321     "  allows you to control the arguments passed into this alternate\n"
322     "  invocation of the build.\n"
323     "\n"
324     "  Any default system arguments or arguments passed in on the command-\n"
325     "  line will also be passed to the alternate invocation unless explicitly\n"
326     "  overridden by toolchain_args.\n"
327     "\n"
328     "  The toolchain_args will be ignored when the toolchain being defined\n"
329     "  is the default. In this case, it's expected you want the default\n"
330     "  argument values.\n"
331     "\n"
332     "  See also \"gn help buildargs\" for an overview of these arguments.\n"
333     "\n"
334     "Example:\n"
335     "  toolchain(\"my_weird_toolchain\") {\n"
336     "    ...\n"
337     "    toolchain_args() {\n"
338     "      # Override the system values for a generic Posix system.\n"
339     "      is_win = false\n"
340     "      is_posix = true\n"
341     "\n"
342     "      # Pass this new value for specific setup for my toolchain.\n"
343     "      is_my_weird_system = true\n"
344     "    }\n"
345     "  }\n";
346
347 Value RunToolchainArgs(Scope* scope,
348                        const FunctionCallNode* function,
349                        const std::vector<Value>& args,
350                        BlockNode* block,
351                        Err* err) {
352   // Find the toolchain definition we're executing inside of. The toolchain
353   // function will set a property pointing to it that we'll pick up.
354   Toolchain* toolchain = reinterpret_cast<Toolchain*>(
355       scope->GetProperty(&kToolchainPropertyKey, NULL));
356   if (!toolchain) {
357     *err = Err(function->function(),
358                "toolchain_args() called outside of toolchain().",
359                "The toolchain_args() function can only be used inside a "
360                "toolchain() definition.");
361     return Value();
362   }
363
364   if (!args.empty()) {
365     *err = Err(function->function(), "This function takes no arguments.");
366     return Value();
367   }
368
369   // This function makes a new scope with various variable sets on it, which
370   // we then save on the toolchain to use when re-invoking the build.
371   Scope block_scope(scope);
372   block->ExecuteBlockInScope(&block_scope, err);
373   if (err->has_error())
374     return Value();
375
376   Scope::KeyValueMap values;
377   block_scope.GetCurrentScopeValues(&values);
378   toolchain->args() = values;
379
380   return Value();
381 }
382
383 }  // namespace functions