diff --git a/Package.swift b/Package.swift index 7ac7d1f9..722859ee 100644 --- a/Package.swift +++ b/Package.swift @@ -205,6 +205,7 @@ let package = Package( .package(url: "https://github.com/swiftlang/swift-syntax", from: "602.0.0"), .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), .package(url: "https://github.com/apple/swift-system", from: "1.4.0"), + .package(url: "https://github.com/apple/swift-log", from: "1.2.0"), // // FIXME: swift-subprocess stopped supporting 6.0 when it moved into a package; // // we'll need to drop 6.0 as well, but currently blocked on doing so by swiftpm plugin pending design questions @@ -395,6 +396,7 @@ let package = Package( .target( name: "SwiftJavaToolLib", dependencies: [ + .product(name: "Logging", package: "swift-log"), .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), @@ -418,6 +420,7 @@ let package = Package( .executableTarget( name: "SwiftJavaTool", dependencies: [ + .product(name: "Logging", package: "swift-log"), .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), diff --git a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift index 3bce6c18..9a05a286 100644 --- a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift +++ b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +import Logging import ArgumentParser import Foundation import SwiftJavaToolLib @@ -27,6 +28,9 @@ import SwiftJavaShared extension SwiftJava { struct ConfigureCommand: SwiftJavaBaseAsyncParsableCommand, HasCommonOptions, HasCommonJVMOptions { + + static let log: Logging.Logger = Logger(label: "swift-java:\(configuration.commandName!)") + static let configuration = CommandConfiguration( commandName: "configure", abstract: "Configure and emit a swift-java.config file based on an input dependency or jar file") @@ -63,7 +67,7 @@ extension SwiftJava { extension SwiftJava.ConfigureCommand { mutating func runSwiftJavaCommand(config: inout Configuration) async throws { let classpathEntries = self.configureCommandJVMClasspath( - searchDirs: [self.effectiveSwiftModuleURL], config: config) + searchDirs: [self.effectiveSwiftModuleURL], config: config, log: Self.log) let jvm = try self.makeJVM(classpathEntries: classpathEntries) diff --git a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift index 69ad3ebe..43362edb 100644 --- a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift +++ b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift @@ -14,15 +14,18 @@ import Foundation import ArgumentParser +import Logging import SwiftJavaToolLib import SwiftJava import JavaUtilJar -import SwiftJavaToolLib import SwiftJavaConfigurationShared extension SwiftJava { struct WrapJavaCommand: SwiftJavaBaseAsyncParsableCommand, HasCommonOptions, HasCommonJVMOptions { + + static let log: Logging.Logger = .init(label: "swift-java:\(configuration.commandName!)") + static let configuration = CommandConfiguration( commandName: "wrap-java", abstract: "Wrap Java classes with corresponding Swift bindings.") @@ -74,7 +77,7 @@ extension SwiftJava.WrapJavaCommand { print("[trace][swift-java] INPUT: \(input)") var classpathEntries = self.configureCommandJVMClasspath( - searchDirs: classpathSearchDirs, config: config) + searchDirs: classpathSearchDirs, config: config, log: Self.log) // Load all of the dependent configurations and associate them with Swift modules. let dependentConfigs = try loadDependentConfigs(dependsOn: self.dependsOn).map { moduleName, config in diff --git a/Sources/SwiftJavaTool/CommonOptions.swift b/Sources/SwiftJavaTool/CommonOptions.swift index c88ecbc8..e8aee62d 100644 --- a/Sources/SwiftJavaTool/CommonOptions.swift +++ b/Sources/SwiftJavaTool/CommonOptions.swift @@ -20,6 +20,7 @@ import SwiftJava import JavaUtilJar import JavaNet import SwiftSyntax +import Logging import SwiftJavaConfigurationShared import SwiftJavaShared @@ -43,7 +44,7 @@ extension SwiftJava { var inputSwift: String? = nil @Option(name: .shortAndLong, help: "Configure the level of logs that should be printed") - var logLevel: Logger.Level = .info + var logLevel: JExtractSwiftLib.Logger.Level = .info } struct CommonJVMOptions: ParsableArguments { @@ -78,46 +79,46 @@ extension HasCommonJVMOptions { /// swift-java.classpath files as configured. /// Parameters: /// - searchDirs: search directories where we can find swift.java.classpath files to include in the configuration - func configureCommandJVMClasspath(searchDirs: [Foundation.URL], config: Configuration) -> [String] { + func configureCommandJVMClasspath(searchDirs: [Foundation.URL], config: Configuration, log: Logging.Logger) -> [String] { // Form a class path from all of our input sources: // * Command-line option --classpath let classpathOptionEntries: [String] = self.classpathEntries let classpathFromEnv = ProcessInfo.processInfo.environment["CLASSPATH"]?.split(separator: ":").map(String.init) ?? [] - print("[debug][swift-java] Base classpath from CLASSPATH environment: \(classpathFromEnv)") + log.debug("Base classpath from CLASSPATH environment: \(classpathFromEnv)") let classpathFromConfig: [String] = config.classpath?.split(separator: ":").map(String.init) ?? [] - print("[debug][swift-java] Base classpath from config: \(classpathFromConfig)") + log.debug("Base classpath from config: \(classpathFromConfig)") var classpathEntries: [String] = classpathFromConfig for searchDir in searchDirs { let classPathFilesSearchDirectory = searchDir.path - print("[debug][swift-java] Search *.swift-java.classpath in: \(classPathFilesSearchDirectory)") + log.debug("Search *.swift-java.classpath in: \(classPathFilesSearchDirectory)") let foundSwiftJavaClasspath = findSwiftJavaClasspaths(in: classPathFilesSearchDirectory) - print("[debug][swift-java] Classpath from *.swift-java.classpath files: \(foundSwiftJavaClasspath)") + log.debug("Classpath from *.swift-java.classpath files: \(foundSwiftJavaClasspath)") classpathEntries += foundSwiftJavaClasspath } if !classpathOptionEntries.isEmpty { - print("[debug][swift-java] Classpath from options: \(classpathOptionEntries)") + log.debug("Classpath from options: \(classpathOptionEntries)") classpathEntries += classpathOptionEntries } else { // * Base classpath from CLASSPATH env variable - print("[debug][swift-java] Classpath from environment: \(classpathFromEnv)") + log.debug("Classpath from environment: \(classpathFromEnv)") classpathEntries += classpathFromEnv } let extraClasspath = self.commonJVMOptions.classpath let extraClasspathEntries = extraClasspath.split(separator: ":").map(String.init) - print("[debug][swift-java] Extra classpath: \(extraClasspathEntries)") + log.debug("Extra classpath: \(extraClasspathEntries)") classpathEntries += extraClasspathEntries // Bring up the Java VM when necessary - // if logLevel >= .debug { + if log.logLevel >= .debug { let classpathString = classpathEntries.joined(separator: ":") - print("[debug][swift-java] Initialize JVM with classpath: \(classpathString)") - // } + log.debug("Initialize JVM with classpath: \(classpathString)") + } return classpathEntries } diff --git a/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift index 6b8c0ec6..9763b4b3 100644 --- a/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift +++ b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift @@ -24,9 +24,13 @@ import SwiftSyntax import SwiftSyntaxBuilder import SwiftJavaConfigurationShared import SwiftJavaShared +import Logging protocol SwiftJavaBaseAsyncParsableCommand: AsyncParsableCommand { - var logLevel: Logger.Level { get set } + + var log: Logging.Logger { get } + + var logLevel: JExtractSwiftLib.Logger.Level { get set } /// Must be implemented with an `@OptionGroup` in Command implementations var commonOptions: SwiftJava.CommonOptions { get set } @@ -45,8 +49,8 @@ extension SwiftJavaBaseAsyncParsableCommand { extension SwiftJavaBaseAsyncParsableCommand { public mutating func run() async { - print("[info][swift-java] Run \(Self.self): \(CommandLine.arguments.joined(separator: " "))") - print("[info][swift-java] Current work directory: \(URL(fileURLWithPath: ".").path)") + self.log.info("Run \(Self.self): \(CommandLine.arguments.joined(separator: " "))") + self.log.info("Current work directory: \(URL(fileURLWithPath: ".").path)") do { var config = try readInitialConfiguration(command: self) @@ -54,12 +58,12 @@ extension SwiftJavaBaseAsyncParsableCommand { } catch { // We fail like this since throwing out of the run often ends up hiding the failure reason when it is executed as SwiftPM plugin (!) let message = "Failed with error: \(error)" - print("[error][java-swift] \(message)") + self.log.error("\(message)") fatalError(message) } // Just for debugging so it is clear which command has finished - print("[debug][swift-java] " + "Done: ".green + CommandLine.arguments.joined(separator: " ").green) + self.log.debug("\("Done: ".green) \(CommandLine.arguments.joined(separator: " ").green)") } } @@ -95,7 +99,11 @@ extension SwiftJavaBaseAsyncParsableCommand { extension SwiftJavaBaseAsyncParsableCommand { - var logLevel: Logger.Level { + var log: Logging.Logger { // FIXME: replace with stored property inside specific commands + .init(label: "swift-java") + } + + var logLevel: JExtractSwiftLib.Logger.Level { get { self.commonOptions.logLevel }