[GHC] #11244: Compiler plugins should not have visibility controlled by -package

GHC ghc-devs at haskell.org
Thu Dec 17 18:44:32 UTC 2015


#11244: Compiler plugins should not have visibility controlled by -package
-------------------------------------+-------------------------------------
           Reporter:  ezyang         |             Owner:  ezyang
               Type:  bug            |            Status:  new
           Priority:  normal         |         Milestone:  8.0.1
          Component:  Compiler       |           Version:  7.11
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  None/Unknown
  Unknown/Multiple                   |
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 The current way compiler plugins are recommended to be specified is by
 putting it in a package and then referring to the exported module name in
 the `-fplugin` flag.  Consequently, the recommended way to use a plugin
 from Cabal is to put it in `build-depends`. For example,
 [https://hackage.haskell.org/package/ghc-typelits-natnormalise ghc-
 typelits-natnormalise] is used by [http://hackage.haskell.org/package
 /clash-prelude clash-prelude], whose [http://hackage.haskell.org/package
 /clash-prelude-0.10.4/clash-prelude.cabal build-depends] depends on it
 explicitly.

 There are numerous downsides to operating in this manner:
 1. Cabal will always link in any library which is `build-depend`ed on,
 even if there is no runtime dependency on the package in question. For
 example, suppose the default `cabal-init` package with a `build-depends:
 ghc` and doesn't use it, you get:
 {{{
 ezyang at sabre:~/Dev/labs/link$ cat Main.hs
 module Main where

 main :: IO ()
 main = putStrLn "Hello, Haskell!"
 ezyang at sabre:~/Dev/labs/link$ cabal configure --enable-executable-dynamic;
 cabal build
 # elided
 ezyang at sabre:~/Dev/labs/link$ ldd dist/build/link/link | grep libHSghc
         libHSghc-7.10.2-JzwEp1oQ8kA7NFNTGk1ho5-ghc7.10.2.so =>
 /srv/code/ghc-7.10.2/usr/lib/ghc-7.10.2/ghc_JzwEp1oQ8kA7NFNTGk1ho5/libHSghc-7.10.2-JzwEp1oQ8kA7NFNTGk1ho5-ghc7.10.2.so
 (0x00007f591f47a000)
 }}}
    That's terrible. And it's inflicted on every package which depends on a
 library that uses the plugin. The situation is better with static linking,
 since the linker can drop unreferenced object files; but we shouldn't be
 passing it to the linker in the first place.
 2. It should be possible use a compiler plugin with a cross-compiler (e.g.
 GHCJS, etc.); unlike Template Haskell, the plugin must be written with the
 host compiler in mind. But the package database contains libraries
 compiled in the //target language//; whereas a compiler plugin must be
 compiled in the //host language//.

 It seems clear that using `-package` to bring a plugin into scope is
 highly undesirable. So what should we do?  The necessary information to
 load a plugin is:

 1. The package DB entry for the package it lives in (and information about
 all its transitive dependencies, because we may need to load code from
 them as well),
 2. The actual module which contains the plugin.

 This leaves us with a number of options on the GHC end:

 1. We could have a explicitly, IPID qualified method of specifying
 plugins.  So, instead of saying `-fplugin ModuleName` and being at the
 mercy of what is exposed, you could say `-fplugin foo-0.1-xxxx:ModuleName`
 and as long as that package is usable (not ignored/broken) it would get
 loaded.

 2. We could have a *completely separate* package database for plugins.
 You would control it using `-plugin-package` rather than `-package`; you
 don't even have to use the default system/user databases (which means that
 it might be possible to support a cross-compiler, although the details are
 fuzzy in my head). A benefit of this approach is that you can support the
 `-fplugin MyModule` mode of use, and have Cabal feed in the extra plugin
 package arguments to give meaning to this expression.

    An alternate command line interface (suggested by SPJ) would be that to
 load a plugin, you specify a path to the package database, package, and
 module in question, something like `-fplugin
 /path/to/package.conf/foo-0.1-xxxx.conf:MyPlugin` (one difficulty with
 this approach is that you may need multiple package databases to get this
 to work.)

 There would also be necessary Cabal adjustments, to get people to not put
 their plugins in `build-depends`, but a different dependency section, and
 how to have Cabal feed the IPID of the plugin to GHC.

 I'm happy to implement, but I'm looking for some consensus on what to do.
 (1) is easier to implement, but I dare say harder to integrate with Cabal.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11244>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list