Replace single-package scaffolding with monorepo Package.swift generation
This commit is contained in:
parent
f6adf61167
commit
5278fe90c3
1 changed files with 117 additions and 0 deletions
|
|
@ -20,6 +20,7 @@ extension CodeGenerator {
|
||||||
/// - repository: The parsed GIR repository containing namespace metadata,
|
/// - repository: The parsed GIR repository containing namespace metadata,
|
||||||
/// `<c:include>`, `<include>`, and `<package>` values.
|
/// `<c:include>`, `<include>`, and `<package>` values.
|
||||||
/// - Returns: A dictionary of relative path → file content.
|
/// - Returns: A dictionary of relative path → file content.
|
||||||
|
@available(*, deprecated, message: "Use generateMonorepoScaffolding(analysis:) for monorepo packages.")
|
||||||
public static func generatePackageScaffolding(config: GenerationConfig, repository: Repository) -> [String: String] {
|
public static func generatePackageScaffolding(config: GenerationConfig, repository: Repository) -> [String: String] {
|
||||||
var files: [String: String] = [:]
|
var files: [String: String] = [:]
|
||||||
let cName = "C\(config.library)"
|
let cName = "C\(config.library)"
|
||||||
|
|
@ -114,6 +115,122 @@ extension CodeGenerator {
|
||||||
return files
|
return files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Monorepo Package Scaffolding Generation
|
||||||
|
|
||||||
|
/// Generates all scaffolding files for the monorepo: Package.swift,
|
||||||
|
/// C bridge module maps and umbrella headers, and re-export files.
|
||||||
|
///
|
||||||
|
/// - Parameter analysis: The resolved multi-package analysis.
|
||||||
|
/// - Returns: A dictionary of relative path → file content.
|
||||||
|
public static func generateMonorepoScaffolding(analysis: MultiPackageAnalysis) -> [String: String] {
|
||||||
|
var files: [String: String] = [:]
|
||||||
|
|
||||||
|
// Re-export umbrella files
|
||||||
|
let umbrellas = generateReexportUmbrellas(analysis: analysis)
|
||||||
|
for (path, content) in umbrellas {
|
||||||
|
files[path] = content
|
||||||
|
}
|
||||||
|
|
||||||
|
// C bridge files
|
||||||
|
for (moduleName, repo) in analysis.repositories {
|
||||||
|
let cName = "C\(moduleName)"
|
||||||
|
let ns = repo.namespaces.first { $0.name == moduleName } ?? repo.namespaces.first
|
||||||
|
|
||||||
|
let sharedLibrary = ns?.cSharedLibrary ?? ""
|
||||||
|
let libraries = sharedLibrary.split(separator: ",").map(String.init)
|
||||||
|
let allLinkNames = libraries.compactMap { extractLinkName(from: $0) }
|
||||||
|
let lowerModName = moduleName.lowercased()
|
||||||
|
let cHeader = repo.cHeaderPath
|
||||||
|
let umbrellaHeader = cHeader.isEmpty
|
||||||
|
? "#include <\(lowerModName)/\(lowerModName).h>"
|
||||||
|
: "#include <\(cHeader)>"
|
||||||
|
|
||||||
|
// External C link names from GIR includes
|
||||||
|
var externalLinks: [String] = []
|
||||||
|
for include in repo.includedPackages {
|
||||||
|
let el = include.name.lowercased()
|
||||||
|
if !externalLinks.contains(el) {
|
||||||
|
externalLinks.append(el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let linkLines = (allLinkNames + externalLinks).map { " link \"\($0)\"" }.joined(separator: "\n")
|
||||||
|
let moduleMap = """
|
||||||
|
module \(cName) [system] {
|
||||||
|
header "\(cName).h"
|
||||||
|
\(linkLines)
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
files["Sources/\(cName)/module.modulemap"] = moduleMap
|
||||||
|
files["Sources/\(cName)/\(cName).h"] = umbrellaHeader + "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monorepo Package.swift
|
||||||
|
let packageSwift = generateMonorepoPackage(analysis: analysis)
|
||||||
|
files["Package.swift"] = packageSwift
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates the single monorepo Package.swift containing all targets.
|
||||||
|
private static func generateMonorepoPackage(analysis: MultiPackageAnalysis) -> String {
|
||||||
|
let moduleNames = analysis.repositories.keys.sorted()
|
||||||
|
|
||||||
|
// Products
|
||||||
|
var products = ""
|
||||||
|
for name in moduleNames {
|
||||||
|
products += " .library(name: \"\(name)\", targets: [\"\(name)\"]),\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
// C system library targets
|
||||||
|
var cTargets = ""
|
||||||
|
for name in moduleNames {
|
||||||
|
let cName = "C\(name)"
|
||||||
|
cTargets += " .systemLibrary(name: \"\(cName)\", path: \"Sources/\(cName)\"),\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swift wrapper targets
|
||||||
|
var swiftTargets = ""
|
||||||
|
for name in moduleNames {
|
||||||
|
let cName = "C\(name)"
|
||||||
|
let dirDeps = analysis.directDependencies[name] ?? []
|
||||||
|
var depList = "\"\(cName)\""
|
||||||
|
for dep in dirDeps.sorted() {
|
||||||
|
depList += ", \"\(dep)\""
|
||||||
|
}
|
||||||
|
swiftTargets += """
|
||||||
|
.target(
|
||||||
|
name: "\(name)",
|
||||||
|
dependencies: [\(depList)],
|
||||||
|
swiftSettings: swiftSettings
|
||||||
|
),
|
||||||
|
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
return """
|
||||||
|
// swift-tools-version: 6.2
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let swiftSettings: [SwiftSetting] = [
|
||||||
|
.enableExperimentalFeature("StrictConcurrency=complete"),
|
||||||
|
.defaultIsolation(MainActor.self),
|
||||||
|
.enableUpcomingFeature("NonisolatedNonsendingByDefault"),
|
||||||
|
]
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "gtk-swift",
|
||||||
|
platforms: [.macOS(.v14)],
|
||||||
|
products: [
|
||||||
|
\(products) ],
|
||||||
|
targets: [
|
||||||
|
\(cTargets)
|
||||||
|
\(swiftTargets) ]
|
||||||
|
)
|
||||||
|
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
/// Extracts link name from a shared-library string like "libgtk-4.so.1" -> "gtk-4".
|
/// Extracts link name from a shared-library string like "libgtk-4.so.1" -> "gtk-4".
|
||||||
private static func extractLinkName(from sharedLib: String) -> String? {
|
private static func extractLinkName(from sharedLib: String) -> String? {
|
||||||
guard sharedLib.hasPrefix("lib") else { return nil }
|
guard sharedLib.hasPrefix("lib") else { return nil }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue