I've made some small additions (for v9.3 and later) to raco pkg that I hope will help package management and cooperation with OS package managers. There's not one big idea here, but a bunch of little adjustments to potentially make things easier.
Improving installable-package creation (from installed to installable)
Installing into user scope to gather and compile packages is the way things are supposed to work, at least as the first step, and using racket -A is a good way to direct the output. But a user-scope installation directory is not always the right shape as the source for another installation, particularly when rendered documentation is included. Using raco pkg create --built --from-installed is the intended way to get from a user-scope installation to an installable package.
New pieces to help:
-
raco pkg create command can now create any number of packages at a time, instead of just one.
-
raco pkg create --format dir, which amounts to a shortcut for staying in directory mode, if that's useful. Along those lines, pkg/dirs-catalog recognizes checksum files that are created by --format dir; it's not clear that the checksums are important for the immediate goal, but having them closes a small consistency gap.
-
raco pkg create --adjacent-deps infers additional packages to create based on the dependencies of specified packages and directories that are siblings on the specified ones. This can reduce the need to manually list relevant packages.
It would be nice if raco pkg install --destdir <dir> (described in the next section) could do all of this itself. But the raco pkg install would have to restart Racket with -A, and while that doesn't seem so bad for command-line, it would be weird for the Racket-level API to do the same thing. So, I didn't try to merge the steps that way.
Improving package staging (from installable back to "installed" as staged)
After installable packages area available, they need to be put in a format to be added to a Racket installation.
New pieces to help:
-
raco pkg install --destdir <dir> stages a package installation (potentially with dependencies) into <dir>, instead of installing into the current Racket instance. If staging uses all the packages originally created by raco pkg create --format dir, then it turns out that the staged directory will be a copy of that one. In principle, though, this step converts from "installable packages" to "packages in installed form". Also, raco pkg install --destdir can potentially be used to follow dependencies (aided by a catalog or --adjacent-deps described below) to arrive at the right set of packages.
-
setup/doc-to-destdir supports moving rendered documentation within --destdir output to a separate directory, so that rendered documentation can be set up for copying into the final "doc" destination. Otherwise, the "packages in installed form" will still be modified further by raco setup to move documentation into the central "doc" directory. Of course, this step is not needed if documentation isn't being rendered.
Without docs, "installed" for user scope and "installed" for installation scope are currently the same shape, so it's tempting to skip the back-and-forth. But back and forth (with adjustments, sometimes) is how it's supposed to work.
Improving installation into an exsting Racket tree (from staged to really installed)
Assuming that we have the right packages (and perhaps documentation) staged, and there's no conflict with existing files in the Racket installation, we can to write the packages into the installation and link them. Although no files should be overwritten at first, linking will need to update files in the Racket installation: "share/info-cache.rktd", "share/links.rktd", "share/pkgs/pkgs.rktd", and similar documentation-related indices and regenerated entry points.
New pieces to help:
-
raco pkg install --attach is an alternative to --link when the relevant package directories (and, optionally, documentation) are already in place. The intent is that packages created via --destdir have been copied into the installed-package directory by the time --attach is used. This new --attach mode installs the package as if they came from a catalog, which means that each package can carry along a checksum and connect to an original source repo.
-
raco pkg install --adjacent-deps can discover dependencies without relying on a catalog. This isn't needed if all packages can be listed.
-
raco pkg install --no-promote is for the case when all packages are listed, but when there's one package that should count as explicitly installed and others are installed only as dependencies (so that raco pkg uninstall --auto on the main page can remove all of them). The --no-promote flag attaches all listed packages as auto-installed dependencies. After attaching all packages, the main one can be promoted to explicitly installed using raco pkg install --skip-installed, which is documented as promoting an auto-installed package, and has been changed to not require the original package source to be written again.
Improving installation into a separate tree (staged to really installed)
Suppose that we don't want to write package files into the Racket tree and instead keep them separate. We'll install the package in --link mode --- so, still updating some files in the Racket installation, but not adding new ones. Maybe we're doing that because there's a potential for conflicts, so we only want to link packages that are not already installed.
New pieces to help:
-
The --adjacent-deps flag can be used with --link more as well as --attach. Since dependencies will be searched only if they are not already installed, this can help avoid conflicts.
-
When listing all packages, combining --skip-installed with --no-promote solves a similar problem with --link as it solved with --attach: even though the packages to link are enumerated, they are not all made explicitly installed, and auto-installed existing packages are skipped the same as explicitly installed existing packages.
Putting the pieces together
This revised makefile for Rhombus (should work with the next snapshot, at least) shows how many of these pieces are meant to be put together: