Skip to content

Commit

Permalink
Implement system dependency checking plugin to fix terrible SwiftPM e…
Browse files Browse the repository at this point in the history
…rrors for missing system dependencies
  • Loading branch information
stackotter committed Apr 7, 2024
1 parent 612a3d1 commit 09d6a23
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 3 deletions.
13 changes: 11 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ let package = Package(
.target(name: "AppKitBackend", dependencies: ["SwiftCrossUI"]),
.target(
name: "QtBackend",
dependencies: ["SwiftCrossUI", .product(name: "Qlift", package: "qlift")]
dependencies: ["SwiftCrossUI", .product(name: "Qlift", package: "qlift")],
plugins: ["DependencyCheckingPlugin"]
),
.target(
name: "CursesBackend",
Expand All @@ -91,7 +92,11 @@ let package = Package(
.product(name: "CLVGL", package: "LVGLSwift"),
]
),
.target(name: "GtkBackend", dependencies: ["SwiftCrossUI", "Gtk", "CGtk"]),
.target(
name: "GtkBackend",
dependencies: ["SwiftCrossUI", "Gtk", "CGtk"],
plugins: ["DependencyCheckingPlugin"]
),
.systemLibrary(
name: "CGtk",
pkgConfig: "gtk4",
Expand All @@ -112,6 +117,10 @@ let package = Package(
"XMLCoder", .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"),
]
),
.plugin(
name: "DependencyCheckingPlugin",
capability: .buildTool()
),
]
)

Expand Down
98 changes: 98 additions & 0 deletions Plugins/DependencyCheckingPlugin/DependencyCheckingPlugin.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import Foundation
import PackagePlugin

enum DependencyError: Error, CustomStringConvertible {
case missingSystemDependency(String)

var description: String {
switch self {
case .missingSystemDependency(let name):
Diagnostics.error("Missing '\(name)' system dependency.")

#if os(Windows)
return "No installation instructions for Windows."
#else
let installationInstructions: String?
let packageManager: String
#if os(macOS)
packageManager = "brew"
switch name {
case "CGtk":
installationInstructions = "brew install gtk4"
case "Qt5Widgets":
installationInstructions = "brew install qt@5 && brew link qt@5"
default:
installationInstructions = nil
}
#elseif os(Linux)
packageManager = "apt"
switch name {
case "CGtk":
installationInstructions = "apt install libgtk-4-dev clang"
case "Qt5Widgets":
installationInstructions = "apt install qt5-default"
default:
installationInstructions = nil
}
#endif

let instructions =
installationInstructions
?? "Missing installation instructions for '\(name)', please open an issue at https://github.com/stackotter/swift-cross-ui"
return "To install with \(packageManager): \(instructions)"
#endif
}
}
}

@main
struct DependencyCheckingPlugin: BuildToolPlugin {
func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] {
if ProcessInfo.processInfo.environment["SWIFTCROSSUI_SKIP_DEP_CHECK"] == "1" {
return []
}

#if os(Windows)
Diagnostics.warning(
"Dependency checking not implemented on Windows. Set SWIFTCROSSUI_SKIP_DEP_CHECK=1 to disable this warning"
)
return []
#endif

for dependency in target.recursiveTargetDependencies {
try check(dependency)
}

return []
}

func check(_ target: Target) throws {
// TODO: Add hardcoded checks for curses and lvgl
if let systemDependency = target as? SystemLibraryTarget {
guard let pkgConfigName = systemDependency.pkgConfig else {
Diagnostics.warning(
"Dependency checking not implemented for system libraries without pkgConfig names, manually implement a check for '\(systemDependency.name)'"
)
return
}

try checkPkgConfig(pkgConfigName)
}
}

func checkPkgConfig(_ name: String) throws {
let process = Process()
process.executableURL = URL(fileURLWithPath: "/usr/bin/env")
process.arguments = [
"pkg-config",
name,
]

try process.run()
process.waitUntilExit()

if process.terminationStatus != 0 {
throw DependencyError.missingSystemDependency(name)
}
}
}
2 changes: 1 addition & 1 deletion format_and_lint.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
swift format format --in-place --recursive --configuration .swift-format Sources Examples
swift format format --in-place --recursive --configuration .swift-format Sources Examples/Sources Plugins
swiftlint lint --quiet

0 comments on commit 09d6a23

Please sign in to comment.