Skip to content

Code Generation

swift4j generates Kotlin/Java proxy classes from your Swift source files. There are two ways to run the generator: as an SPM command plugin (the primary workflow) or directly via the CLI tool.

The generate-java-bridging command plugin ships with swift4j. Run it from your package directory:

Terminal window
swift package plugin generate-java-bridging --product <ProductName>

Replace <ProductName> with the name of the SPM product whose targets you want to export. The plugin processes all targets in the product recursively.

Generated files are written to:

.build/plugins/generate-java-bridging/outputs/<ProductName>/main/java/

The directory structure under main/java/ follows the Java package naming convention, using the target name as the package name (hyphens replaced with underscores):

main/java/
MyLibrary/
GreetingService.kt
Greeting.kt
Counter.kt

If your Swift targets include bundled .java files (such as the base classes shipped with swift4j itself), pass --copy-java-sources to include them in the output:

Terminal window
swift package plugin generate-java-bridging --product MyLibrary --copy-java-sources

For Android projects using @Observable types, pass --generate-android-viewmodels to generate ViewModel and ViewModelFactory subclasses:

Terminal window
swift package plugin generate-java-bridging \
--product MyLibrary \
--generate-android-viewmodels

See Observable for details.

Android (Gradle)

Copy or symlink the generated main/java/ directory into your Android module’s source set. In build.gradle:

android {
sourceSets {
main {
java.srcDirs += [
"path/to/.build/plugins/generate-java-bridging/outputs/MyLibrary/main/java"
]
}
}
}

JVM (Gradle)

sourceSets {
main {
kotlin.srcDirs += [
"path/to/.build/plugins/generate-java-bridging/outputs/MyLibrary/main/java"
]
}
}

The generator defaults to Java 11 compatibility. Pass --java-version to target a different version:

Terminal window
swift package plugin generate-java-bridging --product MyLibrary --java-version 17

Run the plugin again whenever you add, remove, or rename exported Swift types. The output directory is replaced entirely on each run — do not edit the generated files by hand.