Swift/Java Interop Community Call: November 27th

Hi everyone,

We had a great first kick-off call last week, and we’re going to continue with these periodic Java interop

The primary purpose of these calls is to coordinate work and collaborate on developing Java interoperability (swift-java), including any support tools like gradle or swiftpm plugins etc. If you'd like to contribute in any capacity, please don't hesitate to join.

Event Details

  • When: 2025-11-27T14:00:00Z, click the link to see this time in your timezone.
    • We found the time to work relatively well and span 4 very different timezones, please cooperate with us as we continue with this timeslot. We may choose different times in the future.
    • Where: The meeting will hosted on Webex, make sure to install the app before joining.

Agenda

  • Go over action items from last time
    • swift-java-jni repo
    • how to contribute
    • android examples improvements?
  • Go over topics posted in this thread, so please post your discussion topics ahead of time
  • Additional discussion

While this isn't an official workgroup meeting per se, we'd like to keep it focused on development tasks: how to improve, coordinate, or plan the future development of swift java interoperability. If you have experience, or are interested in gaining experience, developing language interop, this is the place to be! :slight_smile:

See you all soon,
Konrad

7 Likes

Updated the time to use the built-in “time” feature of Discourse

Hi folks. We in the Kotlin team are currently working on a couple of initiatives that might be tangential to the Swift/Java interop work. In particular, I would like to know whether we have any shared angle in the integration with SwiftPM dependencies.

Our Kotlin/Native backend can interoperate with Objective-C and C APIs, and we are building a feature that will streamline the consumption of SwiftPM dependencies with Objective-C APIs in Gradle (our primary build system) by setting up all the necessary bridging under the hood.

There are 2 main components that we need to be able to import SwiftPM dependencies:

  • Arguments that we will use to initialize the libclang parsing machinery that the Kotlin/Native backend uses to be able to import said APIs

  • Arguments that we will pass to ld to be able to produce executables and dylibs from the Kotlin/Native backend and search paths for dyld

From my understanding, SwiftPM doesn’t have a direct way to expose this information, and this is also complicated a bit by the fact that SwiftPM supports at least 2 build systems: swift build and xcodebuild, likely with variations I am not fully knowledgeable about. At this moment, we have built our integration through roughly the following mechanics:

  • During the Gradle build, we generate a Package.swift file with the dependencies the user specified in their Gradle build script, and declare a fake Objective-C target in this package.

  • Then we run xcodebuild on this package with CC and LD overrides, capture the arguments passed to these calls and forward them to the Kotlin/Native backend.

This works, but I wonder if there is a better/more resilient way SwiftPM could expose this information to another build system. In addition, this model currently introduces a performance issue for us: we want the libclang part to be as fast as possible because it runs as a part of the IDE import pipeline, so what we ideally want from SwiftPM and the build system is to give us all the modulemaps, headers, -Swift.h generated headers, unwrapped XCFrameworks, but skip all the non relevant steps, such as machine code generation, resources processing, etc.

I wonder if the Swift/Java interop has some similar requirements? I see that the swift-java tool already provides automated import of Swift code into Java; are there plans to extend it to transparently import SwiftPM dependencies in Gradle?

1 Like

This sounds like a great topic to discuss in the call, we’d love contributions in this area! I don’t think swift-java would go through any objc parts, however the general ability to pull a Swift dependency does feel in-line in what we’d like to support. It’s early days and we’ve not worked on this yet – so any help on building out a gradle plugin like this would be very welcome.

We can also work with SwiftPM team to figure out requirements and see if we can make these things easier – @dschaefer2 has some ideas in the general build systems integrations space, perhaps he’ll join us too in this call :slight_smile:

1 Like

During today's call, we discussed using a Gradle plugin to improve the build logic. I mentioned convention plugins, and Gradle has documentation and a sample for setting this up. We also discussed best practices for writing build logic, and Gradle has some documentation on this.

We also briefly discussed publishing a Gradle plugin that could be applied to any Gradle project. I believe the best documentation entry point on this is here, but Gradle plugins don’t necessarily need to be published to the Gradle Plugin Portal.

I think there was a call to action to help with the build scripts. I see the swift-java already has some setup with the convention plugins. Is there some specific place where it would be beneficial to help with the build logic, or are you looking for a general overview of the existing build scripts? I could offer a PR showcasing how the kts build scripts compare to the existing Groovy setup.

I am also curious about what everyone has in mind for the features/requirements of the swift-java Gradle plugin mentioned during the call.

1 Like

Thanks for the links, I’m aware of these. I was wondering if you had recently worked on some plugin and could share recommended approaches; later I realized we probably should kick off our efforts on top of the existing Swift gradle plugin though :thinking:

The swift-java build and the convention plugins I’m not as much concerned about. Sure, the swift-java build could be cleaned up some more, but that’s not really important – what is important is to make using swift-java easier for developers in their Gradle builds.


The goal here is to offer a “Swift” (or “swift java interop”) plugin for Gradle. We can do this either by building our own, or improving existing ones.

You’ll notice that the Samples including the recent swift-java android sample, have an annoying amount of copy-paste in order to orchestrate invoking the swift build, swift-java tool, and then locate the built dynamic libraries and package them up.

Here’s some rough ideas what such SwiftJava Gradle plugin should be:

Maybe? Invoke swift-java to perform extraction steps:

  • Today we’re relying on swift build triggering swift-java jextract
    • The gradle plugin doesn’t really invoke swift-java, but just does swift-build and we happen to know the Swift project has the swift-java plugin which then triggers jextract.
    • I wonder if it would be beneficial to have the gradle plugin be able to invoke jextract directly?

Building Swift:

  • The plugin “building” a Swift project as part of your gradle build
    • This is for projects which develop swift side by side java, it should be possible to point the plugin at a Package.swift and build either some specific targets, or the whole thing
    • The building remains TBD how much we need to do here… just doing swift build is pretty naive, I’d hope we can do better than that.
  • Preferably, we should take the existing plugin SwiftCompile - Gradle DSL Version 9.2.1 and investigate what’s missing and how we can improve it. I’m told it is not very actively maintained, but perhaps I’m wrong?
    • Then if we can improve and upstream it that would probably be the best, we may need to iterate in a fork for a while to see what we want.
  • We should offer control over building in debug and release modes, and passing flags
    • The existing official plugin has some of that already

SwiftJava tool integrations:

  • I’m not sure if the Gradle plugin should directly invoke swift-java jextract or we leave it to SwiftPM plugins to drive; we should investigate that.
  • Either way, swift-java jextract produces Java sources as outputs; we should make it easy to include those sources in sourceSets of your Gradle build.

Testing

  • Do we want to offer a testSwift task which invokes swift tests of targets the gradle project has included?
    • The existing gradle plugin does so

Improved “depend on Swift library” (maybe?)

  • [future] potentially allow declaring a swift project dependency (this is something you were interested in AFAIK); where we’d declare a package dependency in the gradle build and we’d a) fetch and b) build the dependency as part of the gradle build
    • E.g. if such dependency was already swift-java enabled, via the swift-java SwiftPM plugin, and produced shared libraries, you could then make use
  • Maybe? One might argue to also support “just stuff some Swift sources into src/main/swift but I’m not sure this is great, we’d have to reinvent a Package.swift somewhere anyway… It may be simpler to just keep a “real swift project” side by side.

Support packaging jars (and apks if android specific):

  • Some use cases want to make a “fat” jar with the built shared libraries included in them. This is not trivial for developers not familiar with Swift, because e.g. you need to cross build. When building on macOS you’d want to build for Linux as well (arm, x64 etc), and then allow developers in the gradle plugin to put those together;

So it’s mostly around orchestrating building and packaging Swift libraries into your jars/apks.

I’d welcome any additional opinions and ideas here, cc @android-workgroup, @madsodgaard.


There exists the Building Swift projects Gradle plugin that was developed a few ages ago, however I was told it’s not been very actively maintained.

Most likely it would be best to see if we can improve that plugin, and upstream any changes we might need eventually to the official plugin.

cc @dschaefer2 this plugin should be interesting to your investigations.


@beaumont I think I captured your use case with those points, but if there’s something you’d like to add please do. I think the biggest annoyance for you was building and finding all the shared libraries for other platforms and then producing the far jar, right?

1 Like

Another piece for inspiration for the Gradle plugin: Swift Android Gradle Plugin: Build Swift Libraries for Android We could reach out to Charles if he’d be interested in working together on the plugin.

Meeting notes

Swift Java Community Call Notes: 2

Actions from last time

  • ACTION: swift-java-jni repository or not discussions
  • ACTION: Konrad to wtite up some architectural hints to help "how to contribite"
  • ACTION: Konrad, make an issue about the linking discussion
  • ACTION: Greg, some quick update to the android example how to add dependencies
    • Did push those

Present

  • Konrad - Swift team
  • Doug - Swift package manager
  • Finagolfin - Android workgroup, help on CI on Android
  • Tracy - Swift VSCode plugin
  • Mahdi - Server Side Swift, nothing in Swift Java yet; maybe for an Android app at work?
  • Thomas - Swift fan, some upcoming Swift projects in their iOS and wants a common core in Swift, Windows using KMP
  • Mads - frameo.com, jextract-jni
  • Bartłomiej - iOS developer, recently contributing a bunch
  • Gregorio - IBM, and interested in contributing, Android focus but also some Server systems may use Swift
  • Artem - JetBrains, KMP main work, main area is Kotlin Native
  • Gleb - JetBrains, works on KMP with Swift
  • Sergey - JetBrains, KMP team, worked on Swift Export
  • Timofey, JetBrains, on Gradle build tooling for KMP
  • Elliah - JetBrains

Agenda

Gradle plugin discussions

  • Timofey: Topic about simplifying pulling swift dependencies into Gradle projects
    • Gradle integration... Kotlin native backend has ability to import objective C APIs
    • want to enable easily consuming Swift APIs "through headers or @objc", to make this for KMP codebases...
    • Challenge: no resilient way to get parameters swifptm would pass to clang compiler etc.
    • Looking to streamline this;
  • Konrad: explained how swift-java works on just sources; there's no headers involved
  • Timofey: can we handle xcframeworks at all, when we don't have the sources.
    • Konrad: we can handle .swiftinterface as inputs, so a closed source codebase could be "wrapped" for Java this way
  • Doug: Thinking about the future, how would we get precompiled shared objects, the Gradle plugin would need to get hold of libraries we need to find etc...
  • Timofey: Swift package dump gives structured info but there may be guessing involved...
  • Doug: Binary targets should show up in graph, in theory at least
  • Timofey: Finding exact names and locations might be difficult still though
  • Doug: integrating cmake and ninja have good tooling to spit out metadata... We're open to find more ways to integrate
  • :a: Timofey: Prepare a list of requests and questions, preferably as issues in SwiftPM github or via forums.

Swift-syntax prebuilts issues

Konrad/Doug: swift-syntax prebuilts issue swift-java fails to link with prebuilts enabled · Issue #9331 · swiftlang/swift-package-manager · GitHub

  • Doug: The issue is that prebuilts were focused on macros; but now we have libraries and source generators etc.
    • Trying to fix in 6.3, so we have prebuilts for all host platforms... this should cover generators
    • Doug: The issue seems to be swift-test links both the prebuilt lib AND the source compiled
      • Then gold panics since we've double linked the symbols;
    • :a: Doug: Doug's working on fixing this.

Swift-java hitting sandbox issues inside plugins, even with disabled sandbox

  • Mads: Explained the sandbox issue again; it is blocking the completion of the callbacks feature in jextract jni
    • The issue is in CI; works locally on Mads machine
    • Konrad: Can reproduce this reliably, it seems to be on "first run" kind of thing. Likely a bug in flag handling in swiftpm perhaps?
    • :a: Konrad: Investigate and report findings to SwiftPM team, maybe offer a fix.

Gradle plugin continued

  • Gradle plugins:
    • :a: Konrad, No specific requirements, I can come up with a list.
    • Convenience plugins is unrelated, this is about a published plugins for Developers to build mixed swift and java apps.
    • :a: Timofey: post best practice for plugins, maybe we can collaborate on the plugin?

swift-java and "direct" kotlin support

Improved ergonomics from jextract e.g. enums etc

  • Konrad, Bartek: Should we have a way to emit Kotlin sources directly instead of Java?
    • Bartek: Was thinking about it
    • Konrad: Doesn't seem like there's much pressure to push on this yet; Kotlin can "just" call thorugh the Java bindings we're emitting

No action.

Kotlin native and Swift

  • Artem: somewhere in this ballpark, thinking about a mode to jextract, change codegen into the KMP C-interop...

    • To allow exporting Swift to export into Kotlin native

    • Wondering what we're willing to accept

    • Artem: JetBrains, we know a lot of people want Swift to Kotlin Native interop

    • Bartek: Most leaders for mobile are into Swift on Android, potential to collab with kotlin native; Unlikely to get contributions from those mobile teams "if it was there, we'd use it"

      • This would be for iOS side; allow KMP users to use Swift libraries.
      • KMP does the same. Could take swift-java walker and expose new KN via c-interop.
    • Konrad: To be clear, this is specifically benefitting only the c-interop direction which is about Kotlin native calling Swift code on e.g. iOS etc.

    • Konrad: Overall the analysis and thunks, lowering, that is all common infra. It would be possible to have a new --mode just like the ffm or jni ones for the c-interop-kotlin basically.

    • :a: Artem: prototype what could be done here and how it would look like. This would be another --mode that would be

  • Elliah: It would be nice to import some SPM plugin and don't care how we're going to interop etc. On receiving side it'd be the same.

Hi folks. I was thinking about what the benefit of NOT driving jextract from swift build might be. I think the most significant benefit would probably be that once the swift-java interop is mature enough, an arbitrary Java consumer might want to consume a Swift dependency, and it would be a hurdle if the producer of the library had to apply build plugins for the library to become accessible to Java.

I wanted to see how difficult it would be to jextract an arbitrary SwiftPM dependency, so I translated pieces of our SwiftPM import prototype into a Gradle plugin in the Swift Java repository and adapted it to do jextract instead of Kotlin’s cinterop. I pushed it as a PR in the swift-java repository just as a showcase - PoC SwiftPM import for Swift Java by abdulowork · Pull Request #486 · swiftlang/swift-java · GitHub.

I see that jextract machinery currently operates on Swift sources through swift-syntax and doesn’t perform any type checking, so it doesn't depend on .swiftmodules and .swiftinterfaces as our Objective-C import machinery does. In that case, using SWIFT_EXEC override feels contrived, but I kept it since jextract emits Swift bridges as sources that still need to be compiled, and it makes sense to infer compiler arguments from the compilation of the original sources to compile the bridges. I guess the other option would be to recompile original sources with the Swift bridges.

The linkage model in swift-java is different compared to what we have in Kotlin/Native, and swift-java assumes every Swift module will be in its own image, so I used a SwiftPM hack where you add all dependencies in 2 dynamic products, which forces all transitive products to promote to dynamic libraries as well. The LD dump was anyway useful to link the bridges and to pass library paths to java.library.path and do some DYLD_ env hacks.

Because all of our work on SwiftPM import was based on xcodebuild, this prototype also uses xcodebuild, and thus it only works on macOS.

I wanted to try out some flashy examples of external SwiftPM dependencies, but swift-java produces uncompilable Java and Swift sources, especially around functions like ==, overloads, and anything that touches generics. I managed to fix the Java bridge compilations, but the Swift compilations were too difficult, and I rolled back all these changes. In the end, I settled for a simple randomSample wrapper function from the Algorithms.

What do you think about a use case of applying jextract from an outside Gradle plugin? I am also curious what you think about the SWIFT_EXEC and the LD as ways to introspect the build system.

2 Likes

That’s fantastic, thanks for taking a stab at it! :partying_face: I’ll give the PR a proper review as well, from skimming it it looks like a really great start, thanks for doing this.

Do we think this is reliable, or would we perhaps need a mode to force SwiftPM into “everything as dynamic please”. I think we discussed this at some point in the past that it may be beneficial… WDYT @dschaefer2?

Gotcha, let’s see if we have everything we need in SwiftPM to be able to use that instead so it’d handle all platforms. @dschaefer2 would you be able to have a look at the build pieces in the plugin please?

There may still be limitations in what the tool handles, we can tackle those one by one. What

That’s definitely useful, being able to consume an arbitrary Swift package without having to modify it in any way is absolutely something I can see people wanting to do. Without driving the swift-java tool directly like this we would probably come up with some workarounds by having a “fake small swiftpm project” driving the plugin but I think the Gradle driving the plugin directly approach is much cleaner. So this does sound like a good goal to have for sure.

I’ll give the other questions and PR a deeper look and will follow up here or on the PR, thank you!

Do we think this is reliable, or would we perhaps need a mode to force SwiftPM into “everything as dynamic please”.

I feel it could also be a meaningful feature to let the jextract caller decide where the pieces of the Swift Java runtime will be, including the Swift bridges and the SwiftRuntimeFunctions. Ideally, SwiftPM and xcodebuild would have a standard way to say: here are the linked images I will produce, and the following will be the mapping between SwiftPM targets and the resulting images - then producing the right System.loadLibrary(...) calls would be kind of trivial.

The only ways I know to infer this information from SwiftPM are xcodebuild -dumpPIF (and maybe swift package dump-pif?) and a shim like LD where you can try to make sense of the underlying ld call. I will file an issue for this feature in the SwiftPM repo, and I think it could be valuable for Kotlin/Native and Swift Java.

1 Like