✓
Passing This code compiles and runs correctly.
Code
import std/build
import std/io
std/build:app { name: "Icon App", id: "org.koru.regtest.icon", version: "0.1", icon: "appicon.icns" }
std/io:print.ln("bundled icon input")
Supporting Files
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>CFBundleIdentifier</key><string>org.koru.regtest.icon</string><key>CFBundleName</key><string>Icon App</string><key>CFBundleDisplayName</key><string>Icon App</string><key>CFBundleExecutable</key><string>Icon App</string><key>CFBundlePackageType</key><string>APPL</string><key>NSPrincipalClass</key><string>NSApplication</string><key>LSMinimumSystemVersion</key><string>10.13</string><key>CFBundleIconFile</key><string>appicon</string><key>CFBundleShortVersionString</key><string>0.1</string><key>CFBundleVersion</key><string>0.1</string></dict></plist>APPL????<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Resources/appicon.icns</key>
<data>
4k/eyofXsvb5scgJk2m3udwn4JQ=
</data>
</dict>
<key>files2</key>
<dict>
<key>Resources/appicon.icns</key>
<dict>
<key>hash2</key>
<data>
26Jopz1llhlNCDtdIcw3aLT+TQbH2jD7sxwL8wASgNQ=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^Resources/</key>
<true/>
<key>^Resources/.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Resources/Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^.*</key>
<true/>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^Resources/</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^Resources/.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Resources/Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^[^/]+$</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>
Actual
bundled icon input
Expected output
bundled icon input
Flows
flow ~app click a branch to expand · @labels scroll to their anchor
app (source: name: "Icon App", id: "org.koru.regtest.icon", version: "0.1", icon: "appicon.icns")
flow ~print.ln click a branch to expand · @labels scroll to their anchor
print.ln (expr: "bundled icon input")
Test Configuration
MUST_RUN
Post-validation Script:
#!/bin/bash
# `icon:` on std/build:app must land the .icns in Contents/Resources and
# name it via CFBundleIconFile (basename minus extension) in the disk
# plist — and the embedded __TEXT,__info_plist must carry the same key,
# or codesign's cross-check would refuse.
set -u
APP="Icon App.app"
rm -rf "$APP" "Missing Icon.app" missing_icon.k missing.log
SCRATCH="$(mktemp -d)"
if ! koruc bundle "$KORU_INPUT" > bundle.log 2>&1; then
echo "FAIL: koruc bundle refused"
cat bundle.log
exit 1
fi
fail() { echo "FAIL: $1"; exit 1; }
[ -f "$APP/Contents/Resources/appicon.icns" ] || fail "no Contents/Resources/appicon.icns"
[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIconFile' "$APP/Contents/Info.plist")" = "appicon" ] \
|| fail "CFBundleIconFile mismatch"
plutil -lint "$APP/Contents/Info.plist" | grep -q "OK" || fail "Info.plist does not lint"
codesign --verify "$APP" 2> codesign.err || { cat codesign.err; fail "bundle does not verify"; }
# A missing icon file must refuse cleanly, not ship a bundle with a dead
# key. The probe lives in a scratch dir — a stray .k in the test dir is
# picked up by the fixture un-ignores.
cat > "$SCRATCH/missing_icon.k" <<'EOF'
import std/build
import std/io
std/build:app { name: "Missing Icon", id: "org.koru.regtest.iconmissing", icon: "nope.icns" }
std/io:print.ln("x")
EOF
( cd "$SCRATCH" && koruc bundle missing_icon.k ) > missing.log 2>&1 && fail "missing icon was not refused"
grep -q "app icon not found" missing.log || { cat missing.log; fail "wrong refusal for missing icon"; }
[ ! -d "$SCRATCH/Missing Icon.app" ] || fail "refusal still left a bundle"
echo "PASS: Icon App.app — icon in Resources, CFBundleIconFile, signature, missing-icon refusal"
exit 0