summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/genie/src/actions/xcode/xcode6_project.lua
blob: 3ee73127e2a478e36de858336d59b381c88e32a3 (plain) (blame)
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
--
-- xcode4_project.lua
-- Generate an Xcode4 C/C++ project.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--

local xcode  = premake.xcode
local xcode6 = xcode.xcode6
local tree   = premake.tree

--
-- Create a tree corresponding to what is shown in the Xcode project browser
-- pane, with nodes for files and folders, resources, frameworks, and products.
--
-- @param prj
--    The project being generated.
-- @returns
--    A tree, loaded with metadata, which mirrors Xcode's view of the project.
--

function xcode6.buildprjtree(prj)
	local tr = premake.project.buildsourcetree(prj)
	
	-- create a list of build configurations and assign IDs
	tr.configs = {}
	for _, cfgname in ipairs(prj.solution.configurations) do
		for _, platform in ipairs(prj.solution.xcode.platforms) do
			local cfg = premake.getconfig(prj, cfgname, platform)
			cfg.xcode = {}
			cfg.xcode.targetid = xcode.newid(prj.xcode.projectnode, cfgname)
			cfg.xcode.projectid = xcode.newid(tr, cfgname)
			table.insert(tr.configs, cfg)
		end
	end
	
	-- convert localized resources from their filesystem layout (English.lproj/MainMenu.xib)
	-- to Xcode's display layout (MainMenu.xib/English).
	tree.traverse(tr, {
		onbranch = function(node)
			if path.getextension(node.name) == ".lproj" then
				local lang = path.getbasename(node.name)  -- "English", "French", etc.
				
				-- create a new language group for each file it contains
				for _, filenode in ipairs(node.children) do
					local grpnode = node.parent.children[filenode.name]
					if not grpnode then
						grpnode = tree.insert(node.parent, tree.new(filenode.name))
						grpnode.kind = "vgroup"
					end
					
					-- convert the file node to a language node and add to the group
					filenode.name = path.getbasename(lang)
					tree.insert(grpnode, filenode)
				end
				
				-- remove this directory from the tree
				tree.remove(node)
			end
		end
	})
	
	-- fix .xcassets files, they should be treated as a file, not a folder
	tree.traverse(tr, {
		onbranch = function(node)
			if path.getextension(node.name) == ".xcassets" then
				node.children = {}
			end
		end
	})
			
	-- the special folder "Frameworks" lists all linked frameworks
	tr.frameworks = tree.new("Frameworks")
	for cfg in premake.eachconfig(prj) do
		for _, link in ipairs(premake.getlinks(cfg, "system", "fullpath")) do
			local name = path.getname(link)
			if xcode.isframework(name) and not tr.frameworks.children[name] then
				node = tree.insert(tr.frameworks, tree.new(name))
				node.path = link
			end
		end
	end
	
	-- only add it to the tree if there are frameworks to link
	if #tr.frameworks.children > 0 then 
		tree.insert(tr, tr.frameworks)
	end
	
	-- the special folder "Products" holds the target produced by the project; this
	-- is populated below
	tr.products = tree.insert(tr, tree.new("Products"))

	-- the special folder "Projects" lists sibling project dependencies
	tr.projects = tree.new("Projects")
	for _, dep in ipairs(premake.getdependencies(prj, "sibling", "object")) do
		-- create a child node for the dependency's xcodeproj
		local xcpath = xcode.getxcodeprojname(dep)
		local xcnode = tree.insert(tr.projects, tree.new(path.getname(xcpath)))
		xcnode.path = xcpath
		xcnode.project = dep
		xcnode.productgroupid = xcode.newid(xcnode, "prodgrp")
		xcnode.productproxyid = xcode.newid(xcnode, "prodprox")
		xcnode.targetproxyid  = xcode.newid(xcnode, "targprox")
		xcnode.targetdependid = xcode.newid(xcnode, "targdep")
		
		-- create a grandchild node for the dependency's link target
		local cfg = premake.getconfig(dep, prj.configurations[1])
		node = tree.insert(xcnode, tree.new(cfg.linktarget.name))
		node.path = cfg.linktarget.fullpath
		node.cfg = cfg
	end

	if #tr.projects.children > 0 then
		tree.insert(tr, tr.projects)
	end

	-- Final setup
	tree.traverse(tr, {
		onnode = function(node)
			-- assign IDs to every node in the tree
			node.id = xcode.newid(node)
			
			-- assign build IDs to buildable files
			if xcode.getbuildcategory(node) then
				node.buildid = xcode.newid(node, "build")
			end

			-- remember key files that are needed elsewhere
			if string.endswith(node.name, "Info.plist") then
				tr.infoplist = node
			end						
			if string.endswith(node.name, ".entitlements") then
				tr.entitlements = node
			end
		end
	}, true)

	-- Plug in the product node into the Products folder in the tree. The node
	-- was built in xcode.preparesolution() in xcode_common.lua; it contains IDs
	-- that are necessary for inter-project dependencies
	node = tree.insert(tr.products, prj.xcode.projectnode)
	node.kind = "product"
	node.path = node.cfg.buildtarget.fullpath
	node.cfgsection = xcode.newid(node, "cfg")
	node.resstageid = xcode.newid(node, "rez")
	node.sourcesid  = xcode.newid(node, "src")
	node.fxstageid  = xcode.newid(node, "fxs")

	return tr
end


--
-- Generate an Xcode4 .xcodeproj for a Premake project.
--
-- @param prj
--    The Premake project to generate.
--

function xcode6.project(prj)
	local tr = xcode6.buildprjtree(prj)
	
	xcode6.Header(tr)
	xcode6.PBXProject(tr)
	
	xcode.PBXBuildFile(tr)
	xcode.PBXContainerItemProxy(tr)
	xcode.PBXFileReference(tr,prj)
	xcode.PBXFrameworksBuildPhase(tr)
	xcode.PBXGroup(tr)
	xcode.PBXNativeTarget(tr)
	xcode.PBXReferenceProxy(tr)
	xcode.PBXResourcesBuildPhase(tr)
	xcode.PBXShellScriptBuildPhase(tr)
	xcode.PBXSourcesBuildPhase(tr,prj)
	xcode.PBXVariantGroup(tr)
	xcode.PBXTargetDependency(tr)
	xcode.XCBuildConfiguration(tr)
	xcode.XCBuildConfigurationList(tr)
	
	xcode6.PBXConfigsGroup()
	xcode6.Footer(tr)
end

---------------------------------------------------------------------------
-- Section generator functions, in the same order in which they appear
-- in the .pbxproj file
---------------------------------------------------------------------------

function xcode6.Header()
	_p('// !$*UTF8*$!')
	_p('{')
	_p(1,'archiveVersion = 1;')
	_p(1,'classes = {}')
	_p(1,'objectVersion = 46;')
	_p(1,'rootObject = __RootObject_;')
	_p(1,'objects = {')
end

function xcode6.PBXProject(tr)
	_p(2,'__RootObject_ = {')
	_p(3,'isa = PBXProject;')
	_p(3,'attributes = {LastUpgradeCheck = 9999;};')
	_p(3,'buildConfigurationList = ___RootConfs_;', tr.name)
	_p(3,'compatibilityVersion = "Xcode 3.2";')
	_p(3,'developmentRegion = English;')
	_p(3,'hasScannedForEncodings = 0;')
	_p(3,'knownRegions = (en);')
	_p(3,'mainGroup = ___RootGroup_;')
	_p(3,'projectDirPath = "";')
	_p(3,'projectRoot = "";')
	
	_p(3,'targets = (')
	for _, node in ipairs(tr.products.children) do
		_p(4,'%s /* %s */,', node.targetid, node.name)
	end
	_p(3,');')
	
	if #tr.projects.children > 0 then
		_p(3,'projectReferences = (')
		for _, node in ipairs(tr.projects.children) do
			_p(4,'{')
			_p(5,'ProductGroup = %s /* Products */;', node.productgroupid)
			_p(5,'ProjectRef = %s /* %s */;', node.id, path.getname(node.path))
			_p(4,'},')
		end
		_p(3,');')
	end
	
	_p(2,'};')
	_p('')
end

function xcode6.PBXConfigsGroup()
	_p(2, "_____Configs_ = {")
	_p(3, "isa = PBXGroup;")
	_p(3, "children = (")
	-- '__PBXFileRef_SGLMath.xcodeproj/Configs/Project.xcconfig'
	_p(3, ");")
	_p(3, "name = Configs;")
	_p(3, "sourceTree = '<group>';")
	_p(2, "};")
end

function xcode6.Footer()
	_p(1,'};')
	_p('}')
end