From 08b1029922563b806323937e0fccba78c0c48123 Mon Sep 17 00:00:00 2001 From: jappeace-sloth Date: Sun, 26 Apr 2026 11:10:19 +0000 Subject: [PATCH 01/10] Add CI reproduction test for iOS SIGILL on pre-A13 devices (#216) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Apple Silicon, GHC invokes clang without -mcpu, so clang defaults to the host CPU and emits ARMv8.4+ instructions (UDOT/SDOT) that crash on pre-A13 iOS devices (A12/A12X). This adds a canary C function (uint8 dot-product loop) that auto-vectorizes into UDOT at -O2, compiled with the same toolchain as the iOS build. The test disassembles the output and checks for UDOT/SDOT — expected to FAIL on Apple Silicon CI, proving the vulnerability exists. Prompt: reproduce issue #216 (SIGILL on pre-A13 ios devices) with a CI test Co-Authored-By: Claude Opus 4.6 --- .github/workflows/ci.yaml | 3 +++ nix/ci.nix | 47 ++++++++++++++++++++++++++++++++++++--- test/ios/sigill_canary.c | 18 +++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 test/ios/sigill_canary.c diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 99ce2c77..fe07656d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -99,6 +99,9 @@ jobs: - run: nix-build nix/ci.nix -A simulator-all -A ios-lib - name: Run combined simulator test (lifecycle + UI + buttons + scroll) run: nix-build nix/ci.nix -A simulator-all -o result-simulator-all && ./result-simulator-all/bin/test-all-ios + - name: "Repro #216: detect SIGILL-prone instructions in default clang output" + continue-on-error: true + run: nix-build nix/ci.nix -A ios-sigill-check - name: Cancel workflow on failure if: failure() continue-on-error: true diff --git a/nix/ci.nix b/nix/ci.nix index 4cbee3a1..d9c10135 100644 --- a/nix/ci.nix +++ b/nix/ci.nix @@ -31,9 +31,50 @@ let license = lib.licenses.mit; }; }; - } // (if isDarwin then { - ios-lib = import ./ios.nix { inherit sources; }; - watchos-lib = import ./watchos.nix { inherit sources; }; + } // (if isDarwin then let + isAppleSilicon = builtins.currentSystem == "aarch64-darwin"; + iosLib = import ./ios.nix { inherit sources; }; + watchosLib = import ./watchos.nix { inherit sources; }; + canary = ../test/ios/sigill_canary.c; + in { + ios-lib = iosLib; + watchos-lib = watchosLib; + + # Issue #216: On Apple Silicon, GHC invokes clang without -mcpu, + # so clang targets the host CPU (M1/M2/M3) and emits ARMv8.4+ + # instructions like UDOT that crash on pre-A13 iOS devices. + # + # This test compiles a canary C function (uint8 dot-product that + # auto-vectorizes into UDOT at -O2) using the same toolchain as + # the iOS build, then checks the disassembly for UDOT/SDOT. + # + # Expected: FAILS on Apple Silicon (proving the vulnerability), + # SKIPS on Intel Macs (x86_64 doesn't emit ARM instructions). + ios-sigill-check = pkgs.runCommand "ios-sigill-check" {} ( + if isAppleSilicon then '' + # Compile canary with default -O2 (no -mcpu), same as GHC does. + cc -c -O2 -o canary.o ${canary} + otool -tv canary.o > disasm.txt + + echo "=== Disassembly ===" + cat disasm.txt + + if grep -qi 'udot\|sdot' disasm.txt; then + echo "" + echo "REPRODUCED: clang emitted UDOT/SDOT (ARMv8.4+) without -mcpu." + echo "These instructions cause SIGILL on pre-A13 iOS devices (A12/A12X)." + echo "See https://github.com/jappeace/hatter/issues/216" + exit 1 + else + echo "No UDOT/SDOT found — host clang did not auto-vectorize the canary." + echo "The canary may need updating, or the compiler version changed." + touch $out + fi + '' else '' + echo "SKIP: not Apple Silicon (${builtins.currentSystem}), UDOT not relevant." + touch $out + '' + ); } else {}); # Emulator/simulator test runners — heavy (include system images), diff --git a/test/ios/sigill_canary.c b/test/ios/sigill_canary.c new file mode 100644 index 00000000..62b100fc --- /dev/null +++ b/test/ios/sigill_canary.c @@ -0,0 +1,18 @@ +// Canary for iOS SIGILL issue #216. +// +// This dot-product loop auto-vectorizes into UDOT (ARMv8.4-A) at -O2 +// on Apple Silicon when clang targets the host CPU. UDOT causes SIGILL +// on pre-A13 devices (A12/A12X lack the instruction). +// +// The iOS build test compiles this with the same toolchain GHC uses and +// checks the disassembly for UDOT. If found, the build would produce +// binaries that crash on older devices. +#include + +int dotProduct(const uint8_t *a, const uint8_t *b, int n) { + int sum = 0; + for (int i = 0; i < n; i++) { + sum += a[i] * b[i]; + } + return sum; +} From 9e9b5453fb3303457e6829420058582a3222a961 Mon Sep 17 00:00:00 2001 From: jappeace-sloth Date: Sun, 26 Apr 2026 11:44:23 +0000 Subject: [PATCH 02/10] Fix ios-sigill-check: add cc and otool to nativeBuildInputs runCommand doesn't provide a C compiler by default in the nix sandbox. Prompt: fix reproduction test, cc was not found in CI Co-Authored-By: Claude Opus 4.6 --- nix/ci.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nix/ci.nix b/nix/ci.nix index d9c10135..5945af5c 100644 --- a/nix/ci.nix +++ b/nix/ci.nix @@ -50,7 +50,9 @@ let # # Expected: FAILS on Apple Silicon (proving the vulnerability), # SKIPS on Intel Macs (x86_64 doesn't emit ARM instructions). - ios-sigill-check = pkgs.runCommand "ios-sigill-check" {} ( + ios-sigill-check = pkgs.runCommand "ios-sigill-check" { + nativeBuildInputs = [ pkgs.stdenv.cc pkgs.cctools ]; + } ( if isAppleSilicon then '' # Compile canary with default -O2 (no -mcpu), same as GHC does. cc -c -O2 -o canary.o ${canary} From 4d54e0492c19c506d8d26a918349d03928a6c498 Mon Sep 17 00:00:00 2001 From: jappeace-sloth Date: Sun, 26 Apr 2026 12:25:31 +0000 Subject: [PATCH 03/10] Fix canary: use explicit -mcpu=apple-m1 to prove UDOT vulnerability The nix CC wrapper targets generic aarch64, not the host CPU, so the previous test did not produce UDOT. Now explicitly compiles with -mcpu=apple-m1 (simulating host-CPU targeting) and -mcpu=apple-a12 (the proposed fix), comparing the outputs to prove: 1. M1-targeting produces UDOT (the bug) 2. A12-targeting suppresses it (the fix) Prompt: fix reproduction, nix cc wrapper uses generic aarch64 target Co-Authored-By: Claude Opus 4.6 --- nix/ci.nix | 60 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/nix/ci.nix b/nix/ci.nix index 5945af5c..09ec138a 100644 --- a/nix/ci.nix +++ b/nix/ci.nix @@ -40,36 +40,58 @@ let ios-lib = iosLib; watchos-lib = watchosLib; - # Issue #216: On Apple Silicon, GHC invokes clang without -mcpu, - # so clang targets the host CPU (M1/M2/M3) and emits ARMv8.4+ - # instructions like UDOT that crash on pre-A13 iOS devices. + # Issue #216: On Apple Silicon, clang targeting M1+ CPUs emits + # ARMv8.4+ instructions (UDOT/SDOT) that crash on pre-A13 iOS + # devices (A12/A12X). This test proves the vulnerability exists + # by compiling a canary with -mcpu=apple-m1 (what happens when + # code targets Apple Silicon) and verifying UDOT appears in the + # output. It also verifies -mcpu=apple-a12 suppresses UDOT, + # confirming that flag is the correct fix. # - # This test compiles a canary C function (uint8 dot-product that - # auto-vectorizes into UDOT at -O2) using the same toolchain as - # the iOS build, then checks the disassembly for UDOT/SDOT. - # - # Expected: FAILS on Apple Silicon (proving the vulnerability), - # SKIPS on Intel Macs (x86_64 doesn't emit ARM instructions). + # The nix CC wrapper uses a generic aarch64 target, so we must + # explicitly pass -mcpu to demonstrate the issue. ios-sigill-check = pkgs.runCommand "ios-sigill-check" { nativeBuildInputs = [ pkgs.stdenv.cc pkgs.cctools ]; } ( if isAppleSilicon then '' - # Compile canary with default -O2 (no -mcpu), same as GHC does. - cc -c -O2 -o canary.o ${canary} - otool -tv canary.o > disasm.txt + echo "=== Compile targeting Apple M1 (simulates host-CPU targeting) ===" + cc -c -O2 -mcpu=apple-m1 -o canary_m1.o ${canary} + otool -tv canary_m1.o > disasm_m1.txt + cat disasm_m1.txt + + echo "" + echo "=== Compile targeting Apple A12 (minimum for iOS 17+) ===" + cc -c -O2 -mcpu=apple-a12 -o canary_a12.o ${canary} + otool -tv canary_a12.o > disasm_a12.txt + cat disasm_a12.txt + + echo "" + echo "=== Results ===" + + M1_HAS_UDOT=false + A12_HAS_UDOT=false + if grep -qi 'udot\|sdot' disasm_m1.txt; then M1_HAS_UDOT=true; fi + if grep -qi 'udot\|sdot' disasm_a12.txt; then A12_HAS_UDOT=true; fi - echo "=== Disassembly ===" - cat disasm.txt + echo "M1 target produces UDOT/SDOT: $M1_HAS_UDOT" + echo "A12 target produces UDOT/SDOT: $A12_HAS_UDOT" - if grep -qi 'udot\|sdot' disasm.txt; then + if [ "$M1_HAS_UDOT" = "true" ] && [ "$A12_HAS_UDOT" = "false" ]; then echo "" - echo "REPRODUCED: clang emitted UDOT/SDOT (ARMv8.4+) without -mcpu." - echo "These instructions cause SIGILL on pre-A13 iOS devices (A12/A12X)." + echo "REPRODUCED: -mcpu=apple-m1 emits UDOT (crashes on A12)," + echo " -mcpu=apple-a12 does not (safe for A12)." + echo "Any C code compiled targeting Apple Silicon without -mcpu" + echo "constraint will SIGILL on pre-A13 iOS devices." echo "See https://github.com/jappeace/hatter/issues/216" exit 1 + elif [ "$M1_HAS_UDOT" = "false" ]; then + echo "" + echo "INCONCLUSIVE: M1 target did not produce UDOT." + echo "Canary may need updating for this clang version." + touch $out else - echo "No UDOT/SDOT found — host clang did not auto-vectorize the canary." - echo "The canary may need updating, or the compiler version changed." + echo "" + echo "UNEXPECTED: A12 target also produces UDOT — bug in test or clang." touch $out fi '' else '' From 0341d70544c89fa950a9b2e4c18425752620b510 Mon Sep 17 00:00:00 2001 From: jappeace-sloth Date: Sun, 26 Apr 2026 13:02:15 +0000 Subject: [PATCH 04/10] Detect UDOT as raw .long encoding (otool doesn't know the mnemonic) CI showed otool printing UDOT as '.long 0x6e829480' instead of the mnemonic. The UDOT IS being emitted by -mcpu=apple-m1, but otool can't disassemble it. Match UDOT/SDOT vector encodings (0x[06]e8x94xx) in addition to mnemonics. Prompt: fix detection, otool shows .long for UDOT encoding Co-Authored-By: Claude Opus 4.6 --- nix/ci.nix | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/nix/ci.nix b/nix/ci.nix index 09ec138a..f33c4087 100644 --- a/nix/ci.nix +++ b/nix/ci.nix @@ -68,10 +68,19 @@ let echo "" echo "=== Results ===" + # Detect UDOT/SDOT: either as a mnemonic or as a raw .long + # encoding (otool prints .long when it doesn't know the opcode). + # UDOT vector: 0x6E8x94xx, SDOT vector: 0x0E8x94xx + has_dotprod() { + grep -qi 'udot\|sdot' "$1" && return 0 + grep -qE '\.long\s+0x[06]e8[0-9a-f]94' "$1" && return 0 + return 1 + } + M1_HAS_UDOT=false A12_HAS_UDOT=false - if grep -qi 'udot\|sdot' disasm_m1.txt; then M1_HAS_UDOT=true; fi - if grep -qi 'udot\|sdot' disasm_a12.txt; then A12_HAS_UDOT=true; fi + if has_dotprod disasm_m1.txt; then M1_HAS_UDOT=true; fi + if has_dotprod disasm_a12.txt; then A12_HAS_UDOT=true; fi echo "M1 target produces UDOT/SDOT: $M1_HAS_UDOT" echo "A12 target produces UDOT/SDOT: $A12_HAS_UDOT" From bba0a54ff7814ea8babafdc09b9ad12a34b0a557 Mon Sep 17 00:00:00 2001 From: jappeace-sloth Date: Sun, 26 Apr 2026 17:22:26 +0000 Subject: [PATCH 05/10] Make ios-sigill-check fail CI (remove continue-on-error) The reproduction test should visibly fail CI so the issue is apparent from the commit status. Prompt: remove continue-on-error so CI fails red Co-Authored-By: Claude Opus 4.6 --- .github/workflows/ci.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fe07656d..ba5be3cf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -100,7 +100,6 @@ jobs: - name: Run combined simulator test (lifecycle + UI + buttons + scroll) run: nix-build nix/ci.nix -A simulator-all -o result-simulator-all && ./result-simulator-all/bin/test-all-ios - name: "Repro #216: detect SIGILL-prone instructions in default clang output" - continue-on-error: true run: nix-build nix/ci.nix -A ios-sigill-check - name: Cancel workflow on failure if: failure() From 2a8869ee4c2e4d3952fe09b630622d5f2622120f Mon Sep 17 00:00:00 2001 From: jappeace-sloth Date: Sun, 26 Apr 2026 18:22:25 +0000 Subject: [PATCH 06/10] Fix iOS SIGILL on pre-A13 devices: default to -mcpu=apple-a12 Add deviceCpu parameter (default "apple-a12") to iOS/watchOS build pipeline. This constrains the instruction set to avoid ARMv8.4+ ops (UDOT/SDOT) that crash on A12/A12X devices. Three layers of C code are covered: - Hatter's own cbits: -optc -mcpu flag on ghc -staticlib - Haskell dependency C sources: mkDerivation overlay in ios-deps.nix injects --ghc-option=-optc-mcpu into configureFlags - C library deps (gmp, libffi): NIX_CFLAGS_COMPILE override The ios-sigill-check test is now a regression guard that passes when -mcpu=apple-a12 suppresses UDOT (confirming the fix works). Closes #216 Prompt: Implement the plan for fixing iOS SIGILL on pre-A13 devices (hatter#216) Tokens: ~50k input, ~5k output Co-Authored-By: Claude Opus 4.6 --- nix/ci.nix | 28 +++++++++++----------------- nix/ios-deps.nix | 13 +++++++++++++ nix/ios.nix | 5 +++-- nix/lib.nix | 24 +++++++++++++++++++++--- nix/watchos.nix | 5 +++-- 5 files changed, 51 insertions(+), 24 deletions(-) diff --git a/nix/ci.nix b/nix/ci.nix index f33c4087..f91895f0 100644 --- a/nix/ci.nix +++ b/nix/ci.nix @@ -40,16 +40,11 @@ let ios-lib = iosLib; watchos-lib = watchosLib; - # Issue #216: On Apple Silicon, clang targeting M1+ CPUs emits - # ARMv8.4+ instructions (UDOT/SDOT) that crash on pre-A13 iOS - # devices (A12/A12X). This test proves the vulnerability exists - # by compiling a canary with -mcpu=apple-m1 (what happens when - # code targets Apple Silicon) and verifying UDOT appears in the - # output. It also verifies -mcpu=apple-a12 suppresses UDOT, - # confirming that flag is the correct fix. - # - # The nix CC wrapper uses a generic aarch64 target, so we must - # explicitly pass -mcpu to demonstrate the issue. + # Issue #216: Regression guard for SIGILL on pre-A13 iOS devices. + # Verifies that -mcpu=apple-a12 suppresses ARMv8.4+ instructions + # (UDOT/SDOT) that -mcpu=apple-m1 emits. The build now defaults + # to deviceCpu="apple-a12", so this test confirms the fix works. + # Fails if A12 target unexpectedly produces UDOT. ios-sigill-check = pkgs.runCommand "ios-sigill-check" { nativeBuildInputs = [ pkgs.stdenv.cc pkgs.cctools ]; } ( @@ -87,12 +82,11 @@ let if [ "$M1_HAS_UDOT" = "true" ] && [ "$A12_HAS_UDOT" = "false" ]; then echo "" - echo "REPRODUCED: -mcpu=apple-m1 emits UDOT (crashes on A12)," - echo " -mcpu=apple-a12 does not (safe for A12)." - echo "Any C code compiled targeting Apple Silicon without -mcpu" - echo "constraint will SIGILL on pre-A13 iOS devices." + echo "VERIFIED: -mcpu=apple-m1 emits UDOT (would crash on A12)," + echo " -mcpu=apple-a12 does not (safe for A12)." + echo "The deviceCpu=apple-a12 build flag protects against this." echo "See https://github.com/jappeace/hatter/issues/216" - exit 1 + touch $out elif [ "$M1_HAS_UDOT" = "false" ]; then echo "" echo "INCONCLUSIVE: M1 target did not produce UDOT." @@ -100,8 +94,8 @@ let touch $out else echo "" - echo "UNEXPECTED: A12 target also produces UDOT — bug in test or clang." - touch $out + echo "FAIL: A12 target also produces UDOT — fix is ineffective." + exit 1 fi '' else '' echo "SKIP: not Apple Silicon (${builtins.currentSystem}), UDOT not relevant." diff --git a/nix/ios-deps.nix b/nix/ios-deps.nix index 1491f335..0cb6e203 100644 --- a/nix/ios-deps.nix +++ b/nix/ios-deps.nix @@ -15,6 +15,7 @@ , consumerCabal2Nix ? null , hpkgs ? (_: _: {}) # consumer haskellPackages overrides , hatterSrc ? null # hatter source tree (builds hatter as a normal dep) +, deviceCpu ? "apple-a12" # minimum CPU target for C compilations (issue #216) }: let pkgs = import sources.nixpkgs {}; @@ -41,10 +42,22 @@ let }); } else {}; + # Issue #216: Inject -mcpu into C compilations of Haskell dependencies + # (e.g. sqlite3.c in direct-sqlite) to avoid ARMv8.4+ instructions. + deviceCpuOverride = self: super: + if deviceCpu != null then { + mkDerivation = args: super.mkDerivation (args // { + configureFlags = (args.configureFlags or []) ++ [ + "--ghc-option=-optc-mcpu=${deviceCpu}" + ]; + }); + } else {}; + nativeHaskellPkgs = pkgs.haskellPackages.override { overrides = pkgs.lib.composeManyExtensions [ unwitchOverride hatterOverride + deviceCpuOverride hpkgs ]; }; diff --git a/nix/ios.nix b/nix/ios.nix index dfd50dff..64da2200 100644 --- a/nix/ios.nix +++ b/nix/ios.nix @@ -9,16 +9,17 @@ , consumerCabalFile ? null , consumerCabal2Nix ? null , hpkgs ? (_: _: {}) # consumer haskellPackages overrides +, deviceCpu ? "apple-a12" # minimum CPU target for device builds (issue #216) }: let lib = import ./lib.nix { inherit sources; }; iosDeps = import ./ios-deps.nix { - inherit sources consumerCabalFile consumerCabal2Nix hpkgs; + inherit sources consumerCabalFile consumerCabal2Nix hpkgs deviceCpu; hatterSrc = ../.; }; in lib.mkIOSLib { hatterSrc = ../.; - inherit mainModule simulator; + inherit mainModule simulator deviceCpu; crossDeps = iosDeps; } diff --git a/nix/lib.nix b/nix/lib.nix index 85d71294..40654c00 100644 --- a/nix/lib.nix +++ b/nix/lib.nix @@ -193,12 +193,28 @@ let , pname ? "hatter-${platform}" , extraModuleCopy ? "" , crossDeps ? null # output of ios-deps.nix (lib/, pkgdb/) + , deviceCpu ? "apple-a12" # minimum CPU target for device builds (issue #216) }: let mac2tool = import (hatterSrc + "/nix/mac2${platform}.nix") { inherit sources; pkgs = applePkgs; }; toolBin = "mac2${platform}"; + + # Issue #216: Constrain instruction set to deviceCpu on device builds + # to avoid ARMv8.4+ instructions (UDOT/SDOT) that crash on pre-A13. + useCpuFlag = !simulator && deviceCpu != null; + cpuFlag = if useCpuFlag then "-optc -mcpu=${deviceCpu}" else ""; + deviceGmpStatic = if useCpuFlag + then gmpStatic.overrideAttrs (old: { + NIX_CFLAGS_COMPILE = (old.NIX_CFLAGS_COMPILE or "") + " -mcpu=${deviceCpu}"; + }) + else gmpStatic; + deviceLibffiStatic = if useCpuFlag + then libffiStatic.overrideAttrs (old: { + NIX_CFLAGS_COMPILE = (old.NIX_CFLAGS_COMPILE or "") + " -mcpu=${deviceCpu}"; + }) + else libffiStatic; in applePkgs.stdenv.mkDerivation { inherit pname; @@ -207,7 +223,7 @@ let src = hatterSrc + "/src"; nativeBuildInputs = [ appleGhc applePkgs.cctools ]; - buildInputs = [ libffiStatic gmpStatic ]; + buildInputs = [ deviceLibffiStatic deviceGmpStatic ]; buildPhase = '' ${if crossDeps != null then '' @@ -223,6 +239,7 @@ let ghc -staticlib \ -O2 \ + ${cpuFlag} \ -o libHatter.a \ -I${hatterSrc}/include \ -package-db ${crossDeps}/pkgdb \ @@ -247,6 +264,7 @@ let ghc -staticlib \ -O2 \ + ${cpuFlag} \ -o libHatter.a \ -I${hatterSrc}/include \ -optl-lffi \ @@ -262,8 +280,8 @@ let echo "Merging static archives into libHatter.a" libtool -static -o libCombined.a libHatter.a \ - ${gmpStatic}/lib/libgmp.a \ - ${libffiStatic}/lib/libffi.a \ + ${deviceGmpStatic}/lib/libgmp.a \ + ${deviceLibffiStatic}/lib/libffi.a \ ${if crossDeps != null then "${crossDeps}/lib/*.a" else ""} mv libCombined.a libHatter.a diff --git a/nix/watchos.nix b/nix/watchos.nix index ff671a00..8d2c9960 100644 --- a/nix/watchos.nix +++ b/nix/watchos.nix @@ -5,16 +5,17 @@ , consumerCabalFile ? null , consumerCabal2Nix ? null , hpkgs ? (_: _: {}) # consumer haskellPackages overrides +, deviceCpu ? "apple-a12" # minimum CPU target for device builds (issue #216) }: let lib = import ./lib.nix { inherit sources; }; iosDeps = import ./ios-deps.nix { - inherit sources consumerCabalFile consumerCabal2Nix hpkgs; + inherit sources consumerCabalFile consumerCabal2Nix hpkgs deviceCpu; hatterSrc = ../.; }; in lib.mkWatchOSLib { hatterSrc = ../.; - inherit mainModule simulator; + inherit mainModule simulator deviceCpu; crossDeps = iosDeps; } From a9acfca7ff39da5868771b0cab4bfcf949a456dd Mon Sep 17 00:00:00 2001 From: jappeace-sloth Date: Mon, 27 Apr 2026 08:02:59 +0000 Subject: [PATCH 07/10] Revert "Fix iOS SIGILL on pre-A13 devices: default to -mcpu=apple-a12" This reverts commit 2a8869ee4c2e4d3952fe09b630622d5f2622120f. --- nix/ci.nix | 28 +++++++++++++++++----------- nix/ios-deps.nix | 13 ------------- nix/ios.nix | 5 ++--- nix/lib.nix | 24 +++--------------------- nix/watchos.nix | 5 ++--- 5 files changed, 24 insertions(+), 51 deletions(-) diff --git a/nix/ci.nix b/nix/ci.nix index f91895f0..f33c4087 100644 --- a/nix/ci.nix +++ b/nix/ci.nix @@ -40,11 +40,16 @@ let ios-lib = iosLib; watchos-lib = watchosLib; - # Issue #216: Regression guard for SIGILL on pre-A13 iOS devices. - # Verifies that -mcpu=apple-a12 suppresses ARMv8.4+ instructions - # (UDOT/SDOT) that -mcpu=apple-m1 emits. The build now defaults - # to deviceCpu="apple-a12", so this test confirms the fix works. - # Fails if A12 target unexpectedly produces UDOT. + # Issue #216: On Apple Silicon, clang targeting M1+ CPUs emits + # ARMv8.4+ instructions (UDOT/SDOT) that crash on pre-A13 iOS + # devices (A12/A12X). This test proves the vulnerability exists + # by compiling a canary with -mcpu=apple-m1 (what happens when + # code targets Apple Silicon) and verifying UDOT appears in the + # output. It also verifies -mcpu=apple-a12 suppresses UDOT, + # confirming that flag is the correct fix. + # + # The nix CC wrapper uses a generic aarch64 target, so we must + # explicitly pass -mcpu to demonstrate the issue. ios-sigill-check = pkgs.runCommand "ios-sigill-check" { nativeBuildInputs = [ pkgs.stdenv.cc pkgs.cctools ]; } ( @@ -82,11 +87,12 @@ let if [ "$M1_HAS_UDOT" = "true" ] && [ "$A12_HAS_UDOT" = "false" ]; then echo "" - echo "VERIFIED: -mcpu=apple-m1 emits UDOT (would crash on A12)," - echo " -mcpu=apple-a12 does not (safe for A12)." - echo "The deviceCpu=apple-a12 build flag protects against this." + echo "REPRODUCED: -mcpu=apple-m1 emits UDOT (crashes on A12)," + echo " -mcpu=apple-a12 does not (safe for A12)." + echo "Any C code compiled targeting Apple Silicon without -mcpu" + echo "constraint will SIGILL on pre-A13 iOS devices." echo "See https://github.com/jappeace/hatter/issues/216" - touch $out + exit 1 elif [ "$M1_HAS_UDOT" = "false" ]; then echo "" echo "INCONCLUSIVE: M1 target did not produce UDOT." @@ -94,8 +100,8 @@ let touch $out else echo "" - echo "FAIL: A12 target also produces UDOT — fix is ineffective." - exit 1 + echo "UNEXPECTED: A12 target also produces UDOT — bug in test or clang." + touch $out fi '' else '' echo "SKIP: not Apple Silicon (${builtins.currentSystem}), UDOT not relevant." diff --git a/nix/ios-deps.nix b/nix/ios-deps.nix index 0cb6e203..1491f335 100644 --- a/nix/ios-deps.nix +++ b/nix/ios-deps.nix @@ -15,7 +15,6 @@ , consumerCabal2Nix ? null , hpkgs ? (_: _: {}) # consumer haskellPackages overrides , hatterSrc ? null # hatter source tree (builds hatter as a normal dep) -, deviceCpu ? "apple-a12" # minimum CPU target for C compilations (issue #216) }: let pkgs = import sources.nixpkgs {}; @@ -42,22 +41,10 @@ let }); } else {}; - # Issue #216: Inject -mcpu into C compilations of Haskell dependencies - # (e.g. sqlite3.c in direct-sqlite) to avoid ARMv8.4+ instructions. - deviceCpuOverride = self: super: - if deviceCpu != null then { - mkDerivation = args: super.mkDerivation (args // { - configureFlags = (args.configureFlags or []) ++ [ - "--ghc-option=-optc-mcpu=${deviceCpu}" - ]; - }); - } else {}; - nativeHaskellPkgs = pkgs.haskellPackages.override { overrides = pkgs.lib.composeManyExtensions [ unwitchOverride hatterOverride - deviceCpuOverride hpkgs ]; }; diff --git a/nix/ios.nix b/nix/ios.nix index 64da2200..dfd50dff 100644 --- a/nix/ios.nix +++ b/nix/ios.nix @@ -9,17 +9,16 @@ , consumerCabalFile ? null , consumerCabal2Nix ? null , hpkgs ? (_: _: {}) # consumer haskellPackages overrides -, deviceCpu ? "apple-a12" # minimum CPU target for device builds (issue #216) }: let lib = import ./lib.nix { inherit sources; }; iosDeps = import ./ios-deps.nix { - inherit sources consumerCabalFile consumerCabal2Nix hpkgs deviceCpu; + inherit sources consumerCabalFile consumerCabal2Nix hpkgs; hatterSrc = ../.; }; in lib.mkIOSLib { hatterSrc = ../.; - inherit mainModule simulator deviceCpu; + inherit mainModule simulator; crossDeps = iosDeps; } diff --git a/nix/lib.nix b/nix/lib.nix index 40654c00..85d71294 100644 --- a/nix/lib.nix +++ b/nix/lib.nix @@ -193,28 +193,12 @@ let , pname ? "hatter-${platform}" , extraModuleCopy ? "" , crossDeps ? null # output of ios-deps.nix (lib/, pkgdb/) - , deviceCpu ? "apple-a12" # minimum CPU target for device builds (issue #216) }: let mac2tool = import (hatterSrc + "/nix/mac2${platform}.nix") { inherit sources; pkgs = applePkgs; }; toolBin = "mac2${platform}"; - - # Issue #216: Constrain instruction set to deviceCpu on device builds - # to avoid ARMv8.4+ instructions (UDOT/SDOT) that crash on pre-A13. - useCpuFlag = !simulator && deviceCpu != null; - cpuFlag = if useCpuFlag then "-optc -mcpu=${deviceCpu}" else ""; - deviceGmpStatic = if useCpuFlag - then gmpStatic.overrideAttrs (old: { - NIX_CFLAGS_COMPILE = (old.NIX_CFLAGS_COMPILE or "") + " -mcpu=${deviceCpu}"; - }) - else gmpStatic; - deviceLibffiStatic = if useCpuFlag - then libffiStatic.overrideAttrs (old: { - NIX_CFLAGS_COMPILE = (old.NIX_CFLAGS_COMPILE or "") + " -mcpu=${deviceCpu}"; - }) - else libffiStatic; in applePkgs.stdenv.mkDerivation { inherit pname; @@ -223,7 +207,7 @@ let src = hatterSrc + "/src"; nativeBuildInputs = [ appleGhc applePkgs.cctools ]; - buildInputs = [ deviceLibffiStatic deviceGmpStatic ]; + buildInputs = [ libffiStatic gmpStatic ]; buildPhase = '' ${if crossDeps != null then '' @@ -239,7 +223,6 @@ let ghc -staticlib \ -O2 \ - ${cpuFlag} \ -o libHatter.a \ -I${hatterSrc}/include \ -package-db ${crossDeps}/pkgdb \ @@ -264,7 +247,6 @@ let ghc -staticlib \ -O2 \ - ${cpuFlag} \ -o libHatter.a \ -I${hatterSrc}/include \ -optl-lffi \ @@ -280,8 +262,8 @@ let echo "Merging static archives into libHatter.a" libtool -static -o libCombined.a libHatter.a \ - ${deviceGmpStatic}/lib/libgmp.a \ - ${deviceLibffiStatic}/lib/libffi.a \ + ${gmpStatic}/lib/libgmp.a \ + ${libffiStatic}/lib/libffi.a \ ${if crossDeps != null then "${crossDeps}/lib/*.a" else ""} mv libCombined.a libHatter.a diff --git a/nix/watchos.nix b/nix/watchos.nix index 8d2c9960..ff671a00 100644 --- a/nix/watchos.nix +++ b/nix/watchos.nix @@ -5,17 +5,16 @@ , consumerCabalFile ? null , consumerCabal2Nix ? null , hpkgs ? (_: _: {}) # consumer haskellPackages overrides -, deviceCpu ? "apple-a12" # minimum CPU target for device builds (issue #216) }: let lib = import ./lib.nix { inherit sources; }; iosDeps = import ./ios-deps.nix { - inherit sources consumerCabalFile consumerCabal2Nix hpkgs deviceCpu; + inherit sources consumerCabalFile consumerCabal2Nix hpkgs; hatterSrc = ../.; }; in lib.mkWatchOSLib { hatterSrc = ../.; - inherit mainModule simulator deviceCpu; + inherit mainModule simulator; crossDeps = iosDeps; } From 6913ff6c3402605465004d5cd8f398e82361587b Mon Sep 17 00:00:00 2001 From: jappeace-sloth Date: Mon, 27 Apr 2026 08:13:13 +0000 Subject: [PATCH 08/10] Fix iOS SIGILL on pre-A13: deviceCpu=apple-a12 via build system Add deviceCpu parameter (default "apple-a12") to lib.nix module level. This constrains all iOS/watchOS C compilation to avoid ARMv8.4+ ops (UDOT/SDOT) that crash on A12/A12X devices. Three layers of C code are covered: - Hatter cbits: -optc -mcpu flag on ghc -staticlib (device only) - Haskell dependency C sources: mkDerivation overlay in ios-deps.nix injects --ghc-option=-optc-mcpu into configureFlags - C library deps (gmp, libffi): NIX_CFLAGS_COMPILE override Rewrites ios-sigill-check to compile the canary through the same GHC + flags as mkAppleStaticLib (via lib.compileIOSDeviceC), so the test exercises the actual build system instead of hardcoded -mcpu flags. Closes #216 Prompt: revert previous fix, rewrite reproduction test to use hatter build system so the fix flows through naturally Tokens: ~120k input, ~15k output Co-Authored-By: Claude Opus 4.6 --- .github/workflows/ci.yaml | 2 +- nix/ci.nix | 62 +++++++++------------------------------ nix/ios-deps.nix | 13 ++++++++ nix/ios.nix | 5 ++-- nix/lib.nix | 31 +++++++++++++++++--- nix/watchos.nix | 5 ++-- 6 files changed, 61 insertions(+), 57 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ba5be3cf..9e4b0169 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -99,7 +99,7 @@ jobs: - run: nix-build nix/ci.nix -A simulator-all -A ios-lib - name: Run combined simulator test (lifecycle + UI + buttons + scroll) run: nix-build nix/ci.nix -A simulator-all -o result-simulator-all && ./result-simulator-all/bin/test-all-ios - - name: "Repro #216: detect SIGILL-prone instructions in default clang output" + - name: "Guard #216: verify no UDOT/SDOT in iOS device compilation" run: nix-build nix/ci.nix -A ios-sigill-check - name: Cancel workflow on failure if: failure() diff --git a/nix/ci.nix b/nix/ci.nix index f33c4087..38896d59 100644 --- a/nix/ci.nix +++ b/nix/ci.nix @@ -35,38 +35,19 @@ let isAppleSilicon = builtins.currentSystem == "aarch64-darwin"; iosLib = import ./ios.nix { inherit sources; }; watchosLib = import ./watchos.nix { inherit sources; }; + lib = import ./lib.nix { inherit sources; }; canary = ../test/ios/sigill_canary.c; in { ios-lib = iosLib; watchos-lib = watchosLib; - # Issue #216: On Apple Silicon, clang targeting M1+ CPUs emits - # ARMv8.4+ instructions (UDOT/SDOT) that crash on pre-A13 iOS - # devices (A12/A12X). This test proves the vulnerability exists - # by compiling a canary with -mcpu=apple-m1 (what happens when - # code targets Apple Silicon) and verifying UDOT appears in the - # output. It also verifies -mcpu=apple-a12 suppresses UDOT, - # confirming that flag is the correct fix. - # - # The nix CC wrapper uses a generic aarch64 target, so we must - # explicitly pass -mcpu to demonstrate the issue. - ios-sigill-check = pkgs.runCommand "ios-sigill-check" { - nativeBuildInputs = [ pkgs.stdenv.cc pkgs.cctools ]; - } ( + # Issue #216: Verify iOS device C compilation doesn't emit ARMv8.4+ + # instructions (UDOT/SDOT) that crash on pre-A13 devices (A12/A12X). + # Compiles a canary through the same GHC + flags as mkAppleStaticLib. + ios-sigill-check = pkgs.runCommand "ios-sigill-check" {} ( if isAppleSilicon then '' - echo "=== Compile targeting Apple M1 (simulates host-CPU targeting) ===" - cc -c -O2 -mcpu=apple-m1 -o canary_m1.o ${canary} - otool -tv canary_m1.o > disasm_m1.txt - cat disasm_m1.txt - - echo "" - echo "=== Compile targeting Apple A12 (minimum for iOS 17+) ===" - cc -c -O2 -mcpu=apple-a12 -o canary_a12.o ${canary} - otool -tv canary_a12.o > disasm_a12.txt - cat disasm_a12.txt - - echo "" - echo "=== Results ===" + echo "=== Disassembly of canary compiled for iOS device ===" + cat ${lib.compileIOSDeviceC canary} # Detect UDOT/SDOT: either as a mnemonic or as a raw .long # encoding (otool prints .long when it doesn't know the opcode). @@ -77,32 +58,17 @@ let return 1 } - M1_HAS_UDOT=false - A12_HAS_UDOT=false - if has_dotprod disasm_m1.txt; then M1_HAS_UDOT=true; fi - if has_dotprod disasm_a12.txt; then A12_HAS_UDOT=true; fi - - echo "M1 target produces UDOT/SDOT: $M1_HAS_UDOT" - echo "A12 target produces UDOT/SDOT: $A12_HAS_UDOT" - - if [ "$M1_HAS_UDOT" = "true" ] && [ "$A12_HAS_UDOT" = "false" ]; then + if has_dotprod ${lib.compileIOSDeviceC canary}; then echo "" - echo "REPRODUCED: -mcpu=apple-m1 emits UDOT (crashes on A12)," - echo " -mcpu=apple-a12 does not (safe for A12)." - echo "Any C code compiled targeting Apple Silicon without -mcpu" - echo "constraint will SIGILL on pre-A13 iOS devices." + echo "FAIL: iOS device C compilation emits UDOT/SDOT." + echo "These crash on pre-A13 devices (A12/A12X)." echo "See https://github.com/jappeace/hatter/issues/216" exit 1 - elif [ "$M1_HAS_UDOT" = "false" ]; then - echo "" - echo "INCONCLUSIVE: M1 target did not produce UDOT." - echo "Canary may need updating for this clang version." - touch $out - else - echo "" - echo "UNEXPECTED: A12 target also produces UDOT — bug in test or clang." - touch $out fi + + echo "" + echo "OK: No UDOT/SDOT detected in iOS device C compilation." + touch $out '' else '' echo "SKIP: not Apple Silicon (${builtins.currentSystem}), UDOT not relevant." touch $out diff --git a/nix/ios-deps.nix b/nix/ios-deps.nix index 1491f335..0cb6e203 100644 --- a/nix/ios-deps.nix +++ b/nix/ios-deps.nix @@ -15,6 +15,7 @@ , consumerCabal2Nix ? null , hpkgs ? (_: _: {}) # consumer haskellPackages overrides , hatterSrc ? null # hatter source tree (builds hatter as a normal dep) +, deviceCpu ? "apple-a12" # minimum CPU target for C compilations (issue #216) }: let pkgs = import sources.nixpkgs {}; @@ -41,10 +42,22 @@ let }); } else {}; + # Issue #216: Inject -mcpu into C compilations of Haskell dependencies + # (e.g. sqlite3.c in direct-sqlite) to avoid ARMv8.4+ instructions. + deviceCpuOverride = self: super: + if deviceCpu != null then { + mkDerivation = args: super.mkDerivation (args // { + configureFlags = (args.configureFlags or []) ++ [ + "--ghc-option=-optc-mcpu=${deviceCpu}" + ]; + }); + } else {}; + nativeHaskellPkgs = pkgs.haskellPackages.override { overrides = pkgs.lib.composeManyExtensions [ unwitchOverride hatterOverride + deviceCpuOverride hpkgs ]; }; diff --git a/nix/ios.nix b/nix/ios.nix index dfd50dff..d9f8b410 100644 --- a/nix/ios.nix +++ b/nix/ios.nix @@ -9,11 +9,12 @@ , consumerCabalFile ? null , consumerCabal2Nix ? null , hpkgs ? (_: _: {}) # consumer haskellPackages overrides +, deviceCpu ? "apple-a12" # minimum CPU target for device builds (issue #216) }: let - lib = import ./lib.nix { inherit sources; }; + lib = import ./lib.nix { inherit sources deviceCpu; }; iosDeps = import ./ios-deps.nix { - inherit sources consumerCabalFile consumerCabal2Nix hpkgs; + inherit sources consumerCabalFile consumerCabal2Nix hpkgs deviceCpu; hatterSrc = ../.; }; in diff --git a/nix/lib.nix b/nix/lib.nix index 85d71294..c1369bf6 100644 --- a/nix/lib.nix +++ b/nix/lib.nix @@ -11,7 +11,7 @@ # Usage: # let lib = import ./lib.nix { sources = import ../npins; }; # in lib.mkAndroidLib { hatterSrc = ../.; mainModule = ../test/ScrollDemoMain.hs; } -{ sources, androidArch ? "aarch64" }: +{ sources, androidArch ? "aarch64", deviceCpu ? "apple-a12" }: let archConfig = { aarch64 = { @@ -72,13 +72,21 @@ let # --- Apple (iOS/watchOS) shared infrastructure --- applePkgs = import sources.nixpkgs {}; appleGhc = applePkgs.haskellPackages.ghc; + + # Issue #216: Constrain instruction set to deviceCpu on device builds + # to prevent ARMv8.4+ instructions (UDOT/SDOT) that crash on pre-A13. + iosDeviceCpuFlag = if deviceCpu != null then "-optc -mcpu=${deviceCpu}" else ""; + iosCFlags = if deviceCpu != null then "-mcpu=${deviceCpu}" else ""; + gmpStatic = applePkgs.gmp.overrideAttrs (old: { dontDisableStatic = true; - }); + } // (if iosCFlags != "" then { + NIX_CFLAGS_COMPILE = (old.NIX_CFLAGS_COMPILE or "") + " ${iosCFlags}"; + } else {})); # Apple's libffi (v40) only ships .dylib — no static archive. # Build GNU libffi from source with --enable-static for bundling # into the iOS fat archive (mac2ios patches the platform tag). - libffiStatic = applePkgs.stdenv.mkDerivation { + libffiStatic = applePkgs.stdenv.mkDerivation ({ pname = "libffi-static"; version = "3.5.2"; src = applePkgs.fetchurl { @@ -86,7 +94,9 @@ let hash = "sha256-86MIKiOzfCk6T80QUxR7Nx8v+R+n6hsqUuM1Z2usgtw="; }; configureFlags = [ "--enable-static" "--disable-shared" ]; - }; + } // (if iosCFlags != "" then { + NIX_CFLAGS_COMPILE = "${iosCFlags}"; + } else {})); # ------------------------------------------------------------------------- # Shared data lists — single source of truth for modules, sources, headers @@ -223,6 +233,7 @@ let ghc -staticlib \ -O2 \ + ${if !simulator then iosDeviceCpuFlag else ""} \ -o libHatter.a \ -I${hatterSrc}/include \ -package-db ${crossDeps}/pkgdb \ @@ -247,6 +258,7 @@ let ghc -staticlib \ -O2 \ + ${if !simulator then iosDeviceCpuFlag else ""} \ -o libHatter.a \ -I${hatterSrc}/include \ -optl-lffi \ @@ -703,4 +715,15 @@ in { inherit name; }; + # --------------------------------------------------------------------------- + # compileIOSDeviceC: Compile a C file the same way mkAppleStaticLib does for + # device cbits. Used by ios-sigill-check to verify no UDOT/SDOT appears. + # --------------------------------------------------------------------------- + compileIOSDeviceC = src: applePkgs.runCommand "ios-device-c-obj" { + nativeBuildInputs = [ appleGhc applePkgs.cctools ]; + } '' + ghc -c -O2 ${iosDeviceCpuFlag} -o compiled.o ${src} + otool -tv compiled.o > $out + ''; + } diff --git a/nix/watchos.nix b/nix/watchos.nix index ff671a00..df4007a6 100644 --- a/nix/watchos.nix +++ b/nix/watchos.nix @@ -5,11 +5,12 @@ , consumerCabalFile ? null , consumerCabal2Nix ? null , hpkgs ? (_: _: {}) # consumer haskellPackages overrides +, deviceCpu ? "apple-a12" # minimum CPU target for device builds (issue #216) }: let - lib = import ./lib.nix { inherit sources; }; + lib = import ./lib.nix { inherit sources deviceCpu; }; iosDeps = import ./ios-deps.nix { - inherit sources consumerCabalFile consumerCabal2Nix hpkgs; + inherit sources consumerCabalFile consumerCabal2Nix hpkgs deviceCpu; hatterSrc = ../.; }; in From 89e49660b727a3a262f66f91e909421af85b54f2 Mon Sep 17 00:00:00 2001 From: jappeace-sloth Date: Mon, 27 Apr 2026 20:28:01 +0000 Subject: [PATCH 09/10] Retrigger CI: watchos simulator test was cancelled Co-Authored-By: Claude Opus 4.6 From dec8a2bd8505f2bdafc1ed7a0a9ed3ad96b5630c Mon Sep 17 00:00:00 2001 From: jappeace-sloth Date: Mon, 27 Apr 2026 21:25:13 +0000 Subject: [PATCH 10/10] Make deviceCpu opt-in: default null, only ios-sigill-check uses it The deviceCpu=apple-a12 default was changing derivation hashes for all builds (including simulator), causing nix cache misses and slower watchOS simulator tests that timed out CI. Now deviceCpu defaults to null everywhere (no flag applied). Only the ios-sigill-check test in ci.nix explicitly passes deviceCpu=apple-a12 via libWithCpuFlag to prove the fix works. Consumers who need the pre-A13 protection can pass deviceCpu="apple-a12" explicitly. Prompt: make deviceCpu opt-in, only used by reproducer test Co-Authored-By: Claude Opus 4.6 --- nix/ci.nix | 12 +++++++----- nix/ios-deps.nix | 2 +- nix/ios.nix | 2 +- nix/lib.nix | 2 +- nix/watchos.nix | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/nix/ci.nix b/nix/ci.nix index 38896d59..05ab4376 100644 --- a/nix/ci.nix +++ b/nix/ci.nix @@ -36,6 +36,8 @@ let iosLib = import ./ios.nix { inherit sources; }; watchosLib = import ./watchos.nix { inherit sources; }; lib = import ./lib.nix { inherit sources; }; + # lib with deviceCpu set — only used by ios-sigill-check to prove the fix works + libWithCpuFlag = import ./lib.nix { inherit sources; deviceCpu = "apple-a12"; }; canary = ../test/ios/sigill_canary.c; in { ios-lib = iosLib; @@ -46,8 +48,8 @@ let # Compiles a canary through the same GHC + flags as mkAppleStaticLib. ios-sigill-check = pkgs.runCommand "ios-sigill-check" {} ( if isAppleSilicon then '' - echo "=== Disassembly of canary compiled for iOS device ===" - cat ${lib.compileIOSDeviceC canary} + echo "=== Disassembly of canary compiled for iOS device (with deviceCpu=apple-a12) ===" + cat ${libWithCpuFlag.compileIOSDeviceC canary} # Detect UDOT/SDOT: either as a mnemonic or as a raw .long # encoding (otool prints .long when it doesn't know the opcode). @@ -58,16 +60,16 @@ let return 1 } - if has_dotprod ${lib.compileIOSDeviceC canary}; then + if has_dotprod ${libWithCpuFlag.compileIOSDeviceC canary}; then echo "" - echo "FAIL: iOS device C compilation emits UDOT/SDOT." + echo "FAIL: iOS device C compilation emits UDOT/SDOT even with deviceCpu=apple-a12." echo "These crash on pre-A13 devices (A12/A12X)." echo "See https://github.com/jappeace/hatter/issues/216" exit 1 fi echo "" - echo "OK: No UDOT/SDOT detected in iOS device C compilation." + echo "OK: No UDOT/SDOT detected when deviceCpu=apple-a12 is set." touch $out '' else '' echo "SKIP: not Apple Silicon (${builtins.currentSystem}), UDOT not relevant." diff --git a/nix/ios-deps.nix b/nix/ios-deps.nix index 0cb6e203..7c14b7da 100644 --- a/nix/ios-deps.nix +++ b/nix/ios-deps.nix @@ -15,7 +15,7 @@ , consumerCabal2Nix ? null , hpkgs ? (_: _: {}) # consumer haskellPackages overrides , hatterSrc ? null # hatter source tree (builds hatter as a normal dep) -, deviceCpu ? "apple-a12" # minimum CPU target for C compilations (issue #216) +, deviceCpu ? null # optional CPU target for C compilations (issue #216) }: let pkgs = import sources.nixpkgs {}; diff --git a/nix/ios.nix b/nix/ios.nix index d9f8b410..6dc9f8f8 100644 --- a/nix/ios.nix +++ b/nix/ios.nix @@ -9,7 +9,7 @@ , consumerCabalFile ? null , consumerCabal2Nix ? null , hpkgs ? (_: _: {}) # consumer haskellPackages overrides -, deviceCpu ? "apple-a12" # minimum CPU target for device builds (issue #216) +, deviceCpu ? null # optional CPU target for device builds (issue #216) }: let lib = import ./lib.nix { inherit sources deviceCpu; }; diff --git a/nix/lib.nix b/nix/lib.nix index c1369bf6..cb6e5056 100644 --- a/nix/lib.nix +++ b/nix/lib.nix @@ -11,7 +11,7 @@ # Usage: # let lib = import ./lib.nix { sources = import ../npins; }; # in lib.mkAndroidLib { hatterSrc = ../.; mainModule = ../test/ScrollDemoMain.hs; } -{ sources, androidArch ? "aarch64", deviceCpu ? "apple-a12" }: +{ sources, androidArch ? "aarch64", deviceCpu ? null }: let archConfig = { aarch64 = { diff --git a/nix/watchos.nix b/nix/watchos.nix index df4007a6..3ebe1e8a 100644 --- a/nix/watchos.nix +++ b/nix/watchos.nix @@ -5,7 +5,7 @@ , consumerCabalFile ? null , consumerCabal2Nix ? null , hpkgs ? (_: _: {}) # consumer haskellPackages overrides -, deviceCpu ? "apple-a12" # minimum CPU target for device builds (issue #216) +, deviceCpu ? null # optional CPU target for device builds (issue #216) }: let lib = import ./lib.nix { inherit sources deviceCpu; };