mirror of
https://github.com/wentasah/ros2nix.git
synced 2025-06-10 00:02:23 +03:00
Merge 83c04566d1
into 04b3d80304
This commit is contained in:
commit
5f61b172c5
3 changed files with 192 additions and 18 deletions
100
README.md
100
README.md
|
@ -35,11 +35,24 @@ you don't have to be concerned with it.
|
||||||
```sh
|
```sh
|
||||||
ros2nix $(find -name package.xml)
|
ros2nix $(find -name package.xml)
|
||||||
```
|
```
|
||||||
This also creates `./overlay.nix` and `./default.nix` for easy
|
This also creates `./shell.nix` for development in the local
|
||||||
integration and/or testing of created packages.
|
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:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
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:
|
||||||
|
|
||||||
2. Try building some of your packages (replace `my-package` with real
|
|
||||||
name):
|
|
||||||
```sh
|
```sh
|
||||||
nix-build -A rosPackages.humble.my-package
|
nix-build -A rosPackages.humble.my-package
|
||||||
nix-build -A rosPackages.jazzy.my-package
|
nix-build -A rosPackages.jazzy.my-package
|
||||||
|
@ -106,6 +119,79 @@ the [Autoware][] project as an example.
|
||||||
|
|
||||||
[Autoware]: https://autoware.org/
|
[Autoware]: https://autoware.org/
|
||||||
|
|
||||||
|
## 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](https://index.ros.org/) (just
|
||||||
|
replace `_` with `-`) or any package from
|
||||||
|
[nixpkgs](https://search.nixos.org/packages).
|
||||||
|
|
||||||
|
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][nix-system-graphics-install]. 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.
|
||||||
|
|
||||||
|
[nix-system-graphics]: https://github.com/soupglasses/nix-system-graphics
|
||||||
|
[nix-system-graphics-install]: https://github.com/soupglasses/nix-system-graphics?tab=readme-ov-file#installing-with-nix-flakes
|
||||||
|
|
||||||
|
### Automatically entering the environment
|
||||||
|
|
||||||
## ros2nix reference
|
## ros2nix reference
|
||||||
|
|
||||||
<!-- `$ python3 -m ros2nix --help` -->
|
<!-- `$ python3 -m ros2nix --help` -->
|
||||||
|
@ -121,8 +207,9 @@ usage: ros2nix [-h]
|
||||||
[--extra-check-inputs DEP1,DEP2,...]
|
[--extra-check-inputs DEP1,DEP2,...]
|
||||||
[--extra-native-build-inputs DEP1,DEP2,...] [--flake]
|
[--extra-native-build-inputs DEP1,DEP2,...] [--flake]
|
||||||
[--default | --no-default] [--overlay | --no-overlay]
|
[--default | --no-default] [--overlay | --no-overlay]
|
||||||
[--nix-ros-overlay FLAKEREF] [--nixfmt] [--compare]
|
[--shell | --no-shell] [--nix-ros-overlay FLAKEREF] [--nixfmt]
|
||||||
[--copyright-holder COPYRIGHT_HOLDER] [--license LICENSE]
|
[--compare] [--copyright-holder COPYRIGHT_HOLDER]
|
||||||
|
[--license LICENSE]
|
||||||
package.xml [package.xml ...]
|
package.xml [package.xml ...]
|
||||||
|
|
||||||
positional arguments:
|
positional arguments:
|
||||||
|
@ -195,6 +282,7 @@ options:
|
||||||
None)
|
None)
|
||||||
--overlay, --no-overlay
|
--overlay, --no-overlay
|
||||||
Generate overlay.nix (default: True)
|
Generate overlay.nix (default: True)
|
||||||
|
--shell, --no-shell Generate shell.nix (default: True)
|
||||||
--nix-ros-overlay FLAKEREF
|
--nix-ros-overlay FLAKEREF
|
||||||
Flake reference of nix-ros-overlay. You may want to
|
Flake reference of nix-ros-overlay. You may want to
|
||||||
change the branch from master to develop or use your
|
change the branch from master to develop or use your
|
||||||
|
|
|
@ -179,6 +179,57 @@ import nix-ros-overlay {{
|
||||||
''')
|
''')
|
||||||
|
|
||||||
|
|
||||||
|
def generate_shell(args, packages: set[str]):
|
||||||
|
nix_ros_overlay = flakeref_to_expr(args.nix_ros_overlay)
|
||||||
|
with file_writer(f'{args.output_dir or "."}/shell.nix', args.compare) as f:
|
||||||
|
f.write(f'''{{
|
||||||
|
nix-ros-overlay ? {nix_ros_overlay},
|
||||||
|
pkgs ? import nix-ros-overlay {{ }},
|
||||||
|
rosDistro ? "{args.distro}",
|
||||||
|
extraPkgs ? {{ }},
|
||||||
|
extraPaths ? [ ],
|
||||||
|
withPackages ? _: [ ],
|
||||||
|
}}:
|
||||||
|
pkgs.mkShell {{
|
||||||
|
name = "ros2nix ${{rosDistro}} shell";
|
||||||
|
packages = [
|
||||||
|
(pkgs.rosPackages.${{rosDistro}}.buildEnv {{
|
||||||
|
wrapPrograms = false;
|
||||||
|
paths =
|
||||||
|
[
|
||||||
|
pkgs.colcon
|
||||||
|
pkgs.rosPackages.${{rosDistro}}.ros-core
|
||||||
|
|
||||||
|
# Work around https://github.com/lopsided98/nix-ros-overlay/pull/624
|
||||||
|
pkgs.rosPackages.${{rosDistro}}.ament-cmake-core
|
||||||
|
pkgs.rosPackages.${{rosDistro}}.python-cmake-module
|
||||||
|
]
|
||||||
|
++ (
|
||||||
|
with pkgs;
|
||||||
|
with pkgs.rosPackages.${{rosDistro}};
|
||||||
|
with extraPkgs;
|
||||||
|
[
|
||||||
|
# Dependencies from package.xml files
|
||||||
|
{indent('\n'.join(sorted(list(packages))), " ")}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
++ builtins.attrValues extraPkgs
|
||||||
|
++ extraPaths
|
||||||
|
++ withPackages (pkgs // pkgs.rosPackages.${{rosDistro}});
|
||||||
|
}}
|
||||||
|
)
|
||||||
|
];
|
||||||
|
shellHook = ''
|
||||||
|
# Setup ROS 2 shell completion. Doing it in direnv is useless.
|
||||||
|
if [[ ! $DIRENV_IN_ENVRC ]]; then
|
||||||
|
eval "$(${{pkgs.python3Packages.argcomplete}}/bin/register-python-argcomplete ros2)"
|
||||||
|
eval "$(${{pkgs.python3Packages.argcomplete}}/bin/register-python-argcomplete colcon)"
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
}}
|
||||||
|
''')
|
||||||
|
|
||||||
|
|
||||||
def generate_flake(args):
|
def generate_flake(args):
|
||||||
with file_writer(f'{args.output_dir or "."}/flake.nix', args.compare) as f:
|
with file_writer(f'{args.output_dir or "."}/flake.nix', args.compare) as f:
|
||||||
f.write('''
|
f.write('''
|
||||||
|
@ -205,18 +256,10 @@ def generate_flake(args):
|
||||||
legacyPackages = pkgs.rosPackages;
|
legacyPackages = pkgs.rosPackages;
|
||||||
packages = builtins.intersectAttrs (import ./overlay.nix null null) pkgs.rosPackages.${rosDistro};
|
packages = builtins.intersectAttrs (import ./overlay.nix null null) pkgs.rosPackages.${rosDistro};
|
||||||
checks = builtins.intersectAttrs (import ./overlay.nix null null) pkgs.rosPackages.${rosDistro};
|
checks = builtins.intersectAttrs (import ./overlay.nix null null) pkgs.rosPackages.${rosDistro};
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = import ./shell.nix {
|
||||||
name = "Example project";
|
inherit pkgs rosDistro;
|
||||||
packages = [
|
extraPkgs = { };
|
||||||
pkgs.colcon
|
extraPaths = [ ];
|
||||||
# ... other non-ROS packages
|
|
||||||
(with pkgs.rosPackages.${rosDistro}; buildEnv {
|
|
||||||
paths = [
|
|
||||||
ros-core
|
|
||||||
# ... other ROS packages
|
|
||||||
];
|
|
||||||
})
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
nixConfig = {
|
nixConfig = {
|
||||||
|
@ -343,6 +386,12 @@ def ros2nix(args):
|
||||||
default=True,
|
default=True,
|
||||||
help="Generate overlay.nix",
|
help="Generate overlay.nix",
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--shell",
|
||||||
|
action=argparse.BooleanOptionalAction,
|
||||||
|
default=True,
|
||||||
|
help="Generate shell.nix",
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--nix-ros-overlay",
|
"--nix-ros-overlay",
|
||||||
metavar="FLAKEREF",
|
metavar="FLAKEREF",
|
||||||
|
@ -384,6 +433,8 @@ def ros2nix(args):
|
||||||
with open(cache_file) as f:
|
with open(cache_file) as f:
|
||||||
git_cache = json.load(f)
|
git_cache = json.load(f)
|
||||||
patch_filenames = set()
|
patch_filenames = set()
|
||||||
|
our_pkg_names: set[str] = set()
|
||||||
|
all_dependencies: set[str] = set()
|
||||||
|
|
||||||
for source in args.source:
|
for source in args.source:
|
||||||
try:
|
try:
|
||||||
|
@ -535,6 +586,14 @@ def ros2nix(args):
|
||||||
patches=[f"./{p}" for p in patches],
|
patches=[f"./{p}" for p in patches],
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
our_pkg_names.add(derivation.name)
|
||||||
|
all_dependencies |= (
|
||||||
|
derivation.build_inputs
|
||||||
|
| derivation.native_build_inputs
|
||||||
|
| derivation.propagated_build_inputs
|
||||||
|
| derivation.propagated_native_build_inputs
|
||||||
|
| derivation.check_inputs
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
err(f'Failed to prepare Nix expression from {source}')
|
err(f'Failed to prepare Nix expression from {source}')
|
||||||
|
@ -592,6 +651,9 @@ def ros2nix(args):
|
||||||
if args.overlay:
|
if args.overlay:
|
||||||
generate_overlay(expressions, args)
|
generate_overlay(expressions, args)
|
||||||
|
|
||||||
|
if args.shell:
|
||||||
|
generate_shell(args, all_dependencies - our_pkg_names)
|
||||||
|
|
||||||
if args.flake:
|
if args.flake:
|
||||||
generate_flake(args)
|
generate_flake(args)
|
||||||
if args.default or (args.default is None and not args.flake):
|
if args.default or (args.default is None and not args.flake):
|
||||||
|
|
|
@ -18,6 +18,30 @@ load common.bash
|
||||||
nix-build -A rosPackages.humble.ros-node -A rosPackages.jazzy.ros-node -A rosPackages.rolling.ros-node
|
nix-build -A rosPackages.humble.ros-node -A rosPackages.jazzy.ros-node -A rosPackages.rolling.ros-node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "nixify local workspace and build it by colcon in nix-shell" {
|
||||||
|
cd ws
|
||||||
|
ros2nix --distro=jazzy $(find src -name package.xml)
|
||||||
|
nix-shell --run "colcon build"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "nix-shell for local workspace with additional ROS package" {
|
||||||
|
ros2nix --distro=jazzy $(find ws/src -name package.xml)
|
||||||
|
nix-shell --arg withPackages 'p: with p; [ compressed-image-transport ]' \
|
||||||
|
--run "ros2 pkg list | grep compressed_image_transport"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "nix-shell for local workspace with additional nixpkgs package" {
|
||||||
|
ros2nix --distro=jazzy $(find ws/src -name package.xml)
|
||||||
|
nix-shell --arg withPackages 'p: with p; [ hello ]' \
|
||||||
|
--run "which hello"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "nixify local workspace and build it by colcon in nix develop" {
|
||||||
|
cd ws
|
||||||
|
ros2nix --flake --distro=jazzy $(find src -name package.xml)
|
||||||
|
nix develop --command colcon build
|
||||||
|
}
|
||||||
|
|
||||||
@test "nixify package in the current directory" {
|
@test "nixify package in the current directory" {
|
||||||
cd ws/src/library
|
cd ws/src/library
|
||||||
ros2nix package.xml
|
ros2nix package.xml
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue