Skip to content

Commit 0306fc2

Browse files
authored
Handle Xcode 11.4 changes to Swift module maps (#5294)
* Fix broken outputDirs zipPods option combination
1 parent ecfe3ee commit 0306fc2

File tree

5 files changed

+58
-18
lines changed

5 files changed

+58
-18
lines changed

ZipBuilder/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ In order to build the Zip file, you will need:
2424
You can run the tool with `swift run ReleasePackager [ARGS]` or generate an Xcode project with
2525
`swift package generate-xcodeproj` and run within Xcode.
2626

27+
Since Apple does not support linking libraries built by future Xcode versions, make sure to builid with the
28+
earliest Xcode needed by any of the library clients. The Xcode command line tools must also be configured
29+
for that version. Check with `xcodebuild -version`.
30+
2731
### Launch Arguments
2832

2933
See `main.swift` and the `LaunchArgs` struct for information on specific launch arguments.

ZipBuilder/Sources/ZipBuilder/FrameworkBuilder.swift

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -670,15 +670,37 @@ struct FrameworkBuilder {
670670
let destSwiftModuleDir = destModuleDir.appendingPathComponent(swiftModule.lastPathComponent)
671671
for file in files {
672672
let fileURL = URL(fileURLWithPath: file)
673-
do {
674-
try fileManager.copyItem(at: fileURL, to:
675-
destSwiftModuleDir.appendingPathComponent(fileURL.lastPathComponent))
676-
} catch {
677-
fatalError("Could not copy Swift module file from \(fileURL) to " + "\(destSwiftModuleDir): \(error)")
673+
let projectDir = swiftModule.appendingPathComponent("Project")
674+
if fileURL.lastPathComponent == "Project",
675+
fileManager.directoryExists(at: projectDir) {
676+
// The Project directory (introduced with Xcode 11.4) already exist, only copy in
677+
// new contents.
678+
let projectFiles = try fileManager.contentsOfDirectory(at: projectDir,
679+
includingPropertiesForKeys: nil).compactMap { $0.path }
680+
let destProjectDir = destSwiftModuleDir.appendingPathComponent("Project")
681+
for projectFile in projectFiles {
682+
let projectFileURL = URL(fileURLWithPath: projectFile)
683+
do {
684+
try fileManager.copyItem(at: projectFileURL, to:
685+
destProjectDir.appendingPathComponent(projectFileURL.lastPathComponent))
686+
} catch {
687+
fatalError("Could not copy Project file from \(projectFileURL) to " +
688+
"\(destProjectDir): \(error)")
689+
}
690+
}
691+
} else {
692+
do {
693+
try fileManager.copyItem(at: fileURL, to:
694+
destSwiftModuleDir.appendingPathComponent(fileURL.lastPathComponent))
695+
} catch {
696+
fatalError("Could not copy Swift module file from \(fileURL) to " +
697+
"\(destSwiftModuleDir): \(error)")
698+
}
678699
}
679700
}
680701
} catch {
681-
fatalError("Failed to get Modules directory contents - \(moduleDir): \(error.localizedDescription)")
702+
fatalError("Failed to get Modules directory contents - \(moduleDir):" +
703+
"\(error.localizedDescription)")
682704
}
683705
}
684706
} catch {

ZipBuilder/Sources/ZipBuilder/LaunchArgs.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ struct LaunchArgs {
4040
/// Keys associated with the launch args. See `Usage` for descriptions of each flag.
4141
private enum Key: String, CaseIterable {
4242
case archs
43+
case buildDependencies
4344
case buildRoot
4445
case carthageDir
4546
case carthageSkipVersionCheck
@@ -62,6 +63,8 @@ struct LaunchArgs {
6263
case .archs:
6364
return "The list of architectures to build for. The default list is " +
6465
"\(Architecture.allCases.map { $0.rawValue })."
66+
case .buildDependencies:
67+
return "Whether or not to build dependencies of requested pods. The default is true."
6568
case .buildRoot:
6669
return "The root directory for build artifacts. If `nil`, a temporary directory will be " +
6770
"used."
@@ -109,6 +112,9 @@ struct LaunchArgs {
109112
/// verify expected version numbers.
110113
let allSDKsPath: URL?
111114

115+
/// Build dependencies flag.
116+
let buildDependencies: Bool
117+
112118
/// The root directory for build artifacts. If `nil`, a temporary directory will be used.
113119
let buildRoot: URL?
114120

@@ -170,6 +176,8 @@ struct LaunchArgs {
170176
// Override default values for specific keys.
171177
// - Always run `pod repo update` and pod cache clean -all` unless explicitly set to false.
172178
defaults.register(defaults: [Key.updatePodRepo.rawValue: true])
179+
// - Always build dependencies unless explicitly set to false.
180+
defaults.register(defaults: [Key.buildDependencies.rawValue: true])
173181

174182
// Get the project template directory, and fail if it doesn't exist.
175183
guard let templatePath = defaults.string(forKey: Key.templateDir.rawValue) else {
@@ -336,6 +344,7 @@ struct LaunchArgs {
336344
minimumIOSVersion = "9.0"
337345
}
338346

347+
buildDependencies = defaults.bool(forKey: Key.buildDependencies.rawValue)
339348
carthageSkipVersionCheck = defaults.bool(forKey: Key.carthageSkipVersionCheck.rawValue)
340349
dynamic = defaults.bool(forKey: Key.dynamic.rawValue)
341350
updatePodRepo = defaults.bool(forKey: Key.updatePodRepo.rawValue)

ZipBuilder/Sources/ZipBuilder/ZipBuilder.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,14 +153,18 @@ struct ZipBuilder {
153153
ModuleMapBuilder(customSpecRepos: customSpecRepos, selectedPods: installedPods).build()
154154
}
155155

156+
let podsToBuild = LaunchArgs.shared.buildDependencies ? installedPods :
157+
installedPods.filter { podsToInstall.map { $0.name }.contains($0.key) }
158+
156159
// Generate the frameworks. Each key is the pod name and the URLs are all frameworks to be
157160
// copied in each product's directory.
158-
let (frameworks, carthageFrameworks) = generateFrameworks(fromPods: installedPods, inProjectDir: projectDir)
161+
let (frameworks, carthageFrameworks) = generateFrameworks(fromPods: podsToBuild,
162+
inProjectDir: projectDir)
159163

160164
for (framework, paths) in frameworks {
161165
print("Frameworks for pod: \(framework) were compiled at \(paths)")
162166
}
163-
return (installedPods, frameworks, carthageFrameworks)
167+
return (podsToBuild, frameworks, carthageFrameworks)
164168
}
165169

166170
// TODO: This function contains a lot of "copy these paths to this directory, fail if there are

ZipBuilder/Sources/ZipBuilder/main.swift

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,24 +51,22 @@ if let outputDir = args.outputDir {
5151
}
5252
}
5353

54-
var zipped: URL
55-
if args.zipPods == nil {
56-
// Do a Firebase build.
57-
FirebaseBuilder(zipBuilder: builder).build(in: projectDir)
58-
} else {
59-
let (installedPods, frameworks, _) = builder.buildAndAssembleZip(podsToInstall: LaunchArgs.shared.zipPods!)
54+
if let zipPods = args.zipPods {
55+
let (installedPods, frameworks, _) = builder.buildAndAssembleZip(podsToInstall: zipPods)
6056
let staging = FileManager.default.temporaryDirectory(withName: "staging")
6157
try builder.copyFrameworks(fromPods: Array(installedPods.keys), toDirectory: staging,
6258
frameworkLocations: frameworks)
63-
zipped = Zip.zipContents(ofDir: staging, name: "Frameworks.zip")
59+
let zipped = Zip.zipContents(ofDir: staging, name: "Frameworks.zip")
6460
print(zipped.absoluteString)
6561
if let outputDir = args.outputDir {
66-
try FileManager.default.copyItem(at: zipped, to: outputDir)
67-
print("Success! Zip file can be found at \(outputDir.path)")
62+
let outputFile = outputDir.appendingPathComponent("Frameworks.zip")
63+
try FileManager.default.copyItem(at: zipped, to: outputFile)
64+
print("Success! Zip file can be found at \(outputFile.path)")
6865
} else {
6966
// Move zip to parent directory so it doesn't get removed with other artifacts.
7067
let parentLocation =
71-
zipped.deletingLastPathComponent().deletingLastPathComponent().appendingPathComponent(zipped.lastPathComponent)
68+
zipped.deletingLastPathComponent().deletingLastPathComponent()
69+
.appendingPathComponent(zipped.lastPathComponent)
7270
// Clear out the output file if it exists.
7371
FileManager.default.removeIfExists(at: parentLocation)
7472
do {
@@ -78,6 +76,9 @@ if args.zipPods == nil {
7876
}
7977
print("Success! Zip file can be found at \(parentLocation.path)")
8078
}
79+
} else {
80+
// Do a Firebase Zip Release package build.
81+
FirebaseBuilder(zipBuilder: builder).build(in: projectDir)
8182
}
8283

8384
if !args.keepBuildArtifacts {

0 commit comments

Comments
 (0)