123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689 |
- --
- -- xcode_common.lua
- -- Functions to generate the different sections of an Xcode project.
- -- Copyright (c) 2009-2015 Jason Perkins and the Premake project
- --
- local p = premake
- local xcode = p.modules.xcode
- local tree = p.tree
- local workspace = p.workspace
- local project = p.project
- local config = p.config
- local fileconfig = p.fileconfig
- --
- -- Return the Xcode build category for a given file, based on the file extension.
- --
- -- @param node
- -- The node to identify.
- -- @returns
- -- An Xcode build category, one of "Sources", "Resources", "Frameworks", or nil.
- --
- function xcode.getbuildcategory(node)
- local categories = {
- [".a"] = "Frameworks",
- [".c"] = "Sources",
- [".cc"] = "Sources",
- [".cpp"] = "Sources",
- [".cxx"] = "Sources",
- [".c++"] = "Sources",
- [".dylib"] = "Frameworks",
- [".framework"] = "Frameworks",
- [".m"] = "Sources",
- [".mm"] = "Sources",
- [".strings"] = "Resources",
- [".nib"] = "Resources",
- [".xib"] = "Resources",
- [".storyboard"] = "Resources",
- [".icns"] = "Resources",
- [".s"] = "Sources",
- [".S"] = "Sources",
- [".swift"] = "Sources",
- [".metal"] = "Resources",
- }
- if node.isResource then
- return "Resources"
- elseif node.cfg and (node.cfg.kind == p.SHAREDLIB or node.cfg.kind == p.STATICLIB) then
- return "Frameworks"
- end
- return categories[path.getextension(node.name)]
- end
- function xcode.isItemResource(project, node)
- local res
- if project and project.xcodebuildresources then
- if type(project.xcodebuildresources) == "table" then
- res = project.xcodebuildresources
- end
- end
- local function checkItemInList(item, list)
- if item then
- for _,v in pairs(list) do
- if string.find(item, path.wildcards(v)) then
- return true
- end
- end
- end
- return false
- end
- if (checkItemInList(node.path, res)) then
- return true
- end
- return false
- end
- --
- -- Return 'explicitFileType' if the given file is being set with 'compileas'
- --
- function xcode.getfiletypekey(node, cfg)
- if node.configs then
- local filecfg = fileconfig.getconfig(node, cfg)
- if filecfg and filecfg["compileas"] then
- return "explicitFileType"
- end
- end
- return "lastKnownFileType"
- end
- --
- -- Return the Xcode type for a given file, based on the file extension.
- --
- -- @param fname
- -- The file name to identify.
- -- @returns
- -- An Xcode file type, string.
- --
- function xcode.getfiletype(node, cfg)
- if node.configs then
- local filecfg = fileconfig.getconfig(node, cfg)
- if filecfg then
- if p.languages.isc(filecfg.compileas) then
- return "sourcecode.c.c"
- elseif p.languages.iscpp(filecfg.compileas) then
- return "sourcecode.cpp.cpp"
- elseif filecfg.compileas == p.OBJECTIVEC then
- return "sourcecode.c.objc"
- elseif filecfg.compileas == p.OBJECTIVECPP then
- return "sourcecode.cpp.objcpp"
- end
- end
- end
- local types = {
- [".c"] = "sourcecode.c.c",
- [".cc"] = "sourcecode.cpp.cpp",
- [".cpp"] = "sourcecode.cpp.cpp",
- [".css"] = "text.css",
- [".cxx"] = "sourcecode.cpp.cpp",
- [".c++"] = "sourcecode.cpp.cpp",
- [".S"] = "sourcecode.asm.asm",
- [".framework"] = "wrapper.framework",
- [".gif"] = "image.gif",
- [".h"] = "sourcecode.c.h",
- [".html"] = "text.html",
- [".lua"] = "sourcecode.lua",
- [".m"] = "sourcecode.c.objc",
- [".mm"] = "sourcecode.cpp.objc",
- [".nib"] = "wrapper.nib",
- [".storyboard"] = "file.storyboard",
- [".pch"] = "sourcecode.c.h",
- [".plist"] = "text.plist.xml",
- [".strings"] = "text.plist.strings",
- [".xib"] = "file.xib",
- [".icns"] = "image.icns",
- [".s"] = "sourcecode.asm",
- [".bmp"] = "image.bmp",
- [".wav"] = "audio.wav",
- [".xcassets"] = "folder.assetcatalog",
- [".swift"] = "sourcecode.swift",
- [".metal"] = "sourcecode.metal",
- [".dylib"] = "compiled.mach-o.dylib",
- }
- return types[path.getextension(node.path)] or "text"
- end
- xcode.escapeSpecialChars = {
- ['\n'] = '\\n',
- ['\r'] = '\\r',
- ['\t'] = '\\t',
- }
- function xcode.escapeChar(c)
- return xcode.escapeSpecialChars[c] or '\\'..c
- end
- function xcode.escapeArg(value)
- value = value:gsub('[\'"\\\n\r\t ]', xcode.escapeChar)
- return value
- end
- function xcode.escapeSetting(value)
- value = value:gsub('["\\\n\r\t]', xcode.escapeChar)
- return value
- end
- function xcode.stringifySetting(value)
- value = value..''
- if not value:match('^[%a%d_./]+$') then
- value = '"'..xcode.escapeSetting(value)..'"'
- end
- return value
- end
- function xcode.customStringifySetting(value)
- value = value..''
- local test = value:match('^[%a%d_./%+]+$')
- if test then
- value = '"'..xcode.escapeSetting(value)..'"'
- end
- return value
- end
- function xcode.printSetting(level, name, value)
- if type(value) == 'function' then
- value(level, name)
- elseif type(value) ~= 'table' then
- _p(level, '%s = %s;', xcode.stringifySetting(name), xcode.stringifySetting(value))
- --elseif #value == 1 then
- --_p(level, '%s = %s;', xcode.stringifySetting(name), xcode.stringifySetting(value[1]))
- elseif #value >= 1 then
- _p(level, '%s = (', xcode.stringifySetting(name))
- for _, item in ipairs(value) do
- _p(level + 1, '%s,', xcode.stringifySetting(item))
- end
- _p(level, ');')
- end
- end
- function xcode.printSettingsTable(level, settings)
- -- Maintain alphabetic order to be consistent
- local keys = table.keys(settings)
- table.sort(keys)
- for _, k in ipairs(keys) do
- xcode.printSetting(level, k, settings[k])
- end
- end
- function xcode.overrideSettings(settings, overrides)
- if type(overrides) == 'table' then
- for name, value in pairs(overrides) do
- -- Allow an override to remove a value by using false
- settings[name] = iif(not table.equals(value, { false }), value, nil)
- end
- end
- end
- --
- -- Return the Xcode product type, based target kind.
- --
- -- @param node
- -- The product node to identify.
- -- @returns
- -- An Xcode product type, string.
- --
- function xcode.getproducttype(node)
- local types = {
- ConsoleApp = "com.apple.product-type.tool",
- WindowedApp = "com.apple.product-type.application",
- StaticLib = "com.apple.product-type.library.static",
- SharedLib = "com.apple.product-type.library.dynamic",
- OSXBundle = "com.apple.product-type.bundle",
- OSXFramework = "com.apple.product-type.framework",
- XCTest = "com.apple.product-type.bundle.unit-test",
- }
- return types[iif(node.cfg.kind == "SharedLib" and node.cfg.sharedlibtype, node.cfg.sharedlibtype, node.cfg.kind)]
- end
- --
- -- Return the Xcode target type, based on the target file extension.
- --
- -- @param node
- -- The product node to identify.
- -- @returns
- -- An Xcode target type, string.
- --
- function xcode.gettargettype(node)
- local types = {
- ConsoleApp = "\"compiled.mach-o.executable\"",
- WindowedApp = "wrapper.application",
- StaticLib = "archive.ar",
- SharedLib = "\"compiled.mach-o.dylib\"",
- OSXBundle = "wrapper.cfbundle",
- OSXFramework = "wrapper.framework",
- XCTest = "wrapper.cfbundle",
- }
- return types[iif(node.cfg.kind == "SharedLib" and node.cfg.sharedlibtype, node.cfg.sharedlibtype, node.cfg.kind)]
- end
- --
- -- Return the Xcode debug information format for the current configuration
- --
- -- @param cfg
- -- The current configuration
- -- @returns
- -- The corresponding value of DEBUG_INFORMATION_FORMAT, or 'dwarf-with-dsym' if invalid
- --
- function xcode.getToolSet(cfg)
- local default = "clang"
- local minOSVersion = project.systemversion(cfg)
- if minOSVersion ~= nil
- and cfg.system == p.MACOSX
- and p.checkVersion(minOSVersion, "<10.7")
- then
- default = "gcc"
- end
- local toolset = p.tools[_OPTIONS.cc or cfg.toolset or default]
- if not toolset then
- error("Invalid toolset '" .. cfg.toolset .. "'")
- end
- return toolset
- end
- function xcode.getdebugformat(cfg)
- local formats = {
- ["Dwarf"] = "dwarf",
- ["Default"] = "dwarf-with-dsym",
- ["SplitDwarf"] = "dwarf-with-dsym",
- }
- local rval = "dwarf-with-dsym"
- if cfg.debugformat then
- rval = formats[cfg.debugformat] or rval
- end
- return rval
- end
- --
- -- Return a unique file name for a project. Since Xcode uses .xcodeproj's to
- -- represent both workspaces and projects there is a likely change of a name
- -- collision. Tack on a number to differentiate them.
- --
- -- @param prj
- -- The project being queried.
- -- @returns
- -- A uniqued file name
- --
- function xcode.getxcodeprojname(prj)
- -- if there is a workspace with matching name, then use "projectname1.xcodeproj"
- -- just get something working for now
- local fname = p.filename(prj, ".xcodeproj")
- return fname
- end
- --
- -- Returns true if the file name represents a framework.
- --
- -- @param fname
- -- The name of the file to test.
- --
- function xcode.isframework(fname)
- return (path.getextension(fname) == ".framework")
- end
- --
- -- Returns true if the file name represents a dylib.
- --
- -- @param fname
- -- The name of the file to test.
- --
- function xcode.isdylib(fname)
- return (path.getextension(fname) == ".dylib")
- end
- --
- -- Returns true if the file name represents a framework or dylib.
- --
- -- @param fname
- -- The name of the file to test.
- --
- function xcode.isframeworkordylib(fname)
- return xcode.isframework(fname) or xcode.isdylib(fname)
- end
- --
- -- Retrieves a unique 12 byte ID for an object.
- -- This function accepts an array of parameters that will be used to generate the id.
- --
- -- @returns
- -- A 24-character string representing the 12 byte ID.
- --
- function xcode.newid(...)
- local name = ''
- local arg = {...}
- for i, v in pairs(arg) do
- name = name..v..'****'
- end
- return ("%08X%08X%08X"):format(name:hash(16777619), name:hash(2166136261), name:hash(46577619))
- end
- --
- -- Create a product tree node and all projects in a workspace; assigning IDs
- -- that are needed for inter-project dependencies.
- --
- -- @param wks
- -- The workspace to prepare.
- --
- function xcode.prepareWorkspace(wks)
- -- create and cache a list of supported platforms
- wks.xcode = { }
- for prj in p.workspace.eachproject(wks) do
- -- need a configuration to get the target information
- local cfg = project.getconfig(prj, prj.configurations[1], prj.platforms[1])
- -- build the product tree node
- local bundlepath = cfg.buildtarget.bundlename ~= "" and cfg.buildtarget.bundlename or cfg.buildtarget.name;
- if (prj.external) then
- bundlepath = cfg.project.name
- end
- local node = p.tree.new(path.getname(bundlepath))
- node.cfg = cfg
- node.id = xcode.newid(node.name, "product")
- node.targetid = xcode.newid(node.name, "target")
- -- attach it to the project
- prj.xcode = {}
- prj.xcode.projectnode = node
- end
- end
- ---------------------------------------------------------------------------
- -- Section generator functions, in the same order in which they appear
- -- in the .pbxproj file
- ---------------------------------------------------------------------------
- function xcode.PBXBuildFile(tr)
- local settings = {};
- tree.traverse(tr, {
- onnode = function(node)
- if node.buildid then
- settings[node.buildid] = function(level)
- _p(level,'%s /* %s in %s */ = {isa = PBXBuildFile; fileRef = %s /* %s */; };',
- node.buildid, node.name, xcode.getbuildcategory(node), node.id, node.name)
- if node.embedid then
- local attrs = ""
- if xcode.shouldembedandsign(tr, node) then
- attrs = attrs .. "CodeSignOnCopy, "
- end
- if xcode.isframework(node.name) then
- attrs = attrs .. "RemoveHeadersOnCopy, "
- end
- if attrs ~= "" then
- attrs = " settings = {ATTRIBUTES = (" .. attrs .. "); };"
- end
- _p(level,'%s /* %s in Embed Libraries */ = {isa = PBXBuildFile; fileRef = %s /* %s */;%s };',
- node.embedid, node.name, node.id, node.name, attrs)
- end
- end
- end
- end
- })
- if not table.isempty(settings) then
- _p('/* Begin PBXBuildFile section */')
- xcode.printSettingsTable(2, settings);
- _p('/* End PBXBuildFile section */')
- _p('')
- end
- end
- function xcode.PBXContainerItemProxy(tr)
- local settings = {}
- for _, node in ipairs(tr.projects.children) do
- settings[node.productproxyid] = function()
- _p(2,'%s /* PBXContainerItemProxy */ = {', node.productproxyid)
- _p(3,'isa = PBXContainerItemProxy;')
- _p(3,'containerPortal = %s /* %s */;', node.id, path.getrelative(node.parent.parent.project.location, node.path))
- _p(3,'proxyType = 2;')
- _p(3,'remoteGlobalIDString = %s;', node.project.xcode.projectnode.id)
- _p(3,'remoteInfo = %s;', xcode.stringifySetting(node.project.xcode.projectnode.name))
- _p(2,'};')
- end
- settings[node.targetproxyid] = function()
- _p(2,'%s /* PBXContainerItemProxy */ = {', node.targetproxyid)
- _p(3,'isa = PBXContainerItemProxy;')
- _p(3,'containerPortal = %s /* %s */;', node.id, path.getrelative(node.parent.parent.project.location, node.path))
- _p(3,'proxyType = 1;')
- _p(3,'remoteGlobalIDString = %s;', node.project.xcode.projectnode.targetid)
- _p(3,'remoteInfo = %s;', xcode.stringifySetting(node.project.xcode.projectnode.name))
- _p(2,'};')
- end
- end
- if not table.isempty(settings) then
- _p('/* Begin PBXContainerItemProxy section */')
- xcode.printSettingsTable(2, settings);
- _p('/* End PBXContainerItemProxy section */')
- _p('')
- end
- end
- function xcode.PBXFileReference(tr)
- local cfg = project.getfirstconfig(tr.project)
- local settings = {}
- tree.traverse(tr, {
- onleaf = function(node)
- -- I'm only listing files here, so ignore anything without a path
- if not node.path then
- return
- end
- -- is this the product node, describing the output target?
- if node.kind == "product" then
- settings[node.id] = function(level)
- _p(level,'%s /* %s */ = {isa = PBXFileReference; explicitFileType = %s; includeInIndex = 0; name = %s; path = %s; sourceTree = BUILT_PRODUCTS_DIR; };',
- node.id, node.name, xcode.gettargettype(node), xcode.stringifySetting(node.name), xcode.stringifySetting(path.getname(node.cfg.buildtarget.bundlename ~= "" and node.cfg.buildtarget.bundlename or node.cfg.buildtarget.relpath)))
- end
- -- is this a project dependency?
- elseif node.parent.parent == tr.projects then
- settings[node.parent.id] = function(level)
- -- ms Is there something wrong with path is relative ?
- -- if we have a and b without slashes get relative should assume the same parent folder and return ../
- -- this works if we put it like below
- local relpath = path.getrelative(path.getabsolute(tr.project.location), path.getabsolute(node.parent.project.location))
- _p(level,'%s /* %s */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = %s; path = %s; sourceTree = SOURCE_ROOT; };',
- node.parent.id, node.name, xcode.customStringifySetting(node.parent.name), xcode.stringifySetting(path.join(relpath, node.parent.name)))
- end
- -- something else
- else
- settings[node.id] = function(level)
- local pth, src
- if xcode.isframework(node.path) then
- --respect user supplied paths
- -- look for special variable-starting paths for different sources
- local nodePath = node.path
- local _, matchEnd, variable = string.find(nodePath, "^%$%((.+)%)/")
- if variable then
- -- by skipping the last '/' we support the same absolute/relative
- -- paths as before
- nodePath = string.sub(nodePath, matchEnd + 1)
- end
- if string.find(nodePath,'/') then
- if string.find(nodePath,'^%.')then
- --error('relative paths are not currently supported for frameworks')
- pth = path.getrelative(tr.project.location, node.path)
- --print(tr.project.location, node.path , pth)
- src = "SOURCE_ROOT"
- variable = src
- else
- pth = nodePath
- src = "<absolute>"
- end
- end
- -- if it starts with a variable, use that as the src instead
- if variable then
- src = variable
- -- if we are using a different source tree, it has to be relative
- -- to that source tree, so get rid of any leading '/'
- if string.find(pth, '^/') then
- pth = string.sub(pth, 2)
- end
- else
- pth = "System/Library/Frameworks/" .. node.path
- src = "SDKROOT"
- end
- elseif xcode.isdylib(node.path) then
- --respect user supplied paths
- -- look for special variable-starting paths for different sources
- local nodePath = node.path
- local _, matchEnd, variable = string.find(nodePath, "^%$%((.+)%)/")
- if variable then
- -- by skipping the last '/' we support the same absolute/relative
- -- paths as before
- nodePath = string.sub(nodePath, matchEnd + 1)
- end
- if string.find(nodePath,'^%/') then
- pth = nodePath
- src = "<absolute>"
- else
- pth = path.getrelative(tr.project.location, node.path)
- src = "SOURCE_ROOT"
- end
- else
- -- something else; probably a source code file
- src = "<group>"
- if node.abspath then
- pth = path.getrelative(tr.project.location, node.abspath)
- else
- pth = node.path
- end
- --end
- end
- _p(level,'%s /* %s */ = {isa = PBXFileReference; %s = %s; name = %s; path = %s; sourceTree = %s; };',
- node.id, node.name, xcode.getfiletypekey(node, cfg), xcode.getfiletype(node, cfg), xcode.stringifySetting(node.name), xcode.stringifySetting(pth), xcode.stringifySetting(src))
- end
- end
- end
- })
- if not table.isempty(settings) then
- _p('/* Begin PBXFileReference section */')
- xcode.printSettingsTable(2, settings)
- _p('/* End PBXFileReference section */')
- _p('')
- end
- end
- function xcode.PBXFrameworksBuildPhase(tr)
- _p('/* Begin PBXFrameworksBuildPhase section */')
- _p(2,'%s /* Frameworks */ = {', tr.products.children[1].fxstageid)
- _p(3,'isa = PBXFrameworksBuildPhase;')
- _p(3,'buildActionMask = 2147483647;')
- _p(3,'files = (')
- -- write out library dependencies
- tree.traverse(tr.frameworks, {
- onleaf = function(node)
- if node.buildid then
- _p(4,'%s /* %s in Frameworks */,', node.buildid, node.name)
- end
- end
- })
- -- write out project dependencies
- tree.traverse(tr.projects, {
- onleaf = function(node)
- if node.buildid then
- _p(4,'%s /* %s in Frameworks */,', node.buildid, node.name)
- end
- end
- })
- _p(3,');')
- _p(3,'runOnlyForDeploymentPostprocessing = 0;')
- _p(2,'};')
- _p('/* End PBXFrameworksBuildPhase section */')
- _p('')
- end
- function xcode.embedListContains(list, node)
- -- Frameworks and dylibs referenced by path are expected
- -- to provide the file name (but not path). Project
- -- references are expected to provide the project name.
- local entryname = node.name
- if node.parent.project then
- entryname = node.parent.project.name
- end
- return table.contains(list, entryname)
- end
- function xcode.shouldembed(tr, node)
- if not xcode.isframeworkordylib(node.name) then
- return false
- end
- for _, cfg in ipairs(tr.configs) do
- if xcode.embedListContains(cfg.embed, node) or xcode.embedListContains(cfg.embedAndSign, node) then
- return true
- end
- end
- end
- function xcode.shouldembedandsign(tr, node)
- if not xcode.isframeworkordylib(node.name) then
- return false
- end
- for _, cfg in ipairs(tr.configs) do
- if xcode.embedListContains(cfg.embedAndSign, node) then
- return true
- end
- end
- end
- function xcode.PBXCopyFilesBuildPhaseForEmbedFrameworks(tr)
- _p('/* Begin PBXCopyFilesBuildPhase section */')
- _p(2,'%s /* Embed Libraries */ = {', tr.products.children[1].embedstageid)
- _p(3,'isa = PBXCopyFilesBuildPhase;')
- _p(3,'buildActionMask = 2147483647;')
- _p(3,'dstPath = "";')
- _p(3,'dstSubfolderSpec = 10;')
- _p(3,'files = (')
- -- write out library dependencies
- tree.traverse(tr.frameworks, {
- onleaf = function(node)
- if node.embedid then
- _p(4,'%s /* %s in Frameworks */,', node.embedid, node.name)
- end
- end
- })
- -- write out project dependencies
- tree.traverse(tr.projects, {
- onleaf = function(node)
- if node.embedid then
- _p(4,'%s /* %s in Projects */,', node.embedid, node.parent.project.name)
- end
- end
- })
- _p(3,');')
- _p(3,'name = "Embed Libraries";')
- _p(3,'runOnlyForDeploymentPostprocessing = 0;')
- _p(2,'};')
- _p('/* End PBXCopyFilesBuildPhase section */')
- _p('')
- end
- function xcode.PBXGroup(tr)
- local settings = {}
- tree.traverse(tr, {
- onnode = function(node)
- -- Skip over anything that isn't a proper group
- if (node.path and #node.children == 0) or node.kind == "vgroup" then
- return
- end
- local function isAggregateTarget(node)
- local productsId = xcode.newid("Products")
- return node.id == productsId and node.parent.project and node.parent.project.kind == "Utility"
- end
- if isAggregateTarget(node) then
- return
- end
- settings[node.productgroupid or node.id] = function()
- -- project references get special treatment
- if node.parent == tr.projects then
- _p(2,'%s /* Products */ = {', node.productgroupid)
- else
- _p(2,'%s /* %s */ = {', node.id, node.name)
- end
- _p(3,'isa = PBXGroup;')
- _p(3,'children = (')
- for _, childnode in ipairs(node.children) do
- if not isAggregateTarget(childnode) then
- _p(4,'%s /* %s */,', childnode.id, childnode.name)
- end
- end
- _p(3,');')
- if node.parent == tr.projects then
- _p(3,'name = Products;')
- else
- _p(3,'name = %s;', xcode.stringifySetting(node.name))
- local vpath = project.getvpath(tr.project, node.name)
- if node.path and node.name ~= vpath then
- local p = node.path
- if node.parent.path then
- p = path.getrelative(node.parent.path, node.path)
- end
- _p(3,'path = %s;', xcode.stringifySetting(p))
- end
- end
- _p(3,'sourceTree = "<group>";')
- _p(2,'};')
- end
- end
- }, true)
- if not table.isempty(settings) then
- _p('/* Begin PBXGroup section */')
- xcode.printSettingsTable(2, settings)
- _p('/* End PBXGroup section */')
- _p('')
- end
- end
- function xcode.GetBuildCommands(tr)
- local buildCommandInfos = {}
- tree.traverse(tr, {
- onnode = function(node)
- if node.buildcommandid then
- local info = {
- node = node,
- inputs = { node.relpath },
- outputs = {},
- depends = {},
- transact = false,
- }
- for cfg in project.eachconfig(tr.project) do
- local filecfg = fileconfig.getconfig(node, cfg)
- if filecfg then
- for _, v in ipairs(filecfg.buildinputs) do
- table.insert(info.inputs, project.getrelative(tr.project, v))
- end
- for _, v in ipairs(filecfg.buildoutputs) do
- table.insert(info.outputs, project.getrelative(tr.project, v))
- end
- end
- end
- table.insert(buildCommandInfos, info)
- end
- end
- })
- for _, mine in ipairs(buildCommandInfos) do
- for _, their in ipairs(buildCommandInfos) do
- if mine ~= their then
- for _, input in ipairs(mine.inputs) do
- if table.contains(their.outputs, input) then
- table.insert(mine.depends, their)
- break
- end
- end
- end
- end
- end
- local buildCommands = {}
- local leftover = #buildCommandInfos
- while leftover > 0 do
- local prev = leftover
- for _, info in ipairs(buildCommandInfos) do
- if not info.transact then
- local transact = true
- for _, depend in ipairs(info.depends) do
- transact = depend.transact
- if not transact then
- break
- end
- end
- if transact then
- table.insert(buildCommands, info.node)
- info.transact = true
- leftover = leftover - 1
- end
- end
- end
- if prev == leftover then
- error('detect circular reference.')
- end
- end
- return buildCommands
- end
- function xcode.PBXAggregateOrNativeTarget(tr, pbxTargetName)
- local kinds = {
- Aggregate = {
- "Utility",
- },
- Native = {
- "ConsoleApp",
- "WindowedApp",
- "SharedLib",
- "StaticLib",
- },
- }
- local hasTarget = false
- for _, node in ipairs(tr.products.children) do
- hasTarget = table.contains(kinds[pbxTargetName], node.cfg.kind)
- if hasTarget then
- break
- end
- end
- if not hasTarget then
- return
- end
- _p('/* Begin PBX%sTarget section */', pbxTargetName)
- local buildCommands = xcode.GetBuildCommands(tr)
- for _, node in ipairs(tr.products.children) do
- local name = tr.project.name
- local function hasBuildCommands(which)
- for _, cfg in ipairs(tr.configs) do
- if #cfg[which] > 0 then
- return true
- end
- end
- end
- _p(2,'%s /* %s */ = {', node.targetid, name)
- _p(3,'isa = PBX%sTarget;', pbxTargetName)
- _p(3,'buildConfigurationList = %s /* Build configuration list for PBX%sTarget "%s" */;', node.cfgsection, pbxTargetName, xcode.escapeSetting(name))
- _p(3,'buildPhases = (')
- if hasBuildCommands('prebuildcommands') then
- _p(4,'9607AE1010C857E500CD1376 /* Prebuild */,')
- end
- for _, v in ipairs(buildCommands) do
- _p(4,'%s /* Build "%s" */,', v.buildcommandid, v.name)
- end
- if pbxTargetName == "Native" then
- _p(4,'%s /* Resources */,', node.resstageid)
- _p(4,'%s /* Sources */,', node.sourcesid)
- end
- if hasBuildCommands('prelinkcommands') then
- _p(4,'9607AE3510C85E7E00CD1376 /* Prelink */,')
- end
- if pbxTargetName == "Native" then
- _p(4,'%s /* Frameworks */,', node.fxstageid)
- _p(4,'%s /* Embed Libraries */,', node.embedstageid)
- end
- if hasBuildCommands('postbuildcommands') then
- _p(4,'9607AE3710C85E8F00CD1376 /* Postbuild */,')
- end
- _p(3,');')
- _p(3,'buildRules = (')
- _p(3,');')
- _p(3,'dependencies = (')
- for _, node in ipairs(tr.projects.children) do
- _p(4,'%s /* PBXTargetDependency */,', node.targetdependid)
- end
- _p(3,');')
- _p(3,'name = %s;', xcode.stringifySetting(name))
- if pbxTargetName == "Native" then
- local p
- if node.cfg.kind == "ConsoleApp" then
- p = "$(HOME)/bin"
- elseif node.cfg.kind == "WindowedApp" then
- p = "$(HOME)/Applications"
- end
- if p then
- _p(3,'productInstallPath = %s;', xcode.stringifySetting(p))
- end
- end
- _p(3,'productName = %s;', xcode.stringifySetting(name))
- if pbxTargetName == "Native" then
- _p(3,'productReference = %s /* %s */;', node.id, node.name)
- _p(3,'productType = %s;', xcode.stringifySetting(xcode.getproducttype(node)))
- end
- _p(2,'};')
- end
- _p('/* End PBX%sTarget section */', pbxTargetName)
- _p('')
- end
- function xcode.PBXAggregateTarget(tr)
- xcode.PBXAggregateOrNativeTarget(tr, "Aggregate")
- end
- function xcode.PBXNativeTarget(tr)
- xcode.PBXAggregateOrNativeTarget(tr, "Native")
- end
- function xcode.PBXProject(tr)
- _p('/* Begin PBXProject section */')
- _p(2,'08FB7793FE84155DC02AAC07 /* Project object */ = {')
- _p(3,'isa = PBXProject;')
- local capabilities = tr.project.xcodesystemcapabilities
- if not table.isempty(capabilities) then
- local keys = table.keys(capabilities)
- table.sort(keys)
- _p(3, 'attributes = {')
- _p(4, 'TargetAttributes = {')
- _p(5, '%s = {', tr.project.xcode.projectnode.targetid)
- _p(6, 'SystemCapabilities = {')
- for _, key in pairs(keys) do
- _p(7, '%s = {', key)
- _p(8, 'enabled = %d;', iif(capabilities[key], 1, 0))
- _p(7, '};')
- end
- _p(6, '};')
- _p(5, '};')
- _p(4, '};')
- _p(3, '};')
- end
- _p(3,'buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "%s" */;', tr.name)
- _p(3,'compatibilityVersion = "Xcode 3.2";')
- _p(3,'hasScannedForEncodings = 1;')
- _p(3,'mainGroup = %s /* %s */;', tr.id, tr.name)
- _p(3,'projectDirPath = "";')
- 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(3,'projectRoot = "";')
- _p(3,'targets = (')
- for _, node in ipairs(tr.products.children) do
- _p(4,'%s /* %s */,', node.targetid, node.name)
- end
- _p(3,');')
- _p(2,'};')
- _p('/* End PBXProject section */')
- _p('')
- end
- function xcode.PBXReferenceProxy(tr)
- local settings = {}
- tree.traverse(tr.projects, {
- onleaf = function(node)
- settings[node.id] = function()
- _p(2,'%s /* %s */ = {', node.id, node.name)
- _p(3,'isa = PBXReferenceProxy;')
- _p(3,'fileType = %s;', xcode.gettargettype(node))
- _p(3,'path = %s;', xcode.stringifySetting(node.name))
- _p(3,'remoteRef = %s /* PBXContainerItemProxy */;', node.parent.productproxyid)
- _p(3,'sourceTree = BUILT_PRODUCTS_DIR;')
- _p(2,'};')
- end
- end
- })
- if not table.isempty(settings) then
- _p('/* Begin PBXReferenceProxy section */')
- xcode.printSettingsTable(2, settings)
- _p('/* End PBXReferenceProxy section */')
- _p('')
- end
- end
- function xcode.PBXResourcesBuildPhase(tr)
- _p('/* Begin PBXResourcesBuildPhase section */')
- for _, target in ipairs(tr.products.children) do
- _p(2,'%s /* Resources */ = {', target.resstageid)
- _p(3,'isa = PBXResourcesBuildPhase;')
- _p(3,'buildActionMask = 2147483647;')
- _p(3,'files = (')
- tree.traverse(tr, {
- onnode = function(node)
- if xcode.getbuildcategory(node) == "Resources" then
- _p(4,'%s /* %s in Resources */,', node.buildid, node.name)
- end
- end
- })
- _p(3,');')
- _p(3,'runOnlyForDeploymentPostprocessing = 0;')
- _p(2,'};')
- end
- _p('/* End PBXResourcesBuildPhase section */')
- _p('')
- end
- function xcode.PBXShellScriptBuildPhase(tr)
- local wrapperWritten = false
- local function doblock(id, name, which)
- -- see if there are any config-specific commands to add
- local commands = {}
- for _, cfg in ipairs(tr.configs) do
- local cfgcmds = cfg[which]
- if #cfgcmds > 0 then
- table.insert(commands, 'if [ "${CONFIGURATION}" = "' .. cfg.buildcfg .. '" ]; then')
- for i = 1, #cfgcmds do
- table.insert(commands, cfgcmds[i])
- end
- table.insert(commands, 'fi')
- end
- end
- if #commands > 0 then
- table.insert(commands, 1, 'set -e') -- Tells the shell to exit when any command fails
- commands = os.translateCommands(commands, p.MACOSX)
- 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 = (');
- _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;', xcode.stringifySetting(table.concat(commands, '\n')))
- _p(2,'};')
- end
- end
- doblock("9607AE1010C857E500CD1376", "Prebuild", "prebuildcommands")
- local settings = {}
- tree.traverse(tr, {
- onnode = function(node)
- if node.buildcommandid then
- settings[node.buildcommandid] = function(level)
- local commands = {}
- local inputs = {}
- local outputs = {}
- for cfg in project.eachconfig(tr.project) do
- local filecfg = fileconfig.getconfig(node, cfg)
- if filecfg then
- table.insert(commands, 'if [ "${CONFIGURATION}" = "' .. cfg.buildcfg .. '" ]; then')
- if filecfg.buildmessage then
- table.insert(commands, '\techo "' .. filecfg.buildmessage .. '"')
- end
- local cmds = os.translateCommandsAndPaths(filecfg.buildcommands, filecfg.project.basedir, filecfg.project.location)
- for _, cmd in ipairs(cmds) do
- table.insert(commands, '\t' .. cmd)
- end
- table.insert(commands, 'fi')
- for _, v in ipairs(filecfg.buildinputs) do
- if not table.indexof(inputs, v) then
- table.insert(inputs, v)
- end
- end
- for _, v in ipairs(filecfg.buildoutputs) do
- if not table.indexof(outputs, v) then
- table.insert(outputs, v)
- end
- end
- end
- end
- if #commands > 0 then
- table.insert(commands, 1, 'set -e') -- Tells the shell to exit when any command fails
- end
- _p(level,'%s /* Build "%s" */ = {', node.buildcommandid, node.name)
- _p(level+1,'isa = PBXShellScriptBuildPhase;')
- _p(level+1,'buildActionMask = 2147483647;')
- _p(level+1,'files = (')
- _p(level+1,');')
- _p(level+1,'inputPaths = (');
- _p(level+2,'"%s",', xcode.escapeSetting(node.relpath))
- for _, v in ipairs(inputs) do
- _p(level+2,'"%s",', xcode.escapeSetting(project.getrelative(tr.project, v)))
- end
- _p(level+1,');')
- _p(level+1,'name = %s;', xcode.stringifySetting('Build "' .. node.name .. '"'))
- _p(level+1,'outputPaths = (')
- for _, v in ipairs(outputs) do
- _p(level+2,'"%s",', xcode.escapeSetting(project.getrelative (tr.project, v)))
- end
- _p(level+1,');')
- _p(level+1,'runOnlyForDeploymentPostprocessing = 0;');
- _p(level+1,'shellPath = /bin/sh;');
- _p(level+1,'shellScript = %s;', xcode.stringifySetting(table.concat(commands, '\n')))
- _p(level,'};')
- end
- end
- end
- })
- if not table.isempty(settings) then
- if not wrapperWritten then
- _p('/* Begin PBXShellScriptBuildPhase section */')
- wrapperWritten = true
- end
- xcode.printSettingsTable(2, settings)
- end
- doblock("9607AE3510C85E7E00CD1376", "Prelink", "prelinkcommands")
- doblock("9607AE3710C85E8F00CD1376", "Postbuild", "postbuildcommands")
- if wrapperWritten then
- _p('/* End PBXShellScriptBuildPhase section */')
- _p('')
- end
- end
- function xcode.PBXSourcesBuildPhase(tr)
- _p('/* Begin PBXSourcesBuildPhase section */')
- for _, target in ipairs(tr.products.children) do
- _p(2,'%s /* Sources */ = {', target.sourcesid)
- _p(3,'isa = PBXSourcesBuildPhase;')
- _p(3,'buildActionMask = 2147483647;')
- _p(3,'files = (')
- tree.traverse(tr, {
- onleaf = function(node)
- if xcode.getbuildcategory(node) == "Sources" and node.buildid then
- _p(4,'%s /* %s in Sources */,', node.buildid, node.name)
- end
- end
- })
- _p(3,');')
- _p(3,'runOnlyForDeploymentPostprocessing = 0;')
- _p(2,'};')
- end
- _p('/* End PBXSourcesBuildPhase section */')
- _p('')
- end
- function xcode.PBXVariantGroup(tr)
- local settings = {}
- tree.traverse(tr, {
- onbranch = function(node)
- settings[node.id] = function()
- if node.kind == "vgroup" then
- _p(2,'%s /* %s */ = {', node.id, node.name)
- _p(3,'isa = PBXVariantGroup;')
- _p(3,'children = (')
- for _, lang in ipairs(node.children) do
- _p(4,'%s /* %s */,', lang.id, lang.name)
- end
- _p(3,');')
- _p(3,'name = %s;', node.name)
- _p(3,'sourceTree = "<group>";')
- _p(2,'};')
- end
- end
- end
- })
- if not table.isempty(settings) then
- _p('/* Begin PBXVariantGroup section */')
- xcode.printSettingsTable(2, settings)
- _p('/* End PBXVariantGroup section */')
- _p('')
- end
- end
- function xcode.PBXTargetDependency(tr)
- local settings = {}
- tree.traverse(tr.projects, {
- onleaf = function(node)
- settings[node.parent.targetdependid] = function()
- _p(2,'%s /* PBXTargetDependency */ = {', node.parent.targetdependid)
- _p(3,'isa = PBXTargetDependency;')
- _p(3,'name = %s;', xcode.stringifySetting(node.name))
- _p(3,'targetProxy = %s /* PBXContainerItemProxy */;', node.parent.targetproxyid)
- _p(2,'};')
- end
- end
- })
- if not table.isempty(settings) then
- _p('/* Begin PBXTargetDependency section */')
- xcode.printSettingsTable(2, settings)
- _p('/* End PBXTargetDependency section */')
- _p('')
- end
- end
- function xcode.XCBuildConfiguration_Target(tr, target, cfg)
- local settings = {}
- settings['ALWAYS_SEARCH_USER_PATHS'] = 'NO'
- if cfg.symbols ~= p.OFF then
- settings['DEBUG_INFORMATION_FORMAT'] = xcode.getdebugformat(cfg)
- end
- if cfg.kind ~= "StaticLib" and cfg.buildtarget.prefix ~= '' then
- settings['EXECUTABLE_PREFIX'] = cfg.buildtarget.prefix
- end
- if cfg.buildtarget.extension then
- local exts = {
- WindowedApp = "app",
- SharedLib = "dylib",
- StaticLib = "a",
- OSXBundle = "bundle",
- OSXFramework = "framework",
- XCTest = "xctest",
- }
- local ext = cfg.buildtarget.extension:sub(2)
- if ext ~= exts[iif(cfg.kind == "SharedLib" and cfg.sharedlibtype, cfg.sharedlibtype, cfg.kind)] then
- if cfg.kind == "WindowedApp" or (cfg.kind == "SharedLib" and cfg.sharedlibtype) then
- settings['WRAPPER_EXTENSION'] = ext
- elseif cfg.kind == "SharedLib" or cfg.kind == "StaticLib" then
- settings['EXECUTABLE_EXTENSION'] = ext
- end
- end
- end
- local outdir = path.getrelative(tr.project.location, path.getdirectory(cfg.buildtarget.relpath))
- if outdir ~= "." then
- settings['CONFIGURATION_BUILD_DIR'] = outdir
- end
- settings['GCC_DYNAMIC_NO_PIC'] = 'NO'
- if tr.infoplist then
- settings['INFOPLIST_FILE'] = config.findfile(cfg, path.getextension(tr.infoplist.name))
- end
- local installpaths = {
- ConsoleApp = '/usr/local/bin',
- WindowedApp = '"$(HOME)/Applications"',
- SharedLib = '/usr/local/lib',
- StaticLib = '/usr/local/lib',
- OSXBundle = '$(LOCAL_LIBRARY_DIR)/Bundles',
- OSXFramework = '$(LOCAL_LIBRARY_DIR)/Frameworks',
- }
- settings['INSTALL_PATH'] = installpaths[iif(cfg.kind == "SharedLib" and cfg.sharedlibtype, cfg.sharedlibtype, cfg.kind)]
- local fileNameList = {}
- local file_tree = project.getsourcetree(tr.project)
- tree.traverse(tr, {
- onnode = function(node)
- if node.buildid and not node.isResource and node.abspath then
- -- ms this seems to work on visual studio !!!
- -- why not in xcode ??
- local filecfg = fileconfig.getconfig(node, cfg)
- if filecfg and filecfg.flags.ExcludeFromBuild then
- --fileNameList = fileNameList .. " " ..filecfg.name
- table.insert(fileNameList, xcode.escapeArg(node.name))
- end
- --ms new way
- -- if the file is not in this config file list excluded it from build !!!
- --if not cfg.files[node.abspath] then
- -- table.insert(fileNameList, xcode.escapeArg(node.name))
- --end
- end
- end
- })
- if not table.isempty(fileNameList) then
- settings['EXCLUDED_SOURCE_FILE_NAMES'] = fileNameList
- end
- settings['PRODUCT_NAME'] = iif(cfg.kind == "ConsoleApp" and cfg.buildtarget.extension, cfg.buildtarget.basename .. cfg.buildtarget.extension, cfg.buildtarget.basename)
- if os.istarget(p.IOS) then
- settings['SDKROOT'] = 'iphoneos'
- settings['CODE_SIGN_IDENTITY[sdk=iphoneos*]'] = cfg.xcodecodesigningidentity or 'iPhone Developer'
- local minOSVersion = project.systemversion(cfg)
- if minOSVersion ~= nil then
- settings['IPHONEOS_DEPLOYMENT_TARGET'] = minOSVersion
- end
- local families = {
- ['iPhone/iPod touch'] = '1',
- ['iPad'] = '2',
- ['Universal'] = '1,2',
- }
- local family = families[cfg.iosfamily]
- if family then
- settings['TARGETED_DEVICE_FAMILY'] = family
- end
- else
- local minOSVersion = project.systemversion(cfg)
- if minOSVersion ~= nil then
- settings['MACOSX_DEPLOYMENT_TARGET'] = minOSVersion
- end
- end
- --ms not by default ...add it manually if you need it
- --settings['COMBINE_HIDPI_IMAGES'] = 'YES'
- xcode.overrideSettings(settings, cfg.xcodebuildsettings)
- _p(2,'%s /* %s */ = {', cfg.xcode.targetid, cfg.buildcfg)
- _p(3,'isa = XCBuildConfiguration;')
- _p(3,'buildSettings = {')
- xcode.printSettingsTable(4, settings)
- _p(3,'};')
- xcode.printSetting(3, 'name', cfg.buildcfg);
- _p(2,'};')
- end
- xcode.cLanguageStandards = {
- ["Default"] = "compiler-default", -- explicit compiler default
- ["C89"] = "c89",
- ["C90"] = "c90",
- ["C99"] = "c99",
- ["C11"] = "c11",
- ["gnu89"] = "gnu89",
- ["gnu90"] = "gnu90",
- ["gnu99"] = "gnu99",
- ["gnu11"] = "gnu11"
- }
- function xcode.XCBuildConfiguration_CLanguageStandard(settings, cfg)
- -- if no cppdialect is provided, don't set C dialect
- -- projects without C dialect set will use compiler default
- if not cfg.cdialect then
- return
- end
- local cLanguageStandard = xcode.cLanguageStandards[cfg.cdialect]
- if cLanguageStandard then
- settings['GCC_C_LANGUAGE_STANDARD'] = cLanguageStandard
- end
- end
- xcode.cppLanguageStandards = {
- ["Default"] = "compiler-default", -- explicit compiler default
- ["C++98"] = "c++98",
- ["C++0x"] = "c++11",
- ["C++11"] = "c++11",
- ["C++1y"] = "c++14",
- ["C++14"] = "c++14",
- ["C++1z"] = "c++1z",
- ["C++17"] = "c++1z",
- ["C++2a"] = "c++2a",
- ["C++20"] = "c++2a",
- ["gnu++98"] = "gnu++98",
- ["gnu++0x"] = "gnu++0x",
- ["gnu++11"] = "gnu++0x", -- Xcode project GUI uses gnu++0x, but gnu++11 also works
- ["gnu++1y"] = "gnu++14",
- ["gnu++14"] = "gnu++14",
- ["gnu++1z"] = "gnu++1z",
- ["gnu++17"] = "gnu++1z",
- ["gnu++2a"] = "gnu++2a",
- ["gnu++20"] = "gnu++2a",
- }
- function xcode.XCBuildConfiguration_CppLanguageStandard(settings, cfg)
- -- if no cppdialect is provided, don't set C++ dialect
- -- projects without C++ dialect set will use compiler default
- if not cfg.cppdialect then
- return
- end
- local cppLanguageStandard = xcode.cppLanguageStandards[cfg.cppdialect]
- if cppLanguageStandard then
- settings['CLANG_CXX_LANGUAGE_STANDARD'] = cppLanguageStandard
- end
- end
- function xcode.XCBuildConfiguration_SwiftLanguageVersion(settings, cfg)
- -- if no swiftversion is provided, don't set swift version
- -- Projects with swift files but without swift version will refuse
- -- to build on Xcode but setting a default SWIFT_VERSION may have
- -- unexpected interactions with other systems like cocoapods
- if cfg.swiftversion then
- settings['SWIFT_VERSION'] = cfg.swiftversion
- end
- end
- function xcode.XCBuildConfiguration_Project(tr, cfg)
- local settings = {}
- local toolset = xcode.getToolSet(cfg)
- local archs = {
- Native = "$(NATIVE_ARCH_ACTUAL)",
- x86 = "i386",
- x86_64 = "x86_64",
- Universal32 = "$(ARCHS_STANDARD_32_BIT)",
- Universal64 = "$(ARCHS_STANDARD_64_BIT)",
- Universal = "$(ARCHS_STANDARD_32_64_BIT)",
- }
- settings['ARCHS'] = archs[cfg.platform or "Native"]
- --ms This is the default so don;t write it
- --settings['SDKROOT'] = 'macosx'
- local targetdir = path.getdirectory(cfg.buildtarget.relpath)
- if targetdir ~= "." then
- settings['CONFIGURATION_BUILD_DIR'] = '$(SYMROOT)'
- end
- settings['CONFIGURATION_TEMP_DIR'] = '$(OBJROOT)'
- if config.isDebugBuild(cfg) then
- settings['COPY_PHASE_STRIP'] = 'NO'
- end
- xcode.XCBuildConfiguration_CLanguageStandard(settings, cfg)
- xcode.XCBuildConfiguration_CppLanguageStandard(settings, cfg)
- if cfg.exceptionhandling == p.OFF then
- settings['GCC_ENABLE_CPP_EXCEPTIONS'] = 'NO'
- end
- if cfg.rtti == p.OFF then
- settings['GCC_ENABLE_CPP_RTTI'] = 'NO'
- end
- if cfg.symbols == p.ON and cfg.editandcontinue ~= "Off" then
- settings['GCC_ENABLE_FIX_AND_CONTINUE'] = 'YES'
- end
- if cfg.exceptionhandling == p.OFF then
- settings['GCC_ENABLE_OBJC_EXCEPTIONS'] = 'NO'
- end
- local optimizeMap = { On = 3, Size = 's', Speed = 3, Full = 'fast', Debug = 1 }
- settings['GCC_OPTIMIZATION_LEVEL'] = optimizeMap[cfg.optimize] or 0
- if cfg.pchheader and not cfg.flags.NoPCH then
- settings['GCC_PRECOMPILE_PREFIX_HEADER'] = 'YES'
- settings['GCC_PREFIX_HEADER'] = cfg.pchheader
- end
- local escapedDefines = { }
- for i,v in ipairs(cfg.defines) do
- escapedDefines[i] = xcode.escapeArg(v)
- end
- settings['GCC_PREPROCESSOR_DEFINITIONS'] = escapedDefines
- settings["GCC_SYMBOLS_PRIVATE_EXTERN"] = 'NO'
- if cfg.unsignedchar ~= nil then
- settings['GCC_CHAR_IS_UNSIGNED_CHAR'] = iif(cfg.unsignedchar, "YES", "NO")
- end
- if cfg.flags.FatalWarnings then
- settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'YES'
- end
- settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'YES'
- settings['GCC_WARN_UNUSED_VARIABLE'] = 'YES'
- local includedirs = project.getrelative(cfg.project, cfg.includedirs)
- for i,v in ipairs(includedirs) do
- cfg.includedirs[i] = p.quoted(v)
- end
- settings['USER_HEADER_SEARCH_PATHS'] = cfg.includedirs
- local sysincludedirs = project.getrelative(cfg.project, cfg.sysincludedirs)
- for i,v in ipairs(sysincludedirs) do
- cfg.sysincludedirs[i] = p.quoted(v)
- end
- if not table.isempty(cfg.sysincludedirs) then
- table.insert(cfg.sysincludedirs, "$(inherited)")
- end
- settings['SYSTEM_HEADER_SEARCH_PATHS'] = cfg.sysincludedirs
- for i,v in ipairs(cfg.libdirs) do
- cfg.libdirs[i] = p.project.getrelative(cfg.project, cfg.libdirs[i])
- end
- for i,v in ipairs(cfg.syslibdirs) do
- cfg.syslibdirs[i] = p.project.getrelative(cfg.project, cfg.syslibdirs[i])
- end
- settings['LIBRARY_SEARCH_PATHS'] = table.join (cfg.libdirs, cfg.syslibdirs)
- for i,v in ipairs(cfg.frameworkdirs) do
- cfg.frameworkdirs[i] = p.project.getrelative(cfg.project, cfg.frameworkdirs[i])
- end
- settings['FRAMEWORK_SEARCH_PATHS'] = cfg.frameworkdirs
- local runpathdirs = table.join (cfg.runpathdirs, config.getsiblingtargetdirs (cfg))
- settings['LD_RUNPATH_SEARCH_PATHS'] = toolset.getrunpathdirs(cfg, runpathdirs, "path")
- local objDir = path.getrelative(tr.project.location, cfg.objdir)
- settings['OBJROOT'] = objDir
- settings['ONLY_ACTIVE_ARCH'] = iif(p.config.isDebugBuild(cfg), 'YES', 'NO')
- -- build list of "other" C/C++ flags
- local checks = {
- ["-ffast-math"] = cfg.floatingpoint == "Fast",
- ["-fomit-frame-pointer"] = cfg.omitframepointer == "On",
- ["-fno-omit-frame-pointer"] = cfg.omitframepointer == "Off",
- }
- local flags = { }
- for flag, check in pairs(checks) do
- if check then
- table.insert(flags, flag)
- end
- end
- --[[if (type(cfg.buildoptions) == "table") then
- for k,v in pairs(cfg.buildoptions) do
- table.insertflat(flags, string.explode(v," -"))
- end
- end
- ]]
- settings['OTHER_CFLAGS'] = table.join(flags, cfg.buildoptions)
- -- build list of "other" linked flags.
- flags = { }
- for _, lib in ipairs(config.getlinks(cfg, "system")) do
- if not xcode.isframeworkordylib(lib) then
- table.insert(flags, "-l" .. lib)
- end
- end
- --ms this step is for reference projects only
- for _, lib in ipairs(config.getlinks(cfg, "dependencies", "object")) do
- if (lib.external) then
- if not xcode.isframeworkordylib(lib.linktarget.basename) then
- table.insert(flags, "-l" .. xcode.escapeArg(lib.linktarget.basename))
- end
- end
- end
- settings['OTHER_LDFLAGS'] = table.join(flags, cfg.linkoptions)
- if cfg.flags.StaticRuntime then
- settings['STANDARD_C_PLUS_PLUS_LIBRARY_TYPE'] = 'static'
- end
- if targetdir ~= "." then
- settings['SYMROOT'] = path.getrelative(tr.project.location, targetdir)
- end
- if cfg.warnings == "Off" then
- settings['WARNING_CFLAGS'] = '-w'
- elseif cfg.warnings == "High" then
- settings['WARNING_CFLAGS'] = '-Wall'
- elseif cfg.warnings == "Extra" then
- settings['WARNING_CFLAGS'] = '-Wall -Wextra'
- elseif cfg.warnings == "Everything" then
- settings['WARNING_CFLAGS'] = '-Weverything'
- end
- xcode.XCBuildConfiguration_SwiftLanguageVersion(settings, cfg)
- xcode.overrideSettings(settings, cfg.xcodebuildsettings)
- _p(2,'%s /* %s */ = {', cfg.xcode.projectid, cfg.buildcfg)
- _p(3,'isa = XCBuildConfiguration;')
- _p(3,'buildSettings = {')
- xcode.printSettingsTable(4, settings)
- _p(3,'};')
- xcode.printSetting(3, 'name', cfg.buildcfg);
- _p(2,'};')
- end
- function xcode.XCBuildConfiguration(tr)
- local settings = {}
- for _, target in ipairs(tr.products.children) do
- for _, cfg in ipairs(tr.configs) do
- settings[cfg.xcode.targetid] = function()
- xcode.XCBuildConfiguration_Target(tr, target, cfg)
- end
- end
- end
- for _, cfg in ipairs(tr.configs) do
- settings[cfg.xcode.projectid] = function()
- xcode.XCBuildConfiguration_Project(tr, cfg)
- end
- end
- if not table.isempty(settings) then
- _p('/* Begin XCBuildConfiguration section */')
- xcode.printSettingsTable(0, settings)
- _p('/* End XCBuildConfiguration section */')
- _p('')
- end
- end
- function xcode.XCBuildConfigurationList(tr)
- local wks = tr.project.workspace
- local defaultCfgName = xcode.stringifySetting(tr.configs[1].buildcfg)
- local settings = {}
- for _, target in ipairs(tr.products.children) do
- settings[target.cfgsection] = function()
- _p(2,'%s /* Build configuration list for PBXNativeTarget "%s" */ = {', target.cfgsection, target.name)
- _p(3,'isa = XCConfigurationList;')
- _p(3,'buildConfigurations = (')
- for _, cfg in ipairs(tr.configs) do
- _p(4,'%s /* %s */,', cfg.xcode.targetid, cfg.buildcfg)
- end
- _p(3,');')
- _p(3,'defaultConfigurationIsVisible = 0;')
- _p(3,'defaultConfigurationName = %s;', defaultCfgName)
- _p(2,'};')
- end
- end
- settings['1DEB928908733DD80010E9CD'] = function()
- _p(2,'1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "%s" */ = {', tr.name)
- _p(3,'isa = XCConfigurationList;')
- _p(3,'buildConfigurations = (')
- for _, cfg in ipairs(tr.configs) do
- _p(4,'%s /* %s */,', cfg.xcode.projectid, cfg.buildcfg)
- end
- _p(3,');')
- _p(3,'defaultConfigurationIsVisible = 0;')
- _p(3,'defaultConfigurationName = %s;', defaultCfgName)
- _p(2,'};')
- end
- _p('/* Begin XCConfigurationList section */')
- xcode.printSettingsTable(2, settings)
- _p('/* End XCConfigurationList section */')
- end
|