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
This commit is contained in:
Claude
2026-04-09 23:23:11 +00:00
parent dee050c6d8
commit 09001bbe98
3 changed files with 56 additions and 15 deletions
+20 -12
View File
@@ -82,21 +82,29 @@ fi
echo "" 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 ==="
echo "=== Running Kotlin/Native benchmark ===" case "$OS_NAME" in
"$ROOT/gradlew" -p "$ROOT" :quartz:linuxX64Test --tests "*.Secp256k1NativeBenchmark" \ Linux)
2>/dev/null || true 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" "$ROOT/gradlew" -p "$ROOT" ":quartz:$KN_TARGET" --tests "*.Secp256k1NativeBenchmark" \
if [ -f "$KN_XML" ]; then 2>/dev/null || true
sed -n '/<!\[CDATA\[/,/\]\]>/p' "$KN_XML" | grep -v 'CDATA\|]]>'
else KN_XML="$ROOT/quartz/build/test-results/$KN_TARGET/TEST-${KN_TARGET}.com.vitorpamplona.quartz.utils.secp256k1.Secp256k1NativeBenchmark.xml"
echo "K/Native benchmark XML not found." if [ -f "$KN_XML" ]; then
fi sed -n '/<!\[CDATA\[/,/\]\]>/p' "$KN_XML" | grep -v 'CDATA\|]]>'
else else
echo "=== Skipping Kotlin/Native benchmark (only linuxX64 target available) ===" echo "K/Native benchmark XML not found."
fi fi
echo "" echo ""
+29
View File
@@ -87,6 +87,9 @@ kotlin {
linuxX64() linuxX64()
macosX64()
macosArm64()
// This makes sure that the resource file directory is visible for iOS tests. // This makes sure that the resource file directory is visible for iOS tests.
val rootDir = "${rootProject.rootDir.path}/quartz/src/commonTest/resources" val rootDir = "${rootProject.rootDir.path}/quartz/src/commonTest/resources"
@@ -297,6 +300,32 @@ kotlin {
dependsOn(iosTest.get()) 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 = val linuxMain =
create("linuxMain") { create("linuxMain") {
dependsOn(nativeMain) dependsOn(nativeMain)
@@ -20,6 +20,7 @@
*/ */
package com.vitorpamplona.quartz.utils.secp256k1 package com.vitorpamplona.quartz.utils.secp256k1
import com.vitorpamplona.quartz.utils.platform
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue
import kotlin.time.TimeSource 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. * 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. * IMPORTANT: Requires -opt in the compiler options for meaningful results.
* Without it, K/N compiles in debug mode (~12x slower). See build.gradle.kts. * Without it, K/N compiles in debug mode (~12x slower). See build.gradle.kts.
@@ -167,7 +171,7 @@ class Secp256k1NativeBenchmark {
Secp256k1.ecdhXOnly(pub2xOnly, privKey) 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 ==================== // ==================== Batch verification ====================
// Same pubkey, n events — the typical Nostr pattern (feed from one author). // 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 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 // 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) assertTrue(hiSink != Long.MIN_VALUE || ltSink != Long.MIN_VALUE || out.l0 != Long.MIN_VALUE)