Skip to content

Commit c4f6fd2

Browse files
committed
wip towards making jars with dylibs
This allows us to include dylibs in the jar and load them as resources. This allows us to: ``` -> % java --enable-native-access=ALL-UNNAMED -cp ../../SwiftKit/build/classes/java/main:./build/libs/swift-and-java-jar-sample-lib-1.0-SNAPSHOT.jar -Djava.library.path=/usr/lib/swift/ Example.java [swift][MySwiftLibrary/MySwiftLibrary.swift:27](helloWorld()) helloWorld() ``` and we can even include the swiftCore libs in the jar to make it really fat and include all swift dependencies. I think we should maybe make that an option in the inevitable gradle plugin we'll need to do here.
1 parent 867128b commit c4f6fd2

File tree

18 files changed

+1195
-32
lines changed

18 files changed

+1195
-32
lines changed

Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ struct JExtractSwiftBuildToolPlugin: BuildToolPlugin {
2323
// Note: Target doesn't have a directoryURL counterpart to directory,
2424
// so we cannot eliminate this deprecation warning.
2525
let sourceDir = target.directory.string
26+
27+
let t = target.dependencies.first!
28+
switch (t) {
29+
case .target(let t):
30+
t.sourceModule
31+
case .product(let p):
32+
p.sourceModules
33+
@unknown default:
34+
fatalError("Unknown target dependency type: \(t)")
35+
}
2636

2737
let toolURL = try context.tool(named: "JExtractSwiftTool").url
2838
let configuration = try readConfiguration(sourceDir: "\(sourceDir)")
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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 com.example.swift.MySwiftLibrary;
16+
17+
public class Example {
18+
19+
public static void main(String[] args) {
20+
MySwiftLibrary.helloWorld();
21+
}
22+
23+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// swift-tools-version: 6.0
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import CompilerPluginSupport
5+
import PackageDescription
6+
7+
import class Foundation.FileManager
8+
import class Foundation.ProcessInfo
9+
10+
// Note: the JAVA_HOME environment variable must be set to point to where
11+
// Java is installed, e.g.,
12+
// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home.
13+
func findJavaHome() -> String {
14+
if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] {
15+
return home
16+
}
17+
18+
// This is a workaround for envs (some IDEs) which have trouble with
19+
// picking up env variables during the build process
20+
let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home"
21+
if let home = try? String(contentsOfFile: path, encoding: .utf8) {
22+
if let lastChar = home.last, lastChar.isNewline {
23+
return String(home.dropLast())
24+
}
25+
26+
return home
27+
}
28+
29+
fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.")
30+
}
31+
let javaHome = findJavaHome()
32+
33+
let javaIncludePath = "\(javaHome)/include"
34+
#if os(Linux)
35+
let javaPlatformIncludePath = "\(javaIncludePath)/linux"
36+
#elseif os(macOS)
37+
let javaPlatformIncludePath = "\(javaIncludePath)/darwin"
38+
#else
39+
// TODO: Handle windows as well
40+
#error("Currently only macOS and Linux platforms are supported, this may change in the future.")
41+
#endif
42+
43+
let package = Package(
44+
name: "SwiftAndJavaJarSampleLib",
45+
platforms: [
46+
.macOS(.v10_15)
47+
],
48+
products: [
49+
.library(
50+
name: "MySwiftLibrary",
51+
type: .dynamic,
52+
targets: ["MySwiftLibrary"]
53+
),
54+
55+
],
56+
dependencies: [
57+
.package(name: "swift-java", path: "../../"),
58+
],
59+
targets: [
60+
.target(
61+
name: "MySwiftLibrary",
62+
dependencies: [
63+
.product(name: "SwiftKitSwift", package: "swift-java"),
64+
],
65+
exclude: [
66+
"swift-java.config",
67+
],
68+
swiftSettings: [
69+
.swiftLanguageMode(.v5),
70+
.unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"])
71+
],
72+
plugins: [
73+
.plugin(name: "JExtractSwiftPlugin", package: "swift-java"),
74+
]
75+
),
76+
]
77+
)
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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+
// This is a "plain Swift" file containing various types of declarations,
16+
// that is exported to Java by using the `jextract-swift` tool.
17+
//
18+
// No annotations are necessary on the Swift side to perform the export.
19+
20+
#if os(Linux)
21+
import Glibc
22+
#else
23+
import Darwin.C
24+
#endif
25+
26+
public func helloWorld() {
27+
p("\(#function)")
28+
}
29+
30+
public func globalTakeInt(i: Int) {
31+
p("i:\(i)")
32+
}
33+
34+
public func globalTakeIntInt(i: Int, j: Int) {
35+
p("i:\(i), j:\(j)")
36+
}
37+
38+
public func globalCallMeRunnable(run: () -> ()) {
39+
run()
40+
}
41+
42+
public class MySwiftClass {
43+
44+
public var len: Int
45+
public var cap: Int
46+
47+
public init(len: Int, cap: Int) {
48+
self.len = len
49+
self.cap = cap
50+
51+
p("\(MySwiftClass.self).len = \(self.len)")
52+
p("\(MySwiftClass.self).cap = \(self.cap)")
53+
let addr = unsafeBitCast(self, to: UInt64.self)
54+
p("initializer done, self = 0x\(String(addr, radix: 16, uppercase: true))")
55+
}
56+
57+
deinit {
58+
let addr = unsafeBitCast(self, to: UInt64.self)
59+
p("Deinit, self = 0x\(String(addr, radix: 16, uppercase: true))")
60+
}
61+
62+
public var counter: Int32 = 0
63+
64+
public func voidMethod() {
65+
p("")
66+
}
67+
68+
public func takeIntMethod(i: Int) {
69+
p("i:\(i)")
70+
}
71+
72+
public func echoIntMethod(i: Int) -> Int {
73+
p("i:\(i)")
74+
return i
75+
}
76+
77+
public func makeIntMethod() -> Int {
78+
p("make int -> 12")
79+
return 12
80+
}
81+
82+
public func makeRandomIntMethod() -> Int {
83+
return Int.random(in: 1..<256)
84+
}
85+
}
86+
87+
// ==== Internal helpers
88+
89+
private func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) {
90+
print("[swift][\(file):\(line)](\(function)) \(msg)")
91+
fflush(stdout)
92+
}
93+
94+
#if os(Linux)
95+
// FIXME: why do we need this workaround?
96+
@_silgen_name("_objc_autoreleaseReturnValue")
97+
public func _objc_autoreleaseReturnValue(a: Any) {}
98+
99+
@_silgen_name("objc_autoreleaseReturnValue")
100+
public func objc_autoreleaseReturnValue(a: Any) {}
101+
#endif
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"javaPackage": "com.example.swift"
3+
}

0 commit comments

Comments
 (0)