Skip to content

Commit ec91ba3

Browse files
authored
Zip Builder support for dependencies through subspecs (#4940)
1 parent a3e78ac commit ec91ba3

File tree

3 files changed

+57
-18
lines changed

3 files changed

+57
-18
lines changed

ZipBuilder/Sources/ZipBuilder/CocoaPodUtils.swift

+33-10
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,17 @@ enum CocoaPodUtils {
5757
/// Binary frameworks in this pod.
5858
letbinaryFrameworks:[URL]
5959

60+
/// Subspecs installed for this pod.
61+
letsubspecs:Set<String>
62+
6063
/// The contents of the module map for all frameworks associated with the pod.
6164
varmoduleMapContents:String
6265

63-
init(version:String, dependencies:[String], installedLocation:URL){
66+
init(version:String, dependencies:[String], installedLocation:URL, subspecs:Set<String>){
6467
self.version = version
6568
self.dependencies = dependencies
6669
self.installedLocation = installedLocation
70+
self.subspecs = subspecs
6771
moduleMapContents =""
6872

6973
// Get all the frameworks contained in this directory.
@@ -186,30 +190,48 @@ enum CocoaPodUtils {
186190
break
187191
}
188192
iflet(pod, version)=detectVersion(fromLine: line){
189-
letcorePod= pod.components(separatedBy:"/")[0]
190-
currentPod = corePod.trimmingCharacters(in: quotes)
193+
currentPod = pod.trimmingCharacters(in: quotes)
191194
pods[currentPod!]= version
192195
}elseiflet currentPod = currentPod {
193196
letmatches= depRegex.matches(in: line, range:NSRange(location:0, length: line.utf8.count))
194197
// Match something like - GTMSessionFetcher/Full (= 1.3.0)
195198
iflet match = matches.first {
196199
letdepLine=(line asNSString).substring(with: match.range(at:0))asString
197200
// Split spaces and subspecs.
198-
letdep= depLine.components(separatedBy:["","/"])[2].trimmingCharacters(in: quotes)
201+
letdep= depLine.components(separatedBy:[""])[2].trimmingCharacters(in: quotes)
199202
if dep != currentPod {
200-
ifdeps[currentPod]==nil{
201-
deps[currentPod]=Set()
202-
}
203-
deps[currentPod]?.insert(dep)
203+
deps[currentPod, default:Set()].insert(dep)
204204
}
205205
}
206206
}
207207
}
208+
// Organize the subspecs
209+
varversions:[String:String]=[:]
210+
varsubspecs:[String:Set<String>]=[:]
211+
212+
for(podName, version)in pods {
213+
letsubspecArray= podName.components(separatedBy:"/")
214+
if subspecArray.count >2{
215+
fatalError("Multi-layered subspecs are not supported - \(podName)")
216+
}elseif subspecArray.count ==1{
217+
versions[podName]= version
218+
}else{
219+
iflet previousVersion =versions[podName], version != previousVersion {
220+
fatalError("Different installed versions for \(podName)."+
221+
"\(version) versus \(previousVersion)")
222+
}else{
223+
letbasePodName=subspecArray[0]
224+
versions[basePodName]= version
225+
subspecs[basePodName, default:Set()].insert(subspecArray[1])
226+
deps[basePodName]=deps[basePodName, default:Set()].union(deps[podName]??Set())
227+
}
228+
}
229+
}
208230

209231
// Generate an InstalledPod for each Pod found.
210232
letpodsDir= projectDir.appendingPathComponent("Pods")
211233
varinstalledPods:[String:PodInfo]=[:]
212-
for(podName, version)inpods{
234+
for(podName, version)inversions{
213235
varpodDir= podsDir.appendingPathComponent(podName)
214236
// Make sure that pod got installed if it's not coming from a local podspec.
215237
if !FileManager.default.directoryExists(at: podDir){
@@ -220,7 +242,8 @@ enum CocoaPodUtils {
220242
podDir = repoDir
221243
}
222244
letdependencies=[String](deps[podName]??[])
223-
letpodInfo=PodInfo(version: version, dependencies: dependencies, installedLocation: podDir)
245+
letpodInfo=PodInfo(version: version, dependencies: dependencies, installedLocation: podDir,
246+
subspecs:subspecs[podName]??Set())
224247
installedPods[podName]= podInfo
225248
}
226249
return installedPods

ZipBuilder/Sources/ZipBuilder/FrameworkBuilder.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,9 @@ struct FrameworkBuilder {
408408
}
409409
// Verify Firebase frameworks include an explicit umbrella header for Firebase.h.
410410
letheadersDir= podsDir.appendingPathComponents(["Headers","Public", framework])
411-
if framework.hasPrefix("Firebase"), framework !="FirebaseCoreDiagnostics"{
411+
if framework.hasPrefix("Firebase"),
412+
framework !="FirebaseCoreDiagnostics",
413+
framework !="FirebaseUI"{
412414
letframeworkHeader= headersDir.appendingPathComponent("\(framework).h")
413415
guard fileManager.fileExists(atPath: frameworkHeader.path)else{
414416
fatalError("Missing explicit umbrella header for \(framework).")

ZipBuilder/Sources/ZipBuilder/ModuleMapBuilder.swift

+21-7
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@ struct ModuleMapBuilder {
2323
privateclassFrameworkInfo{
2424
letisSourcePod:Bool
2525
letversionedPod:CocoaPodUtils.VersionedPod
26+
letsubspecs:Set<String>
2627
vartransitiveFrameworks:Set<String>?
2728
vartransitiveLibraries:Set<String>?
2829

29-
init(isSourcePod:Bool, versionedPod:CocoaPodUtils.VersionedPod){
30+
init(isSourcePod:Bool, versionedPod:CocoaPodUtils.VersionedPod, subspecs:Set<String>){
3031
self.isSourcePod = isSourcePod
3132
self.versionedPod = versionedPod
33+
self.subspecs = subspecs
3234
}
3335
}
3436

@@ -55,11 +57,8 @@ struct ModuleMapBuilder {
5557

5658
varinstalledPods:[String:FrameworkInfo]=[:]
5759
forpodin selectedPods {
58-
letframeworkName= pod.key
59-
letisSourcePod= pod.value.isSourcePod
60-
letversion= pod.value.version
61-
letversionedPod=CocoaPodUtils.VersionedPod(name: frameworkName, version: version)
62-
installedPods[frameworkName]=FrameworkInfo(isSourcePod: isSourcePod, versionedPod: versionedPod)
60+
letversionedPod=CocoaPodUtils.VersionedPod(name: pod.key, version: pod.value.version)
61+
installedPods[pod.key]=FrameworkInfo(isSourcePod: pod.value.isSourcePod, versionedPod: versionedPod, subspecs: pod.value.subspecs)
6362
}
6463
self.installedPods = installedPods
6564
}
@@ -85,7 +84,7 @@ struct ModuleMapBuilder {
8584
privatefunc generate(framework:FrameworkInfo){
8685
letpodName= framework.versionedPod.name
8786
letdeps=CocoaPodUtils.transitiveVersionedPodDependencies(for: podName, in: allPods)
88-
_ =CocoaPodUtils.installPods([framework.versionedPod]+ deps,
87+
_ =CocoaPodUtils.installPods(allSubspecList(framework: framework)+ deps,
8988
inDir: projectDir,
9089
customSpecRepos: customSpecRepos)
9190
letxcconfigFile= projectDir.appendingPathComponents(["Pods","Target Support Files",
@@ -94,6 +93,21 @@ struct ModuleMapBuilder {
9493
allPods[podName]?.moduleMapContents =makeModuleMap(forFramework: framework, withXcconfigFile: xcconfigFile)
9594
}
9695

96+
/// Convert a list of versioned pods to a list of versioned pods specified with all needed subspecs.
97+
privatefunc allSubspecList(framework:FrameworkInfo)->[CocoaPodUtils.VersionedPod]{
98+
letname= framework.versionedPod.name
99+
letversion= framework.versionedPod.version
100+
letsubspecs= framework.subspecs
101+
if subspecs.count ==0{
102+
return[CocoaPodUtils.VersionedPod(name:"\(name)", version: version)]
103+
}
104+
varlist:[CocoaPodUtils.VersionedPod]=[]
105+
forsubspecin framework.subspecs {
106+
list.append(CocoaPodUtils.VersionedPod(name:"\(name)/\(subspec)", version: version))
107+
}
108+
return list
109+
}
110+
97111
// Extract the framework and library dependencies for a framework from
98112
// the xcconfig file from an app generated from a Podfile only with that
99113
// CocoaPod and removing the frameworks and libraries from its transitive dependencies.

0 commit comments

Comments
 (0)
close