Is it possible to get cabal to
Download a particular package source, including all dependency packages sources.
At a later stage (when internet connectivity can no longer be relied upon) install these packages via cabal, from the locally downloaded files, automatically in the right order so that the desired package is build?
I know that you can use cabal unpack to view the source of a particular package, but I am not sure how to achieve above. Also note that in this post Can't get cabal update to work inside corporate network it was mentioned that this could be done, but the instructions were not specific enough for me.
cabal help | grep fetch:
fetch Downloads packages for later installation.
Example:
$ cabal fetch unbound
Resolving dependencies...
Downloading RepLib-0.5.3.1...
Downloading type-equality-0.1.1...
Downloading unbound-0.4.1.1...
Running cabal install unbound at a later stage won't require Internet access.
Related
I would like to download all the dependencies of my cabal project to my project directory/repository and force cabal to never use ~/.cabal/ and never download any new dependency from the internet. The downloaded libraries should be system independent (not include local paths etc.). Is this possible?
The idea behind this is, to copy the project directory to another (offline) system where the same ghc is installed and it should work out of the box.
According to the cabal docs, you can set active-repositories: none in your cabal.project or cabal file to put cabal-install in offline mode.
Then, you could create a cabal project and try to make all the dependencies that don't come bundled with GHC itself local packages. Clone them in your project folder and add them to the packages: section of cabal.project.
The problem with the above is that running cabal clean would require re-compiling all packages afterwards.
As an alternative, create a local no-index package repository in your offline machine, make it the only available package repository using active-repositories:, and put the sdist tarballs of all your dependencies there.
That way the dependencies will only be compiled once.
I'm trying to install aeson on GHC 9.2.1. I first ran cabal install --allow-newer --lib aeson, which failed when it got to building attoparsec. It turns out this problem is already fixed in their Git repo, but hasn't landed in a release on Hackage yet. I then did these steps to build a local version with the fix:
git clone https://github.com/haskell/attoparsec.git
cd attoparsec
cabal install --allow-newer --lib .
cd ..
That succeeded, but then when I did cabal install --allow-newer --lib aeson again, it tried to build attoparsec from Hackage again, and so failed again. How can I make cabal use what I just built and installed instead?
There are two main methods.
One is to create a cabal project that includes both the cloned version of attoparsec and the local packages that you are working on (packages that might depend on aeson). It could be as simple as
packages: attoparsec yourpackage
In fact, you don't even need to clone the repo, you could use the source-repository-package field instead.
Because local packages always take precedence over external ones, the repo version will be chosen when resolving dependencies.
This approach works well but has the disadvantage that if you use the patched attoparsec in many different projects, you'll have to reference and re-compile it each time.
Another approach is to create a local no-index package repository in your machine, give it priority over stardard Hackage, and put attoparsec's sdist tarball there.
You need to declare the extra package repository using the repository field of your global cabal config (the path to the config is displayed in the last line of cabal help). By default, there's only Hackage:
repository hackage.haskell.org
url: http://hackage.haskell.org/
To give the local package repository priority over Hackage, you need to use the active-repositories field, either in your global Cabal config or in a cabal.project file.
The advantage of this method is that you don't need to create a Cabal project, and that the patched version of attoparsec will only be compiled once (as if it came from Hackage).
I just upgraded to the latest version of cabal-install which is 1.20. I am not sure if it is related but cabal started fetching old versions of packages for some reason.
In my cabal file, all dependencies are specified without version numbers. So I believe, cabal should fetch the latest versions available unless there is a conflict, correct?
If I run cabal install --only-dependencies within a sandbox environment, cabal pulls all kind of rubbish and old package versions like mongoDB-1.2.2 instead of 1.4.4 and scotty-0.5 instead of 0.7.2. If I run a specific package installation like cabal install scotty then it fetches the latest version and all is well. So I have to install all dependencies manually to get the latest versions - one by one. Annoying. What is going on?
Google gives me no hits.
If there are some kind of changes in cabal, what is it? And how do I pull all the latest dependencies within a sandbox.
Thanks.
Some of your dependencies have upper bounds that are forcing the usage of older versions of a given package. One thing that might help is to start over. Delete your package repository (~/.ghc on linux machines), and keep a discipline to work entirely within sandboxes. Use your package manager to install stuff you need globally, sandboxes for your development projects, and you can avoid a lot of the reasons this problem crops up. That said, if you're truly depending on a project that hasn't updated its upper bounds, then you're stuck using the older packages, short of submitting a patch to the library author or switching to a different dependency.
So I'm trying to install a package with a big messy dependency set (gitit, in this case). A direct cabal install from hackage forces rebuilds of plenty of libraries I don't want to rebuild (having to do with constraints on text, constraints on network, constraints on parsec, etc.) I did the right thing, ran cabal unpack gitit, manually edited the .cabal file, and successfully put it through a cabal configure, cabal build cycle. So far, so good.
Now, I want to run a cabal install. In the good old days (last year), this would just install the already built binaries and files where they belong. However, now, running cabal install runs the dependency checker, which decides that all the packages that I'm building with don't use the same parsec, etc., and tries to reinstall them anyway! Even though I just ran a perfectly fine cabal build. What's the magic flag to turn this off and get the old, not-clever, and perfectly acceptable behavior?
Looking at the flags, there doesn't seem to be any indication of cabal install doing this. In times of yore, before cabal install and when you had to manually get your own packages, the incantation at the install stage was runghc Setup install --user after you had run runghc Setup configure --prefix=$FOO --user - perhaps this will work? Setup.hs will not automatically invoke 'build' when you tell it to 'install', if my memory serves correctly.
Now, for the future, if you want to avoid this entire nasty dependency hell, I would highly suggest you use cabal-dev which will sandbox your package installations and never touch your actual user/global package database, in this case you'd just do:
$ cabal unpack gitit
$ cd gitit-0.8.0.1 # latest hackage version
$ cabal-dev install
It'll properly download and install all the needed dependencies like cabal install, but it'll sandbox them by creating a ./cabal-dev directory containing a self-contained package database. It never touches your global or user package db in ~/.ghc/. cabal-dev effectively makes editing cabal files and dealing with the diamond dependency problems Cabal faces a thing of the past, the way cabal-install made manually downloading packages a thing of the past.
It also turns out that there is an --only flag that lets one build and install only that package, just as the ./Setup route does.
I've been provided with a Setup.hs file, along with another .hs file that contains the source code. Whenever I try to configure the install by the following:
runhaskell Setup.hs configure
I get the error:
Setup: At least the following dependencies are missing:
binary >=0.4.0 && <0.6.0, haskeline ==0.6.*
I've since installed these dependencies using cabal, but when I try to run the Setup configure command again, I get the same error. I'm completely new to Haskell - is there another step I'm missing after doing a cabal install before trying to run Setup again?
How did you install the packages? If you installed them with the --userflag, then you also need to configure with the --user flag.
You can verify that the packages are installed by running ghc-pkg list binary and ghc-pkg list haskeline. It will list the installed package versions matching that name along with where they are installed.