Cross compiling
Build an executable for another operating system or CPU from the machine you have.
On this page
A build normally produces an executable for the machine it runs on. With --target, the same source builds an executable for another operating system or CPU, without installing a toolchain for it: the linker and the libraries each platform needs ship with Valk.
Choose a target#
Name the platform the executable is for:
valk build src -o app --target win-x64
| Target | Platform |
|---|---|
linux-x64 |
Linux on x86-64 |
linux-arm64 |
Linux on 64-bit ARM, such as a Raspberry Pi or an AWS Graviton server |
macos-x64 |
macOS on Intel |
macos-arm64 |
macOS on Apple silicon |
win-x64 |
Windows on x86-64 |
A Windows target adds .exe to the output name, so the command above writes app.exe. The executable cannot run on the build machine; copy it to a machine of that platform, or build in a CI job for each platform you ship.
Check code for every platform#
A lint compiles without linking, so it works for any target without extra setup:
valk build src --lint --target macos-arm64
Run it for each target your project supports to catch code that only compiles on one platform.
Write platform-specific code#
OS and ARCH are set for the target being built, not for the build machine. OS is linux, macos or win; ARCH is x64 or arm64.
fn config_dir() String {
#if OS == "win"
return "C:/ProgramData/app"
#elif OS == "macos"
return "/Library/Application Support/app"
#else
return "/etc/app"
#end
}
fn main() {
println(config_dir())
}
Code in a branch that is not selected is never compiled, so it may call functions that exist on one platform only.
Add OpenSSL for the target#
A Valk release ships OpenSSL for its own platform only. valk.net, valk.http and valk.crypto link it, and so does every package built on them, such as a database driver or an HTTP client. Cross compiling such a program stops with a message that names the package to add:
vman install github.com/valk-lang/openssl-win-x64 --libs
There is one package per target: openssl-linux-x64, openssl-linux-arm64, openssl-macos-x64, openssl-macos-arm64 and openssl-win-x64. Each holds only the libraries. --libs records that the project allows linking libraries from this dependency; without that flag the build refuses, because the libraries are code you never read. The entry in valk.json looks like this:
{
"dependencies": {
"openssl_win_x64": {
"src": "github.com/valk-lang/openssl-win-x64",
"version": "3.5.x",
"libs": true
}
}
}
A program that does not use these namespaces needs nothing extra for any target.
Link your own C libraries#
A C library named with -l or a link declaration must be built for the target. Put it in libs/<target>/ next to valk.json, for example libs/win-x64/foo.lib, or pass its directory with -L. A build for the machine itself also searches the system's library directories; a cross build does not.
--static links the C runtime and the libraries into the executable, so a Linux build runs on machines that lack them. Valk's own releases are built this way.
