Merge pull request #1619 from nickgravelyn/xcode-embed-libraries

Xcode embed libraries
This commit is contained in:
starkos 2021-04-19 11:01:51 -04:00 committed by GitHub
commit efd2ab50ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 347 additions and 13 deletions

View File

@ -46,6 +46,18 @@
}
}
p.api.register {
name = "embed",
scope = "config",
kind = "list",
}
p.api.register {
name = "embedAndSign",
scope = "config",
kind = "list",
}
--
-- Register the Xcode exporters.
--

View File

@ -69,6 +69,38 @@
]]
end
function suite.PBXBuildFile_ListsDependencyTargets_OnSharedLibWhenEmbedding()
kind "SharedLib"
project "MyProject"
embed { "MyProject2" }
prepare()
xcode.PBXBuildFile(tr)
test.capture [[
/* Begin PBXBuildFile section */
1BC538B0FA67D422AF49D6F0 /* libMyProject2-d.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107168B810144BEA4A68FEF8 /* libMyProject2-d.dylib */; };
6514841E8D4F3CD074EACA5E /* libMyProject2-d.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = 107168B810144BEA4A68FEF8 /* libMyProject2-d.dylib */; };
/* End PBXBuildFile section */
]]
end
function suite.PBXBuildFile_ListsDependencyTargets_OnSharedLibWhenEmbeddingAndSigning()
kind "SharedLib"
project "MyProject"
embedAndSign { "MyProject2" }
prepare()
xcode.PBXBuildFile(tr)
test.capture [[
/* Begin PBXBuildFile section */
1BC538B0FA67D422AF49D6F0 /* libMyProject2-d.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107168B810144BEA4A68FEF8 /* libMyProject2-d.dylib */; };
6514841E8D4F3CD074EACA5E /* libMyProject2-d.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = 107168B810144BEA4A68FEF8 /* libMyProject2-d.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
/* End PBXBuildFile section */
]]
end
---------------------------------------------------------------------------
-- PBXContainerItemProxy tests
@ -166,6 +198,35 @@
]]
end
---------------------------------------------------------------------------
-- PBXCopyFilesBuildPhaseForEmbedFrameworks tests
---------------------------------------------------------------------------
function suite.PBXCopyFilesBuildPhaseForEmbedFrameworks_ListsDependencies_OnSharedLib()
kind "SharedLib"
project "MyProject"
embed { "MyProject2" }
prepare()
xcode.PBXCopyFilesBuildPhaseForEmbedFrameworks(tr)
test.capture [[
/* Begin PBXCopyFilesBuildPhase section */
E1D3B542862652F4985E9B82 /* Embed Libraries */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
6514841E8D4F3CD074EACA5E /* MyProject2 in Projects */,
);
name = "Embed Libraries";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
]]
end
---------------------------------------------------------------------------
-- PBXGroup tests
---------------------------------------------------------------------------
@ -229,6 +290,7 @@
0FC4B7F6B3104128CDE10E36 /* Resources */,
7971D14D1CBD5A7F378E278D /* Sources */,
9FDD37564328C0885DF98D96 /* Frameworks */,
E1D3B542862652F4985E9B82 /* Embed Libraries */,
);
buildRules = (
);

View File

@ -106,6 +106,55 @@
]]
end
function suite.PBXBuildFile_ListsDylibs()
links { "../libA.dylib", "libB.dylib", "/usr/lib/libC.dylib" }
prepare()
xcode.PBXBuildFile(tr)
test.capture [[
/* Begin PBXBuildFile section */
3C98627697D9B5E86B3400B6 /* libB.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D413533EEB25EE70DB41E97E /* libB.dylib */; };
91686CDFDECB631154EA631F /* libA.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F9AE5C74A870BB9926CD407 /* libA.dylib */; };
A7E42B5676077F08FD15D196 /* libC.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CF0547FE2A469B70FDA0E63E /* libC.dylib */; };
/* End PBXBuildFile section */
]]
end
function suite.PBXBuildFile_ListsFrameworksAndDylibsForSigning()
links
{
"../libA.dylib",
"libB.dylib",
"/usr/lib/libC.dylib",
"../D.framework",
"../E.framework",
}
embedAndSign
{
"libA.dylib",
"D.framework",
}
embed
{
"libB.dylib",
"E.framework",
}
prepare()
xcode.PBXBuildFile(tr)
test.capture [[
/* Begin PBXBuildFile section */
12F1B82D44EB02DFBECA3E6D /* E.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A817AE35FEA518A7D71E2C75 /* E.framework */; };
6557012668C7D358EA347766 /* E.framework in Embed Libraries */ = {isa = PBXBuildFile; fileRef = A817AE35FEA518A7D71E2C75 /* E.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
3C98627697D9B5E86B3400B6 /* libB.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D413533EEB25EE70DB41E97E /* libB.dylib */; };
AC7C2020DB2274123463CE60 /* libB.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = D413533EEB25EE70DB41E97E /* libB.dylib */; };
91686CDFDECB631154EA631F /* libA.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F9AE5C74A870BB9926CD407 /* libA.dylib */; };
E054F1BF0EFB45B1683C9FFF /* libA.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = 5F9AE5C74A870BB9926CD407 /* libA.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
A7E42B5676077F08FD15D196 /* libC.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CF0547FE2A469B70FDA0E63E /* libC.dylib */; };
F56B754B2764BFFDA143FB8B /* D.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F3987C734A25E6E5229EFAB3 /* D.framework */; };
966D8A4599DE5C771B4B0085 /* D.framework in Embed Libraries */ = {isa = PBXBuildFile; fileRef = F3987C734A25E6E5229EFAB3 /* D.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
/* End PBXBuildFile section */
]]
end
function suite.PBXBuildFile_IgnoresVpaths()
files { "source.h", "source.c", "source.cpp", "Info.plist" }
vpaths { ["Source Files"] = { "**.c", "**.cpp" } }
@ -378,6 +427,20 @@
end
function suite.PBXFileReference_ListDylibsCorrectly()
links { "../libA.dylib", "libB.dylib", "/usr/lib/libC.dylib" }
prepare()
xcode.PBXFileReference(tr)
test.capture [[
/* Begin PBXFileReference section */
19A5C4E61D1697189E833B26 /* MyProject */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = MyProject; path = MyProject; sourceTree = BUILT_PRODUCTS_DIR; };
5F9AE5C74A870BB9926CD407 /* libA.dylib */ = {isa = PBXFileReference; lastKnownFileType = compiled.mach-o.dylib; name = libA.dylib; path = ../libA.dylib; sourceTree = SOURCE_ROOT; };
CF0547FE2A469B70FDA0E63E /* libC.dylib */ = {isa = PBXFileReference; lastKnownFileType = compiled.mach-o.dylib; name = libC.dylib; path = /usr/lib/libC.dylib; sourceTree = "<absolute>"; };
D413533EEB25EE70DB41E97E /* libB.dylib */ = {isa = PBXFileReference; lastKnownFileType = compiled.mach-o.dylib; name = libB.dylib; path = libB.dylib; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
]]
end
function suite.PBXFileReference_leavesFrameworkLocationsAsIsWhenSupplied_pathIsSetToInput()
local inputFrameWork = 'somedir/Foo.framework'
links(inputFrameWork)
@ -496,6 +559,59 @@
end
---------------------------------------------------------------------------
-- PBXCopyFilesBuildPhaseForEmbedFrameworks tests
---------------------------------------------------------------------------
function suite.PBXCopyFilesBuildPhaseForEmbedFrameworks_OnNoFiles()
prepare()
xcode.PBXCopyFilesBuildPhaseForEmbedFrameworks(tr)
test.capture [[
/* Begin PBXCopyFilesBuildPhase section */
E1D3B542862652F4985E9B82 /* Embed Libraries */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Libraries";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
]]
end
function suite.PBXCopyFilesBuildPhaseForEmbedFrameworks_ListsEmbeddedLibrariesCorrectly()
links
{
"../libA.dylib",
"../D.framework",
}
embed { "libA.dylib" }
embedAndSign { "D.framework" }
prepare()
xcode.PBXCopyFilesBuildPhaseForEmbedFrameworks(tr)
test.capture [[
/* Begin PBXCopyFilesBuildPhase section */
E1D3B542862652F4985E9B82 /* Embed Libraries */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
E054F1BF0EFB45B1683C9FFF /* libA.dylib in Frameworks */,
966D8A4599DE5C771B4B0085 /* D.framework in Frameworks */,
);
name = "Embed Libraries";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
]]
end
---------------------------------------------------------------------------
-- PBXGroup tests
---------------------------------------------------------------------------
@ -730,6 +846,7 @@
0FC4B7F6B3104128CDE10E36 /* Resources */,
7971D14D1CBD5A7F378E278D /* Sources */,
9FDD37564328C0885DF98D96 /* Frameworks */,
E1D3B542862652F4985E9B82 /* Embed Libraries */,
);
buildRules = (
);
@ -759,6 +876,7 @@
0F791C0512E9EE3794569245 /* Resources */,
7926355C7C97078EFE03AB9C /* Sources */,
9F919B65A3026D97246F11A5 /* Frameworks */,
A0315911431F7FC3D2455F51 /* Embed Libraries */,
);
buildRules = (
);
@ -788,6 +906,7 @@
A1093E0F9A6F3F818E0A9C4F /* Resources */,
0AB65766041C58D8F7B7B5A6 /* Sources */,
3121BD6F2A87BEE11E231BAF /* Frameworks */,
D652259BC13E4B8D092413DB /* Embed Libraries */,
);
buildRules = (
);
@ -825,6 +944,7 @@
7971D14D1CBD5A7F378E278D /* Sources */,
9607AE3510C85E7E00CD1376 /* Prelink */,
9FDD37564328C0885DF98D96 /* Frameworks */,
E1D3B542862652F4985E9B82 /* Embed Libraries */,
9607AE3710C85E8F00CD1376 /* Postbuild */,
);
buildRules = (
@ -867,6 +987,7 @@
0FC4B7F6B3104128CDE10E36 /* Resources */,
7971D14D1CBD5A7F378E278D /* Sources */,
9FDD37564328C0885DF98D96 /* Frameworks */,
E1D3B542862652F4985E9B82 /* Embed Libraries */,
);
buildRules = (
);
@ -910,6 +1031,7 @@
0FC4B7F6B3104128CDE10E36 /* Resources */,
7971D14D1CBD5A7F378E278D /* Sources */,
9FDD37564328C0885DF98D96 /* Frameworks */,
E1D3B542862652F4985E9B82 /* Embed Libraries */,
);
buildRules = (
);

View File

@ -144,6 +144,7 @@
[".xcassets"] = "folder.assetcatalog",
[".swift"] = "sourcecode.swift",
[".metal"] = "sourcecode.metal",
[".dylib"] = "compiled.mach-o.dylib",
}
return types[path.getextension(node.path)] or "text"
end
@ -335,6 +336,29 @@
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.
@ -403,6 +427,25 @@
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
@ -514,6 +557,23 @@
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>"
@ -574,6 +634,79 @@
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 = {}
@ -762,6 +895,7 @@
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 */,')
@ -1292,14 +1426,14 @@
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
-- 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)
@ -1435,12 +1569,10 @@
settings['OTHER_CFLAGS'] = table.join(flags, cfg.buildoptions)
-- 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
-- build list of "other" linked flags.
flags = { }
for _, lib in ipairs(config.getlinks(cfg, "system")) do
if not xcode.isframework(lib) then
if not xcode.isframeworkordylib(lib) then
table.insert(flags, "-l" .. lib)
end
end
@ -1448,7 +1580,7 @@
--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.isframework(lib.linktarget.basename) then
if not xcode.isframeworkordylib(lib.linktarget.basename) then
table.insert(flags, "-l" .. xcode.escapeArg(lib.linktarget.basename))
end
end

View File

@ -103,7 +103,7 @@
for cfg in project.eachconfig(prj) do
for _, link in ipairs(config.getlinks(cfg, "system", "fullpath")) do
local name = path.getname(link)
if xcode.isframework(name) and not tr.frameworks.children[name] then
if xcode.isframeworkordylib(name) and not tr.frameworks.children[name] then
node = tree.insert(tr.frameworks, tree.new(name))
node.path = link
end
@ -159,6 +159,10 @@
-- assign build IDs to buildable files
if xcode.getbuildcategory(node) and not node.excludefrombuild and not xcode.mustExcludeFromTarget(node, tr.project) then
node.buildid = xcode.newid(node.name, "build", nodePath)
if xcode.shouldembed(tr, node) then
node.embedid = xcode.newid(node.name, "embed", nodepath)
end
end
-- remember key files that are needed elsewhere
@ -174,10 +178,11 @@
node = tree.insert(tr.products, prj.xcode.projectnode)
node.kind = "product"
node.path = node.cfg.buildtarget.fullpath
node.cfgsection = xcode.newid(node.name, "cfg")
node.resstageid = xcode.newid(node.name, "rez")
node.sourcesid = xcode.newid(node.name, "src")
node.fxstageid = xcode.newid(node.name, "fxs")
node.cfgsection = xcode.newid(node.name, "cfg")
node.resstageid = xcode.newid(node.name, "rez")
node.sourcesid = xcode.newid(node.name, "src")
node.fxstageid = xcode.newid(node.name, "fxs")
node.embedstageid = xcode.newid(node.name, "embed")
return tr
end
@ -224,6 +229,7 @@
xcode.PBXContainerItemProxy(tr)
xcode.PBXFileReference(tr)
xcode.PBXFrameworksBuildPhase(tr)
xcode.PBXCopyFilesBuildPhaseForEmbedFrameworks(tr)
xcode.PBXGroup(tr)
xcode.PBXNativeTarget(tr)
xcode.PBXAggregateTarget(tr)