packages feed

kit-0.7.9: Kit/Xcode/Builder.hs

{-# LANGUAGE PackageImports #-}
module Kit.Xcode.Builder (renderXcodeProject) where
  import Kit.Xcode.Common
  import Kit.Xcode.ProjectFileTemplate
  import Text.PList
  import qualified Text.PList.PrettyPrint as PList (pp, ppFlat)
  import Kit.Util
  import Data.List (nub)
  import "mtl" Control.Monad.State

  createBuildFile :: Integer -> FilePath -> PBXBuildFile
  createBuildFile i path = PBXBuildFile uuid1 $ PBXFileReference uuid2 path
    where uuid1 = uuid i
          uuid2 = uuid $ i + 10000000

  buildFileFromState :: FilePath -> State [Integer] PBXBuildFile
  buildFileFromState filePath = flip createBuildFile filePath <$> popS 

  -- | Render an Xcode project!
  renderXcodeProject :: 
    [FilePath]    -- ^ Headers  
    -> [FilePath] -- ^ Sources
    -> [FilePath] -- ^ Static Libs
    -> String     -- ^ Output lib name
    -> String     
  renderXcodeProject headers sources libs outputLibName = fst . flip runState [1..] $ 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 $ 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 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"
    ]