1212//
1313// ===----------------------------------------------------------------------===//
1414
15+ import groovy.json.JsonSlurper
1516import org.swift.swiftkit.gradle.BuildUtils
1617
1718import java.nio.file.*
19+ import kotlinx.serialization.json.*
1820
1921plugins {
2022 id(" build-logic.java-application-conventions" )
@@ -34,26 +36,57 @@ java {
3436 }
3537}
3638
39+ def swiftProductsWithJExtractPlugin () {
40+ def stdout = new ByteArrayOutputStream ()
41+ def stderr = new ByteArrayOutputStream ()
42+
43+ def result = exec {
44+ commandLine ' swift' , ' package' , ' describe' , ' --type' , ' json'
45+ standardOutput = stdout
46+ errorOutput = stderr
47+ ignoreExitValue = true
48+ }
49+
50+ def jsonOutput = stdout. toString()
51+
52+ if (result. exitValue == 0 ) {
53+ def json = new JsonSlurper (). parseText(jsonOutput)
54+ def products = json. targets
55+ .findAll { target ->
56+ target. product_dependencies?. contains(" JExtractSwiftPlugin" )
57+ }
58+ .collectMany { target ->
59+ target. product_memberships ?: []
60+ }
61+ return products
62+ } else {
63+ logger. warn(" Command failed: ${ stderr.toString()} " )
64+ return []
65+ }
66+ }
67+
68+
3769def swiftCheckValid = tasks. register(" swift-check-valid" , Exec ) {
3870 commandLine " swift"
3971 args(" -version" )
4072}
4173
4274def jextract = tasks. register(" jextract" , Exec ) {
43- description = " Builds swift sources, including swift-java source generation "
75+ description = " Generate Java wrappers for swift target "
4476 dependsOn swiftCheckValid
45- // dependsOn compileSwiftJExtractPlugin
4677
4778 // only because we depend on "live developing" the plugin while using this project to test it
4879 inputs. file(new File (rootDir, " Package.swift" ))
4980 inputs. dir(new File (rootDir, " Sources" ))
5081
82+ // If the package description changes, we should execute jextract again, maybe we added jextract to new targets
5183 inputs. file(new File (projectDir, " Package.swift" ))
52- inputs. dir(new File (projectDir, " Sources" ))
5384
54- // TODO: we can use package describe --type json to figure out which targets depend on JExtractSwiftPlugin and will produce outputs
55- // Avoid adding this directory, but create the expected one specifically for all targets
56- // which WILL produce sources because they have the plugin
85+ // monitor all targets/products which depend on the JExtract plugin
86+ swiftProductsWithJExtractPlugin(). each {
87+ logger. info(" [swift-java:jextract (Gradle)] Swift input target: ${ it} " )
88+ inputs. dir(new File (layout. projectDirectory. asFile, " Sources/${ it} " . toString()))
89+ }
5790 outputs. dir(layout. buildDirectory. dir(" ../.build/plugins/outputs/${ layout.projectDirectory.asFile.getName().toLowerCase()} " ))
5891
5992 File baseSwiftPluginOutputsDir = layout. buildDirectory. dir(" ../.build/plugins/outputs/" ). get(). asFile
@@ -69,7 +102,16 @@ def jextract = tasks.register("jextract", Exec) {
69102
70103 workingDir = layout. projectDirectory
71104 commandLine " swift"
72- args(" run" , " swift-java" , " jextract" , " -v" , " --log-level" , " info" ) // TODO: pass log level from Gradle build
105+ args(" build" ) // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build
106+ // If we wanted to execute a specific subcommand, we can like this:
107+ // args("run",/*
108+ // "swift-java", "jextract",
109+ // "--swift-module", "MySwiftLibrary",
110+ // // java.package is obtained from the swift-java.config in the swift module
111+ // "--output-java", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/src/generated/java").get()}",
112+ // "--output-swift", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/Sources").get()}",
113+ // "--log-level", (logging.level <= LogLevel.INFO ? "debug" : */"info")
114+ // )
73115}
74116
75117// Add the java-swift generated Java sources
0 commit comments