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:
systemd
service unitsudev
ruleslogrotate
config filescron
scripts- custom
copyright
,README
, and/orTODO
documentation - 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
systemd
service - use
udev
to detect and configure new/custom/unusual hardware - rotate logs generated by your ROS application
- run your ROS application from a
cron
script - 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/foo
debian/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/foo
and adebian/foo.em
, the expansion of the latter overwrites the former. -
The example
rsyslog
filter rule file is acmake
trick, not adebhelper
trick. 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.