diff --git a/.github/workflows/uniffi.yaml b/.github/workflows/uniffi.yaml index 32dd5efa..b4193941 100644 --- a/.github/workflows/uniffi.yaml +++ b/.github/workflows/uniffi.yaml @@ -134,4 +134,441 @@ jobs: SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }} GPG_SIGNING_PASSPHRASE: ${{ secrets.GPG_SIGNING_PASSPHRASE }} - run: ./gradlew publishAllPublicationsToCentralPortal + run: ./gradlew publishMavenKotlinPublicationToCentralPortal publishMavenJavaPublicationToCentralPortal + + + build-ios: + if: "!contains(github.event.head_commit.message, 'skip ci')" + env: + OUTPUT_NAME: zen_uniffi + IPHONEOS_DEPLOYMENT_TARGET: '16.0' + + strategy: + fail-fast: true + matrix: + settings: + - target: 'aarch64-apple-ios' + output: 'lib{0}.a' + lib_dir: 'ios-aarch64' + - target: 'x86_64-apple-ios' + output: 'lib{0}.a' + lib_dir: 'ios-x86-64' + - target: 'aarch64-apple-ios-sim' + output: 'lib{0}.a' + lib_dir: 'ios-aarch64-sim' + + name: UniFFI iOS - ${{ matrix.settings.target }} + runs-on: macos-latest + + steps: + - uses: actions/checkout@v3 + + - name: Setup Rust Toolchain + uses: dtolnay/rust-toolchain@stable + with: + target: ${{ matrix.settings.target }} + + - name: Build iOS + run: | + if [ "${{ matrix.settings.target }}" = "aarch64-apple-ios-sim" ]; then + export BINDGEN_EXTRA_CLANG_ARGS="--target=aarch64-apple-ios --sysroot=$(xcrun --sdk iphonesimulator --show-sdk-path)" + fi + cargo build -p zen-uniffi --target ${{ matrix.settings.target }} --release --features bindgen + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.settings.lib_dir }} + path: target/${{ matrix.settings.target }}/release/${{ format(matrix.settings.output, env.OUTPUT_NAME) }} + if-no-files-found: error + + create-xcframework: + runs-on: macos-latest + needs: [ build-ios ] + if: "!contains(github.event.head_commit.message, 'skip ci')" + + steps: + - uses: actions/checkout@v3 + + - name: Download iOS artifacts + uses: actions/download-artifact@v4 + with: + path: target-ios + + - name: Reorganize artifacts to match target structure + run: | + mkdir -p target/aarch64-apple-ios/release + mkdir -p target/x86_64-apple-ios/release + mkdir -p target/aarch64-apple-ios-sim/release + + cp target-ios/ios-aarch64/libzen_uniffi.a target/aarch64-apple-ios/release/ + cp target-ios/ios-x86-64/libzen_uniffi.a target/x86_64-apple-ios/release/ + cp target-ios/ios-aarch64-sim/libzen_uniffi.a target/aarch64-apple-ios-sim/release/ + + - name: Setup Rust Toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Generate Swift bindings + run: | + cargo run --bin uniffi-bindgen -- generate \ + --library target/aarch64-apple-ios/release/libzen_uniffi.a \ + --language swift \ + --out-dir swift-bindings-temp + + - name: Organize Swift bindings structure + run: | + # Create the proper directory structure + mkdir -p swift-bindings/zen_uniffiFFI + mkdir -p swift-bindings/ZenUniffi + + # Move and rename the header file to zen_uniffiFFI.h in the zen_uniffiFFI folder + if [ -f swift-bindings-temp/zen_uniffiFFI.h ]; then + mv swift-bindings-temp/zen_uniffiFFI.h swift-bindings/zen_uniffiFFI/ + fi + + # Move and rename the modulemap to module.modulemap in the zen_uniffiFFI folder + if [ -f swift-bindings-temp/zen_uniffiFFI.modulemap ]; then + mv swift-bindings-temp/zen_uniffiFFI.modulemap swift-bindings/zen_uniffiFFI/module.modulemap + fi + + # Move the Swift file to zen_uniffi.swift in the ZenUniffi folder + if [ -f swift-bindings-temp/zen_uniffi.swift ]; then + mv swift-bindings-temp/zen_uniffi.swift swift-bindings/ZenUniffi/ + fi + + # Clean up temp directory + rm -rf swift-bindings-temp + + - name: Create fat simulator library + run: | + mkdir -p target/universal-sim/release + lipo -create \ + target/x86_64-apple-ios/release/libzen_uniffi.a \ + target/aarch64-apple-ios-sim/release/libzen_uniffi.a \ + -output target/universal-sim/release/libzen_uniffi.a + + - name: Create XCFramework + run: | + # Create XCFramework with device + universal simulator + xcodebuild -create-xcframework \ + -library target/aarch64-apple-ios/release/libzen_uniffi.a \ + -headers swift-bindings/zen_uniffiFFI \ + -library target/universal-sim/release/libzen_uniffi.a \ + -headers swift-bindings/zen_uniffiFFI \ + -output ZenUniffi.xcframework + + - name: Upload XCFramework + uses: actions/upload-artifact@v4 + with: + name: xcframework + path: ZenUniffi.xcframework/ + if-no-files-found: error + + - name: Upload Swift bindings + uses: actions/upload-artifact@v4 + with: + name: swift-bindings + path: swift-bindings + if-no-files-found: error + + release-ios: + name: Release iOS + runs-on: macos-latest + needs: [ create-xcframework ] + if: "startsWith(github.event.head_commit.message, 'chore(release): publish uniffi')" + + steps: + - name: Checkout zen-ios + uses: actions/checkout@v3 + with: + repository: gorules/zen-ios + persist-credentials: false + token: ${{ secrets.PAT }} + + - name: Download XCFramework + uses: actions/download-artifact@v4 + with: + name: xcframework + path: ZenUniffi.xcframework + + - name: Download Swift bindings + uses: actions/download-artifact@v4 + with: + name: swift-bindings + path: swift-bindings + + - name: Move artifacts to repo + run: | + # Remove existing Sources if it exists + rm -rf Sources + + # Move swift-bindings to Sources (already has the proper structure) + mv swift-bindings Sources + + - name: Set branch name + run: | + echo "BRANCH_NAME=chore/${{ github.run_id }}-${{ github.run_attempt }}" >> $GITHUB_ENV + + - name: Commit changes + run: | + BRANCH_NAME="${{ env.BRANCH_NAME }}" + git checkout -b $BRANCH_NAME + + # Setup the committers identity + git config user.email "bot@gorules.io" + git config user.name "Bot GoRules" + git config http.postBuffer 524288000 + git config http.lowSpeedTime 600 + + # Show what we have + ls -la + + # Commit the changes - add all new/modified files + git add -A + git status + git commit -m "chore: update XCFramework" + + - name: Push changes + uses: ad-m/github-push-action@master + with: + repository: gorules/zen-ios + github_token: ${{ secrets.PAT }} + branch: ${{ env.BRANCH_NAME }} + + - name: Create PR + run: | + BRANCH_NAME="${{ env.BRANCH_NAME }}" + + # Store the PAT in a file that can be accessed by the GitHub CLI + echo "${{ secrets.PAT }}" > token.txt + + # Authorize GitHub CLI and create a pull request + echo "Authorizing for PR" + gh auth login --with-token < token.txt + gh pr create \ + --body "" \ + --title "chore: update XCFramework" \ + --head "$BRANCH_NAME" \ + --base "master" + + build-android: + if: "!contains(github.event.head_commit.message, 'skip ci')" + runs-on: ubuntu-latest + env: + OUTPUT_NAME: zen_uniffi + + steps: + - uses: actions/checkout@v3 + + - name: Setup Rust Toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Install cargo-ndk + run: cargo install cargo-ndk + + - name: Setup Android NDK + uses: nttld/setup-ndk@v1 + id: setup-ndk + with: + ndk-version: r26d + add-to-path: true + + - name: Add Rust Android targets + run: | + rustup target add aarch64-linux-android + rustup target add armv7-linux-androideabi + rustup target add i686-linux-android + rustup target add x86_64-linux-android + + - name: Build for Android + env: + ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }} + run: | + cargo ndk -t arm64-v8a -t armeabi-v7a -t x86 -t x86_64 \ + --platform 33 \ + -o ./android-libs \ + build -p zen-uniffi --release --features bindgen + + - name: Upload Android artifacts + uses: actions/upload-artifact@v4 + with: + name: android-libs + path: android-libs/ + if-no-files-found: error + + prepare-android-bindings: + runs-on: ubuntu-latest + needs: [ build ] + if: "!contains(github.event.head_commit.message, 'skip ci')" + + defaults: + run: + working-directory: ${{ env.UNIFFI_DIRECTORY }} + + steps: + - uses: actions/checkout@v3 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: ${{ env.UNIFFI_DIRECTORY }}/build/generated/resources + + - name: Print directory tree + run: tree build + + - name: Generate Kotlin sources + run: | + cargo run --bin uniffi-bindgen -- generate \ + --library build/generated/resources/darwin-x86-64/libzen_uniffi.dylib \ + --language kotlin \ + --config uniffi-android.toml \ + --out-dir build/generated/kotlin-android + + - name: Upload Kotlin bindings + uses: actions/upload-artifact@v4 + with: + name: kotlin-android-bindings + path: ${{ env.UNIFFI_DIRECTORY }}/build/generated/kotlin-android + if-no-files-found: error + + - name: Print directory tree + run: tree build + + package-android-aar: + runs-on: ubuntu-latest + needs: [ build-android, prepare-android-bindings ] + if: "!contains(github.event.head_commit.message, 'skip ci')" + defaults: + run: + working-directory: ${{ env.UNIFFI_DIRECTORY }} + env: + ANDROID_BUILD_DIR: android-build + + steps: + - uses: actions/checkout@v3 + + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + + - name: Setup Android SDK + uses: android-actions/setup-android@v2 + id: setup-android + + - name: Download Kotlin bindings + uses: actions/download-artifact@v4 + with: + name: kotlin-android-bindings + path: ${{ env.UNIFFI_DIRECTORY }}/kotlin-bindings + + - name: Download Android native libraries + uses: actions/download-artifact@v4 + with: + name: android-libs + path: ${{ env.UNIFFI_DIRECTORY }}/android-libs + + - name: Create AAR structure + run: | + rm -rf "${{ env.ANDROID_BUILD_DIR }}" + mkdir -p "${{ env.ANDROID_BUILD_DIR }}/zen-engine-android/src/main/java" + mkdir -p "${{ env.ANDROID_BUILD_DIR }}/zen-engine-android/src/main/jniLibs" + mkdir -p "${{ env.ANDROID_BUILD_DIR }}/gradle/wrapper" + + - name: Copy native libraries + run: | + cp -r android-libs/* "${{ env.ANDROID_BUILD_DIR }}/zen-engine-android/src/main/jniLibs/" + + - name: Copy Kotlin bindings + run: | + cp -r kotlin-bindings/* "${{ env.ANDROID_BUILD_DIR }}/zen-engine-android/src/main/java/" + + - name: Copy custom Kotlin lib + run: | + cp -r lib/kotlin/* "${{ env.ANDROID_BUILD_DIR }}/zen-engine-android/src/main/java/" + + - name: Copy Gradle configuration files + run: | + cp gradlew "${{ env.ANDROID_BUILD_DIR }}" + cp -r gradle "${{ env.ANDROID_BUILD_DIR }}" + cp gradle.properties "${{ env.ANDROID_BUILD_DIR }}" + + - name: Copy Android Gradle files from repo + run: | + cp gradle.android/build.gradle.kts "${{ env.ANDROID_BUILD_DIR }}/" + cp gradle.android/settings.gradle.kts "${{ env.ANDROID_BUILD_DIR }}/" + cp gradle.android/zen-engine-android-build.gradle.kts "${{ env.ANDROID_BUILD_DIR }}/zen-engine-android/build.gradle.kts" + cp gradle.android/AndroidManifest.xml "${{ env.ANDROID_BUILD_DIR }}" + cp gradle.android/gradle.properties "${{ env.ANDROID_BUILD_DIR }}" + + - name: Print directory tree for ${{ env.ANDROID_BUILD_DIR }} + run: tree ${{ env.ANDROID_BUILD_DIR }} + + - name: Build AAR with Gradle + env: + ANDROID_HOME: ${{ env.ANDROID_SDK_ROOT }} + ANDROID_NDK_HOME: ${{ env.ANDROID_NDK_ROOT }} + run: | + cd "${{ env.ANDROID_BUILD_DIR }}" + chmod +x gradlew + ./gradlew :zen-engine-android:assembleRelease --no-daemon --stacktrace + + - name: Verify AAR file + run: | + AAR_FILE="${{ env.ANDROID_BUILD_DIR }}/zen-engine-android/build/outputs/aar/zen-engine-android-release.aar" + if [ -f "$AAR_FILE" ]; then + ls -lh "$AAR_FILE" + unzip -l "$AAR_FILE" | grep -E "\.so|\.class|AndroidManifest" | head -20 + else + echo "AAR file not found!" + exit 1 + fi + + - name: Upload AAR artifact + uses: actions/upload-artifact@v4 + with: + name: android-aar + path: ${{ env.UNIFFI_DIRECTORY }}/${{ env.ANDROID_BUILD_DIR }}/zen-engine-android/build/outputs/aar/zen-engine-android-release.aar + if-no-files-found: error + + release-android: + runs-on: ubuntu-latest + needs: [ package-android-aar ] + if: "startsWith(github.event.head_commit.message, 'chore(release): publish uniffi')" + defaults: + run: + working-directory: ${{ env.UNIFFI_DIRECTORY }} + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Validate Gradle wrapper jar + uses: gradle/actions/wrapper-validation@v3 + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 + + - name: Download Kotlin bindings + uses: actions/download-artifact@v4 + with: + name: kotlin-android-bindings + path: ${{ env.UNIFFI_DIRECTORY }}/build/generated/kotlin-android + + - name: Download Android AAR artifact + uses: actions/download-artifact@v4 + with: + name: android-aar + path: ${{ env.UNIFFI_DIRECTORY }}/build-android/aar/ + + - name: Publish Android Kotlin package to Maven Central + env: + SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} + SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} + GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }} + GPG_SIGNING_PASSPHRASE: ${{ secrets.GPG_SIGNING_PASSPHRASE }} + run: ./gradlew publishMavenKotlinAndroidPublicationToCentralPortal \ No newline at end of file diff --git a/bindings/uniffi/Cargo.toml b/bindings/uniffi/Cargo.toml index 5e324312..f702547a 100644 --- a/bindings/uniffi/Cargo.toml +++ b/bindings/uniffi/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "zen-uniffi" -version = "0.4.1" +version = "0.4.3" edition = "2024" license = "MIT" publish = false [lib] -crate-type = ["cdylib"] +crate-type = ["cdylib", "staticlib"] [[bin]] name = "uniffi-bindgen" @@ -22,4 +22,7 @@ async-trait = "0.1" tokio = "1.46" [build-dependencies] -uniffi = { version = "0.29", features = ["build"] } \ No newline at end of file +uniffi = { version = "0.29", features = ["build"] } + +[features] +bindgen = ["zen-engine/bindgen"] \ No newline at end of file diff --git a/bindings/uniffi/build.gradle.kts b/bindings/uniffi/build.gradle.kts index 45de6658..67f5336b 100644 --- a/bindings/uniffi/build.gradle.kts +++ b/bindings/uniffi/build.gradle.kts @@ -48,6 +48,15 @@ sourceSets { compileClasspath += sourceSets["main"].compileClasspath runtimeClasspath += sourceSets["main"].runtimeClasspath } + + val kotlinAndroid by creating { + kotlin { + srcDirs("lib/kotlin", "build/generated/kotlin_android") + } + + compileClasspath += sourceSets["main"].compileClasspath + runtimeClasspath += sourceSets["main"].runtimeClasspath + } } @@ -82,6 +91,12 @@ tasks { from(sourceSets["kotlin"].kotlin) } + val generateKotlinAndroidSourcesJar by creating(Jar::class) { + archiveBaseName.set("zen_engine_kotlin_android") + archiveClassifier.set("sources") + from(sourceSets["kotlinAndroid"].kotlin) + } + val dokkaJavadocJava by creating(DokkaTask::class) { outputDirectory.set(layout.buildDirectory.dir("dokka/java")) dokkaSourceSets { named("java") } @@ -93,6 +108,11 @@ tasks { dokkaSourceSets { named("kotlin") } } + val dokkaJavadocKotlinAndroid by creating(DokkaTask::class) { + outputDirectory.set(layout.buildDirectory.dir("dokka/kotlin_android")) + dokkaSourceSets { named("kotlinAndroid") } + } + val javadocJarJava by creating(Jar::class) { dependsOn(dokkaGeneratePublicationJavadoc) archiveBaseName.set("zen_engine") @@ -108,6 +128,14 @@ tasks { from(dokkaGeneratePublicationJavadoc.get()) } + + val javadocJarKotlinAndroid by creating(Jar::class) { + dependsOn(dokkaGeneratePublicationJavadoc) + archiveBaseName.set("zen_engine_kotlin_android") + archiveClassifier.set("javadoc") + + from(dokkaGeneratePublicationJavadoc.get()) + } } publishing { @@ -135,6 +163,23 @@ publishing { dependency("net.java.dev.jna:jna:5.17.0") } } + + create("mavenKotlinAndroid") { + groupId = "io.gorules" + artifactId = "zen-engine-kotlin-android" + + artifact("build-android/aar/zen-engine-android-release.aar") { + extension = "aar" + } + artifact(tasks["generateKotlinAndroidSourcesJar"]) + artifact(tasks["javadocJarKotlinAndroid"]) + + configurePom { + dependency("net.java.dev.jna:jna:5.14.0", "aar") + dependency("androidx.core:core-ktx:1.12.0") + dependency("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2") + } + } } repositories { mavenLocal() @@ -149,7 +194,7 @@ signing { val signingKey = Base64.getDecoder().decode(signingKeyBase64.get()).toString(Charsets.UTF_8) useInMemoryPgpKeys(signingKey, signingPassphrase.get()) - sign(publishing.publications["mavenJava"], publishing.publications["mavenKotlin"]) + sign(publishing.publications["mavenJava"], publishing.publications["mavenKotlin"], publishing.publications["mavenKotlinAndroid"]) } } @@ -214,20 +259,28 @@ fun MavenPublication.configurePom(dependencyConfig: PomDependencyBuilder.() -> U } class PomDependencyBuilder { - private val dependencies = mutableListOf>() + private val dependencies = mutableListOf>() - fun dependency(notation: String) { + fun dependency(notation: String, type: String = "jar") { val parts = notation.split(":") require(parts.size == 3) { "Dependency notation must be 'group:artifact:version'" } - dependencies.add(Triple(parts[0], parts[1], parts[2])) + dependencies.add(mapOf( + "groupId" to parts[0], + "artifactId" to parts[1], + "version" to parts[2], + "type" to type + )) } fun addToXml(dependenciesNode: groovy.util.Node) { - dependencies.forEach { (groupId, artifactId, version) -> + dependencies.forEach { dep -> val dependencyNode = dependenciesNode.appendNode("dependency") - dependencyNode.appendNode("groupId", groupId) - dependencyNode.appendNode("artifactId", artifactId) - dependencyNode.appendNode("version", version) + dependencyNode.appendNode("groupId", dep["groupId"]) + dependencyNode.appendNode("artifactId", dep["artifactId"]) + dependencyNode.appendNode("version", dep["version"]) + if (dep["type"] != "jar") { + dependencyNode.appendNode("type", dep["type"]) + } dependencyNode.appendNode("scope", "runtime") } } diff --git a/bindings/uniffi/gradle.android/AndroidManifest.xml b/bindings/uniffi/gradle.android/AndroidManifest.xml new file mode 100644 index 00000000..74b7379f --- /dev/null +++ b/bindings/uniffi/gradle.android/AndroidManifest.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/bindings/uniffi/gradle.android/build.gradle.kts b/bindings/uniffi/gradle.android/build.gradle.kts new file mode 100644 index 00000000..e3e3a120 --- /dev/null +++ b/bindings/uniffi/gradle.android/build.gradle.kts @@ -0,0 +1,21 @@ +buildscript { + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle:8.1.0") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.0") + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +tasks.register("clean", Delete::class) { + delete(rootProject.layout.buildDirectory) +} diff --git a/bindings/uniffi/gradle.android/gradle.properties b/bindings/uniffi/gradle.android/gradle.properties new file mode 100644 index 00000000..984b83ad --- /dev/null +++ b/bindings/uniffi/gradle.android/gradle.properties @@ -0,0 +1,4 @@ +android.useAndroidX=true +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +org.gradle.parallel=true +org.gradle.caching=true diff --git a/bindings/uniffi/gradle.android/settings.gradle.kts b/bindings/uniffi/gradle.android/settings.gradle.kts new file mode 100644 index 00000000..8ff1814c --- /dev/null +++ b/bindings/uniffi/gradle.android/settings.gradle.kts @@ -0,0 +1,2 @@ +rootProject.name = "ZenEngineAndroid" +include(":zen-engine-android") diff --git a/bindings/uniffi/gradle.android/zen-engine-android-build.gradle.kts b/bindings/uniffi/gradle.android/zen-engine-android-build.gradle.kts new file mode 100644 index 00000000..b3ea2f19 --- /dev/null +++ b/bindings/uniffi/gradle.android/zen-engine-android-build.gradle.kts @@ -0,0 +1,46 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "io.gorules.zen_engine.kotlin_android" + compileSdk = 34 + + defaultConfig { + minSdk = 24 + targetSdk = 34 + version = "0.4.0" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = "11" + } + + sourceSets { + getByName("main") { + jniLibs.srcDirs("src/main/jniLibs") + } + } +} + +dependencies { + implementation("androidx.core:core-ktx:1.12.0") + implementation("net.java.dev.jna:jna:5.14.0@aar") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2") +} diff --git a/bindings/uniffi/uniffi-android.toml b/bindings/uniffi/uniffi-android.toml new file mode 100644 index 00000000..4afb32b5 --- /dev/null +++ b/bindings/uniffi/uniffi-android.toml @@ -0,0 +1,10 @@ +# Kotlin Android +[bindings.kotlin] +package_name = "io.gorules.zen_engine.kotlin_android" +generate_immutable_records = true +android = true + +[bindings.kotlin.custom_types.JsonBuffer] +imports = ["io.gorules.zen_engine.kotlin.JsonBuffer"] +into_custom = "JsonBuffer({})" +from_custom = "{}.value" diff --git a/core/engine/Cargo.toml b/core/engine/Cargo.toml index 88bb1be3..7799787b 100644 --- a/core/engine/Cargo.toml +++ b/core/engine/Cargo.toml @@ -49,4 +49,7 @@ rquickjs = { version = "0.9", features = ["macro", "loader", "rust-alloc", "futu [[bench]] harness = false -name = "engine" \ No newline at end of file +name = "engine" + +[features] +bindgen = ["rquickjs/bindgen"] \ No newline at end of file