Skip to content

cabal new-install UI design concept (WIP) #4558

Closed
@hvr

Description

@hvr

Status


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_ENVIRONMENTs (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.projects 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)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions