Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
9b624db
Add repositories configuration option in swift-java.config
bo2themax Aug 26, 2025
7bf0de7
Add a repositories configuration example and fix artifactUrls output
bo2themax Aug 26, 2025
6a126ec
Update naming convention
bo2themax Aug 26, 2025
ef69b18
Rename descriptionGradleStyle
bo2themax Aug 28, 2025
5a6616b
Add JavaJson Example
bo2themax Aug 28, 2025
9416c56
Change JavaRepositoryDescriptor to enum
bo2themax Aug 28, 2025
149358a
Add JavaRepositoryTests to test dependencies resolving with custom re…
bo2themax Aug 28, 2025
52243ad
Add documentation for swift-java resolve
bo2themax Aug 28, 2025
764d586
Add another non-resolvable config to verify artifactUrls
bo2themax Aug 28, 2025
7f6cd04
Move JavaRepositoryTests to SwiftJavaToolTests
bo2themax Aug 29, 2025
8bb6cfa
Rename JavaJson to OrgAndrejsJson
bo2themax Aug 29, 2025
c57c017
Add referenced issue in the document
bo2themax Aug 29, 2025
ab8f3ab
[Test] Change minified json to pretty printed
bo2themax Aug 29, 2025
f6f9800
Remove System dependency from OrgAndrejsJsonTests
bo2themax Aug 29, 2025
de3dab3
Add more referenced documents for JavaRepositoryDescriptor
bo2themax Aug 29, 2025
f6ad15f
[Test] Add a SimpleJavaProject to JavaRepositoryTests
bo2themax Aug 29, 2025
8e0687b
Merge branch 'swiftlang:main' into main
bo2themax Aug 29, 2025
a61c518
[Test] Update error messages in JavaRepositoryTests.swift
bo2themax Aug 29, 2025
967ccaf
[Test] Add missing license headers
bo2themax Aug 31, 2025
8fe1360
Add JavaResolver in SwiftJavaToolLib to resolve for ResolveCommand
bo2themax Sep 1, 2025
be87290
[Test] Move SwiftJavaToolTests/JavaRepositoryTests
bo2themax Sep 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"classes": {
"org.apache.commons.io.FilenameUtils": "FilenameUtils",
"org.apache.commons.io.IOCase": "IOCase",
"org.apache.commons.csv.CSVFormat": "CSVFormat",
"org.apache.commons.csv.CSVParser": "CSVParser",
"org.apache.commons.csv.CSVRecord": "CSVRecord"
},
"dependencies": [
"org.apache.commons:commons-csv:1.12.0"
],
"repositories": [
{
"type": "maven",
"url": "https://jitpack.io",
"artifactUrls": []
},
{
"type": "maven",
"url": "file:~/.m2/repository"
},
{
"type": "mavenLocal"
},
{
"type": "mavenCentral"
}
]
}
37 changes: 37 additions & 0 deletions Sources/SwiftJavaConfigurationShared/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ public struct Configuration: Codable {

// Java dependencies we need to fetch for this target.
public var dependencies: [JavaDependencyDescriptor]?
// Java repositories for this target when fetching dependencies.
public var repositories: [JavaRepositoryDescriptor]?

public init() {
}
Expand Down Expand Up @@ -133,6 +135,41 @@ public struct JavaDependencyDescriptor: Hashable, Codable {
}
}

/// Descriptor for [repositories](https://docs.gradle.org/current/userguide/supported_repository_types.html#sec:maven-repo)
public struct JavaRepositoryDescriptor: Hashable, Codable {
public enum RepositoryType: String, Codable {
case mavenLocal, mavenCentral
case maven // TODO: ivy .. https://docs.gradle.org/current/userguide/supported_repository_types.html#sec:maven-repo
}

public var type: RepositoryType
public var url: String?
public var artifactUrls: [String]?

public init(type: RepositoryType, url: String? = nil, artifactUrls: [String]? = nil) {
self.type = type
self.url = url
self.artifactUrls = artifactUrls
}

public var descriptionGradleStyle: String? {
switch type {
case .mavenLocal, .mavenCentral:
return "\(type.rawValue)()"
case .maven:
guard let url else {
return nil
}
return """
maven {
url "\(url)"
\((artifactUrls ?? []).map({ "artifactUrls(\"\($0)\")" }).joined(separator: "\n"))
}
"""
}
}
}

public func readConfiguration(sourceDir: String, file: String = #fileID, line: UInt = #line) throws -> Configuration? {
// Workaround since filePath is macOS 13
let sourcePath =
Expand Down
34 changes: 25 additions & 9 deletions Sources/SwiftJavaTool/Commands/ResolveCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,19 @@ extension SwiftJava.ResolveCommand {
return
}

var configuredRepositories: [JavaRepositoryDescriptor] = []

if let repositories = config.repositories {
configuredRepositories += repositories
}

if !configuredRepositories.contains(where: { $0.type == .mavenCentral }) {
// swift-java dependencies are originally located in mavenCentral
configuredRepositories.append(JavaRepositoryDescriptor(type: .mavenCentral))
}

let dependenciesClasspath =
try await resolveDependencies(swiftModule: swiftModule, dependencies: dependenciesToResolve)
try await resolveDependencies(swiftModule: swiftModule, dependencies: dependenciesToResolve, repositories: configuredRepositories)

// FIXME: disentangle the output directory from SwiftJava and then make it a required option in this Command
guard let outputDirectory = self.commonOptions.outputDirectory else {
Expand All @@ -91,20 +102,22 @@ extension SwiftJava.ResolveCommand {


/// Resolves Java dependencies from swift-java.config and returns classpath information.
///
///
/// - Parameters:
/// - swiftModule: module name from --swift-module. e.g.: --swift-module MySwiftModule
/// - dependencies: parsed maven-style dependency descriptors (groupId:artifactId:version)
/// from Sources/MySwiftModule/swift-java.config "dependencies" array.
/// - repositories: repositories used to resolve dependencies
///
/// - Throws:
func resolveDependencies(
swiftModule: String, dependencies: [JavaDependencyDescriptor]
swiftModule: String, dependencies: [JavaDependencyDescriptor],
repositories: [JavaRepositoryDescriptor]
) async throws -> ResolvedDependencyClasspath {
let deps = dependencies.map { $0.descriptionGradleStyle }
print("[debug][swift-java] Resolve and fetch dependencies for: \(deps)")

let dependenciesClasspath = await resolveDependencies(dependencies: dependencies)
let dependenciesClasspath = await resolveDependencies(dependencies: dependencies, repositories: repositories)
let classpathEntries = dependenciesClasspath.split(separator: ":")

print("[info][swift-java] Resolved classpath for \(deps.count) dependencies of '\(swiftModule)', classpath entries: \(classpathEntries.count), ", terminator: "")
Expand All @@ -119,10 +132,11 @@ extension SwiftJava.ResolveCommand {


/// Resolves maven-style dependencies from swift-java.config under temporary project directory.
///
///
/// - Parameter dependencies: maven-style dependencies to resolve
/// - Parameter repositories: repositories used to resolve dependencies
/// - Returns: Colon-separated classpath
func resolveDependencies(dependencies: [JavaDependencyDescriptor]) async -> String {
func resolveDependencies(dependencies: [JavaDependencyDescriptor], repositories: [JavaRepositoryDescriptor]) async -> String {
let workDir = URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
.appendingPathComponent(".build")
let resolverDir = try! createTemporaryDirectory(in: workDir)
Expand All @@ -135,7 +149,7 @@ extension SwiftJava.ResolveCommand {

try! copyGradlew(to: resolverDir)

try! printGradleProject(directory: resolverDir, dependencies: dependencies)
try! printGradleProject(directory: resolverDir, dependencies: dependencies, repositories: repositories)

if #available(macOS 15, *) {
let process = try! await _Subprocess.run(
Expand Down Expand Up @@ -173,14 +187,16 @@ extension SwiftJava.ResolveCommand {
}

/// Creates Gradle project files (build.gradle, settings.gradle.kts) in temporary directory.
func printGradleProject(directory: URL, dependencies: [JavaDependencyDescriptor]) throws {
func printGradleProject(directory: URL, dependencies: [JavaDependencyDescriptor], repositories: [JavaRepositoryDescriptor]) throws {
let buildGradle = directory
.appendingPathComponent("build.gradle", isDirectory: false)

let buildGradleText =
"""
plugins { id 'java-library' }
repositories { mavenCentral() }
repositories {
\(repositories.compactMap(\.descriptionGradleStyle).joined(separator: "\n"))
}

dependencies {
\(dependencies.map({ dep in "implementation(\"\(dep.descriptionGradleStyle)\")" }).joined(separator: ",\n"))
Expand Down