Builder Functions
Builder Functions
Section titled “Builder Functions”Ghaf provides reusable builder functions that can be consumed by both Ghaf internally and downstream projects. This eliminates code duplication and ensures consistency across projects.
Solution
Section titled “Solution”Ghaf now exports builder functions via flake.builders that can be imported and used by any downstream project.
Available Builders
Section titled “Available Builders”mkGhafConfiguration
Section titled “mkGhafConfiguration”Creates a Ghaf configuration for supported target profiles such as laptop-x86 and orin.
# Function signaturemkGhafConfiguration :: { self: flake, inputs: attrSet, lib: lib,} -> ({ name: string, system: string, profile: string, hardwareModule: module, variant?: string, extraModules?: [module], extraConfig?: attrSet, vmConfig?: attrSet} -> { hostConfiguration: nixosSystem, variant: string, name: string, package: derivation})mkGhafInstaller
Section titled “mkGhafInstaller”Creates a bootable ISO installer for a Ghaf image package. The outer builder application evaluates the shared installer NixOS system once, and per-target calls only override the ISO contents with the target-specific Ghaf image.
# Function signaturemkGhafInstaller :: { self: flake, lib: lib, system?: string = "x86_64-linux" extraModules?: [module]} -> ({ name: string, imagePath: path} -> { name: string, package: derivation})Usage in Downstream Projects
Section titled “Usage in Downstream Projects”Basic Example
Section titled “Basic Example”{ inputs = { ghaf.url = "github:tiiuae/ghaf"; nixpkgs.follows = "ghaf/nixpkgs"; };
outputs = { ghaf, nixpkgs, ... }: let mkGhafConfiguration = ghaf.builders.mkGhafConfiguration { self = ghaf; inputs = { inherit ghaf nixpkgs; }; lib = ghaf.lib; };
myLaptop = mkGhafConfiguration { name = "my-laptop"; system = "x86_64-linux"; profile = "laptop-x86"; hardwareModule = ./hardware-configuration.nix; variant = "debug"; extraModules = [ ghaf.nixosModules.reference-profiles ghaf.nixosModules.profiles ]; extraConfig = { reference.profiles.mvp-user-trial.enable = true; }; };
in { nixosConfigurations.${myLaptop.name} = myLaptop.hostConfiguration; packages.x86_64-linux.${myLaptop.name} = myLaptop.package; };}With Installer
Section titled “With Installer”{ outputs = { ghaf, nixpkgs, ... }: let system = "x86_64-linux";
mkGhafConfiguration = ghaf.builders.mkGhafConfiguration { self = ghaf; inputs = { inherit ghaf nixpkgs; }; lib = ghaf.lib; };
mkGhafInstaller = ghaf.builders.mkGhafInstaller { self = ghaf; lib = ghaf.lib; inherit system; extraModules = [ { networking.wireless.networks."MyWiFi".psk = "password"; } ]; };
laptop = mkGhafConfiguration { name = "my-laptop"; inherit system; profile = "laptop-x86"; hardwareModule = ./hardware-configuration.nix; variant = "debug"; };
installer = mkGhafInstaller { name = laptop.name; imagePath = laptop.package; };
in { packages.${system} = { ${laptop.name} = laptop.package; ${installer.name} = installer.package; }; };}Implementation Details
Section titled “Implementation Details”The builders are located in lib/builders/ and are exported via flake.builders. They are also available as self.builders within the flake, allowing direct usage in flake-modules without intermediate files.
Internal Usage (Ghaf modules)
Section titled “Internal Usage (Ghaf modules)”Internal flake-modules call builders with parameters to get the builder functions:
{ lib, self, inputs, ...}:let system = "x86_64-linux";
# Call builders with parameters to get the builder functions ghaf-configuration = self.builders.mkGhafConfiguration { inherit self inputs; inherit (self) lib; };
ghaf-installer = self.builders.mkGhafInstaller { inherit self system; inherit (self) lib; extraModules = installerModules; };
# Then use the builder functions with machine-specific parameters target-configs = [ (ghaf-configuration { name = "lenovo-x1-carbon-gen11"; inherit system; profile = "laptop-x86"; hardwareModule = self.nixosModules.hardware-lenovo-x1-carbon-gen11; variant = "debug"; extraModules = commonModules; extraConfig = { reference.profiles.mvp-user-trial.enable = true; }; }) ];
target-installers = map (t: ghaf-installer { name = t.name; imagePath = self.packages.${system}.${t.name}; }) target-configs;in { flake.packages.${system} = builtins.listToAttrs ( map (t: lib.nameValuePair t.name t.package) (target-configs ++ target-installers) );}External Usage (Downstream projects)
Section titled “External Usage (Downstream projects)”External projects access builders via the flake output:
{ inputs.ghaf.url = "github:tiiuae/ghaf";
outputs = { ghaf, nixpkgs, ... }: let mkGhafConfiguration = ghaf.builders.mkGhafConfiguration { self = ghaf; inputs = { inherit ghaf nixpkgs; }; lib = ghaf.lib; }; in { # Use the builder... };}This approach eliminates relative import paths (../../lib/builders/) while maintaining clean separation between internal and external usage patterns.