Nix makes packaging software reproducible and portable. Here’s how to create a minimal derivation for a C program, and how to modernize it with flakes for automatic platform detection.
Write Your Program Suppose you have a simple C file,
simple.c
:#include <stdio.h> int main() { puts("🐧 Hello! allo, allo!"); return 0; }
Write a Build Script Create
simple_builder.sh
:export PATH="$coreutils/bin:$gcc/bin" mkdir -p $out/bin gcc -o $out/bin/simple $src
Write a Platform-Aware Derivation Create
simple.nix
that takes system as an argument:{ pkgs ? import <nixpkgs> { }, system ? builtins.currentSystem }: pkgs.stdenv.mkDerivation { name = "simple"; src = ./simple.c; builder = "${pkgs.bash}/bin/bash"; args = [ ./simple_builder.sh ]; inherit (pkgs) gcc coreutils; system = system; }
Build with:
nix-build simple.nix ./result/bin/simple
Or override the platform:
nix-build simple.nix --argstr system x86_64-linux
Use Flakes for Maximum Portability
Tip: Flakes require your project to be in a git repo.Create
flake.nix
:{ description = "Simple C program"; inputs.nixpkgs.url = "github:NixOS/nixpkgs"; outputs = { self, nixpkgs }: { packages = nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" ] (system: let pkgs = nixpkgs.legacyPackages.${system}; in pkgs.stdenv.mkDerivation { name = "simple"; src = ./simple.c; builder = "${pkgs.bash}/bin/bash"; args = [ ./simple_builder.sh ]; inherit (pkgs) gcc coreutils; system = system; } ); }; }
Initialize git and build:
git init # if not already a git repo nix build .#simple ./result/bin/simple
Summary#
- Use system to make your derivation portable.
- With flakes, your build will work on any supported platform—just keep your project in a git repo.
- Nix ensures your builds are reproducible and cross-platform, with minimal boilerplate.