Halcyon checks twice for cabal constraints
Closed this issue · 4 comments
Halcyon runs cabal freeze
twice. The first time is in Determining constraints (with my project it takes 0.86 seconds), and The second time is after "Using existing sandbox directory" (takes the same amount of time).
On a related note, I'd like it to have a cache so that it doesn't have to check each time; only when the .cabal file has been changed perhaps? When run on a project that has nothing changed, and is already built, this would take a 2.7 second build down to 0.95 seconds.
You should declare version constraints for your project, which will avoid the need for Halcyon to determine constraints, i.e., the first cabal freeze
. This should be clear from the Halcyon tutorial, starting with the “Install the app” section. Halcyon warns you if version constraints aren’t declared:
-----> Determining constraints
*** WARNING: Using newest versions of all packages
MonadRandom-0.3.0.1
StateVar-1.1.0.0
aeson-0.8.0.2
...
In order to declare version constraints, you can either take the list of constraints printed by Halcyon and add them to your project as .halcyon/constraints
, or run cabal freeze
yourself, and keep the resulting cabal.config
.
These two methods are currently equivalent, which isn’t clear from the documentation (mietek/halcyon-website#1), but this is likely to change soon, as the use of cabal freeze
is due to be replaced (#52).
The second cabal freeze
is an attempt at working around the deficiencies of Cabal (#1). Sometimes, the second run gives a different result than the first run (or than the declared version constraints). When this happens, Halcyon prints a warning which includes diff output, such as:
*** WARNING: Unexpected constraints difference
@@ -56,7 +56,6 @@
nats-0.2
network-2.5.0.0
old-locale-1.0.0.5
-old-time-1.1.0.1
parallel-3.2.0.4
parsec-3.1.5
prelude-extras-0.4
There are two possible reasons:
- Cabal loses track of installed packages which only contain executables (haskell/cabal#779). This corresponds to diff lines starting with
-
. As explained by @benarmston (haskell/cabal#1896 (comment)):
When cabal installs a package, say
foo
, it registers the package's library (if any) with ghc-pkg. But the information which is registered doesn't contain any details aboutfoo
's executables. When cabal's resolver selects the installed version offoo
, it queries ghc-pkg to find out whatbuild-depends
foo
was compiled against. That list contains thebuild-depends
forfoo
's library but not anybuild-depends
for any offoo
's executables.
In the test program provided by @mietek the only dependency onold-time
is from thesnap
package's executablesnap
. When thesnap
package has been registered with ghc-pkg and the installed version ofsnap
is selected, anybuild-depends
in thesnap
package's executables are not available.
- The version constraints declared in
.halcyon/constraints
orcabal.config
are incomplete. It’s not possible to determine this without installing dependencies (or restoring a previously-built sandbox directory), becausecabal freeze
ignores existing version constraints (haskell/cabal#2265). This corresponds to diff lines starting with+
, and is explained in the “Declare a constraint” section of the Halcyon tutorial.
If you have any suggestions regarding the documentation, please open a mietek/halcyon-website issue.
Both cabal freeze
runs are likely to be replaced by a single cabal install --dependencies-only --dry-run
in the future (#52).
Thanks for that information. My builds runs just that bit faster.