packages feed

kit-0.2: Kit/XCode/Builder.hs

module Kit.XCode.Builder (buildXCodeProject) where

  import Data.Monoid
  import Data.List
  import Kit.XCode.Common
  import Kit.XCode.ProjectFile
  import Kit.Util
  
  createBuildFile :: Integer -> FilePath -> PBXBuildFile
  createBuildFile i path = PBXBuildFile uuid1 $ PBXFileReference uuid2 path
    where uuid1 = uuid i
          uuid2 = uuid $ i + 10000000
  
  buildXCodeProject :: [FilePath] -> [FilePath] -> String
  buildXCodeProject headers sources = 
      projectPbxProj bfs frs classes hs srcs 
    where
      sourceStart = toInteger (length headers + 1)
      headerBuildFiles = zipWith createBuildFile [1..] headers
      sourceBuildFiles = zipWith createBuildFile [sourceStart..] sources
      allBuildFiles = (sourceBuildFiles ++ headerBuildFiles)
      bfs = buildFileSection allBuildFiles
      frs = fileReferenceSection $ map buildFileReference allBuildFiles
      classes = classesSection $ map buildFileReference (sourceBuildFiles ++ headerBuildFiles)
      hs = headersSection headerBuildFiles
      srcs = sourcesSection sourceBuildFiles
  
  xxx :: FilePath -> UUID -> UUID -> PBXBuildFile
  xxx fp buildId fileId = PBXBuildFile buildId (PBXFileReference fileId fp)

  -- 47021EC1117A7776003DB5B7 /* motive.m in Sources */ = {isa = PBXBuildFile; fileRef = 47021EBF117A7776003DB5B7 /* motive.m */; };
  buildFileItem :: PBXBuildFile -> String
  buildFileItem bf = lineItem i comment dict
    where fr = buildFileReference bf
          i = buildFileId bf
          comment = let ft Unknown = "Unknown"
                        ft Header = "Headers"
                        ft Source = "Sources"
                        bit = ft . fileType . fileReferencePath $ fr
                    in fileReferenceName fr ++ " in " ++ bit
          dict = [
              "isa" ~> "PBXBuildFile",
              "fileRef" ~> (fileReferenceId fr ++ " /* " ++ fileReferenceName fr ++ " */")
            ]

  fileTypeBit :: FileType -> String
  fileTypeBit Header = "sourcecode.c.h"
  fileTypeBit Source = "sourcecode.c.objc"
  fileTypeBit Unknown = "sourcecode.unknown"

  -- 47021EBE117A7776003DB5B7 /* motive.h */ = {isa = PBXFileReference; fileEncoding = 4;
  -- lastKnownFileType = sourcecode.c.h; name = motive.h; path = "kits/motive-0.1/src/motive.h"; sourceTree = "<group>"; };
  fileReferenceItem :: PBXFileReference -> String
  fileReferenceItem fr = lineItem fid fileName dict
    where
      fid = fileReferenceId fr
      path = fileReferencePath fr
      fileName = fileReferenceName fr
      dict = [
          "isa" ~> "PBXFileReference",
          "fileEncoding" ~> "4",
          "lastKnownFileType" ~> (fileTypeBit . fileType $ fileName),
          "name" ~> show fileName,
          "path" ~> show path,
          "sourceTree" ~> show "<group>"
        ]
      
  layoutSection :: String -> [String] -> String
  layoutSection name body = let 
      front  = "/* Begin " ++ name ++ " section */"
      middle = map ("    " ++) body
      back   = "/* End " ++ name ++ " section */"
      in mconcat $ intersperse "\n" ((front : middle) ++ [back])

  buildFileSection :: [PBXBuildFile] -> String
  buildFileSection bfs = layoutSection "PBXBuildFile" (map buildFileItem bfs ++ [
      "4728C530117C02B10027D7D1 /* Kit.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 4728C52F117C02B10027D7D1 /* Kit.xcconfig */; };",
      "AA747D9F0F9514B9006C5449 /* KitDeps_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = AA747D9E0F9514B9006C5449 /* KitDeps_Prefix.pch */; };",
      "AACBBE4A0F95108600F1A2B1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AACBBE490F95108600F1A2B1 /* Foundation.framework */; };"
    ])  
    
  fileReferenceSection :: [PBXFileReference] -> String
  fileReferenceSection refs = layoutSection "PBXFileReference" (map fileReferenceItem refs ++ [
  		"4728C52F117C02B10027D7D1 /* Kit.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Kit.xcconfig; sourceTree = \"<group>\"; };",
      "AA747D9E0F9514B9006C5449 /* KitDeps_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KitDeps_Prefix.pch; sourceTree = SOURCE_ROOT; };",
	    "AACBBE490F95108600F1A2B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };",
	    "D2AAC07E0554694100DB518D /* libKitDeps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libKitDeps.a; sourceTree = BUILT_PRODUCTS_DIR; };"
    ])

  classesSection :: [PBXFileReference] -> String
  classesSection files = lineItem "08FB77AEFE84172EC02AAC07" "Classes" dict
	    where dict = [
            	    "isa" ~> "PBXGroup",
            	    "children" ~> ("(" ++ (mconcat (intersperse "," (map fileReferenceId files))) ++ ",)"),
            	    "name" ~> "Classes",
            	    "sourceTree" ~> show "<group>"
	                ]
	
	{-/* Begin PBXHeadersBuildPhase section */
  		D2AAC07A0554694100DB518D /* Headers */ = {
  			isa = PBXHeadersBuildPhase;
  			buildActionMask = 2147483647;
  			files = (
  				AA747D9F0F9514B9006C5449 /* KitDeps_Prefix.pch in Headers */,
  				4791C244117A7893001EB278 /* motive.h in Headers */,
  			);
  			runOnlyForDeploymentPostprocessing = 0;
  		};
  /* End PBXHeadersBuildPhase section */-}                
  headersSection :: [PBXBuildFile] -> String
  headersSection bfs = layoutSection "PBXHeadersBuildPhase" [lineItem "D2AAC07A0554694100DB518D" "Headers" [
    "isa" ~> "PBXHeadersBuildPhase",
    "buildActionMask" ~> "2147483647",
    "files" ~> ("(" ++ (stringJoin "," $ prefixPchUUID : map buildFileId bfs) ++ ",)"),
    "runOnlyForDeploymentPostprocessing" ~> "0"
	  ]]
	  where prefixPchUUID = "AA747D9F0F9514B9006C5449"
	  
	{-
    /* Begin PBXSourcesBuildPhase section */
    		D2AAC07B0554694100DB518D /* Sources */ = {
    			isa = PBXSourcesBuildPhase;
    			buildActionMask = 2147483647;
    			files = (
    				47021EC1117A7776003DB5B7 /* motive.m in Sources */,
    			);
    			runOnlyForDeploymentPostprocessing = 0;
    		};
    /* End PBXSourcesBuildPhase section */
	-}
  sourcesSection :: [PBXBuildFile] -> String
  sourcesSection bfs = layoutSection "PBXSourcesBuildPhase" [lineItem "D2AAC07B0554694100DB518D" "Sources" [
    "isa" ~> "PBXSourcesBuildPhase",
    "buildActionMask" ~> "2147483647",
    "files" ~> ("(" ++ (stringJoin "," $ map buildFileId bfs) ++ ",)"),
    "runOnlyForDeploymentPostprocessing" ~> "0"
    ]]
  
  testBuilder = let
    header = PBXFileReference "1" "fk/fk.h"
    source = PBXFileReference "2" "fk/fk.m"
    headerBF = PBXBuildFile "10" header
    sourceBF = PBXBuildFile "20" source
      in do
          putStrLn . buildFileSection $  [headerBF, sourceBF]
          putStrLn . fileReferenceSection $ [header, source]