> For the complete documentation index, see [llms.txt](https://kmanu225.gitbook.io/cs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kmanu225.gitbook.io/cs/software-engineering/cross-compilation.md).

# Cross-Compilation

How I Survived an Ultra-Minimalist ARM Environment

Some days, you realize just how much you take a simple `curl` command for granted. Recently, during a professional assignment, I faced a "hardened" ARM/GNU Linux target. The setup? A system stripped to its bare essentials: no package manager, no compiler, and, most importantly, no `curl`.

My challenge: initiate HTTPS requests on a machine with virtually no network tools. This is the story of my deep dive into the world of cross-compilation.

### The Context: From WSL to ARM

My workstation was a WSL2 environment (**x86\_64**). My target? An **armv7l** processor. Compiling directly on the target was impossible, and waiting for the systems team to provide tools or info would have taken weeks. It was just me and my terminal.

### The "All-in-One" Strategy (Static Binary)

Since I had little visibility into which libraries were available on the target, I made a radical choice: **static linking**. Instead of relying on shared libraries (`.so`) on the destination, I decided to bake all dependencies directly into the `curl` executable.

### Choosing Lightness: Musl

The standard `glibc` is often too bloated or complex for pure static linking. That’s where **musl libc** comes in. It is a lightweight alternative optimized for static binaries. It was the missing piece of the puzzle to ensure my binary would run flawlessly on a minimalist kernel.

### The Crash Test: qemu-arm-static

Compiling is great, but testing without constant back-and-forth with the target is better. Thanks to `qemu-arm-static`, I was able to emulate and run my ARM binary directly within my WSL terminal.

I regretted missing this step during my first attempts. In fact, I could not access the target whenever I wanted. Once I saw the `curl` help menu pop up on my x86 host, I knew I had won.

### The Recipe

The final configuration can be found on my GitHub: [compliation-recipe/x86\_64-to-arm/curl at main · kmanu225/compliation-recipe](https://github.com/kmanu225/compliation-recipe/tree/main/x86_64-to-arm/curl).

If I had to keep one thing in mind when dealing with cross-compilation, it is that you need to properly characterize the target before taking any action.

### Glossary

For those looking to demystify the technical jargon used above:

* **Architecture (ARM vs x86):** The processor's physical "language." A program compiled for a PC (x86) is unreadable by a mobile or embedded processor (ARM).
* **libc:** The fundamental C library. It acts as the bridge between your code and the Linux kernel (e.g., opening a file).
* [**musl libc**](https://musl.libc.org/)**:** A lightweight, fast, and simple implementation of the C standard library.
* **Cross-compilation:** The process of compiling a program on Architecture A to run on Architecture B.
* **Static vs. Dynamic Linking:**
  * **Dynamic:** The program calls external files at runtime.
  * **Static:** The program bundles everything into a single file. More robust but larger (my `curl` binary went from a few KB to several MB).
* **eabihf (Embedded Application Binary Interface Hard Float):** A calling convention indicating the processor uses its hardware unit for floating-point math (faster).
* **CMake vs Make:** `Make` executes build scripts. `CMake` is a higher-level tool that generates those scripts for you.
