diff --git a/Package.swift b/Package.swift index 706da53f..f6645115 100644 --- a/Package.swift +++ b/Package.swift @@ -188,7 +188,12 @@ let package = Package( .target( name: "JavaKit", - dependencies: ["JavaRuntime", "JavaKitMacros", "JavaTypes"], + dependencies: [ + "JavaRuntime", + "JavaKitMacros", + "JavaTypes", + "JavaKitConfigurationShared", // for Configuration reading at runtime + ], exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), @@ -198,10 +203,8 @@ let package = Package( .unsafeFlags( [ "-L\(javaHome)/lib/server", - "-Xlinker", - "-rpath", - "-Xlinker", - "\(javaHome)/lib/server", + "-Xlinker", "-rpath", + "-Xlinker", "\(javaHome)/lib/server", ], .when(platforms: [.linux, .macOS]) ), diff --git a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift index 16e5f442..51b41264 100644 --- a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift +++ b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift @@ -24,6 +24,7 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { var verbose: Bool = getEnvironmentBool("SWIFT_JAVA_VERBOSE") func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { + log("Create build commands for: \(target.name)") guard let sourceModule = target.sourceModule else { return [] } // Note: Target doesn't have a directoryURL counterpart to directory, @@ -41,6 +42,7 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { /// this target depends on. var dependentConfigFiles: [(String, URL)] = [] func searchForConfigFiles(in target: any Target) { + log("Search for config files in target: \(target.name)") let dependencyURL = URL(filePath: target.directory.string) // Look for a config file within this target. @@ -58,10 +60,13 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { for dependency in target.dependencies { switch dependency { case .target(let target): + log("Dependency target: \(target.name)") searchForConfigFiles(in: target) case .product(let product): + log("Dependency product: \(product.name)") for target in product.targets { + log("Dependency product: \(product.name), target: \(target.name)") searchForConfigFiles(in: target) } @@ -72,6 +77,7 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { // Process indirect target dependencies. for dependency in target.recursiveTargetDependencies { + log("Recursive dependency target: \(dependency.name)") searchForConfigFiles(in: dependency) } @@ -115,7 +121,7 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { while classpath.lastPathComponent != "Java" { classpath.deleteLastPathComponent() } - arguments += [ "--classpath", classpath.path() ] + arguments += ["--classpath", classpath.path()] // For each of the class files, note that it can have Swift-native // implementations. We figure this out based on the path. @@ -131,7 +137,7 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { let className = classNameComponents .reversed() .joined(separator: ".") - arguments += [ "--swift-native-implementation", className] + arguments += ["--swift-native-implementation", className] } } @@ -141,7 +147,6 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { } let executable = try context.tool(named: "Java2Swift").url - log("Prepared build command: \(executable) \(arguments)") return [ .buildCommand( diff --git a/Samples/JavaDependencySampleApp/Package.swift b/Samples/JavaDependencySampleApp/Package.swift index 125aea0a..d8ced924 100644 --- a/Samples/JavaDependencySampleApp/Package.swift +++ b/Samples/JavaDependencySampleApp/Package.swift @@ -84,6 +84,7 @@ let package = Package( name: "JavaCommonsCSV", dependencies: [ .product(name: "JavaKit", package: "swift-java"), + .product(name: "JavaKitFunction", package: "swift-java"), .product(name: "JavaRuntime", package: "swift-java"), ], swiftSettings: [ diff --git a/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/dummy.swift b/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/dummy.swift index 59b16b3a..76f848f9 100644 --- a/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/dummy.swift +++ b/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/dummy.swift @@ -11,4 +11,3 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// - diff --git a/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config b/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config index b6b92d88..7e1f4aeb 100644 --- a/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config +++ b/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config @@ -2,7 +2,7 @@ "classes" : { "org.apache.commons.io.FilenameUtils" : "FilenameUtils" }, - "classpath" : "\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:JavaKit\/build\/classes\/java\/main:..\/..\/JavaKit\/build\/classes\/java\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:JavaKit\/build\/classes\/java\/main:..\/..\/JavaKit\/build\/classes\/java\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:JavaKit\/build\/classes\/java\/main:..\/..\/JavaKit\/build\/classes\/java\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:JavaKit\/build\/classes\/java\/main:..\/..\/JavaKit\/build\/classes\/java\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:JavaKit\/build\/classes\/java\/main:..\/..\/JavaKit\/build\/classes\/java\/main", + "classpath" : "\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:JavaKit\/build\/classes\/java\/main:..\/..\/JavaKit\/build\/classes\/java\/main", "dependencies" : [ "org.apache.commons:commons-csv:1.12.0" ] diff --git a/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift b/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift index 92c580e7..53aef9dc 100644 --- a/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift +++ b/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift @@ -14,9 +14,29 @@ import JavaKit import JavaKitFunction +import JavaKitConfigurationShared +import Foundation + +// Import the commons-csv library wrapper: import JavaCommonsCSV -// Just showcasing that we imported the module -let s: Subscriber? = nil +// Make sure we have the classpath loaded +// TODO: this is more complex than that, need to account for dependencies of our module +let currentDir = FileManager.default.currentDirectoryPath +let configuration = try readConfiguration(sourceDir: "\(currentDir)/Sources/JavaCommonsCSV/") + +// 1) Start a JVM with apropriate classpath +let jvm = try JavaVirtualMachine.shared(classpath: configuration.classpathEntries) + +// 2) Get the FilenameUtils Java class so we can call the static methods on it +let FilenameUtilsClass = try JavaClass() + +// Some silly sample path we want to work with: +let path = "/example/path/executable.exe" +print("Path = \(path)") + +let ext = try! FilenameUtilsClass.getExtension(path) +print("Java FilenameUtils found extension = \(ext)") +precondition(ext == "exe") -print("Done.") \ No newline at end of file +print("Done.") diff --git a/Samples/JavaDependencySampleApp/ci-validate.sh b/Samples/JavaDependencySampleApp/ci-validate.sh index e8a354ae..658960c6 100755 --- a/Samples/JavaDependencySampleApp/ci-validate.sh +++ b/Samples/JavaDependencySampleApp/ci-validate.sh @@ -11,14 +11,16 @@ MODULE_CONFIG_PATH="$MODULE_CONFIG_DIR/swift-java.config" --module-name "$MODULE_NAME" \ --output-directory "$MODULE_CONFIG_DIR" -### 2) extract the config for the fetched dependency -DEP_JAR_CP=$(jq .classpath "$MODULE_CONFIG_PATH") -DEP_JAR_CP=$(echo "$DEP_JAR_CP" | tr -d '"') # trim the "..." -# shellcheck disable=SC2086 -"$JAVASWIFT" --jar $DEP_JAR_CP \ - --module-name "$MODULE_NAME" \ - --existing-config amend -# --java-package-filter com.google.common \ +#### 2) extract the config for the fetched dependency +#DEP_JAR_CP=$(jq .classpath "$MODULE_CONFIG_PATH") +#DEP_JAR_CP=$(echo "$DEP_JAR_CP" | tr -d '"') # trim the "..." +## shellcheck disable=SC2086 +#"$JAVASWIFT" --jar $DEP_JAR_CP \ +# --module-name "$MODULE_NAME" \ +# --java-package-filter org.apache.commons \ +# --existing-config amend + +# for now in CI we just use what we have already generated and comitted in the config ### 3) make wrappers for the module -"$JAVASWIFT" "$MODULE_CONFIG_PATH" --module-name "$MODULE_NAME" +swift run diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 1e85de10..2f9347e6 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -161,7 +161,7 @@ struct JavaToSwift: ParsableCommand { let toolMode: ToolMode if jar { if let moduleBaseDir { - config = try readConfiguration(sourceDir: "file://" + moduleBaseDir.path) + config = try readConfiguration(sourceDir: moduleBaseDir.path) } else { config = Configuration() } @@ -304,7 +304,7 @@ struct JavaToSwift: ParsableCommand { fatalError(message) } - print("[info][swift-java] " + "Done.".green) + print("[info][swift-java] " + "Done: ".green + CommandLine.arguments.joined(separator: " ")) } private func names(from javaClassNameOpt: String) -> (javaClassName: String, swiftName: String) { @@ -380,7 +380,7 @@ extension JavaToSwift { return (false, .init()) case .amend: let configPath = actualOutputDirectory - return (true, try readConfiguration(sourceDir: "file://" + configPath.path)) + return (true, try readConfiguration(sourceDir: configPath.path)) } } } diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift index 3bb34d97..6169c261 100644 --- a/Sources/JavaKitConfigurationShared/Configuration.swift +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -32,6 +32,14 @@ public struct Configuration: Codable { /// The Java class path that should be passed along to the Java2Swift tool. public var classpath: String? = nil + public var classpathEntries: [String] { + guard let classpath else { + return [] + } + + return classpath.split(separator: ":").map(String.init) + } + /// The Java classes that should be translated to Swift. The keys are /// canonical Java class names (e.g., java.util.Vector) and the values are /// the corresponding Swift names (e.g., JavaVector). @@ -86,6 +94,7 @@ public struct JavaDependencyDescriptor: Hashable, Codable { } public func readConfiguration(sourceDir: String, file: String = #fileID, line: UInt = #line) throws -> Configuration { + // Workaround since filePath is macOS 13 let sourcePath = if sourceDir.hasPrefix("file://") { sourceDir } else { "file://" + sourceDir } let configFile = URL(string: sourcePath)!.appendingPathComponent("swift-java.config", isDirectory: false)