summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/genie/src/actions/xcode/xcode8.lua
blob: c7e1801f1662f9704eaa25029b3efe44404068a6 (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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
--
-- _xcode8.lua
-- Define the Apple XCode 8.0 action and support functions.
--

	local premake = premake
	premake.xcode8 = { }

	local xcode  = premake.xcode
	local xcode8 = premake.xcode8

	function xcode8.XCBuildConfiguration_Target(tr, target, cfg)
		local cfgname = xcode.getconfigname(cfg)
		local installpaths = {
			ConsoleApp = "/usr/local/bin",
			WindowedApp = "$(HOME)/Applications",
			SharedLib = "/usr/local/lib",
			StaticLib = "/usr/local/lib",
			Bundle    = "$(LOCAL_LIBRARY_DIR)/Bundles",
		}

		-- options table to return
		local options = {
			ALWAYS_SEARCH_USER_PATHS = "NO",
			GCC_DYNAMIC_NO_PIC = "NO",
			GCC_MODEL_TUNING = "G5",
			INSTALL_PATH = installpaths[cfg.kind],
			PRODUCT_NAME = cfg.buildtarget.basename,
		}

		if not cfg.flags.Symbols then
			options.DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"
		end

		if cfg.kind ~= "StaticLib" and cfg.buildtarget.prefix ~= "" then
			options.EXECUTABLE_PREFIX = cfg.buildtarget.prefix
		end

		if cfg.targetextension then
			local ext = cfg.targetextension
			options.EXECUTABLE_EXTENSION = iif(ext:startswith("."), ext:sub(2), ext)
		end

		if cfg.flags.ObjcARC then
			options.CLANG_ENABLE_OBJC_ARC = "YES"
		end

--		local outdir = path.getdirectory(cfg.buildtarget.directory)
--		if outdir ~= "." then
--			options.CONFIGURATION_BUILD_DIR = outdir
--		end
		options.CONFIGURATION_BUILD_DIR = "$(SYSROOT)"

		if tr.infoplist then
			options.INFOPLIST_FILE = tr.infoplist.cfg.name
		end

		local infoplist_file = nil

		for _, v in ipairs(cfg.files) do
			-- for any file named *info.plist, use it as the INFOPLIST_FILE
			if (string.find (string.lower (v), 'info.plist') ~= nil) then
				infoplist_file = string.format('$(SRCROOT)/%s', v)
			end
		end

		if infoplist_file ~= nil then
			options.INFOPLIST_FILE = infoplist_file
		end

		local action = premake.action.current()
		xcode.setdeploymenttarget(cfg, action.xcode, options)

		if cfg.kind == "Bundle" and not cfg.options.SkipBundling then
			options.PRODUCT_BUNDLE_IDENTIFIER = "genie." .. cfg.buildtarget.basename:gsub("%s+", ".") --replace spaces with .
			local ext = cfg.targetextension
			if ext then
				options.WRAPPER_EXTENSION = iif(ext:startswith("."), ext:sub(2), ext)
			else
				options.WRAPPER_EXTENSION = "bundle"
			end
		end

		return options
	end

	function xcode8.XCBuildConfiguration_Project(tr, prj, cfg)
		local cfgname = xcode.getconfigname(cfg)
		local archs = {
			Native      = nil,
			x32         = "i386",
			x64         = "x86_64",
			Universal32 = "$(ARCHS_STANDARD_32_BIT)",
			Universal64 = "$(ARCHS_STANDARD_64_BIT)",
			Universal   = "$(ARCHS_STANDARD_32_64_BIT)",
		}

		-- build list of "other" C/C++ flags
		local checks = {
			["-ffast-math"]          = cfg.flags.FloatFast,
			["-ffloat-store"]        = cfg.flags.FloatStrict,
			["-fomit-frame-pointer"] = cfg.flags.NoFramePointer,
		}

		local cflags = { }
		for flag, check in pairs(checks) do
			if check then
				table.insert(cflags, flag)
			end
		end

		-- build list of "other" linked flags. All libraries that aren't frameworks
		-- are listed here, so I don't have to try and figure out if they are ".a"
		-- or ".dylib", which Xcode requires to list in the Frameworks section
		local ldflags = { }
		for _, lib in ipairs(premake.getlinks(cfg, "system")) do
			if not xcode.isframework(lib) then
				table.insert(ldflags, "-l" .. lib)
			end
		end

		local defines = {}
		for k, v in pairs(cfg.defines or {}) do
			defines[k] = v:gsub('[\'"\\\n\r\t ]', function (c) return ({ ['\n'] = '\\n', ['\r'] = '\\r', ['\t'] = '\\t' })[c] or '\\'..c end)
		end

		-- options table to return
		local options = {
			ARCHS                              = archs[cfg.platform],
			CLANG_WARN__DUPLICATE_METHOD_MATCH = "YES",
			CLANG_WARN_BOOL_CONVERSION         = "YES",
			CLANG_WARN_CONSTANT_CONVERSION     = "YES",
			CLANG_WARN_EMPTY_BODY              = "YES",
			CLANG_WARN_ENUM_CONVERSION         = "YES",
			CLANG_WARN_INFINITE_RECURSION      = "YES",
			CLANG_WARN_INT_CONVERSION          = "YES",
			CLANG_WARN_SUSPICIOUS_MOVE         = "YES",
			CLANG_WARN_UNREACHABLE_CODE        = "YES",
			CONFIGURATION_TEMP_DIR             = "$(OBJROOT)",
			ENABLE_STRICT_OBJC_MSGSEND         = "YES",
			ENABLE_TESTABILITY                 = "YES",
			GCC_C_LANGUAGE_STANDARD            = "gnu99",
			GCC_NO_COMMON_BLOCKS               = "YES",
			GCC_PREPROCESSOR_DEFINITIONS       = defines,
			GCC_SYMBOLS_PRIVATE_EXTERN         = "NO",
			GCC_WARN_64_TO_32_BIT_CONVERSION   = "YES",
			GCC_WARN_ABOUT_RETURN_TYPE         = "YES",
			GCC_WARN_UNDECLARED_SELECTOR       = "YES",
			GCC_WARN_UNINITIALIZED_AUTOS       = "YES",
			GCC_WARN_UNUSED_FUNCTION           = "YES",
			GCC_WARN_UNUSED_VARIABLE           = "YES",
			HEADER_SEARCH_PATHS                = table.join(cfg.includedirs, cfg.systemincludedirs),
			LIBRARY_SEARCH_PATHS               = cfg.libdirs,
			OBJROOT                            = cfg.objectsdir,
			ONLY_ACTIVE_ARCH                   = "YES",
			OTHER_CFLAGS                       = table.join(cflags, cfg.buildoptions, cfg.buildoptions_c),
			OTHER_CPLUSPLUSFLAGS               = table.join(cflags, cfg.buildoptions, cfg.buildoptions_cpp),
			OTHER_LDFLAGS                      = table.join(ldflags, cfg.linkoptions),
			SDKROOT                            = xcode.toolset,
			USER_HEADER_SEARCH_PATHS           = cfg.userincludedirs,
		}

		if tr.entitlements then
			options.CODE_SIGN_ENTITLEMENTS = tr.entitlements.cfg.name
		end

		local targetdir = path.getdirectory(cfg.buildtarget.bundlepath)
		if targetdir ~= "." then
			options.CONFIGURATION_BUILD_DIR = "$(SYMROOT)"
			options.SYMROOT = targetdir
		end

		if cfg.flags.Symbols then
			options.COPY_PHASE_STRIP = "NO"
		end

		local excluded = xcode.cfg_excluded_files(prj, cfg)
		if #excluded > 0 then
			options.EXCLUDED_SOURCE_FILE_NAMES = excluded
		end

		if cfg.flags.NoExceptions then
			options.GCC_ENABLE_CPP_EXCEPTIONS = "NO"
		end

		if cfg.flags.NoRTTI then
			options.GCC_ENABLE_CPP_RTTI = "NO"
		end

		if cfg.flags.Symbols and not cfg.flags.NoEditAndContinue then
			options.GCC_ENABLE_FIX_AND_CONTINUE = "YES"
		end

		if cfg.flags.NoExceptions then
			options.GCC_ENABLE_OBJC_EXCEPTIONS = "NO"
		end

		if cfg.flags.Optimize or cfg.flags.OptimizeSize then
			options.GCC_OPTIMIZATION_LEVEL = "s"
		elseif cfg.flags.OptimizeSpeed then
			options.GCC_OPTIMIZATION_LEVEL = 3
		else
			options.GCC_OPTIMIZATION_LEVEL = 0
		end

		if cfg.pchheader and not cfg.flags.NoPCH then
			options.GCC_PRECOMPILE_PREFIX_HEADER = "YES"

			-- Visual Studio requires the PCH header to be specified in the same way
			-- it appears in the #include statements used in the source code; the PCH
			-- source actual handles the compilation of the header. GCC compiles the
			-- header file directly, and needs the file's actual file system path in
			-- order to locate it.

			-- To maximize the compatibility between the two approaches, see if I can
			-- locate the specified PCH header on one of the include file search paths
			-- and, if so, adjust the path automatically so the user doesn't have
			-- add a conditional configuration to the project script.

			local pch = cfg.pchheader
			for _, incdir in ipairs(cfg.includedirs) do

				-- convert this back to an absolute path for os.isfile()
				local abspath = path.getabsolute(path.join(cfg.project.location, incdir))

				local testname = path.join(abspath, pch)
				if os.isfile(testname) then
					pch = path.getrelative(cfg.location, testname)
					break
				end
			end

			options.GCC_PREFIX_HEADER = pch
		end

		if cfg.flags.FatalWarnings then
			options.GCC_TREAT_WARNINGS_AS_ERRORS = "YES"
		end

		if cfg.kind == "Bundle" then
			options.MACH_O_TYPE = "mh_bundle"
		end

		if cfg.flags.StaticRuntime then
			options.STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = "static"
		end

		if cfg.flags.PedanticWarnings or cfg.flags.ExtraWarnings then
			options.WARNING_CFLAGS = "-Wall"
		end

		if cfg.flags.Cpp11 then
			options.CLANG_CXX_LANGUAGE_STANDARD = "c++11"
		elseif cfg.flags.Cpp14 or cfg.flags.CppLatest then
			options.CLANG_CXX_LANGUAGE_STANDARD = "c++14"
		elseif cfg.flags.Cpp17 then
			-- XCode8 does not support C++17, but other actions use this as
			-- base that *do* support C++17, so check if this is the current
			-- action before erroring.
			if premake.action.current() == premake.action.get("xcode8") then
				error("XCode8 does not support C++17.")
			end
		end

		for _, val in ipairs(premake.xcode.parameters) do
			local eqpos = string.find(val, "=")
			if eqpos ~= nil then
				local key = string.trim(string.sub(val, 1, eqpos - 1))
				local value = string.trim(string.sub(val, eqpos + 1))
				options[key] = value
			end
		end

		return options
	end

	function xcode8.project(prj)
		local tr = xcode.buildprjtree(prj)
		xcode.Header(tr, 48)
		xcode.PBXBuildFile(tr)
		xcode.PBXContainerItemProxy(tr)
		xcode.PBXFileReference(tr,prj)
		xcode.PBXFrameworksBuildPhase(tr)
		xcode.PBXGroup(tr)
		xcode.PBXNativeTarget(tr)
		xcode.PBXProject(tr, "8.0")
		xcode.PBXReferenceProxy(tr)
		xcode.PBXResourcesBuildPhase(tr)
		xcode.PBXShellScriptBuildPhase(tr)
		xcode.PBXCopyFilesBuildPhase(tr)
		xcode.PBXSourcesBuildPhase(tr,prj)
		xcode.PBXVariantGroup(tr)
		xcode.PBXTargetDependency(tr)
		xcode.XCBuildConfiguration(tr, prj, {
			ontarget = xcode8.XCBuildConfiguration_Target,
			onproject = xcode8.XCBuildConfiguration_Project,
		})
		xcode.XCBuildConfigurationList(tr)
		xcode.Footer(tr)
	end


--
-- xcode8 action
--

	newaction
	{
		trigger         = "xcode8",
		shortname       = "Xcode 8",
		description     = "Generate Apple Xcode 8 project files",
		os              = "macosx",

		valid_kinds     = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" },

		valid_languages = { "C", "C++" },

		valid_tools     = {
			cc     = { "gcc" },
		},

		valid_platforms = {
			Native = "Native",
			x32 = "Native 32-bit",
			x64 = "Native 64-bit",
			Universal = "Universal",
		},

		default_platform = "Native",

		onsolution = function(sln)
			premake.generate(sln, "%%.xcworkspace/contents.xcworkspacedata", xcode.workspace_generate)
			premake.generate(sln, "%%.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings", xcode.workspace_settings)
			premake.generate(sln, "%%.xcworkspace/xcshareddata/xcschemes/-ALL-.xcscheme", xcode.workspace_scheme)
		end,

		onproject = function(prj)
			premake.generate(prj, "%%.xcodeproj/project.pbxproj", xcode8.project)
			xcode.generate_schemes(prj, "%%.xcodeproj/xcshareddata/xcschemes")
		end,

		oncleanproject = function(prj)
			premake.clean.directory(prj, "%%.xcodeproj")
			premake.clean.directory(prj, "%%.xcworkspace")
		end,

		oncheckproject = xcode.checkproject,

		xcode = {
			iOSTargetPlatformVersion = nil,
			macOSTargetPlatformVersion = nil,
			tvOSTargetPlatformVersion = nil,
		},
	}