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

View File

@ -39,14 +39,43 @@ public class CarthageDependencyResolver {
versionLoader = CarthageVersionLoader(buildPath: project.basePath + CarthageDependencyResolver.getBuildPath(project)) 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 /// 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 { switch linkType {
case .static: case .static:
return "\(buildPath)/\(platform.carthageName)/Static" path += "/Static"
case .dynamic: case .dynamic:
return "\(buildPath)/\(platform.carthageName)" break
} }
return path
} }
/// Fetches all carthage dependencies for a given target /// Fetches all carthage dependencies for a given target

View File

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

View File

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

View File

@ -55,7 +55,7 @@ class CarthageDependencyResolverTests: XCTestCase {
} }
try allPlatforms.forEach { platform in 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)
} }
} }
} }