summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/genie/src/actions/xcode/xcode_common.lua
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/genie/src/actions/xcode/xcode_common.lua')
-rw-r--r--3rdparty/genie/src/actions/xcode/xcode_common.lua726
1 files changed, 451 insertions, 275 deletions
diff --git a/3rdparty/genie/src/actions/xcode/xcode_common.lua b/3rdparty/genie/src/actions/xcode/xcode_common.lua
index b3f925273b8..762c27aada1 100644
--- a/3rdparty/genie/src/actions/xcode/xcode_common.lua
+++ b/3rdparty/genie/src/actions/xcode/xcode_common.lua
@@ -18,10 +18,16 @@
function xcode.getbuildcategory(node)
local categories = {
[".a"] = "Frameworks",
+ [".h"] = "Headers",
+ [".hh"] = "Headers",
+ [".hpp"] = "Headers",
+ [".hxx"] = "Headers",
+ [".inl"] = "Headers",
[".c"] = "Sources",
[".cc"] = "Sources",
[".cpp"] = "Sources",
[".cxx"] = "Sources",
+ [".c++"] = "Sources",
[".dylib"] = "Frameworks",
[".bundle"] = "Frameworks",
[".framework"] = "Frameworks",
@@ -39,7 +45,8 @@
[".xcdatamodeld"] = "Sources",
[".swift"] = "Sources",
}
- return categories[path.getextension(node.name)]
+ return categories[path.getextension(node.name)] or
+ categories[string.lower(path.getextension(node.name))]
end
@@ -78,12 +85,17 @@
[".cpp"] = "sourcecode.cpp.cpp",
[".css"] = "text.css",
[".cxx"] = "sourcecode.cpp.cpp",
+ [".c++"] = "sourcecode.cpp.cpp",
[".entitlements"] = "text.xml",
[".bundle"] = "wrapper.cfbundle",
[".framework"] = "wrapper.framework",
[".tbd"] = "sourcecode.text-based-dylib-definition",
[".gif"] = "image.gif",
[".h"] = "sourcecode.c.h",
+ [".hh"] = "sourcecode.cpp.h",
+ [".hpp"] = "sourcecode.cpp.h",
+ [".hxx"] = "sourcecode.cpp.h",
+ [".inl"] = "sourcecode.cpp.h",
[".html"] = "text.html",
[".lua"] = "sourcecode.lua",
[".m"] = "sourcecode.c.objc",
@@ -101,7 +113,8 @@
[".xcdatamodeld"] = "wrapper.xcdatamodeld",
[".swift"] = "sourcecode.swift",
}
- return types[path.getextension(node.path)] or "text"
+ return types[path.getextension(node.path)] or
+ (types[string.lower(path.getextension(node.path))] or "text")
end
--
@@ -120,12 +133,17 @@
[".cpp"] = "sourcecode.cpp.cpp",
[".css"] = "text.css",
[".cxx"] = "sourcecode.cpp.cpp",
+ [".c++"] = "sourcecode.cpp.cpp",
[".entitlements"] = "text.xml",
[".bundle"] = "wrapper.cfbundle",
[".framework"] = "wrapper.framework",
[".tbd"] = "wrapper.framework",
[".gif"] = "image.gif",
[".h"] = "sourcecode.cpp.h",
+ [".hh"] = "sourcecode.cpp.h",
+ [".hpp"] = "sourcecode.cpp.h",
+ [".hxx"] = "sourcecode.cpp.h",
+ [".inl"] = "sourcecode.cpp.h",
[".html"] = "text.html",
[".lua"] = "sourcecode.lua",
[".m"] = "sourcecode.cpp.objcpp",
@@ -142,7 +160,8 @@
[".xcdatamodeld"] = "wrapper.xcdatamodeld",
[".swift"] = "sourcecode.swift",
}
- return types[path.getextension(node.path)] or "text"
+ return types[path.getextension(node.path)] or
+ (types[string.lower(path.getextension(node.path))] or "text")
end
--
-- Return the Xcode product type, based target kind.
@@ -156,10 +175,10 @@
function xcode.getproducttype(node)
local types = {
ConsoleApp = "com.apple.product-type.tool",
- WindowedApp = "com.apple.product-type.application",
+ WindowedApp = node.cfg.options.SkipBundling and "com.apple.product-type.tool" or "com.apple.product-type.application",
StaticLib = "com.apple.product-type.library.static",
SharedLib = "com.apple.product-type.library.dynamic",
- Bundle = "com.apple.product-type.bundle",
+ Bundle = node.cfg.options.SkipBundling and "com.apple.product-type.tool" or "com.apple.product-type.bundle",
}
return types[node.cfg.kind]
end
@@ -177,10 +196,10 @@
function xcode.gettargettype(node)
local types = {
ConsoleApp = "\"compiled.mach-o.executable\"",
- WindowedApp = "wrapper.application",
+ WindowedApp = node.cfg.options.SkipBundling and "\"compiled.mach-o.executable\"" or "wrapper.application",
StaticLib = "archive.ar",
SharedLib = "\"compiled.mach-o.dylib\"",
- Bundle = "wrapper.cfbundle",
+ Bundle = node.cfg.options.SkipBundling and "\"compiled.mach-o.bundle\"" or "wrapper.cfbundle",
}
return types[node.cfg.kind]
end
@@ -216,6 +235,16 @@
return (path.getextension(fname) == ".framework" or path.getextension(fname) == ".tbd")
end
+--
+-- Generates a unique 12 byte ID.
+-- Parameter is optional
+--
+-- @returns
+-- A 24-character string representing the 12 byte ID.
+--
+ function xcode.uuid(param)
+ return os.uuid(param):upper():gsub('-',''):sub(0,24)
+ end
--
-- Retrieves a unique 12 byte ID for an object. This function accepts and ignores two
@@ -226,14 +255,77 @@
-- A 24-character string representing the 12 byte ID.
--
- function xcode.newid()
- return string.format("%04X%04X%04X%04X%04X%04X",
- math.random(0, 32767),
- math.random(0, 32767),
- math.random(0, 32767),
- math.random(0, 32767),
- math.random(0, 32767),
- math.random(0, 32767))
+ function xcode.newid(node, usage)
+ local base = ''
+
+ -- Seed the uuid with the project name and a project-specific counter.
+ -- This is to prevent matching strings from generating the same uuid,
+ -- while still generating the same uuid for the same properties across
+ -- runs.
+ local prj = node.project
+
+ if prj == nil then
+ local parent = node.parent
+ while parent ~= nil do
+ if parent.project ~= nil then
+ prj = parent.project
+ break
+ end
+ parent = parent.parent
+ end
+ end
+
+ if prj ~= nil then
+ prj.uuidcounter = (prj.uuidcounter or 0) + 1
+ base = base .. prj.name .. "$" .. prj.uuidcounter .. "$"
+ end
+
+ base = base .. "$" .. (node.path or node.name or "")
+ base = base .. "$" .. (usage or "")
+ return xcode.uuid(base)
+ end
+
+--
+-- Creates a label for a given scriptphase
+-- based on command and config
+-- such as the result looks like this:
+-- 'Script Phase <number> [cmd] (Config)', e.g. 'Script Phase 1 [rsync] (Debug)'
+--
+-- This function is used for generating `PBXShellScriptBuildPhase` from `xcodescriptphases`.
+-- (Thus required in more than 1 place).
+--
+-- @param cmd
+-- The command itself
+-- @param count
+-- counter to avoid having duplicate label names
+-- @param cfg
+-- The configuration the command is generated for
+--
+
+ function xcode.getscriptphaselabel(cmd, count, cfg)
+ return string.format("\"Script Phase %s [%s] (%s)\"", count, cmd:match("(%w+)(.+)"), iif(cfg, xcode.getconfigname(cfg), "all"))
+ end
+
+
+--
+-- Creates a label for a given copy phase
+-- based on target
+-- such as the result looks like this:
+-- 'Copy <type> <number> [target]', e.g. 'Copy Files 1 [assets]'
+--
+-- This function is used for generating `PBXCopyFilesPhase` from `xcodecopyresources`.
+-- (Thus required in more than 1 place).
+--
+-- @param type
+-- The copy type ('Resources' for now)
+-- @param count
+-- counter to avoid having duplicate label names
+-- @param target
+-- The target subfolder
+--
+
+ function xcode.getcopyphaselabel(type, count, target)
+ return string.format("\"Copy %s %s [%s]\"", type, count, target)
end
@@ -276,11 +368,14 @@
-- The Xcode specific list tag.
--
- function xcode.printlist(list, tag)
+ function xcode.printlist(list, tag, sort)
if #list > 0 then
+ if sort ~= nil and sort == true then
+ table.sort(list)
+ end
_p(4,'%s = (', tag)
for _, item in ipairs(list) do
- local escaped_item = item:gsub("\"", "\\\"")
+ local escaped_item = item:gsub("\"", "\\\\\\\""):gsub("'", "\\\\'")
_p(5, '"%s",', escaped_item)
end
_p(4,');')
@@ -288,24 +383,66 @@
end
+--
+-- Escape a string for use in an Xcode project file.
+--
+
+ function xcode.quotestr(str)
+ -- simple strings don't need quotes
+ if str:match("[^a-zA-Z0-9$._/]") == nil then
+ return str
+ end
+
+ return "\"" .. str:gsub("[\"\\\"]", "\\%0") .. "\""
+ end
+
+
+
---------------------------------------------------------------------------
-- Section generator functions, in the same order in which they appear
-- in the .pbxproj file
---------------------------------------------------------------------------
- function xcode.Header()
- _p('// !$*UTF8*$!')
- _p('{')
- _p(1,'archiveVersion = 1;')
- _p(1,'classes = {')
- _p(1,'};')
- _p(1,'objectVersion = 45;')
- _p(1,'objects = {')
- _p('')
- end
+function xcode.Header(tr, objversion)
+ _p('// !$*UTF8*$!')
+ _p('{')
+ _p(1,'archiveVersion = 1;')
+ _p(1,'classes = {')
+ _p(1,'};')
+ _p(1,'objectVersion = %d;', objversion)
+ _p(1,'objects = {')
+ _p('')
+end
function xcode.PBXBuildFile(tr)
+ local function gatherCopyFiles(which)
+ local copyfiles = {}
+ local targets = tr.project[which]
+ if #targets > 0 then
+ for _, t in ipairs(targets) do
+ for __, tt in ipairs(t) do
+ table.insertflat(copyfiles, tt[2])
+ end
+ end
+ end
+ return table.translate(copyfiles, path.getname)
+ end
+
+ local function gatherCopyFrameworks(which)
+ local copyfiles = {}
+ local targets = tr.project[which]
+ if #targets > 0 then
+ table.insertflat(copyfiles, targets)
+ end
+ return table.translate(copyfiles, path.getname)
+ end
+
+ local copyfiles = table.flatten({
+ gatherCopyFiles('xcodecopyresources'),
+ gatherCopyFrameworks('xcodecopyframeworks')
+ })
+
_p('/* Begin PBXBuildFile section */')
tree.traverse(tr, {
onnode = function(node)
@@ -313,6 +450,15 @@
_p(2,'%s /* %s in %s */ = {isa = PBXBuildFile; fileRef = %s /* %s */; };',
node.buildid, node.name, xcode.getbuildcategory(node), node.id, node.name)
end
+
+ -- adds duplicate PBXBuildFile file entry as 'CopyFiles' for files marked to be copied
+ -- for frameworks: add signOnCopy flag
+ if table.icontains(copyfiles, node.name) then
+ _p(2,'%s /* %s in %s */ = {isa = PBXBuildFile; fileRef = %s /* %s */; %s };',
+ xcode.uuid(node.name .. 'in CopyFiles'), node.name, 'CopyFiles', node.id, node.name,
+ iif(xcode.isframework(node.name), "settings = {ATTRIBUTES = (CodeSignOnCopy, ); };", "")
+ )
+ end
end
})
_p('/* End PBXBuildFile section */')
@@ -381,7 +527,8 @@
end
if string.find(nodePath,'/') then
if string.find(nodePath,'^%.')then
- error('relative paths are not currently supported for frameworks')
+ --error('relative paths are not currently supported for frameworks')
+ nodePath = path.getabsolute(path.join(tr.project.location, nodePath))
end
pth = nodePath
elseif path.getextension(nodePath)=='.tbd' then
@@ -404,9 +551,13 @@
-- something else; probably a source code file
src = "<group>"
- -- if the parent node is virtual, it won't have a local path
- -- of its own; need to use full relative path from project
- if node.parent.isvpath then
+ if node.location then
+ pth = node.location
+ elseif node.parent.isvpath then
+ -- if the parent node is virtual, it won't have a local path
+ -- of its own; need to use full relative path from project
+ -- (in fact, often almost all paths are virtual because vpath
+ -- trims the leading dots from the full path)
pth = node.cfg.name
else
pth = tree.getlocalpath(node)
@@ -486,7 +637,10 @@
_p(3,'name = Products;')
else
_p(3,'name = "%s";', node.name)
- if node.path and not node.isvpath then
+
+ if node.location then
+ _p(3,'path = "%s";', node.location)
+ elseif node.path and not node.isvpath then
local p = node.path
if node.parent.path then
p = path.getrelative(node.parent.path, node.path)
@@ -527,22 +681,85 @@
end
end
+ local function dobuildblock(id, label, which, action)
+ if hasBuildCommands(which) then
+ local commandcount = 0
+ for _, cfg in ipairs(tr.configs) do
+ commandcount = commandcount + #cfg[which]
+ end
+ if commandcount > 0 then
+ action(id, label)
+ end
+ end
+ end
+
+ local function doscriptphases(which, action)
+ local i = 0
+ for _, cfg in ipairs(tr.configs) do
+ local cfgcmds = cfg[which]
+ if cfgcmds ~= nil then
+ for __, scripts in ipairs(cfgcmds) do
+ for ___, script in ipairs(scripts) do
+ local cmd = script[1]
+ local label = xcode.getscriptphaselabel(cmd, i, cfg)
+ local id = xcode.uuid(label)
+ action(id, label)
+ i = i + 1
+ end
+ end
+ end
+ end
+ end
+
+ local function docopyresources(which, action)
+ if hasBuildCommands(which) then
+ local targets = tr.project[which]
+ if #targets > 0 then
+ local i = 0
+ for _, t in ipairs(targets) do
+ for __, tt in ipairs(t) do
+ local label = xcode.getcopyphaselabel('Resources', i, tt[1])
+ local id = xcode.uuid(label)
+ action(id, label)
+ i = i + 1
+ end
+ end
+ end
+ end
+ end
+
+ local function docopyframeworks(which, action)
+ if hasBuildCommands(which) then
+ local targets = tr.project[which]
+ if #targets > 0 then
+ local label = "Copy Frameworks"
+ local id = xcode.uuid(label)
+ action(id, label)
+ end
+ end
+ end
+
+ local function _p_label(id, label)
+ _p(4, '%s /* %s */,', id, label)
+ end
+
+
_p(2,'%s /* %s */ = {', node.targetid, name)
_p(3,'isa = PBXNativeTarget;')
_p(3,'buildConfigurationList = %s /* Build configuration list for PBXNativeTarget "%s" */;', node.cfgsection, name)
_p(3,'buildPhases = (')
- if hasBuildCommands('prebuildcommands') then
- _p(4,'9607AE1010C857E500CD1376 /* Prebuild */,')
- end
+ dobuildblock('9607AE1010C857E500CD1376', 'Prebuild', 'prebuildcommands', _p_label)
_p(4,'%s /* Resources */,', node.resstageid)
_p(4,'%s /* Sources */,', node.sourcesid)
- if hasBuildCommands('prelinkcommands') then
- _p(4,'9607AE3510C85E7E00CD1376 /* Prelink */,')
- end
+ dobuildblock('9607AE3510C85E7E00CD1376', 'Prelink', 'prelinkcommands', _p_label)
_p(4,'%s /* Frameworks */,', node.fxstageid)
- if hasBuildCommands('postbuildcommands') then
- _p(4,'9607AE3710C85E8F00CD1376 /* Postbuild */,')
+ dobuildblock('9607AE3710C85E8F00CD1376', 'Postbuild', 'postbuildcommands', _p_label)
+ doscriptphases("xcodescriptphases", _p_label)
+ docopyresources("xcodecopyresources", _p_label)
+ if tr.project.kind == "WindowedApp" then
+ docopyframeworks("xcodecopyframeworks", _p_label)
end
+
_p(3,');')
_p(3,'buildRules = (')
_p(3,');')
@@ -575,12 +792,12 @@
end
- function xcode.PBXProject(tr)
+ function xcode.PBXProject(tr, compatVersion)
_p('/* Begin PBXProject section */')
_p(2,'__RootObject_ /* Project object */ = {')
_p(3,'isa = PBXProject;')
_p(3,'buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "%s" */;', tr.name)
- _p(3,'compatibilityVersion = "Xcode 3.2";')
+ _p(3,'compatibilityVersion = "Xcode %s";', compatVersion)
_p(3,'hasScannedForEncodings = 1;')
_p(3,'mainGroup = %s /* %s */;', tr.id, tr.name)
_p(3,'projectDirPath = "";')
@@ -653,47 +870,91 @@
function xcode.PBXShellScriptBuildPhase(tr)
local wrapperWritten = false
- local function doblock(id, name, which)
+ local function doblock(id, name, commands, files)
+ if commands ~= nil then
+ commands = table.flatten(commands)
+ end
+ if #commands > 0 then
+ if not wrapperWritten then
+ _p('/* Begin PBXShellScriptBuildPhase section */')
+ wrapperWritten = true
+ end
+ _p(2,'%s /* %s */ = {', id, name)
+ _p(3,'isa = PBXShellScriptBuildPhase;')
+ _p(3,'buildActionMask = 2147483647;')
+ _p(3,'files = (')
+ _p(3,');')
+ _p(3,'inputPaths = (');
+ if files ~= nil then
+ files = table.flatten(files)
+ if #files > 0 then
+ for _, file in ipairs(files) do
+ _p(4, '"%s",', file)
+ end
+ end
+ end
+ _p(3,');');
+ _p(3,'name = %s;', name);
+ _p(3,'outputPaths = (');
+ _p(3,');');
+ _p(3,'runOnlyForDeploymentPostprocessing = 0;');
+ _p(3,'shellPath = /bin/sh;');
+ _p(3,'shellScript = "%s";', table.concat(commands, "\\n"):gsub('"', '\\"'))
+ _p(2,'};')
+ end
+ end
+
+ local function wrapcommands(cmds, cfg)
+ local commands = {}
+ if #cmds > 0 then
+ table.insert(commands, 'if [ "${CONFIGURATION}" = "' .. xcode.getconfigname(cfg) .. '" ]; then')
+ for i = 1, #cmds do
+ local cmd = cmds[i]
+ cmd = cmd:gsub('\\','\\\\')
+ table.insert(commands, cmd)
+ end
+ table.insert(commands, 'fi')
+ end
+ return commands
+ end
+
+ local function dobuildblock(id, name, which)
-- see if there are any commands to add for each config
local commands = {}
for _, cfg in ipairs(tr.configs) do
- local cfgcmds = cfg[which]
+ local cfgcmds = wrapcommands(cfg[which], cfg)
if #cfgcmds > 0 then
- table.insert(commands, 'if [ "${CONFIGURATION}" = "' .. xcode.getconfigname(cfg) .. '" ]; then')
- for i = 1, #cfgcmds do
- local cmd = cfgcmds[i]
- cmd = cmd:gsub('\\','\\\\')
+ for i, cmd in ipairs(cfgcmds) do
table.insert(commands, cmd)
end
- table.insert(commands, 'fi')
end
end
+ doblock(id, name, commands)
+ end
- if #commands > 0 then
- if not wrapperWritten then
- _p('/* Begin PBXShellScriptBuildPhase section */')
- wrapperWritten = true
+ local function doscriptphases(which)
+ local i = 0
+ for _, cfg in ipairs(tr.configs) do
+ local cfgcmds = cfg[which]
+ if cfgcmds ~= nil then
+ for __, scripts in ipairs(cfgcmds) do
+ for ___, script in ipairs(scripts) do
+ local cmd = script[1]
+ local files = script[2]
+ local label = xcode.getscriptphaselabel(cmd, i, cfg)
+ local id = xcode.uuid(label)
+ doblock(id, label, wrapcommands({cmd}, cfg), files)
+ i = i + 1
+ end
+ end
end
- _p(2,'%s /* %s */ = {', id, name)
- _p(3,'isa = PBXShellScriptBuildPhase;')
- _p(3,'buildActionMask = 2147483647;')
- _p(3,'files = (')
- _p(3,');')
- _p(3,'inputPaths = (');
- _p(3,');');
- _p(3,'name = %s;', name);
- _p(3,'outputPaths = (');
- _p(3,');');
- _p(3,'runOnlyForDeploymentPostprocessing = 0;');
- _p(3,'shellPath = /bin/sh;');
- _p(3,'shellScript = "%s";', table.concat(commands, "\\n"):gsub('"', '\\"'))
- _p(2,'};')
end
end
- doblock("9607AE1010C857E500CD1376", "Prebuild", "prebuildcommands")
- doblock("9607AE3510C85E7E00CD1376", "Prelink", "prelinkcommands")
- doblock("9607AE3710C85E8F00CD1376", "Postbuild", "postbuildcommands")
+ dobuildblock("9607AE1010C857E500CD1376", "Prebuild", "prebuildcommands")
+ dobuildblock("9607AE3510C85E7E00CD1376", "Prelink", "prelinkcommands")
+ dobuildblock("9607AE3710C85E8F00CD1376", "Postbuild", "postbuildcommands")
+ doscriptphases("xcodescriptphases")
if wrapperWritten then
_p('/* End PBXShellScriptBuildPhase section */')
@@ -725,6 +986,82 @@
_p('')
end
+ -- copyresources leads to this
+ -- xcodeembedframeworks
+ function xcode.PBXCopyFilesBuildPhase(tr)
+ local wrapperWritten = false
+
+ local function doblock(id, name, folderSpec, path, files)
+ -- note: folder spec:
+ -- 0: Absolute Path
+ -- 1: Wrapper
+ -- 6: Executables
+ -- 7: Resources
+ -- 10: Frameworks
+ -- 16: Products Directory
+ -- category: 'Frameworks' or 'CopyFiles'
+
+ if #files > 0 then
+ if not wrapperWritten then
+ _p('/* Begin PBXCopyFilesBuildPhase section */')
+ wrapperWritten = true
+ end
+ _p(2,'%s /* %s */ = {', id, name)
+ _p(3,'isa = PBXCopyFilesBuildPhase;')
+ _p(3,'buildActionMask = 2147483647;')
+ _p(3,'dstPath = \"%s\";', path)
+ _p(3,'dstSubfolderSpec = \"%s\";', folderSpec)
+ _p(3,'files = (')
+ tree.traverse(tr, {
+ onleaf = function(node)
+ -- print(node.name)
+ if table.icontains(files, node.name) then
+ _p(4,'%s /* %s in %s */,',
+ xcode.uuid(node.name .. 'in CopyFiles'), node.name, 'CopyFiles')
+ end
+ end
+ })
+ _p(3,');')
+ _p(3,'runOnlyForDeploymentPostprocessing = 0;');
+ _p(2,'};')
+ end
+ end
+
+ local function docopyresources(which)
+ local targets = tr.project[which]
+ if #targets > 0 then
+ local i = 0
+ for _, t in ipairs(targets) do
+ for __, tt in ipairs(t) do
+ local label = xcode.getcopyphaselabel('Resources', i, tt[1])
+ local id = xcode.uuid(label)
+ local files = table.translate(table.flatten(tt[2]), path.getname)
+ doblock(id, label, 7, tt[1], files)
+ i = i + 1
+ end
+ end
+ end
+ end
+
+ local function docopyframeworks(which)
+ local targets = tr.project[which]
+ if #targets > 0 then
+ local label = "Copy Frameworks"
+ local id = xcode.uuid(label)
+ local files = table.translate(table.flatten(targets), path.getname)
+ doblock(id, label, 10, "", files)
+ end
+ end
+
+ docopyresources("xcodecopyresources")
+ if tr.project.kind == "WindowedApp" then
+ docopyframeworks("xcodecopyframeworks")
+ end
+
+ if wrapperWritten then
+ _p('/* End PBXCopyFilesBuildPhase section */')
+ end
+ end
function xcode.PBXVariantGroup(tr)
_p('/* Begin PBXVariantGroup section */')
@@ -767,83 +1104,7 @@
end
- function xcode.XCBuildConfiguration_Target(tr, target, cfg)
- local cfgname = xcode.getconfigname(cfg)
-
- _p(2,'%s /* %s */ = {', cfg.xcode.targetid, cfgname)
- _p(3,'isa = XCBuildConfiguration;')
- _p(3,'buildSettings = {')
- _p(4,'ALWAYS_SEARCH_USER_PATHS = NO;')
-
- if not cfg.flags.Symbols then
- _p(4,'DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";')
- end
-
- if cfg.kind ~= "StaticLib" and cfg.buildtarget.prefix ~= "" then
- _p(4,'EXECUTABLE_PREFIX = %s;', cfg.buildtarget.prefix)
- end
-
- if cfg.targetextension then
- local ext = cfg.targetextension
- ext = iif(ext:startswith("."), ext:sub(2), ext)
- _p(4,'EXECUTABLE_EXTENSION = %s;', ext)
- end
-
- if cfg.flags.ObjcARC then
- _p(4,'CLANG_ENABLE_OBJC_ARC = YES;')
- end
-
- local outdir = path.getdirectory(cfg.buildtarget.bundlepath)
- if outdir ~= "." then
- _p(4,'CONFIGURATION_BUILD_DIR = %s;', outdir)
- end
-
- _p(4,'GCC_DYNAMIC_NO_PIC = NO;')
- _p(4,'GCC_MODEL_TUNING = G5;')
-
- if tr.infoplist then
- _p(4,'INFOPLIST_FILE = "%s";', tr.infoplist.cfg.name)
- end
-
- installpaths = {
- ConsoleApp = '/usr/local/bin',
- WindowedApp = '"$(HOME)/Applications"',
- SharedLib = '/usr/local/lib',
- StaticLib = '/usr/local/lib',
- Bundle = '"$(LOCAL_LIBRARY_DIR)/Bundles"',
- }
- _p(4,'INSTALL_PATH = %s;', installpaths[cfg.kind])
-
- 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
- _p(4,'INFOPLIST_FILE = "%s";', infoplist_file)
- end
-
- if cfg.kind == "Bundle" then
- _p(4, 'PRODUCT_BUNDLE_IDENTIFIER = "genie.%s";', cfg.buildtarget.basename:gsub("%s+", '.')) --replace spaces with .
- end
-
- _p(4,'PRODUCT_NAME = "%s";', cfg.buildtarget.basename)
-
- if cfg.kind == "Bundle" then
- _p(4, 'WRAPPER_EXTENSION = bundle;')
- end
-
- _p(3,'};')
- _p(3,'name = "%s";', cfgname)
- _p(2,'};')
- end
-
-
- local function cfg_excluded_files(prj, cfg)
+ function xcode.cfg_excluded_files(prj, cfg)
local excluded = {}
-- Converts a file path to a pattern with no relative parts, prefixed with `*`.
@@ -902,161 +1163,76 @@
end
- function xcode.XCBuildConfiguration_Project(tr, prj, cfg)
+ function xcode.XCBuildConfiguration_Impl(tr, id, opts, cfg)
local cfgname = xcode.getconfigname(cfg)
- _p(2,'%s /* %s */ = {', cfg.xcode.projectid, cfgname)
+ _p(2,'%s /* %s */ = {', id, cfgname)
_p(3,'isa = XCBuildConfiguration;')
_p(3,'buildSettings = {')
- local archs = {
- Native = "$(NATIVE_ARCH_ACTUAL)",
- x32 = "i386",
- x64 = "x86_64",
- Universal32 = "$(ARCHS_STANDARD_32_BIT)",
- Universal64 = "$(ARCHS_STANDARD_64_BIT)",
- Universal = "$(ARCHS_STANDARD_32_64_BIT)",
- }
- _p(4,'ARCHS = "%s";', archs[cfg.platform])
-
- _p(4,'SDKROOT = "%s";', xcode.toolset)
-
- if tr.entitlements then
- _p(4,'CODE_SIGN_ENTITLEMENTS = "%s";', tr.entitlements.cfg.name)
- end
-
- local targetdir = path.getdirectory(cfg.buildtarget.bundlepath)
- if targetdir ~= "." then
- _p(4,'CONFIGURATION_BUILD_DIR = "$(SYMROOT)";');
- end
-
- _p(4,'CONFIGURATION_TEMP_DIR = "$(OBJROOT)";')
+ for k, v in table.sortedpairs(opts) do
+ if type(v) == "table" then
+ if #v > 0 then
+ _p(4,'%s = (', k)
- if cfg.flags.Symbols then
- _p(4,'COPY_PHASE_STRIP = NO;')
- end
+ for i, v2 in ipairs(v) do
+ _p(5,'%s,', xcode.quotestr(tostring(v2)))
+ end
- local excluded = cfg_excluded_files(prj, cfg)
- if #excluded > 0 then
- _p(4, 'EXCLUDED_SOURCE_FILE_NAMES = (')
- for _, file in ipairs(excluded) do
- _p(5, '"' .. file .. '",')
+ _p(4,');')
+ end
+ else
+ _p(4,'%s = %s;', k, xcode.quotestr(tostring(v)))
end
- _p(4, ');')
- end
-
- _p(4,'GCC_C_LANGUAGE_STANDARD = gnu99;')
-
- if cfg.flags.NoExceptions then
- _p(4,'GCC_ENABLE_CPP_EXCEPTIONS = NO;')
- end
-
- if cfg.flags.NoRTTI then
- _p(4,'GCC_ENABLE_CPP_RTTI = NO;')
- end
-
- if _ACTION ~= "xcode4" and cfg.flags.Symbols and not cfg.flags.NoEditAndContinue then
- _p(4,'GCC_ENABLE_FIX_AND_CONTINUE = YES;')
- end
-
- if cfg.flags.NoExceptions then
- _p(4,'GCC_ENABLE_OBJC_EXCEPTIONS = NO;')
- end
-
- if cfg.flags.Optimize or cfg.flags.OptimizeSize then
- _p(4,'GCC_OPTIMIZATION_LEVEL = s;')
- elseif cfg.flags.OptimizeSpeed then
- _p(4,'GCC_OPTIMIZATION_LEVEL = 3;')
- else
- _p(4,'GCC_OPTIMIZATION_LEVEL = 0;')
- end
-
- if cfg.pchheader and not cfg.flags.NoPCH then
- _p(4,'GCC_PRECOMPILE_PREFIX_HEADER = YES;')
- _p(4,'GCC_PREFIX_HEADER = "%s";', cfg.pchheader)
- end
-
- xcode.printlist(cfg.defines, 'GCC_PREPROCESSOR_DEFINITIONS')
-
- _p(4,'GCC_SYMBOLS_PRIVATE_EXTERN = NO;')
-
- if cfg.flags.FatalWarnings then
- _p(4,'GCC_TREAT_WARNINGS_AS_ERRORS = YES;')
end
- _p(4,'GCC_WARN_ABOUT_RETURN_TYPE = YES;')
- _p(4,'GCC_WARN_UNUSED_VARIABLE = YES;')
-
- xcode.printlist(cfg.includedirs, 'HEADER_SEARCH_PATHS')
- xcode.printlist(cfg.userincludedirs, 'USER_HEADER_SEARCH_PATHS')
- xcode.printlist(cfg.libdirs, 'LIBRARY_SEARCH_PATHS')
-
- _p(4,'OBJROOT = "%s";', cfg.objectsdir)
-
- _p(4,'ONLY_ACTIVE_ARCH = %s;',iif(premake.config.isdebugbuild(cfg),'YES','NO'))
-
- -- 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,
- }
+ _p(3,'};')
+ _p(3,'name = %s;', xcode.quotestr(cfgname))
+ _p(2,'};')
+ end
- local flags = { }
- for flag, check in pairs(checks) do
- if check then
- table.insert(flags, flag)
+ local function add_options(options, extras)
+ for _, tbl in ipairs(extras) do
+ for tkey, tval in pairs(tbl) do
+ options[tkey] = tval
end
end
+ end
- for _, val in ipairs(premake.xcode.parameters) do
- _p(4, val ..';')
- end
-
- xcode.printlist(table.join(flags, cfg.buildoptions, cfg.buildoptions_c), 'OTHER_CFLAGS')
- xcode.printlist(table.join(flags, cfg.buildoptions, cfg.buildoptions_cpp), 'OTHER_CPLUSPLUSFLAGS')
+ local function add_wholearchive_links(opts, cfg)
+ if #cfg.wholearchive > 0 then
+ local linkopts = {}
- -- 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
- flags = { }
- for _, lib in ipairs(premake.getlinks(cfg, "system")) do
- if not xcode.isframework(lib) then
- table.insert(flags, "-l" .. lib)
+ for _, depcfg in ipairs(premake.getlinks(cfg, "siblings", "object")) do
+ if table.icontains(cfg.wholearchive, depcfg.project.name) then
+ local linkpath = path.rebase(depcfg.linktarget.fullpath, depcfg.location, cfg.location)
+ table.insert(linkopts, "-force_load")
+ table.insert(linkopts, linkpath)
+ end
end
- end
- flags = table.join(flags, cfg.linkoptions)
- xcode.printlist(flags, 'OTHER_LDFLAGS')
-
- if cfg.flags.StaticRuntime then
- _p(4,'STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = static;')
- end
- if targetdir ~= "." then
- _p(4,'SYMROOT = "%s";', targetdir)
- end
+ if opts.OTHER_LDFLAGS then
+ linkopts = table.join(linkopts, opts.OTHER_LDFLAGS)
+ end
- if cfg.flags.PedanticWarnings
- or cfg.flags.ExtraWarnings
- then
- _p(4,'WARNING_CFLAGS = "-Wall";')
+ opts.OTHER_LDFLAGS = linkopts
end
-
- _p(3,'};')
- _p(3,'name = "%s";', cfgname)
- _p(2,'};')
end
-
- function xcode.XCBuildConfiguration(tr, prj)
+ function xcode.XCBuildConfiguration(tr, prj, opts)
_p('/* Begin XCBuildConfiguration section */')
for _, target in ipairs(tr.products.children) do
for _, cfg in ipairs(tr.configs) do
- xcode.XCBuildConfiguration_Target(tr, target, cfg)
+ local values = opts.ontarget(tr, target, cfg)
+ add_options(values, cfg.xcodetargetopts)
+ xcode.XCBuildConfiguration_Impl(tr, cfg.xcode.targetid, values, cfg)
end
end
for _, cfg in ipairs(tr.configs) do
- xcode.XCBuildConfiguration_Project(tr, prj, cfg)
+ local values = opts.onproject(tr, prj, cfg)
+ add_options(values, cfg.xcodeprojectopts)
+ add_wholearchive_links(values, cfg)
+ xcode.XCBuildConfiguration_Impl(tr, cfg.xcode.projectid, values, cfg)
end
_p('/* End XCBuildConfiguration section */')
_p('')