Cabal: Task: Implement `v2-install --bindir-method={copy,symlink}`

Created on 11 Jan 2019  路  10Comments  路  Source: haskell/cabal

There's at least two use-cases for having this code-path

  1. On Windows, symlink support requires extra configuration; file copying however works without trouble (but we might need to use "ADS" to store some metadata to support store garbage-collection) (see also #5748)
  2. When using Docker or other custom workflows, symlinks might easily break; there a way to copy instead of symlink is desirable as well (see e.g. #5628)

Currently, cabal already has support for two locations,

  1. --bindir=DIR
  2. --symlink-bindir=DIR

All that we need is the ability to configure which of those two locations to use; right now v2-install is hardwired to symlink and use --symlink-bindir

This task is about adding a new flag --bindir-method=... to v2-install (whose default ought to be configurable via ~/.cabal/config) which takes takes an enumeration of at least

  1. symlink, symlink into --symlink-bindir location; operation fails if it cannot be symlinked
  2. copy, copy into --bindir location; operation fails if it cannot be copied to target location

Optional (i.e. not critical for 2.4; can be done later): additionally, we might want a 3rd variant (maybe called auto) which tries to symlink, but falls back to copy if symlink fails (relevant for Windows; see also PR #5684 which tried to hardcode this scheme)

Finally, for the implied defaults (i.e. when there's no explicit default set via ~/.cabal/config) for bindir-method: we should have

  1. on non-Windows platforms: symlink
  2. on Windows: copy (or maybe the auto method, once it's implemented; however sticking to copy as default might result in more deterministic results)

Possible bikeshedding alternative:

  • --bindir-style
  • --bindir-policy (c.f. --overwrite-policy)
cminstall priority

Most helpful comment

the cabal 3.0 branch seems to have been cut but v2-install still seems to default to a non-working default on Windows. It's default seems to be symlink but there's no code to support symlinks in cabal so it all fails with

cabal.exe: Symlinking feature not available on Windows

All 10 comments

Update:

@fgaz's PRs (see #5870) have gone for using a new flag --installdir=DIR instead of --*bindir=DIR, and so the current draft entails to have the following install-flags:

$ cabal --help

...

    --overwrite-policy=always|never                      How to handle already
                                                         existing symlinks.
    --install-method=copy|symlink                        How to install the
                                                         executables.
    --installdir=DIR                                     Where to install (by
                                                         symlinking or copying) the
                                                         executables in.

Installs one or more packages. This is done by installing them in the store
and symlinking/copying the executables in the directory specified by the
--installdir flag (`~/.cabal/bin/` by default). If you want the installed
executables to be available globally, make sure that the PATH environment
variable contains that directory.

If TARGET is a library, it will be added to the global environment. When doing
this, cabal will try to build a plan that includes all the previously
installed libraries. This is currently not implemented.

For Windows, one could detect developer mode via the registry [1] or detect if the user has elevation rights [2] and on Windows Vista+, then symlinks would work, otherwise default to copy.

This way you don't need to fail the operation to determine if it supports symlinks or not.

One annoyance is that https://github.com/haskell/cabal/issues/4597 is still the case, so we'd store symlinks in a location that is being synched. I'm not sure if this will cause problems or not for network users.

Perhaps we really should fix this for v2-*.

[1] https://stackoverflow.com/questions/41231586/how-to-detect-if-developer-mode-is-active-on-windows-10
[2] https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-gettokeninformation

I think it would be pretty weird to have two different windows defaults that are picked via some "smart" policy. Imho it would be less confusing to end users for windows to always default to copy.

I think it would be pretty weird to have two different windows defaults that are picked via some "smart" policy. Imho it would be less confusing to end users for windows to always default to copy.

I disagree. The end-user doesn't and shouldn't care about which method is being used. copying is just simply slower. and it takes more space especially on a platform where we statically link binaries.

I don't see why it should matter to the end-user as long as it works and works consistently. We shouldn't punish Windows users with an inferior approach. Also "copying" as it currently is implemented in Directory goes through the GHC I/O manager (another limitation that posix apis have but not Windows for when moving files to another physical disk), so we hit another much slower path.

I personally think, users will be much more annoyed by having things be even slower.

What about opening a separate issue for adding an --install-method=auto which does the registry magic? I can't add that in #5869/#5870 since I do not have a windows machine and getting one / a vm would take a bit

Edit: Well, I could get a vps

the cabal 3.0 branch seems to have been cut but v2-install still seems to default to a non-working default on Windows. It's default seems to be symlink but there's no code to support symlinks in cabal so it all fails with

cabal.exe: Symlinking feature not available on Windows

Sounds like something we should try to fix in 3.0.0.1.

and what would be an eta on that? :-)

(btw congrats on 3.0.0.0 !)

2-3 weeks.

I opened an MR changing the default on windows: https://github.com/haskell/cabal/pull/6506

Was this page helpful?
0 / 5 - 0 ratings