# How the OpenLogi Nix Flake Package Expression Builds for x86_64-linux and aarch64-linux

> Discover how OpenLogi's Nix Flake uses forAllSystems to build identical package sets for x86_64-linux and aarch64-linux from a single flake.nix definition.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: internals
- Published: 2026-08-23

---

**OpenLogi's Nix Flake uses a `forAllSystems` helper to generate identical package sets for both x86_64-linux and aarch64-linux targets from a single source definition in `flake.nix`.**

The AprilNEA/OpenLogi repository provides a fully reproducible build environment through its Nix Flake package expression, enabling seamless compilation for both Intel/AMD and ARM64 Linux architectures. Understanding how this multi-platform build system works is essential for developers packaging the application for heterogeneous server environments or ARM-based development machines. The configuration relies on functional Nix patterns to eliminate duplication while ensuring architecture-specific toolchains are selected correctly.

## Declaring Target Architectures in `flake.nix`

The build configuration begins with the **`systems`** attribute defined in the root `flake.nix`. This list explicitly declares exactly two supported platforms:

- `x86_64-linux`
- `aarch64-linux`

According to the source code at lines 23-25, this restricted set ensures the flake only evaluates configurations for platforms the project actively tests and supports. Rather than duplicating build logic for each architecture, the expression uses a **`forAllSystems`** helper function (line 27) that maps arbitrary values across every system in the list. This functional approach eliminates redundancy while guaranteeing architecture-specific toolchains are selected correctly.

## Package Expression Architecture

Inside the **`packages`** output (line 81), the `forAllSystems` function expands the OpenLogi build definition across both targets. For each system in the list, the expression evaluates:

```nix
pkgs.legacyPackages.${system}

```

This selects the appropriate **nixpkgs** toolchain—including the Rust compiler and system libraries—targeting either the standard x86_64 Linux host or the ARM64 Linux variant (commonly used on Raspberry Pi or Apple Silicon devices). The concrete package definition resides in `packaging/linux/package.nix`, which the flake imports and instantiates separately for each architecture with the correct `system` parameter.

## Building for x86_64-linux and aarch64-linux

When you invoke Nix commands against the flake, the `--system` flag or your current host platform selects the matching entry in the `packages` output. The build process compiles the Rust workspace twice—once with the x86_64 toolchain and once with the aarch64 toolchain—producing independent, reproducible artifacts in separate `result/` directories.

To build explicitly for one architecture:

```bash

# Build the x86_64-linux binary

nix build .#packages.x86_64-linux.openlogi

# Build the aarch64-linux binary

nix build .#packages.aarch64-linux.openlogi

```

To build both targets simultaneously (useful for CI pipelines):

```bash
nix build .#packages.x86_64-linux.openlogi .#packages.aarch64-linux.openlogi

```

## Development Shell and Verification

The flake provides additional outputs using the same `forAllSystems` pattern. The **`checks`** attribute (lines 92-97) defines automated test suites for both architectures, while the **`formatter`** enables consistent code formatting via `nixfmt`. Developers can enter the project's development environment with all dependencies pre-configured:

```bash

# Enter dev shell with Rust toolchain and build dependencies

nix develop

# Run CI-style checks for all declared systems

nix flake check --all-systems --no-build

```

## Summary

- The OpenLogi Nix Flake declares `x86_64-linux` and `aarch64-linux` support explicitly in the **`systems`** list within `flake.nix` (lines 23-25).
- The **`forAllSystems`** helper function eliminates duplication by mapping build logic across both architectures (line 27).
- The **`packages`** output instantiates `packaging/linux/package.nix` separately for each system using `pkgs.legacyPackages.${system}` (line 81).
- **Checks** and **formatters** reuse the same multi-architecture pattern defined in lines 92-97.
- Build commands like `nix build .#packages.x86_64-linux.openlogi` select the appropriate toolchain automatically based on the specified target.

## Frequently Asked Questions

### How do I build OpenLogi for ARM64 Linux if I'm running on x86_64?

Nix supports cross-compilation through its `nix build` command with explicit package paths. Even on an x86_64 host, you can generate the aarch64-linux binary by running `nix build .#packages.aarch64-linux.openlogi`, provided you have the appropriate remote builders or QEMU emulation configured, or you can let Nix handle the system selection automatically if building natively on ARM64 hardware.

### Why does the flake only support Linux and not macOS?

The **`systems`** attribute in `flake.nix` (lines 23-25) intentionally restricts builds to `x86_64-linux` and `aarch64-linux`. The Linux-specific packaging logic in `packaging/linux/package.nix` and the project's target deployment environment dictated this restriction, though the `forAllSystems` pattern would allow easy extension to Darwin targets if the packaging were adapted.

### What is the purpose of the `forAllSystems` function in the OpenLogi flake?

The **`forAllSystems`** function acts as a higher-order abstraction that takes a function and applies it to every system in the `systems` list. This prevents repetitive Nix code duplication when defining `packages`, `checks`, and `formatter` outputs, ensuring that both x86_64 and aarch64 receive identical build configurations differentiated only by their respective `pkgs` toolchains.

### Can I run tests for both architectures without building the packages?

Yes. The command `nix flake check --all-systems --no-build` evaluates the **`checks`** output for both `x86_64-linux` and `aarch64-linux` without realizing the package derivations. This is useful for CI pipelines to validate the flake structure and test configurations across all supported platforms quickly.