Description
Status
- Executables
- Local
- Nonlocal new-install: nonlocal exes #4825 (see also new-install symlink location #5000)
- Libraries
- Local
- Nonlocal
There's at least two axes for use-cases which need to be considered for the UI design: Most importantly is the distinction between
- making executables available
- making libraries available in
GHC_ENVIRONMENT
s (for GHC 8.0.2+)
And then sources can be distinguished by being either
- Non-local packages
- Local packages/projects
With the new nix-store paradigm, the idiomatic way to "install" things would be to first populate the requested target in the nix-store, and install a reference to the materialised artifact in a "view" (this signficantly differs depending on whether it's an executable or a library).
In this paradigm, the "installation" rather refers to installing a symlink or adding a reference to a package-env, than to build the actual artifacts. In some cases, all a cabal new-install
operation does degenerates into replacing the target of an existing symlink (e.g. if you first "install" alex-3.2.0
, and then you install alex-3.2.1
, and then decide to install alex-3.2.0
again; the 3rd operation would merely update the symlink, as the store would already contain both versions of alex
)
Basic UI
The basic UI would look like
$ cabal new-install <build-target-spec> [<install-location>]
(NOTE: as of #4825, the syntax is cabal new-install [--symlink-bindir=<install-location>] <build-target-spec>
)
A build-target would be something like
Omission of <install-location>
would denote a default location.
For libraries the default would be the current value of GHC_ENVIRONMENT
, or otherwise the default
environment (this matches the ghc-env lookup logic of GHC 8.0.2+).
For executables, the install location denotes a bin
folder; by default this would be the value configured in ~/.cabal/config
(e.g. ${HOME}/.cabal/bin
) or possibly in the in-scope cabal.project
.
Executables
Non-local packages
Installing executables from non-local packages is the easiest case; in fact, this can be emulated already now via script like https://gist.github.com/hvr/c77c54d682555b7dd4fe1248732fe978
Which first causes the requested executable to be materialised (if it wasn't already cached) in the nix store via a dummy package description containing build-tool-depends: ${PKG}:${EXE}
, and then
locates the resulting executable to install a symlink to the desired folder-location.
Local packages
This case is currently less straightforward when the non-local components have associated package-data (#4120).
However, this use-case is quite important, e.g. when a cabal project is embedded into a larger build-system which needs to invoke cabal to make available some "local" executable to the rest of the
build-system, then such a project is often just part of the source-tree and as such comprised of local
unpublished) packages.
Libraries
Libraries are a bit more complicated, as package-environments should ideally represent views into the nix-store providing a flat consistent install-plan where each package exposed shall be compatible with each other package in the same view.
The simple case is when creating a new package-environment, and specify /all/ libraries to be installed therein upfront. This is the known situation as handled already by cabal new-build
via build-depends
speecifications.
However, cabal new-install
should also support installing new packages into an existing view in an incremental way. But this means that if we may get into a situation where the "old" cabal install
would warn about running into a "reinstall"-situation.
One way to design the UI would be to ask the user whether we should try to resolve, and come up with a new consistent monolithic install-plan for the set of packages that were already available in the package-environment plus the newly to be added packages.
This would take into account the original version constraints imposed if there were any specified for the pre-existing packages. We may need something like per package-environment "world" files, to basically
keep track of an incrementally growing list of build-depends
lines (and also possibly constraint
-lines and other flags such as profiling levels). This way the user could have control over the package environment in a direct way by editing the world-files in order to manually resolve hard conflicts.
Non-local packages
To some degree, this could be emulated right now with an external shell (similiar to the executable-install-case mentioned above) by using a dummy .cabal
file where the requested libraries are
specified via build-depends
, and the automatically resulting .ghc.environment.*
file which is copied over to the package-environment specified as the install-location.
Local packages
For one, parts of this is already automatically provided by the automatic creation of .ghc.environment.*
files, but you'd currently need to manually copy them to their <install-location>
. But this would also be limited to single cabal.project
s currently.
This is more complicated just as for the local executable case, as associated package-data of local libraries is not handled conveniently for this use-case currently (#4120).
TODO:
- describe how
extra-packages:
fits into this scheme (see this comment)