From ae18c34675cd499c435e6134620e1ae95a47db81 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 7 Apr 2026 07:43:00 +0900 Subject: [PATCH] =?UTF-8?q?Revert=20"jextract:=20Evaluate=20IfConfigDecl?= =?UTF-8?q?=20and=20add=20--static-build-config=20option=20=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e0f3745ad5072e832555f7c3eb24042f5d439fea. --- Package.swift | 24 +-- .../JExtractSwiftPlugin.swift | 9 +- .../_StaticBuildConfigPlugin.swift | 33 ---- .../Convenience/SwiftSyntax+Extensions.swift | 4 +- .../JExtractDefaultBuildConfiguration.swift | 99 ---------- Sources/JExtractSwiftLib/Swift2Java.swift | 1 + .../Swift2JavaTranslator.swift | 18 -- .../JExtractSwiftLib/Swift2JavaVisitor.swift | 28 +-- .../SwiftParsedModuleSymbolTableBuilder.swift | 51 +---- .../SwiftTypes/SwiftSymbolTable.swift | 4 - .../StaticBuildConfigPluginExecutable.swift | 70 ------- .../Configuration.swift | 4 - .../Documentation.docc/SupportedFeatures.md | 37 ---- .../Commands/JExtractCommand.swift | 7 - .../Asserts/TextAssertions.swift | 12 +- Tests/JExtractSwiftTests/IfConfigTests.swift | 177 ------------------ 16 files changed, 18 insertions(+), 560 deletions(-) delete mode 100644 Plugins/_StaticBuildConfigPlugin/_StaticBuildConfigPlugin.swift delete mode 100644 Sources/JExtractSwiftLib/JExtractDefaultBuildConfiguration.swift delete mode 100644 Sources/StaticBuildConfigPluginExecutable/StaticBuildConfigPluginExecutable.swift delete mode 100644 Tests/JExtractSwiftTests/IfConfigTests.swift diff --git a/Package.swift b/Package.swift index 73ac97446..ce340154a 100644 --- a/Package.swift +++ b/Package.swift @@ -118,12 +118,12 @@ let package = Package( ], dependencies: [ swiftJavaJNICoreDep, - .package(url: "https://github.com/swiftlang/swift-syntax", from: "603.0.0"), + .package(url: "https://github.com/swiftlang/swift-syntax", from: "602.0.0"), .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), .package(url: "https://github.com/apple/swift-system", from: "1.4.0"), .package(url: "https://github.com/apple/swift-log", from: "1.2.0"), .package(url: "https://github.com/apple/swift-collections", .upToNextMinor(from: "1.3.0")), // primarily for ordered collections - .package(url: "https://github.com/swiftlang/swift-subprocess.git", from: "0.4.0", traits: ["SubprocessFoundation"]), + .package(url: "https://github.com/swiftlang/swift-subprocess.git", from: "0.2.1", traits: ["SubprocessFoundation"]), // Benchmarking .package(url: "https://github.com/ordo-one/package-benchmark", .upToNextMajor(from: "1.4.0")), @@ -320,7 +320,6 @@ let package = Package( dependencies: [ .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftLexicalLookup", package: "swift-syntax"), - .product(name: "SwiftIfConfig", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), .product(name: "ArgumentParser", package: "swift-argument-parser"), @@ -332,25 +331,6 @@ let package = Package( ], swiftSettings: [ .swiftLanguageMode(.v5) - ], - plugins: [ - .plugin(name: "_StaticBuildConfigPlugin") - ] - ), - - .executableTarget( - name: "StaticBuildConfigPluginExecutable", - dependencies: [ - .product(name: "Subprocess", package: "swift-subprocess"), - .product(name: "SwiftIfConfig", package: "swift-syntax"), - ] - ), - - .plugin( - name: "_StaticBuildConfigPlugin", - capability: .buildTool(), - dependencies: [ - "StaticBuildConfigPluginExecutable" ] ), diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index dd5d2f2b7..9c2f48a5c 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -46,7 +46,7 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { // The name of the configuration file SwiftJava.config from the target for // which we are generating Swift wrappers for Java classes. let configFile = sourceDir.appending(path: "swift-java.config") - let configuration = try readConfiguration(configPath: configFile) + let configuration = try readConfiguration(sourceDir: sourceDir) // We use the the usual maven-style structure of "src/[generated|main|test]/java/..." // that is common in JVM ecosystem @@ -71,13 +71,6 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { // We'll have to make up some caching inside the tool so we don't re-parse files which have not changed etc. ] - if let staticBuildConfig = configuration?.staticBuildConfigurationFile { - guard let resolvedURL = URL(string: staticBuildConfig, relativeTo: configFile) else { - fatalError("Could not resolve 'staticBuildConfigurationFile' url: \(staticBuildConfig)") - } - arguments += ["--static-build-config", resolvedURL.absoluteURL.path(percentEncoded: false)] - } - let dependentConfigFilesArguments = dependentConfigFiles.flatMap { moduleAndConfigFile in let (moduleName, configFile) = moduleAndConfigFile return [ diff --git a/Plugins/_StaticBuildConfigPlugin/_StaticBuildConfigPlugin.swift b/Plugins/_StaticBuildConfigPlugin/_StaticBuildConfigPlugin.swift deleted file mode 100644 index 4816f59c6..000000000 --- a/Plugins/_StaticBuildConfigPlugin/_StaticBuildConfigPlugin.swift +++ /dev/null @@ -1,33 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2026 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation -import PackagePlugin - -@main -struct _StaticBuildConfigPlugin: BuildToolPlugin { - func createBuildCommands(context: PluginContext, target: any Target) async throws -> [Command] { - let outSwift = context.pluginWorkDirectoryURL.appending(path: "StaticBuildConfiguration+embedded.swift") - return [ - .buildCommand( - displayName: "Run -print-static-build-config", - executable: try context.tool(named: "StaticBuildConfigPluginExecutable").url, - arguments: [outSwift.absoluteURL.path(percentEncoded: false)], - environment: [:], - inputFiles: [], - outputFiles: [outSwift.absoluteURL] - ) - ] - } -} diff --git a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift index 4b05971ec..86ed42115 100644 --- a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift @@ -229,10 +229,8 @@ extension DeclSyntaxProtocol { } else { "var" } - case .unexpectedCodeDecl(let node): - node.trimmedDescription case .usingDecl(let node): - node.trimmedDescription + node.nameForDebug } } diff --git a/Sources/JExtractSwiftLib/JExtractDefaultBuildConfiguration.swift b/Sources/JExtractSwiftLib/JExtractDefaultBuildConfiguration.swift deleted file mode 100644 index cdca43554..000000000 --- a/Sources/JExtractSwiftLib/JExtractDefaultBuildConfiguration.swift +++ /dev/null @@ -1,99 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2026 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation -import SwiftIfConfig -import SwiftSyntax - -/// A default, fixed build configuration during static analysis for interface extraction. -struct JExtractDefaultBuildConfiguration: BuildConfiguration { - static let shared = JExtractDefaultBuildConfiguration() - - private var base: StaticBuildConfiguration - - init() { - let decoder = JSONDecoder() - do { - base = try decoder.decode(StaticBuildConfiguration.self, from: StaticBuildConfiguration.embedded) - } catch { - fatalError("Embedded StaticBuildConfiguration is broken! data: \(String(data: StaticBuildConfiguration.embedded, encoding: .utf8) ?? "")") - } - } - - func isCustomConditionSet(name: String) throws -> Bool { - base.isCustomConditionSet(name: name) - } - - func hasFeature(name: String) throws -> Bool { - base.hasFeature(name: name) - } - - func hasAttribute(name: String) throws -> Bool { - base.hasAttribute(name: name) - } - - func canImport(importPath: [(TokenSyntax, String)], version: CanImportVersion) throws -> Bool { - try base.canImport(importPath: importPath, version: version) - } - - func isActiveTargetOS(name: String) throws -> Bool { - true - } - - func isActiveTargetArchitecture(name: String) throws -> Bool { - true - } - - func isActiveTargetEnvironment(name: String) throws -> Bool { - true - } - - func isActiveTargetRuntime(name: String) throws -> Bool { - true - } - - func isActiveTargetPointerAuthentication(name: String) throws -> Bool { - true - } - - func isActiveTargetObjectFormat(name: String) throws -> Bool { - true - } - - var targetPointerBitWidth: Int { - base.targetPointerBitWidth - } - - var targetAtomicBitWidths: [Int] { - base.targetAtomicBitWidths - } - - var endianness: Endianness { - base.endianness - } - - var languageVersion: VersionTuple { - base.languageVersion - } - - var compilerVersion: VersionTuple { - base.compilerVersion - } -} - -extension BuildConfiguration where Self == JExtractDefaultBuildConfiguration { - static var jextractDefault: JExtractDefaultBuildConfiguration { - .shared - } -} diff --git a/Sources/JExtractSwiftLib/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift index 909b671f4..5a1b2da24 100644 --- a/Sources/JExtractSwiftLib/Swift2Java.swift +++ b/Sources/JExtractSwiftLib/Swift2Java.swift @@ -34,6 +34,7 @@ public struct SwiftToJava { } let translator = Swift2JavaTranslator(config: config) + translator.log.logLevel = config.logLevel ?? .info let log = translator.log if config.javaPackage == nil || config.javaPackage!.isEmpty { diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index 106247a48..a5d96a1af 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -14,7 +14,6 @@ import Foundation import SwiftBasicFormat -import SwiftIfConfig import SwiftJavaConfigurationShared import SwiftJavaJNICore import SwiftParser @@ -28,9 +27,6 @@ public final class Swift2JavaTranslator { let config: Configuration - /// The build configuration used to resolve #if conditional compilation blocks. - let buildConfig: any BuildConfiguration - /// The name of the Swift module being translated. let swiftModuleName: String @@ -74,19 +70,6 @@ public final class Swift2JavaTranslator { self.log = Logger(label: "translator", logLevel: config.logLevel ?? .info) self.config = config self.swiftModuleName = swiftModule - - if let staticBuildConfigPath = config.staticBuildConfigurationFile { - do { - let data = try Data(contentsOf: URL(fileURLWithPath: staticBuildConfigPath)) - let decoder = JSONDecoder() - self.buildConfig = try decoder.decode(StaticBuildConfiguration.self, from: data) - self.log.info("Using custom static build configuration from: \(staticBuildConfigPath)") - } catch { - fatalError("Failed to load static build configuration from '\(staticBuildConfigPath)': \(error)") - } - } else { - self.buildConfig = .jextractDefault - } } } @@ -169,7 +152,6 @@ extension Swift2JavaTranslator { moduleName: self.swiftModuleName, inputs + [dependenciesSource], config: self.config, - buildConfig: self.buildConfig, log: self.log, ) self.lookupContext = SwiftTypeLookupContext(symbolTable: symbolTable) diff --git a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift index c6390bc14..1a583b1d5 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// import Foundation -import SwiftIfConfig import SwiftJavaConfigurationShared import SwiftParser import SwiftSyntax @@ -71,8 +70,7 @@ final class Swift2JavaVisitor { self.visit(subscriptDecl: node, in: parent) case .enumCaseDecl(let node): self.visit(enumCaseDecl: node, in: parent) - case .ifConfigDecl(let node): - self.visit(ifConfigDecl: node, in: parent, sourceFilePath: sourceFilePath) + default: break } @@ -368,30 +366,6 @@ final class Swift2JavaVisitor { } } - private func visit( - ifConfigDecl node: IfConfigDeclSyntax, - in parent: ImportedNominalType?, - sourceFilePath: String - ) { - let (clause, _) = node.activeClause(in: translator.buildConfig) - if let clause, let elements = clause.elements { - switch elements { - case .statements(let codeBlock): - for codeItem in codeBlock { - if let declNode = codeItem.item.as(DeclSyntax.self) { - self.visit(decl: declNode, in: parent, sourceFilePath: sourceFilePath) - } - } - case .decls(let memberBlock): - for memberItem in memberBlock { - self.visit(decl: memberItem.decl, in: parent, sourceFilePath: sourceFilePath) - } - default: - break - } - } - } - private func importAccessor( from node: DeclSyntax, in typeContext: ImportedNominalType?, diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift index f8e5927c9..895a0a1b8 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// -import SwiftIfConfig import SwiftSyntax struct SwiftParsedModuleSymbolTableBuilder { @@ -24,9 +23,6 @@ struct SwiftParsedModuleSymbolTableBuilder { /// Imported modules to resolve type syntax. let importedModules: [String: SwiftModuleSymbolTable] - /// The build configuration used to resolve #if conditional compilation blocks. - let buildConfig: any BuildConfiguration - /// Extension decls their extended type hasn't been resolved. var unresolvedExtensions: [ExtensionDeclSyntax] @@ -35,7 +31,6 @@ struct SwiftParsedModuleSymbolTableBuilder { requiredAvailablityOfModuleWithName: String? = nil, alternativeModules: SwiftModuleSymbolTable.AlternativeModuleNamesData? = nil, importedModules: [String: SwiftModuleSymbolTable], - buildConfig: any BuildConfiguration = .jextractDefault, log: Logger? = nil ) { self.log = log @@ -45,7 +40,6 @@ struct SwiftParsedModuleSymbolTableBuilder { alternativeModules: alternativeModules ) self.importedModules = importedModules - self.buildConfig = buildConfig self.unresolvedExtensions = [] } @@ -62,25 +56,17 @@ extension SwiftParsedModuleSymbolTableBuilder { ) { // Find top-level type declarations. for statement in sourceFile.statements { - self.handle(codeBlockItem: statement.item, sourceFilePath: sourceFilePath) - } - } - - mutating func handle( - codeBlockItem node: CodeBlockItemSyntax.Item, - sourceFilePath: String - ) { - // We only care about declarations. - guard case .decl(let decl) = node else { - return - } + // We only care about declarations. + guard case .decl(let decl) = statement.item else { + continue + } - if let nominalTypeNode = decl.asNominal { - self.handle(sourceFilePath: sourceFilePath, nominalTypeDecl: nominalTypeNode, parent: nil) - } else if let extensionNode = decl.as(ExtensionDeclSyntax.self) { - self.handle(extensionDecl: extensionNode, sourceFilePath: sourceFilePath) - } else if let ifConfigNode = decl.as(IfConfigDeclSyntax.self) { - self.handle(ifConfig: ifConfigNode, sourceFilePath: sourceFilePath) + if let nominalTypeNode = decl.asNominal { + self.handle(sourceFilePath: sourceFilePath, nominalTypeDecl: nominalTypeNode, parent: nil) + } + if let extensionNode = decl.as(ExtensionDeclSyntax.self) { + self.handle(extensionDecl: extensionNode, sourceFilePath: sourceFilePath) + } } } @@ -166,23 +152,6 @@ extension SwiftParsedModuleSymbolTableBuilder { return true } - mutating func handle( - ifConfig node: IfConfigDeclSyntax, - sourceFilePath: String - ) { - let (clause, _) = node.activeClause(in: buildConfig) - if let clause, let elements = clause.elements { - switch elements { - case .statements(let codeBlock): - for codeItem in codeBlock { - self.handle(codeBlockItem: codeItem.item, sourceFilePath: sourceFilePath) - } - default: - break - } - } - } - /// Finalize the symbol table and return it. mutating func finalize() -> SwiftModuleSymbolTable { // Handle the unresolved extensions. diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift index 5ba824c49..d1a5d9e01 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// import CodePrinting -import SwiftIfConfig import SwiftJavaConfigurationShared import SwiftParser import SwiftSyntax @@ -70,7 +69,6 @@ extension SwiftSymbolTable { moduleName: String, _ inputFiles: some Collection, config: Configuration?, - buildConfig: any BuildConfiguration = .jextractDefault, log: Logger, ) -> SwiftSymbolTable { @@ -106,7 +104,6 @@ extension SwiftSymbolTable { var stubBuilder = SwiftParsedModuleSymbolTableBuilder( moduleName: stubModuleName, importedModules: ["Swift": importedModules["Swift"]!], - buildConfig: buildConfig, ) stubBuilder.handle(sourceFile: sourceFile, sourceFilePath: "\(stubModuleName)_stub.swift") let stubModule = stubBuilder.finalize() @@ -125,7 +122,6 @@ extension SwiftSymbolTable { var builder = SwiftParsedModuleSymbolTableBuilder( moduleName: moduleName, importedModules: importedModules, - buildConfig: buildConfig, log: log, ) // First, register top-level and nested nominal types to the symbol table. diff --git a/Sources/StaticBuildConfigPluginExecutable/StaticBuildConfigPluginExecutable.swift b/Sources/StaticBuildConfigPluginExecutable/StaticBuildConfigPluginExecutable.swift deleted file mode 100644 index 3c7479653..000000000 --- a/Sources/StaticBuildConfigPluginExecutable/StaticBuildConfigPluginExecutable.swift +++ /dev/null @@ -1,70 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2026 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation -import Subprocess -import SwiftIfConfig - -@main struct StaticBuildConfigPluginExecutable { - static func main() async throws { - let args = CommandLine.arguments - guard args.count > 1 else { - print("Usage: \(args[0]) ") - return - } - let dst = URL(fileURLWithPath: args[1]) - - let data = try await loadStaticBuildConfig() - let template = #""" - import Foundation - import SwiftIfConfig - - extension StaticBuildConfiguration { - static var embedded: Data { - Data(#"\#(data)"#.utf8) - } - } - """# - try template.write(to: dst, atomically: true, encoding: .utf8) - } - - static func loadStaticBuildConfig() async throws -> String { - #if compiler(>=6.3) - let result = try await run( - .name("swift"), - arguments: ["frontend", "-print-static-build-config", "-target", "aarch64-unknown-linux-gnu"], - output: .string(limit: 65536), - error: .string(limit: 65536) - ) - if let error = result.standardError, !error.isEmpty { - fatalError(error) - } - return result.standardOutput ?? "" - #else - #if compiler(>=6.2) - let configuration = StaticBuildConfiguration( - languageVersion: .init(components: [5, 10]), - compilerVersion: .init(components: [6, 2]) - ) - #else - let configuration = StaticBuildConfiguration( - languageVersion: .init(components: [5, 10]), - compilerVersion: .init(components: [6, 1]) - ) - #endif - let encoder = JSONEncoder() - return String(data: try encoder.encode(configuration), encoding: .utf8) ?? "" - #endif - } -} diff --git a/Sources/SwiftJavaConfigurationShared/Configuration.swift b/Sources/SwiftJavaConfigurationShared/Configuration.swift index 24beabaa2..502996c47 100644 --- a/Sources/SwiftJavaConfigurationShared/Configuration.swift +++ b/Sources/SwiftJavaConfigurationShared/Configuration.swift @@ -132,10 +132,6 @@ public struct Configuration: Codable { /// ``` public var specialize: [String: SpecializationConfigEntry]? - /// If set, use this JSON file as the static build configuration for jextract. - /// This allows users to provide a custom StaticBuildConfiguration for #if resolution. - public var staticBuildConfigurationFile: String? - // ==== wrap-java --------------------------------------------------------- /// The Java class path that should be passed along to the swift-java tool. diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index 4a681d866..c320bedc6 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -464,40 +464,3 @@ public final class FishBox ... { > NOTE: Currently no helpers are available to convert between unspecialized types to specialized ones, but this can be offered > as additional `box.as(FishBox.class)` conversion methods in the future. - -### Evaluating `#if` - -In jextract, `#if` branches are evaluated using [SwiftIfConfig](https://github.com/swiftlang/swift-syntax/blob/main/Sources/SwiftIfConfig/SwiftIfConfig.docc/SwiftIfConfig.md). -The evaluation parameters are fixed; for example, the `os` expression always evaluates to true, so in the following case the value of the variable will be `Linux`. - -```swift -#if os(Linux) -let os = "Linux" -#elseif os(Android) -let os = "Android" -#else -let os = "Other" -#endif -``` - -If you want the above situation to be evaluated as `Android`, you can override the evaluation parameters. -First, obtain a [StaticBuildConfiguration](https://github.com/swiftlang/swift-syntax/blob/main/Sources/SwiftIfConfig/StaticBuildConfiguration.swift) with the following command and save it to a file. -(Adjust `-target` to match the environment you want to build for. This command is available from Swift 6.3.) - -```sh -swift frontend -print-static-build-config -target aarch64-unknown-linux-android28 > static-build-config.json -``` - -Then pass the path to that file when running jextract. - -- When using the jextract command: `--static-build-config ` -- When configuring via `swift-java.config`: - ```json - { - ... - "staticBuildConfigurationFile": "" // Relative path from `swift-java.config` - } - ``` - -As a result, jextract will evaluate `os` as `Android`. - diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index b1789cc38..93dc860fc 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -133,12 +133,6 @@ extension SwiftJava { @Option(help: "If specified, only generate bindings for this single Swift type name") var singleType: String? - - @Option( - help: - "Path to a JSON file containing a StaticBuildConfiguration. Used to resolve #if conditional compilation blocks." - ) - var staticBuildConfig: String? } } @@ -161,7 +155,6 @@ extension SwiftJava.JExtractCommand { configure(&config.swiftFilterInclude, append: self.filterInclude) configure(&config.swiftFilterExclude, append: self.filterExclude) configure(&config.singleType, overrideWith: self.singleType) - configure(&config.staticBuildConfigurationFile, overrideWith: self.staticBuildConfig) try checkModeCompatibility(config: config) diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 1f10b2aad..f0e1e72a6 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -87,17 +87,9 @@ func assertOutput( let sourceLocation = SourceLocation(fileID: fileID, filePath: filePath, line: line, column: column) for notExpectedChunk in notExpectedChunks { - let outputNotContainsNotExpectedChunk = !output.contains(notExpectedChunk) #expect( - outputNotContainsNotExpectedChunk, - """ - \("error: Output must not contain not expected chunk!".red) - ==== Not Expected output ----------------------------------------------- - \(notExpectedChunk.yellow) - ==== Got output ---------------------------------------------------- - \(output) - ==== --------------------------------------------------------------- - """, + !output.contains(notExpectedChunk), + "Output must not contain:\n\(notExpectedChunk)\n\nGot output:\n\(output)", sourceLocation: sourceLocation ) } diff --git a/Tests/JExtractSwiftTests/IfConfigTests.swift b/Tests/JExtractSwiftTests/IfConfigTests.swift deleted file mode 100644 index 6eddc08bf..000000000 --- a/Tests/JExtractSwiftTests/IfConfigTests.swift +++ /dev/null @@ -1,177 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2026 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation -import JExtractSwiftLib -import SwiftJavaConfigurationShared -import Testing - -#if compiler(>=6.3) -private let has6_3compilerFeature = true -#else -private let has6_3compilerFeature = false -#endif - -@Suite -struct IfConfigTests { - @Test - func evaluateIfConfigs() throws { - try assertOutput( - input: """ - #if os(Android) - public func androidFunc() - #else - public func notAndroidFunc() - #endif - - #if canImport(Foundation) - public struct CanImport { - } - #else - public struct CannotImport { - } - #endif - - #if DEBUG - public struct IsDebug { - } - #else - public struct IsNotDebug { - #if os(Linux) - public var linuxVar: Int - #elseif os(iOS) || os(macOS) - public var iOSorMacOSVar: Int - #else - #error("unsupported platform") - #endif - } - #endif - """, - .ffm, - .java, - detectChunkByInitialLines: 1, - expectedChunks: [ - "public static void androidFunc()", - "public final class CannotImport", - "public final class IsNotDebug", - "public long getLinuxVar()", - ], - notExpectedChunks: [ - "public static void notAndroidFunc()", - "public final class CanImport", - "public final class IsDebug", - "public long getIOSorMacOSVar() ", - ] - ) - } - - @Test - func overrideWithStaticBuildConfigurationFile() throws { - try withTemporaryFile( - suffix: "json", - contents: """ - { - "attributes": [], - "compilerVersion": { - "components": [6, 3] - }, - "customConditions": [ - "DEBUG" - ], - "endianness": "little", - "features": [], - "languageMode": { - "components": [5, 10] - }, - "targetArchitectures": [], - "targetAtomicBitWidths": [], - "targetEnvironments": [], - "targetOSs": [], - "targetObjectFileFormats": [], - "targetPointerAuthenticationSchemes": [], - "targetPointerBitWidth": 64, - "targetRuntimes": [] - } - """ - ) { staticBuildConfigFile in - var config = Configuration() - config.staticBuildConfigurationFile = staticBuildConfigFile.absoluteURL.path(percentEncoded: false) - - try assertOutput( - input: """ - #if DEBUG - public struct IsDebug {} - #else - public struct IsNotDebug {} - #endif - """, - config: config, - .ffm, - .java, - detectChunkByInitialLines: 1, - expectedChunks: [ - "public final class IsDebug" - ], - notExpectedChunks: [ - "public final class IsNotDebug" - ] - ) - } - } - - @Test(.enabled(if: has6_3compilerFeature)) - func swiftinterfaceCommonPattern() throws { - try assertOutput( - input: """ - public enum Foundation { - public struct URL {} - } - - public struct AppStore : Swift.Sendable, Swift.Codable { - public var storeURL: Foundation.URL? - #if compiler(>=5.3) && $NonescapableTypes - public init(storeURL: Foundation.URL?) - #endif - public func encode(to encoder: any Swift.Encoder) throws - public init(from decoder: any Swift.Decoder) throws - } - """, - .jni, - .swift, - detectChunkByInitialLines: 1, - expectedChunks: [ - """ - @_cdecl("Java_com_example_swift_AppStore__00024init__J") - public func Java_com_example_swift_AppStore__00024init__J(environment: UnsafeMutablePointer!, thisClass: jclass, storeURL: jlong) -> jlong - """ - ] - ) - } -} - -private func withTemporaryFile( - suffix: String, - contents: String = "", - in tempDirectory: URL = FileManager.default.temporaryDirectory, - _ perform: (URL) throws -> Void -) throws { - let tempFileName = "tmp_\(UUID().uuidString).\(suffix)" - let tempFileURL = tempDirectory.appendingPathComponent(tempFileName) - - try contents.write(to: tempFileURL, atomically: true, encoding: .utf8) - defer { - try? FileManager.default.removeItem(at: tempFileURL) - } - try perform(tempFileURL) -}