I don't think there's a best practice, but there are trade-offs to consider. I try to keep a few potential use cases in mind when deciding how to organize the code:
- A user wants to build a few of your packages but not all of them.
- The maintainer wants to patch just one package.
- The maintainer wants to do a first release of each package.
- I want to test a set of changes across multiple packages before merging a pull request.
There are certainly other use cases, but I think these are the ones I run into most often. The two strategies in question are:
- to put related packages in the same git/hg repository or
- to put each package in a single repository.
For the first use case, the ROS tools make it easier to build only a few packages if they each come from different repositories. If they're all in separate repositories then the user can be provided with a .rosinstall
file or use the rosinstall_generator --upstream-development
command to get the packages they desire. If instead the packages share a repository with other packages the user doesn't want, then they need to get the common repository and then selectively disable what packages to build by using CATKIN_IGNORE
files or by clever us of the build tools, e.g. using catkin_make_isolated --only-pkg-with-deps <leaf package>
or catkin build <leaf package>
.
For the second use case, if you have one package per repository, then you can increment the version of each package individually. Releasing a patch release in the narrowest scope possible. If you combine packages into a single repository then you're required to have all packages share the same version number, which leads to you needing to increment version numbers of packages even when they do not have changes. This is required because conceptually there is no way to create a version tag, e.g. 0.1.0
, for the whole repository if packages don't have the same version. This is also why stacks
had versions and packages
did not in rosbuild
. If you can avoid extraneous new versions of packages it helps the build farm since we don't make use of the ABI versioning and a new version of a package requires all down stream packages to be rebuilt, even if nothing actually changed in that package. Also, unnecessary package version updates require the end-users to download the new .deb
files when they do apt-get dist-upgrade
, even though they didn't actually change. Later, if we start using ABI compatibility correctly, then some of the negatives from use case are mitigated, but I don't think that's likely to start happening since it requires structural changes the code and extra infrastructures, not just flipping a switch.
For the third use case, you can get a complication when trying to do a first release when packages share a repository but they have indirect dependencies on each other with intermediate dependencies in other ... (more)
Hesitate to post an answer (as that seems to discourage other contributions), but I've generally put things in one repository only if they should be versioned (released) in sync. Repos per pkg can become difficult to manage / complex for users (what is where?).