This page summarizes the differences between catkin and rosbuild. The source of information for this page are the catkin docs, the catkin API reviews, and the catkin source code.
Motivation for catkin
The main problem with rosbuild was the difficulty of installing ROS on other operating systems or architectures than those initially targeted by Willow Garage. Catkin provides build and install targets for ROS packages, with FHS compliant install layouts, which eases cross platform development.
Achieving cross platform seemed very hard if not impossible to achieve by merely changing rosbuild.
The main design decision was to implement catkin as a set of CMake macros, variables and helper functions written in python.
The designers of catkin also attempted to improve the catkin experience to reduce the effort involved with cmake and rosbuild projects when building a lot of them with plenty of dependencies. In particular the build speed with rosbuild was a source of many complaints.
So the main design goals of catkin were:
- install target with whitelisted set of files to install
- FHS compliant layout of files
- Auto-Generation of cmake compliant configuration files
- Out-of-source builds (also for cross compilation)
- single command to build many projects in the right order
- allow standard cmake commands instead of wrapper commands
- development cycle without need to install
- speed up compilation cycles using parallel compilation of c++ files across inter-dependent projects
- Split configure and build phases to improve build speed
- Improve build speed by avoiding multiple rospack-like lookup of resources (using single cmake lookup instead)
Stack and package concept
rosbuild defined two key concepts, stacks and packages. A package was a folder containing a manifest.xml and source files. A stack was a folder with a stack.xml file. Packages were part of a stack if they were a subfolder of a stack (both in source as in installed layouts). Stacks could depend only on other stacks, packages could only depend on other packages.
With catkin, packages are the atomic units of build and of release, metapackages are non-atomic units of release that can be used to replace the function of stacks. With catkin, packages in source are folders with a manifest file called package.xml and source files. However when installed, due to the FHS requirements, package artifacts are no longer strictly contained in a package folder.
Making packages be the atomic unit of release allows for smaller ROS installations, as undesired packages need not be installed with a stack. Adhering to FHS layout allows easier installation of ROS on a variety of operating systems and architectures.
The build process in rosbuild was driven by the ROS_PACKAGE_PATH environment variable, the rosmake command, and the rospack library. The rosmake command located packages by crawling the directories listed in the ROS_PACKAGE_PATH, then invoking make on all package folders found, respecting the order of dependencies. The make command typically relied on cmake and both configured and build the project sources. Dependencies were looked up using the rospack library, which also used the ROS_PACKAGE_PATH to locate files belonging to a package. For each package, cmake and make were invoked in isolation, which also replicated efforts to find dependencies for several packages.
With catkin, the build process is driven by a workspace folder, the standard cmake commands, and the cmake conventions for looking up dependencies. The workspace folder contains a cmake file which will crawl only the workspace folder for catkin packages, and configures the build of those. During configuration, cmake configuration files are automatically generated. Resources in dependencies are looked up using those auto-generated cmake configuration files instead of rospack. This also allows 3rd-party software to build upon installed ROS packages without using any ROS build toolchain.
As for plain cmake, the CMAKE_PREFIX_PATH environment variable contains the locations that will be searched, replacing the need for a ROS-specific ROS_PACKAGE_PATH variable.
The build process (calling make) then only compiles build targets, potentially allowing to compile files in parallel across interdependent projects (which had to be build sequentially with rosbuild).
So speed-ups in catkin compared to rosbuild are expected mainly due to these reasons:
- configure once, build many times; re-configuration only on demand
- a single configure step using cmake (looking up same dependencies just once)
- a single make process (compiling in parallel even across interdependent projects)
This design has some caveats, as namespace conflicts can arise, mainly around same names for cmake targets, other global (cached) variables and multiple incompatible invocations of find_package. Mitigations for this are naming standards for targets and variables, isolated catkin builds (using catkin_make_isolated) and splitting up catkin workspaces.
There are toolchains to create package files installable for Ubuntu for both rosbuild and catkin packages. rosbuild packages are installed with both their source files and compiled files, in a single folder. All packages of a stack are packaged into a single distribution unit, often installing packages the user did not want to.
catkin packages are (typically) installed without source files that are not needed to run the code. Also only the packages that the user wants to are installed (rather than while stacks as with rosbuild).
The installation files for catkin packages are spread over several folders as requested by the FHS standard. ROS still distinguishes global from local executable folders. This means executable files typically do not go into a global bin folder on the PATH, but instead go into subfolders of lib or share (depending on whether they are binaries or scripts), and should be invoked using rosrun.
The benefit of following FHS is that the packages can easily be packaged for a variety of operating systems (Unix, BSD, other linux distros) and package managers, and that software can be built on top of packages without requiring to depend on a special toolchain. So installed catkin packages can easily reused without requiring catkin.
rosbuild allowed users to put packages under development anywhere on the ROS_PACKAGE_PATH. A typical usage would encourage a single source workspace folder. rosmake could be invoked from anywhere with the name of a package (or fallback using the current folder), and would recursively build the graph of dependencies of the given package. The ROS_PACKAGE_PATH had to be managed by the user, uses were encouraged to use the rosinstall/rosws command to generate suitable setup.*sh files, as well as provide VCS operations over many projects. Each project folder was also used as build space, so only one build space existed per package.
With catkin, each build/configure process is strictly limited to a single workspace folder which must contain a cmake file provided by catkin to guide the configuration process. The build and configuration processes must be launched from a specific folder (or passing that as an option), it is not trivially possible to build all targets of a single package and its dependencies only. Since catkin separates build space from the source folder, it is possible to have multiple build spaces. Catkin also defines a devel space and an install space. Both refer to folders having generated setup.*sh files to source for using those spaces. This means rosinstall/rosws generated setup.*sh cannot be used anymore. The wstool command replaces rosinstall/rosws to only perform VCS operations.
These changes benefit developers with the need of multiple build spaces such as for cross-compilation purposes. The changes also allow a certain speedup of the compile cycle compared to both rosbuild or plain cmake.
The default catkin workflow relies on a single folder acting as a central source folder having a CMakeLists.txt provided by catkin. This calls a function that crawls this folder for catkin packages to build. This is different from rosbuild where the ROS_PACKAGE_PATH determined the list of locations to crawl for packages to be build. So locations are whitelisted with rosbuild via the ROS_PACKAGE_PATH. Locations are blacklisted instead with catkin (all packages found in src folder are used unless they have a marker file).
Overlaying is also different, as rosbuild relied on rospack to identify a single package out of multiple candidates with the same name to be used for build. This was done using the ROS_PACKAGE_PATH as first precedence and the earliest find crawling a single location in the ROS_PACKAGE_PATH as a second priority. catkin does not allow having multiple packages in the same location (src folder), but allows overlaying via chained workspaces. This kind of overlaying however is improper, as the overlay semantics are local to each workspace.
With rosbuild, a package was required to have a manifest.xml file and a Makefile, and typically also had a CMakeLists.txt file used by the Makefile. Developers declared certain build and generation steps in the CMakelists.txt file, dependencies were declared in the manifest file. To serve as dependencies, projects also had to declare export attributes in the manifest.xml file, which was error-prone and caused failures for cross-compilation. An install target was not required or supported.
Catkin still uses a manifest file for packages, but calls it package.xml. With catkin, no Makefile is used anymore, the CMakeLists.txt file is mandatory instead. To serve as a dependency, catkin auto-generates configuration files instead of using hand-crafted export flags. Developers are required to provide install targets in the CMakeLists.txt, meaning they have to specify which files are going to be installed and which files are not. This allows to drastically reduce the size of downloads/updates for ROS packages.
The ROS-specific macros used in the CMakeLists.txt files have changed between rosbuild and catkin in both name and structure, migration must be done manually with only limited tool support possible.
The package.xml and mainfest.xml files have a different syntax.
Those changes were mostly required to achieve the design goals. Developers benefit from the auto-generation of configuration files, users benefit from the increased portability of ROS packages.