function_toolchain.cc revision 58537e28ecd584eab876aee8be7156509866d23a
1d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// found in the LICENSE file.
4d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
5d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/err.h"
6d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/functions.h"
7d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/parse_tree.h"
8d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scheduler.h"
9d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scope.h"
10d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/settings.h"
11d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/toolchain.h"
12d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace functions {
14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
15d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochnamespace {
16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// This is jsut a unique value to take the address of to use as the key for
18d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// the toolchain property on a scope.
19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst int kToolchainPropertyKey = 0;
20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Reads the given string from the scope (if present) and puts the result into
22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// dest. If the value is not a string, sets the error and returns false.
23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool ReadString(Scope& scope, const char* var, std::string* dest, Err* err) {
24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const Value* v = scope.GetValue(var, true);
25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!v)
26d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return true;  // Not present is fine.
27d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
28d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!v->VerifyTypeIs(Value::STRING, err))
29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return false;
30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  *dest = v->string_value();
31d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return true;
32d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
33d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
34d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}  // namespace
35d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// toolchain -------------------------------------------------------------------
37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kToolchain[] = "toolchain";
39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kToolchain_Help[] =
40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "TODO(brettw) write this.";
41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunToolchain(Scope* scope,
43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                   const FunctionCallNode* function,
44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                   const std::vector<Value>& args,
45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                   BlockNode* block,
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                   Err* err) {
47d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!EnsureNotProcessingImport(function, scope, err) ||
48d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !EnsureNotProcessingBuildConfig(function, scope, err))
49d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
50d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
51d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Note that we don't want to use MakeLabelForScope since that will include
52d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // the toolchain name in the label, and toolchain labels don't themselves
53d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // have toolchain names.
543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const SourceDir& input_dir = scope->GetSourceDir();
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Label label(input_dir, args[0].string_value());
56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (g_scheduler->verbose_logging())
57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    g_scheduler->Log("Generating toolchain", label.GetUserVisibleName(false));
58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // This object will actually be copied into the one owned by the toolchain
60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // manager, but that has to be done in the lock.
61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Toolchain toolchain(label);
62d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
63d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Scope block_scope(scope);
64d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  block_scope.SetProperty(&kToolchainPropertyKey, &toolchain);
65d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  block->ExecuteBlockInScope(&block_scope, err);
66d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  block_scope.SetProperty(&kToolchainPropertyKey, NULL);
67d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (err->has_error())
68d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
69d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!block_scope.CheckForUnusedVars(err))
70d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
71d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
72d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const BuildSettings* build_settings = scope->settings()->build_settings();
73d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  {
74d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // Save the toolchain definition in the toolchain manager and mark the
75d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // corresponding item in the dependency tree resolved so that targets
76d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // that depend on this toolchain know it's ready.
77d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    base::AutoLock lock(build_settings->item_tree().lock());
78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    build_settings->toolchain_manager().SetToolchainDefinitionLocked(
79d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        toolchain, function->GetRange(), err);
80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    build_settings->item_tree().MarkItemDefinedLocked(build_settings, label,
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                                      err);
82d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
83d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
84d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
85d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// tool ------------------------------------------------------------------------
87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kTool[] = "tool";
89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kTool_Help[] =
90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "TODO(brettw) write this.";
91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunTool(Scope* scope,
93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)              const FunctionCallNode* function,
94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)              const std::vector<Value>& args,
95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)              BlockNode* block,
96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)              Err* err) {
97d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Find the toolchain definition we're executing inside of. The toolchain
98d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // function will set a property pointing to it that we'll pick up.
99d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Toolchain* toolchain = reinterpret_cast<Toolchain*>(
100d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      scope->GetProperty(&kToolchainPropertyKey, NULL));
101d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!toolchain) {
102d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(), "tool() called outside of toolchain().",
103d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "The tool() function can only be used inside a toolchain() "
104d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "definition.");
105d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
106d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
107d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
108d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!EnsureSingleStringArg(function, args, err))
109d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
110d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const std::string& tool_name = args[0].string_value();
111d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Toolchain::ToolType tool_type = Toolchain::ToolNameToType(tool_name);
112d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (tool_type == Toolchain::TYPE_NONE) {
113d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(args[0], "Unknown tool type");
114d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
115d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
116d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
117d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Run the tool block.
118d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Scope block_scope(scope);
119d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  block->ExecuteBlockInScope(&block_scope, err);
120d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (err->has_error())
121d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
122d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
123d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Extract the stuff we need.
124d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Toolchain::Tool t;
125d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!ReadString(block_scope, "command", &t.command, err) ||
126d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !ReadString(block_scope, "depfile", &t.depfile, err) ||
127d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !ReadString(block_scope, "deps", &t.deps, err) ||
128d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !ReadString(block_scope, "description", &t.description, err) ||
129d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !ReadString(block_scope, "pool", &t.pool, err) ||
130d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !ReadString(block_scope, "restat", &t.restat, err) ||
131d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !ReadString(block_scope, "rspfile", &t.rspfile, err) ||
132d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !ReadString(block_scope, "rspfile_content", &t.rspfile_content, err))
133d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
134d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
135d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Make sure there weren't any vars set in this tool that were unused.
136d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!block_scope.CheckForUnusedVars(err))
137d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
138d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
139d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  toolchain->SetTool(tool_type, t);
140d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
141d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// toolchain_args --------------------------------------------------------------
1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)extern const char kToolchainArgs[] = "toolchain_args";
1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)extern const char kToolchainArgs_Help[] =
1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "toolchain_args: Set build arguments for toolchain build setup.\n"
1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  When you specify a target using an alternate toolchain, the master\n"
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  build configuration file is re-interpreted in the context of that\n"
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  toolchain. This function allows you to control the arguments passed\n"
1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  into this alternate invocation of the build.\n"
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  Any default system arguments or arguments passed in on the command-\n"
1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  line will also be passed to the alternate invocation unless explicitly\n"
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  overriddey by toolchain_args.\n"
1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  The toolchain_args will be ignored when the toolchain being defined\n"
1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  is the default. In this case, it's expected you want the default\n"
1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  argument values.\n"
1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  See also \"gn help buildargs\" for an overview of these arguments.\n"
1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "Example:\n"
1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  toolchain(\"my_weird_toolchain\") {\n"
1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    ...\n"
1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    toolchain_args() {\n"
1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "      # Override the system values for a generic Posix system.\n"
1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "      is_win = false\n"
1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "      is_posix = true\n"
1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "      # Pass this new value for specific setup for my toolchain.\n"
1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "      is_my_weird_system = true\n"
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    }\n"
1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  }\n";
1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Value RunToolchainArgs(Scope* scope,
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                       const FunctionCallNode* function,
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                       const std::vector<Value>& args,
1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                       BlockNode* block,
1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                       Err* err) {
1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Find the toolchain definition we're executing inside of. The toolchain
1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // function will set a property pointing to it that we'll pick up.
1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Toolchain* toolchain = reinterpret_cast<Toolchain*>(
1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      scope->GetProperty(&kToolchainPropertyKey, NULL));
1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!toolchain) {
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    *err = Err(function->function(),
1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               "toolchain_args() called outside of toolchain().",
1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               "The toolchain_args() function can only be used inside a "
1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               "toolchain() definition.");
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return Value();
1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!args.empty()) {
1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    *err = Err(function->function(), "This function takes no arguments.");
1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return Value();
1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // This function makes a new scope with various variable sets on it, which
2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // we then save on the toolchain to use when re-invoking the build.
2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Scope block_scope(scope);
2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  block->ExecuteBlockInScope(&block_scope, err);
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err->has_error())
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return Value();
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Scope::KeyValueMap values;
2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  block_scope.GetCurrentScopeValues(&values);
2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  toolchain->args() = values;
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return Value();
2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace functions
214