diff --git a/android-configure b/android-configure index fe054813ac1..4eb9159f6dc 100755 --- a/android-configure +++ b/android-configure @@ -1,7 +1,7 @@ #!/bin/bash # In order to cross-compile node for Android using NDK, run: -# source android-configure [arch] +# source android-configure [arch] [targetapi] # # By running android-configure with source, will allow environment variables to # be persistent in current session. This is useful for installing native node @@ -15,6 +15,12 @@ else ARCH="$2" fi +if [ -z "$3" ]; then + TARGET_API=21 +else + TARGET_API="$3" +fi + CC_VER="4.9" case $ARCH in arm) @@ -55,7 +61,7 @@ function make_toolchain { --install-dir=$TOOLCHAIN \ --stl=libc++ \ --force \ - --platform=android-21 + --platform=android-$TARGET_API } export TOOLCHAIN=$PWD/android-toolchain diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 1597828c868..f864343bb38 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -79,13 +79,19 @@ extern char** environ; # endif #endif +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 +# include /* for dlsym */ +#endif + #if defined(__MVS__) #include #endif #if defined(__linux__) # include -# define uv__accept4 accept4 +# if !(defined(__ANDROID_API__) && __ANDROID_API__ < 21) +# define uv__accept4 accept4 +# endif #endif static int uv__run_pending(uv_loop_t* loop); @@ -1029,7 +1035,7 @@ int uv__open_cloexec(const char* path, int flags) { int uv__dup2_cloexec(int oldfd, int newfd) { -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__linux__) +#if defined(__FreeBSD__) || defined(__NetBSD__) || (defined(__linux__) && !(defined(__ANDROID_API__) && __ANDROID_API__ < 21)) int r; r = dup3(oldfd, newfd, O_CLOEXEC); @@ -1154,6 +1160,13 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { size_t shell_size; long initsize; int r; +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 + int (*getpwuid_r)(uid_t, struct passwd*, char*, size_t, struct passwd**); + + getpwuid_r = dlsym(RTLD_DEFAULT, "getpwuid_r"); + if (getpwuid_r == NULL) + return UV_ENOSYS; +#endif if (pwd == NULL) return UV_EINVAL; diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 976f84d28ee..3d766184e60 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -229,7 +229,11 @@ static ssize_t uv__fs_futime(uv_fs_t* req) { struct timespec ts[2]; ts[0] = uv__fs_to_timespec(req->atime); ts[1] = uv__fs_to_timespec(req->mtime); +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 + return utimensat(req->file, NULL, ts, 0); +#else return futimens(req->file, ts); +#endif #elif defined(__APPLE__) \ || defined(__DragonFly__) \ || defined(__FreeBSD__) \ diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index caaf3ce8830..294ba6341e6 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -85,7 +85,17 @@ static uint64_t read_cpufreq(unsigned int cpunum); int uv__platform_loop_init(uv_loop_t* loop) { int fd; + + /* It was reported that EPOLL_CLOEXEC is not defined on Android API < 21, + * a.k.a. Lollipop. Since EPOLL_CLOEXEC is an alias for O_CLOEXEC on all + * architectures, we just use that instead. + */ +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 + fd = -1; + errno = ENOSYS; +#else fd = epoll_create1(O_CLOEXEC); +#endif /* epoll_create1() can fail either because it's not implemented (old kernel) * or because it doesn't understand the O_CLOEXEC flag. @@ -310,11 +320,16 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { abort(); if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) { +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 + nfds = -1; + errno = ENOSYS; +#else nfds = epoll_pwait(loop->backend_fd, events, ARRAY_SIZE(events), timeout, &sigset); +#endif if (nfds == -1 && errno == ENOSYS) { uv__store_relaxed(&no_epoll_pwait_cached, 1); no_epoll_pwait = 1; diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c index 42b601adbf8..9b26202fb33 100644 --- a/deps/uv/src/unix/linux-inotify.c +++ b/deps/uv/src/unix/linux-inotify.c @@ -29,7 +29,6 @@ #include #include -#include #include #include @@ -65,17 +64,45 @@ static void uv__inotify_read(uv_loop_t* loop, static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop); -static int init_inotify(uv_loop_t* loop) { +static int new_inotify_fd(void) { + int err; int fd; + fd = uv__inotify_init1(UV__IN_NONBLOCK | UV__IN_CLOEXEC); + if (fd != -1) + return fd; + + if (errno != ENOSYS) + return UV__ERR(errno); + + fd = uv__inotify_init(); + if (fd == -1) + return UV__ERR(errno); + + err = uv__cloexec(fd, 1); + if (err == 0) + err = uv__nonblock(fd, 1); + + if (err) { + uv__close(fd); + return err; + } + + return fd; +} + + +static int init_inotify(uv_loop_t* loop) { + int err; + if (loop->inotify_fd != -1) return 0; - fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); - if (fd < 0) - return UV__ERR(errno); + err = new_inotify_fd(); + if (err < 0) + return err; - loop->inotify_fd = fd; + loop->inotify_fd = err; uv__io_init(&loop->inotify_read_watcher, uv__inotify_read, loop->inotify_fd); uv__io_start(loop, &loop->inotify_read_watcher, POLLIN); @@ -159,7 +186,7 @@ static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) { if ((!w->iterating) && QUEUE_EMPTY(&w->watchers)) { /* No watchers left for this path. Clean up. */ RB_REMOVE(watcher_root, CAST(&loop->inotify_watchers), w); - inotify_rm_watch(loop->inotify_fd, w->wd); + uv__inotify_rm_watch(loop->inotify_fd, w->wd); uv__free(w); } } @@ -167,7 +194,7 @@ static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) { static void uv__inotify_read(uv_loop_t* loop, uv__io_t* dummy, unsigned int events) { - const struct inotify_event* e; + const struct uv__inotify_event* e; struct watcher_list* w; uv_fs_event_t* h; QUEUE queue; @@ -192,12 +219,12 @@ static void uv__inotify_read(uv_loop_t* loop, /* Now we have one or more inotify_event structs. */ for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { - e = (const struct inotify_event*) p; + e = (const struct uv__inotify_event*)p; events = 0; - if (e->mask & (IN_ATTRIB|IN_MODIFY)) + if (e->mask & (UV__IN_ATTRIB|UV__IN_MODIFY)) events |= UV_CHANGE; - if (e->mask & ~(IN_ATTRIB|IN_MODIFY)) + if (e->mask & ~(UV__IN_ATTRIB|UV__IN_MODIFY)) events |= UV_RENAME; w = find_watcher(loop, e->wd); @@ -263,16 +290,16 @@ int uv_fs_event_start(uv_fs_event_t* handle, if (err) return err; - events = IN_ATTRIB - | IN_CREATE - | IN_MODIFY - | IN_DELETE - | IN_DELETE_SELF - | IN_MOVE_SELF - | IN_MOVED_FROM - | IN_MOVED_TO; + events = UV__IN_ATTRIB + | UV__IN_CREATE + | UV__IN_MODIFY + | UV__IN_DELETE + | UV__IN_DELETE_SELF + | UV__IN_MOVE_SELF + | UV__IN_MOVED_FROM + | UV__IN_MOVED_TO; - wd = inotify_add_watch(handle->loop->inotify_fd, path, events); + wd = uv__inotify_add_watch(handle->loop->inotify_fd, path, events); if (wd == -1) return UV__ERR(errno); diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c index 160056b46ec..087c99dd992 100644 --- a/deps/uv/src/unix/linux-syscalls.c +++ b/deps/uv/src/unix/linux-syscalls.c @@ -34,6 +34,46 @@ # endif #endif /* __arm__ */ +#ifndef __NR_inotify_init +# if defined(__x86_64__) +# define __NR_inotify_init 253 +# elif defined(__i386__) +# define __NR_inotify_init 291 +# elif defined(__arm__) +# define __NR_inotify_init (UV_SYSCALL_BASE + 316) +# endif +#endif /* __NR_inotify_init */ + +#ifndef __NR_inotify_init1 +# if defined(__x86_64__) +# define __NR_inotify_init1 294 +# elif defined(__i386__) +# define __NR_inotify_init1 332 +# elif defined(__arm__) +# define __NR_inotify_init1 (UV_SYSCALL_BASE + 360) +# endif +#endif /* __NR_inotify_init1 */ + +#ifndef __NR_inotify_add_watch +# if defined(__x86_64__) +# define __NR_inotify_add_watch 254 +# elif defined(__i386__) +# define __NR_inotify_add_watch 292 +# elif defined(__arm__) +# define __NR_inotify_add_watch (UV_SYSCALL_BASE + 317) +# endif +#endif /* __NR_inotify_add_watch */ + +#ifndef __NR_inotify_rm_watch +# if defined(__x86_64__) +# define __NR_inotify_rm_watch 255 +# elif defined(__i386__) +# define __NR_inotify_rm_watch 293 +# elif defined(__arm__) +# define __NR_inotify_rm_watch (UV_SYSCALL_BASE + 318) +# endif +#endif /* __NR_inotify_rm_watch */ + #ifndef __NR_recvmmsg # if defined(__x86_64__) # define __NR_recvmmsg 299 @@ -146,6 +186,42 @@ struct uv__mmsghdr; +int uv__inotify_init(void) { +#if defined(__NR_inotify_init) + return syscall(__NR_inotify_init); +#else + return errno = ENOSYS, -1; +#endif +} + + +int uv__inotify_init1(int flags) { +#if defined(__NR_inotify_init1) + return syscall(__NR_inotify_init1, flags); +#else + return errno = ENOSYS, -1; +#endif +} + + +int uv__inotify_add_watch(int fd, const char* path, uint32_t mask) { +#if defined(__NR_inotify_add_watch) + return syscall(__NR_inotify_add_watch, fd, path, mask); +#else + return errno = ENOSYS, -1; +#endif +} + + +int uv__inotify_rm_watch(int fd, int32_t wd) { +#if defined(__NR_inotify_rm_watch) + return syscall(__NR_inotify_rm_watch, fd, wd); +#else + return errno = ENOSYS, -1; +#endif +} + + int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen, @@ -172,28 +248,28 @@ int uv__recvmmsg(int fd, ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) { -#if defined(__NR_preadv) - return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); -#else +#if !defined(__NR_preadv) || defined(__ANDROID_API__) && __ANDROID_API__ < 24 return errno = ENOSYS, -1; +#else + return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); #endif } ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset) { -#if defined(__NR_pwritev) - return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); -#else +#if !defined(__NR_pwritev) || defined(__ANDROID_API__) && __ANDROID_API__ < 24 return errno = ENOSYS, -1; +#else + return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); #endif } int uv__dup3(int oldfd, int newfd, int flags) { -#if defined(__NR_dup3) - return syscall(__NR_dup3, oldfd, newfd, flags); -#else +#if !defined(__NR_dup3) || defined(__ANDROID_API__) && __ANDROID_API__ < 21 return errno = ENOSYS, -1; +#else + return syscall(__NR_dup3, oldfd, newfd, flags); #endif } @@ -225,21 +301,18 @@ int uv__statx(int dirfd, int flags, unsigned int mask, struct uv__statx* statxbuf) { - /* __NR_statx make Android box killed by SIGSYS. - * That looks like a seccomp2 sandbox filter rejecting the system call. - */ -#if defined(__NR_statx) && !defined(__ANDROID__) - return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf); -#else +#if !defined(__NR_statx) || defined(__ANDROID_API__) && __ANDROID_API__ < 30 return errno = ENOSYS, -1; +#else + return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf); #endif } ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags) { -#if defined(__NR_getrandom) - return syscall(__NR_getrandom, buf, buflen, flags); -#else +#if !defined(__NR_getrandom) || defined(__ANDROID_API__) && __ANDROID_API__ < 28 return errno = ENOSYS, -1; +#else + return syscall(__NR_getrandom, buf, buflen, flags); #endif } diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h index 761ff32e21b..d00e6ab5530 100644 --- a/deps/uv/src/unix/linux-syscalls.h +++ b/deps/uv/src/unix/linux-syscalls.h @@ -31,6 +31,31 @@ #include #include +#define UV__IN_CLOEXEC O_CLOEXEC +#define UV__IN_NONBLOCK O_NONBLOCK + +/* inotify flags */ +#define UV__IN_ACCESS 0x001 +#define UV__IN_MODIFY 0x002 +#define UV__IN_ATTRIB 0x004 +#define UV__IN_CLOSE_WRITE 0x008 +#define UV__IN_CLOSE_NOWRITE 0x010 +#define UV__IN_OPEN 0x020 +#define UV__IN_MOVED_FROM 0x040 +#define UV__IN_MOVED_TO 0x080 +#define UV__IN_CREATE 0x100 +#define UV__IN_DELETE 0x200 +#define UV__IN_DELETE_SELF 0x400 +#define UV__IN_MOVE_SELF 0x800 + +struct uv__inotify_event { + int32_t wd; + uint32_t mask; + uint32_t cookie; + uint32_t len; + /* char name[0]; */ +}; + struct uv__statx_timestamp { int64_t tv_sec; uint32_t tv_nsec; @@ -61,6 +86,10 @@ struct uv__statx { uint64_t unused1[14]; }; +int uv__inotify_init(void); +int uv__inotify_init1(int flags); +int uv__inotify_add_watch(int fd, const char* path, uint32_t mask); +int uv__inotify_rm_watch(int fd, int32_t wd); ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset); ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset); int uv__dup3(int oldfd, int newfd, int flags); diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index 1a85d1d4fcd..c9a18d1e8d4 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -709,9 +709,11 @@ int uv_cond_init(uv_cond_t* cond) { if (err) return UV__ERR(err); +#if !(defined(__ANDROID_API__) && __ANDROID_API__ < 21) err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); if (err) goto error2; +#endif err = pthread_cond_init(cond, &attr); if (err) @@ -803,7 +805,16 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { #endif ts.tv_sec = timeout / NANOSEC; ts.tv_nsec = timeout % NANOSEC; +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 + + /* + * The bionic pthread implementation doesn't support CLOCK_MONOTONIC, + * but has this alternative function instead. + */ + r = pthread_cond_timedwait_monotonic_np(cond, mutex, &ts); +#else r = pthread_cond_timedwait(cond, mutex, &ts); +#endif /* __ANDROID_API__ */ #endif diff --git a/deps/uvwasi/src/uvwasi.c b/deps/uvwasi/src/uvwasi.c index 37a1905d72e..bf4bcb568d2 100644 --- a/deps/uvwasi/src/uvwasi.c +++ b/deps/uvwasi/src/uvwasi.c @@ -29,6 +29,11 @@ # undef POSIX_FADV_NORMAL #endif +/* Android before API 21 does not support posix_fadvise() */ +#if defined(__BIONIC__) && __ANDROID_API__ < 21 +# undef POSIX_FADV_NORMAL +#endif + #define VALIDATE_FSTFLAGS_OR_RETURN(flags) \ do { \ if ((flags) & ~(UVWASI_FILESTAT_SET_ATIM | \ diff --git a/src/debug_utils.cc b/src/debug_utils.cc index 687a6fb97da..01210316565 100644 --- a/src/debug_utils.cc +++ b/src/debug_utils.cc @@ -371,7 +371,7 @@ void PrintLibuvHandleInformation(uv_loop_t* loop, FILE* stream) { std::vector NativeSymbolDebuggingContext::GetLoadedLibraries() { std::vector list; -#if defined(__linux__) || defined(__FreeBSD__) || \ +#if (defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21)) || defined(__FreeBSD__) || \ defined(__OpenBSD__) || defined(__DragonFly__) dl_iterate_phdr( [](struct dl_phdr_info* info, size_t size, void* data) {