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

Fix c2hs handling in Cabal #6233

Draft
wants to merge 40 commits into
base: master
Choose a base branch
from
Draft

Fix c2hs handling in Cabal #6233

wants to merge 40 commits into from

Conversation

vmchale
Copy link
Contributor

@vmchale vmchale commented Sep 11, 2019

This fixes a 13 year-old bug, viz. #55 aka #1906

  • Patches conform to the coding conventions.
  • Any changes that could be relevant to users have been recorded in the changelog.
  • The documentation has been updated, if necessary.
  • If the change is docs-only, [ci skip] is used to avoid triggering the build bots.

I tested it by building my own library.

echo "Cabal-${CABAL_VER} will be installed from the local Git clone."
(cd ../Cabal && install_pkg ${CABAL_VER} ${CABAL_VER_REGEXP})
(cd ../Cabal && ${ALEX_PATH} -g Distribution/C2Hs/Lexer.x && install_pkg ${CABAL_VER} ${CABAL_VER_REGEXP})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on the fence with these. The lexer for .cabal files is generated in manual preprocessing step (see Makefile). And rather keep it that way, i.e. let's not have compile-time dependency on alex.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

@@ -3,6 +3,7 @@
.PHONY : cabal-install-dev cabal-install-prod

LEXER_HS:=Cabal/Distribution/Fields/Lexer.hs
LEXER_CHS:=Cabal/Distribution/C2Hs/Lexer.hs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need to commit in Lexer.hs file too. So the people who do not modify Lexer.x shouldn't need to be aware of it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be done.

@vmchale
Copy link
Contributor Author

vmchale commented Sep 12, 2019

CI is acting up, but this should be ready to merge.

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleContexts #-}

-- Based on https://github.com/gtk2hs/gtk2hs/blob/master/tools/src/Gtk2HsSetup.hs#L414
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's GPLd repository, we cannot "base" anything on that code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, good point.


$module = [A-Za-z\.]

tokens :-
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file needs comments, what it does. Is there a reason why you chose alex, and not writing something using parsec?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used alex because it seems to be the best choice for lexers and I've used it in the past for identifying dependencies in e.g. C.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I don't agree that we need to write any new alex code. It's write-only for almost any other contributor. You should been asked before making tech choice

import Distribution.Simple.Utils (dieNoVerbosity, findFileWithExtension, withUTF8FileContents)
import System.FilePath (joinPath)

reorderC2Hs :: [FilePath] -> [ModuleName] -> IO [ModuleName]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This need a proper comment, what it does, and why.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

mods <- case getImports con of
Right ms -> case traverse simpleParsec ms of
Just ms' -> pure ms'
Nothing -> dieNoVerbosity ("Cannot parse module name in c2hs file " ++ f)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This dieing here feels wrong. There should be way to fail in pure way...

We need tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have changed the dieNoVerbosity to a warn.

I've added some tests to ensure it works as I need it to.

Left err -> dieNoVerbosity ("Cannot parse c2hs import in " ++ f ++ ": " ++ err)
pure (md { moduleRequires = mods })

sortTopological :: [ModDep] -> [ModDep]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to Distribution.Compat.Graph to not reinvent the wheel?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes; I've fixed this.

@@ -168,7 +169,8 @@ preprocessComponent pd comp lbi clbi isSrcDist verbosity handlers = do
(CLib lib@Library{ libBuildInfo = bi }) -> do
let dirs = hsSourceDirs bi ++ [autogenComponentModulesDir lbi clbi
,autogenPackageModulesDir lbi]
for_ (map ModuleName.toFilePath $ allLibModules lib clbi) $
mods <- reorderC2Hs dirs (allLibModules lib clbi)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why only for librayr components, shouldn't this be done for all components?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this should be fixed now.

@vmchale
Copy link
Contributor Author

vmchale commented Sep 26, 2019

@phadej is this ready to be merged?

Copy link
Collaborator

@phadej phadej left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry to say no to this.

There are issues I commented inline. Also I'd personally expect a single comment with a good commit message explaining what and why that commit does. There're plenty of code.

But I'm not familiar with issue #55, and maybe someone talked you already to do this PR this way.

Please find someone else to review this. as said, I don't feel this is right, but I cannot explain myself better.

If someone else want to take responsibility of merging this, I won't be offended.


$module = [A-Za-z\.]

tokens :-
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I don't agree that we need to write any new alex code. It's write-only for almost any other contributor. You should been asked before making tech choice

@@ -0,0 +1,119 @@
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this file actually compiled, or is it only an input for tests?

Can we place it's somewhere where it doesn't look like real file.

I value that we have "real life" tests inputs, but we also should have something more minimal.

Also negative examples.

@23Skidoo
Copy link
Member

/cc @dcoutts

@vmchale
Copy link
Contributor Author

vmchale commented Sep 28, 2019

@hvr thoughts?

I'm quite keen on getting this merged (/fixed), and I'm open to rearranging most of it based on the experience of others (I am quite partial to the alex-based lexer, though).

@vmchale
Copy link
Contributor Author

vmchale commented Sep 28, 2019

(Also, if someone else wants to rewrite the lexer I would not be offended - but I would not know how to do this without alex or a similar tool/library for lexers)

@DanielG
Copy link
Collaborator

DanielG commented Oct 5, 2019

@vmchale I'm also interested in improving dependency tracking for cabal preprocessors, but in general, not just for c2hs. I don't really understand in detail what exactly c2hs needs here, maybe you cain explain what is going on?

Also is there a reason you can see that would prevent doing this more generally, by say adding an eplicit interface for any preprocessors to communicate dependencies to Cabal instead of Cabal having to parse the preprocessor's input which seems like a pretty nasty violation of the separation of concerns?

@vmchale
Copy link
Contributor Author

vmchale commented Oct 8, 2019

@DanielG That's a good point. It might be better to expose a general interface to allow preprocessors to reorder dependencies.

As for what c2hs needs here: I think the easiest way to explain is an example: https://github.com/vmchale/libarchive/blob/master/src/Codec/Archive/Foreign/Archive.chs#L327

Briefly, c2hs can {# import #} another .chs module which gives that module some "context" for marshaling Haskell types.

If you have any more questions about the specific c2hs case, feel free to ask.

My 2¢ is that Cabal should include a special case for c2hs, since it tries to includes support for .chs files out of the box.

@DanielG
Copy link
Collaborator

DanielG commented Oct 9, 2019

I'm not against shipping special support code for the builtin preprocessors, I just think it should be possible for external ones to work to the same extent. Possibly with some custom Setup.hs code but ideally I'd like to just have some protocol that preprocessors can choose to expose which Cabal can automatically use to give you improved dependency tracking.

@vmchale
Copy link
Contributor Author

vmchale commented Oct 13, 2019

Right, my guess is it's easier to require custom Setup.hs code - designing such a protocol is more complex.

@phadej
Copy link
Collaborator

phadej commented Nov 22, 2019

I have thinking about this, and I won't accept this approach. There are two options:

  • Either c2hs is tought a variant where Cabal can pass it all the files to process
  • Or there is some discovery option, so Cabal could ask c2hs (again passing all the files) in which order to process them.

cf. that with ghc --make or possible single-shot compilation with initial dependency discovery.

To say it directly: I won't accept cabal "learning" about the contents of source files. c2hs might be quite stable, but there's no reason to assume it won't change. Let's not couple c2hs and Cabal.

@vmchale
Copy link
Contributor Author

vmchale commented Nov 26, 2019

@phadej So you think it would be sensible to provide build tools a mechanism to pass dependency reorderings to cabal-install?

Should a spec be decided on on the cabal side before making PRs to c2hs and so on?:

@phadej phadej mentioned this pull request Apr 22, 2020
@vmchale vmchale mentioned this pull request May 30, 2021
3 tasks
@mergify mergify bot added the merge delay passed Applied (usually by Mergify) when PR approved and received no updates for 2 days label Sep 1, 2022
@ulysses4ever ulysses4ever removed the merge delay passed Applied (usually by Mergify) when PR approved and received no updates for 2 days label Sep 3, 2022
@Kleidukos
Copy link
Member

Marking this PR as draft 🙂

@Kleidukos Kleidukos marked this pull request as draft May 17, 2023 06:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants