dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 1 | # How GN handles cross-compiling |
| 2 | |
| 3 | ## As a GN user |
| 4 | |
| 5 | GN has robust support for doing cross compiles and building things for |
| 6 | multiple architectures in a single build (e.g., to build some things to |
| 7 | run locally and some things to run on an embedded device). In fact, |
| 8 | there is no limit on the number of different architectures you can build |
| 9 | at once; the Chromium build uses at least four in some configurations. |
| 10 | |
| 11 | To start, GN has the concepts of a _host_ and a _target_. The host is |
| 12 | the platform that the build is run on, and the target is the platform |
| 13 | where the code will actually run (This is different from |
| 14 | [autotools](http://www.gnu.org/software/automake/manual/html_node/Cross_002dCompilation.html)' |
| 15 | terminology, but uses the more common terminology for cross |
Joe Armstrong | 9edc6c0 | 2019-06-28 10:12:54 +0800 | [diff] [blame] | 16 | compiling). |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 17 | |
| 18 | (Confusingly, GN also refers to each build artifact -- an executable, |
| 19 | library, etc. -- as a target. On this page, we will use "target" only to |
| 20 | refer to the system you want to run your code on, and use "rule" or some |
| 21 | other synonym to refer to a specific build artifact). |
| 22 | |
| 23 | When GN starts up, the `host_os` and `host_cpu` variables are set |
| 24 | automatically to match the operating system (they can be overridden in |
| 25 | args files, which can be useful in weird corner cases). The user can |
| 26 | specify that they want to do a cross-compile by setting either or both |
| 27 | of `target_os` and `target_cpu`; if they are not set, the build config |
| 28 | files will usually set them to the host's values, though the Chromium |
| 29 | build will set target\_cpu to "arm" if target\_os is set to "android"). |
| 30 | |
| 31 | So, for example, running on an x64 Linux machine: |
| 32 | |
| 33 | ``` |
| 34 | gn gen out/Default |
| 35 | ``` |
| 36 | |
| 37 | is equivalent to: |
| 38 | |
| 39 | ``` |
| 40 | gn gen out/Default --args='target_os="linux" target_cpu="x64"' |
| 41 | ``` |
| 42 | |
| 43 | To do an 32-bit ARM Android cross-compile, do: |
| 44 | |
| 45 | ``` |
| 46 | gn gen out/Default --args='target_os="android"' |
| 47 | ``` |
| 48 | |
| 49 | (We don't have to specify target\_cpu because of the conditionals |
| 50 | mentioned above). |
| 51 | |
derat | 0cfcb21 | 2017-02-22 09:57:55 -0800 | [diff] [blame] | 52 | And, to do a 64-bit MIPS Chrome OS cross-compile: |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 53 | |
| 54 | ``` |
| 55 | gn gen out/Default --args='target_os="chromeos" target_cpu="mips64el"' |
| 56 | ``` |
| 57 | |
| 58 | ## As a BUILD.gn author |
| 59 | |
| 60 | If you are editing build files outside of the //build directory (i.e., |
| 61 | not directly working on toolchains, compiler configs, etc.), generally |
| 62 | you only need to worry about a few things: |
| 63 | |
| 64 | The `current_toolchain`, `current_cpu`, and `current_os` variables |
| 65 | reflect the settings that are **currently** in effect in a given rule. |
| 66 | The `is_linux`, `is_win` etc. variables are updated to reflect the |
| 67 | current settings, and changes to `cflags`, `ldflags` and so forth also |
| 68 | only apply to the current toolchain and the current thing being built. |
| 69 | |
| 70 | You can also refer to the `target_cpu` and `target_os` variables. This |
| 71 | is useful if you need to do something different on the host depending on |
| 72 | which target\_arch is requested; the values are constant across all |
| 73 | toolchains. You can do similar things for the `host_cpu` and `host_os` |
| 74 | variables, but should generally never need to. |
| 75 | |
agrieve | dea44a3 | 2016-06-08 13:30:15 -0700 | [diff] [blame] | 76 | For the default toolchain, `target_cpu` and `current_cpu` are the same. For a |
| 77 | secondary toolchain, `current_cpu` is set based on the toolchain definition |
| 78 | and `target_cpu` remains the same. When writing rules, **`current_cpu` should |
| 79 | be used rather than `target_cpu` most of the time**. |
| 80 | |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 81 | By default, dependencies listed in the `deps` variable of a rule use the |
| 82 | same (currently active) toolchain. You may specify a different toolchain |
Quinten Yearsley | 030b729 | 2017-07-18 16:13:31 +0000 | [diff] [blame] | 83 | using the `foo(bar)` label notation as described in [the label section |
| 84 | of the reference doc](reference.md#Toolchains). |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 85 | |
agrieve | dea44a3 | 2016-06-08 13:30:15 -0700 | [diff] [blame] | 86 | Here's an example of when to use `target_cpu` vs `current_cpu`: |
| 87 | |
| 88 | ``` |
| 89 | declare_args() { |
| 90 | # Applies only to toolchains targeting target_cpu. |
| 91 | sysroot = "" |
| 92 | } |
| 93 | |
| 94 | config("my_config") { |
| 95 | # Uses current_cpu because compile flags are toolchain-dependent. |
| 96 | if (current_cpu == "arm") { |
| 97 | defines = [ "CPU_IS_32_BIT" ] |
| 98 | } else { |
| 99 | defines = [ "CPU_IS_64_BIT" ] |
| 100 | } |
| 101 | # Compares current_cpu with target_cpu to see whether current_toolchain |
| 102 | # has the same architecture as target_toolchain. |
| 103 | if (sysroot != "" && current_cpu == target_cpu) { |
| 104 | cflags = [ |
| 105 | "-isysroot", |
| 106 | sysroot, |
| 107 | ] |
| 108 | } |
| 109 | } |
| 110 | ``` |
| 111 | |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 112 | ## As a //build/config or //build/toolchain author |
| 113 | |
Brett Wilson | 2a18133 | 2020-03-20 13:38:18 -0700 | [diff] [blame] | 114 | The `default_toolchain` is declared in the `BUILDCONFIG.gn` file (in Google |
| 115 | projects this normally is in the `//build/config` directory). Usually the |
| 116 | `default_toolchain` should be the toolchain for the `target_os` and |
| 117 | `target_cpu`. The `current_toolchain` reflects the toolchain that is currently |
| 118 | in effect for a rule. |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 119 | |
| 120 | Be sure you understand the differences between `host_cpu`, `target_cpu`, |
| 121 | `current_cpu`, and `toolchain_cpu` (and the os equivalents). The first |
| 122 | two are set as described above. You are responsible for making sure that |
| 123 | `current_cpu` is set appropriately in your toolchain definitions; if you |
| 124 | are using the stock templates like `gcc_toolchain` and `msvc_toolchain`, |
| 125 | that means you are responsible for making sure that `toolchain_cpu` and |
| 126 | `toolchain_os` are set as appropriate in the template invocations. |