Cross-compiling
From v12.2 onwards, Please has cross-compilation support. This allows you to instruct it to build outputs for other architectures alongside the host architecture.
To target a different architecture, use the
--arch
flag when invoking plz. Architectures are
formed of a two-part tags in a similar format to Go's - i.e.
linux_amd64
etc. These are passed in as a single
flag but decomposed into separate OS and architecture parts for later
operations. You can request whatever architecture you want, but obviously the
build will not succeed unless you have tools that understand that
architecture.
The outputs from a cross-compiled build will be in a directory under plz-out
prefixed with the architecture - e.g.
plz-out/bin/linux_x86
,
plz-out/gen/darwin_amd64
etc.
Technical notes
Cross compilation is primarily achieved through global variables in the BUILD language. Build rules adjust their commands as necessary based on these values. When compiling a target for a different architecture, the BUILD file is re-parsed generating specialised rules for that architecture.
The CONFIG.ARCH
and
CONFIG.OS
properties will be set to the target
architecture. Similarly, when the rule builds, the
OS
and ARCH
environment
variables will also be set. The CONFIG.HOSTOS
and
CONFIG.HOSTARCH
contain the host machines
operating system and CPU architecture.
The distinction between tools
and other
dependencies of a target (e.g. src
or
deps
) is extremely important when
cross-compiling. Dependencies of a rule typically behave as you'd hope. All
dependencies except tools
will use the target architecture unless explicitly told not to via a
platform specific label e.g.
///linux_amd64//some/target
.
Tools, on the other hand, always use the host architecture since they are
executed on the host during the build. In some cases tools might need to
know the architecture they're targeting. To facilitate this, the target
architecture is set in CONFIG.TARGET_OS
and
CONFIG.TARGET_ARCH
.
The config file for any target
architecture is read (if present) and applied for targets compiling for that
architecture - e.g. .plzconfig_linux_x86
.
Typically you will need to create this file and modify the appropriate
settings i.e. compiler flags.
Language status
The various builtin languages have differing levels of support. Currently they are as follows:
C & C++
Works for most cases; there is an example in the Please repo which tests a simple amd64 -> x86 compilation.
You will need to alter the config file to make this work - see the example for x86 for some examples of the settings to change. So far this has not been tested in anger on a more complex setup.
Go
Works well across all platforms supported by Go. When using go_toolchain() to manage your go installation, cross compilation works out of the box.
Otherwise you must ensure the standard library is available for the target
architecture on the host machine via
GOOS="linux" GOARCH="386" go install -i std
.
Python
Currently has very limited support. Of course it will work for pure Python, however, binary modules built locally need a similar approach to C.
Binary third-party modules downloaded via pip_library won't work since pip can't be instructed to use a different architecture. python_wheel works fine but requires something else to have built & hosted the .whl file.
Java
This is not terribly relevant to Java since it effectively always targets
the same JVM architecture.
maven_jar
rules that specify native = True
will download
for the target architecture.
While not exactly related to this cross-compilation mechanism, there are also config options controlling the target, source and release level for Java.