diff --git a/Ports/AvailablePorts.md b/Ports/AvailablePorts.md index 178fd5873a..0553ddf596 100644 --- a/Ports/AvailablePorts.md +++ b/Ports/AvailablePorts.md @@ -49,6 +49,7 @@ Please make sure to keep this list up to date when adding and updating ports. :^ | [`libgcrypt`](libgcrypt/) | libgcrypt | 1.9.2 | https://gnupg.org/software/libgcrypt/index.html | | [`libgpg-error`](libgpg-error/)| libgpg-error | 1.42 | https://gnupg.org/software/libgpg-error/index.html | | [`libiconv`](libiconv/) | GNU libiconv | 1.16 | https://www.gnu.org/software/libiconv/ | +| [`libicu`](libicu/) | ICU | 69.1 | http://site.icu-project.org/ | | [`libksba`](libksba/) | libksba | 1.5.1 | https://gnupg.org/software/libksba/index.html | | [`libjpeg`](libjpeg/) | libjpeg | 9d | https://ijg.org/ | | [`libogg`](libogg/) | libogg | 1.3.4 | https://github.com/xiph/ogg | diff --git a/Ports/libicu/package.sh b/Ports/libicu/package.sh new file mode 100755 index 0000000000..67b9607e71 --- /dev/null +++ b/Ports/libicu/package.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env -S bash ../.port_include.sh +port=libicu +version=69_1 +useconfigure=true +workdir=icu/source +configopts=--with-cross-build=$(pwd)/${workdir}/../host-build +files="https://github.com/unicode-org/icu/releases/download/release-${version//_/-}/icu4c-${version}-src.tgz icu4c-${version}-src.tgz" + +configure() { + host_env + run mkdir -p ../host-build + run sh -c "cd ../host-build && ../source/configure && make $makeopts" + target_env + run ./configure --host="${SERENITY_ARCH}-pc-serenity" $configopts +} + +export CFLAGS="-DU_HAVE_NL_LANGINFO_CODESET=0 -DLC_MESSAGES=1" +export CXXFLAGS="-DU_HAVE_NL_LANGINFO_CODESET=0 -DLC_MESSAGES=1" diff --git a/Ports/libicu/patches/icu.patch b/Ports/libicu/patches/icu.patch new file mode 100644 index 0000000000..0706911c21 --- /dev/null +++ b/Ports/libicu/patches/icu.patch @@ -0,0 +1,548 @@ +diff -ur source/config/mh-serenity source.serenity/config/mh-serenity +--- source/config/mh-serenity 1970-01-01 01:00:00.000000000 +0100 ++++ source.serenity/config/mh-serenity 2021-04-11 09:20:23.857575570 +0200 +@@ -0,0 +1,87 @@ ++## -*-makefile-*- ++## Copyright (C) 2016 and later: Unicode, Inc. and others. ++## License & terms of use: http://www.unicode.org/copyright.html ++## Linux-specific setup ++## Copyright (c) 1999-2013, International Business Machines Corporation and ++## others. All Rights Reserved. ++ ++## Commands to generate dependency files ++GEN_DEPS.c= $(CC) -E -MM $(DEFS) $(CPPFLAGS) ++GEN_DEPS.cc= $(CXX) -E -MM $(DEFS) $(CPPFLAGS) $(CXXFLAGS) ++ ++## Flags for position independent code ++SHAREDLIBCFLAGS = -fPIC ++SHAREDLIBCXXFLAGS = -fPIC ++SHAREDLIBCPPFLAGS = -DPIC ++ ++## Additional flags when building libraries and with threads ++THREADSCPPFLAGS = -D_REENTRANT ++LIBCPPFLAGS = ++ ++## Compiler switch to embed a runtime search path ++LD_RPATH= -Wl,-zorigin,-rpath,'$$'ORIGIN ++LD_RPATH_PRE = -Wl,-rpath, ++ ++## These are the library specific LDFLAGS ++LDFLAGSICUDT=-nodefaultlibs -nostdlib ++ ++## Compiler switch to embed a library name ++# The initial tab in the next line is to prevent icu-config from reading it. ++ LD_SONAME = -Wl,-soname -Wl,$(notdir $(MIDDLE_SO_TARGET)) ++#SH# # We can't depend on MIDDLE_SO_TARGET being set. ++#SH# LD_SONAME= ++ ++## Shared library options ++LD_SOOPTIONS= -Wl,-Bsymbolic ++ ++## Shared object suffix ++SO = so ++## Non-shared intermediate object suffix ++STATIC_O = ao ++ ++## Compilation rules ++%.$(STATIC_O): $(srcdir)/%.c ++ $(call SILENT_COMPILE,$(strip $(COMPILE.c) $(STATICCPPFLAGS) $(STATICCFLAGS)) -o $@ $<) ++%.o: $(srcdir)/%.c ++ $(call SILENT_COMPILE,$(strip $(COMPILE.c) $(DYNAMICCPPFLAGS) $(DYNAMICCFLAGS)) -o $@ $<) ++ ++%.$(STATIC_O): $(srcdir)/%.cpp ++ $(call SILENT_COMPILE,$(strip $(COMPILE.cc) $(STATICCPPFLAGS) $(STATICCXXFLAGS)) -o $@ $<) ++%.o: $(srcdir)/%.cpp ++ $(call SILENT_COMPILE,$(strip $(COMPILE.cc) $(DYNAMICCPPFLAGS) $(DYNAMICCXXFLAGS)) -o $@ $<) ++ ++ ++## Dependency rules ++%.d: $(srcdir)/%.c ++ $(call ICU_MSG,(deps)) $< ++ @$(SHELL) -ec '$(GEN_DEPS.c) $< \ ++ | sed '\''s%\($*\)\.o[ :]*%\1.o $@ : %g'\'' > $@; \ ++ [ -s $@ ] || rm -f $@' ++ ++%.d: $(srcdir)/%.cpp ++ $(call ICU_MSG,(deps)) $< ++ @$(SHELL) -ec '$(GEN_DEPS.cc) $< \ ++ | sed '\''s%\($*\)\.o[ :]*%\1.o $@ : %g'\'' > $@; \ ++ [ -s $@ ] || rm -f $@' ++ ++## Versioned libraries rules ++ ++%.$(SO).$(SO_TARGET_VERSION_MAJOR): %.$(SO).$(SO_TARGET_VERSION) ++ $(RM) $@ && ln -s ${~mutex(); + initCondition->~condition_variable(); ++#endif + UMutex::cleanup(); + + // Reset the once_flag, by destructing it and creating a fresh one in its place. + // Do not use this trick anywhere else in ICU; use umtx_initOnce, not std::call_once(). ++#ifndef __serenity__ + pInitFlag->~once_flag(); + pInitFlag = new(&initFlag) std::once_flag(); ++#endif + return true; + } + + static void U_CALLCONV umtx_init() { ++#ifndef __serenity__ + initMutex = STATIC_NEW(std::mutex); + initCondition = STATIC_NEW(std::condition_variable); ++#endif + ucln_common_registerCleanup(UCLN_COMMON_MUTEX, umtx_cleanup); + } + U_CDECL_END + + +-std::mutex *UMutex::getMutex() { ++#ifndef __serenity__ ++std::mutex ++#else ++void ++#endif ++*UMutex::getMutex() { ++#ifndef __serenity__ + std::mutex *retPtr = fMutex.load(std::memory_order_acquire); + if (retPtr == nullptr) { + std::call_once(*pInitFlag, umtx_init); +@@ -92,6 +108,9 @@ + } + U_ASSERT(retPtr != nullptr); + return retPtr; ++#else ++ return this; ++#endif + } + + UMutex *UMutex::gListHead = nullptr; +@@ -99,8 +118,10 @@ + void UMutex::cleanup() { + UMutex *next = nullptr; + for (UMutex *m = gListHead; m != nullptr; m = next) { ++#ifndef __serenity__ + (*m->fMutex).~mutex(); + m->fMutex = nullptr; ++#endif + next = m->fListLink; + m->fListLink = nullptr; + } +@@ -143,8 +164,12 @@ + // + U_COMMON_API UBool U_EXPORT2 + umtx_initImplPreInit(UInitOnce &uio) { ++#ifndef __serenity__ + std::call_once(*pInitFlag, umtx_init); + std::unique_lock lock(*initMutex); ++#else ++ umtx_init(); ++#endif + if (umtx_loadAcquire(uio.fState) == 0) { + umtx_storeRelease(uio.fState, 1); + return true; // Caller will next call the init function. +@@ -152,7 +177,9 @@ + while (umtx_loadAcquire(uio.fState) == 1) { + // Another thread is currently running the initialization. + // Wait until it completes. ++#ifndef __serenity__ + initCondition->wait(lock); ++#endif + } + U_ASSERT(uio.fState == 2); + return false; +@@ -169,10 +196,14 @@ + U_COMMON_API void U_EXPORT2 + umtx_initImplPostInit(UInitOnce &uio) { + { ++#ifndef __serenity__ + std::unique_lock lock(*initMutex); ++#endif + umtx_storeRelease(uio.fState, 2); + } ++#ifndef __serenity__ + initCondition->notify_all(); ++#endif + } + + U_NAMESPACE_END +diff -ur source/common/umutex.h source.serenity/common/umutex.h +--- source/common/umutex.h 2021-04-08 02:10:27.000000000 +0200 ++++ source.serenity/common/umutex.h 2021-04-11 09:33:17.301246150 +0200 +@@ -231,17 +231,25 @@ + + // requirements for C++ BasicLockable, allows UMutex to work with std::lock_guard + void lock() { ++#ifndef __serenity__ + std::mutex *m = fMutex.load(std::memory_order_acquire); + if (m == nullptr) { m = getMutex(); } + m->lock(); ++#endif ++ } ++ void unlock() { ++#ifndef __serenity__ ++ fMutex.load(std::memory_order_relaxed)->unlock(); ++#endif + } +- void unlock() { fMutex.load(std::memory_order_relaxed)->unlock(); } + + static void cleanup(); + + private: ++#ifndef __serenity__ + alignas(std::mutex) char fStorage[sizeof(std::mutex)] {}; + std::atomic fMutex { nullptr }; ++#endif + + /** All initialized UMutexes are kept in a linked list, so that they can be found, + * and the underlying std::mutex destructed, by u_cleanup(). +@@ -253,7 +261,12 @@ + * Initial fast check is inline, in lock(). The returned value may never + * be nullptr. + */ +- std::mutex *getMutex(); ++#ifndef __serenity__ ++ std::mutex ++#else ++ void ++#endif ++ *getMutex(); + }; + + +diff -ur source/common/unifiedcache.cpp source.serenity/common/unifiedcache.cpp +--- source/common/unifiedcache.cpp 2021-04-08 02:10:27.000000000 +0200 ++++ source.serenity/common/unifiedcache.cpp 2021-04-11 09:44:51.810895675 +0200 +@@ -13,16 +13,20 @@ + #include "unifiedcache.h" + + #include // For std::max() ++#ifndef __serenity__ + #include ++#endif + + #include "uassert.h" + #include "uhash.h" + #include "ucln_cmn.h" + + static icu::UnifiedCache *gCache = NULL; ++#ifndef __serenity__ + static std::mutex *gCacheMutex = nullptr; + static std::condition_variable *gInProgressValueAddedCond; + static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER; ++#endif + + static const int32_t MAX_EVICT_ITERATIONS = 10; + static const int32_t DEFAULT_MAX_UNUSED = 1000; +@@ -31,13 +35,17 @@ + + U_CDECL_BEGIN + static UBool U_CALLCONV unifiedcache_cleanup() { ++#ifndef __serenity__ + gCacheInitOnce.reset(); ++#endif + delete gCache; + gCache = nullptr; ++#ifndef __serenity__ + gCacheMutex->~mutex(); + gCacheMutex = nullptr; + gInProgressValueAddedCond->~condition_variable(); + gInProgressValueAddedCond = nullptr; ++#endif + return TRUE; + } + U_CDECL_END +@@ -72,8 +80,10 @@ + ucln_common_registerCleanup( + UCLN_COMMON_UNIFIED_CACHE, unifiedcache_cleanup); + ++#ifndef __serenity__ + gCacheMutex = STATIC_NEW(std::mutex); + gInProgressValueAddedCond = STATIC_NEW(std::condition_variable); ++#endif + gCache = new UnifiedCache(status); + if (gCache == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; +@@ -86,7 +96,11 @@ + } + + UnifiedCache *UnifiedCache::getInstance(UErrorCode &status) { ++#ifndef __serenity__ + umtx_initOnce(gCacheInitOnce, &cacheInit, status); ++#else ++ cacheInit(status); ++#endif + if (U_FAILURE(status)) { + return NULL; + } +@@ -135,28 +149,38 @@ + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } ++#ifndef __serenity__ + std::lock_guard lock(*gCacheMutex); ++#endif + fMaxUnused = count; + fMaxPercentageOfInUse = percentageOfInUseItems; + } + + int32_t UnifiedCache::unusedCount() const { ++#ifndef __serenity__ + std::lock_guard lock(*gCacheMutex); ++#endif + return uhash_count(fHashtable) - fNumValuesInUse; + } + + int64_t UnifiedCache::autoEvictedCount() const { ++#ifndef __serenity__ + std::lock_guard lock(*gCacheMutex); ++#endif + return fAutoEvictedCount; + } + + int32_t UnifiedCache::keyCount() const { ++#ifndef __serenity__ + std::lock_guard lock(*gCacheMutex); ++#endif + return uhash_count(fHashtable); + } + + void UnifiedCache::flush() const { ++#ifndef __serenity__ + std::lock_guard lock(*gCacheMutex); ++#endif + + // Use a loop in case cache items that are flushed held hard references to + // other cache items making those additional cache items eligible for +@@ -165,7 +189,9 @@ + } + + void UnifiedCache::handleUnreferencedObject() const { ++#ifndef __serenity__ + std::lock_guard lock(*gCacheMutex); ++#endif + --fNumValuesInUse; + _runEvictionSlice(); + } +@@ -184,7 +210,9 @@ + } + + void UnifiedCache::dumpContents() const { ++#ifndef __serenity__ + std::lock_guard lock(*gCacheMutex); ++#endif + _dumpContents(); + } + +@@ -224,7 +252,9 @@ + // Now all that should be left in the cache are entries that refer to + // each other and entries with hard references from outside the cache. + // Nothing we can do about these so proceed to wipe out the cache. ++#ifndef __serenity__ + std::lock_guard lock(*gCacheMutex); ++#endif + _flush(TRUE); + } + uhash_close(fHashtable); +@@ -325,7 +355,9 @@ + const CacheKeyBase &key, + const SharedObject *&value, + UErrorCode &status) const { ++#ifndef __serenity__ + std::lock_guard lock(*gCacheMutex); ++#endif + const UHashElement *element = uhash_find(fHashtable, &key); + if (element != NULL && !_inProgress(element)) { + _fetch(element, value, status); +@@ -350,14 +382,18 @@ + UErrorCode &status) const { + U_ASSERT(value == NULL); + U_ASSERT(status == U_ZERO_ERROR); ++#ifndef __serenity__ + std::unique_lock lock(*gCacheMutex); ++#endif + const UHashElement *element = uhash_find(fHashtable, &key); + + // If the hash table contains an inProgress placeholder entry for this key, + // this means that another thread is currently constructing the value object. + // Loop, waiting for that construction to complete. + while (element != NULL && _inProgress(element)) { ++#ifndef __serenity__ + gInProgressValueAddedCond->wait(lock); ++#endif + element = uhash_find(fHashtable, &key); + } + +@@ -430,7 +466,9 @@ + + // Tell waiting threads that we replace in-progress status with + // an error. ++#ifndef __serenity__ + gInProgressValueAddedCond->notify_all(); ++#endif + } + + void UnifiedCache::_fetch( +diff -ur source/config.sub source.serenity/config.sub +--- source/config.sub 2021-04-08 02:10:27.000000000 +0200 ++++ source.serenity/config.sub 2021-04-11 07:59:52.531086431 +0200 +@@ -1416,7 +1416,7 @@ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ +- | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*) ++ | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -serenity*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) +diff -ur source/configure source.serenity/configure +--- source/configure 2021-04-08 02:10:27.000000000 +0200 ++++ source.serenity/configure 2021-04-11 09:24:04.971314734 +0200 +@@ -5274,6 +5274,8 @@ + else + icu_cv_host_frag=mh-cygwin-msvc + fi ;; ++*-serenity*) ++ icu_cv_host_frag=mh-serenity ;; + *-*-mingw*) + if test "$GCC" = yes; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +diff -ur source/i18n/decimfmt.cpp source.serenity/i18n/decimfmt.cpp +--- source/i18n/decimfmt.cpp 2021-04-08 02:10:27.000000000 +0200 ++++ source.serenity/i18n/decimfmt.cpp 2021-04-11 09:58:25.946465400 +0200 +@@ -1827,13 +1827,21 @@ + if (!fields->canUseFastFormat) { + return false; + } ++#ifndef __serenity__ + if (std::isnan(input) ++#else ++ if (isnan(input) ++#endif + || uprv_trunc(input) != input + || input <= INT32_MIN + || input > INT32_MAX) { + return false; + } ++#ifndef __serenity__ + doFastFormatInt32(static_cast(input), std::signbit(input), output); ++#else ++ doFastFormatInt32(static_cast(input), signbit(input), output); ++#endif + return true; + } + +diff -ur source/i18n/number_decimalquantity.cpp source.serenity/i18n/number_decimalquantity.cpp +--- source/i18n/number_decimalquantity.cpp 2021-04-08 02:10:27.000000000 +0200 ++++ source.serenity/i18n/number_decimalquantity.cpp 2021-04-11 10:00:59.729454484 +0200 +@@ -419,13 +419,25 @@ + setBcdToZero(); + flags = 0; + // signbit() from handles +0.0 vs -0.0 ++#ifndef __serenity__ + if (std::signbit(n)) { ++#else ++ if (signbit(n)) { ++#endif + flags |= NEGATIVE_FLAG; + n = -n; + } ++#ifndef __serenity__ + if (std::isnan(n) != 0) { ++#else ++ if (isnan(n) != 0) { ++#endif + flags |= NAN_FLAG; ++#ifndef __serenity__ + } else if (std::isfinite(n) == 0) { ++#else ++ } else if (isfinite(n) == 0) { ++#endif + flags |= INFINITY_FLAG; + } else if (n != 0) { + _setToDoubleFast(n); +diff -ur source/i18n/number_utils.cpp source.serenity/i18n/number_utils.cpp +--- source/i18n/number_utils.cpp 2021-04-08 02:10:27.000000000 +0200 ++++ source.serenity/i18n/number_utils.cpp 2021-04-11 09:59:55.181535153 +0200 +@@ -130,7 +130,11 @@ + + void DecNum::setTo(double d, UErrorCode& status) { + // Need to check for NaN and Infinity before going into DoubleToStringConverter ++#ifndef __serenity__ + if (std::isnan(d) != 0 || std::isfinite(d) == 0) { ++#else ++ if (isnan(d) != 0 || isfinite(d) == 0) { ++#endif + status = U_UNSUPPORTED_ERROR; + return; + } +@@ -157,7 +161,11 @@ + + // Set exponent and bitmask. Note that DoubleToStringConverter does not do negatives. + fData.getAlias()->exponent += point - length; ++#ifndef __serenity__ + fData.getAlias()->bits |= static_cast(std::signbit(d) ? DECNEG : 0); ++#else ++ fData.getAlias()->bits |= static_cast(signbit(d) ? DECNEG : 0); ++#endif + } + + void DecNum::_setTo(const char* str, int32_t maxDigits, UErrorCode& status) { +diff -ur source/i18n/reldatefmt.cpp source.serenity/i18n/reldatefmt.cpp +--- source/i18n/reldatefmt.cpp 2021-04-08 02:10:27.000000000 +0200 ++++ source.serenity/i18n/reldatefmt.cpp 2021-04-11 09:55:40.409893218 +0200 +@@ -1008,7 +1008,11 @@ + return; + } + UDateDirection direction = UDAT_DIRECTION_NEXT; ++#ifndef __serenity__ + if (std::signbit(offset)) { // needed to handle -0.0 ++#else ++ if (signbit(offset)) { ++#endif + direction = UDAT_DIRECTION_LAST; + offset = -offset; + }