#Packaging Question - How should I prepare directories? General guidance for packaging requested

16 messages · Page 1 of 1 (latest)

fair storm
#

I'm looking to finalize a few programs I've made and make a PKGBUILD for them for distribution. But after reading both https://wiki.archlinux.org/title/Creating_packages and https://wiki.archlinux.org/title/PKGBUILD I've still got a few questions relating to how to approach directory structure. I have some ideas and general direction for how to answer these questions, but I think it'd be best to get as much guidance here as possible:

  1. Where should my applications store a db file? Should it be located in ~home/.config or is there a better directory for it? It is always user specific.
  2. Should config files be under ~home/.config/<package_name>/config.extension? The use case here would never have shared global configs for multiple users, so should I bother falling back to /etc/<package_name>/config.extension?
  3. The application binary belongs in /usr/bin/<binary_application> I'm guessing?
  4. For all of these prior questions, do environment variables ever influence or change these points? In other words, can an environment variable ever change where config files are located for the user (eg: instead of in ~home/.config the environment variable specifies /mnt/.config?)
    4a. How should my program handle environment variables beyond reading the home env var for the current user? I'm not asking for specific implementation, but for what env vars I should be interested in using/paying attention to?
    4b. If I don't need to pay much attention to environment variables per Q4/Q4a, do I then just hardcode the expected directory paths (minus user specific paths which have to be built at runtime) in my application? Eg: I check for user home config file, then check for /etc/ config file, then create a default config in the home directory? Does this need to interact with the PKGBUILD in any particular way, other than in the prepare() and package() sections, where I'd basically just be uncompressing to X directory?

Thank you very much for any help!

hexed geyser
# fair storm I'm looking to finalize a few programs I've made and make a PKGBUILD for them fo...

The best reference for what directories the PKGBUILD should install to is: https://wiki.archlinux.org/title/Arch_package_guidelines#Directories. Also, there's language specific guidelines pages linked at the top of this page.

For your upstream program, I'd recommend following the XDG Base Directory spec: https://wiki.archlinux.org/title/XDG_Base_Directory (full spec here: https://specifications.freedesktop.org/basedir/latest/), essentially it says that your program should first check if the user has defined the environment variables (ex: XDG_DATA_HOME), if so use that, if not then use the default directory (ex: $HOME/.local/share).

  1. $XDG_DATA_HOME/<program name>/data.db
  2. $XDG_CONFIG_HOME/<program name>/config.ext for user specific configs. If there should be a system-wide config, it should go in /etc/<program name>/config.ext
  3. Yes.
  4. Your program should respect the XDG dir environment variables or use XDG's defaults
    4a. Not sure about anything beyond XDG user directories env vars.
    4b. respect XDG env vars, if you have a config file with defaults that should be system-wide, the PKGBUILD should install that to /etc/<program name>/config.ext and then use backup: https://wiki.archlinux.org/title/PKGBUILD#backup for that config file. If it doesn't make sense to have a system-wide config with default values for users to edit, creating a user-specific config in XDG config home on program's first launch would be a good approach.

The PKGBUILD should never touch the user's home directory or any of the XDG user dirs I mentioned before. package() should use install commands to put files in $pkgdir

fair storm
#

Thanks, I think that's exactly what I wanted!

Weirdly enough however, I don't have an XDG_DATA_HOME nor an XDG_CONFIG_HOME on my desktop. I do have an XDG_CONFIG_DIRS which has multiple paths, and one of which is my ~home/.config, and an XDG_DATA_DIRS which has multiple paths, one of which is /usr/share, but I'm not sure how I'd reliably pick the correct path from those anyways. Is it unusual that my desktop doesn't have these XDG Base Directory environment variables? I think the Wiki mentions that all but one aren't set by default on Arch if I'm reading it right, so I guess this is fine.

I guess I should just have a default fallback path to the defaults listed in the XDG Wiki page if I can't find the variables. Thanks!

#

I guess that does raise one question though - what's the best way to reliably find the home path for the fallback default? I have a $HOME variable on my system, but is that going to be consistent for others? I don't know if ~ will work from a filesystem call in my application, I guess I could test it.

#

I'm thinking $HOME is going to be much more standardized and should be safe to use as a fallback, but just wanted to double check.

hexed geyser
hexed geyser
fair storm
#

Awesome, thank you very much!

hexed geyser
#

you're welcome! if you want to show me your PKGBUILD, i'd be happy to review it

fair storm
#

Thanks! I'll keep that in mind. Still preparing that directory structure within my program, I think I'm just wrapping up.

Another question, should my application or the PKGBUILD be responsible for creating directories eg $HOME/.config/<package_name>/config.ext? I'm assuming the config file is user provided and not something I'm generating in the application if it doesn't exist (currently at least).

Then there's some static files which need to be provided as well. I would assume all of these directories are created by the PKGBUILD since it's responsible for moving the files to said locations, but I was curious if my program should be responsible for creating the directories if they don't exist for some compatibility reason.

#

I see that install -Dm xxx is pretty common and I see that -D is creating all directories up to the last point, so I see that the PKGBUILD creates them there of course.

hexed geyser
# fair storm Thanks! I'll keep that in mind. Still preparing that directory structure withi...

the PKGBUILD should only create directories in $pkgdir, and in pkgdir only create files in root directories /etc, /usr, etc. It's up to the application to create $HOME/.config/<package_name>/config.ext.

your app could automatically create the user's config (and leading directories if they don't exist) with default values, or leave the defaults internal and document them on manpage or doc somewhere, and let the user create the config.ext based on reading doc about options there are. This is up to your preference, whatever you want to do. (I personally like it when apps I use create an example default user config, but that's my opinion)

not sure what static files you mean, but follow https://wiki.archlinux.org/title/Arch_package_guidelines#Directories. the PKGBUILD should install to the directories in the table, and should not install to any of the directories in the list below.

fair storm
#

The inability to install to a user's home seems extremely arbitrary and restrictive. It makes me want to not use the user's home directory for my config and files since I can't manage this in the system installer, even though the config is 100% per-user.

How am I even supposed to install a directory with install? -d doesn't seem to work, so it looks like mv or cp are my only options. I'm just trying to put my binary and static files in my pkg fakeroot via package() , and all advice says to use install and not mv or cp, yet nothing seems to cover installing a directory.

hexed geyser
# fair storm The inability to install to a user's home seems extremely arbitrary and restrict...

Installing in a user’s home would break the ability to ship the package to anyone, the complete .pkg.tar.zst would be host-specific and break reproducibility (two people running makepkg should get the same package). Packages are also built as fakeroot, so a user would have the apps files owned by root. There’s also no way to know which user(s) should receive the files at build time, and there’s no way to know if any users even exist on the system that’s building it.

For install -d, it creates the target directory and all leading components (https://man.archlinux.org/man/install.1#d). So it would typically look like: install -dm755 "$pkgdir/usr/share/$pkgname", and this creates just the directory. Installing single files is typically done with install -Dm755 bin/$pkgname "$pkgdir/usr/bin/$pkgname" (https://man.archlinux.org/man/install.1#D).

If you have a lot of single files in one directory, it’s cleaner to create the dir with install -d and then use cp -a "$srcdir/something/"* "$pkgdir/usr/share/$pkgname" (https://man.archlinux.org/man/cp.1#a), for example: https://gitlab.archlinux.org/archlinux/packaging/packages/upterm/-/blob/main/PKGBUILD#L41-L42.

fair storm
#

Installing in a user’s home would break the ability to ship the package to anyone, the complete .pkg.tar.zst would be host-specific and break reproducibility (two people running makepkg should get the same package). Packages are also built as fakeroot, so a user would have the apps files owned by root. There’s also no way to know which user(s) should receive the files at build time, and there’s no way to know if any users even exist on the system that’s building it.

Why would this matter for an AUR package where these paths are determined after the PKGBUILD is processed? Why can't these directories be handled by envvars just like my program is supposed to? If home doesn't exist it should fall back to system level directories - there's no technical reason that can't be determined in the PKGBUILD. Ownership could also surely be set.

The inconsistency of using install for single packages and then install + cp for groups is really not intuitive at all, I really don't understand why install can't install a directory just as it does a single file with or without an additional flag.

hexed geyser
# fair storm >Installing in a user’s home would break the ability to ship the package to anyo...

If you were to handle user home paths in the PKGBUILD, how would you handle if multiple users on the same system wanted to use it? Only the user that makepkg’s it would have the directories. For ownership, I don’t think there’s a reliable way to know their uid and $HOME might not be set in the subshell/fakeroot environment (I’m not sure as I’ve never tried this since this is not how it should be done)

Your upstream program can for sure default to user config, then fallback to a system config, but the user config really has to be created by the program itself.

For install, idk why the GNU programmers didn’t write a way to copy a whole directory. They just decided not to, so cp is commonly used