Skip to content

Introduce subcommand for jextract to prevent linking Foundation#624

Open
madsodgaard wants to merge 7 commits intoswiftlang:mainfrom
madsodgaard:jextract-no-foundation
Open

Introduce subcommand for jextract to prevent linking Foundation#624
madsodgaard wants to merge 7 commits intoswiftlang:mainfrom
madsodgaard:jextract-no-foundation

Conversation

@madsodgaard
Copy link
Contributor

Resolves #619

Specifying any non Swift files as build plugin outputs, will make SPM generate a bundle accessor file which imports Foundation unconditionally.

To solve this, we introduce a new subcommand that handles the callback part of the JExtract build plugin.

@madsodgaard madsodgaard requested a review from ktoso as a code owner March 16, 2026 09:08
jextractOutputFiles += [javaSourcesFile]
// NOTE: javaSourcesFile is intentionally NOT added to jextractOutputFiles.
// Adding a non-Swift file as a build command output causes SPM to bundle it
// as a module resource, which triggers resource_bundle_accessor.swift generation
Copy link
Collaborator

@ktoso ktoso Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh oh no... ;-(

arguments: arguments,
inputFiles: [configFile] + swiftFiles,
outputFiles: jextractOutputFiles
outputFiles: jextractOutputFiles,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pretty sure formatter will dislike this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it passed 🤷

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okey I'm honestly confused with swift-format sometimes... 😅

// inputFiles includes the Swift outputs from jextract so that SPM knows
// this command must run after jextract finishes.
var javaCallbacksArguments = [
"java-callbacks-build",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we HAVE to do it all int one huge mega step? Can we not invoke multiple commands one by one? I'd like to make this hidden in command line somehow...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, what would we benefit from writing multiple commands? As this is only intended for internal use and a workaround for the SwiftPM limitation.

@preconcurrency import SystemPackage
#endif

/// Builds Swift-Java callbacks in a single command:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a huge WORKAROUND: rdar://172649681 if we invoke commands one by one with java outputs SwiftPM will link Foundation here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, would be good if you filed an issue on swiftpm explaining this behavior, might be better to track that way coming from you directly as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

@ktoso ktoso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please construct a Linkage test that would show this problem? I'd like to not regress on it by accident

/// Gradle output directories) as module resources, which would trigger
/// resource_bundle_accessor.swift generation and pull Foundation.Bundle into the binary.
extension SwiftJava {
struct JavaCallbacksBuildCommand: AsyncParsableCommand {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Man I really dislike this command... we'll have to copy around and keep it updated constantly :-\

Before we merge this, can we make sure we can't avoid it? How about just ignoring the java outputs, does swiftpm prevent things from working if we just pretend they don't exist but we write them anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is I am guessing that SwiftPM uses the input/output to derive the dependencies between the build commands. So, I am afraid that it will run the builds in the wrong order.

Alternatively, if its only using it for stale checks, that means that if we remove them from the outputs, we would retrigger those commands on each invocation of the build plugin. Maybe someone from the SwiftPM team can confirm the behaviour here?

ResolveCommand.self,
WrapJavaCommand.self,
JExtractCommand.self,
JavaCallbacksBuildCommand.self,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check how we can hide this form --help? Alternatively, _ prefix it or do something to its name in argument parser etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what the shouldDisplay: false does:

OVERVIEW: Generate sources and configuration for Swift and Java interoperability.

USAGE: swift-java <subcommand>

OPTIONS:
  -h, --help              Show help information.

SUBCOMMANDS:
  configure               Configure and emit a swift-java.config file based on an input dependency or jar file
  resolve                 Resolve dependencies and write the resulting swift-java.classpath file
  wrap-java               Wrap Java classes with corresponding Swift bindings.
  jextract                Wrap Swift functions and types with Java bindings, making them available to be called from Java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Adding JExtractSwiftPlugin links Full Foundation

2 participants