Index: libcxx/trunk/CMakeLists.txt =================================================================== --- libcxx/trunk/CMakeLists.txt +++ libcxx/trunk/CMakeLists.txt @@ -121,6 +121,7 @@ option(LIBCXX_ENABLE_MONOTONIC_CLOCK "Build libc++ with support for a monotonic clock. This option may only be set to OFF when LIBCXX_ENABLE_THREADS=OFF." ON) +option(LIBCXX_HAS_MUSL_LIBC "Build libc++ with support for the Musl C library" OFF) # Misc options ---------------------------------------------------------------- # FIXME: Turn -pedantic back ON. It is currently off because it warns @@ -200,6 +201,11 @@ LIBCXX_ENABLE_ABI_LINKER_SCRIPT") endif() +if (LIBCXX_HAS_MUSL_LIBC AND NOT LIBCXX_INSTALL_SUPPORT_HEADERS) + message(FATAL_ERROR "LIBCXX_INSTALL_SUPPORT_HEADERS can not be turned off" + "when building for Musl with LIBCXX_HAS_MUSL_LIBC.") +endif() + #=============================================================================== # Configure System #=============================================================================== @@ -364,6 +370,8 @@ config_define_if_not(LIBCXX_ENABLE_MONOTONIC_CLOCK _LIBCPP_HAS_NO_MONOTONIC_CLOCK) config_define_if_not(LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS) +config_define_if(LIBCXX_HAS_MUSL_LIBC _LIBCPP_HAS_MUSL_LIBC) + if (LIBCXX_NEEDS_SITE_CONFIG) configure_file( include/__config_site.in Index: libcxx/trunk/include/__config =================================================================== --- libcxx/trunk/include/__config +++ libcxx/trunk/include/__config @@ -386,14 +386,19 @@ #elif defined(__ANDROID__) #define _LIBCPP_HAS_QUICK_EXIT #elif defined(__linux__) -#include +#if !defined(_LIBCPP_HAS_MUSL_LIBC) +# include #if __GLIBC_PREREQ(2, 15) #define _LIBCPP_HAS_QUICK_EXIT #endif #if __GLIBC_PREREQ(2, 17) #define _LIBCPP_HAS_C11_FEATURES #endif +#else // defined(_LIBCPP_HAS_MUSL_LIBC) +#define _LIBCPP_HAS_QUICK_EXIT +#define _LIBCPP_HAS_C11_FEATURES #endif +#endif // __linux__ #endif #if (__has_feature(cxx_noexcept)) Index: libcxx/trunk/include/__config_site.in =================================================================== --- libcxx/trunk/include/__config_site.in +++ libcxx/trunk/include/__config_site.in @@ -18,5 +18,6 @@ #cmakedefine _LIBCPP_HAS_NO_THREADS #cmakedefine _LIBCPP_HAS_NO_MONOTONIC_CLOCK #cmakedefine _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS +#cmakedefine _LIBCPP_HAS_MUSL_LIBC -#endif +#endif // _LIBCPP_CONFIG_SITE Index: libcxx/trunk/include/__locale =================================================================== --- libcxx/trunk/include/__locale +++ libcxx/trunk/include/__locale @@ -37,6 +37,8 @@ #elif (defined(__GLIBC__) || defined(__APPLE__) || defined(__FreeBSD__) \ || defined(__EMSCRIPTEN__) || defined(__IBMCPP__)) # include +#elif defined(_LIBCPP_HAS_MUSL_LIBC) +# include #endif // __GLIBC__ || __APPLE__ || __FreeBSD__ || __sun__ || __EMSCRIPTEN__ || __IBMCPP__ #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -329,7 +331,7 @@ class _LIBCPP_TYPE_VIS ctype_base { public: -#ifdef __GLIBC__ +#if defined(__GLIBC__) typedef unsigned short mask; static const mask space = _ISspace; static const mask print = _ISprint; @@ -359,7 +361,7 @@ typedef __uint32_t mask; # elif defined(__FreeBSD__) typedef unsigned long mask; -# elif defined(__EMSCRIPTEN__) || defined(__NetBSD__) +# elif defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(_LIBCPP_HAS_MUSL_LIBC) typedef unsigned short mask; # endif static const mask space = _CTYPE_S; @@ -406,7 +408,11 @@ # define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA # define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT #else +#if defined(_LIBCPP_HAS_MUSL_LIBC) + typedef unsigned short mask; +#else typedef unsigned long mask; +#endif static const mask space = 1<<0; static const mask print = 1<<1; static const mask cntrl = 1<<2; @@ -628,7 +634,7 @@ #endif _LIBCPP_ALWAYS_INLINE const mask* table() const _NOEXCEPT {return __tab_;} static const mask* classic_table() _NOEXCEPT; -#if defined(__GLIBC__) || defined(__EMSCRIPTEN__) +#if defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC) static const int* __classic_upper_table() _NOEXCEPT; static const int* __classic_lower_table() _NOEXCEPT; #endif Index: libcxx/trunk/include/support/musl/xlocale.h =================================================================== --- libcxx/trunk/include/support/musl/xlocale.h +++ libcxx/trunk/include/support/musl/xlocale.h @@ -0,0 +1,58 @@ +// -*- C++ -*- +//===------------------- support/musl/xlocale.h ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This adds support for the extended locale functions that are currently +// missing from the Musl C library. +// +// This only works when the specified locale is "C" or "POSIX", but that's +// about as good as we can do without implementing full xlocale support +// in Musl. +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_SUPPORT_MUSL_XLOCALE_H +#define _LIBCPP_SUPPORT_MUSL_XLOCALE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static inline long long strtoll_l(const char *nptr, char **endptr, int base, + locale_t) { + return strtoll(nptr, endptr, base); +} + +static inline unsigned long long strtoull_l(const char *nptr, char **endptr, + int base, locale_t) { + return strtoull(nptr, endptr, base); +} + +static inline long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, + int base, locale_t) { + return wcstoll(nptr, endptr, base); +} + +static inline unsigned long long wcstoull_l(const wchar_t *nptr, + wchar_t **endptr, int base, + locale_t) { + return wcstoull(nptr, endptr, base); +} + +static inline long double wcstold_l(const wchar_t *nptr, wchar_t **endptr, + locale_t) { + return wcstold(nptr, endptr); +} + +#ifdef __cplusplus +} +#endif + +#endif // _LIBCPP_SUPPORT_MUSL_XLOCALE_H Index: libcxx/trunk/src/locale.cpp =================================================================== --- libcxx/trunk/src/locale.cpp +++ libcxx/trunk/src/locale.cpp @@ -812,7 +812,8 @@ { #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c; -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ + defined(__NetBSD__) || defined(_LIBCPP_HAS_MUSL_LIBC) return isascii(c) ? ctype::__classic_upper_table()[c] : c; #else return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c; @@ -825,7 +826,8 @@ for (; low != high; ++low) #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low; -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ + defined(__NetBSD__) || defined(_LIBCPP_HAS_MUSL_LIBC) *low = isascii(*low) ? ctype::__classic_upper_table()[*low] : *low; #else @@ -839,7 +841,8 @@ { #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c; -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ + defined(__NetBSD__) || defined(_LIBCPP_HAS_MUSL_LIBC) return isascii(c) ? ctype::__classic_lower_table()[c] : c; #else return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c; @@ -852,7 +855,8 @@ for (; low != high; ++low) #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low; -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ + defined(__NetBSD__) || defined(_LIBCPP_HAS_MUSL_LIBC) *low = isascii(*low) ? ctype::__classic_lower_table()[*low] : *low; #else @@ -921,8 +925,8 @@ static_cast(_DefaultRuneLocale.__mapupper[static_cast(c)]) : c; #elif defined(__NetBSD__) return static_cast(__classic_upper_table()[static_cast(c)]); -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) - return isascii(c) ? +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC) + return isascii(c) ? static_cast(__classic_upper_table()[static_cast(c)]) : c; #else return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c; @@ -938,7 +942,7 @@ static_cast(_DefaultRuneLocale.__mapupper[static_cast(*low)]) : *low; #elif defined(__NetBSD__) *low = static_cast(__classic_upper_table()[static_cast(*low)]); -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC) *low = isascii(*low) ? static_cast(__classic_upper_table()[static_cast(*low)]) : *low; #else @@ -955,7 +959,7 @@ static_cast(_DefaultRuneLocale.__maplower[static_cast(c)]) : c; #elif defined(__NetBSD__) return static_cast(__classic_lower_table()[static_cast(c)]); -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC) return isascii(c) ? static_cast(__classic_lower_table()[static_cast(c)]) : c; #else @@ -971,7 +975,7 @@ *low = isascii(*low) ? static_cast(_DefaultRuneLocale.__maplower[static_cast(*low)]) : *low; #elif defined(__NetBSD__) *low = static_cast(__classic_lower_table()[static_cast(*low)]); -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC) *low = isascii(*low) ? static_cast(__classic_lower_table()[static_cast(*low)]) : *low; #else *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low; @@ -1012,7 +1016,7 @@ return low; } -#ifdef __EMSCRIPTEN__ +#if defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC) extern "C" const unsigned short ** __ctype_b_loc(); extern "C" const int ** __ctype_tolower_loc(); extern "C" const int ** __ctype_toupper_loc(); @@ -1114,7 +1118,7 @@ return _ctype+1; // internal ctype mask table defined in msvcrt.dll // This is assumed to be safe, which is a nonsense assumption because we're // going to end up dereferencing it later... -#elif defined(__EMSCRIPTEN__) +#elif defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC) return *__ctype_b_loc(); #elif defined(_NEWLIB_VERSION) // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1]. @@ -1157,7 +1161,7 @@ return _C_toupper_tab_ + 1; } -#elif defined(__EMSCRIPTEN__) +#elif defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC) const int* ctype::__classic_lower_table() _NOEXCEPT { @@ -1169,7 +1173,7 @@ { return *__ctype_toupper_loc(); } -#endif // __GLIBC__ || __EMSCRIPTEN__ || __NETBSD__ +#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ || defined(_LIBCPP_HAS_MUSL_LIBC) // template <> class ctype_byname