Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
285 changes: 36 additions & 249 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@
nix-ros-overlay.inputs.flake-utils.lib.eachDefaultSystem (
system:
let
# List of supported ROS distros
distros = [
"jazzy" # default
"rolling"
];

pkgs = import nixpkgs {
inherit system;
overlays = [
Expand All @@ -35,246 +29,56 @@
];
};

rustToolchain = pkgs.rust-bin.stable."1.91.0".default.override {
extensions = [
"rust-src"
"rust-analyzer"
];
};

rustfmtNightly = pkgs.rust-bin.nightly.latest.rustfmt;

# Override rustfmt to use nightly
rustfmt-nightly-bin = pkgs.writeShellScriptBin "rustfmt" ''
exec ${rustfmtNightly}/bin/rustfmt "$@"
'';

# Factory to create environment for a specific ROS distro
mkRosEnv =
rosDistro:
let
rosDeps = {
rcl = with pkgs.rosPackages.${rosDistro}; [
rcl
rcl-interfaces
rclcpp
rcutils
demo-nodes-py
demo-nodes-cpp
action-tutorials-cpp
];

messages = with pkgs.rosPackages.${rosDistro}; [
std-msgs
geometry-msgs
sensor-msgs
example-interfaces
common-interfaces
rosidl-default-generators
rosidl-default-runtime
rosidl-adapter
rosidl-typesupport-fastrtps-c
rosidl-typesupport-fastrtps-cpp
];

# Test-only message packages
testMessages = with pkgs.rosPackages.${rosDistro}; [
test-msgs
];

devExtras = with pkgs.rosPackages.${rosDistro}; [
ament-cmake-core
ros-core
rclpy
rmw
rmw-implementation
rmw-zenoh-cpp
ament-cmake
ament-cmake-gtest
ament-lint-auto
ament-lint-common
launch
launch-testing
ros2cli
];
};
in
{
# Development environment with all dependencies including test messages
dev = pkgs.rosPackages.${rosDistro}.buildEnv {
paths = rosDeps.rcl ++ rosDeps.messages ++ rosDeps.testMessages ++ rosDeps.devExtras;
};

# Core RCL only (for minimal builds)
rcl = pkgs.rosPackages.${rosDistro}.buildEnv {
paths = rosDeps.rcl;
};

# Runtime messages only
msgs = pkgs.rosPackages.${rosDistro}.buildEnv {
paths = rosDeps.messages;
};

# Build environment with runtime messages but NO test messages
build = pkgs.rosPackages.${rosDistro}.buildEnv {
paths = rosDeps.rcl ++ rosDeps.messages;
};

# Test environment for core tests only (no test_msgs)
testCore = pkgs.rosPackages.${rosDistro}.buildEnv {
paths = rosDeps.rcl ++ rosDeps.messages;
};

# Test environment with test messages (for all tests)
testFull = pkgs.rosPackages.${rosDistro}.buildEnv {
paths = rosDeps.rcl ++ rosDeps.messages ++ rosDeps.testMessages;
};
};

# Common build tools
commonBuildInputs = with pkgs; [
rustToolchain
sccache
clang
llvmPackages.libclang
llvmPackages.bintools
pkg-config
nushell
protobuf
markdownlint-cli
];

# Development tools
devTools = with pkgs; [
cargo-edit
cargo-watch
clang-tools
rust-analyzer
nixfmt-rfc-style
gdb
];

# Documentation tools
docTools = with pkgs; [
mdbook
mdbook-admonish
mdbook-mermaid
];

# Test tools
testTools = with pkgs; [
cargo-nextest
];

# Environment variables for Rust/C++ interop
commonEnvVars = rec {
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
CLANG_PATH = "${pkgs.llvmPackages.clang}/bin/clang";
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [
pkgs.stdenv.cc.cc.lib
# ROS libraries will be added by the ROS environment packages
];
RUST_BACKTRACE = "1";
RMW_IMPLEMENTATION = "rmw_zenoh_cpp";
RUSTC_WRAPPER = "${pkgs.sccache}/bin/sccache";
};

# Export environment variables as shell commands
exportEnvVars = pkgs.lib.concatStringsSep "\n" (
pkgs.lib.mapAttrsToList (name: value: "export ${name}=\"${value}\"") commonEnvVars
);

# Base shell configuration factory
mkDevShell =
{
name,
packages,
banner ? "",
extraShellHook ? "",
}:
pkgs.mkShell {
inherit name packages;
shellHook = ''
${exportEnvVars}
${extraShellHook}
${if banner != "" then banner else ""}
'';
hardeningDisable = [ "all" ];
};

# Helper to create shells for a specific ROS distro
mkRosShells =
rosDistro:
let
rosEnv = mkRosEnv rosDistro;
in
{
default = mkDevShell {
name = "ros-z-dev-${rosDistro}";
packages = [
rustfmt-nightly-bin
]
++ commonBuildInputs
++ devTools
++ docTools
++ testTools
++ [ rosEnv.dev ]
++ pre-commit-check.enabledPackages;
extraShellHook = ''
${pre-commit-check.shellHook}
mdbook-mermaid install book/ 2>/dev/null || true
mdbook-admonish install book/ 2>/dev/null || true
'';
banner = ''
echo "🦀 ros-z development environment (with ROS)"
echo "ROS 2 Distribution: ${rosDistro}"
echo "Rust: $(rustc --version)"
'';
};
rosEnv = import ./nix/ros-env.nix { inherit pkgs; };

ci = mkDevShell {
name = "ros-z-ci-${rosDistro}";
packages = commonBuildInputs ++ docTools ++ testTools ++ [ rosEnv.testFull ];
extraShellHook = ''
mdbook-mermaid install book/ 2>/dev/null || true
mdbook-admonish install book/ 2>/dev/null || true
'';
};
};

# Generate shells for all distros
allDistroShells = builtins.listToAttrs (
builtins.map (distro: {
name = distro;
value = mkRosShells distro;
}) distros
);
# Pre-commit hooks configuration
pre-commit-check = import ./nix/pre-commit.nix {
devshells = import ./nix/devshells.nix {
inherit
pkgs
git-hooks
pre-commit-check
rosEnv
system
rustfmtNightly
;
};

pre-commit-check = import ./nix/pre-commit.nix {
inherit pkgs git-hooks system;
rustfmtNightly = devshells.rustfmtNightly;
};

inherit (devshells)
commonBuildInputs
devTools
docTools
testTools
mkDevShell
rustfmtNightlyBin
mdbookInstallHook
allDistroShells
;

distros = rosEnv.distros;

makeDistroShells =
suffix:
builtins.listToAttrs (
builtins.map (distro: {
name = "ros-${distro}${suffix}";
value = allDistroShells.${distro}.${if suffix == "" then "default" else "ci"};
}) distros
);
in
{
# Pre-commit checks
checks = {
inherit pre-commit-check;
};

# Development shells
devShells = {
# Default: first distro in the list with ROS
default = allDistroShells.${builtins.head distros}.default;

# Without ROS
pureRust = mkDevShell {
name = "ros-z-pure-rust";
packages = [
rustfmt-nightly-bin
rustfmtNightlyBin
]
++ commonBuildInputs
++ devTools
Expand All @@ -283,39 +87,22 @@
++ pre-commit-check.enabledPackages;
extraShellHook = ''
${pre-commit-check.shellHook}
mdbook-mermaid install book/ 2>/dev/null || true
mdbook-admonish install book/ 2>/dev/null || true
${mdbookInstallHook}
'';
banner = ''
echo "🦀 ros-z development environment (pure Rust)"
echo "Rust: $(rustc --version)"
'';
};

# CI without ROS
pureRust-ci = mkDevShell {
name = "ros-z-ci-pure-rust";
packages = commonBuildInputs ++ docTools ++ testTools;
extraShellHook = ''
mdbook-mermaid install book/ 2>/dev/null || true
mdbook-admonish install book/ 2>/dev/null || true
'';
extraShellHook = mdbookInstallHook;
};
}
# Add per-distro dev shells (ros-jazzy, ros-rolling, ...)
// (builtins.listToAttrs (
builtins.map (distro: {
name = "ros-${distro}";
value = allDistroShells.${distro}.default;
}) distros
))
# Add per-distro CI shells (ros-jazzy-ci, ros-rolling-ci, ...)
// (builtins.listToAttrs (
builtins.map (distro: {
name = "ros-${distro}-ci";
value = allDistroShells.${distro}.ci;
}) distros
));
// (makeDistroShells "")
// (makeDistroShells "-ci");

formatter = pkgs.nixfmt-rfc-style;
}
Expand Down
Loading
Loading