-1

Situation

Software author wants to add zsh completion to his project. Has written completion script, works.

Needs to figure out where under $CMAKE_INSTALL_PREFIX to install so it gets found by default.

Problem

Testing Fedora 34 against Ubuntu 20.04, it was found that the only common member of $fpath is /usr/local/share/zsh/site-functions; none of the /usr/share fpaths overlap. Especially, Ubuntu does not read /usr/share/zsh/site-functions.

So, I can't just install into $CMAKE_INSTALL_PREFIX/share/zsh/site-functions, because that only works for $CMAKE_INSTALL_PREFIX==/usr/local, but not later in packaging ($CMAKE_INSTALL_PREFIX==/usr). I'd argue this is a Ubuntu inconsistency, but that doesn't effectively matter.

Question

Is there a sensible way to figure out at CMake time where to put completion scripts?

Note that CMake is not usually run from zsh, so checking $fpath is not an option.

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
  • "Note that CMake is not usually run from zsh, so checking $fpath is not an option." - Inside CMake script you could run (via `execute_process`) `zsh` and pass it some script or code. That script (code) would e.g. print `$fpath`. Then (in CMake script) you could test printed value against some patterns, and make appropriate choice for where to install files in your project. – Tsyvarev Nov 11 '21 at 11:58
  • hm, true, @Tsyvarev, but that feels *a lot* like I'd rely on a user's ZSH configuration (which might add a lot to fpath that's not in there system-wide), so if I'm completely honest, I'd prefer to not do that. But the idea isn't bad, I could do something like `zsh -dfi -c '...'` or so to get a better feeling for what's there. Still, there's going to be a lot of regular expression application and guessing which of the resulting paths is appropriate, and that's not really "sensible", I guess :/ But it's the best lead I've got so far, thank you! – Marcus Müller Nov 11 '21 at 12:02
  • I don't understand your considerations about `CMAKE_INSTALL_PREFIX` being equal to `/usr` or `/usr/local`. Generally, if a project is configured with `CMAKE_INSTALL_PREFIX` equal to `/usr`, then it is intended to work **only if** installed according to that prefix. E.g. if you configure the project with prefix `/usr`, but (manually) place resulted files according to prefix `/usr/local`, the project is not intended to work. A packaging is some sort of installing a project into **other machine**. Only location of files on that other machine which matters. – Tsyvarev Nov 11 '21 at 12:04
  • @Tsyvarev exactly! So, if I set the prefix to `/usr`, I mustn't install things under `/usr/local/share/zsh/site-functions`, but under `/usr/share/site-functions`, right? Problem is, that one isn't used on Ubuntu. It's inconsistent: the default fpath on Ubuntu doesn't look at the same directories under /usr/local as under /usr. – Marcus Müller Nov 11 '21 at 12:08
  • When a project is packaged for a standard project manager, it is passed an installation prefix. That installation prefix is **distro-specific**: E.g. they could use `/usr` for Fedora and `/usr/local` for Ubuntu. This is why `zsh` is configured for use different `$fpath` on different distros. (Aside from the installation prefix, some other directories from [FHS](https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard) could be distro-specific too.) So for build the completion project for Fedora, you need to configure it with use prefix `/usr`, but for Ubuntu you need to use `/usr/local`. – Tsyvarev Nov 11 '21 at 13:06
  • @Tsyvarev that's incorrect. For Fedora, I don't "need" to use /usr, and for Ubuntu I don't "need" to use /usr/local. Both distros' packaging guidelines explicitly forbid using /usr/local when packaging something! The question is also about something else, namely, how do I figure out which path to *use* given that I have a prefix specified by the user (or using the default prefix). – Marcus Müller Nov 11 '21 at 14:11
  • Prefixes `/usr` and `/usr/local` was just an example, which seems to be not good. Technically, if your project zsh completion provides some **files for other project** (zsh), then installation of these files is NOT affected by `CMAKE_INSTALL_PREFIX` of your project. This installation is affected by **parameters** for that **other project**. E.g. zsh has parameter `--enable-site-fndir=`, which is responsible for location of `site-functions/` directory. According to [that answer](https://unix.stackexchange.com/a/26558), exactly this directory is intended for functions of 3d-party packages. – Tsyvarev Nov 11 '21 at 15:44
  • 1
    From my understanding, parsing `$fpath` of zsh and finding a directory ended with `/site-functions` would be the most reliable way for choosing directory for your files. You could also provide a parameter (say, `ZSH_SITE_FUNCTIONS_DIR`) which allows the user to redefine automatic selection of the directory. – Tsyvarev Nov 11 '21 at 15:48
  • that's a pretty good suggestion, thanks! – Marcus Müller Nov 11 '21 at 15:56
  • You could have multiple copies of zsh installed. Trying to run it and parse out $fpath is just a mess. People will end up needing to disable that when creating packages with fixed paths. `--enable-site-fndir=` is analagous to things like `--mandir=`. `--enable-additional-fpath=` was added to make it easier to add things like `/usr/local/..` which on Linux tends to be left for the local system administrator. That does mostly get used so will work for local sys admin installs of gnuradio to `/usr/local` – okapi Nov 11 '21 at 19:38

1 Answers1

2

$CMAKE_INSTALL_PREFIX/share/zsh/site-functions is the right place.

It is the same with man pages, info pages, pkg-config path, binaries and libraries and whatever else. On a default install, man will only look in predefined places like /usr/share/man and /usr/local/share/man.

If someone decides to install to /opt/gnuradio or whatever, it is then also their responsibility to ensure that they set $PATH, $MANPATH $INFOPATH and whatever else accordingly. It is the same for $fpath. The best software can do is ensure that they stick to established conventions and not to spew files elsewhere on the filesystem outside of $PREFIX.

If Ubuntu wants to be clever and invent their own vendor-completion directories then a consequence of that is that is that they need to patch everything they package that includes a zsh completion. That's their problem because they created the problem for themselves.

okapi
  • 1,340
  • 9
  • 17