android-tools: fix musl build (off64_t, LFS64 fns, b64_pton, ANDROID_HOST_MUSL)

Several independent musl gaps surfaced one after another as each was
fixed and the build progressed further:
- android-base/off64_t.h only worked around __APPLE__ lacking off64_t;
  extend the same typedef fallback to musl.
- sysdeps.h's adb_pread/adb_pwrite/adb_lseek only fell back to the
  plain (non-LFS64) functions on __APPLE__; musl needs the same
  fallback for pread64/pwrite64/lseek64.
- daemon/auth.cpp calls b64_pton() from <resolv.h>, which the Linux
  host build gets via -lresolv and bionic provides natively, but musl
  has neither; vendor the standard BSD implementation for it.
- android-base/endian.h and threads.h already gate a musl-aware branch
  behind ANDROID_HOST_MUSL, matching upstream's own expectation, but
  nothing defined that macro for this recipe's build; define it via
  CFLAGS/CXXFLAGS for the musl toolchain.

AI-Generated: Uses Claude Code

Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
This commit is contained in:
Khem Raj committed 2026-09-29 15:35:17 -07:00
1 parent 52dd81583b
commit 255a09ab7f
4 files changed
+242

No files matched your search

@@ -0,0 +1,42 @@
From: Khem Raj <khem.raj@oss.qualcomm.com>
Date: Tue, 29 Sep 2026 02:01:07 +0000
Subject: [PATCH] libbase: extend the off64_t compat typedef to musl
android-base/off64_t.h already works around Apple's libc not
providing the glibc LFS64 off64_t name by typedef'ing it to off_t.
musl has the exact same situation -- it never defines the LFS64
names because its off_t is already 64-bit -- but the guard only
checked for __APPLE__, so building against musl failed:
| system/libbase/mapped_file.cpp:47:67: error: unknown type name 'off64_t'; did you mean 'off_t'?
| system/libbase/include/android-base/file.h:105:71: error: unknown type name 'off64_t'; did you mean 'off_t'?
| system/libbase/include/android-base/mapped_file.h:50:61: error: unknown type name 'off64_t'; did you mean 'off_t'?
Both file.h and mapped_file.h (and every .cpp that includes them)
already pull in android-base/off64_t.h, so extending its guard to
any non-glibc, non-bionic, non-Windows libc (i.e. musl) fixes all of
these call sites in a single place.
Upstream-Status: Pending
Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
---
system/libbase/include/android-base/off64_t.h | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/system/libbase/include/android-base/off64_t.h b/system/libbase/include/android-base/off64_t.h
index a4b7715..857ff29 100644
--- a/system/libbase/include/android-base/off64_t.h
+++ b/system/libbase/include/android-base/off64_t.h
@@ -16,7 +16,10 @@
#pragma once
-#if defined(__APPLE__)
-/** Mac OS has always had a 64-bit off_t, so it doesn't have off64_t. */
+#if defined(__APPLE__) || \
+ (!defined(__GLIBC__) && !defined(__BIONIC__) && !defined(_WIN32))
+/** Mac OS has always had a 64-bit off_t, so it doesn't have off64_t.
+ * musl doesn't provide the glibc LFS64 off64_t name either, but its off_t
+ * is already 64-bit, so the same typedef works there too. */
typedef off_t off64_t;
#endif
@@ -0,0 +1,58 @@
From: Khem Raj <khem.raj@oss.qualcomm.com>
Date: Tue, 29 Sep 2026 02:36:00 +0000
Subject: [PATCH] adb: sysdeps: provide pread64/pwrite64/lseek64 fallback for
musl
adb_pread(), adb_pwrite() and adb_lseek() in sysdeps.h already special
case __APPLE__ to call the plain (non-LFS64) pread/pwrite/lseek,
because Mac OS never had the glibc LFS64 names. musl has the exact
same situation -- like off64_t (see
0012-libbase-off64_t-extend-non-glibc-compat-typedef-to-musl.patch),
it never defines pread64/pwrite64/lseek64 since its off_t is already
64-bit -- but these three call sites only checked for __APPLE__, so
building against musl failed:
| sysdeps.h:522:31: error: use of undeclared identifier 'pread64'
| sysdeps.h:544:32: error: use of undeclared identifier 'pwrite64'
| sysdeps.h:554:12: error: use of undeclared identifier 'lseek64'
Extend the same non-glibc/non-bionic/non-Windows guard used by
off64_t.h to these three functions.
Upstream-Status: Pending
Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
---
--- a/packages/modules/adb/sysdeps.h
+++ b/packages/modules/adb/sysdeps.h
@@ -516,7 +516,10 @@ static inline int adb_getlogin_r(char* buf, size_t bufsize) {
}
static inline int adb_pread(borrowed_fd fd, void* buf, size_t len, off64_t offset) {
-#if defined(__APPLE__)
+#if defined(__APPLE__) || \
+ (!defined(__GLIBC__) && !defined(__BIONIC__) && !defined(_WIN32))
+ /* Mac OS and musl don't have the LFS64 pread64: their plain pread is
+ * already 64-bit (see android-base/off64_t.h). */
return TEMP_FAILURE_RETRY(pread(fd.get(), buf, len, offset));
#else
return TEMP_FAILURE_RETRY(pread64(fd.get(), buf, len, offset));
@@ -538,7 +541,8 @@ static inline int unix_read_interruptible(borrowed_fd fd, void* buf, size_t le
}
static inline int adb_pwrite(int fd, const void* buf, size_t len, off64_t offset) {
-#if defined(__APPLE__)
+#if defined(__APPLE__) || \
+ (!defined(__GLIBC__) && !defined(__BIONIC__) && !defined(_WIN32))
return TEMP_FAILURE_RETRY(pwrite(fd, buf, len, offset));
#else
return TEMP_FAILURE_RETRY(pwrite64(fd, buf, len, offset));
@@ -548,7 +552,8 @@ static inline int adb_pwrite(int fd, const void* buf, size_t len, off64_t offs
// (write and pwrite macros omitted: incompatible with GCC/abseil compat)
static inline int64_t adb_lseek(borrowed_fd fd, int64_t pos, int where) {
-#if defined(__APPLE__)
+#if defined(__APPLE__) || \
+ (!defined(__GLIBC__) && !defined(__BIONIC__) && !defined(_WIN32))
return lseek(fd.get(), pos, where);
#else
return lseek64(fd.get(), pos, where);
@@ -0,0 +1,131 @@
From: Khem Raj <khem.raj@oss.qualcomm.com>
Date: Tue, 29 Sep 2026 02:47:00 +0000
Subject: [PATCH] daemon/auth: vendor a portable b64_pton() for non-glibc,
non-bionic libcs
adbd's daemon/auth.cpp calls b64_pton() from <resolv.h> to decode a
client's base64-encoded public key. Android.bp gets this on the Linux
host build by linking -lresolv ("b64_pton" comment at host_ldlibs),
and bionic (the Android target libc) provides its own. musl has
neither the symbol nor a libresolv to link against, so building
against musl failed:
| daemon/auth.cpp:119:13: error: use of undeclared identifier 'b64_pton'
| daemon/auth.cpp:166:13: error: use of undeclared identifier 'b64_pton'
Vendor the standard BSD base64 decoder (the same implementation
glibc's own resolv/base64.c is derived from) as a local static
function, gated to only be used where the libc doesn't already
provide it, rather than adding a new libresolv-equivalent dependency
just for this one call site.
Upstream-Status: Pending
Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
---
--- a/packages/modules/adb/daemon/auth.cpp
+++ b/packages/modules/adb/daemon/auth.cpp
@@ -22,6 +22,10 @@
#include <stdio.h>
#include <string.h>
+#if !defined(__GLIBC__) && !defined(__BIONIC__)
+#include <cctype>
+#endif
+
#include <algorithm>
#include <chrono>
#include <iomanip>
@@ -49,6 +53,93 @@
#include "transport.h"
#include "types.h"
+#if !defined(__GLIBC__) && !defined(__BIONIC__)
+/*
+ * musl doesn't provide libresolv's b64_pton(): glibc gets it by linking
+ * -lresolv (see Android.bp's host_ldlibs) and bionic has its own, but musl
+ * has neither the symbol nor a libresolv to link. This is the standard BSD
+ * base64 decoder (the same one glibc's own resolv/base64.c is derived
+ * from), vendored here so this one call site doesn't need a new
+ * dependency.
+ */
+static int b64_pton(const char* src, uint8_t* target, size_t targsize) {
+ static const char Base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ static const char Pad64 = '=';
+ int tarindex, state, ch;
+ const char* pos;
+
+ state = 0;
+ tarindex = 0;
+
+ while ((ch = *src++) != '\0') {
+ if (isspace(static_cast<unsigned char>(ch))) continue;
+
+ if (ch == Pad64) break;
+
+ pos = strchr(Base64, ch);
+ if (pos == nullptr) return -1;
+
+ switch (state) {
+ case 0:
+ if (target) {
+ if (static_cast<size_t>(tarindex) >= targsize) return -1;
+ target[tarindex] = (pos - Base64) << 2;
+ }
+ state = 1;
+ break;
+ case 1:
+ if (target) {
+ if (static_cast<size_t>(tarindex) + 1 >= targsize) return -1;
+ target[tarindex] |= (pos - Base64) >> 4;
+ target[tarindex + 1] = ((pos - Base64) & 0x0f) << 4;
+ }
+ tarindex++;
+ state = 2;
+ break;
+ case 2:
+ if (target) {
+ if (static_cast<size_t>(tarindex) + 1 >= targsize) return -1;
+ target[tarindex] |= (pos - Base64) >> 2;
+ target[tarindex + 1] = ((pos - Base64) & 0x03) << 6;
+ }
+ tarindex++;
+ state = 3;
+ break;
+ case 3:
+ if (target) {
+ if (static_cast<size_t>(tarindex) >= targsize) return -1;
+ target[tarindex] |= (pos - Base64);
+ }
+ tarindex++;
+ state = 0;
+ break;
+ }
+ }
+
+ if (ch == Pad64) {
+ if (state != 2 && state != 3) return -1;
+
+ if (state == 2) {
+ for ((void)(ch = *src++); isspace(static_cast<unsigned char>(ch));
+ (void)(ch = *src++))
+ continue;
+ if (ch != Pad64) return -1;
+ (void)(ch = *src++);
+ }
+
+ while ((ch = *src++) != '\0') {
+ if (!isspace(static_cast<unsigned char>(ch))) break;
+ }
+ if (ch != '\0') return -1;
+ } else {
+ if (state != 0) return -1;
+ }
+
+ return tarindex;
+}
+#endif
+
using namespace adb::crypto;
using namespace adb::tls;
using namespace std::chrono_literals;
@@ -57,6 +57,9 @@ SRC_URI = "https://deb.debian.org/debian/pool/main/a/android-platform-tools/andr
file://0009-libbase-include-stdint.h-in-hex.cpp.patch \
file://0010-adbd-make-systemd-sd_notify-conditional-on-HAVE_SYSTEMD.patch \
file://0011-adb-drop-non-portable-is_standard_layout-assertion.patch \
file://0012-libbase-off64_t-extend-non-glibc-compat-typedef-to-musl.patch \
file://0013-adb-sysdeps-provide-pread64-pwrite64-lseek64-fallba.patch \
file://0014-daemon-auth-vendor-a-portable-b64_pton-for-non-glib.patch \
"
SRC_URI[orig.md5sum] = "352376965cdef7bd7505d8fefdd43d50"
@@ -81,12 +84,20 @@ SYSTEMD_PACKAGES = "${PN}-adbd"
SYSTEMD_SERVICE:${PN}-adbd = "android-tools-adbd.service"
CFLAGS:append = " -fPIC -std=gnu2x"
# android-base/endian.h and threads.h already have an
# ANDROID_HOST_MUSL-gated branch for building against musl (alongside their
# __GLIBC__ one); upstream expects the build system to define this macro,
# which the debian/ Makefile-based packaging used here doesn't do on its
# own. Without it those headers fall through to their Windows-only branch
# and fail with "'winsock2.h' file not found".
CFLAGS:append:libc-musl = " -DANDROID_HOST_MUSL"
# The bundled fmtlib 10.2.0 validates FMT_STRING() inside a consteval
# basic_format_string constructor whose parse path evaluates "it - begin()",
# which current C++ frontends reject as a non-constant subexpression. Define
# FMT_CONSTEVAL to empty so format-string checking falls back to fmt's runtime
# path instead of the broken compile-time one.
CXXFLAGS:append = " -fPIC -std=gnu++20 -D_Nonnull= -D_Nullable= -I${STAGING_INCDIR}/boringssl -DFMT_CONSTEVAL="
CXXFLAGS:append:libc-musl = " -DANDROID_HOST_MUSL"
LDFLAGS:append = " -fPIC -L${STAGING_LIBDIR}/android"