use carthage xcframeworks

This commit is contained in:
yonaskolb 2021-02-15 02:06:08 +11:00
parent 8d918c1e7e
commit e7ee5f3f63
5 changed files with 82 additions and 34 deletions

View File

@ -10,9 +10,11 @@ public struct SpecOptions: Equatable {
public static let generateEmptyDirectoriesDefault = false
public static let findCarthageFrameworksDefault = false
public static let useBaseInternationalizationDefault = true
public static let carthageXCFrameworksDefault = false
public static let schemePathPrefixDefault = "../../"
public var minimumXcodeGenVersion: Version?
public var carthageXCFrameworks: Bool
public var carthageBuildPath: String?
public var carthageExecutablePath: String?
public var createIntermediateGroups: Bool
@ -76,6 +78,7 @@ public struct SpecOptions: Equatable {
public init(
minimumXcodeGenVersion: Version? = nil,
carthageXCFrameworks: Bool = carthageXCFrameworksDefault,
carthageBuildPath: String? = nil,
carthageExecutablePath: String? = nil,
createIntermediateGroups: Bool = createIntermediateGroupsDefault,
@ -102,6 +105,7 @@ public struct SpecOptions: Equatable {
schemePathPrefix: String = schemePathPrefixDefault
) {
self.minimumXcodeGenVersion = minimumXcodeGenVersion
self.carthageXCFrameworks = carthageXCFrameworks
self.carthageBuildPath = carthageBuildPath
self.carthageExecutablePath = carthageExecutablePath
self.createIntermediateGroups = createIntermediateGroups
@ -136,6 +140,7 @@ extension SpecOptions: JSONObjectConvertible {
minimumXcodeGenVersion = try Version.parse(string)
}
carthageXCFrameworks = jsonDictionary.json(atKeyPath: "carthageXCFrameworks") ?? SpecOptions.carthageXCFrameworksDefault
carthageBuildPath = jsonDictionary.json(atKeyPath: "carthageBuildPath")
carthageExecutablePath = jsonDictionary.json(atKeyPath: "carthageExecutablePath")
bundleIdPrefix = jsonDictionary.json(atKeyPath: "bundleIdPrefix")
@ -205,6 +210,9 @@ extension SpecOptions: JSONEncodable {
if useBaseInternationalization != SpecOptions.useBaseInternationalizationDefault {
dict["useBaseInternationalization"] = useBaseInternationalization
}
if carthageXCFrameworks != SpecOptions.carthageXCFrameworksDefault {
dict["carthageXCFrameworks"] = carthageXCFrameworks
}
if schemePathPrefix != SpecOptions.schemePathPrefixDefault {
dict["schemePathPrefix"] = schemePathPrefix
}

View File

@ -39,14 +39,43 @@ public class CarthageDependencyResolver {
versionLoader = CarthageVersionLoader(buildPath: project.basePath + CarthageDependencyResolver.getBuildPath(project))
}
func frameworkPath(for name: String, platform: Platform, linkType: Dependency.CarthageLinkType) -> Path {
var file = Path(name)
var xcFramework = project.options.carthageXCFrameworks
switch file.extension {
case "xcframework":
xcFramework = true
case "framework":
xcFramework = false
case .none:
let fileExtension: String
if xcFramework {
fileExtension = "xcframework"
} else {
fileExtension = "framework"
}
file = Path(file.string + ".\(fileExtension)")
default:
break
}
let parentPath = Path(buildPath(for: platform, linkType: linkType, xcFramework: xcFramework))
return parentPath + file
}
/// Carthage's build path for the given platform
func buildPath(for platform: Platform, linkType: Dependency.CarthageLinkType) -> String {
func buildPath(for platform: Platform, linkType: Dependency.CarthageLinkType, xcFramework: Bool) -> String {
var path = buildPath
if !xcFramework {
path += "/\(platform.carthageName)"
}
switch linkType {
case .static:
return "\(buildPath)/\(platform.carthageName)/Static"
path += "/Static"
case .dynamic:
return "\(buildPath)/\(platform.carthageName)"
break
}
return path
}
/// Fetches all carthage dependencies for a given target

View File

@ -57,8 +57,13 @@ class CarthageVersionLoader {
struct CarthageVersionFile: Decodable {
private struct Reference: Decodable, Equatable {
public let name: String
public let hash: String
let name: String
let hash: String
let container: String?
var frameworkFilename: String {
container ?? "\(name).framework"
}
}
private let data: [Platform: [String]]
@ -67,7 +72,7 @@ struct CarthageVersionFile: Decodable {
let container = try decoder.container(keyedBy: Platform.self)
data = try Platform.allCases.reduce(into: [:]) { data, platform in
let references = try container.decodeIfPresent([Reference].self, forKey: platform) ?? []
let frameworks = Set(references.map { $0.name }).sorted()
let frameworks = Set(references.map { $0.frameworkFilename }).sorted()
data[platform] = frameworks
}
}

View File

@ -24,6 +24,7 @@ public class PBXProjGenerator {
var packageReferences: [String: XCRemoteSwiftPackageReference] = [:]
var carthageFrameworksByPlatform: [String: Set<PBXFileElement>] = [:]
var carthageXCFrameworks: Set<PBXFileElement> = []
var frameworkFiles: [PBXFileElement] = []
var bundleFiles: [PBXFileElement] = []
@ -225,8 +226,8 @@ public class PBXProjGenerator {
try project.targets.forEach(generateTarget)
try project.aggregateTargets.forEach(generateAggregateTarget)
if !carthageFrameworksByPlatform.isEmpty {
var platforms: [PBXGroup] = []
if !carthageFrameworksByPlatform.isEmpty || !carthageXCFrameworks.isEmpty {
var children: [PBXFileElement] = []
for (platform, files) in carthageFrameworksByPlatform {
let platformGroup: PBXGroup = addObject(
PBXGroup(
@ -235,11 +236,14 @@ public class PBXProjGenerator {
path: platform
)
)
platforms.append(platformGroup)
children.append(platformGroup)
}
if !carthageXCFrameworks.isEmpty {
children += Array(carthageXCFrameworks)
}
let carthageGroup = addObject(
PBXGroup(
children: platforms,
children: children,
sourceTree: .group,
name: "Carthage",
path: carthageResolver.buildPath
@ -677,7 +681,7 @@ public class PBXProjGenerator {
let targetSupportsDirectEmbed = !(target.platform.requiresSimulatorStripping &&
(target.type.isApp || target.type == .watch2Extension))
let directlyEmbedCarthage = target.directlyEmbedCarthageDependencies ?? targetSupportsDirectEmbed
let directlyEmbedCarthage = target.directlyEmbedCarthageDependencies ?? project.options.carthageXCFrameworks || targetSupportsDirectEmbed
func getEmbedSettings(dependency: Dependency, codeSign: Bool) -> [String: Any] {
var embedAttributes: [String] = []
@ -871,14 +875,14 @@ public class PBXProjGenerator {
? carthageResolver.relatedDependencies(for: dependency, in: target.platform) : [dependency]
allDependencies.forEach { dependency in
let platformPath = Path(carthageResolver.buildPath(for: target.platform, linkType: linkType))
var frameworkPath = platformPath + dependency.reference
if frameworkPath.extension == nil {
frameworkPath = Path(frameworkPath.string + ".framework")
}
let fileReference = self.sourceGenerator.getFileReference(path: frameworkPath, inPath: platformPath)
let frameworkPath = carthageResolver.frameworkPath(for: dependency.reference, platform: target.platform, linkType: linkType)
let fileReference = self.sourceGenerator.getFileReference(path: frameworkPath, inPath: frameworkPath.parent())
self.carthageFrameworksByPlatform[target.platform.carthageName, default: []].insert(fileReference)
if frameworkPath.extension == "xcframework" {
self.carthageXCFrameworks.insert(fileReference)
} else {
self.carthageFrameworksByPlatform[target.platform.carthageName, default: []].insert(fileReference)
}
let isStaticLibrary = target.type == .staticLibrary
let isCarthageStaticLink = dependency.carthageLinkType == .static
@ -954,12 +958,8 @@ public class PBXProjGenerator {
let isFromTopLevelTarget = carthageDependency.isFromTopLevelTarget
let embed = dependency.embed ?? target.shouldEmbedCarthageDependencies
let platformPath = Path(carthageResolver.buildPath(for: target.platform, linkType: dependency.carthageLinkType ?? .default))
var frameworkPath = platformPath + dependency.reference
if frameworkPath.extension == nil {
frameworkPath = Path(frameworkPath.string + ".framework")
}
let fileReference = sourceGenerator.getFileReference(path: frameworkPath, inPath: platformPath)
let frameworkPath = carthageResolver.frameworkPath(for: dependency.reference, platform: target.platform, linkType: dependency.carthageLinkType ?? .default)
let fileReference = self.sourceGenerator.getFileReference(path: frameworkPath, inPath: frameworkPath.parent())
if dependency.carthageLinkType == .static {
guard isFromTopLevelTarget else { continue } // ignore transitive dependencies if static
@ -1079,7 +1079,7 @@ public class PBXProjGenerator {
if !carthageFrameworksToEmbed.isEmpty {
let inputPaths = carthageFrameworksToEmbed
.map { "$(SRCROOT)/\(carthageResolver.buildPath(for: target.platform, linkType: .dynamic))/\($0)\($0.contains(".") ? "" : ".framework")" }
.map { "$(SRCROOT)/\(carthageResolver.frameworkPath(for: $0, platform: target.platform, linkType: .dynamic))" }
let outputPaths = carthageFrameworksToEmbed
.map { "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/\($0)\($0.contains(".") ? "" : ".framework")" }
let carthageExecutable = carthageResolver.executable
@ -1249,15 +1249,21 @@ public class PBXProjGenerator {
let configFrameworkBuildPaths: [String]
if !carthageDependencies.isEmpty {
var carthagePlatformBuildPaths: Set<String> = []
if carthageDependencies.contains(where: { $0.dependency.carthageLinkType == .static }) {
let carthagePlatformBuildPath = "$(PROJECT_DIR)/" + carthageResolver.buildPath(for: target.platform, linkType: .static)
carthagePlatformBuildPaths.insert(carthagePlatformBuildPath)
func getCarthageBuildPaths(linkType: Dependency.CarthageLinkType) -> Set<String> {
var paths: Set<String> = []
if carthageDependencies.contains(where: { $0.dependency.carthageLinkType == linkType }) {
let path = "$(PROJECT_DIR)/\(carthageResolver.buildPath(for: target.platform, linkType: linkType, xcFramework: false))"
paths.insert(path)
if project.options.carthageXCFrameworks {
let path = "$(PROJECT_DIR)/\(carthageResolver.buildPath(for: target.platform, linkType: linkType, xcFramework: true))/**"
paths.insert(path)
}
}
return paths
}
if carthageDependencies.contains(where: { $0.dependency.carthageLinkType == .dynamic }) {
let carthagePlatformBuildPath = "$(PROJECT_DIR)/" + carthageResolver.buildPath(for: target.platform, linkType: .dynamic)
carthagePlatformBuildPaths.insert(carthagePlatformBuildPath)
}
configFrameworkBuildPaths = carthagePlatformBuildPaths.sorted() + frameworkBuildPaths.sorted()
carthagePlatformBuildPaths = carthagePlatformBuildPaths.union(getCarthageBuildPaths(linkType: .static))
carthagePlatformBuildPaths = carthagePlatformBuildPaths.union(getCarthageBuildPaths(linkType: .dynamic))
configFrameworkBuildPaths = carthagePlatformBuildPaths.union(frameworkBuildPaths).sorted()
} else {
configFrameworkBuildPaths = frameworkBuildPaths.sorted()
}

View File

@ -55,7 +55,7 @@ class CarthageDependencyResolverTests: XCTestCase {
}
try allPlatforms.forEach { platform in
try expect(expectedByPlatform[platform]) == resolver.buildPath(for: platform, linkType: .dynamic)
try expect(expectedByPlatform[platform]) == resolver.buildPath(for: platform, linkType: .dynamic, xcFramework: false)
}
}
}