Summary by @ezyang. When you write build-tools: alex, Cabal only checks that an executable of this name is installed; cabal-install does not know that if there is no such executable, alex needs to be installed. One complication is that build-tools does not necessarily correspond to a package, so it is not a priori obvious to cabal-install what should be installed to get an executable.
Here is Proposal A: Build-tools only
- We introduce a new type of qualified goal, a
build-tools goal, similar to how setup qualified goals work.
- We modify the solver to interpret each field of
build-tools as a package name, and we solve for each build-tool as a separate build-tools dependency (so we don't do something goofy like try to solve for happy and alex's dependency sets consistently when they really couldn't care less.)
- Some
build-tools fields don't correspond to actual packages. We give two escape hooks in this situation. First, Cabal has an internal mapping of build tools to Maybe PackageName. If Nothing, this indicates that the build-tool is not managed by Cabal and we shouldn't try to solve for it. If Just pn, then it means that installing pn will also install the requested executable. This mapping will be configurable using the build-tool-packages field in a cabal-project and also modifiable by command line argument. (Names can be bikeshedded of course.) Our second escape hook is, if a build-tool refers to an unknown package name, we print a warning but continue to solve, simply ignoring that package. A user can suppress the warning by disabling this using the aforementioned flag.
Consider these examples:
build-tools: mytoolpkg: cabal-install will install all executables defined by a package named mytoolpkg, and ensure they are available prior to building this package.
build-tools: gtk2hsc2hs: cabal-install is hard-coded to know that the gtk2hsc2hs executable is provided by the gtk2hs-buildtools, so it ensures that it builds and installs all executables from the package before building this package.
build-tools: someprog, plus a flag --provides-build-tool someprog=somepkg, cabal-install sees someprog (which has no package), but using the flag mapping it knows that somepkg is the package that provides this build tool.
Here is Proposal B: tool-depends
- We introduce a new type of qualified goal, a
build-tools goal, similar to how setup qualified goals work. (Like before)
- We introduce a new
tool-depends field, which consists of pkg:exename version-constraints specifications, e.g., tool-depends: gtk2hs-buildtools:gtk2hs2hs < 2.0. This means that we must build the gtk2hsc2hs executable from gtk2hs-buildtools before building this package. In principle cabal-install need only build the gtk2hsc2hs executable, although today's setup interface doesn't allow one to selectively enable executables, so we'd probably just build all executables. If qualification is omitted it is assumed that you need ALL executables from the package.
build-tools refers exclusively to non-packaged executables, e.g. provided by the system. However, for backwards compatibility, we introduce an internal mapping hard-coded into GHC which maps some build-tools fields to package names. The intended interpretation is that build-tools: happy > 0.4 actually elaborates to tool-depends: happy:happy > 0.4. This mapping will be configurable using the build-tool-packages field in a cabal-project and also modifiable by command line argument. (Names can be bikeshedded of course.)
Examples:
tool-depends: mytoolpkg: cabal-install will install all executables defined by a package named mytoolpkg, and ensure they are available prior to building this package.
tool-depends: mytoolpkg:mytool: cabal-install will install the executable mytool from mytoolpkg before building this package
build-tools: happy: this is equivalent to writing tool-depends: happy:happy.
build-tools: someprog: as before this does not effect solver behavior; there just simply needs to be a someprog in the path.
(Imported from Trac #227, reported by guest on 2008-02-01)
On #haskell, nelhage mentioned that one of the bugs he ran into while trying to install Yi-0.3 through cabal-install was an error which looked like this:
Installing: /home/gwern/.cabal/lib/regex-posix-0.72.0.2/ghc-6.8.2/regex-posix-0.72.0.2/ghc-6.8.2
Registering regex-posix-0.72.0.2...
Reading package info from "dist/installed-pkg-config" ... done.
Saving old package config file... done.
Writing new package config file... done.
'yi-0.3' is cached.
[1 of 1] Compiling Main ( Setup.hs, dist/setup/Main.o )
Linking dist/setup/setup ...
Configuring yi-0.3...
setup: alex version >=2.0.1&&<3 is required but it could not be found.
That is, the dependency on Alex (a version which satisfied >=2.0.1&&<3) was not met. Perfectly sensible as he did not have Alex installed. Puzzled, he did a 'cabal install alex', which worked, and then re-started. (I guess he had his GHC installed locally?).
He and I were puzzled, because cabal-install is supposed/usually does track down dependencies. Is build-tools excluded for a reason, or was it just accidentally omitted from dependency-tracking? If the latter, I think this is a bit of a bug.
(I use Cabal-1.2.3.0, btw, and the error message above was my reproduction of Nelhage's problem. I had to uninstall Alex from my system, but that did the trick, and reinstalling bypassed the issue just fine - which is why I hadn't seen it before.)
gwern
Summary by @ezyang. When you write
build-tools: alex, Cabal only checks that an executable of this name is installed;cabal-installdoes not know that if there is no such executable,alexneeds to be installed. One complication is thatbuild-toolsdoes not necessarily correspond to a package, so it is not a priori obvious tocabal-installwhat should be installed to get an executable.Here is Proposal A: Build-tools only
build-toolsgoal, similar to howsetupqualified goals work.build-toolsas a package name, and we solve for each build-tool as a separatebuild-toolsdependency (so we don't do something goofy like try to solve forhappyandalex's dependency sets consistently when they really couldn't care less.)build-toolsfields don't correspond to actual packages. We give two escape hooks in this situation. First, Cabal has an internal mapping of build tools toMaybe PackageName. IfNothing, this indicates that the build-tool is not managed by Cabal and we shouldn't try to solve for it. IfJust pn, then it means that installingpnwill also install the requested executable. This mapping will be configurable using thebuild-tool-packagesfield in acabal-projectand also modifiable by command line argument. (Names can be bikeshedded of course.) Our second escape hook is, if abuild-toolrefers to an unknown package name, we print a warning but continue to solve, simply ignoring that package. A user can suppress the warning by disabling this using the aforementioned flag.Consider these examples:
build-tools: mytoolpkg: cabal-install will install all executables defined by a package namedmytoolpkg, and ensure they are available prior to building this package.build-tools: gtk2hsc2hs: cabal-install is hard-coded to know that thegtk2hsc2hsexecutable is provided by thegtk2hs-buildtools, so it ensures that it builds and installs all executables from the package before building this package.build-tools: someprog, plus a flag--provides-build-tool someprog=somepkg, cabal-install seessomeprog(which has no package), but using the flag mapping it knows thatsomepkgis the package that provides this build tool.Here is Proposal B: tool-depends
build-toolsgoal, similar to howsetupqualified goals work. (Like before)tool-dependsfield, which consists ofpkg:exename version-constraintsspecifications, e.g.,tool-depends: gtk2hs-buildtools:gtk2hs2hs < 2.0. This means that we must build thegtk2hsc2hsexecutable fromgtk2hs-buildtoolsbefore building this package. In principle cabal-install need only build thegtk2hsc2hsexecutable, although today's setup interface doesn't allow one to selectively enable executables, so we'd probably just build all executables. If qualification is omitted it is assumed that you need ALL executables from the package.build-toolsrefers exclusively to non-packaged executables, e.g. provided by the system. However, for backwards compatibility, we introduce an internal mapping hard-coded into GHC which maps somebuild-toolsfields to package names. The intended interpretation is thatbuild-tools: happy > 0.4actually elaborates totool-depends: happy:happy > 0.4. This mapping will be configurable using thebuild-tool-packagesfield in acabal-projectand also modifiable by command line argument. (Names can be bikeshedded of course.)Examples:
tool-depends: mytoolpkg: cabal-install will install all executables defined by a package namedmytoolpkg, and ensure they are available prior to building this package.tool-depends: mytoolpkg:mytool: cabal-install will install the executablemytoolfrommytoolpkgbefore building this packagebuild-tools: happy: this is equivalent to writingtool-depends: happy:happy.build-tools: someprog: as before this does not effect solver behavior; there just simply needs to be asomeprogin the path.(Imported from Trac #227, reported by guest on 2008-02-01)
On #haskell, nelhage mentioned that one of the bugs he ran into while trying to install Yi-0.3 through cabal-install was an error which looked like this:
That is, the dependency on Alex (a version which satisfied >=2.0.1&&<3) was not met. Perfectly sensible as he did not have Alex installed. Puzzled, he did a 'cabal install alex', which worked, and then re-started. (I guess he had his GHC installed locally?).
He and I were puzzled, because cabal-install is supposed/usually does track down dependencies. Is build-tools excluded for a reason, or was it just accidentally omitted from dependency-tracking? If the latter, I think this is a bit of a bug.
(I use Cabal-1.2.3.0, btw, and the error message above was my reproduction of Nelhage's problem. I had to uninstall Alex from my system, but that did the trick, and reinstalling bypassed the issue just fine - which is why I hadn't seen it before.)
gwern