Skip to content
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

Re-compilation when querying UnitInfo #120

Open
coot opened this issue May 24, 2020 · 13 comments
Open

Re-compilation when querying UnitInfo #120

coot opened this issue May 24, 2020 · 13 comments
Labels

Comments

@coot
Copy link

coot commented May 24, 2020

The haddock documentation of UnitInfo sais:

The information extracted from a 'Unit''s on-disk configuration cache.

But when I do a runQuery (allUnits id), the whole project is recompiled. Either the documentation is in-accurate or the runQuery does not what it's supposed to do (I hope for the latter).

@coot
Copy link
Author

coot commented May 24, 2020

I found that reconfigureUnit runs buildProjectTarget with OnlyCfg (which turns on --only-configure flag). Isn't it possible to check if a project is already configured?

@coot
Copy link
Author

coot commented May 24, 2020

But it does not seem that cabal-helper only configures:

Configuring library for ghc-tags-core-0.2.0.0..
Preprocessing library for ghc-tags-core-0.2.0.0..
Building library for ghc-tags-core-0.2.0.0..
[ 1 of 13] Compiling GhcTags.CTag.Header ( lib/GhcTags/CTag/Header.hs, /home/coot/repos/ghc-tags-plugin/d
...

@DanielG
Copy link
Owner

DanielG commented May 24, 2020

But when I do a runQuery (allUnits id), the whole project is recompiled. Either the documentation is in-accurate or the runQuery does not what it's supposed to do (I hope for the latter).

The documentation is correct though arguably it omits some of the details; c-h will re-generate the mentioned cache, Cabal's setup-config file, if it deems it necessary. This is done using a simple mtime check, see getUnitModTimes. Though the part about on-disk you mention is on the UnitInfo type, not on runQuery so there simply is no documented guarantee how a Query will get executed ATM.

I found that reconfigureUnit runs buildProjectTarget with OnlyCfg (which turns on --only-configure flag). Isn't it possible to check if a project is already configured?

Yes and we do that as I explained above. However the build-tool, in your case cabal, should also have another layer of caching that actually runs re-configuration only if necessary.

What you might be observing is dependencies being built: when, say, an executable depends on a library in the same package we have to build this library before we can configure the executable.

That's just an unfortunate reality of how Cabal functions.

@coot
Copy link
Author

coot commented May 24, 2020

Whenever cabal-hepler starts it seems always re-configures even if after cabal build all. Is this necessary? Are there any other cache strategies?

Maybe I am using the wrong tool; What I need is just a list of project files and DynFlags needed to parse them (I am writing a ctags like tool for Haskell).

@DanielG
Copy link
Owner

DanielG commented May 28, 2020

Can you run your test again with CABAL_HELPER_DEBUG=1 and send me a gist?

Maybe I am using the wrong tool; What I need is just a list of project files and DynFlags needed to parse them (I am writing a ctags like tool for Haskell).

Certainly this is what cabal-helper is intended to do :)

However I think for generating TAGS you wouldn't actually need to know the project structure like IDEs might like (which is the use-case cabal-helper is intended for) in which case it might be a good idea to look into implementing that as a GHC plugin instead. Then all this environment stuff is just handled by the vanilla build-tools and your plugin just runs as a side-effect of a regular build.

@coot
Copy link
Author

coot commented Jun 6, 2020

Here's the log. Cabal cache is also invalidated after using cabal-helper.

it might be a good idea to look into implementing that as a GHC plugin instead.

That's what I did first, since a plugin is easier to implement ghc-tags-plugin, but I think it's useful to have a standalone tool for tags: easier to integrate into a project, especially a stack based. I found setting ghc plugins to be difficult at times.

@DanielG
Copy link
Owner

DanielG commented Jun 7, 2020

Yeah, so if I'm reading that right the library in that project is being compiled because the examples depend on it and to configure the examples we need to compile the library. I'm not sure whats up with the cabal_macros.h failures after that. We might need some more cabal verbosity to figure that out. cabal -v3 should give us more info.

That's what I did first, since a plugin is easier to implement ghc-tags-plugin, but I think it's useful to have a standalone tool for tags: easier to integrate into a project, especially a stack based. I found setting ghc plugins to be difficult at times.

Why not just have this stand-alone tool manage all the plugin stuff for the user? Essentially just have it be a simple wrapper around cabal/stack that adds the appropriate options to let the plugin run?

Another approach I've been toying with is to go with the old school approach of having what ammounts to a custom GHC driver, like ghc-mod used to and hie does now. Just a program that links against the GHC library to do your custom thing -- but with a twist. Instead of using cabal-helper to run cabal/stack and collect info you ask cabal-helper to run your custom GHC driver as part of the cabal/stack build process.

This removes the difficulties associated with distributing and managing ghc plugin installation, you get full access to GHC's internals but you don't have to deal with the pain associated with version matching the global GHC install and your tool because in this scenario cabal-helper fully controls what GHC will be used (i.e. yours).

The only thing you need to do to make that approach work is implement GHC's ususal commandline conventions so cabal can talk to your tool.

@coot
Copy link
Author

coot commented Jun 7, 2020

Yeah, so if I'm reading that right the library in that project is being compiled because the examples depend on it and to configure the examples we need to compile the library.

That's right. That's a serious limitation for any larger projects which contains multiple libraries in one repo.

Why not just have this stand-alone tool manage all the plugin stuff for the user? Essentially just have it be a simple wrapper around cabal/stack that adds the appropriate options to let the plugin run?

That requires modifying cabal files at least for stack, for cabal one can add config to cabal.project.local files.

I will need to look into hie.

@coot coot closed this as completed Jun 7, 2020
@DanielG
Copy link
Owner

DanielG commented Jun 7, 2020

Yeah, so if I'm reading that right the library in that project is being compiled because the examples depend on it and to configure the examples we need to compile the library.

That's right. That's a serious limitation for any larger projects which contains multiple libraries in one repo.

I agree but it's just what we have to do currently. I have some ideas on how to lift that limitation if you're interested in helping we can have a more in-depth chat about that.

Why not just have this stand-alone tool manage all the plugin stuff for the user? Essentially just have it be a simple wrapper around cabal/stack that adds the appropriate options to let the plugin run?

That requires modifying cabal files at least for stack, for cabal one can add config to cabal.project.local files.

What about just adding --ghc-options on the command line? That should work for stack and cabal without any config file changes. Incidentally you can do that with cabal-helper if you like using the Program.caba/stackUnitArgs

I will need to look into hie.

HIE uses cabal-helper and hie-bios which has the same limitation. hie-bios essentially runs cabal repl which will go and compile the units themselves not just the dependencies, so even more stuff!

@DanielG DanielG reopened this Jun 7, 2020
@coot
Copy link
Author

coot commented Jun 8, 2020

I have some ideas on how to lift that limitation if you're interested in helping we can have a more in-depth chat about that.

Yes, I'd be interested.

What about just adding --ghc-options on the command line?

That's what I basically do in cabal.project.local file, but for some reason I need to add -package-db so the plugin can be found. This most of the time works fine, the difficulty is to get it installed & updated. I screwed my package db stack a few times with ghc-pkg and I encountered problems with cabal install --lib too.

@DanielG
Copy link
Owner

DanielG commented Jun 8, 2020 via email

@coot
Copy link
Author

coot commented Jun 8, 2020

Sure, I just don't think it's a good idea to mess around with the user's
persistent config.

I should be more precise: I do that as a user of my plugin.

What problem do you see exactly with building dependencies?

Generating tags should not relay on things to type check. One might want to update tags file while one of the dependencies is not compiling. Running whole compiler cycle when I just need enough to parse files (so only DynFlags) is not right.

With a future version of ghc plugins it might be possible to generate information about expressions generated by TemplateHaskell, but for standalone tool I think this is acceptable to skip it. I'd be surprised if I needed to compile dependencies just to parse, but maybe I am wrong.

I don't need renamer. After parsing phase I get original identifiers, renaming happens later.

@DanielG
Copy link
Owner

DanielG commented Jun 8, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants