bloom your ROS projects with the full power of
debhelper.
$ tree ~/my_catkin_ws
/home/user/my_catkin_ws
`-- src
`-- my_project
|-- CMakeLists.txt
|-- debian
| |-- TODO.em
| |-- control.em
| |-- cron.daily.em
| |-- logrotate.em
| |-- postinst.em
| |-- postrm.em
| |-- rules.em
| |-- service.em
| `-- udev.em
|-- etc
| `-- rsyslog.d
| `-- 99-slug.conf.in
|-- launch
| `-- main.launch
|-- package.xml
`-- src
`-- main.cpp
$ bloom-release --rosdistro melodic ...
...
$ # checkout release, gbp buildpackage
...
$ dpkg-deb --raw-extract ../ros-melodic-my-project_0.0.1_amd64.deb ./raw
$ tree ./raw
./raw
|-- DEBIAN
| |-- conffiles
| |-- control
| |-- md5sums
| |-- postinst
| |-- postrm
| |-- preinst
| `-- prerm
|-- etc
| |-- cron.daily
| | `-- ros-melodic-my-project
| |-- logrotate.d
| | `-- ros-melodic-my-project
| `-- rsyslog.d
| `-- 99-ros-melodic-my-project.conf
|-- lib
| |-- systemd
| | `-- system
| | `-- ros-melodic-my-project.service
| `-- udev
| `-- rules.d
| `-- 60-ros-melodic-my-project.rules
|-- opt
| `-- ros
| `-- melodic
| |-- lib
| | |-- my_project
| | | `-- my-project
| | `-- pkgconfig
| | `-- my_project.pc
| `-- share
| `-- my_project
| |-- cmake
| | |-- my_projectConfig-version.cmake
| | `-- my_projectConfig.cmake
| |-- launch
| | `-- main.launch
| `-- package.xml
`-- usr
`-- share
`-- doc
`-- ros-melodic-my-project
|-- TODO.Debian
`-- changelog.Debian.gz
You can bloom your ROS project (that thing you build with catkin)
into a Debian package archive (*.deb) that installs one (or more) of the
following:
systemdservice unitsudevruleslogrotateconfig filescronscripts- custom
copyright,README, and/orTODOdocumentation - more coming soon
Because you're a Debian package maintainer and you want to do one (or more) of the following:
- run your ROS application as a
systemdservice - use
udevto detect and configure new/custom/unusual hardware - rotate logs generated by your ROS application
- run your ROS application from a
cronscript - include a bespoke license
- more coming soon
Within your ROS project directory (where you keep the CMakeLists.txt and
package.xml), create a debian directory. Put your debhelper-compatible
files in there. Here's a sampling, showing where each lands after installation:
catkin_ws/src/my_project/debian/TODO -> /usr/share/doc/ros-${ROS_DISTRO}-my-project/TODO.Debian
catkin_ws/src/my_project/debian/cron.daily -> /etc/cron.daily/ros-${ROS_DISTRO}-my-project
catkin_ws/src/my_project/debian/logrotate -> /etc/logrotate.d/ros-${ROS_DISTRO}-my-project
catkin_ws/src/my_project/debian/service -> /lib/systemd/system/ros-${ROS_DISTRO}-my-project.service
catkin_ws/src/my_project/debian/udev -> /lib/udev/rules.d/60-ros-${ROS_DISTRO}-my-project.rules
There are really two mechanisms enabling this trick. The first is the manner by
which bloom populates the debian directory of the released package. The
second is the fallback behavior in debhelper.
As of bloom 0.5.13, you can supply files in a "debian" folder in your package, and the various debhelpers, including dh_installudev will pick them up.
-- mikepurvis, answering himself,
https://answers.ros.org/question/133966/install-directly-to-etcudevrulesd/?answer=212041#post-id-212041
As of this writing, the latest release of bloom is 0.8.0
(c247a13)
and the mechanism to which mikepurvis alludes is implemented within
bloom/generators/debian/generator.py, in and around the function
place_template_files:
During the execution of bloom-release, place_template_files will copy the
debian directory from the catkin project (thing being bloomed) to the
"Debianized release" (thing being generated). The copied contents are combined
with various
templates
and then the process of template expansion begins.
Template files have a *.em suffix and any *.em file found in the debian
directory will be expanded using empy. For each template file, empy
replaces any variable reference with the associated value and writes the
expanded result into the .em-suffix-stripped filename. For example, a
template foobar.txt.em would be empy-expanded to produce
foobar.txt. bloom-generate explicitly defines the set of variable-value
pairs empy will use. The following is a partial enumeration of those
variables:
@(Copyright)@(DebianInc)@(Description)@(Distribution)@(Homepage)@(InstallationPrefix)@(Maintainer)@(Package)
bloom-generate tacitly assumes you will use debhelper to build your Debian
packages --- it uses a debian/rules.em template that explicitly invokes
dh. In any case, the resulting expansions are committed to the "release"
(almost always a bare git repository) from which the Debian packages can be
built.
When debhelper goes looking for files, it searches under the debian
directory. Some of these files are required. Other files are
optional. For most of the optional files, each has within its
basename (usually as package. prefix) the name of the package to which it
belongs. Consider the following examples for the fictitious package foo:
debian/foo.init: init script, installs to/etc/init.d/foodebian/foo.cron.hourly: hourly cron job, installs to/etc/cron.hourly/foo
Additionally, and crucially, debhelper also uses other files:
Note for the first (or only) binary package listed in debian/control, debhelper will use debian/foo when there's no debian/package.foo file. However, it is often a good idea to keep the package. prefix as it is more explicit. The primary exception to this are files that debhelper by default installs in every binary package when it does not have a package prefix (such as debian/copyright or debian/changelog).
-- http://man7.org/linux/man-pages/man7/debhelper.7.html, "Debhelper Config Files" section
This association to an implicit package name is useful when, say, you don't
actually know the name of the package for which you want to install
artifacts. This is exactly the case for ROS packages targeting a Debian-like
OS. The Debian package name is of the form ros-${ROS_DISTRO}-catkin-project
and the ${ROS_DISTRO} could be one of several identifiers through which
bloom-release iterates. The quantity and nature of package names is known to
the maintainer only after the bloom succeeds.
-
In the case where you have both a
debian/fooand adebian/foo.em, the expansion of the latter overwrites the former. -
The example
rsyslogfilter rule file is acmaketrick, not adebhelpertrick. It's there to illustrate how such a thing would interact withdh_logrotate.
This repository was borne out of a question I asked on ROS Answers: https://answers.ros.org/question/331528/how-to-bloom-with-init-system-integration/
Thanks to @mikepurvis who, back in 2014, asked --- and then
answered --- the question about the proper way to install a udev rules file.
Thanks to @gvdhoorn, both for pointing me toward the already-answered questions relevant to mine, and for discussing various shortcomings inherent to my approach.
Thanks to @nuclearsandwich for the insight into, and explanations for, some little-known ROS package conventions.