9

I'm distributing a module which can be imported and used as a library. It also comes with an executable—installed via console_scripts—for people to use.

That executable can also be started as a systemd service (Type=simple) to provide a daemon to the system.

systemd services need to refer to absolute paths in their ExecStart lines, so I need to figure out where the console_script got installed to.

With other build systemd like CMake, autotools or Meson, I can directly access the prefix and then use something like configure_file (meson) to substitute @PREFIX@ in foo.service.in, and then install the generated unit to $prefix/lib/systemd/system/.

I just can't figure out how to do this with setuptools. Inside setup.py, sys.prefix is set to python's prefix, which isn't the same thing. I have tried overriding install_data and install, but these approaches all have various problems like breaking when building a wheel via pip, or leaving the file around when uninstalling. (I'd be OK just not installing the service when we're not being installed system-wide; systemd wouldn't be able to find it if the prefix is not /usr or /usr/local anyway.)

Someone pointed me at a website which says that you're not supposed to do this with setuptools:

Note, by the way, that this encapsulation of data files means that you can't actually install data files to some arbitrary location on a user's machine; this is a feature, not a bug.

Which sounds like I'm just going against the grain here. I'm really looking for pointers or examples to tell me what I'm supposed to be doing here. If that's "don't use setuptools", fine - but then advice on what the preferred thing is would be welcome.

Iain Lane
  • 176
  • 8
  • 1
    I would say don't use _setuptools_ for this, it's not what it's made for. Instead use the package manager for the target distribution (apt, rpm, flatpak, pacman, snap, etc.) – sinoroc May 18 '20 at 10:13
  • 1
    https://stackoverflow.com/a/58817117/7976758 – phd May 18 '20 at 16:28
  • @sinoroc Distribution packages invoke an *upstream* build system to cause everything to be laid out in the correct way. Are you basically telling me that I should roll the build system myself instead of using something that the Python community provides? In that case I will write a Meson build file, but I'd be re-inventing logic that e.g. setuptools already knows, and I'd lose pip installability for the module (the unit is *optional*), so it feels a bit sad. – Iain Lane May 19 '20 at 11:40

1 Answers1

6

I would say don't use setuptools for this, it's not what it's made for. Instead use the package manager for the target distribution (apt, rpm, flatpak, pacman, snap, etc.).

I believe systemd and such things that are specific to the operating system (Linux distribution, Linux init system) are out of scope for Python packaging, pip, setuptools, etc. Keep as much as reasonably possible under setuptools's responsibility, so that the project stays pip-installable, and so that the project itself provides easy way to get access to systemd specific files but don't install them (maybe with a command my-thing-generate-systemd-files --target path/to/output for example, that would simplify the task for the users of the project). And on the other side provide Linux-distribution-specific packages (deb, rpm, etc.), if I am not mistaken there are tools that allow to build such packages starting from the Python project (a sdist or the source code repository).

Some ideas (quick search without testing, not recommendations):

sinoroc
  • 18,409
  • 2
  • 39
  • 70
  • Mmm, if I could sensibly wrap the setuptools distribution to add the platform / system specific stuff on top that would make sense. It would then know what the prefix is to be able to generate the unit and call `setup.py` with the same prefix. I wonder what a nice way to do that is. Thanks for the answer! – Iain Lane May 19 '20 at 12:59