Fix Android multicall build
ober
f1347baa0ea481e747c61a50ec3eb2cba1e00759
--- a/data/error-fixes.sexp +++ b/data/error-fixes.sexp @@ -2580,4 +2580,18 @@ ("pattern" . "mktemp: failed to create directory via template .*/tmp/.*: Permission denied") - ("type" . "build"))) + ("type" . "build")) + (("code_example" + . + "#if defined(__ANDROID__)\nstatic int *jerboa_errno_location(void) { return __errno(); }\nstatic int jerboa_ioctl(int fd, unsigned long request, void *arg) { return ioctl(fd, request, arg); }\nstatic mode_t jerboa_umask(mode_t mode) { return umask(mode); }\n#endif") + ("explanation" + . + "Bionic uses __errno instead of glibc's __errno_location and exposes some libc calls through clang overloadable/fortify declarations, making direct function-address registration ambiguous. A wrapper provides a single concrete symbol signature for Chez foreign-procedure lookup.") + ("fix" + . + "On Android/bionic, do not register libc symbols by taking direct addresses of bionic overloadable/fortified functions. Register small compatibility wrappers instead: map __errno_location to __errno(), wrap ioctl(int,unsigned long,void*), wrap variadic open(const char*,int,...), and wrap umask(mode_t).") + ("id" . "android-bionic-multicall-libc-wrappers") + ("pattern" + . + "use of undeclared identifier '__errno_location'|address of overloaded function 'ioctl' is ambiguous|address of overloaded function 'open' is ambiguous|address of overloaded function 'umask' is ambiguous") + ("type" . "compile"))) --- a/support/build-jerboa-multicall.ss +++ b/support/build-jerboa-multicall.ss @@ -387,6 +387,16 @@ [(string-suffix? m "nt") 'windows] [else 'linux])) (define target-os (machine->os machine)) +(define termux-prefix + (let ([p (getenv "PREFIX")]) + (if (and p (> (string-length p) 0)) + p + "/data/data/com.termux/files/usr"))) +(define termux-android-native? + (and (not cross?) + (eq? target-os 'linux) + (or (env "TERMUX_VERSION" #f) + (string-prefix? "/data/data/com.termux/files/usr" termux-prefix)))) (define bundle-tar-command (if (eq? target-os 'darwin) "COPYFILE_DISABLE=1 tar --no-xattrs --no-mac-metadata" @@ -1499,7 +1509,9 @@ [(freebsd) "-lm -lpthread"] [(darwin) "-lm -lpthread"] [else "-lm -lpthread"]) - (cond [(string-suffix? machine "osx") "-lm -lpthread -lncurses -liconv"] + (cond [termux-android-native? + (format "-L~a/lib -lm -ldl -lpthread -lncurses -liconv" termux-prefix)] + [(string-suffix? machine "osx") "-lm -lpthread -lncurses -liconv"] [(string-suffix? machine "fb") "-lm -lpthread -lncurses -L/usr/local/lib -liconv"] [else "-lm -ldl -lpthread -lncurses"]))) ;; Libs jerbuild must pass when it links an ON-TARGET binary against this --- a/support/multicall-main.c +++ b/support/multicall-main.c @@ -20,6 +20,7 @@ #include <fcntl.h> #include <pwd.h> #include <signal.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -51,6 +52,31 @@ static ssize_t (*const posix_write_fn)(int, const void *, size_t) = write; +#if defined(__ANDROID__) +static int *jerboa_errno_location(void) { + return __errno(); +} + +static int jerboa_ioctl(int fd, unsigned long request, void *arg) { + return ioctl(fd, request, arg); +} + +static int jerboa_open(const char *path, int flags, ...) { + mode_t mode = 0; + if ((flags & O_CREAT) != 0) { + va_list ap; + va_start(ap, flags); + mode = (mode_t)va_arg(ap, int); + va_end(ap); + } + return open(path, flags, mode); +} + +static mode_t jerboa_umask(mode_t mode) { + return umask(mode); +} +#endif + static void call_scheme_1(const char *who, ptr arg) { Scall1(Stop_level_value(Sstring_to_symbol(who)), arg); } @@ -245,7 +271,29 @@ static const char *ensure_extracted(void) { } static const char *write_program_tmpfile(void) { - static char path[] = "/tmp/jerboa-prog-XXXXXX"; + static char path[4096]; + const char *tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL || tmpdir[0] == '\0' || access(tmpdir, W_OK) != 0) { + const char *prefix = getenv("PREFIX"); + if (prefix != NULL && prefix[0] != '\0') { + int n = snprintf(path, sizeof(path), "%s/tmp", prefix); + if (n > 0 && (size_t)n < sizeof(path) && access(path, W_OK) == 0) { + tmpdir = path; + } else { + tmpdir = NULL; + } + } else { + tmpdir = NULL; + } + } + if (tmpdir == NULL || tmpdir[0] == '\0') { + tmpdir = (access("/tmp", W_OK) == 0) ? "/tmp" : "."; + } + int len = snprintf(path, sizeof(path), "%s/jerboa-prog-XXXXXX", tmpdir); + if (len <= 0 || (size_t)len >= sizeof(path)) { + fprintf(stderr, "temporary path too long\n"); + exit(1); + } int fd = mkstemp(path); if (fd < 0) { perror("mkstemp"); exit(1); } if (write_all_retry(fd, program_boot_data, program_boot_size) != 0) { @@ -273,7 +321,10 @@ static void configure_embedded_library_paths(void) { * host executable to publish them explicitly. */ static void register_symbols(void) { Sforeign_symbol("strerror", (void *)strerror); -#if defined(__APPLE__) || defined(__FreeBSD__) +#if defined(__ANDROID__) + Sforeign_symbol("__errno_location", (void *)jerboa_errno_location); + Sforeign_symbol("__errno", (void *)jerboa_errno_location); +#elif defined(__APPLE__) || defined(__FreeBSD__) Sforeign_symbol("__error", (void *)__error); #else Sforeign_symbol("__errno_location", (void *)__errno_location); @@ -298,14 +349,22 @@ static void register_symbols(void) { Sforeign_symbol("getppid", (void *)getppid); Sforeign_symbol("getrlimit", (void *)getrlimit); Sforeign_symbol("getuid", (void *)getuid); +#if defined(__ANDROID__) + Sforeign_symbol("ioctl", (void *)jerboa_ioctl); +#else Sforeign_symbol("ioctl", (void *)ioctl); +#endif Sforeign_symbol("isatty", (void *)isatty); Sforeign_symbol("kill", (void *)kill); Sforeign_symbol("localtime", (void *)localtime); Sforeign_symbol("lseek", (void *)lseek); Sforeign_symbol("lstat", (void *)lstat); Sforeign_symbol("mkfifo", (void *)mkfifo); +#if defined(__ANDROID__) + Sforeign_symbol("open", (void *)jerboa_open); +#else Sforeign_symbol("open", (void *)open); +#endif Sforeign_symbol("pipe", (void *)pipe); Sforeign_symbol("read", (void *)read); Sforeign_symbol("readlink", (void *)readlink); @@ -333,7 +392,11 @@ static void register_symbols(void) { Sforeign_symbol("tcgetpgrp", (void *)tcgetpgrp); Sforeign_symbol("tcsetattr", (void *)tcsetattr); Sforeign_symbol("tcsetpgrp", (void *)tcsetpgrp); +#if defined(__ANDROID__) + Sforeign_symbol("umask", (void *)jerboa_umask); +#else Sforeign_symbol("umask", (void *)umask); +#endif Sforeign_symbol("unlink", (void *)unlink); Sforeign_symbol("unsetenv", (void *)unsetenv); Sforeign_symbol("waitpid", (void *)waitpid);