Beginning about two years ago, ROS began the process of migrating its build system, which is an important infrastructure component. The original ROS build system was called rosbuild, and its replacement is catkin.
Why the change?
There are a variety of motivations behind the design of catkin, but the overarching philosophy is to make ROS a better citizen of its host operating systems, and to better utilize the tools provided by CMake, which is the underlying system used to implement both rosbuild and catkin. The ‘C’ in CMake stands for cross-platform, and one of the key gains by making catkin closer to native CMake is that ROS is now much more portable, especially to platforms like OS X and Windows, as well as to Linux kernels running on embedded targets.
Under rosbuild, each ROS package was its own CMake project, and thus each ROS package you were working on would include its own build folder, as well as a bin folder containing the resulting executable. Because each package was its own project, all inter-package dependency management had to be handled by rosmake—an external, ROS-specific tool—CMake had no information above the level of the individual package.
But dependency management is exactly the sort of thing that a build system is for, so this was an unnecessary reinventing of the wheel. This was particularly bad when serious thought was being given to cross-compiling ROS. CMake can trivially generate a Visual Studio project to build Windows software, but any layers which go beyond the basic functionality provided by CMake would then have to be ported and maintained separately as well. Not good.
Key Challenges
A key change in catkin is that now the entire workspace of ROS packages is built as a single CMake project, with packages added as subprojects. This has many implications, among them:
-Dependency management is handled by native CMake tools, rather than wrappers.
-Several of the build system behaviours which previously were handled by rosbuild_xyz macros now use native CMake macros.
-All the out-of-source build objects go in a single build folder shared by the whole workspace, rather than being divided up by package.
-CMake can make smarter decisions about the order to build things in, including how to parallelize the building of dependencies.
-Supporting alternative architectures (ARM) and OSes (Windows, Mac OS X) is much cleaner.
catkin is a standalone tool which could potentially be adopted by other, non-ROS projects. It would be especially appealing to projects which have a similar requirement of managing dependencies between many independent code modules.
-There is now a universal install target, which assembles a distribution-ready snapshot of workspace packages. This is important for a lot of reasons, including reducing the size of deb packages and simplifying the build infrastructure which produces them. It’s also an important step in enabling ROS to support commercial entities who may wish or need to deploy proprietary, closed-source software into the ROS ecosystem.
Cautions to take
The following cautions are necessary for a developer using catkin:
-Because your workspace is one big CMake project, all the targets shared between packages exist in the same namespace. Your targets don’t need to be unique across the entire ROS ecosystem, as the resulting binaries ultimately go in per-package directories, but they must be unique within the workspace. The suggestion is to prefix targets with the package name, which is accessible using the PROJECT_NAME variable.
-The dependency information is now repeated in two places: once for the packaging system (in package.xml), and once for the build system (in CMakeLists.txt). This helps avoid having either the package manager depend on an implementation detail of the build system, or the build system depend on the package manager (as was the case with rosmake—it depended on being able to call rospack, which would cause all kinds of curious issues, especially when cross-compiling).
-More explicitness. For example, under rosbuild, the rosbuild_genmsg() macro would automatically sweep the package’s msg folder for messages. The catkin version of message_generation requires each one to be individually listed using the add_message_files() macro. This is a small price to pay for the build system not having to check msg and srv folders all over the filesystem to see whether new messages have popped up in them needing to be built.
-Because of the source/build separation, apt packages generated from catkin ROS packages no longer contain the original source code. This means if there are config files, scripts, or any other pieces of the package which need to be distributed but are not generated by the build system, they need to be explicitly installed. (The install () macro is, of course, part of CMake)
There’s much more to catkin than just this, but these are a handful of critical things which have affected some recent development pushes, including work on getting Kingfisher and Husky ready for ROS Hydro.