Use separate APE loader for x86_64 and arm on Apple Silicon

This commit is contained in:
BenceSzalai 2025-05-01 17:17:31 +02:00
parent 4ca513cba2
commit 03ca69148b
No known key found for this signature in database
GPG key ID: B1FC0240D2CD9A19
6 changed files with 33 additions and 3 deletions

View file

@ -613,6 +613,11 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-" .ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-"
.ascii APE_VERSION_STR .ascii APE_VERSION_STR
.ascii "\"\n" .ascii "\"\n"
#if SupportsXnu()
// Add an architecture suffix to the temporary APE Loader
// name to differentiate between x86_64 and arm64.
.ascii "[ -d /Applications ] && t=\"${t}-$(uname -m 2>/dev/null || printf 'unknown')\"\n"
#endif /* SupportsXnu() */
.ascii "[ -x \"$t\" ] || {\n" .ascii "[ -x \"$t\" ] || {\n"
.ascii "mkdir -p \"${t%/*}\" &&\n" .ascii "mkdir -p \"${t%/*}\" &&\n"
.ascii "dd if=\"$o\" of=\"$t.$$\" skip=" .ascii "dd if=\"$o\" of=\"$t.$$\" skip="

View file

@ -10,4 +10,12 @@
#define APE_VERSION_STR_(x, y) APE_VERSION_STR__(x, y) #define APE_VERSION_STR_(x, y) APE_VERSION_STR__(x, y)
#define APE_VERSION_NOTE_(x, y) (100000000 * (x) + 1000000 * (y)) #define APE_VERSION_NOTE_(x, y) (100000000 * (x) + 1000000 * (y))
#if defined(__x86_64__)
#define GetXnuSuffix() "-x86_64"
#elif defined(__aarch64__)
#define GetXnuSuffix() "-arm64"
#else
#define GetXnuSuffix() "-unknown"
#endif
#endif /* COSMOPOLITAN_APE_APE_H_ */ #endif /* COSMOPOLITAN_APE_APE_H_ */

View file

@ -132,7 +132,13 @@ int sys_execve(const char *prog, char *const argv[], char *const envp[]) {
RetryExecve("/usr/bin/ape", shargs, envp); RetryExecve("/usr/bin/ape", shargs, envp);
} }
char *buf = alloca(PATH_MAX); char *buf = alloca(PATH_MAX);
const char *name = "/.ape-" APE_VERSION_STR; const char *name = "";
if (IsXnu()) {
name = "/.ape-" APE_VERSION_STR GetXnuSuffix();
}
else {
name = "/.ape-" APE_VERSION_STR;
}
InitExecve(); InitExecve();
RetryExecve(Join(g_execve.tmpdir, name, buf), shargs, envp); RetryExecve(Join(g_execve.tmpdir, name, buf), shargs, envp);
RetryExecve(Join(g_execve.home, name, buf), shargs, envp); RetryExecve(Join(g_execve.home, name, buf), shargs, envp);

View file

@ -2016,7 +2016,13 @@ int main(int argc, char *argv[]) {
// otherwise try to use the ad-hoc self-extracted loader, securely // otherwise try to use the ad-hoc self-extracted loader, securely
if (loaders.n) { if (loaders.n) {
p = stpcpy(p, "t=\"${TMPDIR:-${HOME:-.}}/.ape-" APE_VERSION_STR "\"\n" p = stpcpy(p, "t=\"${TMPDIR:-${HOME:-.}}/.ape-" APE_VERSION_STR);
if (support_vector & _HOSTXNU) {
// Add the current architecture to the temporary APE Loader
// name to differentiate between x86_64 and arm64 Ape Loaders.
p = stpcpy(p, "$([ -d /Applications ] && ( printf '-'; ( uname -m 2>/dev/null || printf 'unknown')))");
}
p = stpcpy(p, "\"\n"
"[ x\"$1\" != x--assimilate ] && " "[ x\"$1\" != x--assimilate ] && "
"[ -x \"$t\" ] && " "[ -x \"$t\" ] && "
"exec \"$t\" \"$o\" \"$@\"\n"); "exec \"$t\" \"$o\" \"$@\"\n");

View file

@ -555,10 +555,14 @@ void ApplyFilesystemPolicy(unsigned long ipromises) {
if ((p = getenv("TMPDIR"))) { if ((p = getenv("TMPDIR"))) {
UnveilIfExists( UnveilIfExists(
__join_paths(buf, sizeof(buf), p, ".ape-" APE_VERSION_STR), "rx"); __join_paths(buf, sizeof(buf), p, ".ape-" APE_VERSION_STR), "rx");
UnveilIfExists(
__join_paths(buf, sizeof(buf), p, ".ape-" APE_VERSION_STR GetXnuSuffix()), "rx");
} }
if ((p = getenv("HOME"))) { if ((p = getenv("HOME"))) {
UnveilIfExists( UnveilIfExists(
__join_paths(buf, sizeof(buf), p, ".ape-" APE_VERSION_STR), "rx"); __join_paths(buf, sizeof(buf), p, ".ape-" APE_VERSION_STR), "rx");
UnveilIfExists(
__join_paths(buf, sizeof(buf), p, ".ape-" APE_VERSION_STR GetXnuSuffix()), "rx");
} }
} }
} }

View file

@ -136,7 +136,8 @@ On Apple Silicon, `aarch64-unknown-cosmo-cc` produces ELF binaries. If
you build a hello world program, then you need to say `ape ./hello`. If you build a hello world program, then you need to say `ape ./hello`. If
you don't have an `ape` command then run `cc -o ape bin/ape-m1.c` which you don't have an `ape` command then run `cc -o ape bin/ape-m1.c` which
should be moved to `/usr/local/bin/ape`. Your APE interpreter might should be moved to `/usr/local/bin/ape`. Your APE interpreter might
already exist under a path like `$TMPDIR/.ape-1.10`. It's important to already exist under a path like `$TMPDIR/.ape-1.10-arm64` or
`$TMPDIR/.ape-1.10-x86_64` if you are using Rosetta. It's important to
note this is only a gotcha for the cross compiler. Your `cosmocc` note this is only a gotcha for the cross compiler. Your `cosmocc`
compiler wraps the actual ELF binaries with a shell script that'll compiler wraps the actual ELF binaries with a shell script that'll
extract and compile an APE loader automatically, as needed. This also extract and compile an APE loader automatically, as needed. This also