Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ define make_swiftinterface
-emit-module-interface-path ${JEXTRACT_BUILD_DIR}/${$@_MODULE}/${$@_FILENAME}.swiftinterface \
-emit-module-path ${JEXTRACT_BUILD_DIR}/${$@_MODULE}/${$@_FILENAME}.swiftmodule \
-enable-library-evolution \
-Xfrontend -abi-comments-in-module-interface \
-module-name ${$@_MODULE} \
-Xfrontend -abi-comments-in-module-interface \
Sources/${$@_MODULE}/${$@_FILENAME}.swift
echo "Generated: ${JEXTRACT_BUILD_DIR}/${$@_MODULE}/${$@_FILENAME}.swiftinterface"
endef
Expand Down
9 changes: 0 additions & 9 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 4 additions & 21 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ func findJavaHome() -> String {
// picking up env variables during the build process
let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home"
if let home = try? String(contentsOfFile: path) {
if let lastChar = home.last, lastChar.isNewline {
return String(home.dropLast())
}

return home
}

Expand Down Expand Up @@ -97,7 +101,6 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/swiftlang/swift-syntax.git", branch: "main"),
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"),
.package(url: "https://github.com/apple/swift-system", from: "1.0.0"),
],
targets: [
.macro(
Expand Down Expand Up @@ -195,33 +198,13 @@ let package = Package(
]
),

// FIXME: This is swift-foundation's proposed Subprocess; remove when available
// https://github.com/apple/swift-foundation/pull/439
.target(
name: "_Subprocess",
dependencies: [
"_SubprocessCShims",
.product(name: "SystemPackage", package: "swift-system"),
]
),
.target(
name: "_SubprocessCShims",
cSettings: [
.define(
"_CRT_SECURE_NO_WARNINGS",
.when(platforms: [.windows])
)
]
),

.target(
name: "JExtractSwift",
dependencies: [
.product(name: "SwiftBasicFormat", package: "swift-syntax"),
.product(name: "SwiftSyntax", package: "swift-syntax"),
.product(name: "SwiftSyntaxBuilder", package: "swift-syntax"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
"_Subprocess",
"JavaTypes",
]
),
Expand Down
24 changes: 0 additions & 24 deletions Sources/JExtractSwift/Convenience/Collection+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,6 @@
//
//===----------------------------------------------------------------------===//

extension Collection {

@_alwaysEmitIntoClient
public func _mapAsync<T, E>(
_ transform: (Element) async throws(E) -> T
) async throws(E) -> [T] {
let initialCapacity = underestimatedCount
var result = Array<T>()
result.reserveCapacity(initialCapacity)

var iterator = self.makeIterator()

// Add elements up to the initial capacity without checking for regrowth.
for _ in 0..<initialCapacity {
result.append(try await transform(iterator.next()!))
}
// Add remaining elements, if any.
while let element = iterator.next() {
result.append(try await transform(element))
}
return Array(result)
}
}

public extension Dictionary {
/// Same values, corresponding to mapped keys.
func mapKeys<Transformed>(
Expand Down
6 changes: 3 additions & 3 deletions Sources/JExtractSwift/Swift2Java.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import SwiftSyntax
import SwiftSyntaxBuilder

/// Command-line utility, similar to `jextract` to export Swift types to Java.
public struct SwiftToJava: AsyncParsableCommand {
public struct SwiftToJava: ParsableCommand {
public init() {}

public static var _commandName: String {
Expand All @@ -40,7 +40,7 @@ public struct SwiftToJava: AsyncParsableCommand {
@Argument(help: "The Swift interface files to export to Java.")
var swiftInterfaceFiles: [String]

public func run() async throws {
public func run() throws {
let interfaceFiles = self.swiftInterfaceFiles.dropFirst()
print("Interface files: \(interfaceFiles)")

Expand All @@ -55,7 +55,7 @@ public struct SwiftToJava: AsyncParsableCommand {
print("[\(fileNo)/\(interfaceFiles.count)] Importing module '\(swiftModule)', interface file: \(interfaceFile)")
defer { fileNo += 1 }

try await translator.analyze(swiftInterfacePath: interfaceFile)
try translator.analyze(swiftInterfacePath: interfaceFile)
try translator.writeImportedTypesTo(outputDirectory: outputDirectory)

print("[\(fileNo)/\(interfaceFiles.count)] Imported interface file: \(interfaceFile) " + "done.".green)
Expand Down
59 changes: 3 additions & 56 deletions Sources/JExtractSwift/Swift2JavaTranslator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ extension Swift2JavaTranslator {
public func analyze(
swiftInterfacePath: String,
text: String? = nil
) async throws {
) throws {
if text == nil {
precondition(
swiftInterfacePath.hasSuffix(Self.SWIFT_INTERFACE_SUFFIX),
Expand All @@ -84,12 +84,12 @@ extension Swift2JavaTranslator {
log.trace("Analyze: \(swiftInterfacePath)")
let text = try text ?? String(contentsOfFile: swiftInterfacePath)

try await analyzeSwiftInterface(interfaceFilePath: swiftInterfacePath, text: text)
try analyzeSwiftInterface(interfaceFilePath: swiftInterfacePath, text: text)

log.info("Done processing: \(swiftInterfacePath)")
}

package func analyzeSwiftInterface(interfaceFilePath: String, text: String) async throws {
package func analyzeSwiftInterface(interfaceFilePath: String, text: String) throws {
assert(interfaceFilePath.hasSuffix(Self.SWIFT_INTERFACE_SUFFIX))

let sourceFileSyntax = Parser.parse(source: text)
Expand All @@ -104,59 +104,6 @@ extension Swift2JavaTranslator {
translator: self
)
visitor.walk(sourceFileSyntax)

try await self.postProcessImportedDecls()
}

public func postProcessImportedDecls() async throws {
log.info(
"Post process imported decls...",
metadata: [
"types": "\(importedTypes.count)",
"global/funcs": "\(importedGlobalFuncs.count)",
]
)

// FIXME: the use of dylibs to get symbols is a hack we need to remove and replace with interfaces containing mangled names
let dylibPath = ".build/arm64-apple-macosx/debug/lib\(swiftModuleName).dylib"
guard var dylib = SwiftDylib(path: dylibPath) else {
log.warning(
"""
Unable to find mangled names for imported symbols. Dylib not found: \(dylibPath) This method of obtaining symbols is a workaround; it will be removed.
"""
)
return
}

importedGlobalFuncs = try await importedGlobalFuncs._mapAsync { funcDecl in
let funcDecl = try await dylib.fillInMethodMangledName(funcDecl)
log.info("Mapped method '\(funcDecl.identifier)' -> '\(funcDecl.swiftMangledName)'")
return funcDecl
}

importedTypes = Dictionary(uniqueKeysWithValues: try await importedTypes._mapAsync { (tyName, tyDecl) in
var tyDecl = tyDecl
log.info("Mapping type: \(tyDecl.swiftTypeName)")

tyDecl = try await dylib.fillInTypeMangledName(tyDecl)

log.info("Mapping members of: \(tyDecl.swiftTypeName)")
tyDecl.initializers = try await tyDecl.initializers._mapAsync { initDecl in
dylib.log.logLevel = .trace

let initDecl = try await dylib.fillInAllocatingInitMangledName(initDecl)
log.info("Mapped initializer '\(initDecl.identifier)' -> '\(initDecl.swiftMangledName)'")
return initDecl
}

tyDecl.methods = try await tyDecl.methods._mapAsync { funcDecl in
let funcDecl = try await dylib.fillInMethodMangledName(funcDecl)
log.info("Mapped method '\(funcDecl.identifier)' -> '\(funcDecl.swiftMangledName)'")
return funcDecl
}

return (tyName, tyDecl)
})
}
}

Expand Down
Loading