kit-0.7.10: Kit/Xcode/Builder.hs
{-# LANGUAGE PackageImports #-}
module Kit.Xcode.Builder (renderXcodeProject) where
import Kit.Xcode.Common
import Kit.Xcode.ProjectFileTemplate
import Kit.FlaggedFile
import Text.PList
import qualified Text.PList.PrettyPrint as PList (ppFlat)
import Kit.Util
import Data.List (nub, sortBy)
import "mtl" Control.Monad.State
import System.FilePath
import Data.Function (on)
createBuildFile :: Integer -> FlaggedFile -> PBXBuildFile
createBuildFile i ffpath = PBXBuildFile uuid1 (PBXFileReference uuid2 path) compileFlags
where uuid1 = uuid i
uuid2 = uuid $ i + 10000000
path = flaggedFilePath ffpath
compileFlags = flaggedFileFlags ffpath
buildFileFromState :: FlaggedFile -> State [Integer] PBXBuildFile
buildFileFromState filePath = flip createBuildFile filePath <$> popS
-- | Render an Xcode project!
renderXcodeProject ::
[FlaggedFile] -- ^ Headers
-> [FlaggedFile] -- ^ Sources
-> [FlaggedFile] -- ^ Static Libs
-> String -- ^ Output lib name
-> String
renderXcodeProject headers sources libs outputLibName = fst . flip runState [(1::Integer)..] $ do
headerBuildFiles <- mapM buildFileFromState headers
sourceBuildFiles <- mapM buildFileFromState sources
libBuildFiles <- mapM buildFileFromState libs -- Build File Items
let allBuildFiles = sourceBuildFiles ++ headerBuildFiles ++ libBuildFiles
-- Build And FileRef sections
bfs = buildFileSection allBuildFiles
frs = fileReferenceSection (map buildFileReference allBuildFiles) outputLibName
-- Groups
classes = classesGroup $ sortBy (compare `on` (takeFileName . fileReferencePath)) $ map buildFileReference (sourceBuildFiles ++ headerBuildFiles)
fg = frameworksGroup $ map buildFileReference libBuildFiles
-- Phases
headersPhase = headersBuildPhase headerBuildFiles
srcsPhase = sourcesBuildPhase sourceBuildFiles
frameworksPhase = frameworksBuildPhase libBuildFiles
-- UUID indices
libDirs = nub $ map (dropFileName . flaggedFilePath) libs
return . PList.ppFlat $ makeProjectPList (bfs ++ frs ++ [classes, headersPhase, srcsPhase, frameworksPhase, fg]) libDirs
buildFileSection :: [PBXBuildFile] -> [PListObjectItem]
buildFileSection bfs = map buildFileItem bfs ++ [
"4728C530117C02B10027D7D1" ~> buildFile kitConfigRefUUID "",
"AA747D9F0F9514B9006C5449" ~> buildFile "AA747D9E0F9514B9006C5449" "",
"AACBBE4A0F95108600F1A2B1" ~> buildFile "AACBBE490F95108600F1A2B1" ""
]
fileReferenceSection :: [PBXFileReference] -> String -> [PListObjectItem]
fileReferenceSection refs archiveName = map fileReferenceItem refs ++ [
kitConfigRefUUID ~> obj [
"isa" ~> val "PBXFileReference",
"fileEncoding" ~> val "4",
"lastKnownFileType" ~> val "text.xcconfig",
"path" ~> val "DepsOnly.xcconfig",
"sourceTree" ~> val "<group>"
],
"AA747D9E0F9514B9006C5449" ~> obj [
"isa" ~> val "PBXFileReference",
"fileEncoding" ~> val "4",
"lastKnownFileType" ~> val "sourcecode.c.h",
"path" ~> val "Prefix.pch",
"sourceTree" ~> val "SOURCE_ROOT"
],
"AACBBE490F95108600F1A2B1" ~> obj [
"isa" ~> val "PBXFileReference",
"lastKnownFileType" ~> val "wrapper.framework",
"name" ~> val "Foundation.framework",
"path" ~> val "System/Library/Frameworks/Foundation.framework",
"sourceTree" ~> val "SDKROOT"
],
productRefUUID ~> obj [
"isa" ~> val "PBXFileReference",
"explicitFileType" ~> val "archive.ar",
"includeInIndex" ~> val "0",
"path" ~> val archiveName,
"sourceTree" ~> val "BUILT_PRODUCTS_DIR"
]
]
classesGroup :: [PBXFileReference] -> PListObjectItem
classesGroup files = classesGroupUUID ~> group "Classes" (map (val . fileReferenceId) files)
frameworksGroup :: [PBXFileReference] -> PListObjectItem
frameworksGroup files = frameworksGroupUUID ~> group "Frameworks" (val "AACBBE490F95108600F1A2B1" : map (val . fileReferenceId) files)
frameworksBuildPhase :: [PBXBuildFile] -> PListObjectItem
frameworksBuildPhase libs = frameworksBuildPhaseUUID ~> obj [
"isa" ~> val "PBXFrameworksBuildPhase",
"buildActionMask" ~> val "2147483647",
"files" ~> arr (val "AACBBE4A0F95108600F1A2B1" : map (val . buildFileId) libs),
"runOnlyForDeploymentPostprocessing" ~> val "0"
]
headersBuildPhase :: [PBXBuildFile] -> PListObjectItem
headersBuildPhase bfs = headersBuildPhaseUUID ~> obj [
"isa" ~> val "PBXHeadersBuildPhase",
"buildActionMask" ~> val "2147483647",
"files" ~> arr (val "AA747D9F0F9514B9006C5449" : map (val . buildFileId) bfs),
"runOnlyForDeploymentPostprocessing" ~> val "0"
]
sourcesBuildPhase :: [PBXBuildFile] -> PListObjectItem
sourcesBuildPhase bfs = sourcesBuildPhaseUUID ~> obj [
"isa" ~> val "PBXSourcesBuildPhase",
"buildActionMask" ~> val "22147483647147483647",
"files" ~> arr (map (val . buildFileId) bfs),
"runOnlyForDeploymentPostprocessing" ~> val "0"
]