Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

cabal install with and without -j use different Cabal libraries #1244

Closed
snoyberg opened this Issue · 20 comments

5 participants

@snoyberg

Using GHC 7.4.2 and cabal-install 1.16.0.2. When I run cabal install -j followed by cabal build in a project, the result is:

cabal: You need to re-run the 'configure' command. The version of Cabal being
used has changed (was Cabal-1.14.0, now Cabal-1.16.0.3).

However, cabal install followed by cabal build works fine.

@23Skidoo 23Skidoo was assigned
@23Skidoo
Collaborator

Possibly related: #1076.

@dcoutts
Collaborator

snoyberg tells me that he does have Cabal-1.16.0.3 installed (in both global and user dbs) so it's not simply a case of the Cabal lib available to compile the Setup.hs being different to the one that cabal-install is built against. So perhaps it is an issue with the setup-exe-cache.

@23Skidoo
Collaborator

@dcoutts
I'll try to reproduce this.

@23Skidoo
Collaborator

Couldn't reproduce:

$ cabal clean
cleaning...

$ cabal --version
cabal-install version 1.16.0.2
using version 1.16.0.3 of the Cabal library 

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.4.2

$ cabal install -j2
Warning: Error parsing config file /home/cabal-test/.cabal/config:61:
Parse of field 'jobs' failed (jobs should be a number): $ncpus
Warning: Using default configuration.
Resolving dependencies...
In order, the following will be installed:
HUnit-1.2.5.1 (reinstall)
Warning: Note that reinstalls are always dangerous. Continuing anyway...
Configuring HUnit-1.2.5.1...
Building HUnit-1.2.5.1...
Installed HUnit-1.2.5.1

$ cabal build
Building HUnit-1.2.5.1...
Preprocessing library HUnit-1.2.5.1...
In-place registering HUnit-1.2.5.1...

Trying to build a package that uses build-type: Simple also works fine.

@snoyberg

Does this happen with all packages or just sometimes? Maybe there's something peculiar to the package you're trying to build? From the code I see that this error happens when the version of Cabal that the package was configured with doesn't match the version that cabal-install was compiled with.

@23Skidoo
Collaborator

I can reproduce this only by using --cabal-lib-version, but the behaviour is correct in this case:

$ cabal clean
cleaning...

$ cabal install --cabal-lib-version=1.14.0
Warning: Error parsing config file /home/cabal-test/.cabal/config:61:
Parse of field 'jobs' failed (jobs should be a number): $ncpus
Warning: Using default configuration.
Resolving dependencies...
In order, the following will be installed:
HUnit-1.2.5.1 (reinstall)
Warning: Note that reinstalls are always dangerous. Continuing anyway...
Configuring HUnit-1.2.5.1...
Building HUnit-1.2.5.1...
Preprocessing library HUnit-1.2.5.1...
[1 of 5] Compiling Test.HUnit.Terminal ( Test/HUnit/Terminal.hs, dist/build/Test/HUnit/Terminal.o )
[2 of 5] Compiling Test.HUnit.Lang  ( Test/HUnit/Lang.hs, dist/build/Test/HUnit/Lang.o )
[3 of 5] Compiling Test.HUnit.Base  ( Test/HUnit/Base.hs, dist/build/Test/HUnit/Base.o )
[4 of 5] Compiling Test.HUnit.Text  ( Test/HUnit/Text.hs, dist/build/Test/HUnit/Text.o )
[5 of 5] Compiling Test.HUnit       ( Test/HUnit.hs, dist/build/Test/HUnit.o )
Registering HUnit-1.2.5.1...
Installing library in /home/cabal-test/.cabal/lib/HUnit-1.2.5.1/ghc-7.4.2
Registering HUnit-1.2.5.1...
Installed HUnit-1.2.5.1

$ cabal build
cabal: You need to re-run the 'configure' command. The version of Cabal being
used has changed (was Cabal-1.14.0, now Cabal-1.16.0.3).
@kosmikus
Collaborator

Steps to reproduce on my machine.

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.4.2
$ ghc-pkg list Cabal --simple-output
Cabal-1.14.0
$ ~/repos/cabal/bin/cabal --version
cabal-install version 1.16.0.2
using version 1.16.0.3 of the Cabal library 
  1. Create a directory issue1244 with a single file called issue1244.cabal that contains:

     name: issue1244
     version: 1.0
     build-type: Simple
    
     Library
    
  2. Go to that directory and say ~/repos/cabal/bin/cabal -j2 install.

  3. In the same directory, say ~/repos/cabal/bin/cabal build.

I cannot reproduce this with build-type: Custom.

@snoyberg

I've tried coming up with a reproducing case for when Cabal-1.16.0.3 is installed, but I can't quite figure out what the steps needed are. The one time I got it to happen this morning, the steps went something like:

  1. cabal clean the current folder
  2. Unregister Cabal-1.16.0.3
  3. cabal install -j
  4. cabal install Cabal-1.16.0.3
  5. cabal install -j
  6. cabal build

But even this doesn't seem to reproduce it reliably.

@23Skidoo
Collaborator

@kosmikus @snoyberg

Thanks! So it happens when you have cabal-instal-1.16, but not Cabal-1.16 installed. Will look into it.

@23Skidoo
Collaborator

@kosmikus I can reproduce this, but only with Cabal-1.16. With the TOT version, however, I get a different error:

$ cabal build
Configuring with default flags. If this fails, please run configure manually.
Resolving dependencies...
Configuring issue1244-1.0...
Building issue1244-1.0...
Preprocessing library issue1244-1.0...
In-place registering issue1244-1.0...
cabal: issue1244-1.0: Warning: haddock-interfaces:
/home/cabal-test/issue1244/dist/doc/html/issue1244/issue1244.haddock doesn't
exist or isn't a file
issue1244-1.0: Warning: haddock-html:
/home/cabal-test/issue1244/dist/doc/html/issue1244 doesn't exist or isn't a
directory
issue1244-1.0: cannot find libHSissue1244-1.0.a on library path (use --force
to override)

which seems to be related to #1241.

I believe that the first error (the Cabal-1.16 one) is triggered by the fact that install -j2 always uses the external setup method. Since Cabal-1.14 is the only Cabal version installed, the setup executable is compiled against it and in dist/setup-config we get:

Saved package config for issue1244-1.0 written by Cabal-1.14.0 using ghc-7.4

However, cabal build uses the internal setup method (see determineSetupMethod in D.C.SetupWrapper), which then triggers the version mismatch error. With build-type: Custom the external setup method is always used, which explains why you couldn't reproduce it in that case.

I'm not quite sure what we should do here: the root cause of the problem is user configuration (the version of Cabal that cabal-install was compiled with isn't installed), and the error message looks fine to me. Will be looking into why a different error message is printed in the TOT version.

@23Skidoo
Collaborator

BTW, now that we support cross-compilation, shouldn't this line also include $arch and $os:

$ head -1 dist/setup-config
Saved package config for issue1244-1.0 written by Cabal-1.17.0 using ghc-7.4

?

@23Skidoo
Collaborator

@kosmikus Now that #1241 is fixed, your example works fine in TOT version. I think that @ttuegel's changes are responsible: we now reconfigure automatically if needed. Feel free to reopen.

@23Skidoo 23Skidoo closed this
@nh2
nh2 commented

I still have this problem. When I run cabal install in my packageA, it runs fine, but cabal install -j2 fails with some error and printouts that I put into my own branch of cabal days earlier. It seems that this version is stuck into some cache and invoked whenever I use -j2; I cannot get rid of it - git clean -fdx and cabal install in Cabal and cabal-install on cabal master do not help!

Questions:

  • How can I find out where the cabal is that it calls with -j2? Why does reinstalling cabal not override it?
  • Can you explain me what exactly the setup exe cache is good for and how it works?
@nh2
nh2 commented

Update: My problem went away with a cabal clean in packageA. In addition to my two questions above, could you explain what in packageA made the difference between calling two different cabals and where those are?

Update 2: My problem didn't go away at all, it was just that after a clean, cabal install -j2 hid the output. Looking at the log file, -j2 is still using that same old cabal version of which I don't know where it is ... what is going on?

@23Skidoo
Collaborator

@nh2 Remove the ~/.cabal/setup-exe-cache directory. The cause of the problem is that you are using an unreleased version of Cabal, but the setup exe cache code can't distinguish between "most recent Cabal-1.17" and "Cabal-1.17 of two days ago".

@nh2
nh2 commented

I still have problems with this:

After I cabal install from my cabal source code, ~/.cabal/setup-exe-cache/setup-Cabal-1.17.0-x86_64-linux-ghc-7.6.3 will be my system cabal, no matter what. Why?

~/.cabal/bin/cabal is the just-installed cabal I want, but the one in the cache is an old one no matter how often I delete it before.

What is going on here?


The exact procedure:

I'm installing a cabal 1.17.1 after wiping setup-exe-cache. Afterwards, setup-exe-cache will contain some cabal 1.17.0 instead of my installed one.

% ls -l ~/.cabal/setup-exe-cache                                                           
-rwxr-xr-x 1 niklas niklas 11678595 Aug  7 17:46 setup-Cabal-1.17.0-x86_64-linux-ghc-7.6.3*

rm -r ~/.cabal/setup-exe-cache

~/src/cabal/Cabal (git) % head -n2 Cabal.cabal
name: Cabal
version: 1.17.1

~/src/cabal/Cabal (git) % cabal install --disable-library-profiling --disable-documentation --ghc-options="-O0" && cd ../cabal-install && cabal install --disable-library-profiling --disable-documentation --ghc-options="-O0" && cd - 
Resolving dependencies...
In order, the following will be installed:
Cabal-1.17.1 (latest: 1.16.0.3) (reinstall)
Warning: Note that reinstalls are always dangerous. Continuing anyway...
Configuring Cabal-1.17.1...
Building Cabal-1.17.1...
Installed Cabal-1.17.1
Resolving dependencies...
Configuring cabal-install-1.17.1...
Building cabal-install-1.17.1...
Installed cabal-install-1.17.1
~/src/cabal/Cabal

% ls -l ~/.cabal/setup-exe-cache
-rwxr-xr-x 1 niklas niklas 11678595 Aug  7 17:50 setup-Cabal-1.17.0-x86_64-linux-ghc-7.6.3*

This wrong cached cabal is then used when I use cabal install some/directory/, even though my literal cabal in that command is my newer one.

If I run the installation with -v3:

Ready to install cabal-install-1.17.1
Configuring cabal-install-1.17.1...
Using external setup method with build-type Simple
creating dist/setup
Using Cabal library version 1.17.0
Using ./dist/setup/setup.hs as setup script.
Setup executable not found in the cache.
Waiting for install task to finish...
Setup executable needs to be updated, compiling...
("/usr/local/ghc/ghc-7.6.3/bin/ghc",["--make","-v","-static","-odir","./dist/setup","-hidir","./dist/setup","-i","-i.","-package-id","Cabal-1.17.0-efae9db68fc18894d8289dabf0838c54","./dist/setup/setup.hs","-o","./dist/setup/setup","-O0"])
creating /home/niklas/.cabal/setup-exe-cache
Installing executable ./dist/setup/setup to
/home/niklas/.cabal/setup-exe-cache/setup-Cabal-1.17.0-x86_64-linux-ghc-7.6.3

EDIT:

I finally believe to have figured that out. When deciding which version of the Cabal library to use to compile a setup.hs file in cabalLibVersionToUse (within externalSetupMethod), cabal looks at savedVersion <- savedCabalVersion which is determined from dist/setup/setup.version in the package we want to compile.

I think this is wrong: It is incredibly confusing if you go into a project that you have last compiled some time ago, you do cabal install and instead of using the version of Cabal you just typed cabal install with, it uses some older version. You think you are installing your package with the newest version of cabal, but this way your new cabal actually secretly sneaks in an older version to build your project with.

This is especially bad if you ghc-pkg unregister that old Cabal library version - your package won't compile, no matter what cabal tool you run in its directory.

Why was this introduced? Why does cabalLibVersionToUse not just use the version the user is running right now?

@nh2
nh2 commented

Also, that binary in setup-exe-cache is a cache for what?

The comment in the code says For each (compiler, platform, Cabal version) combination the cache holds a compiled setup script executable. - Whose setup script? A package that I'm installing? I still don't understand what the idea behind this is.

@nh2
nh2 commented

Third, why do all packages I install use the same ~/.cabal/setup-exe-cache/setup-Cabal-1.17.0-x86_64-linux-ghc-7.6.3? How can I ever install two packages with a Setup.hs at the same file when they both write to this binary?

@23Skidoo
Collaborator

@nh2

Whose setup script? A package that I'm installing? I still don't understand what the idea behind this is.

All packages with build-type: Simple use the same default setup script, so the compiled setup executable can be cached. This speeds up install -j quite a bit.

Ideally, the Git version of Cabal would be also tagged with the revision SHA-1, so that we could distinguish between e.g. setup-Cabal-1.17.0-a3d4f5-x86_64-linux-ghc-7.6.3 and setup-Cabal-1.17.0-b1c0d2-x86_64-linux-ghc-7.6.3.

Why was this introduced? Why does cabalLibVersionToUse not just use the version the user is running right now?

The logic could probably be improved, but one thing to keep in mind is that the version of Cabal that cabal-install was compiled with is not guaranteed to be installed for the compiler we're using for compiling the package. Consider this example:

$ ghc --numeric-version
7.6.3
$ cabal configure -w /path/to/ghc-7.4.2
# Since Cabal-1.17 is not installed for ghc-7.4.2, compiles a setup exe against the version of Cabal that ships with GHC 7.4.2 (1.14, IIRC)
# The version number of the Cabal lib that the setup exe is compiled against is saved in `setup.version`
$ cabal build
# Uses the setup exe built by `configure`

This is especially bad if you ghc-pkg unregister that old Cabal library version - your package won't compile, no matter what cabal tool you run in its directory.

Just run cabal clean before rebuilding.

@nh2
nh2 commented

Thanks for your explanation!

Ideally, the Git version of Cabal would be also tagged with the revision SHA-1

How would that help though? My two versions (1.17.0 and 1.17.1) were explicitly different.

Since Cabal-1.17 is not installed for ghc-7.4.2, compiles a setup exe against the version of Cabal

Granted, that makes sense. However, for a user who just runs cabal build it is very unclear and it went unnoticed for me for many hours although I was hacking on cabal.

Maybe a warning like You are running cabal-install version 1.17.0 but the project's simple build type is using the Cabal library version 1.14.0 is the way to go?

@23Skidoo
Collaborator

How would that help though? My two versions (1.17.0 and 1.17.1) were explicitly different.

Well, at least the cached setup exe for Cabal-1.17-a1c2ef won't be used when Cabal-1.17-e4f5d8 is requested.

Maybe a warning like [...] is the way to go?

This could be useful, though perhaps not at the default verbosity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.