|  | // 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 <algorithm> | 
|  | #include <limits> | 
|  | #include <memory> | 
|  | #include <utility> | 
|  |  | 
|  | #include "tools/gn/c_tool.h" | 
|  | #include "tools/gn/err.h" | 
|  | #include "tools/gn/functions.h" | 
|  | #include "tools/gn/general_tool.h" | 
|  | #include "tools/gn/label.h" | 
|  | #include "tools/gn/label_ptr.h" | 
|  | #include "tools/gn/parse_tree.h" | 
|  | #include "tools/gn/scheduler.h" | 
|  | #include "tools/gn/scope.h" | 
|  | #include "tools/gn/settings.h" | 
|  | #include "tools/gn/tool.h" | 
|  | #include "tools/gn/toolchain.h" | 
|  | #include "tools/gn/value_extractors.h" | 
|  | #include "tools/gn/variables.h" | 
|  |  | 
|  | namespace functions { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // This is just a unique value to take the address of to use as the key for | 
|  | // the toolchain property on a scope. | 
|  | const int kToolchainPropertyKey = 0; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | // toolchain ------------------------------------------------------------------- | 
|  |  | 
|  | const char kToolchain[] = "toolchain"; | 
|  | const char kToolchain_HelpShort[] = "toolchain: Defines a toolchain."; | 
|  | const char kToolchain_Help[] = | 
|  | R"*(toolchain: Defines a toolchain. | 
|  |  | 
|  | A toolchain is a set of commands and build flags used to compile the source | 
|  | code. The toolchain() function defines these commands. | 
|  |  | 
|  | Toolchain overview | 
|  |  | 
|  | You can have more than one toolchain in use at once in a build and a target | 
|  | can exist simultaneously in multiple toolchains. A build file is executed | 
|  | once for each toolchain it is referenced in so the GN code can vary all | 
|  | parameters of each target (or which targets exist) on a per-toolchain basis. | 
|  |  | 
|  | When you have a simple build with only one toolchain, the build config file | 
|  | is loaded only once at the beginning of the build. It must call | 
|  | set_default_toolchain() (see "gn help set_default_toolchain") to tell GN the | 
|  | label of the toolchain definition to use. The "toolchain_args" section of the | 
|  | toolchain definition is ignored. | 
|  |  | 
|  | When a target has a dependency on a target using different toolchain (see "gn | 
|  | help labels" for how to specify this), GN will start a build using that | 
|  | secondary toolchain to resolve the target. GN will load the build config file | 
|  | with the build arguments overridden as specified in the toolchain_args. | 
|  | Because the default toolchain is already known, calls to | 
|  | set_default_toolchain() are ignored. | 
|  |  | 
|  | To load a file in an alternate toolchain, GN does the following: | 
|  |  | 
|  | 1. Loads the file with the toolchain definition in it (as determined by the | 
|  | toolchain label). | 
|  | 2. Re-runs the master build configuration file, applying the arguments | 
|  | specified by the toolchain_args section of the toolchain definition. | 
|  | 3. Loads the destination build file in the context of the configuration file | 
|  | in the previous step. | 
|  |  | 
|  | The toolchain configuration is two-way. In the default toolchain (i.e. the | 
|  | main build target) the configuration flows from the build config file to the | 
|  | toolchain. The build config file looks at the state of the build (OS type, | 
|  | CPU architecture, etc.) and decides which toolchain to use (via | 
|  | set_default_toolchain()). In secondary toolchains, the configuration flows | 
|  | from the toolchain to the build config file: the "toolchain_args" in the | 
|  | toolchain definition specifies the arguments to re-invoke the build. | 
|  |  | 
|  | Functions and variables | 
|  |  | 
|  | tool() | 
|  | The tool() function call specifies the commands to run for a given step. See | 
|  | "gn help tool". | 
|  |  | 
|  | toolchain_args [scope] | 
|  | Overrides for build arguments to pass to the toolchain when invoking it. | 
|  | This is a variable of type "scope" where the variable names correspond to | 
|  | variables in declare_args() blocks. | 
|  |  | 
|  | When you specify a target using an alternate toolchain, the master build | 
|  | configuration file is re-interpreted in the context of that toolchain. | 
|  | toolchain_args allows you to control the arguments passed into this | 
|  | alternate invocation of the build. | 
|  |  | 
|  | Any default system arguments or arguments passed in via "gn args" will also | 
|  | be passed to the alternate invocation unless explicitly overridden by | 
|  | toolchain_args. | 
|  |  | 
|  | The toolchain_args will be ignored when the toolchain being defined is the | 
|  | default. In this case, it's expected you want the default argument values. | 
|  |  | 
|  | See also "gn help buildargs" for an overview of these arguments. | 
|  |  | 
|  | propagates_configs [boolean, default=false] | 
|  | Determines whether public_configs and all_dependent_configs in this | 
|  | toolchain propagate to targets in other toolchains. | 
|  |  | 
|  | When false (the default), this toolchain will not propagate any configs to | 
|  | targets in other toolchains that depend on it targets inside this | 
|  | toolchain. This matches the most common usage of toolchains where they | 
|  | represent different architectures or compilers and the settings that apply | 
|  | to one won't necessarily apply to others. | 
|  |  | 
|  | When true, configs (public and all-dependent) will cross the boundary out | 
|  | of this toolchain as if the toolchain boundary wasn't there. This only | 
|  | affects one direction of dependencies: a toolchain can't control whether | 
|  | it accepts such configs, only whether it pushes them. The build is | 
|  | responsible for ensuring that any external targets depending on targets in | 
|  | this toolchain are compatible with the compiler flags, etc. that may be | 
|  | propagated. | 
|  |  | 
|  | deps [string list] | 
|  | Dependencies of this toolchain. These dependencies will be resolved before | 
|  | any target in the toolchain is compiled. To avoid circular dependencies | 
|  | these must be targets defined in another toolchain. | 
|  |  | 
|  | This is expressed as a list of targets, and generally these targets will | 
|  | always specify a toolchain: | 
|  | deps = [ "//foo/bar:baz(//build/toolchain:bootstrap)" ] | 
|  |  | 
|  | This concept is somewhat inefficient to express in Ninja (it requires a lot | 
|  | of duplicate of rules) so should only be used when absolutely necessary. | 
|  |  | 
|  | Example of defining a toolchain | 
|  |  | 
|  | toolchain("32") { | 
|  | tool("cc") { | 
|  | command = "gcc {{source}}" | 
|  | ... | 
|  | } | 
|  |  | 
|  | toolchain_args = { | 
|  | use_doom_melon = true  # Doom melon always required for 32-bit builds. | 
|  | current_cpu = "x86" | 
|  | } | 
|  | } | 
|  |  | 
|  | toolchain("64") { | 
|  | tool("cc") { | 
|  | command = "gcc {{source}}" | 
|  | ... | 
|  | } | 
|  |  | 
|  | toolchain_args = { | 
|  | # use_doom_melon is not overridden here, it will take the default. | 
|  | current_cpu = "x64" | 
|  | } | 
|  | } | 
|  |  | 
|  | Example of cross-toolchain dependencies | 
|  |  | 
|  | If a 64-bit target wants to depend on a 32-bit binary, it would specify a | 
|  | dependency using data_deps (data deps are like deps that are only needed at | 
|  | runtime and aren't linked, since you can't link a 32-bit and a 64-bit | 
|  | library). | 
|  |  | 
|  | executable("my_program") { | 
|  | ... | 
|  | if (target_cpu == "x64") { | 
|  | # The 64-bit build needs this 32-bit helper. | 
|  | data_deps = [ ":helper(//toolchains:32)" ] | 
|  | } | 
|  | } | 
|  |  | 
|  | if (target_cpu == "x86") { | 
|  | # Our helper library is only compiled in 32-bits. | 
|  | shared_library("helper") { | 
|  | ... | 
|  | } | 
|  | } | 
|  | )*"; | 
|  |  | 
|  | Value RunToolchain(Scope* scope, | 
|  | const FunctionCallNode* function, | 
|  | const std::vector<Value>& args, | 
|  | BlockNode* block, | 
|  | Err* err) { | 
|  | NonNestableBlock non_nestable(scope, function, "toolchain"); | 
|  | if (!non_nestable.Enter(err)) | 
|  | return Value(); | 
|  |  | 
|  | if (!EnsureNotProcessingImport(function, scope, err) || | 
|  | !EnsureNotProcessingBuildConfig(function, scope, err)) | 
|  | return Value(); | 
|  |  | 
|  | // Note that we don't want to use MakeLabelForScope since that will include | 
|  | // the toolchain name in the label, and toolchain labels don't themselves | 
|  | // have toolchain names. | 
|  | const SourceDir& input_dir = scope->GetSourceDir(); | 
|  | Label label(input_dir, args[0].string_value()); | 
|  | if (g_scheduler->verbose_logging()) | 
|  | g_scheduler->Log("Defining toolchain", label.GetUserVisibleName(false)); | 
|  |  | 
|  | // This object will actually be copied into the one owned by the toolchain | 
|  | // manager, but that has to be done in the lock. | 
|  | std::unique_ptr<Toolchain> toolchain = std::make_unique<Toolchain>( | 
|  | scope->settings(), label, scope->build_dependency_files()); | 
|  | toolchain->set_defined_from(function); | 
|  | toolchain->visibility().SetPublic(); | 
|  |  | 
|  | Scope block_scope(scope); | 
|  | block_scope.SetProperty(&kToolchainPropertyKey, toolchain.get()); | 
|  | block->Execute(&block_scope, err); | 
|  | block_scope.SetProperty(&kToolchainPropertyKey, nullptr); | 
|  | if (err->has_error()) | 
|  | return Value(); | 
|  |  | 
|  | // Read deps (if any). | 
|  | const Value* deps_value = block_scope.GetValue(variables::kDeps, true); | 
|  | if (deps_value) { | 
|  | ExtractListOfLabels(*deps_value, block_scope.GetSourceDir(), | 
|  | ToolchainLabelForScope(&block_scope), | 
|  | &toolchain->deps(), err); | 
|  | if (err->has_error()) | 
|  | return Value(); | 
|  | } | 
|  |  | 
|  | // Read toolchain args (if any). | 
|  | const Value* toolchain_args = block_scope.GetValue("toolchain_args", true); | 
|  | if (toolchain_args) { | 
|  | if (!toolchain_args->VerifyTypeIs(Value::SCOPE, err)) | 
|  | return Value(); | 
|  |  | 
|  | Scope::KeyValueMap values; | 
|  | toolchain_args->scope_value()->GetCurrentScopeValues(&values); | 
|  | toolchain->args() = values; | 
|  | } | 
|  |  | 
|  | // Read propagates_configs (if present). | 
|  | const Value* propagates_configs = | 
|  | block_scope.GetValue("propagates_configs", true); | 
|  | if (propagates_configs) { | 
|  | if (!propagates_configs->VerifyTypeIs(Value::BOOLEAN, err)) | 
|  | return Value(); | 
|  | toolchain->set_propagates_configs(propagates_configs->boolean_value()); | 
|  | } | 
|  |  | 
|  | if (!block_scope.CheckForUnusedVars(err)) | 
|  | return Value(); | 
|  |  | 
|  | // Save this toolchain. | 
|  | toolchain->ToolchainSetupComplete(); | 
|  | Scope::ItemVector* collector = scope->GetItemCollector(); | 
|  | if (!collector) { | 
|  | *err = Err(function, "Can't define a toolchain in this context."); | 
|  | return Value(); | 
|  | } | 
|  | collector->push_back(std::move(toolchain)); | 
|  | return Value(); | 
|  | } | 
|  |  | 
|  | // tool ------------------------------------------------------------------------ | 
|  |  | 
|  | const char kTool[] = "tool"; | 
|  | const char kTool_HelpShort[] = "tool: Specify arguments to a toolchain tool."; | 
|  | const char kTool_Help[] = | 
|  | R"(tool: Specify arguments to a toolchain tool. | 
|  |  | 
|  | Usage | 
|  |  | 
|  | tool(<tool type>) { | 
|  | <tool variables...> | 
|  | } | 
|  |  | 
|  | Tool types | 
|  |  | 
|  | Compiler tools: | 
|  | "cc": C compiler | 
|  | "cxx": C++ compiler | 
|  | "objc": Objective C compiler | 
|  | "objcxx": Objective C++ compiler | 
|  | "rc": Resource compiler (Windows .rc files) | 
|  | "asm": Assembler | 
|  |  | 
|  | Linker tools: | 
|  | "alink": Linker for static libraries (archives) | 
|  | "solink": Linker for shared libraries | 
|  | "link": Linker for executables | 
|  |  | 
|  | Other tools: | 
|  | "stamp": Tool for creating stamp files | 
|  | "copy": Tool to copy files. | 
|  | "action": Defaults for actions | 
|  |  | 
|  | Platform specific tools: | 
|  | "copy_bundle_data": [iOS, macOS] Tool to copy files in a bundle. | 
|  | "compile_xcassets": [iOS, macOS] Tool to compile asset catalogs. | 
|  |  | 
|  | Rust tools: | 
|  | "rustc": Rust compiler and linker | 
|  |  | 
|  | Tool variables | 
|  |  | 
|  | command  [string with substitutions] | 
|  | Valid for: all tools except "action" (required) | 
|  |  | 
|  | The command to run. | 
|  |  | 
|  | command_launcher  [string] | 
|  | Valid for: all tools except "action" (optional) | 
|  |  | 
|  | The prefix with which to launch the command (e.g. the path to a Goma or | 
|  | CCache compiler launcher). | 
|  |  | 
|  | Note that this prefix will not be included in the compilation database or | 
|  | IDE files generated from the build. | 
|  |  | 
|  | default_output_dir  [string with substitutions] | 
|  | Valid for: linker tools | 
|  |  | 
|  | Default directory name for the output file relative to the | 
|  | root_build_dir. It can contain other substitution patterns. This will | 
|  | be the default value for the {{output_dir}} expansion (discussed below) | 
|  | but will be overridden by the "output_dir" variable in a target, if one | 
|  | is specified. | 
|  |  | 
|  | GN doesn't do anything with this string other than pass it along, | 
|  | potentially with target-specific overrides. It is the tool's job to use | 
|  | the expansion so that the files will be in the right place. | 
|  |  | 
|  | default_output_extension  [string] | 
|  | Valid for: linker tools | 
|  |  | 
|  | Extension for the main output of a linkable tool. It includes the | 
|  | leading dot. This will be the default value for the | 
|  | {{output_extension}} expansion (discussed below) but will be overridden | 
|  | by by the "output extension" variable in a target, if one is specified. | 
|  | Empty string means no extension. | 
|  |  | 
|  | GN doesn't actually do anything with this extension other than pass it | 
|  | along, potentially with target-specific overrides. One would typically | 
|  | use the {{output_extension}} value in the "outputs" to read this value. | 
|  |  | 
|  | Example: default_output_extension = ".exe" | 
|  |  | 
|  | depfile  [string with substitutions] | 
|  | Valid for: compiler tools (optional) | 
|  |  | 
|  | If the tool can write ".d" files, this specifies the name of the | 
|  | resulting file. These files are used to list header file dependencies | 
|  | (or other implicit input dependencies) that are discovered at build | 
|  | time. See also "depsformat". | 
|  |  | 
|  | Example: depfile = "{{output}}.d" | 
|  |  | 
|  | depsformat  [string] | 
|  | Valid for: compiler tools (when depfile is specified) | 
|  |  | 
|  | Format for the deps outputs. This is either "gcc" or "msvc". See the | 
|  | ninja documentation for "deps" for more information. | 
|  |  | 
|  | Example: depsformat = "gcc" | 
|  |  | 
|  | description  [string with substitutions, optional] | 
|  | Valid for: all tools | 
|  |  | 
|  | What to print when the command is run. | 
|  |  | 
|  | Example: description = "Compiling {{source}}" | 
|  |  | 
|  | exe_output_extension [string, optional, rust tools only] | 
|  | rlib_output_extension [string, optional, rust tools only] | 
|  | dylib_output_extension [string, optional, rust tools only] | 
|  | cdylib_output_extension [string, optional, rust tools only] | 
|  | proc_macro_output_extension [string, optional, rust tools only] | 
|  | Valid for: Rust tools | 
|  |  | 
|  | These specify the default tool output for each of the crate types. | 
|  | The default is empty for executables, shared, and static libraries and | 
|  | ".rlib" for rlibs. Note that the Rust compiler complains with an error | 
|  | if external crates do not take the form `lib<name>.rlib` or | 
|  | `lib<name>.<shared_extension>`, where `<shared_extension>` is `.so`, | 
|  | `.dylib`, or `.dll` as appropriate for the platform. | 
|  |  | 
|  | lib_switch  [string, optional, link tools only] | 
|  | lib_dir_switch  [string, optional, link tools only] | 
|  | Valid for: Linker tools except "alink" | 
|  |  | 
|  | These strings will be prepended to the libraries and library search | 
|  | directories, respectively, because linkers differ on how specify them. | 
|  | If you specified: | 
|  | lib_switch = "-l" | 
|  | lib_dir_switch = "-L" | 
|  | then the "{{libs}}" expansion for [ "freetype", "expat"] would be | 
|  | "-lfreetype -lexpat". | 
|  |  | 
|  | outputs  [list of strings with substitutions] | 
|  | Valid for: Linker and compiler tools (required) | 
|  |  | 
|  | An array of names for the output files the tool produces. These are | 
|  | relative to the build output directory. There must always be at least | 
|  | one output file. There can be more than one output (a linker might | 
|  | produce a library and an import library, for example). | 
|  |  | 
|  | This array just declares to GN what files the tool will produce. It is | 
|  | your responsibility to specify the tool command that actually produces | 
|  | these files. | 
|  |  | 
|  | If you specify more than one output for shared library links, you | 
|  | should consider setting link_output, depend_output, and | 
|  | runtime_outputs. | 
|  |  | 
|  | Example for a compiler tool that produces .obj files: | 
|  | outputs = [ | 
|  | "{{source_out_dir}}/{{source_name_part}}.obj" | 
|  | ] | 
|  |  | 
|  | Example for a linker tool that produces a .dll and a .lib. The use of | 
|  | {{target_output_name}}, {{output_extension}} and {{output_dir}} allows | 
|  | the target to override these values. | 
|  | outputs = [ | 
|  | "{{output_dir}}/{{target_output_name}}" | 
|  | "{{output_extension}}", | 
|  | "{{output_dir}}/{{target_output_name}}.lib", | 
|  | ] | 
|  |  | 
|  | pool [label, optional] | 
|  | Valid for: all tools (optional) | 
|  |  | 
|  | Label of the pool to use for the tool. Pools are used to limit the | 
|  | number of tasks that can execute concurrently during the build. | 
|  |  | 
|  | See also "gn help pool". | 
|  |  | 
|  | link_output  [string with substitutions] | 
|  | depend_output  [string with substitutions] | 
|  | Valid for: "solink" only (optional) | 
|  |  | 
|  | These two files specify which of the outputs from the solink tool | 
|  | should be used for linking and dependency tracking. These should match | 
|  | entries in the "outputs". If unspecified, the first item in the | 
|  | "outputs" array will be used for all. See "Separate linking and | 
|  | dependencies for shared libraries" below for more. | 
|  |  | 
|  | On Windows, where the tools produce a .dll shared library and a .lib | 
|  | import library, you will want the first two to be the import library | 
|  | and the third one to be the .dll file. On Linux, if you're not doing | 
|  | the separate linking/dependency optimization, all of these should be | 
|  | the .so output. | 
|  |  | 
|  | output_prefix  [string] | 
|  | Valid for: Linker tools (optional) | 
|  |  | 
|  | Prefix to use for the output name. Defaults to empty. This prefix will | 
|  | be prepended to the name of the target (or the output_name if one is | 
|  | manually specified for it) if the prefix is not already there. The | 
|  | result will show up in the {{output_name}} substitution pattern. | 
|  |  | 
|  | Individual targets can opt-out of the output prefix by setting: | 
|  | output_prefix_override = true | 
|  | (see "gn help output_prefix_override"). | 
|  |  | 
|  | This is typically used to prepend "lib" to libraries on | 
|  | Posix systems: | 
|  | output_prefix = "lib" | 
|  |  | 
|  | precompiled_header_type  [string] | 
|  | Valid for: "cc", "cxx", "objc", "objcxx" | 
|  |  | 
|  | Type of precompiled headers. If undefined or the empty string, | 
|  | precompiled headers will not be used for this tool. Otherwise use "gcc" | 
|  | or "msvc". | 
|  |  | 
|  | For precompiled headers to be used for a given target, the target (or a | 
|  | config applied to it) must also specify a "precompiled_header" and, for | 
|  | "msvc"-style headers, a "precompiled_source" value. If the type is | 
|  | "gcc", then both "precompiled_header" and "precompiled_source" must | 
|  | resolve to the same file, despite the different formats required for | 
|  | each." | 
|  |  | 
|  | See "gn help precompiled_header" for more. | 
|  |  | 
|  | restat  [boolean] | 
|  | Valid for: all tools (optional, defaults to false) | 
|  |  | 
|  | Requests that Ninja check the file timestamp after this tool has run to | 
|  | determine if anything changed. Set this if your tool has the ability to | 
|  | skip writing output if the output file has not changed. | 
|  |  | 
|  | Normally, Ninja will assume that when a tool runs the output be new and | 
|  | downstream dependents must be rebuild. When this is set to trye, Ninja | 
|  | can skip rebuilding downstream dependents for input changes that don't | 
|  | actually affect the output. | 
|  |  | 
|  | Example: | 
|  | restat = true | 
|  |  | 
|  | rspfile  [string with substitutions] | 
|  | Valid for: all tools except "action" (optional) | 
|  |  | 
|  | Name of the response file. If empty, no response file will be | 
|  | used. See "rspfile_content". | 
|  |  | 
|  | rspfile_content  [string with substitutions] | 
|  | Valid for: all tools except "action" (required when "rspfile" is used) | 
|  |  | 
|  | The contents to be written to the response file. This may include all | 
|  | or part of the command to send to the tool which allows you to get | 
|  | around OS command-line length limits. | 
|  |  | 
|  | This example adds the inputs and libraries to a response file, but | 
|  | passes the linker flags directly on the command line: | 
|  | tool("link") { | 
|  | command = "link -o {{output}} {{ldflags}} @{{output}}.rsp" | 
|  | rspfile = "{{output}}.rsp" | 
|  | rspfile_content = "{{inputs}} {{solibs}} {{libs}}" | 
|  | } | 
|  |  | 
|  | runtime_outputs  [string list with substitutions] | 
|  | Valid for: linker tools | 
|  |  | 
|  | If specified, this list is the subset of the outputs that should be | 
|  | added to runtime deps (see "gn help runtime_deps"). By default (if | 
|  | runtime_outputs is empty or unspecified), it will be the link_output. | 
|  |  | 
|  | )"  // String break to prevent overflowing the 16K max VC string length. | 
|  | R"(Expansions for tool variables | 
|  |  | 
|  | All paths are relative to the root build directory, which is the current | 
|  | directory for running all tools. These expansions are available to all tools: | 
|  |  | 
|  | {{label}} | 
|  | The label of the current target. This is typically used in the | 
|  | "description" field for link tools. The toolchain will be omitted from | 
|  | the label for targets in the default toolchain, and will be included | 
|  | for targets in other toolchains. | 
|  |  | 
|  | {{label_name}} | 
|  | The short name of the label of the target. This is the part after the | 
|  | colon. For "//foo/bar:baz" this will be "baz". Unlike | 
|  | {{target_output_name}}, this is not affected by the "output_prefix" in | 
|  | the tool or the "output_name" set on the target. | 
|  |  | 
|  | {{output}} | 
|  | The relative path and name of the output(s) of the current build step. | 
|  | If there is more than one output, this will expand to a list of all of | 
|  | them. Example: "out/base/my_file.o" | 
|  |  | 
|  | {{target_gen_dir}} | 
|  | {{target_out_dir}} | 
|  | The directory of the generated file and output directories, | 
|  | respectively, for the current target. There is no trailing slash. See | 
|  | also {{output_dir}} for linker tools. Example: "out/base/test" | 
|  |  | 
|  | {{target_output_name}} | 
|  | The short name of the current target with no path information, or the | 
|  | value of the "output_name" variable if one is specified in the target. | 
|  | This will include the "output_prefix" if any. See also {{label_name}}. | 
|  |  | 
|  | Example: "libfoo" for the target named "foo" and an output prefix for | 
|  | the linker tool of "lib". | 
|  |  | 
|  | Compiler tools have the notion of a single input and a single output, along | 
|  | with a set of compiler-specific flags. The following expansions are | 
|  | available: | 
|  |  | 
|  | {{asmflags}} | 
|  | {{cflags}} | 
|  | {{cflags_c}} | 
|  | {{cflags_cc}} | 
|  | {{cflags_objc}} | 
|  | {{cflags_objcc}} | 
|  | {{defines}} | 
|  | {{include_dirs}} | 
|  | Strings correspond that to the processed flags/defines/include | 
|  | directories specified for the target. | 
|  | Example: "--enable-foo --enable-bar" | 
|  |  | 
|  | Defines will be prefixed by "-D" and include directories will be | 
|  | prefixed by "-I" (these work with Posix tools as well as Microsoft | 
|  | ones). | 
|  |  | 
|  | {{source}} | 
|  | The relative path and name of the current input file. | 
|  | Example: "../../base/my_file.cc" | 
|  |  | 
|  | {{source_file_part}} | 
|  | The file part of the source including the extension (with no directory | 
|  | information). | 
|  | Example: "foo.cc" | 
|  |  | 
|  | {{source_name_part}} | 
|  | The filename part of the source file with no directory or extension. | 
|  | Example: "foo" | 
|  |  | 
|  | {{source_gen_dir}} | 
|  | {{source_out_dir}} | 
|  | The directory in the generated file and output directories, | 
|  | respectively, for the current input file. If the source file is in the | 
|  | same directory as the target is declared in, they will will be the same | 
|  | as the "target" versions above. Example: "gen/base/test" | 
|  |  | 
|  | Linker tools have multiple inputs and (potentially) multiple outputs. The | 
|  | static library tool ("alink") is not considered a linker tool. The following | 
|  | expansions are available: | 
|  |  | 
|  | {{inputs}} | 
|  | {{inputs_newline}} | 
|  | Expands to the inputs to the link step. This will be a list of object | 
|  | files and static libraries. | 
|  | Example: "obj/foo.o obj/bar.o obj/somelibrary.a" | 
|  |  | 
|  | The "_newline" version will separate the input files with newlines | 
|  | instead of spaces. This is useful in response files: some linkers can | 
|  | take a "-filelist" flag which expects newline separated files, and some | 
|  | Microsoft tools have a fixed-sized buffer for parsing each line of a | 
|  | response file. | 
|  |  | 
|  | {{ldflags}} | 
|  | Expands to the processed set of ldflags and library search paths | 
|  | specified for the target. | 
|  | Example: "-m64 -fPIC -pthread -L/usr/local/mylib" | 
|  |  | 
|  | {{libs}} | 
|  | Expands to the list of system libraries to link to. Each will be | 
|  | prefixed by the "lib_switch". | 
|  |  | 
|  | As a special case to support Mac, libraries with names ending in | 
|  | ".framework" will be added to the {{libs}} with "-framework" preceding | 
|  | it, and the lib prefix will be ignored. | 
|  |  | 
|  | Example: "-lfoo -lbar" | 
|  |  | 
|  | {{output_dir}} | 
|  | The value of the "output_dir" variable in the target, or the the value | 
|  | of the "default_output_dir" value in the tool if the target does not | 
|  | override the output directory. This will be relative to the | 
|  | root_build_dir and will not end in a slash. Will be "." for output to | 
|  | the root_build_dir. | 
|  |  | 
|  | This is subtly different than {{target_out_dir}} which is defined by GN | 
|  | based on the target's path and not overridable. {{output_dir}} is for | 
|  | the final output, {{target_out_dir}} is generally for object files and | 
|  | other outputs. | 
|  |  | 
|  | Usually {{output_dir}} would be defined in terms of either | 
|  | {{target_out_dir}} or {{root_out_dir}} | 
|  |  | 
|  | {{output_extension}} | 
|  | The value of the "output_extension" variable in the target, or the | 
|  | value of the "default_output_extension" value in the tool if the target | 
|  | does not specify an output extension. | 
|  | Example: ".so" | 
|  |  | 
|  | {{solibs}} | 
|  | Extra libraries from shared library dependencies not specified in the | 
|  | {{inputs}}. This is the list of link_output files from shared libraries | 
|  | (if the solink tool specifies a "link_output" variable separate from | 
|  | the "depend_output"). | 
|  |  | 
|  | These should generally be treated the same as libs by your tool. | 
|  |  | 
|  | Example: "libfoo.so libbar.so" | 
|  |  | 
|  | )"  // String break to prevent overflowing the 16K max VC string length. | 
|  | R"(  The static library ("alink") tool allows {{arflags}} plus the common tool | 
|  | substitutions. | 
|  |  | 
|  | The copy tool allows the common compiler/linker substitutions, plus | 
|  | {{source}} which is the source of the copy. The stamp tool allows only the | 
|  | common tool substitutions. | 
|  |  | 
|  | The copy_bundle_data and compile_xcassets tools only allows the common tool | 
|  | substitutions. Both tools are required to create iOS/macOS bundles and need | 
|  | only be defined on those platforms. | 
|  |  | 
|  | The copy_bundle_data tool will be called with one source and needs to copy | 
|  | (optionally optimizing the data representation) to its output. It may be | 
|  | called with a directory as input and it needs to be recursively copied. | 
|  |  | 
|  | The compile_xcassets tool will be called with one or more source (each an | 
|  | asset catalog) that needs to be compiled to a single output. The following | 
|  | substitutions are available: | 
|  |  | 
|  | {{inputs}} | 
|  | Expands to the list of .xcassets to use as input to compile the asset | 
|  | catalog. | 
|  |  | 
|  | {{bundle_product_type}} | 
|  | Expands to the product_type of the bundle that will contain the | 
|  | compiled asset catalog. Usually corresponds to the product_type | 
|  | property of the corresponding create_bundle target. | 
|  |  | 
|  | {{bundle_partial_info_plist}} | 
|  | Expands to the path to the partial Info.plist generated by the | 
|  | assets catalog compiler. Usually based on the target_name of | 
|  | the create_bundle target. | 
|  |  | 
|  | Rust tools have the notion of a single input and a single output, along | 
|  | with a set of compiler-specific flags. The following expansions are | 
|  | available: | 
|  |  | 
|  | {{crate_name}} | 
|  | Expands to the string representing the crate name of target under | 
|  | compilation. | 
|  |  | 
|  | {{crate_type}} | 
|  | Expands to the string representing the type of crate for the target | 
|  | under compilation. | 
|  |  | 
|  | {{externs}} | 
|  | Expands to the list of --extern flags needed to include addition Rust | 
|  | libraries in this target. Includes any specified renamed dependencies. | 
|  |  | 
|  | {{rustc_output_extension}} | 
|  | Expands to the output extension for this target's crate type. | 
|  |  | 
|  | {{rustc_output_prefix}} | 
|  | Expands to the prefix for shared and static libraries. This should | 
|  | generally be "lib". Empty for executable targets. | 
|  |  | 
|  | {{rustdeps}} | 
|  | Expands to the list of -Ldependency=<path> strings needed to compile | 
|  | this target. | 
|  |  | 
|  | {{rustenv}} | 
|  | Expands to the list of environment variables. | 
|  |  | 
|  | {{rustflags}} | 
|  | Expands to the list of strings representing Rust compiler flags. | 
|  |  | 
|  | Separate linking and dependencies for shared libraries | 
|  |  | 
|  | Shared libraries are special in that not all changes to them require that | 
|  | dependent targets be re-linked. If the shared library is changed but no | 
|  | imports or exports are different, dependent code needn't be relinked, which | 
|  | can speed up the build. | 
|  |  | 
|  | If your link step can output a list of exports from a shared library and | 
|  | writes the file only if the new one is different, the timestamp of this file | 
|  | can be used for triggering re-links, while the actual shared library would be | 
|  | used for linking. | 
|  |  | 
|  | You will need to specify | 
|  | restat = true | 
|  | in the linker tool to make this work, so Ninja will detect if the timestamp | 
|  | of the dependency file has changed after linking (otherwise it will always | 
|  | assume that running a command updates the output): | 
|  |  | 
|  | tool("solink") { | 
|  | command = "..." | 
|  | outputs = [ | 
|  | "{{output_dir}}/{{target_output_name}}{{output_extension}}", | 
|  | "{{output_dir}}/{{target_output_name}}" | 
|  | "{{output_extension}}.TOC", | 
|  | ] | 
|  | link_output = | 
|  | "{{output_dir}}/{{target_output_name}}{{output_extension}}" | 
|  | depend_output = | 
|  | "{{output_dir}}/{{target_output_name}}" | 
|  | "{{output_extension}}.TOC" | 
|  | restat = true | 
|  | } | 
|  |  | 
|  | Example | 
|  |  | 
|  | toolchain("my_toolchain") { | 
|  | # Put these at the top to apply to all tools below. | 
|  | lib_switch = "-l" | 
|  | lib_dir_switch = "-L" | 
|  |  | 
|  | tool("cc") { | 
|  | command = "gcc {{source}} -o {{output}}" | 
|  | outputs = [ "{{source_out_dir}}/{{source_name_part}}.o" ] | 
|  | description = "GCC {{source}}" | 
|  | } | 
|  | tool("cxx") { | 
|  | command = "g++ {{source}} -o {{output}}" | 
|  | outputs = [ "{{source_out_dir}}/{{source_name_part}}.o" ] | 
|  | description = "G++ {{source}}" | 
|  | } | 
|  | }; | 
|  | )"; | 
|  |  | 
|  | Value RunTool(Scope* scope, | 
|  | const FunctionCallNode* function, | 
|  | const std::vector<Value>& args, | 
|  | BlockNode* block, | 
|  | Err* err) { | 
|  | // Find the toolchain definition we're executing inside of. The toolchain | 
|  | // function will set a property pointing to it that we'll pick up. | 
|  | Toolchain* toolchain = reinterpret_cast<Toolchain*>( | 
|  | scope->GetProperty(&kToolchainPropertyKey, nullptr)); | 
|  | if (!toolchain) { | 
|  | *err = Err(function->function(), "tool() called outside of toolchain().", | 
|  | "The tool() function can only be used inside a toolchain() " | 
|  | "definition."); | 
|  | return Value(); | 
|  | } | 
|  |  | 
|  | if (!EnsureSingleStringArg(function, args, err)) | 
|  | return Value(); | 
|  | const std::string& tool_name = args[0].string_value(); | 
|  |  | 
|  | // Run the tool block. | 
|  | Scope block_scope(scope); | 
|  | block->Execute(&block_scope, err); | 
|  | if (err->has_error()) | 
|  | return Value(); | 
|  |  | 
|  | std::unique_ptr<Tool> tool = | 
|  | Tool::CreateTool(function, tool_name, &block_scope, toolchain, err); | 
|  |  | 
|  | if (!tool) { | 
|  | return Value(); | 
|  | } | 
|  |  | 
|  | tool->set_defined_from(function); | 
|  | toolchain->SetTool(std::move(tool)); | 
|  |  | 
|  | // Make sure there weren't any vars set in this tool that were unused. | 
|  | if (!block_scope.CheckForUnusedVars(err)) | 
|  | return Value(); | 
|  |  | 
|  | return Value(); | 
|  | } | 
|  |  | 
|  | }  // namespace functions |