-
Notifications
You must be signed in to change notification settings - Fork 711
RFC: design for better GHC plugin support in cabal #7901
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Sometimes plugins need to be applied only in a handful of modules.
Dependencies needed for TH would come from the same "host" dependencies. -- I hope this name is awful enough it won't stick
plugin-and-splices-depends: overloaded, record-dot-preprocessor, my-awesome-type-class-th
-- Naturals is the option passed to overloaded. Token syntax can be used here.
ghc-plugins: Overloaded Naturals, RecordDotPreprocessor
-- overloaded needs to be dependent upon, because it provides both the plugin and the library stuff.
-- there is no good reason to separate these today.
build-depends: overloaded Existence of |
If this could solve https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5965, that would be indeed high priority to implement. |
I don't think it would do that? |
@michaelpj do you still support this? I saw this linked from a newer issue, and I think this is a cleaner approach we should just do. I'm not sure I understand the concerns oleg raised, and I'm not sure they're significant enough to warrant against this simpler approach. If you think this simpler approach is still valid, and still worthwhile, I think we would accept a patch for it. |
Hrm -- actually, we would want plugin-depends to alias build-tool-depends or setup-depends maybe, not build-depends, right? Then we get "independent solving" for free. Or er... not sure actually. build-depends is certainly the easiest first step. |
I do think this is nice. I continue to think we probably want a specific It would be nice to have some opinions from other knowledgeable people, perhaps @angerman ?
This isn't going to get to the top of my list soon, I'm afraid...
I don't really know enough about the innards of cabal to say what would be the easiest implementation strategy 🤔 |
The core of this is in my opinion that we end up with two separate package databases; that have distinctly different purposes. In a hypothetical future where cabal properly understands cross compilers, this will become necessary anyway, as the setup-depends/plugin-depends will have host native code, and the build-depends target native code. The alternative would be to eventually have ghc package databases be multi-target aware, and then lump it all together into one package-db, but that seems a lot more messy than just cleanly separating package-dbs for their respective purpose. |
Right, so my proposal here is to at least add the syntax and then at such a time as GHC can actually handle multiple package dbs, we'll be ready to take advantage of that. And in the mean time there are things like |
Correct. However even if GHC can handle multi-arch package DB's, cabal won't be worse of by being able to deal with/having a concept of multiple package DB. |
This problem already exists for In plugin case the dependency separation is less water tight. The plugin should be able to lookup symbols in runtime library (names with uniques), so plugin de-facto depends on runtime library too; they are just no inter-stage final product linkage. So this makes me think that not only we need EDIT: this is conceptually the same as having TH-only dependencies. Code used to generate quotations is essentially a plugin in disguise. |
Don't we have constraints for that? I've absolutely no objective to constraints applying to both. But they need to still be solved independently even if the same set of constraints are applied. If you want to force the same version, |
@angerman constraints are project level concepts. You cannot put The plugin package author should be able to restrict the runtime versions of a library (and also simply add the runtime dependency). That is a cross-stage dependency, which should be expressible in the |
I think oleg is right that we will want some plugins that can be constrained to the same versions as linked at runtime, and some that can be independent. The current proposal, in its initial form, by "under the hood" augmenting build depends means they're always linked, and I think that's better than nothing, as a start? |
I have no specific view how that is solved. All I'm raising is that we must not assume that we can use the identical package, as the buildtime and runtime package can be different architectures. I'd hate to see any such assumptions (of identical architectures) being hardcoded in cabal. |
I am trying to write a plugin but am having the problem where the |
@BebeSparkelSparkel It's usually not very hard to make packages compatible with multiple versions of transformers. Then you won't have to override the version of transformers shipped with GHC. Or you could update GHC to 9.10.1 and get transformers-0.6.1.1: https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/libraries/version-history |
@ysangkok OpenBSD doesn't have 9.10.1 packaged yet and after multiple tries I have not been able to ghc correctly (it instantly seg faults when run). I'm using a custom mtl with some enhancements waiting for pull that I need more than the plugin. Thanks for the suggestions though |
Hello @BebeSparkelSparkel and welcome to the Cabal bug tracker! You write:
I'm afraid your issue has nothing to do with Cabal but rather with GHC itself. The way GHC plugins set up is that they use GHC API, which amounts to depending of the All of this is purely GHC (+plugins) architecture. So, I believe, your request is off topic on this thread, which talks about better support for plugins in cabal packages. |
@ulysses4ever Thank you for more details. Let me give you some more just so that we can be sure that it has nothing to do with cabal and/or belongs in its own issue. I'm using ghc 9.2.7 and cabal 3.12.1.0 ghc 9.2.7 uses transformers 0.5.6.2 (in my case) It's fine if the plugin is compiled with transformers 0.5.6.2 The package I am trying to compile must use transformers 0.6.1.1 For me to use the plugin I think I must add it to the packages build-depends. If that is the case, then cabal reports a dependency conflict. From there I deduced that this is a cabal issue since cabal is intermixing the dependencies of the plugin and package. Cabal should not be intermixing the plugin and package dependencies since the plugin that I am using only modifies the source and does not inject its own compiled objects into the package. Maybe I'm way off here but it seems to make sense to me at least. |
#2965, cited previously, describes the problem and a potential solution. |
@BebeSparkelSparkel okay, maybe you're right that the prosed |
This came out of some discussion on IRC. I started writing an issue, but on reflection I think there's a relatively plausible design sitting there, so I wrote it down.
Motivation
GHC compiler plugins are currently not terribly easy to use with
cabal
, and require some amount of manual fiddling. In addition, they are not specified as declaratively as they could be (i.e. cabal has no concept of a "plugin"), which prevents cabal from doing some things as well as it could do.I think there are two broad kinds of plugin that we should be thinking about:
Package plugins are those which are required by the package itself. They usually have a load-bearing role, in that they are actually necessary to compile the package. An example is the
record-dot-preprocessor
plugin.Today, these can be used by:
build-depends
stanza-fplugin
GHC optionPackage plugins as implemented today have a few weaknesses:
-fplugin-package
, since they are just specified as normalbuild-depends
. This means they get unnecessarily linked into the final build product (Add support for -fplugin-package #6169).-fplugin
options themselves, as well as any-fplugin-opt
flags.Global plugins are ones which users want to run on all packages that get built, regardless of whether the package itself says it requires any plugins. An example is the
ghc-tags-plugin
plugin. Often these are used to e.g. get additional compile-time information out of dependencies.Today these are very difficult to use (#7685, #6307, probably more). Partly the issue is that doing this nicely requires both setting a GHC option for upstream packages (doable today in
cabal.project
), but also building the plugin package and ensuring it is present in the appropriate package db when building the upstream package (hard to do without hacks like specifying your own manually created plugin db).Since these sorts of plugins are also frequently used just in development, it would be particularly nice if they could easily be specified via
cabal.project.local
(#6169 (comment)).Proposal
plugin-depends
field for.cabal
files(Prior art: #2965, but I'm putting it a little differently, so I'll repeat.)
The goal here is to make the situation nicer for package plugins. To that end, we teach cabal a
plugin-depends
field for component stanzas for.cabal
files.plugin-depends
contains a list of package/module pairs.Initially, it could start out as a simple wrapper for
build-depends
, and then we could progressively augment it to have the following features:-fplugin
flags. (This is why we need the module component!-fplugin
needs the actual plugin module.)-fplugin-package
(in particular, I don't think this needs to be a prerequisite, contra RFE: local plugins and build-tool-depends #6307 (comment))This deliberately doesn't cover
-fplugin-opt
flags. It seems reasonable for users to add those themselves.(I'm also disagreeing with my past self here, who thought that we should just have
native-build-depends
and have that include plugins. However, the idea of including the extra information about modules that's needed to automatically pass-fplugin
flags seems appealing to me, and requires a plugin-specific field. You could do this with a combination ofnative-build-depends
andactive-plugins
(the latter taking a list of modules); maybe that would be nicer.)plugin-depends
package field forcabal.project
filesThe goal here is to make the situation nicer for global plugins. To that end, we teach cabal a
plugin-depends
field for package stanzas incabal.project
files.This field simply augments the
plugin-depends
field for the corresponding package. Plugins that truly want to be globally applied can then usepackage *
as usual.The text was updated successfully, but these errors were encountered: