From 09001bbe98f064cc7482e18ff1f61f999a00a4f8 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 9 Apr 2026 23:23:11 +0000 Subject: [PATCH] feat: add macOS native targets (macosX64, macosArm64) to quartz - Declare macosX64() and macosArm64() KMP targets in build.gradle.kts - Wire macosMain/macosTest source sets through appleMain/appleTest - Move Secp256k1NativeBenchmark from linuxX64Test to nativeTest so it runs on all native targets (Linux, macOS, iOS) - Use platform() for dynamic labels instead of hardcoded "linuxX64" - Update run_all.sh to pick the correct native target per OS/arch https://claude.ai/code/session_01WSNE6QKiYM2ZutQD2UihCW --- quartz/benchmarks/run_all.sh | 32 ++++++++++++------- quartz/build.gradle.kts | 29 +++++++++++++++++ .../secp256k1/Secp256k1NativeBenchmark.kt | 10 ++++-- 3 files changed, 56 insertions(+), 15 deletions(-) rename quartz/src/{linuxX64Test => nativeTest}/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Secp256k1NativeBenchmark.kt (96%) diff --git a/quartz/benchmarks/run_all.sh b/quartz/benchmarks/run_all.sh index a2228223e..e1f7852ef 100755 --- a/quartz/benchmarks/run_all.sh +++ b/quartz/benchmarks/run_all.sh @@ -82,21 +82,29 @@ fi echo "" # ============================================================================ -# 2. Kotlin/Native benchmark (Linux only — only linuxX64 target exists) +# 2. Kotlin/Native benchmark (Linux and macOS) # ============================================================================ -if [ "$OS_NAME" = "Linux" ]; then - echo "=== Running Kotlin/Native benchmark ===" - "$ROOT/gradlew" -p "$ROOT" :quartz:linuxX64Test --tests "*.Secp256k1NativeBenchmark" \ - 2>/dev/null || true +echo "=== Running Kotlin/Native benchmark ===" +case "$OS_NAME" in + Linux) + KN_TARGET="linuxX64Test" + ;; + Darwin) + case "$ARCH" in + arm64) KN_TARGET="macosArm64Test" ;; + *) KN_TARGET="macosX64Test" ;; + esac + ;; +esac - KN_XML="$ROOT/quartz/build/test-results/linuxX64Test/TEST-linuxX64Test.com.vitorpamplona.quartz.utils.secp256k1.Secp256k1NativeBenchmark.xml" - if [ -f "$KN_XML" ]; then - sed -n '//p' "$KN_XML" | grep -v 'CDATA\|]]>' - else - echo "K/Native benchmark XML not found." - fi +"$ROOT/gradlew" -p "$ROOT" ":quartz:$KN_TARGET" --tests "*.Secp256k1NativeBenchmark" \ + 2>/dev/null || true + +KN_XML="$ROOT/quartz/build/test-results/$KN_TARGET/TEST-${KN_TARGET}.com.vitorpamplona.quartz.utils.secp256k1.Secp256k1NativeBenchmark.xml" +if [ -f "$KN_XML" ]; then + sed -n '//p' "$KN_XML" | grep -v 'CDATA\|]]>' else - echo "=== Skipping Kotlin/Native benchmark (only linuxX64 target available) ===" + echo "K/Native benchmark XML not found." fi echo "" diff --git a/quartz/build.gradle.kts b/quartz/build.gradle.kts index 117a58791..2b0b93213 100644 --- a/quartz/build.gradle.kts +++ b/quartz/build.gradle.kts @@ -87,6 +87,9 @@ kotlin { linuxX64() + macosX64() + macosArm64() + // This makes sure that the resource file directory is visible for iOS tests. val rootDir = "${rootProject.rootDir.path}/quartz/src/commonTest/resources" @@ -297,6 +300,32 @@ kotlin { dependsOn(iosTest.get()) } + val macosMain = + create("macosMain") { + dependsOn(appleMain) + } + + val macosTest = + create("macosTest") { + dependsOn(appleTest) + } + + val macosX64Main by getting { + dependsOn(macosMain) + } + + val macosX64Test by getting { + dependsOn(macosTest) + } + + val macosArm64Main by getting { + dependsOn(macosMain) + } + + val macosArm64Test by getting { + dependsOn(macosTest) + } + val linuxMain = create("linuxMain") { dependsOn(nativeMain) diff --git a/quartz/src/linuxX64Test/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Secp256k1NativeBenchmark.kt b/quartz/src/nativeTest/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Secp256k1NativeBenchmark.kt similarity index 96% rename from quartz/src/linuxX64Test/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Secp256k1NativeBenchmark.kt rename to quartz/src/nativeTest/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Secp256k1NativeBenchmark.kt index cf7c717d8..865374a6d 100644 --- a/quartz/src/linuxX64Test/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Secp256k1NativeBenchmark.kt +++ b/quartz/src/nativeTest/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Secp256k1NativeBenchmark.kt @@ -20,6 +20,7 @@ */ package com.vitorpamplona.quartz.utils.secp256k1 +import com.vitorpamplona.quartz.utils.platform import kotlin.test.Test import kotlin.test.assertTrue import kotlin.time.TimeSource @@ -42,7 +43,10 @@ import kotlin.time.TimeSource * * Test data is the same across all 3 platform benchmarks for cross-platform comparability. * - * Run with: ./gradlew :quartz:linuxX64Test --tests "*.Secp256k1NativeBenchmark" + * Run with: + * ./gradlew :quartz:linuxX64Test --tests "*.Secp256k1NativeBenchmark" + * ./gradlew :quartz:macosArm64Test --tests "*.Secp256k1NativeBenchmark" + * ./gradlew :quartz:macosX64Test --tests "*.Secp256k1NativeBenchmark" * * IMPORTANT: Requires -opt in the compiler options for meaningful results. * Without it, K/N compiles in debug mode (~12x slower). See build.gradle.kts. @@ -167,7 +171,7 @@ class Secp256k1NativeBenchmark { Secp256k1.ecdhXOnly(pub2xOnly, privKey) } - printResults("secp256k1 Benchmark: Kotlin/Native (LLVM AOT) on linuxX64", results) + printResults("secp256k1 Benchmark: Kotlin/Native (LLVM AOT) on ${platform()}", results) // ==================== Batch verification ==================== // Same pubkey, n events — the typical Nostr pattern (feed from one author). @@ -274,7 +278,7 @@ class Secp256k1NativeBenchmark { ltSink = if (uLt(a.l0 xor ltSink, b.l0)) 1L else 0L } - printResults("secp256k1 Field Micro-Benchmarks: Kotlin/Native (LLVM AOT) on linuxX64", results) + printResults("secp256k1 Field Micro-Benchmarks: Kotlin/Native (LLVM AOT) on ${platform()}", results) // Use sinks to prevent dead code elimination of the entire benchmark assertTrue(hiSink != Long.MIN_VALUE || ltSink != Long.MIN_VALUE || out.l0 != Long.MIN_VALUE)