Allow .dylib extension in links for Xcode

When entries in links are specified with an extension we treat them
like frameworks for the most part. They are placed into the
Frameworks group and added to the Frameworks build phase. We do have
separate logic for the file reference, only because we never want to
resolve a .dylib link to the /System/Frameworks directory. Instead
we assume a .dylib link that is just a file name, e.g. 'libA.dylib',
is relative to the project the same way as if it were prefixed with
'./'.
This commit is contained in:
Nick Gravelyn 2020-09-25 15:26:04 -07:00
parent 65deb619f8
commit 0e93130442
3 changed files with 75 additions and 9 deletions

View File

@ -106,6 +106,19 @@
]]
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_IgnoresVpaths()
files { "source.h", "source.c", "source.cpp", "Info.plist" }
vpaths { ["Source Files"] = { "**.c", "**.cpp" } }
@ -378,6 +391,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)

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
@ -318,6 +319,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.
@ -497,6 +521,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>"
@ -1275,14 +1316,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 = {}
@ -1414,12 +1455,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
@ -1427,7 +1466,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