haskell / cabal

Official upstream development repository for Cabal and cabal-install
https://haskell.org/cabal
Other
1.62k stars 693 forks source link

Supporting BNFC #6726

Open ivanperez-keera opened 4 years ago

ivanperez-keera commented 4 years ago

I'd like to propose that Cabal support BNFC as a build tool. BNFC is a well-known, multi-language parser generator that supports Haskell via Happy & Alex.

Additional context From what I understand, the required changes would be:

Questions:

phadej commented 4 years ago

Adding bnfc-options: to .cabal file syntax is a big deal, so everything else have to be figured out until we can commit to that change, we'll need to live with if forever. Note, we don't have alex-options nor happy-options as these tools self-configure from the input file. I'd appreciate that kind of working mode.

ivanperez-keera commented 4 years ago

I suspect things need changes if there is no one-to-one mapping between source MyLanguage.cf and generated MyLanguage.hs. I guess bnfc generates some .x and .y (and .hs) files. I suspect the multiple output file would case architectural problems.

This assumption is correct. From one .cf file, BNFC generates:

Adding bnfc-options: to .cabal file syntax is a big deal, so everything else have to be figured out until we can commit to that change, we'll need to live with if forever.

Makes sense not to add it then.

I think we have strong assumption that packagename and exename is the same [...] which might require some bigger changes. [...] I suspect the multiple output file would case architectural problems.

I certainly would not expect all of these changes to happen in Cabal just for this. Is this versatility (i.e., more than one file being generated, having different package and executable names) generally desired for the future of cabal, or would this just be annoying to maintain and not provide much benefit? I see their benefit in theory, but I'm just not sure if you've every encountered this before, or expect to.

phadej commented 4 years ago

Is the tricky bit build-system wise. Cabal have to know what files are generated. I suspect one-to-one processing is very deep in how Cabal is made. There are e.g. issues with ordering of c2hs flle processing which Cabal doesn't known anything about (see #6233 for more).

andreasabel commented 3 years ago
* more than one file being generated

Is the tricky bit build-system wise. Cabal have to know what files are generated. I suspect one-to-one processing is very deep in how Cabal is made. There are e.g. issues with ordering of c2hs flle processing which Cabal doesn't known anything about (see #6233 for more).

Found this comment on situations where several files are generated: https://github.com/haskell/cabal/issues/3545#issuecomment-234391866

ivanperez-keera commented 3 years ago

Just a comment which I don't know if/how it is related.

Currently, with cabal-3.4, adding BNFC to the setup build dependencies does not seem to be enough (or I don't know how to do it):

custom-setup                                                                    
  setup-depends:                                                                
      base    >= 4.11.0.0                                                       
    , Cabal   >= 2.0                                                            
    , process                                                                   
    , BNFC    >= 2.9.1   

Instead of installing BNFC as an executable, therefore letting me run it, it installs BNFC as a library. The result is that the following setup program:

-- | Custom Setup that runs bnfc to generate the language sub-libraries         
-- for the parsers included in Ogma.                                            
module Main (main) where                                                        

import Distribution.Simple         ( defaultMainWithHooks, hookedPrograms,      
                                     postConf, preBuild, simpleUserHooks )      
import Distribution.Simple.Program ( Program (..), findProgramVersion,          
                                     simpleProgram )                            
import System.Process              ( system )                                   

-- | Run BNFC on the grammar before the actual build step.                      
--                                                                              
-- All options for bnfc are hard-coded here. There is an open bug in Cabal's    
-- github repo about supporting BNFC.                                           
main :: IO ()                                                                   
main = defaultMainWithHooks $ simpleUserHooks                                   
  { hookedPrograms = [ bnfcProgram ]                                            
  , postConf       = \args flags packageDesc localBuildInfo -> do               
      _ <- system "bnfc --haskell -p Language.W -o src/ grammar/W.cf"           
      postConf simpleUserHooks args flags packageDesc localBuildInfo            
  }                                                                             

-- | TODO: This should be in Cabal.Distribution.Simple.Program.Builtin.         
bnfcProgram :: Program                                                          
bnfcProgram = (simpleProgram "bnfc")                                            
  { programFindVersion = findProgramVersion "--version" id                      
  }

cannot find bnfc in the PATH:

Warning: 'hs-source-dirs: src' directory does not exist.
/bin/sh: 1: bnfc: not found
Preprocessing library for xyz-language-w-0.0.1..
setup: can't find source for Language/W/AbsW in src, dist/build/autogen,
dist/build/global-autogen

although the directory src does exist in the repo. Btw, if I first install BNFC first with:

cabal install bnfc

then it puts the executable in $HOME/.cabal/bin and my package compiles and installs correctly.

gbaz commented 3 years ago

Correct, as discussed in the ticket you linked, build-tool-depends is the correct thing to specify.

ivanperez-keera commented 3 years ago

Indeed. Unfortunately, that did not work for me on 3.6 because of https://github.com/haskell/cabal/issues/7644.