Skip to content

Commit cf34a47

Browse files
committed
docc documentation, first step
1 parent 9c0d7eb commit cf34a47

File tree

7 files changed

+289
-0
lines changed

7 files changed

+289
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,4 @@ Package.resolved
4444
*/**/*.o
4545
*/**/*.swiftdeps
4646
*/**/*.swiftdeps~
47+
*/**/.docc-build/

Package.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,15 @@ let package = Package(
198198
.package(url: "https://github.com/ordo-one/package-benchmark", .upToNextMajor(from: "1.4.0")),
199199
],
200200
targets: [
201+
.target(
202+
name: "Documentation",
203+
dependencies: [
204+
"JavaKit",
205+
"SwiftKitSwift",
206+
"SwiftJavaTool",
207+
]
208+
),
209+
201210
.macro(
202211
name: "JavaKitMacros",
203212
dependencies: [
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Swift Java Interoperability
2+
3+
@Metadata {
4+
@TechnologyRoot
5+
}
6+
7+
## Overview
8+
9+
This project contains a number of support packages, java libraries, tools and plugins that provide a complete
10+
Swift and Java interoperability story.
11+
12+
Please refer to articles about the specific direction of interoperability you are interested in.
13+
14+
## Getting started
15+
16+
TODO: Some general intro
17+
18+
If you prefer a video introduction, you may want to this
19+
[Explore Swift and Java interoperability](https://www.youtube.com/watch?v=QSHO-GUGidA)
20+
WWDC 2025 session,
21+
which is a quick overview of all the features and approaches offered by SwiftJava.
22+
23+
## Topics
24+
25+
### Supported Features
26+
27+
- <doc:SupportedFeatures>
28+
29+
30+
### Source generation
31+
32+
- <doc:SwiftJavaCommandLineTool>
33+
- <doc:SwiftPMPlugin>
34+
35+
### Using Java from Swift
36+
37+
- JavaKit
38+
39+
### Using Swift from Java
40+
41+
- SwiftKitSwift
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Supported Features
2+
3+
Summary of features supported by the swift-java interoperability libraries and tools.
4+
5+
## JavaKit Macros
6+
7+
JavaKit supports both directions of interoperability, using Swift macros and source generation
8+
(via the `swift-java wrap-java` command).
9+
10+
### Java -> Swift
11+
12+
It is possible to use JavaKit macros and the `wrap-java` command to simplify implementing
13+
Java `native` functions. JavaKit simplifies the type conversions
14+
15+
> tip: This direction of interoperability is covered in the WWDC2025 session 'Explore Swift and Java interoperability'
16+
> around the [7-minute mark](https://youtu.be/QSHO-GUGidA?si=vUXxphTeO-CHVZ3L&t=448).
17+
18+
| Feature | Macro support |
19+
|--------------------------------------------------|-------------------------|
20+
| Java `static native` method implemented by Swift |`@JavaImplementation` |
21+
| **This list is very work in progress** | |
22+
23+
### Swift -> Java
24+
25+
26+
> tip: This direction of interoperability is covered in the WWDC2025 session 'Explore Swift and Java interoperability'
27+
> around the [10-minute mark](https://youtu.be/QSHO-GUGidA?si=QyYP5-p2FL_BH7aD&t=616).
28+
29+
| Java Feature | Macro support |
30+
|----------------------------------------|---------------|
31+
| Java `class` ||
32+
| Java class inheritance ||
33+
| Java `abstract class` | TODO |
34+
| Java `enum` ||
35+
| Java methods: `static`, member |`@JavaMethod` |
36+
| **This list is very work in progress** | |
37+
38+
39+
## JExtract: Java -> Swift
40+
41+
SwiftJava's `swift-java jextract` tool automates generating Java bindings from Swift sources.
42+
43+
> tip: This direction of interoperability is covered in the WWDC2025 session 'Explore Swift and Java interoperability'
44+
> around the [14-minute mark](https://youtu.be/QSHO-GUGidA?si=b9YUwAWDWFGzhRXN&t=842).
45+
46+
47+
| Swift Feature | FFM | JNI |
48+
|--------------------------------------------------------------------------------------| -------- |-----|
49+
| | | |
50+
| Initializers: `class`, `struct` |||
51+
| Optional Initializers / Throwing Initializers |||
52+
| Deinitializers: `class`, `struct` |||
53+
| `enum`, `actor` |||
54+
| Global Swift `func` |||
55+
| Class/struct member `func` |||
56+
| Throwing functions: `func x() throws` |||
57+
| Typed throws: `func x() throws(E)` |||
58+
| Stored properties: `var`, `let` (with `willSet`, `didSet`) |||
59+
| Computed properties: `var` (incl. `throws`) | ✅ / TODO ||
60+
| Async functions `func async` and properties: `var { get async {} }` |||
61+
| Arrays: `[UInt8]`, `[T]` |||
62+
| Dictionaries: `[String: Int]`, `[K:V]` |||
63+
| Generic functions |||
64+
| `Foundation.Data`, `any Foundation.DataProtocol` |||
65+
| Tuples: `(Int, String)`, `(A, B, C)` |||
66+
| Protocols: `protocol`, existential parameters `any Collection` |||
67+
| Optional types: `Int?`, `AnyObject?` |||
68+
| Primitive types: `Bool`, `Int`, `Int8`, `Int16`, `Int32`, `Int64`, `Float`, `Double` |||
69+
| Unsigned primitive types: `UInt`, `UInt8`, `UInt16`, `UInt32`, `UInt64` |||
70+
| String (with copying data) |||
71+
| Variadic parameters: `T...` |||
72+
| Parametrer packs / Variadic generics |||
73+
| Ownership modifiers: `inout`, `borrowing`, `consuming` |||
74+
| Default parameter values: `func p(name: String = "")` |||
75+
| Operators: `+`, `-`, user defined |||
76+
| Subscripts: `subscript()` |||
77+
| Equatable |||
78+
| Pointers: `UnsafeRawPointer`, UnsafeBufferPointer (?) | 🟡 ||
79+
| Nested types: `struct Hello { struct World {} }` |||
80+
| Inheritance: `class Caplin: Capybara` |||
81+
| Closures: `func callMe(maybe: () -> ())` |||
82+
| Swift type extensions: `extension String { func uppercased() }` | 🟡 | 🟡 |
83+
| Swift macros (maybe) |||
84+
| Result builders |||
85+
| Automatic Reference Counting of class types / lifetime safety |||
86+
| Value semantic types (e.g. struct copying) |||
87+
| Opaque types: `func get() -> some Builder`, func take(worker: some Worker) |||
88+
| Swift concurrency: `func async`, `actor`, `distribued actor` |||
89+
| | | |
90+
| | | |
91+
92+
> tip: The list of features may be incomplete, please file an issue if something is unclear or should be clarified in this table.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# swift-java command line tool
2+
3+
The `swift-java` command line tool offers multiple ways to interact your Java interoperability enabled projects.
4+
5+
## Generating Swift bindings to Java libraries
6+
7+
The `swift-java wrap-java` command.
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# SwiftJava SwiftPM Plugin
2+
3+
The `SwiftJavaPlugin` automates <doc:SwiftJavaCommandLineTool> invocations during the build process.
4+
5+
## Installing the plugin
6+
7+
To install the SwiftPM plugin in your target of choice include the `swift-java` package dependency:
8+
9+
```swift
10+
import Foundation
11+
12+
let javaHome = findJavaHome()
13+
14+
let javaIncludePath = "\(javaHome)/include"
15+
#if os(Linux)
16+
let javaPlatformIncludePath = "\(javaIncludePath)/linux"
17+
#elseif os(macOS)
18+
let javaPlatformIncludePath = "\(javaIncludePath)/darwin"
19+
#elseif os(Windows)
20+
let javaPlatformIncludePath = "\(javaIncludePath)/win32"
21+
#endif
22+
23+
let package = Package(
24+
name: "MyProject",
25+
26+
products: [
27+
.library(
28+
name: "JavaKitExample",
29+
type: .dynamic,
30+
targets: ["JavaKitExample"]
31+
),
32+
],
33+
34+
dependencies: [
35+
.package(url: "https://github.com/apple/swift-java", from: "..."),
36+
],
37+
38+
targets: [
39+
.target(
40+
name: "MyProject",
41+
dependencies: [
42+
// ...
43+
],
44+
swiftSettings: [
45+
.unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"])
46+
],
47+
plugins: [
48+
.plugin(name: "JavaCompilerPlugin", package: "swift-java"),
49+
.plugin(name: "JExtractSwiftPlugin", package: "swift-java"),
50+
.plugin(name: "SwiftJavaPlugin", package: "swift-java"),
51+
]
52+
),
53+
]
54+
)
55+
```
56+
57+
```swift
58+
59+
// Note: the JAVA_HOME environment variable must be set to point to where
60+
// Java is installed, e.g.,
61+
// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home.
62+
func findJavaHome() -> String {
63+
if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] {
64+
print("JAVA_HOME = \(home)")
65+
return home
66+
}
67+
68+
// This is a workaround for envs (some IDEs) which have trouble with
69+
// picking up env variables during the build process
70+
let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home"
71+
if let home = try? String(contentsOfFile: path, encoding: .utf8) {
72+
if let lastChar = home.last, lastChar.isNewline {
73+
return String(home.dropLast())
74+
}
75+
76+
return home
77+
}
78+
79+
if let home = getJavaHomeFromLibexecJavaHome(),
80+
!home.isEmpty {
81+
return home
82+
}
83+
84+
fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.")
85+
}
86+
87+
/// On MacOS we can use the java_home tool as a fallback if we can't find JAVA_HOME environment variable.
88+
func getJavaHomeFromLibexecJavaHome() -> String? {
89+
let task = Process()
90+
task.executableURL = URL(fileURLWithPath: "/usr/libexec/java_home")
91+
92+
// Check if the executable exists before trying to run it
93+
guard FileManager.default.fileExists(atPath: task.executableURL!.path) else {
94+
print("/usr/libexec/java_home does not exist")
95+
return nil
96+
}
97+
98+
let pipe = Pipe()
99+
task.standardOutput = pipe
100+
task.standardError = pipe // Redirect standard error to the same pipe for simplicity
101+
102+
do {
103+
try task.run()
104+
task.waitUntilExit()
105+
106+
let data = pipe.fileHandleForReading.readDataToEndOfFile()
107+
let output = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines)
108+
109+
if task.terminationStatus == 0 {
110+
return output
111+
} else {
112+
print("java_home terminated with status: \(task.terminationStatus)")
113+
// Optionally, log the error output for debugging
114+
if let errorOutput = String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) {
115+
print("Error output: \(errorOutput)")
116+
}
117+
return nil
118+
}
119+
} catch {
120+
print("Error running java_home: \(error)")
121+
return nil
122+
}
123+
}
124+
```

Sources/Documentation/empty.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
// Empty file, this target is a docs-only target.

0 commit comments

Comments
 (0)