{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} module Distribution.Nixpkgs.Haskell.Derivation ( Derivation, nullDerivation, pkgid, revision, src, subpath, isLibrary, isExecutable , extraFunctionArgs, libraryDepends, executableDepends, testDepends, configureFlags , cabalFlags, runHaddock, jailbreak, doCheck, testTarget, hyperlinkSource, enableSplitObjs , enableLibraryProfiling, enableExecutableProfiling, phaseOverrides, editedCabalFile, metaSection , dependencies, setupDepends, benchmarkDepends, enableSeparateDataOutput ) where import Control.DeepSeq import Control.Lens import Data.List import Data.Set ( Set ) import qualified Data.Set as Set import Data.Set.Lens import Distribution.Nixpkgs.Fetch import Distribution.Nixpkgs.Haskell.BuildInfo import Distribution.Nixpkgs.Haskell.OrphanInstances ( ) import Distribution.Nixpkgs.Meta import Distribution.Package import Distribution.PackageDescription ( FlagAssignment, unFlagName, unFlagAssignment ) import GHC.Generics ( Generic ) import Language.Nix import Language.Nix.PrettyPrinting #if MIN_VERSION_base(4,11,0) import Prelude hiding ((<>)) #endif -- | A represtation of Nix expressions for building Haskell packages. -- The data type correspond closely to the definition of -- 'PackageDescription' from Cabal. data Derivation = MkDerivation { _pkgid :: PackageIdentifier , _revision :: Int , _src :: DerivationSource , _subpath :: FilePath , _isLibrary :: Bool , _isExecutable :: Bool , _extraFunctionArgs :: Set Binding , _setupDepends :: BuildInfo , _libraryDepends :: BuildInfo , _executableDepends :: BuildInfo , _testDepends :: BuildInfo , _benchmarkDepends :: BuildInfo , _configureFlags :: Set String , _cabalFlags :: FlagAssignment , _runHaddock :: Bool , _jailbreak :: Bool , _doCheck :: Bool , _testTarget :: String , _hyperlinkSource :: Bool , _enableLibraryProfiling :: Bool , _enableExecutableProfiling :: Bool , _enableSplitObjs :: Bool , _phaseOverrides :: String , _editedCabalFile :: String , _enableSeparateDataOutput :: Bool , _metaSection :: Meta } deriving (Show, Eq, Generic) nullDerivation :: Derivation nullDerivation = MkDerivation { _pkgid = error "undefined Derivation.pkgid" , _revision = error "undefined Derivation.revision" , _src = error "undefined Derivation.src" , _subpath = error "undefined Derivation.subpath" , _isLibrary = error "undefined Derivation.isLibrary" , _isExecutable = error "undefined Derivation.isExecutable" , _extraFunctionArgs = error "undefined Derivation.extraFunctionArgs" , _setupDepends = error "undefined Derivation.setupDepends" , _libraryDepends = error "undefined Derivation.libraryDepends" , _executableDepends = error "undefined Derivation.executableDepends" , _testDepends = error "undefined Derivation.testDepends" , _benchmarkDepends = error "undefined Derivation.benchmarkDepends" , _configureFlags = error "undefined Derivation.configureFlags" , _cabalFlags = error "undefined Derivation.cabalFlags" , _runHaddock = error "undefined Derivation.runHaddock" , _jailbreak = error "undefined Derivation.jailbreak" , _doCheck = error "undefined Derivation.doCheck" , _testTarget = error "undefined Derivation.testTarget" , _hyperlinkSource = error "undefined Derivation.hyperlinkSource" , _enableLibraryProfiling = error "undefined Derivation.enableLibraryProfiling" , _enableExecutableProfiling = error "undefined Derivation.enableExecutableProfiling" , _enableSplitObjs = error "undefined Derivation.enableSplitObjs" , _phaseOverrides = error "undefined Derivation.phaseOverrides" , _editedCabalFile = error "undefined Derivation.editedCabalFile" , _enableSeparateDataOutput = error "undefined Derivation.enableSeparateDataOutput" , _metaSection = error "undefined Derivation.metaSection" } makeLenses ''Derivation makeLensesFor [("_setupDepends", "dependencies"), ("_libraryDepends", "dependencies"), ("_executableDepends", "dependencies"), ("_testDepends", "dependencies"), ("_benchmarkDepends", "dependencies")] ''Derivation instance Package Derivation where packageId = view pkgid instance NFData Derivation instance Pretty Derivation where pPrint drv@MkDerivation {..} = funargs (map text ("mkDerivation" : toAscList inputs)) $$ vcat [ text "mkDerivation" <+> lbrace , nest 2 $ vcat [ attr "pname" $ doubleQuotes $ disp (packageName _pkgid) , attr "version" $ doubleQuotes $ disp (packageVersion _pkgid) , sourceAttr _src , onlyIf (_subpath /= ".") $ attr "postUnpack" postUnpack , onlyIf (_revision > 0) $ attr "revision" $ doubleQuotes $ int _revision , onlyIf (not (null _editedCabalFile) && _revision > 0) $ attr "editedCabalFile" $ string _editedCabalFile , listattr "configureFlags" empty (map (show . show) renderedFlags) , boolattr "isLibrary" (not _isLibrary || _isExecutable) _isLibrary , boolattr "isExecutable" (not _isLibrary || _isExecutable) _isExecutable , boolattr "enableSeparateDataOutput" _enableSeparateDataOutput _enableSeparateDataOutput , onlyIf (_setupDepends /= mempty) $ pPrintBuildInfo "setup" _setupDepends , onlyIf (_libraryDepends /= mempty) $ pPrintBuildInfo "library" _libraryDepends , onlyIf (_executableDepends /= mempty) $ pPrintBuildInfo "executable" _executableDepends , onlyIf (_testDepends /= mempty) $ pPrintBuildInfo "test" _testDepends , onlyIf (_benchmarkDepends /= mempty) $ pPrintBuildInfo "benchmark" _benchmarkDepends , boolattr "enableLibraryProfiling" _enableLibraryProfiling _enableLibraryProfiling , boolattr "enableExecutableProfiling" _enableExecutableProfiling _enableExecutableProfiling , boolattr "enableSplitObjs" (not _enableSplitObjs) _enableSplitObjs , boolattr "doHaddock" (not _runHaddock) _runHaddock , boolattr "jailbreak" _jailbreak _jailbreak , boolattr "doCheck" (not _doCheck) _doCheck , onlyIf (not (null _testTarget)) $ attr "testTarget" $ string _testTarget , boolattr "hyperlinkSource" (not _hyperlinkSource) _hyperlinkSource , onlyIf (not (null _phaseOverrides)) $ vcat ((map text . lines) _phaseOverrides) , pPrint _metaSection ] , rbrace ] where inputs :: Set String inputs = Set.unions [ Set.map (view (localName . ident)) _extraFunctionArgs , setOf (dependencies . each . folded . localName . ident) drv , Set.fromList ["fetch" ++ derivKind _src | derivKind _src /= "" && not isHackagePackage] ] renderedFlags = [ text "-f" <> (if enable then empty else char '-') <> text (unFlagName f) | (f, enable) <- unFlagAssignment _cabalFlags ] ++ map text (toAscList _configureFlags) isHackagePackage = "mirror://hackage/" `isPrefixOf` derivUrl _src sourceAttr DerivationSource {..} | isHackagePackage = attr "sha256" $ string derivHash | derivKind /= "" = vcat [ text "src" <+> equals <+> text ("fetch" ++ derivKind) <+> lbrace , nest 2 $ vcat [ attr "url" $ string derivUrl , attr "sha256" $ string derivHash , if derivRevision /= "" then attr "rev" (string derivRevision) else empty ] , rbrace <> semi ] | otherwise = attr "src" $ text derivUrl postUnpack = string $ "sourceRoot+=/" ++ _subpath ++ "; echo source root reset to $sourceRoot"