Commit cb7aa1ef authored by Ross Paterson's avatar Ross Paterson
Browse files

add a Build-Type field, and use it in setupWrapper

As discussed on the libraries list (Nov 2006), add a field Build-Type
which can be used to declare that this package uses one of the boilerplate
setup scripts.  This allows setupWrapper (used by cabal-setup and
cabal-install) to bypass the setup script in this case and perform
the setup actions itself.
parent 80476823
......@@ -60,6 +60,7 @@ module Distribution.PackageDescription (
Executable(..),
withExe,
exeModules,
BuildType(..),
-- * Build information
BuildInfo(..),
emptyBuildInfo,
......@@ -77,6 +78,7 @@ module Distribution.PackageDescription (
hcOptions,
autogenModuleName,
haddockName,
cabalVersion,
#ifdef DEBUG
hunitTests,
test
......@@ -144,6 +146,7 @@ data PackageDescription
category :: String,
buildDepends :: [Dependency],
descCabalVersion :: VersionRange, -- ^If this package depends on a specific version of Cabal, give that here.
buildType :: BuildType,
-- components
library :: Maybe Library,
executables :: [Executable],
......@@ -168,6 +171,7 @@ emptyPackageDescription
license = AllRightsReserved,
licenseFile = "",
descCabalVersion = AnyVersion,
buildType = Custom,
copyright = "",
maintainer = "",
author = "",
......@@ -270,6 +274,16 @@ type HookedBuildInfo = (Maybe BuildInfo, [(String, BuildInfo)])
emptyHookedBuildInfo :: HookedBuildInfo
emptyHookedBuildInfo = (Nothing, [])
-- | The type of build system used by this package.
data BuildType
= Simple -- ^ calls @Distribution.Simple.defaultMain@
| Configure -- ^ calls @Distribution.Simple.defaultMainWithHooks defaultUserHooks@,
-- which invokes @configure@ to generate additional build
-- information used by later phases.
| Make -- ^ calls @Distribution.Make.defaultMain@
| Custom -- ^ uses user-supplied @Setup.hs@ or @Setup.lhs@ (default)
deriving (Show, Read, Eq)
-- ------------------------------------------------------------
-- * Utils
-- ------------------------------------------------------------
......@@ -381,6 +395,9 @@ basicStanzaFields =
, simpleField "cabal-version"
(text . showVersionRange) parseVersionRange
descCabalVersion (\v pkg -> pkg{descCabalVersion=v})
, simpleField "build-type"
(text . show) parseReadSQ
buildType (\t pkg -> pkg{buildType=t})
, simpleField "license"
(text . show) parseLicenseQ
license (\l pkg -> pkg{license=l})
......@@ -786,7 +803,8 @@ testPkgDescAnswer =
synopsis = "a nice package!",
description = "a really nice package!",
category = "tools",
descCabalVersion=LaterVersion (Version [1,1,1] []),
descCabalVersion=LaterVersion (Version [1,1,1] []),
buildType=Custom,
buildDepends = [Dependency "haskell-src" AnyVersion,
Dependency "HUnit"
(UnionVersionRanges (ThisVersion (Version [1,0,0] ["rain"]))
......@@ -883,7 +901,7 @@ comparePackageDescriptions :: PackageDescription
-> PackageDescription
-> [String] -- ^Errors
comparePackageDescriptions p1 p2
= catMaybes $ myCmp package "package" : myCmp license "license": myCmp licenseFile "licenseFile": myCmp copyright "copyright": myCmp maintainer "maintainer": myCmp author "author": myCmp stability "stability": myCmp testedWith "testedWith": myCmp homepage "homepage": myCmp pkgUrl "pkgUrl": myCmp synopsis "synopsis": myCmp description "description": myCmp category "category": myCmp buildDepends "buildDepends": myCmp library "library": myCmp executables "executables": myCmp descCabalVersion "cabal-version":[]
= catMaybes $ myCmp package "package" : myCmp license "license": myCmp licenseFile "licenseFile": myCmp copyright "copyright": myCmp maintainer "maintainer": myCmp author "author": myCmp stability "stability": myCmp testedWith "testedWith": myCmp homepage "homepage": myCmp pkgUrl "pkgUrl": myCmp synopsis "synopsis": myCmp description "description": myCmp category "category": myCmp buildDepends "buildDepends": myCmp library "library": myCmp executables "executables": myCmp descCabalVersion "cabal-version": myCmp buildType "build-type": []
where myCmp :: (Eq a, Show a) => (PackageDescription -> a)
......
......@@ -54,7 +54,7 @@ module Distribution.ParseUtils (
parseTestedWithQ, parseLicenseQ, parseExtensionQ, parseCommaList, parseOptCommaList,
showFilePath, showToken, showTestedWith, showDependency, showFreeText,
simpleField, listField, commaListField, optsField,
parseReadS, parseQuoted,
parseReadS, parseReadSQ, parseQuoted,
) where
import Text.PrettyPrint.HughesPJ
......@@ -271,6 +271,10 @@ parseLicenseQ = parseQuoted parseReadS <++ parseReadS
parseExtensionQ :: ReadP r Extension
parseExtensionQ = parseQuoted parseReadS <++ parseReadS
-- | Parse something optionally wrapped in quotes.
parseReadSQ :: Read a => ReadP r a
parseReadSQ = parseQuoted parseReadS <++ parseReadS
parseTokenQ :: ReadP r String
parseTokenQ = parseReadS <++ munch1 (\x -> not (isSpace x) && x /= ',')
......
......@@ -9,11 +9,14 @@
-- Portability : portable
--
-- The user interface to building and installing Cabal packages.
-- This builds the setup script and runs it with the given arguments.
-- If there is no setup script, it calls 'defaultMain'.
-- If the @Built-Type@ field is specified as something other than
-- 'Custom', and the current version of Cabal is acceptable, this performs
-- setup actions directly. Otherwise it builds the setup script and
-- runs it with the given arguments.
module Distribution.SetupWrapper (setupWrapper) where
import qualified Distribution.Make as Make
import Distribution.Simple
import Distribution.Simple.Utils
import Distribution.Simple.Configure
......@@ -22,7 +25,8 @@ import Distribution.Simple.Configure
import Distribution.Setup ( reqPathArg )
import Distribution.PackageDescription
( readPackageDescription,
PackageDescription(..) )
PackageDescription(..),
BuildType(..), cabalVersion )
import System.Console.GetOpt
import System.Directory
import Control.Exception ( finally )
......@@ -32,14 +36,14 @@ import System.Directory ( doesFileExist, getCurrentDirectory, setCurrentDirecto
-- read the .cabal file
-- - attempt to find the version of Cabal required
-- if there's a Setup script,
-- if the Cabal file specifies the build type (not Custom),
-- - behave like a boilerplate Setup.hs of that type
-- otherwise,
-- - if we find GHC,
-- - build it with the right version of Cabal
-- - build the Setup script with the right version of Cabal
-- - invoke it with args
-- - if we find runhaskell (TODO)
-- - use runhaskell to invoke it
-- otherwise,
-- - behave like a boilerplate Setup.hs
--
-- Later:
-- - add support for multiple packages, by figuring out
......@@ -78,18 +82,24 @@ setupWrapper args mdir = inDir mdir $ do
('.':pathSeparator:"setup")
args
trySetupScript "Setup.hs" $ do
trySetupScript "Setup.lhs" $ do
trySetupScript ".Setup.hs" $ do
-- Setup.hs doesn't exist, we need to behave like defaultMain
if descCabalVersion pkg_descr == AnyVersion
then defaultMain
-- doesn't matter which version we use, so no need to compile
-- a special Setup.hs.
else do writeFile ".Setup.hs"
"import Distribution.Simple; main=defaultMain"
case lookup (buildType pkg_descr) buildTypes of
Just (mainAction, mainText) ->
if withinRange cabalVersion (descCabalVersion pkg_descr)
then mainAction -- current version is OK, so no need
-- to compile a special Setup.hs.
else do writeFile ".Setup.hs" mainText
trySetupScript ".Setup.hs" $ error "panic! shouldn't happen"
Nothing ->
trySetupScript "Setup.hs" $
trySetupScript "Setup.lhs" $
die "no special Build-Type, but lacks Setup.hs or Setup.lhs"
buildTypes :: [(BuildType, (IO (), String))]
buildTypes = [
(Simple, (defaultMain, "import Distribution.Simple; main=defaultMain")),
(Configure, (defaultMainWithHooks defaultUserHooks,
"import Distribution.Simple; main=defaultMainWithHooks defaultUserHooks")),
(Make, (Make.defaultMain, "import Distribution.Make; main=defaultMain"))]
inDir :: Maybe FilePath -> IO () -> IO ()
inDir Nothing m = m
......
......@@ -5,6 +5,7 @@
<!ENTITY Make '<ulink url="../libraries/Cabal/Distribution-Make.html">Distribution.Make</ulink>'>
<!ENTITY License '<ulink url="../libraries/Cabal/Distribution-License.html#t:License"><literal>License</literal></ulink>'>
<!ENTITY Extension '<ulink url="../libraries/Cabal/Language-Haskell-Extension.html#t:Extension"><literal>Extension</literal></ulink>'>
<!ENTITY BuildType '<ulink url="../libraries/Cabal/Distribution-PackageDescription.html#t:BuildType"><literal>BuildType</literal></ulink>'>
<!ENTITY Alex '<ulink url="http://www.haskell.org/alex/"><command>alex</command></ulink>'>
<!ENTITY Autoconf '<ulink url="http://www.gnu.org/software/autoconf/"><command>autoconf</command></ulink>'>
<!ENTITY C2hs '<ulink url="http://www.cse.unsw.edu.au/~chak/haskell/c2hs/"><command>c2hs</command></ulink>'>
......@@ -129,6 +130,7 @@ License: BSD3
Author: Dean Herington
Homepage: http://hunit.sourceforge.net/
Category: Testing
Build-Type: Simple
Build-Depends: base
Synopsis: Unit testing framework for Haskell
Exposed-modules:
......@@ -149,6 +151,7 @@ Version: 0.0
License: BSD3
Author: Angela Author
Synopsis: Small package with two programs
Build-Type: Simple
Build-Depends: HUnit
Executable: program1
......@@ -170,6 +173,7 @@ Version: 0.0
License: BSD3
Author: Angela Author
Synopsis: Package with library and two programs
Build-Type: Simple
Build-Depends: HUnit
Exposed-Modules: A, B, C
......@@ -366,6 +370,20 @@ Other-Modules: A, C, Utils</programlisting>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>build-type:</literal> <replaceable>identifier</replaceable>
</term>
<listitem>
<para>The type of build used by this package.
Build types are the constructors of the &BuildType; type,
defaulting to <literal>Custom</literal>.
If this field is given a value other than
<literal>Custom</literal>, some tools will be able to
build the package without using the setup script.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>license:</literal> <replaceable>identifier</replaceable>
......@@ -915,9 +933,10 @@ Other-Modules: A, C, Utils</programlisting>
<para>For some packages, especially those interfacing with C
libraries, implementation details and the build procedure depend
on the build environment. The simple build infrastructure
can handle many such situations using a slightly longer
<filename>Setup.hs</filename>:</para>
on the build environment. A variant of the simple build
infrastructure (the <literal>build-type</literal>
<literal>Configure</literal>) handles many such situations using
a slightly longer <filename>Setup.hs</filename>:</para>
<programlisting>
import Distribution.Simple
main = defaultMainWithHooks defaultUserHooks</programlisting>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment