| # How GN handles cross-compiling |
| |
| ## As a GN user |
| |
| GN has robust support for doing cross compiles and building things for |
| multiple architectures in a single build (e.g., to build some things to |
| run locally and some things to run on an embedded device). In fact, |
| there is no limit on the number of different architectures you can build |
| at once; the Chromium build uses at least four in some configurations. |
| |
| To start, GN has the concepts of a _host_ and a _target_. The host is |
| the platform that the build is run on, and the target is the platform |
| where the code will actually run (This is different from |
| [autotools](http://www.gnu.org/software/automake/manual/html_node/Cross_002dCompilation.html)' |
| terminology, but uses the more common terminology for cross |
| compiling). |
| |
| (Confusingly, GN also refers to each build artifact -- an executable, |
| library, etc. -- as a target. On this page, we will use "target" only to |
| refer to the system you want to run your code on, and use "rule" or some |
| other synonym to refer to a specific build artifact). |
| |
| When GN starts up, the `host_os` and `host_cpu` variables are set |
| automatically to match the operating system (they can be overridden in |
| args files, which can be useful in weird corner cases). The user can |
| specify that they want to do a cross-compile by setting either or both |
| of `target_os` and `target_cpu`; if they are not set, the build config |
| files will usually set them to the host's values, though the Chromium |
| build will set target\_cpu to "arm" if target\_os is set to "android"). |
| |
| So, for example, running on an x64 Linux machine: |
| |
| ``` |
| gn gen out/Default |
| ``` |
| |
| is equivalent to: |
| |
| ``` |
| gn gen out/Default --args='target_os="linux" target_cpu="x64"' |
| ``` |
| |
| To do an 32-bit ARM Android cross-compile, do: |
| |
| ``` |
| gn gen out/Default --args='target_os="android"' |
| ``` |
| |
| (We don't have to specify target\_cpu because of the conditionals |
| mentioned above). |
| |
| And, to do a 64-bit MIPS Chrome OS cross-compile: |
| |
| ``` |
| gn gen out/Default --args='target_os="chromeos" target_cpu="mips64el"' |
| ``` |
| |
| ## As a BUILD.gn author |
| |
| If you are editing build files outside of the //build directory (i.e., |
| not directly working on toolchains, compiler configs, etc.), generally |
| you only need to worry about a few things: |
| |
| The `current_toolchain`, `current_cpu`, and `current_os` variables |
| reflect the settings that are **currently** in effect in a given rule. |
| The `is_linux`, `is_win` etc. variables are updated to reflect the |
| current settings, and changes to `cflags`, `ldflags` and so forth also |
| only apply to the current toolchain and the current thing being built. |
| |
| You can also refer to the `target_cpu` and `target_os` variables. This |
| is useful if you need to do something different on the host depending on |
| which target\_arch is requested; the values are constant across all |
| toolchains. You can do similar things for the `host_cpu` and `host_os` |
| variables, but should generally never need to. |
| |
| For the default toolchain, `target_cpu` and `current_cpu` are the same. For a |
| secondary toolchain, `current_cpu` is set based on the toolchain definition |
| and `target_cpu` remains the same. When writing rules, **`current_cpu` should |
| be used rather than `target_cpu` most of the time**. |
| |
| By default, dependencies listed in the `deps` variable of a rule use the |
| same (currently active) toolchain. You may specify a different toolchain |
| using the `foo(bar)` label notation as described in [the label section |
| of the reference doc](reference.md#Toolchains). |
| |
| Here's an example of when to use `target_cpu` vs `current_cpu`: |
| |
| ``` |
| declare_args() { |
| # Applies only to toolchains targeting target_cpu. |
| sysroot = "" |
| } |
| |
| config("my_config") { |
| # Uses current_cpu because compile flags are toolchain-dependent. |
| if (current_cpu == "arm") { |
| defines = [ "CPU_IS_32_BIT" ] |
| } else { |
| defines = [ "CPU_IS_64_BIT" ] |
| } |
| # Compares current_cpu with target_cpu to see whether current_toolchain |
| # has the same architecture as target_toolchain. |
| if (sysroot != "" && current_cpu == target_cpu) { |
| cflags = [ |
| "-isysroot", |
| sysroot, |
| ] |
| } |
| } |
| ``` |
| |
| ## As a //build/config or //build/toolchain author |
| |
| The `default_toolchain` is declared in the `BUILDCONFIG.gn` file (in Google |
| projects this normally is in the `//build/config` directory). Usually the |
| `default_toolchain` should be the toolchain for the `target_os` and |
| `target_cpu`. The `current_toolchain` reflects the toolchain that is currently |
| in effect for a rule. |
| |
| Be sure you understand the differences between `host_cpu`, `target_cpu`, |
| `current_cpu`, and `toolchain_cpu` (and the os equivalents). The first |
| two are set as described above. You are responsible for making sure that |
| `current_cpu` is set appropriately in your toolchain definitions; if you |
| are using the stock templates like `gcc_toolchain` and `msvc_toolchain`, |
| that means you are responsible for making sure that `toolchain_cpu` and |
| `toolchain_os` are set as appropriate in the template invocations. |