Skip to content

Commit

Permalink
Make bootstrapping even easier by avoiding custom Setup.hs
Browse files Browse the repository at this point in the history
  • Loading branch information
hvr committed Feb 10, 2018
1 parent ff84f44 commit afbf177
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 112 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*~
*.o
*.info
/.ghc.environment.*
/AlexTemplate-debug.bak
/AlexTemplate-ghc-debug.bak
/AlexTemplate-ghc.bak
Expand Down Expand Up @@ -32,6 +33,7 @@
/AlexWrapper-posn
/AlexWrapper-posn-bytestring
/AlexWrapper-strict-bytestring
/data/
/dist
/dist-newstyle
/doc/alex.1
Expand Down
19 changes: 11 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
# language: haskell

env:
# - GHCVER=7.0.4
- GHCVER=7.4.2
- GHCVER=7.6.3
- GHCVER=7.8.4
- GHCVER=7.10.3
- GHCVER=8.0.1
- GHCVER=8.0.2
- GHCVER=8.2.2
- GHCVER=8.4.1

before_install:
- sudo add-apt-repository -y ppa:hvr/ghc
- sudo apt-get update
- sudo apt-get install alex-3.1.7 happy-1.19.5 cabal-install-1.24 ghc-$GHCVER
- export PATH=/opt/cabal/bin:/opt/ghc/$GHCVER/bin:/opt/alex/3.1.7/bin:/opt/happy/1.19.5/bin:$PATH
- sudo apt-get install alex-3.1.7 happy-1.19.5 cabal-install-head ghc-$GHCVER
- export PATH=/opt/cabal/head/bin:/opt/ghc/$GHCVER/bin:/opt/alex/3.1.7/bin:/opt/happy/1.19.5/bin:$PATH

install:
- cabal-1.24 update
- cabal-1.24 install --only-dependencies --enable-tests
- cabal update

script:
- make sdist
- cd dist
- tar xvzf alex-*.tar.gz
- cd alex-*/
- cabal-1.24 configure --enable-tests
- cabal-1.24 build
- cabal-1.24 test
- "echo 'packages: .' > cabal.project"
- cabal new-test --enable-tests
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ sdist ::
$(ALEX) $(ALEX_OPTS) src/Scan.x -o src/Scan.hs
mv src/Parser.y src/Parser.y.boot
mv src/Scan.x src/Scan.x.boot
cabal new-run gen-alex-sdist
cabal sdist
git checkout .
git clean -f
2 changes: 2 additions & 0 deletions Setup.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain
99 changes: 0 additions & 99 deletions Setup.lhs

This file was deleted.

28 changes: 25 additions & 3 deletions alex.cabal
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
cabal-version: >= 1.8
name: alex
version: 3.2.3
-- don't forget updating changelog.md!
Expand All @@ -18,8 +19,26 @@ description:
lex or flex for C/C++.

category: Development
cabal-version: >= 1.8
build-type: Custom
build-type: Simple

data-dir: data/

data-files:
AlexTemplate
AlexTemplate-ghc
AlexTemplate-ghc-nopred
AlexTemplate-ghc-debug
AlexTemplate-debug
AlexWrapper-basic
AlexWrapper-basic-bytestring
AlexWrapper-strict-bytestring
AlexWrapper-posn
AlexWrapper-posn-bytestring
AlexWrapper-monad
AlexWrapper-monad-bytestring
AlexWrapper-monadUserState
AlexWrapper-monadUserState-bytestring
AlexWrapper-gscan

extra-source-files:
CHANGELOG.md
Expand Down Expand Up @@ -50,7 +69,7 @@ extra-source-files:
src/Parser.y.boot
src/Scan.x.boot
src/ghc_hooks.c
templates/GenericTemplate.hs
templates/GenericTemplate.hs
templates/wrappers.hs
tests/Makefile
tests/simple.x
Expand Down Expand Up @@ -126,4 +145,7 @@ executable alex
test-suite tests
type: exitcode-stdio-1.0
main-is: test.hs
-- This line is important as it ensures that the local `exe:alex` component declared above is built before the test-suite component is invoked, as well as making sure that `alex` is made available on $PATH and `$alex_datadir` is set accordingly before invoking `test.hs`
build-tools: alex

build-depends: base, process
6 changes: 6 additions & 0 deletions cabal.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

packages:
./
./gen-alex-sdist/


74 changes: 74 additions & 0 deletions gen-alex-sdist/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
module Main (main) where

import Control.Monad
import Language.Preprocessor.Cpphs
import System.Directory
import System.FilePath

main :: IO ()
main = do
sequence_ ([ cpp_template "GenericTemplate.hs" dst opts | (dst,opts) <- templates ] ++
[ cpp_template "wrappers.hs" dst opts | (dst,opts) <- wrappers ])

putStrLn ""
putStrLn "-- fragment for alex.cabal file"
putStrLn "data-dir: data/"
putStrLn ""
putStrLn "data-files:"
forM_ all_template_files $ \fn -> putStrLn (" " ++ fn)
putStrLn "-- end of fragment"
putStrLn ""
putStrLn "You can invoke `cabal sdist` now"

cpp_template :: FilePath -> FilePath -> [String] -> IO ()
cpp_template src0 dst0 defs = do
ex <- doesFileExist src
unless ex $
fail ("file " ++ show src ++ " not found; are you in the right directory?")

putStrLn ("generating " ++ show dst ++ " (from " ++ show src ++ ")...")
createDirectoryIfMissing False "data"
srcdat <- readFile src
outdat <- runCpphs cppflags src =<< readFile src
writeFile dst outdat

return ()
where
src = "templates" </> src0
dst = "data" </> dst0

cppflags = defaultCpphsOptions
{ defines = [(d,"1") | d <- defs ]
, boolopts = defaultBoolOptions
{ hashline = False
, locations = True
, ansi = False
, macros = True
}
}

all_template_files :: [FilePath]
all_template_files = map fst (templates ++ wrappers)

templates :: [(FilePath,[String])]
templates = [
("AlexTemplate", []),
("AlexTemplate-ghc", ["ALEX_GHC"]),
("AlexTemplate-ghc-nopred",["ALEX_GHC", "ALEX_NOPRED"]),
("AlexTemplate-ghc-debug", ["ALEX_GHC","ALEX_DEBUG"]),
("AlexTemplate-debug", ["ALEX_DEBUG"])
]

wrappers :: [(FilePath,[String])]
wrappers = [
("AlexWrapper-basic", ["ALEX_BASIC"]),
("AlexWrapper-basic-bytestring", ["ALEX_BASIC_BYTESTRING"]),
("AlexWrapper-strict-bytestring", ["ALEX_STRICT_BYTESTRING"]),
("AlexWrapper-posn", ["ALEX_POSN"]),
("AlexWrapper-posn-bytestring", ["ALEX_POSN_BYTESTRING"]),
("AlexWrapper-monad", ["ALEX_MONAD"]),
("AlexWrapper-monad-bytestring", ["ALEX_MONAD_BYTESTRING"]),
("AlexWrapper-monadUserState", ["ALEX_MONAD", "ALEX_MONAD_USER_STATE"]),
("AlexWrapper-monadUserState-bytestring", ["ALEX_MONAD_BYTESTRING", "ALEX_MONAD_USER_STATE"]),
("AlexWrapper-gscan", ["ALEX_GSCAN"])
]
2 changes: 2 additions & 0 deletions gen-alex-sdist/Setup.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain
15 changes: 15 additions & 0 deletions gen-alex-sdist/gen-alex-sdist.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cabal-version: 1.12
name: gen-alex-sdist
version: 0
synopsis: Tool for generating `alex` sdist
category: Development
build-type: Simple

executable gen-alex-sdist
default-language: Haskell2010
main-is: Main.hs
build-depends: base < 5
, cpphs >= 1.20.8 && < 1.21
, directory < 1.4
, process < 1.7
, filepath < 1.5
9 changes: 7 additions & 2 deletions tests/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
ALEX=../dist/build/alex/alex
# NOTE: `cabal` will take care to build the local `alex` executable and place it into $PATH for us to pick up
ALEX:=$(shell which alex)

This comment has been minimized.

Copy link
@peti

peti Apr 2, 2018

Contributor

This change breaks the test suite for users who are running ./Setup test instead of using cabal.

This comment has been minimized.

Copy link
@hvr

hvr Apr 3, 2018

Author Member

Can't you simply invoke it like

PATH=$PWD/dist/build/alex:$PATH ./Setup test

to emulate the behaviour as specified in http://cabal.readthedocs.io/en/latest/developing-packages.html#pkg-field-build-tool-depends ?

This comment has been minimized.

Copy link
@peti

peti Apr 3, 2018

Contributor

I guess I can, but I wonder why I have to?

Why does cabal test behave differently from ./Setup test? The documentation you referred to does not give any indication that this behavior is supposed to be specific to cabal-install. Instead, these docs appear to be talking about Cabal the library, so why doesn't ./Setup test work as well?

This comment has been minimized.

Copy link
@simonmar

simonmar Apr 5, 2018

Member

@hvr can this be fixed? It's undesirable for cabal test to behave differently from ./Setup test.

This comment has been minimized.

Copy link
@simonmar

simonmar Apr 19, 2018

Member

@hvr ping?

This comment has been minimized.

Copy link
@hvr

hvr Apr 19, 2018

Author Member

Good question; fwiw, the Setup.hs interface is becoming more and more a low-level "plumbing" interface (to borrow Git's vocabulary), whereas cabal-install is the porcelain layer which is where the interesting things are being added and thus is slowly getting more logic -- not the least, because it's the layer that has access to some things that are out of scope for the Setup.hs layer. Specifically, the Setup.hs layer knows nothing about the Nix-style store, and that's where build-tools live for next-gen cabal-install; it's no longer Setup.hs responsibility to locate build-tools, so the layer invoking Setup.hs should instead tell Setup.hs where to locate those (in the spirit of the --exact-configuration mode; ideally we'd stop supporting anything but --exact-configuration to avoid having to maintain code-paths that cabal-install doesn't even use anymore)... it's complicated... :-)

This comment has been minimized.

Copy link
@simonmar

simonmar Apr 21, 2018

Member

This is in danger of spiraling out of control a bit. But it looks like you're saying two things:

  1. ./Setup is no longer a supported way for users to build and test packages. I'm sure there are good reasons for wanting to go this way, but it's still a pretty big step. Can we have some design docs/proposals for the changes here, so that all interested parties can comment? A lot of existing docs still suggest building things using runhaskell Setup.
  2. There are a set of requirements on higher-level tooling that uses Cabal-the-library, perhaps via ./Setup. Are these requirements documented?

and therefore

  1. this is wontfix.

is that right?

This comment has been minimized.

Copy link
@peti

peti Apr 23, 2018

Contributor

For what it's worth, the notion that cabal-install is supposed to replace ./Setup as the de-facto build driver for Haskell packages is a nightmare for people who would like to build Haskell packages in a reproducible and sandboxed manner. As far as Nix is concerned, I would certainly not want to have cabal-install run our builds. The same is true for the openSUSE distribution and, I'd guess, for Fedora. cabal-install is problematic because (a) you need a non-trivial Haskell environment to bootstrap the build driver for Haskell packages, (b) cabal has hidden state in $HOME that modifies the build settings beyond what's specified on the command-line, (c) if you run cabal with $HOME unset to combat (b) then it refuses to do anything at all. There's probably other issues I didn't think of right now. Anyhow, the direction in which this development is going is certainly causing trouble to people who want to distribute Haskell packages to normal end-users via their native package managers.

This comment has been minimized.

Copy link
@simonmar

simonmar May 24, 2018

Member

@peti I pushed a fix that should hopefully address this issue, please let me know if it helps.

# NOTE: This assumes that a working `ghc` is on $PATH; this may not necessarily be the same GHC used by `cabal` for building `alex`.
HC=ghc
HC_OPTS=-Wall -fno-warn-missing-signatures -fno-warn-unused-imports -fno-warn-tabs -Werror

Expand Down Expand Up @@ -36,7 +38,9 @@ TESTS = \
tokens_strict_bytestring.x \
unicode.x

TEST_ALEX_OPTS = --template=..
# NOTE: `cabal` will set the `alex_datadir` env-var accordingly before invoking the test-suite
#TEST_ALEX_OPTS = --template=../data/
TEST_ALEX_OPTS=

%.n.hs : %.x
$(ALEX) $(TEST_ALEX_OPTS) $< -o $@
Expand All @@ -62,6 +66,7 @@ all :: $(ALL_TESTS)
clean:
rm -f $(CLEAN_FILES)

# NOTE: The `../dist` path belows don't aren't accurate anymore for recent cabals
interact:
ghci -cpp -i../src -i../dist/build/autogen -i../dist/build/alex/alex-tmp Main -fbreak-on-exception
# -args='--template=.. simple.x -o simple.n.hs'
Expand Down

0 comments on commit afbf177

Please sign in to comment.