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