The purpose of ROS-specific version of buildEnv in this overlay is to reduce the length of environment variables when using many ROS packages. However, currently it works only for ROS 1 and not for ROS 2. This commit is an attempt to fix that.
Although the change looks trivial, it took me multiple full days to figure out what to change and how. The following is my understanding of how handling of environment variables works in ROS 2 and in nix-ros-overlay and why the change in this commit works. I'm not completely sure that it's all correct so feel free to complain if not.
Every ament_cmake ROS package contains a $out/share/*/local_setup.sh script, generated by ament CMake macros, which is responsible for setting environment variables required for proper function of the package under ROS 2. Every package extends AMENT_PREFIX_PATH and it may extend other variables such as PATH. The default prefix used for extending the variables is specified at compile time and is equal to package's Nix store path ($out).
local_setup.sh files are sourced when building dependent ROS packages. In nix-ros-overlay, this is accomplished by ament-cmake-core-setup-hook, which is automatically propagated to all dependents.
ROS-specific buildEnv ensures that ROS packages are not further propagated downstream but non-ROS packages are. ament-cmake-core-setup-hook is a non-ROS package (it's a Nix native package) so if any package in the buildEnv depends on it, it is propagated out of buildEnv. Therefore dependents of the buildEnv source all local_setup.sh files from the buildEnv (and from other ROS packages outside of buildEnv, if there are any).
The problem when sourcing local_setup.sh files now is the default prefix built into them, which causes every package to have a separate entry in the extended variables. However, if the file is sourced with AMENT_CURRENT_PREFIX variable set, its value overrides the default prefix. That's what we do in this commit. We set AMENT_CURRENT_PREFIX to the store path of the sourced package; in case of normal ROS packages it's equal to the default builtin prefix, but in case of buildEnv, it's different and all packages in the environment share the same prefix.
I'm testing this change with the following flake.nix:
without this commit returns 71 entries, while with this commit the result in a single entry!
I gave this change some light testing and didn't find any problems, but if my analysis above is not completely correct, I can imagine this breaking things. I'll continue testing this in my project and I'd appreciate if others can test is too.
The purpose of ROS-specific version of buildEnv in this overlay is to reduce the length of environment variables when using many ROS packages. However, currently it works only for ROS 1 and not for ROS 2. This commit is an attempt to fix that.
Although the change looks trivial, it took me multiple full days to figure out what to change and how. The following is my understanding of how handling of environment variables works in ROS 2 and in nix-ros-overlay and why the change in this commit works. I'm not completely sure that it's all correct so feel free to complain if not.
Every ament_cmake ROS package contains a
$out/share/*/local_setup.sh
script, generated by ament CMake macros, which is responsible for setting environment variables required for proper function of the package under ROS 2. Every package extendsAMENT_PREFIX_PATH
and it may extend other variables such asPATH
. The default prefix used for extending the variables is specified at compile time and is equal to package's Nix store path ($out
).local_setup.sh files are sourced when building dependent ROS packages. In nix-ros-overlay, this is accomplished by
ament-cmake-core-setup-hook
, which is automatically propagated to all dependents.ROS-specific
buildEnv
ensures that ROS packages are not further propagated downstream but non-ROS packages are.ament-cmake-core-setup-hook
is a non-ROS package (it's a Nix native package) so if any package in thebuildEnv
depends on it, it is propagated out ofbuildEnv
. Therefore dependents of thebuildEnv
source alllocal_setup.sh
files from thebuildEnv
(and from other ROS packages outside of buildEnv, if there are any).The problem when sourcing
local_setup.sh
files now is the default prefix built into them, which causes every package to have a separate entry in the extended variables. However, if the file is sourced withAMENT_CURRENT_PREFIX
variable set, its value overrides the default prefix. That's what we do in this commit. We setAMENT_CURRENT_PREFIX
to the store path of the sourced package; in case of normal ROS packages it's equal to the default builtin prefix, but in case ofbuildEnv
, it's different and all packages in the environment share the same prefix.I'm testing this change with the following flake.nix:
Running
nix develop
and then:without this commit returns 71 entries, while with this commit the result in a single entry!
I gave this change some light testing and didn't find any problems, but if my analysis above is not completely correct, I can imagine this breaking things. I'll continue testing this in my project and I'd appreciate if others can test is too.