haskell / cabal

Official upstream development repository for Cabal and cabal-install
https://haskell.org/cabal
Other
1.62k stars 691 forks source link

How to correctly install a locally-built library in Cabal 3? #6478

Closed acrylic-origami closed 3 years ago

acrylic-origami commented 4 years ago

I'm having difficulties installing and using a library built from source. It's likely just a documentation/my understanding issue, but to do the following:

  1. Build a cabal library package from source that depends on other [Hackage] cabal packages;
  2. Install the package into either the user or global package db;
  3. Depend on the package in another project on the same machine.

I could only find one working method that I cannot believe is the Right Way:

  1. runhaskell Setup.hs configure --global; must be global. User installs aren't found by other projects (which I don't understand).
  2. For all Hackage dependencies, manually register them into the global package db. That means ghc-pkg register --global /path/to/user/package.db/package-name.conf.
    • This was needed because setup build was failing with "Encountered missing dependencies". I saw the call it was making to discover packages was /usr/local/bin/ghc-pkg dump --global -v0, where the package (installed by cabal install --lib) was missing. Trying to install with cabal install --global --lib package-name still doesn't show up in ghc-pkg dump --global.
    • This is the main pain point for this otherwise documented workflow. Should Hackage packages be registered by default to the global db? Alternatively, should Setup look in the user package db too?
  3. runhaskell Setup.hs build
  4. sudo runhaskell Setup.hs install
  5. Include the package elsewhere in build-depends as usual.

This is with Setup as Distribution.Simple.defaultMain on GHC 8.6.5 and Cabal 3.0.0.0. GHC 8.4.2 + Cabal 2.4.0.0 surprisingly works with a simple cabal build; cabal install;, so maybe it's a version thing?

Any other combinations seem to fail. In particular, the intuitive cabal new-install --lib: the package isn't found in ghc-pkg list nor cabal list --installed and is an "unknown package" to other libraries. Interestingly, trying to use the package via -fplugin without build-depends will instead say that it's a hidden module of our library.

In case this is rare workflow, at least to develop source plugins it's a vital one. This way, I don't have to specify a source-repository-package and build it again and again in every codebase I analyze, or upload it to Hackage for every edit I want to test.

andreasabel commented 2 years ago

Personally, I never use the runghc Setup.hs method, I want to work at the abstraction of the package manager cabal. Also, this would require a download first (cabal get) with the trouble of manually deciding on a download location. cabal v1-install allows me to skip all that.

Mikolaj commented 2 years ago

Thank you. Let's hope v2 gets enough functionality at some point to retire v1.

ivanperez-keera commented 1 year ago

I have a dream: the current cabal leadership convenes and decides where to put the marvelous text above in the user manual.

Also, I whole-heartedly support suggestion to avoid v1-install at all costs. Even if this requires you to learn a field or two of cabal.project or how GHC environments work. This is easier than it sounds. v1 is legacy and should be expelled imo.

Note that this means we need to teach cabal and GHC environments to newcomers, including people who only intend to use an eDSL that happens to be embedded in Haskell.

Since DSLs are one of the main use cases of Haskell, I think we really need to support using runhaskell without having to create a cabal.project exposing a bunch of libraries that users know nothing about. Having to learn cabal or GHC environments at a deeper level is ofc out of the question if we mean to support such use cases.

I never use the runghc Setup.hs method, I want to work at the abstraction of the package manager cabal.

I use cabal v1-exec -- ghc Code.hs all the time (also with ghci and runhaskell). It exposes all packages installed (in the local dir or in my $HOME or globally, depending). For quick programs and especially for the use case I was talking about above, it's absolutely great.