Bootstrapping Propellor with Cabal is currently failing for me on Archlinux, for several reasons.
Dynamic linking
The ghc
package in Archlinux uses dynamic linking for the GHC boot libraries. This means that the cabal install
and cabal build
steps in src/Propellor/Bootstrap.hs need the --ghc-options=-dynamic
option added. I don't know if it's safe to do that for all OSes, or if this is something that Bootstrap.hs will need to do only on Arch.
GHC 8.8
Archlinux, being a rolling-release distro, has version 8.8.1 of GHC available. This means that once I add the --ghc-options=-dynamic
option to the cabal install
and cabal build
steps, Propellor now fails to build on my Archlinux system with the GHC compiler complaining about src/Propellor/Property/Installer/Target.hs. Specifically, the UserInput i
line in the definition of targetInstalled
produces an "Illegal polymorphic type" error:
src/Propellor/Property/Installer/Target.hs:137:12: error:
• Illegal polymorphic type:
forall metatypes.
(Combines
(RevertableProperty metatypes metatypes)
(RevertableProperty metatypes metatypes),
CombinedType
(RevertableProperty metatypes metatypes)
(RevertableProperty metatypes metatypes)
~ RevertableProperty metatypes metatypes) =>
Propellor.Property.Versioned.VerSpec v metatypes
-> RevertableProperty metatypes metatypes
Perhaps you intended to use RankNTypes
• In the expansion of type synonym ‘Propellor.Property.Versioned.VersionedBy’
In the expansion of type synonym ‘Versioned’
In the type signature:
targetInstalled :: UserInput i =>
Versioned v Host
-> v
-> i
-> TargetPartTable
-> RevertableProperty (HasInfo + DebianLike) (HasInfo
+ DebianLike)
|
137 | :: UserInput i
| ^^^^^^^^^^^^...
This appears to be due to stricter type synonym validity-checking in GHC 8.8. I had to add the RankNTypes
, TypeFamilies
, and FlexibleContexts
extensions to Target.hs in order to make GHC 8.8 happy. (That's a minimal set: removing any one of those three produced one of three different compiler errors, which I won't reproduce here for brevity's safe). This appears to be safe on all OSes, since Propellor compiled happily on my laptop, which is running a Buntish variant called Linux Mint (where GHC 8.0.2 is what Apt gave me). (Though do note that I only tested that on Arch and Mint, and didn't do any testing on Debian to see whether GHC 7.x or earlier is still happy with those extensions being present in the source file).
New-style cabal
Once I added the --ghc-options=-dynamic
option to Cabal, and added those three extensions to the first line of Target.hs, I was then faced with another error: the ln -sf
step failed because dist/build/propellor-config/propellor-config
didn't exist. The version of Cabal that comes with Archlinux has apparently switched to Nix-style local builds as the default action when you run cabal build
, and the propellor-config
binary ended up in /usr/local/propellor/dist-newstyle/build/x86_64-linux/ghc-8.8.1/propellor-5.10.1/x/propellor-config/build/propellor-config/propellor-config
.
This is the point where, not being a Haskell programmer myself, my ability to Google the problem was exhausted. I'm sure there's a way to get Cabal to tell you where it will put the files it's about to build (similar to stack path --dist-dir
), but at this point, I needed to get back to working on other things. So I punted and just added & bootstrapWith (Robustly Stack)
to the properties of my Archlinux host. Bootstrapping with Stack was successful, BTW.
I haven't yet prepared a patch for this, but in src/Propellor/Bootstrap.hs, the
archlinuxdeps Cabal
list of should have"haskell-type-errors"
added to it. That's the name of the Archlinux package for https://hackage.haskell.org/package/type-errors. Without that package, Cabal has to download type-errors and its dependencies before building Propellor, but with that package added, Archlinux's package manager can manage that package (and keep it up-to-date) instead.With that one change, the
archlinuxdeps Cabal
list is complete (at least as of yesterday when I tested it).I'll prepare a patch for this and submit it to propellor@joeyh.name soon.
Seems odd that the way Arch has installed ghc would make
cabal install
fail without additional options being added very time. That does not strike me as a good decision if it's the case. I guess that the -dynamic should only be set on Arch, since only it has inflicted this problem on itself.Would appreciate a patch with the ghc 8.8 fixes.
I would not be surprised if cabal new-build does not provide any good way to find out where the executable was put, because after all cabal build doesn't either (just it's easier to guess there). Cabal expects a workflow where that's followed by cabal install, or cabal run.
This might be one way:
cabal new-install --symlink-bindir=.
But with my older version of cabal, that seems to not actually work, indeed I can't get it to install the binaries anywhere. Maybe it does work with the newer cabal where new-install is the default.
Needing to detect whether new-build was used or not is an added complication.
Best way I've found:
Ghc 8.8 is fixed thanks to your patch.
I was curious how cabal build failed w/o -dynamic, and found this https://bugs.archlinux.org/task/54563#comment158808 which includes a simple change that the archlinux maintainers could make if they didh't want this to be a self-inflicted wound on their users.
But, this seems to do a lot of extra work, including generating a tarball of all the source code, and possibly building the package again unncessarily. And only works with a new enough cabal version.
Ok, I've implemented it using
find
.I had to
in order to get things going.
I would not be surprised at all to learn there is an easier way (perhaps just blowing away /usr/local/propellor)
I'm curious why you needed to make clean. AFAIK the new cabal will ignore any cruft left by the old version and should just do a from scratch build on its own.
Indeed, one of my hosts managed by propellor has both /usr/local/propellor/dist and dist-newstyle, and is building successfully in the latter directory.
Hmm, it overwrites /usr/local/propellor with:
That is safe against dangling symlinks. The safetycopy is created using
cp -pfL
which also seems safe against dangling symlinks (or symlinks pointing to files, though not to directories).