- Separate cross-compilation logic to crosscompile.vsh - Manage Docker in make.vsh, no more manual running `docker build`, etc. - Add MANUAL.md instruction - Enchance Dockerfile
3.5 KiB
Manual cross-compilation
This repository contains ready-made scripts that allow you to describe the
desired results and obtain them simply by running ./make.vsh. However, to
better understand the process, it's worth considering the manual build.
This file describes the algorithm of actions automated in the aforementioned
scripts.
Prepare the environment
We want reproducible builds. We also don't want to clutter our computer with things needed exclusively for cross-compilation. Besides manipulating certain packages in the OS can inadvertently damage the system.
Docker will help us achieve all our goals. Install it if you haven't already. Containers will ensure reproducible builds, as they will always run in the same environment.
Let's begin
Create a V programm. Just initialize empty V project in some dir:
$ mkdir crossv
$ cd crossv
$ v init
Input your project description: Cross-compilation example
Input your project version: (0.0.0)
Input your project license: (MIT)
Initialising ...
Created binary (application) project `crossv`
Contents of main.v:
module main
fn main() {
println('Hello World!')
}
There is already an example Dockerfile in this repository, so here I will focus on CLI. So let's run Debian Linux in container with current directory mounted:
docker run --rm -ti -v .:/app -w /app debian:trixie
See https://docs.docker.com/reference/cli/docker/container/run/ for details.
Now we will run shell commands inside container.
Setup V compiler in container
Install prerequisistes:
apt update
apt install -y --no-install-recommends --no-install-suggests build-essential git ca-certificates file
Download and bootstrap V compiler:
export VMODULES=/tmp/vmodules VCACHE=/tmp/vcache
git clone --depth=1 https://github.com/vlang/v /opt/v && make -C /opt/v && /opt/v/v symlink
After this v command should work. Try:
v version
Cross-compile to ARM64 (AArch64)
Your host is most likely an x86_64 computer. For the sake of example, let's compile our Linux program for the AArch64 architecture.
First we need to add build requirements. Debian already have an excellent cross-compiling support.
Prepate Debian package manager:
dpkg --add-architecture arm64
apt update
We need to install crossbuild-essential-arm64 package:
apt install -y --no-install-recommends --no-install-suggests crossbuild-essential-arm64
Also there is packages for some other architectures which Debian supports: https://packages.debian.org/search?keywords=crossbuild-essential&searchon=names&suite=stable§ion=all
Now we have a GCC cross-compiler and some common libraries for ARM64.
To compile out project just run:
v -prod -cc aarch64-linux-gnu-gcc -o hello .
Let's make sure we've built the correct executable using the file utility:
# file hello
hello: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=e9cfdee9abe5a80c304d489f243fbc60a22d93de, for GNU/Linux 3.7.0, not stripped
Binary is dynamically linked. To produce statically linked binary add -cflags -static flag:
v -prod -cc aarch64-linux-gnu-gcc -cflags -static -o hello .
Done.
Since we were operating as the root user inside the container, it's worth changing the file owner:
chown 1000:1000 hello
Replace 1000:1000 with your actual UID:GID pair on host system.
Now we can exit from container:
exit