diff --git a/Package.swift b/Package.swift index 329c757..13e39b9 100644 --- a/Package.swift +++ b/Package.swift @@ -15,9 +15,11 @@ let package = Package( ], products: [ .executable(name: "swift-package-list", targets: ["SwiftPackageListCommand"]), + .executable(name: "SwiftPackageListCommand", targets: ["SwiftPackageListCommand"]), .library(name: "SwiftPackageList", targets: ["SwiftPackageList"]), .library(name: "SwiftPackageListObjc", type: .dynamic, targets: ["SwiftPackageListObjc"]), .library(name: "SwiftPackageListUI", targets: ["SwiftPackageListUI"]), + .plugin(name: "SwiftPackageListPlugin", targets: ["SwiftPackageListPlugin"]), ], dependencies: [ .package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.1"), @@ -57,5 +59,10 @@ let package = Package( dependencies: ["SwiftPackageListObjc"], resources: [.process("Resources")] ), + .plugin( + name: "SwiftPackageListPlugin", + capability: .buildTool(), + dependencies: [.target(name: "SwiftPackageListCommand")] + ), ] ) diff --git a/Plugins/SwiftPackageListPlugin/FileManager+Extension.swift b/Plugins/SwiftPackageListPlugin/FileManager+Extension.swift new file mode 100644 index 0000000..d3d134e --- /dev/null +++ b/Plugins/SwiftPackageListPlugin/FileManager+Extension.swift @@ -0,0 +1,15 @@ +// +// File.swift +// +// +// Created by Dave Thompson on 16/03/2023. +// + +import Foundation + +extension FileManager { + func createDirectoryIfNotExists(atPath path: String) throws { + guard !fileExists(atPath: path) else { return } + try createDirectory(atPath: path, withIntermediateDirectories: true) + } +} diff --git a/Plugins/SwiftPackageListPlugin/SwiftPackageListPlugin.swift b/Plugins/SwiftPackageListPlugin/SwiftPackageListPlugin.swift new file mode 100644 index 0000000..da4cb40 --- /dev/null +++ b/Plugins/SwiftPackageListPlugin/SwiftPackageListPlugin.swift @@ -0,0 +1,56 @@ +// +// File.swift +// swift-package-list +// +// Created by Dave Thompson on 14/03/2023. +// + +import Foundation +import PackagePlugin + +@main struct Plugin: BuildToolPlugin { + func createBuildCommands(context: PackagePlugin.PluginContext, + target: PackagePlugin.Target) async throws -> [PackagePlugin.Command] { + let projectFilePath = "\(context.package.directory)/\(context.package.displayName).xcodeproj" + let outputFilePath = try outputFilePath(workDirectory: context.pluginWorkDirectory) + return [ + .buildCommand( + displayName: "SwiftPackageListPlugin", + executable: try context.tool(named: "SwiftPackageListCommand").path, + arguments: [projectFilePath, "--output-path", outputFilePath.removingLastComponent(), "--requires-license"], + outputFiles: [outputFilePath] + ) + ] + } +} + +extension Plugin { + private func outputFilePath(workDirectory: Path) throws -> Path { + let outputDirectory = workDirectory.appending("Output") + try FileManager.default.createDirectoryIfNotExists(atPath: outputDirectory.string) + return outputDirectory.appending("package-list.json") + } +} + +#if canImport(XcodeProjectPlugin) + import XcodeProjectPlugin + + extension Plugin: XcodeBuildToolPlugin { + /// This entry point is called when operating on an Xcode project + func createBuildCommands(context: XcodeProjectPlugin.XcodePluginContext, + target: XcodeProjectPlugin.XcodeTarget) throws -> [PackagePlugin.Command] { + let projectFilePath = "\(context.xcodeProject.directory)/\(target.displayName).xcodeproj" + let outputFilePath = try outputFilePath(workDirectory: context.pluginWorkDirectory) + return [ + .buildCommand( + displayName: "SwiftPackageListPlugin", + executable: try context.tool(named: "SwiftPackageListCommand").path, + arguments: [projectFilePath, "--output-path", outputFilePath.removingLastComponent(), "--requires-license"], + outputFiles: [outputFilePath] + ) + ] + } + + + } +#endif diff --git a/README.md b/README.md index 051c5b1..d168154 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,11 @@ A command-line tool to generate a JSON, PLIST, Settings.bundle or PDF file with This includes all the `Package.resolved` informations and the license from the checkouts. Additionally there is a Swift Package to read the generated package-list file from the application's bundle with a top-level function or pre-build UI. +## Brightec Fork + +The fork adds a plugin product to the package that allow the executable to be called as a build tool plugin. This can then be used by an XCode project to auto generate a 3rd party licenses view for use in iOS or macOS projects. + +AcknowledmentsList has also been updated to allow modification of the screen title. It also allows you to additionally append a list of packages to the packages found in the packag-list.json, this caters for the case where additional licenses need to be added that aren't in the swift package manager list. ## Command-Line Tool diff --git a/Sources/SwiftPackageListCommand/SwiftPackageListCommand.swift b/Sources/SwiftPackageListCommand/SwiftPackageListCommand.swift index c563413..b9096c7 100644 --- a/Sources/SwiftPackageListCommand/SwiftPackageListCommand.swift +++ b/Sources/SwiftPackageListCommand/SwiftPackageListCommand.swift @@ -13,7 +13,7 @@ import SwiftPackageListCore struct SwiftPackageListCommand: ParsableCommand { static var configuration: CommandConfiguration { - return CommandConfiguration(version: "2.1.3") + return CommandConfiguration(version: "2.2.0") } @Argument(help: "The path to your .xcodeproj or .xcworkspace file.") diff --git a/Sources/SwiftPackageListCore/Output Generation/PDF/PDFGenerator.swift b/Sources/SwiftPackageListCore/Output Generation/PDF/PDFGenerator.swift index 7a47f4a..0bbbe29 100644 --- a/Sources/SwiftPackageListCore/Output Generation/PDF/PDFGenerator.swift +++ b/Sources/SwiftPackageListCore/Output Generation/PDF/PDFGenerator.swift @@ -5,7 +5,16 @@ // Created by Felix Herrmann on 11.04.22. // -import AppKit +#if os(OSX) + import AppKit +typealias AliasFont = NSFont +typealias AliasEdgeInsets = NSEdgeInsets +#elseif os(iOS) + import UIKit +typealias AliasFont = UIFont +typealias AliasEdgeInsets = UIEdgeInsets +#endif + import SwiftPackageList struct PDFGenerator: OutputGenerator { @@ -67,10 +76,10 @@ struct PDFGenerator: OutputGenerator { } private func buildAttributedString() throws -> NSMutableAttributedString { - guard let defaultFont = NSFont(name: "Helvetica", size: 12) else { + guard let defaultFont = AliasFont(name: "Helvetica", size: 12) else { throw RuntimeError("Font \"Helvetica\" not available") } - guard let boldFont = NSFont(name: "Helvetica Bold", size: 12) else { + guard let boldFont = AliasFont(name: "Helvetica Bold", size: 12) else { throw RuntimeError("Font \"Helvetica Bold\" not available") } @@ -112,7 +121,7 @@ struct PDFGenerator: OutputGenerator { private func calculateDrawableRect(in context: CGContext) -> CGRect { let boxRect = context.boundingBoxOfClipPath - let insets = NSEdgeInsets(top: 80, left: 80, bottom: 80, right: 80) + let insets = AliasEdgeInsets(top: 80, left: 80, bottom: 80, right: 80) let x = boxRect.origin.x + insets.left let y = boxRect.origin.y + insets.top diff --git a/Sources/SwiftPackageListUI/SwiftUI/AcknowledgmentsList.swift b/Sources/SwiftPackageListUI/SwiftUI/AcknowledgmentsList.swift index 20cb995..f8172bd 100644 --- a/Sources/SwiftPackageListUI/SwiftUI/AcknowledgmentsList.swift +++ b/Sources/SwiftPackageListUI/SwiftUI/AcknowledgmentsList.swift @@ -8,6 +8,7 @@ #if canImport(SwiftUI) import SwiftUI +import SwiftPackageList /// A `List` that shows all licenses from the package-list file. /// @@ -38,14 +39,16 @@ import SwiftUI @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public struct AcknowledgmentsList: View { + private var _title: Text? @ObservedObject private var _viewModel: _AcknowledgmentsListViewModel /// Creates a ``AcknowledgmentsList`` for a package-list file. /// - Parameters: /// - packageListBundle: The bundle where the package-list file is stored. Default's to `Bundle.main`. /// - packageListFileName: The name of the package-list file. Default's to `package-list`. - public init(packageListBundle: Bundle = .main, packageListFileName: String = "package-list") { - _viewModel = _AcknowledgmentsListViewModel(packageListBundle: packageListBundle, packageListFileName: packageListFileName) + public init(packageListBundle: Bundle = .main, packageListFileName: String = "package-list", otherPackages: [Package] = [], title: Text? = nil) { + _viewModel = _AcknowledgmentsListViewModel(packageListBundle: packageListBundle, packageListFileName: packageListFileName, otherPackages) + _title = title } public var body: some View { @@ -60,7 +63,7 @@ public struct AcknowledgmentsList: View { } } } - ._navigationTitle(Text("acknowledgments.title", bundle: .module, comment: "Navigation bar title of the license list")) + ._navigationTitle(_title ?? Text("acknowledgments.title", bundle: .module, comment: "Navigation bar title of the license list")) } } diff --git a/Sources/SwiftPackageListUI/SwiftUI/_AcknowledgmentsListViewModel.swift b/Sources/SwiftPackageListUI/SwiftUI/_AcknowledgmentsListViewModel.swift index 60551a0..abcc6c4 100644 --- a/Sources/SwiftPackageListUI/SwiftUI/_AcknowledgmentsListViewModel.swift +++ b/Sources/SwiftPackageListUI/SwiftUI/_AcknowledgmentsListViewModel.swift @@ -14,9 +14,10 @@ internal final class _AcknowledgmentsListViewModel: ObservableObject { @Published internal var _packages: [Package] = [] - internal init(packageListBundle: Bundle, packageListFileName: String) { + internal init(packageListBundle: Bundle, packageListFileName: String, _ otherPackages: [Package] = []) { do { _packages = try packageList(bundle: packageListBundle, fileName: packageListFileName) + _packages.append(contentsOf: otherPackages) } catch { os_log( "Error: %@",