Automating Xcode 4 Template Generation

Hello again!,

It’s a nice day in the French Riviera ( or Côte d’azur )!, it’s been more work than pleasure here, but I guess life is good :D

Nice Ville

In this iDevBlogADay post I will describe how we managed to automate our needs for Xcode 4 template generation. We wanted to automate it because we use a little Engine here at Gando Games (GG), and project templates where more or less a must for us. I have been reading everywhere about project templates in Xcode 4, and I must admit that it’s a rather obscure process. In order to understand a bit more, I followed the Boreal’s Kiss “A minimal project template for Xcode 4” article. After reading it, I realized that since our toolset was changing quite often, we where going to need to somehow automate the generation of Xcode 4 Templates for our internal engine, plus I thought it was a cool thing to do :)

That lead me to extend a very basic Cocos2d tool called Template Generator. This tool is just a simple python script which can build a very basic TemplateInfo.plist, which is basically a .plist file used to describe an Xcode 4 Template, this was great but wasn’t enough for my needs. After having found that tool, I contacted Ricardo Quesada (Cocos2d Lead Developer) and asked him if I could just take that tool and start a new “mini project” from there, he was very cool about it so I started hacking the script right away.

The results can be found in Github under the MIT license under the name of “Xcode 4 Template Generator“, I think the short description is self explanatory:

The Xcode 4 template generator, is a simple script written in Python to aid in the rather obscure process of creating Xcode 4 templates. As you may already be aware, Xcode 4 templates are very different from Xcode 3 templates, so taking a look at Boreal’s Kiss “A minimal project template for Xcode 4” is recommended. In that article you will find a lot of information about what is currently known about the new Template System.

I thought about this tool as a helper script for a meta script ran my Continuous Integration server, this meta script is the one in charge of actually building the full Xcode 4 template, I present you that script here:

WARNING: My Python is really noobish, sorry for that… ;)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
#!/usr/bin/python
import shutil
import sys
import os
import subprocess
 
ROOT_PATH = "GGEngine/"
SRC_PATH = "src/gengine"
GG_USERNAME = "username"
GIT_REPO_URL = "ssh://" + GG_USERNAME + "@gandogames.com/path/to/engine.git "
 
def shell_exec(command):
subprocess.call(command, shell=True)
def header_print(text):
print("+\t" + text + "\t")
 
if (os.path.exists(SRC_PATH)):
header_print("Pulling GGEngine from Master ")
 
pull_command = """
cd %s &&
git --git-dir=.git fetch &&
git --git-dir=.git --work-tree=. merge origin/master
""" % SRC_PATH
shell_exec(pull_command)
 
else:
#checkout gengine.
header_print("Cloning Good Game Engine from Master")
shell_exec("git clone " + GIT_REPO_URL)
 
#Library Directory Paths.
LUA_PATH = SRC_PATH + "/Libraries/Lua/Lua-5.1.4/src/"
BOX2D_PATH = SRC_PATH + "/Libraries/Box2D/Box2D/"
COCOSDENSHION_PATH = SRC_PATH + "/Libraries/CocosDenshion/"
UNIT_TEST_PP_PATH = SRC_PATH + "/Libraries/UnitTest++/UnitTest++/"
GGENGINE_PATH = SRC_PATH + "/Classes/Engine "
GGENGINE_SCRIPTS_PATH = SRC_PATH + "/Resources/Scripts"
GGENGINE_AUDIO_VISUAL_PATH = "\"" + SRC_PATH + "/Resources/Audio " + SRC_PATH + "/Resources/Fonts " + SRC_PATH + "/Resources/Graphics" + "\""
 
#Template Output Paths
LUA_OUT = ROOT_PATH + "lua"
BOX2D_OUT = ROOT_PATH + "box2d"
COCOSDENSHION_OUT = ROOT_PATH + "ccdenshion"
UNIT_TEST_PP_OUT = ROOT_PATH + "unittestpp"
GGENGINE_OUT = ROOT_PATH + "ggengine"
GGENGINE_SCRIPTS_OUT = ROOT_PATH + "ggengine_scripts"
GGENGINE_AUDIO_VISUAL_OUT = ROOT_PATH + "ggengine_audiovisual"
 
#Library Identifiers
LUA_ID = "com.gandogames.lualib"
BOX2D_ID = "com.gandogames.box2d"
COCOSDENSHION_ID = "com.gandogames.ccdenshion"
UNIT_TEST_PP_ID = "com.gandogames.unittest"
GGENGINE_ID = "com.gandogames.ggengine"
GGENGINE_SCRIPTS_ID = "com.gandogames.ggengine_scripts"
GGENGINE_AUDIO_VISUAL_ID = "com.gandogames.ggengine_audiovisual"
 
#check for Libraries directory and delete if it exists
if (os.path.exists(ROOT_PATH)):
shutil.rmtree(ROOT_PATH)
 
#create templates for all the engine required libraries
 
#Lua
header_print("Creating Lualib Template (abstract)")
shell_exec("python template_generator.py -d " + LUA_PATH + " --description \"Lua Lib\" -i " + LUA_ID + " -c no -o " + LUA_OUT )
 
#Box2d
header_print("Creating Box2d Template (abstract)")
shell_exec("python template_generator.py -d " + BOX2D_PATH + " --description \"Box2d Lib\" -i " + BOX2D_ID + " -c no -o " + BOX2D_OUT)
 
#CocosDenshion
header_print("Creating CocosDenshion Template (abstract)")
shell_exec("python template_generator.py -d " + COCOSDENSHION_PATH + " --description \"CocosDenshion Lib\" -i " + COCOSDENSHION_ID + " -c no -o " + COCOSDENSHION_OUT)
 
#UnitTest++
header_print("Creating UnitTest++ Template (abstract)")
shell_exec("python template_generator.py -d " + UNIT_TEST_PP_PATH + " --description \"UnitTest++ Lib\" -i " + UNIT_TEST_PP_ID + " -c no -o " + UNIT_TEST_PP_OUT)
 
#create template for the Engine Lua scripts
header_print("Creating GGEngine Scripts Template (abstract)")
shell_exec("python template_generator.py -d " + GGENGINE_SCRIPTS_PATH + " --description \"GGEngine Lua Scripts\" -i " + GGENGINE_SCRIPTS_ID + " -c no -o " + GGENGINE_SCRIPTS_OUT)
 
#create template for the Engine audio-vidual Resources
header_print("Creating GGEngine Audio/Visual Template (abstract)")
shell_exec("python template_generator.py -d " + GGENGINE_AUDIO_VISUAL_PATH + " --description \"GGEngine Audiovisual resources\" -i " + GGENGINE_AUDIO_VISUAL_ID + " -c no -o " + GGENGINE_AUDIO_VISUAL_OUT)
 
#create template for the Engine itself
header_print("Creating GGEngine Template (abstract)")
shell_exec("python template_generator.py -d " + GGENGINE_PATH + " --description \"Freetype Lib\" -i " + GGENGINE_ID + " --ancestors \"" + LUA_ID + " " + BOX2D_ID + " " + COCOSDENSHION_ID + " " + UNIT_TEST_PP_ID + " " + GGENGINE_AUDIO_VISUAL_ID + " " + GGENGINE_SCRIPTS_ID +"\" -c no -o " + GGENGINE_OUT)
 
#Copy the Base (concrete) OpenGL ES template
header_print("Moving Base GL ES Template (concrete)")
shell_exec("cp -R base/OpenGLGame.xctemplate GGEngine/")
shell_exec("cp -R base/CocoaTouchApplication.xctemplate GGEngine/")
shell_exec("cp -R base/StoryboardApplication.xctemplate GGEngine/")
shell_exec("cp -R base/iPhoneBase.xctemplate GGEngine/")

So, that’s basically it more or less. I hope that from that script you’re able to extrapolate what you need in order to automate your Xcode 4 Template generation. As a last thing to say, the Xcode 4 Template Generator is far from complete, and should have issues… if you happen to need a patch feel free to open an issue in Github… or you want to collaborate I will totally welcome any kind of help, pull requests etc.

Until the next one!



Comments

  1. Kas August 26th

    Comment Arrow

    Thank u so much 4 this python tool ^^

    btw, could u tell me more about ‘how to use’ on OS X ?

    this is python script, so dont know how to use this with some options.

    simply, there is Xcode template project on Desktop, named ‘HoHo’.
    then how to make plist by this tool ?

    could u tell me more ^^;;;

    thanks in advance !


  2. Kas August 26th

    Comment Arrow

    oh got it ^^ thank u !


  3. Nicolas Goles August 26th

    Comment Arrow

    Kas it’s good to hear that it worked for you :) , it’s not REALLY 100% automated, but with a little work (like my “meta” python script example) you can get it to work.

    There’s also some information in the Wiki of the Github webpage of the project.

    Cheers!


Add Yours

  • Author Avatar

    YOU


Comment Arrow



About Author

Nicolas Goles

Gando Games Founder and Lead Engineer, Nicolas is also a software Engineering Student in Santiago, Chile. Mostly developing Games and Utilities for iPhone/iPad/iPod Touch with C/C++/Obj-C and some lua. He has also worked in Mobile Peer-to-Peer (P2P) application and prototype development.