dream2nix Documentation

repository·main·Indexed 23 days ago

https://github.com/nix-community/dream2nix

A modular framework for automated, reproducible packaging across multiple language ecosystems. dream2nix aims to unify '2nix' converter solutions, providing a standardized interface for translating lock files and metadata from ecosystems like Python, Haskell, Rust, and Node.js into Nix derivations. It includes features for handling mono-repos, managing dependency groups, and extending functionality via subsystem modules.

Tokens
14.2K
Snippets
38
Records
68
Agent score
79%

What's inside dream2nix

  1. Overview of dream2nix

    main

    dream2nix is a modular framework designed to automate reproducible packaging across various language ecosystems. Its primary goal is to provide a standardized, generic, and customizable framework for automated packaging solutions (often referred to as '2nix' solutions), aiming to reduce the effort required to develop new converters and simplify package updates.

    Key Goals:

    • Modularity and Customizability
    • Maintainability and code de-duplication
    • Common UI across different 2nix solutions
    • Exploration and adoption of new Nix features
    • Simplified updating of packages
  2. How modules improve package overrides in dream2nix

    main

    In standard nixpkgs, changing package options often requires chaining multiple overrideAttrs and override functions. In dream2nix, you can use the module system to declare a package as a module, allowing you to set options (like flags) and the package name directly within a single attribute set. This avoids complex function chaining and makes the configuration more declarative.

    Instead of chaining overrides, you can use imports to bring in the package definition and then set specific attributes like name or flags directly.

    {
      htop-mod = {
        imports = [./htop.nix];
        name = lib.mkForce "htop-mod";
        flags.sensorsSupport = false;
      };
    }
  3. How composability and overridability work in dream2nix v1

    main

    The v1 API shifts the focus from generating Flakes to delivering individual derivations. This change addresses several architectural limitations of the previous version:

    Composability

    Unlike the previous makeFlakeOutputs which suffered from poor composability due to the nature of Flakes (making filtering and merging nested attrsets difficult), the v1 API focuses on providing individual derivations. While templates and tools for composition are provided, the API does not enforce a specific composition solution on the user.

    Overridability and Discoverability

    To improve the experience of overriding package and dependency builds, the v1 API moves away from relying on mkDerivation override functions. Instead, it utilizes the NixOS module system to handle derivation attributes. This also enables better discoverability, allowing users to inspect the API of an individual package via the module system.

  4. Understand the dream2nix user hierarchy

    main

    The dream2nix v1 API is designed around three distinct levels of users, each with different responsibilities and interaction patterns with the tool:

    1. Integration Maintainers (Level 1): Users responsible for maintaining language2nix integrations (the logic that converts a specific language's ecosystem into Nix expressions).
    2. Package Maintainers (Level 2): Users who utilize dream2nix to generate and maintain Nix derivations for specific software packages.
    3. Consumers (Level 3): End-users who use and customize the packages that were produced via the dream2nix workflow.
  5. Use the mkDerivation-mixin module

    main

    The mkDerivation-mixin is a package module based on the mkDerivation builder from nixpkgs. It is functionally equivalent to the standard dream2nix mkDerivation module, with one key difference in configuration structure: all options are declared at the top-level of the module instead of being nested under a mkDerivation.[...] attribute set.

    Use this mixin when you prefer a flatter configuration structure for your package definitions.

  6. Re-use package definitions using groups

    main

    Each package definition in a group provides two distinct attributes that allow for flexible re-use:

    1. [...].packages.<name>.<version>.module: The package definition (the Nix module).
    2. [...].packages.<name>.<version>.public: The final evaluated derivation.

    Because the module is separated from the final result, you can assemble new groups by importing the module of an existing package from another group. This allows you to create variations of a package (e.g., a modified version for testing) by importing the base definition and applying overrides.

    {config, dream2nix, ...}: {
      groups.dev = {
        # A base package definition
        packages.hello."1.0.0".module = {
          imports = [ dream2nix.modules.dream2nix.mkDerivation ];
          name = "hello";
          version = "1.0.0";
          mkDerivation.buildPhase = lib.mkForce ''echo "Hello World!" > $out''
        };
    
        # A modified version of the same package
        packages.hello-mod."1.0.0".module = {
          imports = [ 
            # Import the module definition from the same group
            config.groups.dev.packages.hello.module
          ];
          mkDerivation.buildPhase = ''echo "Good Bye World!" > $out'';
        };
      };
    
      groups.test = {
        # A package in a different group based on the 'dev' group's package
        packages.hello."1.0.0".module = {
          imports = [ 
            # Import the module definition from the 'dev' group
            config.groups.dev.packages.hello.module
          ];
          mkDerivation.buildPhase = ''echo "Happy testing!" > $out''
        };
      };
    }
  7. Use type safety and typo detection in dream2nix modules

    main

    Unlike mkDerivation in nixpkgs, which may silently ignore invalid options or incorrect types, dream2nix modules provide strict validation:

    • Type Safety: If you provide a value of the wrong type (e.g., a string instead of a boolean for dontPatch), dream2nix raises an informative type error.
    • Typo Detection: If you misspell an option name (e.g., nativBuildInputs instead of nativeBuildInputs), dream2nix raises an error stating that the option does not exist, rather than building with the error silently ignored.
  8. How dream2nix v1 improves integration with lang2nix tools

    main

    In previous versions, integrating existing lang2nix solutions into dream2nix was difficult due to strict standards imposed by the project. The v1 API removes most of these restrictions to simplify integration.

    Depending on your requirements, you can integrate tools using either pure or impure methods:

    • Pure integration: Use integrate lang2nix tool (pure) (see ../v1-api/integrating/integrate-lang2nix-pure.md).
    • Impure integration: Use integrate lang2nix tool (impure) (see ../v1-api/integrating/integrate-lang2nix-impure.md).
  9. Use the package-func module to integrate derivation builders

    main

    The package-func module provides an interface for integrating standard Nix derivation builder functions (such as mkDerivation, buildPythonPackage, etc.) into the dream2nix workflow.

    To use it, you provide the builder function in package-func.func and its corresponding arguments in package-func.args. The module then wraps the result into a package exposed under config.public, while making the raw result available via package-func.result.