Proposal for GNUInstallDirs use to enable multiple installspaces

Following on my ROSCon talk about building and shipping ROS 1/2 workspaces using Nix, I’d like to create a REP with some recommendations that I feel would be a pathway to mitigating aspects of the catkin/ament/colcon ecosystem that make using Nix’s multiple outputs capability less smooth, in particular assumptions:

  • That the runtime content (lib, share, package.xml) will be in a directory relative to the build-time content (headers, cmake modules).
  • That runtime variables like PYTHONPATH and ROS_PACKAGE_PATH will point to the same roots as build-time variables like CMAKE_PREFIX_PATH.
  • That there will never be multiple install locations (eg, in colcon).

Through some aggressive use of Nix’s post-build “fixup” capabilities, I have actually overcome these issues for our builds, but it has involved an unfortunate amount of fairly brittle hackery, much of it targeting specific packages or groups of similar packages, for example:

      # Generated CMake from ament requires lib-path patching.
      if [ -e $cmake/ament_cmake_export_libraries-extras.cmake ]; then
        substituteInPlace $cmake/ament_cmake_export_libraries-extras.cmake \
          --replace "_DIR}/../../../lib" "_LIBDIR}"
      fi;

      # Many rosidl and related packages require these patchups.
      if [ -e $cmake/$name-extras.cmake ]; then
        substituteInPlace $cmake/$name-extras.cmake \
          --replace "_DIR}/../../../lib" "_LIBDIR}" \
          --replace "_DIR}/../resource" "_SHAREDIR}/resource" \
          --replace "INTERFACE_FILES_BASEPATH \"\''${${name}_DIR}" "INTERFACE_FILES_BASEPATH \"\''${${name}_SHAREDIR}/msg"
      fi
      for f in $(find $cmake -name "*_generate_interfaces.cmake"); do
        substituteInPlace $f \
          --replace "_DIR}/../\''${_idl_file}" "_SHAREDIR}/\''${_idl_file}" \
          --replace "_pkg_name}_DIR}/../../.." "_pkg_name}_LIBDIR}/.."
      done

Upstream nixpkgs/CMake already handles much of this automatically (implementation) for packages that observe the conventions given in GNUInstallDirs, so moving in that direction is an obvious step to improve the situation, but I think it would probably make sense to lay out a more complete vision with concrete recommendations that can be reviewed and agreed-upon before hitting up individual maintainers with PRs requesting these types of changes.

The first and most critical piece is teaching colcon-cmake how to optionally do a two-part cmake --install --component [Development|Runtime] --prefix <location> installation, as that will automatically solve a number of issues in cases where it’s CMake-supplied find modules, and provide a pathway to using more specific directory variables in ament- and catkin-supplied files or package-specific “CMake extras” templates.

Would it make sense to get a REP drafted for this? Any prior art I should be aware of as far as previous attempts?

Pinging especially @nuclearsandwich, @cottsay, @jrivero, @wjwwood but obviously open to feedback from all.

5 Likes

Yes, please do start drafting a REP to detail your ideas and the necessary changes. That will help spur some debate. I think moving colcon’s outputs towards anything more flexible and standard-oriented is always a good thing.