Merge pull request #233 from DanielG/dev-pkgs

Make package dependencies consistent with Cabal
This commit is contained in:
Kazu Yamamoto 2014-05-08 10:24:23 +09:00
commit 89bd2ca08b
17 changed files with 218 additions and 66 deletions

3
.gitignore vendored
View File

@ -1,7 +1,8 @@
dist/
elisp/*.elc
*~
.cabal-sandbox/
/.cabal-sandbox/
package.cache
cabal.sandbox.config
# Mac OS generates
# .DS_Store

View File

@ -8,26 +8,26 @@ before_install:
- sudo add-apt-repository -y ppa:hvr/ghc
- sudo apt-get update
- sudo apt-get install cabal-install-1.18 ghc-$GHCVER
- export PATH=/opt/ghc/$GHCVER/bin:$PATH
- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/1.18/bin:$PATH
install:
- cabal-1.18 update
- cabal-1.18 install happy
- cabal update
- cabal install happy
- export PATH=$HOME/.cabal/bin:$PATH
- happy --version
- cabal-1.18 install --only-dependencies --enable-tests
- cabal install --only-dependencies --enable-tests
script:
- cabal-1.18 configure --enable-tests
- cabal-1.18 build
- cabal-1.18 test
- cabal-1.18 check
- cabal-1.18 sdist
- cabal configure --enable-tests
- cabal build
- cabal test
- cabal check
- cabal sdist
# The following scriptlet checks that the resulting source distribution can be built & installed
- export SRC_TGZ=$(cabal-1.18 info . | awk '{print $2 ".tar.gz";exit}');
- export SRC_TGZ=$(cabal info . | awk '{print $2 ".tar.gz";exit}');
cd dist/;
if [ -f "$SRC_TGZ" ]; then
cabal-1.18 install --enable-tests "$SRC_TGZ";
cabal install --enable-tests "$SRC_TGZ";
else
echo "expected '$SRC_TGZ' not found";
exit 1;

View File

@ -7,20 +7,26 @@ module Language.Haskell.GhcMod.CabalApi (
, cabalDependPackages
, cabalSourceDirs
, cabalAllTargets
, cabalGetConfig
, cabalConfigPath
, cabalConfigDependencies
) where
import Language.Haskell.GhcMod.Types
import Language.Haskell.GhcMod.GhcPkg
import Language.Haskell.GhcMod.Utils
import Control.Applicative ((<$>))
import Control.Exception (throwIO)
import Control.Exception (throwIO,catch,SomeException)
import Control.Monad (filterM)
import CoreMonad (liftIO)
import Data.Maybe (maybeToList, catMaybes)
import Data.Maybe (maybeToList)
import Data.Set (fromList, toList)
import Data.List (find,tails,isPrefixOf)
import Distribution.ModuleName (ModuleName,toFilePath)
import Distribution.Package (Dependency(Dependency)
, PackageName(PackageName))
, PackageName(PackageName)
, InstalledPackageId(..))
import qualified Distribution.Package as C
import Distribution.PackageDescription (PackageDescription, BuildInfo, TestSuite, TestSuiteInterface(..), Executable)
import qualified Distribution.PackageDescription as P
@ -29,12 +35,15 @@ import Distribution.PackageDescription.Parse (readPackageDescription)
import Distribution.Simple.Compiler (CompilerId(..), CompilerFlavor(..))
import Distribution.Simple.Program (ghcProgram)
import Distribution.Simple.Program.Types (programName, programFindVersion)
import Distribution.Simple.BuildPaths (defaultDistPref)
import Distribution.Simple.Configure (localBuildInfoFile)
import Distribution.Simple.LocalBuildInfo (ComponentName(..),ComponentLocalBuildInfo(..))
import Distribution.System (buildPlatform)
import Distribution.Text (display)
import Distribution.Verbosity (silent)
import Distribution.Version (Version)
import System.Directory (doesFileExist)
import System.FilePath (dropExtension, takeFileName, (</>))
import System.FilePath ((</>))
----------------------------------------------------------------
@ -45,38 +54,13 @@ getCompilerOptions :: [GHCOption]
-> IO CompilerOptions
getCompilerOptions ghcopts cradle pkgDesc = do
gopts <- getGHCOptions ghcopts cradle rdir $ head buildInfos
dbPkgs <- ghcPkgListEx (cradlePkgDbStack cradle)
return $ CompilerOptions gopts idirs (depPkgs dbPkgs)
depPkgs <- cabalConfigDependencies <$> cabalGetConfig cradle
return $ CompilerOptions gopts idirs depPkgs
where
wdir = cradleCurrentDir cradle
rdir = cradleRootDir cradle
Just cfile = cradleCabalFile cradle
thisPkg = dropExtension $ takeFileName cfile
buildInfos = cabalAllBuildInfo pkgDesc
idirs = includeDirectories rdir wdir $ cabalSourceDirs buildInfos
depPkgs ps = attachPackageIds ps
$ removeThem (problematicPackages ++ [thisPkg])
$ cabalDependPackages buildInfos
----------------------------------------------------------------
-- Dependent packages
removeThem :: [PackageBaseName] -> [PackageBaseName] -> [PackageBaseName]
removeThem badpkgs = filter (`notElem` badpkgs)
problematicPackages :: [PackageBaseName]
problematicPackages = [
"base-compat" -- providing "Prelude"
]
attachPackageIds :: [Package] -> [PackageBaseName] -> [Package]
attachPackageIds pkgs = catMaybes . fmap (`lookup3` pkgs)
lookup3 :: Eq a => a -> [(a,b,c)] -> Maybe (a,b,c)
lookup3 _ [] = Nothing
lookup3 k (t@(a,_,_):ls)
| k == a = Just t
| otherwise = lookup3 k ls
----------------------------------------------------------------
-- Include directories for modules
@ -220,3 +204,54 @@ cabalAllTargets pd = do
getExecutableTarget exe = do
let maybeExes = [p </> e | p <- P.hsSourceDirs $ P.buildInfo exe, e <- [P.modulePath exe]]
liftIO $ filterM doesFileExist maybeExes
----------------------------------------------------------------
type CabalConfig = String
-- | Get file containing 'LocalBuildInfo' data. If it doesn't exist run @cabal
-- configure@ i.e. configure with default options like @cabal build@ would do.
cabalGetConfig :: Cradle -> IO CabalConfig
cabalGetConfig cradle =
readFile path `catch'` (\_ -> configure >> readFile path)
where
catch' = catch :: IO a -> (SomeException -> IO a) -> IO a
prjDir = cradleRootDir cradle
path = prjDir </> cabalConfigPath
configure =
withDirectory_ prjDir $ readProcess' "cabal" ["configure"]
-- | Path to 'LocalBuildInfo' file, usually @dist/setup-config@
cabalConfigPath :: FilePath
cabalConfigPath = localBuildInfoFile defaultDistPref
cabalConfigDependencies :: CabalConfig -> [Package]
cabalConfigDependencies config = cfgDepends
where
lbi :: (ComponentName, ComponentLocalBuildInfo, [ComponentName])
-> ComponentLocalBuildInfo
lbi (_,i,_) = i
components = case extractCabalSetupConfig "componentsConfigs" config of
Just comps -> lbi <$> comps
Nothing -> error $
"cabalConfigDependencies: Extracting field `componentsConfigs' from"
++ " setup-config failed"
pids :: [InstalledPackageId]
pids = fst <$> componentPackageDeps `concatMap` components
cfgDepends = filter (("inplace" /=) . pkgId)
$ fromInstalledPackageId <$> pids
-- | Extract part of cabal's @setup-config@, this is done with a mix of manual
-- string processing and use of 'read'. This way we can extract a field from
-- 'LocalBuildInfo' without having to parse the whole thing which would mean
-- depending on the exact version of Cabal used to configure the project as it
-- is rather likley that some part of 'LocalBuildInfo' changed.
--
-- Right now 'extractCabalSetupConfig' can only deal with Lists and Tuples in
-- the field!
extractCabalSetupConfig :: (Read r) => String -> CabalConfig -> Maybe r
extractCabalSetupConfig field config = do
read <$> extractParens <$> find (field `isPrefixOf`) (tails config)

View File

@ -6,6 +6,8 @@ module Language.Haskell.GhcMod.GhcPkg (
, ghcPkgDbStackOpts
, ghcDbStackOpts
, ghcDbOpt
, fromInstalledPackageId
, fromInstalledPackageId'
, getSandboxDb
, getPackageDbStack
) where
@ -16,13 +18,12 @@ import Control.Exception (SomeException(..))
import qualified Control.Exception as E
import Data.Char (isSpace,isAlphaNum)
import Data.List (isPrefixOf, intercalate)
import Data.List.Split (splitOn)
import Data.Maybe (listToMaybe, maybeToList)
import Distribution.Package (InstalledPackageId(..))
import Language.Haskell.GhcMod.Types
import Language.Haskell.GhcMod.Utils
import System.Exit (ExitCode(..))
import System.FilePath ((</>))
import System.IO (hPutStrLn,stderr)
import System.Process (readProcessWithExitCode)
import Text.ParserCombinators.ReadP (ReadP, char, between, sepBy1, many1, string, choice, eof)
import qualified Text.ParserCombinators.ReadP as P
@ -58,7 +59,6 @@ getPackageDbStack cdir =
(getSandboxDb cdir >>= \db -> return [GlobalDb, PackageDb db])
`E.catch` \(_ :: SomeException) -> return [GlobalDb, UserDb]
-- | List packages in one or more ghc package store
ghcPkgList :: [GhcPkgDb] -> IO [PackageBaseName]
ghcPkgList dbs = map fst3 <$> ghcPkgListEx dbs
@ -66,14 +66,7 @@ ghcPkgList dbs = map fst3 <$> ghcPkgListEx dbs
ghcPkgListEx :: [GhcPkgDb] -> IO [Package]
ghcPkgListEx dbs = do
(rv,output,err) <- readProcessWithExitCode "ghc-pkg" opts ""
case rv of
ExitFailure val -> do
hPutStrLn stderr err
fail $ "ghc-pkg " ++ unwords opts ++ " (exit " ++ show val ++ ")"
ExitSuccess -> return ()
return $ parseGhcPkgOutput $ lines output
parseGhcPkgOutput .lines <$> readProcess' "ghc-pkg" opts
where
opts = ["list", "-v"] ++ ghcPkgDbStackOpts dbs
@ -92,6 +85,20 @@ packageLine l =
Just ((Hidden,p),_) -> Just p
_ -> Nothing
fromInstalledPackageId' :: InstalledPackageId -> Maybe Package
fromInstalledPackageId' pid = let
InstalledPackageId pkg = pid
in case reverse $ splitOn "-" pkg of
i:v:rest -> Just (intercalate "-" (reverse rest), v, i)
_ -> Nothing
fromInstalledPackageId :: InstalledPackageId -> Package
fromInstalledPackageId pid =
case fromInstalledPackageId' pid of
Just p -> p
Nothing -> error $
"fromInstalledPackageId: `"++show pid++"' is not a valid package-id"
data PackageState = Normal | Hidden | Broken deriving (Eq,Show)
packageLineP :: ReadP (PackageState, Package)

View File

@ -1,5 +1,38 @@
module Language.Haskell.GhcMod.Utils where
import Control.Exception (bracket)
import System.Directory (getCurrentDirectory, setCurrentDirectory)
import System.Process (readProcessWithExitCode)
import System.Exit (ExitCode(..))
import System.IO (hPutStrLn, stderr)
-- dropWhileEnd is not provided prior to base 4.5.0.0.
dropWhileEnd :: (a -> Bool) -> [a] -> [a]
dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []
extractParens :: String -> String
extractParens str = extractParens' str 0
where
extractParens' :: String -> Int -> String
extractParens' [] _ = []
extractParens' (s:ss) level
| s `elem` "([{" = s : extractParens' ss (level+1)
| level == 0 = extractParens' ss 0
| s `elem` "}])" && level == 1 = s:[]
| s `elem` "}])" = s : extractParens' ss (level-1)
| otherwise = s : extractParens' ss level
readProcess' :: String -> [String] -> IO String
readProcess' cmd opts = do
(rv,output,err) <- readProcessWithExitCode cmd opts ""
case rv of
ExitFailure val -> do
hPutStrLn stderr err
fail $ cmd ++ " " ++ unwords opts ++ " (exit " ++ show val ++ ")"
ExitSuccess ->
return output
withDirectory_ :: FilePath -> IO a -> IO a
withDirectory_ dir action =
bracket getCurrentDirectory setCurrentDirectory
(\_ -> setCurrentDirectory dir >> action)

View File

@ -37,6 +37,11 @@ Extra-Source-Files: ChangeLog
test/data/check-test-subdir/test/Bar/*.hs
test/data/check-packageid/cabal.sandbox.config.in
test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/template-haskell-2.8.0.0-32d4f24abdbb6bf41272b183b2e23e9c.conf
test/data/duplicate-pkgver/cabal.sandbox.config.in
test/data/duplicate-pkgver/duplicate-pkgver.cabal
test/data/duplicate-pkgver/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/template-haskell-1.0-7c59d13f32294d1ef6dc6233c24df961.conf
test/data/duplicate-pkgver/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/template-haskell-2.8.0.0-14e543bdae2da4d2aeff5386892c9112.conf
test/data/duplicate-pkgver/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/template-haskell-2.8.0.0-32d4f24abdbb6bf41272b183b2e23e9c.conf
test/data/ghc-mod-check/*.cabal
test/data/ghc-mod-check/*.hs
test/data/ghc-mod-check/Data/*.hs
@ -83,6 +88,7 @@ Library
, syb
, time
, transformers
, split
if impl(ghc < 7.7)
Build-Depends: convertible
, Cabal >= 1.10 && < 1.17
@ -154,6 +160,7 @@ Test-Suite spec
, time
, transformers
, hspec >= 1.8.2
, split
if impl(ghc < 7.7)
Build-Depends: convertible
, Cabal >= 1.10 && < 1.17

View File

@ -19,7 +19,6 @@ import Config (cProjectVersionInt) -- ghc version
ghcVersion :: Int
ghcVersion = read cProjectVersionInt
spec :: Spec
spec = do
describe "parseCabalFile" $ do
@ -39,9 +38,9 @@ spec = do
}
if ghcVersion < 706
then ghcOptions res' `shouldBe` ["-global-package-conf", "-no-user-package-conf","-package-conf",cwd </> "test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d","-XHaskell98"]
else ghcOptions res' `shouldBe` ["-global-package-db", "-no-user-package-db","-package-db",cwd </> "test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d","-XHaskell98"]
else ghcOptions res' `shouldBe` ["-global-package-db", "-no-user-package-db","-package-db",cwd </> "test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d","-XHaskell98","-optP-include","-optP" ++ cwd </> "test/data/dist/build/autogen/cabal_macros.h"]
includeDirs res' `shouldBe` ["test/data","test/data/dist/build","test/data/dist/build/autogen","test/data/subdir1/subdir2","test/data/test"]
depPackages res' `shouldSatisfy` (("Cabal", "1.18.1.3", "2b161c6bf77657aa17e1681d83cb051b")`elem`)
(pkgName `map` depPackages res') `shouldContain` ["Cabal"]
describe "cabalDependPackages" $ do
@ -61,3 +60,10 @@ spec = do
it "extracts build info" $ do
info <- cabalAllBuildInfo <$> parseCabalFile "test/data/cabalapi.cabal"
show info `shouldBe` "[BuildInfo {buildable = True, buildTools = [], cppOptions = [], ccOptions = [], ldOptions = [], pkgconfigDepends = [], frameworks = [], cSources = [], hsSourceDirs = [\".\"], otherModules = [ModuleName [\"Browse\"],ModuleName [\"CabalApi\"],ModuleName [\"Cabal\"],ModuleName [\"CabalDev\"],ModuleName [\"Check\"],ModuleName [\"ErrMsg\"],ModuleName [\"Flag\"],ModuleName [\"GHCApi\"],ModuleName [\"GHCChoice\"],ModuleName [\"Gap\"],ModuleName [\"Info\"],ModuleName [\"Lang\"],ModuleName [\"Lint\"],ModuleName [\"List\"],ModuleName [\"Paths_ghc_mod\"],ModuleName [\"Types\"]], defaultLanguage = Nothing, otherLanguages = [], defaultExtensions = [], otherExtensions = [], oldExtensions = [], extraLibs = [], extraLibDirs = [], includeDirs = [], includes = [], installIncludes = [], options = [(GHC,[\"-Wall\"])], ghcProfOptions = [], ghcSharedOptions = [], customFieldsBI = [], targetBuildDepends = [Dependency (PackageName \"Cabal\") (UnionVersionRanges (ThisVersion (Version {versionBranch = [1,10], versionTags = []})) (LaterVersion (Version {versionBranch = [1,10], versionTags = []}))),Dependency (PackageName \"base\") (IntersectVersionRanges (UnionVersionRanges (ThisVersion (Version {versionBranch = [4,0], versionTags = []})) (LaterVersion (Version {versionBranch = [4,0], versionTags = []}))) (EarlierVersion (Version {versionBranch = [5], versionTags = []}))),Dependency (PackageName \"template-haskell\") AnyVersion]},BuildInfo {buildable = True, buildTools = [], cppOptions = [], ccOptions = [], ldOptions = [], pkgconfigDepends = [], frameworks = [], cSources = [], hsSourceDirs = [\"test\",\".\"], otherModules = [ModuleName [\"Expectation\"],ModuleName [\"BrowseSpec\"],ModuleName [\"CabalApiSpec\"],ModuleName [\"FlagSpec\"],ModuleName [\"LangSpec\"],ModuleName [\"LintSpec\"],ModuleName [\"ListSpec\"]], defaultLanguage = Nothing, otherLanguages = [], defaultExtensions = [], otherExtensions = [], oldExtensions = [], extraLibs = [], extraLibDirs = [], includeDirs = [], includes = [], installIncludes = [], options = [], ghcProfOptions = [], ghcSharedOptions = [], customFieldsBI = [], targetBuildDepends = [Dependency (PackageName \"Cabal\") (UnionVersionRanges (ThisVersion (Version {versionBranch = [1,10], versionTags = []})) (LaterVersion (Version {versionBranch = [1,10], versionTags = []}))),Dependency (PackageName \"base\") (IntersectVersionRanges (UnionVersionRanges (ThisVersion (Version {versionBranch = [4,0], versionTags = []})) (LaterVersion (Version {versionBranch = [4,0], versionTags = []}))) (EarlierVersion (Version {versionBranch = [5], versionTags = []})))]}]"
describe "cabalGetConfig" $ do
it "can reconfigure a cabal package" $ do
withDirectory_ "test/data/check-test-subdir" $ do
cradle <- findCradle
cfg <- cabalGetConfig cradle
cfg `shouldSatisfy` not . null

View File

@ -5,8 +5,16 @@ import Test.Hspec
import System.Process
main = do
let sandboxes = [ "test/data", "test/data/check-packageid" ]
let sandboxes = [ "test/data", "test/data/check-packageid"
, "test/data/duplicate-pkgver/" ]
genSandboxCfg dir = withDirectory dir $ \cwd -> do
system ("sed 's|@CWD@|" ++ cwd ++ "|g' cabal.sandbox.config.in > cabal.sandbox.config")
genSandboxCfg `mapM` sandboxes
pkgDirs =
[ "test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d"
, "test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d"
, "test/data/duplicate-pkgver/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d"]
genGhcPkgCache dir = system $ "ghc-pkg recache --force -f" ++ dir
genSandboxCfg `mapM_` sandboxes
genGhcPkgCache `mapM_` pkgDirs
system "find test -name setup-config -exec rm {} \\;"
hspec spec

11
test/UtilsSpec.hs Normal file
View File

@ -0,0 +1,11 @@
module UtilsSpec where
import Language.Haskell.GhcMod.Utils
import Test.Hspec
spec :: Spec
spec = do
describe "extractParens" $ do
it "extracts the part of a string surrounded by parentheses" $ do
extractParens "asdasdasd ( hello [ world ] )()() kljlkjlkjlk" `shouldBe` "( hello [ world ] )"
extractParens "[(PackageName \"template-haskell\",InstalledPackageId \"template-haskell-2.9.0.0-8e2a49468f3b663b671c437d8579cd28\"),(PackageName \"base\",InstalledPackageId \"base-4.7.0.0-e4567cc9a8ef85f78696b03f3547b6d5\"),(PackageName \"Cabal\",InstalledPackageId \"Cabal-1.18.1.3-b9a44a5b15a8bce47d40128ac326e369\")][][]" `shouldBe` "[(PackageName \"template-haskell\",InstalledPackageId \"template-haskell-2.9.0.0-8e2a49468f3b663b671c437d8579cd28\"),(PackageName \"base\",InstalledPackageId \"base-4.7.0.0-e4567cc9a8ef85f78696b03f3547b6d5\"),(PackageName \"Cabal\",InstalledPackageId \"Cabal-1.18.1.3-b9a44a5b15a8bce47d40128ac326e369\")]"

Binary file not shown.

View File

@ -4,15 +4,15 @@
-- if you want to change the default settings for this sandbox.
local-repo: @CWD@/test/data/.cabal-sandbox/packages
logs-dir: @CWD@/test/data/.cabal-sandbox/logs
world-file: @CWD@/test/data/.cabal-sandbox/world
local-repo: @CWD@/test/data/check-packageid/.cabal-sandbox/packages
logs-dir: @CWD@/test/data/check-packageid/.cabal-sandbox/logs
world-file: @CWD@/test/data/check-packageid/.cabal-sandbox/world
user-install: False
package-db: test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d
build-summary: @CWD@/test/data/.cabal-sandbox/logs/build.log
package-db: @CWD@/test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d
build-summary: @CWD@/test/data/check-packageid/.cabal-sandbox/logs/build.log
install-dirs
prefix: @CWD@/test/data/.cabal-sandbox
prefix: @CWD@/test/data/check-packageid/.cabal-sandbox
bindir: $prefix/bin
libdir: $prefix/lib
libsubdir: $arch-$os-$compiler/$pkgid

View File

@ -0,0 +1,4 @@
name: template-haskell
version: 1.0
id: template-haskell-1.0-7c59d13f32294d1ef6dc6233c24df961
exposed: True

View File

@ -0,0 +1,4 @@
name: template-haskell
version: 2.8.0.0
id: template-haskell-2.8.0.0-14e543bdae2da4d2aeff5386892c9112
exposed: True

View File

@ -0,0 +1,4 @@
name: template-haskell
version: 2.8.0.0
id: template-haskell-2.8.0.0-32d4f24abdbb6bf41272b183b2e23e9c
exposed: True

View File

@ -0,0 +1,25 @@
-- This is a Cabal package environment file.
-- THIS FILE IS AUTO-GENERATED. DO NOT EDIT DIRECTLY.
-- Please create a 'cabal.config' file in the same directory
-- if you want to change the default settings for this sandbox.
local-repo: @CWD@/test/data/duplicate-pkgver/.cabal-sandbox/packages
logs-dir: @CWD@/test/data/duplicate-pkgver/.cabal-sandbox/logs
world-file: @CWD@/test/data/duplicate-pkgver/.cabal-sandbox/world
user-install: False
package-db: @CWD@/test/data/duplicate-pkgver/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d
build-summary: @CWD@/test/data/duplicate-pkgver/.cabal-sandbox/logs/build.log
install-dirs
prefix: @CWD@/test/data/duplicate-pkgver/.cabal-sandbox
bindir: $prefix/bin
libdir: $prefix/lib
libsubdir: $arch-$os-$compiler/$pkgid
libexecdir: $prefix/libexec
datadir: $prefix/share
datasubdir: $arch-$os-$compiler/$pkgid
docdir: $datadir/doc/$arch-$os-$compiler/$pkgid
htmldir: $docdir/html
haddockdir: $htmldir
sysconfdir: $prefix/etc

View File

@ -0,0 +1,7 @@
name: duplicate-pkgver
version: 0.1.0
build-type: Simple
cabal-version: >= 1.8
library
build-depends: base == 4.*