Skip to content

Commit 615c671

Browse files
committed
Merge branch 'main' into jni-optional
2 parents 56a9096 + ac30ee4 commit 615c671

File tree

77 files changed

+2583
-478
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+2583
-478
lines changed

.github/actions/prepare_env/action.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ runs:
1010
distribution: ${{ matrix.jdk_vendor }}
1111
java-version: |
1212
24
13-
21
1413
17
1514
cache: 'gradle'
1615
- name: Set JAVA_HOME_{N}

.unacceptablelanguageignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ Sources/_Subprocess/Platforms/Subprocess+Darwin.swift
33
Sources/_Subprocess/Platforms/Subprocess+Linux.swift
44
Sources/_Subprocess/Platforms/Subprocess+Unix.swift
55
Sources/_Subprocess/Teardown.swift
6-
Sources/_Subprocess/Subprocess.swift
6+
Sources/_Subprocess/Subprocess.swift
7+
NOTICE.txt

Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ let package = Package(
422422
name: "JExtractSwiftLib",
423423
dependencies: [
424424
.product(name: "SwiftBasicFormat", package: "swift-syntax"),
425+
.product(name: "SwiftLexicalLookup", package: "swift-syntax"),
425426
.product(name: "SwiftSyntax", package: "swift-syntax"),
426427
.product(name: "SwiftSyntaxBuilder", package: "swift-syntax"),
427428
.product(name: "ArgumentParser", package: "swift-argument-parser"),

README.md

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,65 @@ Required language/runtime versions:
6262

6363
This project contains multiple builds, living side by side together.
6464

65-
Depending on which part you are developing, you may want to run just the swift tests:
65+
You will need to have:
66+
- Swift (6.1.x+)
67+
- Java (24+ for FFM, even though we support lower JDK targets)
68+
- Gradle (installed by "Gradle wrapper" automatically when you run gradle through `./gradlew`)
69+
70+
### Preparing your environment
71+
72+
Install **Swift**, the easiest way to do this is to use **Swiftly**: [swift.org/install/](https://www.swift.org/install/).
73+
This should automatically install a recent Swift, but you can always make sure by running:
74+
75+
```bash
76+
swiftly install 6.1.2 --use
77+
```
78+
79+
Install a recent enough Java distribution. We validate this project using Corretto so you can choose to use that as well,
80+
however any recent enough Java distribution should work correctly. You can use sdkman to install Java:
81+
82+
```bash
83+
# Install sdkman from: https://sdkman.io
84+
curl -s "https://get.sdkman.io" | bash
85+
sdk install java 17.0.15-amzn
86+
sdk install java 24.0.1-amzn
87+
88+
sdk use java 24.0.1-amzn
89+
```
90+
91+
The use of JDK 24 is required to build the project, even though the libraries being published may target lower Java versions.
92+
93+
❗️ Please make sure to `export JAVA_HOME` such that swift-java can find the necessary java libraries!
94+
When using sdkman the easiest way to export JAVA_HOME is to export the "current" used JDK's home, like this:
95+
96+
```bash
97+
export JAVA_HOME="$(sdk home java current)
98+
```
99+
100+
### Testing your changes
101+
102+
Many tests, including source generation tests, are written in Swift and you can execute them all by running the
103+
swift package manager test command:
66104
67105
```bash
68106
> swift test
69107
```
70108
71-
or the Java tests through the Gradle build. The Gradle build may also trigger some Swift compilation because of
72-
interlinked dependencies of the two parts of Swift-Java. To run the Java build and tests use the Gradle wrapper script:
109+
When adding tests in `Tests/...` targets, you can run these tests (or filter a specific test using `swift test --filter type-or-method-name`).
110+
111+
Some tests are implemented in Java and therefore need to be executed using Gradle.
112+
Please always use the gradle wrapper (`./gradlew`) to make sure to use the appropriate Gradle version
73113
74114
```bash
75115
> ./gradlew test
76116
```
77117
78-
Currently it is suggested to use Swift 6.0 and a Java 24+.
118+
> Tip: A lot of the **runtime tests** for code relying on `jextract` are **located in sample apps**,
119+
> so if you need to runtime test any code relying on source generation steps of jextract, consider adding the tests
120+
> to an appropriate Sample. These tests are also executed in CI (which you can check in the `ci-validate.sh` script
121+
> contained in every sample repository).
79122
80-
### Sample Apps
123+
### Sample apps & tests
81124
82125
Sample apps are located in the `Samples/` directory, and they showcase full "roundtrip" usage of the library and/or tools.
83126
@@ -101,19 +144,27 @@ To run a simple example app showcasing the jextract (Java calling Swift) approac
101144
This will also generate the necessary sources (by invoking jextract, extracting the `Sources/ExampleSwiftLibrary`)
102145
and generating Java sources in `src/generated/java`.
103146
147+
#### Other sample apps
148+
149+
Please refer to the [Samples](Samples) directory for more sample apps which showcase the various usage modes of swift-java.
150+
104151
## Benchmarks
105152
106153
You can run Swift [ordo-one/package-benchmark](https://github.com/ordo-one/package-benchmark) and OpenJDK [JMH](https://github.com/openjdk/jmh) benchmarks in this project.
107154
108155
Swift benchmarks are located under `Benchmarks/` and JMH benchmarks are currently part of the SwiftKit sample project: `Samples/SwiftKitSampleApp/src/jmh` because they depend on generated sources from the sample.
109156
157+
### Swift benchmarks
158+
110159
To run **Swift benchmarks** you can:
111160
112161
```bash
113162
cd Benchmarks
114163
swift package benchmark
115164
```
116165
166+
### Java benchmarks
167+
117168
In order to run JMH benchmarks you can:
118169
119170
```bash
@@ -125,4 +176,20 @@ Please read documentation of both performance testing tools and understand that
125176
126177
## User Guide
127178
128-
More details about the project and how it can be used are available in [USER_GUIDE.md](USER_GUIDE.md)
179+
More details about the project can be found in [docc](https://www.swift.org/documentation/docc/) documentation.
180+
181+
To view the rendered docc documentation you can use the docc preview command:
182+
183+
```bash
184+
xcrun docc preview Sources/SwiftJavaDocumentation/Documentation.docc
185+
186+
# OR JavaKit to view JavaKit documentation:
187+
# xcrun docc preview Sources/JavaKit/Documentation.docc
188+
189+
# ========================================
190+
# Starting Local Preview Server
191+
# Address: http://localhost:8080/documentation/documentation
192+
# ========================================
193+
# Monitoring /Users/ktoso/code/swift-java/Sources/SwiftJavaDocumentation/Documentation.docc for changes...
194+
195+
```

Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ public func globalTakeIntInt(i: Int64, j: Int64) {
4545
p("i:\(i), j:\(j)")
4646
}
4747

48+
public func echoUnsignedInt(i: UInt32, j: UInt64) -> UInt64 {
49+
p("i:\(i), j:\(j)")
50+
return UInt64(i) + j
51+
}
52+
4853
// ==== Internal helpers
4954

5055
func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) {

Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,11 @@ void globalVariable() {
6161
MySwiftLibrary.setGlobalVariable(100);
6262
assertEquals(100, MySwiftLibrary.getGlobalVariable());
6363
}
64+
65+
@Test
66+
void globalUnsignedIntEcho() {
67+
int i = 12;
68+
long l = 1200;
69+
assertEquals(1212, MySwiftLibrary.echoUnsignedInt(12, 1200));
70+
}
6471
}

Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,16 @@ public class MySwiftClass {
6060
public func makeRandomIntMethod() -> Int {
6161
return Int.random(in: 1..<256)
6262
}
63+
64+
public func takeUnsignedChar(arg: UInt16) {
65+
p("\(UInt32.self) = \(arg)")
66+
}
67+
68+
public func takeUnsignedInt(arg: UInt32) {
69+
p("\(UInt32.self) = \(arg)")
70+
}
71+
72+
public func takeUnsignedLong(arg: UInt64) {
73+
p("\(UInt64.self) = \(arg)")
74+
}
6375
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2025 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+
package com.example.swift;
16+
17+
import org.junit.jupiter.api.Test;
18+
import org.swift.swiftkit.ffm.AllocatingSwiftArena;
19+
20+
public class UnsignedNumbersTest {
21+
@Test
22+
void take_uint32() {
23+
try (var arena = AllocatingSwiftArena.ofConfined()) {
24+
var c = MySwiftClass.init(1, 2, arena);
25+
c.takeUnsignedInt(128);
26+
}
27+
}
28+
29+
@Test
30+
void take_uint64() {
31+
try (var arena = AllocatingSwiftArena.ofConfined()) {
32+
var c = MySwiftClass.init(1, 2, arena);
33+
c.takeUnsignedLong(Long.MAX_VALUE);
34+
}
35+
}
36+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2025 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+
import JavaTypes
16+
import JavaKitConfigurationShared
17+
18+
/// Determine if the given type needs any extra annotations that should be included
19+
/// in Java sources when the corresponding Java type is rendered.
20+
func getTypeAnnotations(swiftType: SwiftType, config: Configuration) -> [JavaAnnotation] {
21+
if swiftType.isUnsignedInteger, config.effectiveUnsignedNumbersMode == .annotate {
22+
return [JavaAnnotation.unsigned]
23+
}
24+
25+
return []
26+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
import JavaKitConfigurationShared // TODO: this should become SwiftJavaConfigurationShared
16+
import JavaTypes // TODO: this should become SwiftJavaConfigurationShared
17+
18+
extension Configuration {
19+
public var effectiveUnsignedNumericsMode: UnsignedNumericsMode {
20+
switch effectiveUnsignedNumbersMode {
21+
case .annotate: .ignoreSign
22+
case .wrapGuava: .wrapUnsignedGuava
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)