summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/genie/src/actions/xcode/xcode_project.lua
blob: 3a461ebdc167f2f3a6ab38a3e92aa7f3890e30ed (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
--
-- xcode_project.lua
-- Generate an Xcode C/C++ project.
-- Copyright (c) 2009 Jason Perkins and the Premake project
--

	local xcode = premake.xcode
	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 xcode.buildprjtree(prj)
		local tr = premake.project.buildsourcetree(prj, true)

		-- 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, "tgt:"..platform..cfgname)
				cfg.xcode.projectid = xcode.newid(tr, "prj:"..platform..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

		-- Add intermediate paths so groups have sensible locations

		-- find common prefixes going up the tree
		tree.traverse(tr, {
			onbranchexit = function(node)
				for _, child in ipairs(node.children) do
					if (child.location) then
						if (node.location) then
							while (not string.startswith(child.location, node.location)) do
								node.location = path.getdirectory(node.location)
							end
						else
							node.location = path.getdirectory(child.location)
						end
					end
				end
			end,
			onleaf = function(node)
				if (node.cfg) then
					node.location = node.cfg.name
				end
			end
		}, true)

		-- now convert to relative where possible
		tree.traverse(tr, {
			onbranchexit = function(node, depth)
				if (node.location and node.parent and node.parent.location) then
					node.location = path.getrelative(node.parent.location, node.location)
				end
			end,
			onleaf = function(node, depth)
				if (node.location and node.parent and node.parent.location) then
					node.location = path.getrelative(node.parent.location, node.location)
				end
			end
		}, true)

		-- 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