Convert ROS package.xml to package.nix
Find a file
2025-05-10 18:07:01 +02:00
.github/workflows github: Remove deprecated DeterminateSystems/magic-nix-cache-action 2025-01-23 16:37:14 +01:00
maint github: Prevent update action to fail when there are no changes 2024-09-18 15:26:15 +02:00
ros2nix Work around https://github.com/lopsided98/nix-ros-overlay/pull/624 in generated shell.nix 2025-04-22 23:25:44 +02:00
test Generate shell.nix for development in the local workspace 2025-04-22 23:25:44 +02:00
.flake8 Cleanup, flake8 2024-09-15 10:41:08 +02:00
default.nix Add flake-compat 2024-09-15 18:26:06 +02:00
flake.lock rosdistro update 2025-05-09 12:09:21 +02:00
flake.nix Run tests during CI 2024-12-23 01:35:04 +01:00
LICENSE Initial commit 2024-08-25 17:13:12 +02:00
pyproject.toml Fix setuptools error 2024-09-18 09:59:02 +02:00
README.md Generate shell.nix for development in the local workspace 2025-04-22 23:25:44 +02:00

ros2nix

Tool to convert ROS package.xml to Nix expressions compatible with nix-ros-overlay. Under the hood, it uses rosdep to convert ROS package names to nixpkgs attributes so that you don't have to be concerned with it.

Installation

  • With nix-env:

    nix-env --install -f https://github.com/wentasah/ros2nix/archive/main.tar.gz
    

    or try it out without installation:

    nix-shell -p '(import (fetchTarball "https://github.com/wentasah/ros2nix/archive/main.tar.gz")).default'
    
  • With Nix flakes experimental feature:

    nix profile install github:wentasah/ros2nix
    

    or try it out without installation:

    nix shell github:wentasah/ros2nix
    

Usage examples

Nixifying local ROS workspace

  1. Create Nix expressions for local packages

    ros2nix $(find -name package.xml)
    

    This also creates ./shell.nix for development in the local workspace and ./overlay.nix and ./default.nix for easy integration and/or testing of created Nix packages.

  2. To build the local workspace with colcon, run:

    nix-shell
    colcon build
    

    If nix-shell fails, it might be due to missing packages in nixpkgs or nix-ros-overlay. Feel free to submit a bug or provide the package in extraPkgs argument.

  3. To build some of your packages with Nix, replace my-package with a real name and run:

    nix-build -A rosPackages.humble.my-package
    nix-build -A rosPackages.jazzy.my-package
    

    If the build succeeds, you're probably done. Failures can be caused by several things:

    • Missing dependencies in your package.xml
    • Missing/stale nixos keys for nixpkgs packages in rosdep yaml database
    • Bugs in your packages (e.g. in CMakeLists.txt)
    • Bugs in ros2nix please, report them
    • Bugs in nix-ros-overlay report them too :-)

Nixifying 3rd party ROS packages

You can use 3rd party ROS packages (which are not a part of ROS distribution) in your project as follows. We'll show the procedure on the Autoware project as an example.

  1. Clone the 3rd party repositories, e.g.

    git clone https://github.com/autowarefoundation/autoware.git
    cd autoware
    mkdir src
    vcs import src < autoware.repos
    cd ..
    
    ros2nix --output-as-nix-pkg-name --fetch $(find -name package.xml|grep -v ament_cmake)
    

    This will create all Nix expressions in the current directory and named according to their package names. The expressions will fetch the source code from GitHub instead of from local filesystem. Note that we ignore ament_cmake packages forked by autoware since they break the build.

  2. Try building some packages:

    nix-build -A rosPackages.humble.autoware-overlay-rviz-plugin
    

    Note that not all autoware packages can be build successfully.

Tip

To build all generated packages, run ros2nix with the --flake switch and then run nix flake check (depending on your configuration, you may need to add --experimental-features 'nix-command flakes').

  1. If some packages need changes, you can generate Nix expressions with appropriate patches. Commit the needed changes and run ros2nix with the --patches flag, e.g.:

    pushd autoware/src/...package...
    $EDITOR some-file.cxx
    git commit some-file.cxx
    popd
    ros2nix --output-as-nix-pkg-name --fetch --patches $(find -name package.xml|grep -v ament_cmake)
    

    An example of the resulting Nix expression can be seen here.

Working with development environments

By default, ros2nix generates shell.nix file, which declares development environment for compilation of your workspace. In the simplest case, you can enter it by running nix-shell. For greater flexibility, you can extend it as described below.

ROS distribution

By default, nix-shell enters the ROS distribution which was specified by --distro option of ros2nix, which defaults to rolling. If you want to change it, rerun ros2nix with different value of --distro=....

Alternatively, you can override the default distribution when invoking nix-shell:

nix-shell --argstr rosDistro jazzy

Adding other packages

The generated shell.nix has three parameters withPackages, extraPkgs and extraPaths, which you can use to extend or modify the development environment.

Use withPackages to add additional packages to the environment. Define a Nix function, which returns the packages from the given package set (p in the example below):

nix-shell --arg withPackages 'p: with p; [ compressed-image-transport ]'

This command ensures that compressed-image-transport plugin will be available in your development environment in addition to other required packages. You can use more (space separated) packages inside [ ]. Put there any ROS package (just replace _ with -) or any package from nixpkgs.

Parameters extraPkgs and extraPaths are meant for programmatic use and are described in the next section.

Making the changes permanent

Running graphical applications

Since Nix environments aim to be completely independent from your host system (unless it's NixOS), Nix-compiled programs don't use user space portions of graphics drivers from your host distribution. Therefore, running most graphical applications like rviz2 fails. There are multiple possible solutions, but we recommend using nix-system-graphics.

If you have Intel or AMD GPU, follow their install instructions. In a nutshell:

  1. Store flake.nix from their README into an empty directory.
  2. Run there nix run 'github:numtide/system-manager' -- switch --flake ..

This will create a few files in /etc/systemd/system that will create /run/opengl-driver (location where Nix programs expect graphics drivers).

If you have NVIDIA GPU, the setup is more complex because you need to manually select the same version of the driver as the one used by the kernel of your host system.

Automatically entering the environment

ros2nix reference

usage: ros2nix [-h]
               [--output OUTPUT | --output-as-ros-pkg-name | --output-as-nix-pkg-name]
               [--output-dir OUTPUT_DIR] [--fetch] [--use-per-package-src]
               [--patches | --no-patches] [--distro DISTRO]
               [--src-param SRC_PARAM] [--source-root SOURCE_ROOT]
               [--no-cache] [--do-check] [--extra-build-inputs DEP1,DEP2,...]
               [--extra-propagated-build-inputs DEP1,DEP2,...]
               [--extra-check-inputs DEP1,DEP2,...]
               [--extra-native-build-inputs DEP1,DEP2,...] [--flake]
               [--default | --no-default] [--overlay | --no-overlay]
               [--shell | --no-shell] [--nix-ros-overlay FLAKEREF] [--nixfmt]
               [--compare] [--copyright-holder COPYRIGHT_HOLDER]
               [--license LICENSE]
               package.xml [package.xml ...]

positional arguments:
  package.xml           Path to package.xml

options:
  -h, --help            show this help message and exit
  --output OUTPUT       Output filename (default: package.nix)
  --output-as-ros-pkg-name
                        Name output files based on ROS package name, e.g.,
                        package_name.nix. Implies --output-dir=. (default:
                        False)
  --output-as-nix-pkg-name
                        Name output files based on Nix package name, e.g.,
                        package-name.nix. Implies --output-dir=. (default:
                        False)
  --output-dir OUTPUT_DIR
                        Directory to generate output files in. By default,
                        package files are stored next to their corresponding
                        package.xml, top-level files like overlay.nix in the
                        current directory. (default: None)
  --fetch               Use fetches like fetchFromGitHub in src attribute
                        values. The fetch function and its parameters are
                        determined from the local git work tree. sourceRoot
                        attribute is set if needed and not overridden by
                        --source-root. (default: False)
  --use-per-package-src
                        When using --fetch, fetch only the package sub-
                        directory instead of the whole repo. For repos with
                        multiple packages, this will avoid rebuilds of
                        unchanged packages at the cost of longer generation
                        time. (default: False)
  --patches, --no-patches
                        Add local git commits not present in git remote named
                        "origin" to patches in the generated Nix expression.
                        Only allowed with --fetch. This option is experimental
                        and may be changed in the future. (default: None)
  --distro DISTRO       ROS distro (used as a context for evaluation of
                        conditions in package.xml, in the name of the Nix
                        expression and in flake.nix). Note that the generated
                        Nix expression can be used with any ROS distro if its
                        package.xml contains no conditions. (default: rolling)
  --src-param SRC_PARAM
                        Adds a parameter to the generated function and uses it
                        as a value of the src attribute (default: None)
  --source-root SOURCE_ROOT
                        Set sourceRoot attribute value in the generated Nix
                        expression. Substring '{package_name}' gets replaced
                        with the package name. (default: None)
  --no-cache            Don't use cache of git checkout sha265 hashes across
                        generation runs. (default: False)
  --do-check            Set doCheck attribute to true (default: False)
  --extra-build-inputs DEP1,DEP2,...
                        Additional dependencies to add to the generated Nix
                        expressions (default: [])
  --extra-propagated-build-inputs DEP1,DEP2,...
                        Additional dependencies to add to the generated Nix
                        expressions (default: [])
  --extra-check-inputs DEP1,DEP2,...
                        Additional dependencies to add to the generated Nix
                        expressions (default: [])
  --extra-native-build-inputs DEP1,DEP2,...
                        Additional dependencies to add to the generated Nix
                        expressions (default: [])
  --flake               Generate top-level flake.nix instead of default.nix.
                        Use with --fetch if some package.xml files are outside
                        of the flake repo (default: False)
  --default, --no-default
                        Enforce/suppress generation of default.nix (default:
                        None)
  --overlay, --no-overlay
                        Generate overlay.nix (default: True)
  --shell, --no-shell   Generate shell.nix (default: True)
  --nix-ros-overlay FLAKEREF
                        Flake reference of nix-ros-overlay. You may want to
                        change the branch from master to develop or use your
                        own fork. (default: github:lopsided98/nix-ros-
                        overlay/master)
  --nixfmt              Format the resulting expressions with nixfmt (default:
                        False)
  --compare             Don't write any file, but check whether writing the
                        file would change existing files. Exit with exit code
                        2 if a change is detected. Useful for CI. (default:
                        False)
  --copyright-holder COPYRIGHT_HOLDER
                        Copyright holder of the generated Nix expressions.
                        (default: None)
  --license LICENSE     License of the generated Nix expressions, e.g. 'BSD'
                        (default: None)