Skip to content

Commit 18099ca

Browse files
committed
feat(dist-apple): the closure's dylibs in the framework directory, the link-time rpath, ad-hoc signing, the app runner and --format dmg (mcpp#634)
The dylibs the engine stages beside a Mach-O program (2026.9.14.2+), named by the stage manifest's `needs` lines, are copied into Contents/Frameworks/ (Frameworks/ on iOS) and kept out of the resource directory. generate() adds -Wl,-rpath,@executable_path/../Frameworks on macOS and @executable_path/Frameworks on iOS through mcpp::link_flag, on every pass, because the link happens before the pass that learns --format; no load command is edited after the link. A macOS bundle without an identity is signed ad hoc, frameworks first and the bundle second; the iOS device row signs only with an identity and the simulator row never. An incomplete closure is a warning naming the unresolved libraries, and every refusal is a mcpp::warning. On macOS the member supplies the runner named `app` (macapp-run) and declares xim:macapp-run 0.1.0 with when = "run". --format dmg stages the bundle beside an Applications link and runs hdiutil create -format UDZO; it is refused on iOS. tests/app-framework-consumer: a program whose dependency is shared and which exits 7. check-apple-plan.sh passes locally against the new member and fails against 0.9.3 ("no framework step for the staged dylib"); check-apple-bundle.sh is the macOS half (load command, codesign --verify --deep --strict, the program with and without its framework, mcpp run --format app with and without --runner app, hdiutil verify and attach).
1 parent 3c10cbc commit 18099ca

11 files changed

Lines changed: 700 additions & 84 deletions

File tree

dist/apple.cppm

Lines changed: 284 additions & 81 deletions
Large diffs are not rendered by default.

mcpp.toml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,18 @@ implies = ["surface"]
391391
[target.windows.feature-xlings.dist-wix]
392392
"xim:wix" = "5.0.2"
393393

394-
# `dist-apple` declares no payload for `codesign`: it is part of Xcode, which is
395-
# not redistributable, so the member locates it and says where it looked. The
396-
# open-source `rcodesign` is the package that would replace that lookup.
394+
# `dist-apple` declares no payload for `codesign`, `ditto` or `hdiutil`: they are
395+
# part of macOS and Xcode, which are not redistributable, so the member runs the
396+
# system's. The open-source `rcodesign` is the package that would replace the
397+
# `codesign` lookup.
398+
#
399+
# THE RUNNER IS A PAYLOAD, AND ONLY `mcpp run` NEEDS IT. `mcpp run --format app`
400+
# on macOS reaches the bundle through the runner named `app` this member
401+
# supplies, `macapp-run`, which executes the bundle's executable in the
402+
# foreground so that its output and exit status are the program's. `when =
403+
# "run"` keeps a build or a pack from installing it.
404+
[target.'cfg(os = "macos")'.feature-xlings.dist-apple]
405+
"xim:macapp-run" = { version = "0.1.0", when = "run" }
397406

398407
# ── The environment `dist-apk` needs ───────────────────────────────────────
399408
#
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// No `identity`: the bundle is signed ad hoc on macOS, and the fixture
2+
// declares no runner, so `mcpp run --format app` reaches the bundle through the
3+
// runner `dist-apple` supplies.
4+
import std;
5+
import mcpp;
6+
import mcpp.dist.apple;
7+
8+
int main() {
9+
mcpp::dist::apple::options opt;
10+
opt.target = "app-framework-consumer";
11+
opt.app_name = "AppFrameworkConsumer";
12+
return mcpp::dist::apple::generate(opt) ? 0 : 1;
13+
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#!/usr/bin/env bash
2+
# dist-apple on macOS, measured on the bundle and the image (mcpp#634, B1 to B3).
3+
#
4+
# The plan-level half is `check-apple-plan.sh`; this half needs the tools only
5+
# a Mac has (`otool`, `codesign`, `hdiutil`) and runs the program.
6+
#
7+
# 1. The program is linked with the rpath `@executable_path/../Frameworks`,
8+
# as written: the engine anchors no rpath that begins with a loader token
9+
# (mcpp 2026.9.14.2+), and the member adds it through `mcpp::link_flag`.
10+
# 2. The bundle carries the dependency's dylib in `Contents/Frameworks/` and
11+
# not among the resources, keeps the deployed file under
12+
# `Contents/Resources/`, and is signed ad hoc so that `codesign --verify
13+
# --deep --strict` accepts it.
14+
# 3. The bundled program loads the framework copy and exits 7 with its
15+
# output; a copy of the bundle without the framework stops with "Library
16+
# not loaded".
17+
# 4. `mcpp run --format app`, with no runner in the manifest, runs the bundle
18+
# through `macapp-run` and returns the program's 7 with its output and
19+
# arguments; `--runner app` does the same.
20+
# 5. `mcpp pack --format dmg` writes an image `hdiutil verify` accepts, which
21+
# attaches read-only holding the bundle and an `Applications` link.
22+
#
23+
# Usage: MCPP=<mcpp 2026.9.14.2+> ./check-apple-bundle.sh (run from this directory)
24+
set -eu
25+
26+
MCPP="${MCPP:-mcpp}"
27+
NAME=AppFrameworkConsumer
28+
EXE=app-framework-consumer
29+
DYLIB=libapp-framework-dep.dylib
30+
fail() { echo "FAIL: $1"; shift; for f in "$@"; do echo "--- $f ---"; cat "$f" 2>/dev/null; done; exit 1; }
31+
reading() { printf 'READING %s: %s\n' "$1" "$2"; }
32+
packed() { sed -n 's/^ *Packed //p' "$1" | tail -1; }
33+
work=$(mktemp -d)
34+
35+
# ── 1. the rpath, at link time ─────────────────────────────────────────────
36+
echo "== 1. the program's rpath =="
37+
rm -rf target
38+
"$MCPP" build > bundle-build.log 2>&1 || fail "mcpp build failed" bundle-build.log
39+
if find target -name '*.app' | grep -q .; then fail "a plain build produced a bundle"; fi
40+
programs=$(find target -type f -name "$EXE" ! -path '*/.build-mcpp/*')
41+
[ "$(printf '%s\n' "$programs" | grep -c .)" = 1 ] \
42+
|| fail "expected one linked $EXE under target/, found: $(echo $programs)" bundle-build.log
43+
otool -l "$programs" > bundle-loadcommands.log
44+
rpaths=$(awk '/cmd LC_RPATH/ { getline; getline; print $2 }' bundle-loadcommands.log)
45+
reading rpaths "$(echo $rpaths)"
46+
printf '%s\n' "$rpaths" | grep -qxF '@executable_path/../Frameworks' \
47+
|| fail "the program has no LC_RPATH @executable_path/../Frameworks" bundle-loadcommands.log
48+
if printf '%s\n' "$rpaths" | grep -q '.@executable_path'; then
49+
fail "an rpath carries @executable_path after a directory, anchored" bundle-loadcommands.log
50+
fi
51+
otool -L "$programs" > bundle-needed.log
52+
grep -q "@rpath/$DYLIB" bundle-needed.log || fail "the program does not load @rpath/$DYLIB" bundle-needed.log
53+
echo "ok: LC_RPATH @executable_path/../Frameworks, as written, and the dependency is @rpath/$DYLIB"
54+
55+
# ── 2. the bundle ──────────────────────────────────────────────────────────
56+
echo "== 2. the bundle carries the framework and is signed ad hoc =="
57+
"$MCPP" pack --format app > bundle-pack.log 2>&1 || fail "mcpp pack --format app failed" bundle-pack.log
58+
app=$(packed bundle-pack.log)
59+
case "$app" in *"/$NAME.app") ;; *) fail "the pack reported '$app', not $NAME.app" bundle-pack.log ;; esac
60+
[ -d "$app" ] || fail "the reported bundle $app is not a directory" bundle-pack.log
61+
[ -f "$app/Contents/Frameworks/$DYLIB" ] || { find "$app" | sort; fail "no Contents/Frameworks/$DYLIB"; }
62+
if find "$app/Contents/Resources" "$app/Contents/MacOS" -name '*.dylib' 2>/dev/null | grep -q .; then
63+
find "$app" | sort; fail "a dylib is under Contents/Resources or Contents/MacOS"
64+
fi
65+
[ -f "$app/Contents/Resources/data/greeting.txt" ] || { find "$app" | sort; fail "the deployed file is not under Contents/Resources"; }
66+
codesign --verify --deep --strict --verbose=2 "$app" > bundle-codesign.log 2>&1 \
67+
|| fail "codesign --verify --deep --strict refused the bundle" bundle-codesign.log
68+
reading codesign-verify "$(tr '\n' ' ' < bundle-codesign.log)"
69+
# A linked arm64 program is already signed ad hoc by the linker, so the bundle's
70+
# own signature is read from its sealed resources, and the framework's from
71+
# the absence of the linker's flag.
72+
codesign -dv "$app" > bundle-signature.log 2>&1 || true
73+
reading bundle-signature "$(grep -E '^(Signature|CodeDirectory|Sealed Resources)' bundle-signature.log | tr '\n' ' ')"
74+
grep -q '^Signature=adhoc' bundle-signature.log || fail "the bundle's signature is not ad hoc" bundle-signature.log
75+
grep -q '^Sealed Resources' bundle-signature.log || fail "the bundle's resources are not sealed" bundle-signature.log
76+
codesign -dv "$app/Contents/Frameworks/$DYLIB" > bundle-framework-signature.log 2>&1 || true
77+
reading framework-signature "$(grep -E '^(Signature|CodeDirectory)' bundle-framework-signature.log | tr '\n' ' ')"
78+
grep -q '^Signature=adhoc' bundle-framework-signature.log \
79+
|| fail "the framework is not signed" bundle-framework-signature.log
80+
if grep -q 'linker-signed' bundle-framework-signature.log; then
81+
fail "the framework carries the linker's signature, not one of its own" bundle-framework-signature.log
82+
fi
83+
echo "ok: Contents/Frameworks/$DYLIB, nothing loadable among the resources, and codesign --verify --deep --strict passes"
84+
85+
# ── 3. the bundled program ─────────────────────────────────────────────────
86+
echo "== 3. the bundled program loads the framework =="
87+
rc=0
88+
DYLD_PRINT_LIBRARIES=1 "$app/Contents/MacOS/$EXE" > bundle-run.out 2> bundle-run.err || rc=$?
89+
reading bundle-run "exit=$rc $(cat bundle-run.out)"
90+
[ "$rc" -eq 7 ] || fail "the bundled program exited $rc, not 7" bundle-run.out bundle-run.err
91+
grep -qx 'framework-1-2-3 argc=1' bundle-run.out || fail "the bundled program's output is missing" bundle-run.out
92+
loaded=$(grep "$DYLIB" bundle-run.err | head -1)
93+
reading loaded "$loaded"
94+
case "$loaded" in *"/$NAME.app/Contents/Frameworks/$DYLIB") ;;
95+
*) fail "the program did not load the framework copy" bundle-run.err ;; esac
96+
cp -R "$app" "$work/"
97+
rm "$work/$NAME.app/Contents/Frameworks/$DYLIB"
98+
rc=0
99+
"$work/$NAME.app/Contents/MacOS/$EXE" > bundle-noframework.out 2>&1 || rc=$?
100+
reading without-framework "exit=$rc $(head -2 bundle-noframework.out | tr '\n' ' ')"
101+
[ "$rc" -ne 0 ] || fail "the program ran without its framework" bundle-noframework.out
102+
grep -q 'Library not loaded' bundle-noframework.out || fail "the failure is not 'Library not loaded'" bundle-noframework.out
103+
echo "ok: exit 7 through the framework copy; without it, exit $rc and 'Library not loaded'"
104+
105+
# ── 4. mcpp run --format app ───────────────────────────────────────────────
106+
echo "== 4. mcpp run --format app, through the runner dist-apple supplies =="
107+
if grep -q 'runner' mcpp.toml; then fail "the fixture's manifest names a runner" mcpp.toml; fi
108+
# mcpp_run <variant> <mcpp run arguments...>
109+
mcpp_run() {
110+
local variant="$1"; shift
111+
rc=0
112+
"$MCPP" run "$@" > "bundle-mcpp-run-$variant.log" 2>&1 || rc=$?
113+
reading "mcpp-run-$variant" "exit=$rc $(grep -m1 'Running' "bundle-mcpp-run-$variant.log" || echo 'no Running line')"
114+
[ "$rc" -eq 7 ] || fail "mcpp run $* exited $rc, not 7" "bundle-mcpp-run-$variant.log"
115+
grep -q 'Running `.*macapp-run' "bundle-mcpp-run-$variant.log" \
116+
|| fail "the status line does not name macapp-run" "bundle-mcpp-run-$variant.log"
117+
grep -qx 'framework-1-2-3 argc=2' "bundle-mcpp-run-$variant.log" \
118+
|| fail "the program's output with one argument is missing" "bundle-mcpp-run-$variant.log"
119+
}
120+
mcpp_run format --format app -- extra
121+
mcpp_run runner --format app --runner app -- extra
122+
echo "ok: mcpp run --format app, and with --runner app, return 7 with the program's output and argument"
123+
124+
# ── 5. the disk image ──────────────────────────────────────────────────────
125+
echo "== 5. mcpp pack --format dmg =="
126+
"$MCPP" pack --format dmg > bundle-dmg.log 2>&1 || fail "mcpp pack --format dmg failed" bundle-dmg.log
127+
dmg=$(packed bundle-dmg.log)
128+
case "$dmg" in *"/$NAME.dmg") ;; *) fail "the pack reported '$dmg', not $NAME.dmg" bundle-dmg.log ;; esac
129+
[ -f "$dmg" ] || fail "the reported image $dmg does not exist" bundle-dmg.log
130+
hdiutil verify "$dmg" > bundle-hdiutil-verify.log 2>&1 || fail "hdiutil verify refused the image" bundle-hdiutil-verify.log
131+
reading hdiutil-verify "$(grep -i 'checksum' bundle-hdiutil-verify.log | tail -1)"
132+
mnt="$work/mnt"
133+
mkdir -p "$mnt"
134+
hdiutil attach -nobrowse -readonly -mountpoint "$mnt" "$dmg" > bundle-attach.log 2>&1 \
135+
|| fail "hdiutil attach failed" bundle-attach.log
136+
detach() { hdiutil detach "$mnt" > /dev/null 2>&1 || hdiutil detach -force "$mnt" > /dev/null 2>&1 || true; }
137+
trap detach EXIT
138+
reading image-root "$(ls -1 "$mnt" | tr '\n' ' ')"
139+
[ -x "$mnt/$NAME.app/Contents/MacOS/$EXE" ] || fail "the image does not hold the bundle's program"
140+
[ -f "$mnt/$NAME.app/Contents/Frameworks/$DYLIB" ] || fail "the image's bundle lacks the framework"
141+
[ -L "$mnt/Applications" ] || fail "the image holds no Applications link"
142+
[ "$(readlink "$mnt/Applications")" = /Applications ] || fail "the Applications link points to $(readlink "$mnt/Applications")"
143+
codesign --verify --deep --strict "$mnt/$NAME.app" > bundle-image-codesign.log 2>&1 \
144+
|| fail "the bundle inside the image does not verify" bundle-image-codesign.log
145+
detach
146+
trap - EXIT
147+
echo "ok: the image verifies and attaches read-only with the signed bundle and Applications -> /Applications"
148+
149+
echo "PASS: dist-apple's framework, rpath, ad-hoc signature, app runner and disk image, on the bundle"
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
#!/usr/bin/env bash
2+
# Plan-level check for dist-apple's closure, signing, runner and disk image on
3+
# the macOS row (mcpp#634, B1 to B3).
4+
#
5+
# The real bundle is measured on the macOS runner. This script measures, on any
6+
# host, what the compiled build program PLANS under the environment the engine
7+
# sets for `mcpp pack --format app` and `--format dmg` on macOS: the build
8+
# program's target accessors read that environment and nothing else, so a
9+
# process given the same variables takes the branches a real pack takes. The
10+
# staged tree and its stage manifest are fabricated in the shape the engine
11+
# writes (mcpp's docs/50, "The stage manifest").
12+
#
13+
# Usage: MCPP=<mcpp> ./check-apple-plan.sh (run from this directory)
14+
set -e
15+
16+
MCPP="${MCPP:-mcpp}"
17+
fail() { echo "FAIL: $1"; shift; for f in "$@"; do echo "--- $f ---"; cat "$f" 2>/dev/null; done; exit 1; }
18+
command -v python3 >/dev/null || fail "python3 is required to read the planned actions"
19+
20+
rm -rf target
21+
"$MCPP" build > build.log 2>&1 || fail "the host build failed to compile build.mcpp" build.log
22+
BIN=target/.build-mcpp/build.mcpp.bin
23+
[ -x "$BIN" ] || fail "no compiled build.mcpp.bin at $BIN" build.log
24+
25+
# stage_tree <closure> : a staged tree with the program, its dylib and a
26+
# deployed resource, and the stage manifest the engine writes for it.
27+
stage_tree() {
28+
local stage
29+
stage=$(mktemp -d)
30+
mkdir -p "$stage/bin/data"
31+
head -c 5000 /dev/urandom > "$stage/bin/app-framework-consumer"
32+
head -c 4000 /dev/urandom > "$stage/bin/libapp-framework-dep.dylib"
33+
echo hello > "$stage/bin/data/greeting.txt"
34+
{
35+
printf 'closure = %s\n' "$1"
36+
if [ "$1" = not-walked ]; then
37+
printf 'reason = the loader finds no file for @rpath/libmissing.dylib\n'
38+
fi
39+
printf 'needs\t/usr/lib/libSystem.B.dylib\tplatform\n'
40+
printf 'needs\t@rpath/libapp-framework-dep.dylib\tbin/libapp-framework-dep.dylib\n'
41+
if [ "$1" = not-walked ]; then
42+
printf 'needs\t@rpath/libmissing.dylib\tunresolved\n'
43+
fi
44+
printf '5000 bin/app-framework-consumer\n'
45+
printf '4000 bin/libapp-framework-dep.dylib\n'
46+
} > "$stage.stage-manifest"
47+
echo "$stage"
48+
}
49+
50+
# run_program <format> <os> <env> <stage> <log>
51+
run_program() {
52+
local out
53+
out=$(mktemp -d)
54+
env -i PATH="$PATH" \
55+
MCPP_PACK_FORMAT="$1" MCPP_TARGET_OS="$2" MCPP_TARGET_ENV="$3" \
56+
MCPP_PACK_STAGE_DIR="$4" MCPP_MANIFEST_DIR="$PWD" \
57+
MCPP_PKG_NAME=app-framework-consumer MCPP_PKG_VERSION=0.1.0 \
58+
MCPP_OUT_DIR="$out" \
59+
"$BIN" > "$5" 2>&1 || true
60+
}
61+
62+
# check <log> <python assertions reading `actions` (id -> action) and `lines`>
63+
check() {
64+
python3 - "$1" "$2" <<'PY' || exit 1
65+
import json, sys
66+
log, code = sys.argv[1], sys.argv[2]
67+
lines = open(log).read().splitlines()
68+
actions = {}
69+
for l in lines:
70+
if l.startswith("mcpp:action="):
71+
a = json.loads(l[len("mcpp:action="):])
72+
actions[a["id"]] = a
73+
def fail(msg):
74+
print("FAIL: " + msg)
75+
print("--- " + log + " ---")
76+
print("\n".join(lines))
77+
sys.exit(1)
78+
exec(code)
79+
PY
80+
}
81+
82+
echo "== --format app on macOS, with a staged dylib =="
83+
stage=$(stage_tree walked)
84+
run_program app macos "" "$stage" /tmp/apple-plan-app.log
85+
check /tmp/apple-plan-app.log '
86+
fw = actions.get("mcpp.dist.apple.framework.libapp-framework-dep.dylib")
87+
if not fw: fail("no framework step for the staged dylib")
88+
if not fw["outputs"] or not fw["outputs"][0].endswith("/AppFrameworkConsumer.app/Contents/Frameworks/libapp-framework-dep.dylib"):
89+
fail("the framework step does not write Contents/Frameworks/libapp-framework-dep.dylib")
90+
if fw["command"][-2:] != ["sign", "-"]:
91+
fail("the framework step does not sign ad hoc: " + repr(fw["command"]))
92+
if any(i.startswith("mcpp.dist.apple.resource.libapp") for i in actions):
93+
fail("the staged dylib is also planned as a resource")
94+
if "mcpp.dist.apple.resource.data" not in actions:
95+
fail("the deployed resource is not planned")
96+
sign = actions.get("mcpp.dist.apple.codesign")
97+
if not sign: fail("no codesign step on macOS without an identity")
98+
if sign["command"][:4] != ["codesign", "--force", "--sign", "-"] or "--timestamp" in sign["command"]:
99+
fail("the bundle is not signed ad hoc: " + repr(sign["command"]))
100+
if fw["outputs"][0] not in sign["inputs"]:
101+
fail("the bundle signature does not follow the framework")
102+
bundle = actions.get("mcpp.dist.apple.bundle")
103+
if not bundle or sign["outputs"][0] not in bundle["inputs"]:
104+
fail("the bundle step does not follow the signature")
105+
if any(k.startswith("mcpp.dist.apple.dmg") for k in actions):
106+
fail("--format app planned a disk image")
107+
if "mcpp:link-flag=-Wl,-rpath,@executable_path/../Frameworks" not in lines:
108+
fail("no framework rpath was emitted for the link")
109+
if "mcpp:runner-named=app:macapp-run" not in lines:
110+
fail("the app runner was not supplied")
111+
'
112+
echo "ok: the dylib is a framework signed ad hoc, not a resource; the bundle is signed after it; the rpath and the runner are declared"
113+
114+
echo "== --format dmg on macOS =="
115+
run_program dmg macos "" "$stage" /tmp/apple-plan-dmg.log
116+
check /tmp/apple-plan-dmg.log '
117+
bundle = actions.get("mcpp.dist.apple.bundle")
118+
st = actions.get("mcpp.dist.apple.dmg-stage")
119+
img = actions.get("mcpp.dist.apple.dmg")
120+
if not (bundle and st and img): fail("the disk image steps are not planned")
121+
if bundle["outputs"][0] not in st["inputs"]: fail("the image staging does not take the bundle")
122+
if st["outputs"][0] not in img["inputs"]: fail("hdiutil does not take the staging directory")
123+
cmd = img["command"]
124+
if cmd[:2] != ["hdiutil", "create"] or "UDZO" not in cmd or not cmd[-1].endswith("/AppFrameworkConsumer.dmg"):
125+
fail("the image command is not hdiutil create -format UDZO ... AppFrameworkConsumer.dmg: " + repr(cmd))
126+
consumed = set(i for a in actions.values() for i in a["inputs"])
127+
terminals = [a["id"] for a in actions.values() if not set(a["outputs"]) & consumed]
128+
if terminals != ["mcpp.dist.apple.dmg"]:
129+
fail("the image is not the sole terminal artifact: " + repr(terminals))
130+
'
131+
echo "ok: the bundle is staged beside the link and the .dmg is the sole terminal artifact"
132+
133+
echo "== an incomplete closure is reported =="
134+
stage2=$(stage_tree not-walked)
135+
run_program app macos "" "$stage2" /tmp/apple-plan-notwalked.log
136+
check /tmp/apple-plan-notwalked.log '
137+
if not any(l.startswith("mcpp:warning=") and "libmissing.dylib" in l and "closure is incomplete" in l for l in lines):
138+
fail("the incomplete closure is not reported, naming the unresolved library")
139+
if "mcpp.dist.apple.bundle" not in actions:
140+
fail("an incomplete closure stopped the bundle")
141+
'
142+
echo "ok: an incomplete closure is a warning naming the library, and the bundle is still planned"
143+
144+
echo "== --format dmg on iOS is refused =="
145+
run_program dmg ios sim "$stage" /tmp/apple-plan-dmg-ios.log
146+
check /tmp/apple-plan-dmg-ios.log '
147+
if actions: fail("an iOS disk image planned actions")
148+
if not any(l.startswith("mcpp:warning=") and "a .dmg is a macOS disk image" in l for l in lines):
149+
fail("the refusal is not a warning")
150+
'
151+
echo "ok: an iOS disk image is refused, as a warning"
152+
153+
echo "== the iOS simulator row =="
154+
run_program app ios sim "$stage" /tmp/apple-plan-ios.log
155+
check /tmp/apple-plan-ios.log '
156+
fw = actions.get("mcpp.dist.apple.framework.libapp-framework-dep.dylib")
157+
if not fw or not fw["outputs"][0].endswith("/AppFrameworkConsumer.app/Frameworks/libapp-framework-dep.dylib"):
158+
fail("the simulator bundle does not carry the dylib in Frameworks/")
159+
if fw["command"][-1] != "nosign": fail("the simulator framework is signed")
160+
if "mcpp.dist.apple.codesign" in actions: fail("the simulator bundle is signed")
161+
if "mcpp:link-flag=-Wl,-rpath,@executable_path/Frameworks" not in lines:
162+
fail("no iOS framework rpath was emitted")
163+
if any(l.startswith("mcpp:runner-named=app:") for l in lines):
164+
fail("the macOS runner was supplied on iOS")
165+
'
166+
echo "ok: the simulator bundle carries Frameworks/, unsigned, with the iOS rpath and no macOS runner"
167+
168+
echo "PASS: dist-apple's closure, signing, runner and disk image, at the plan level"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
const char* app_framework_dep_marker();

0 commit comments

Comments
 (0)