Skip to content

Commit 0b2f641

Browse files
authored
Hide all ICU public C++ Symbols (#34)
* Hide all ICU public C++ Symbols **Rationale:** When FoundationInternationalization tests are executed, we effectively load two ICU instances into memory: 1) The system ICU loaded by XCTest via system Foundation; 2) The package ICU SwiftFoundation utilizes. These two ICUs cause symbol collisions for dyld due to the fact that all public C++ symbols share a global namespace and coalesce across all loaded dylibs. Consequently, we encounter sporadic test failures in SwiftFoundation as dyld arbitrarily selects ICU symbols and occasionally chooses the system one. To address this issue, we resolved to hide all C++ APIs, ensuring they are not weakly referenced and potentially bound to the system ICU implementation. This solution proves effective for SwiftFoundation, as it does not actually utilize the C++ APIs. * Use U_CAPI for uspoof_getInclusionUnicodeSet and uspoof_getRecommendedUnicodeSet
1 parent c582e32 commit 0b2f641

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

icuSources/i18n/uspoof.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -781,13 +781,13 @@ uspoof_getRecommendedSet(UErrorCode *status) {
781781
return gRecommendedSet->toUSet();
782782
}
783783

784-
U_I18N_API const UnicodeSet * U_EXPORT2
784+
U_CAPI const UnicodeSet * U_EXPORT2
785785
uspoof_getInclusionUnicodeSet(UErrorCode *status) {
786786
umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
787787
return gInclusionSet;
788788
}
789789

790-
U_I18N_API const UnicodeSet * U_EXPORT2
790+
U_CAPI const UnicodeSet * U_EXPORT2
791791
uspoof_getRecommendedUnicodeSet(UErrorCode *status) {
792792
umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
793793
return gRecommendedSet;

icuSources/include/_foundation_unicode/utypes.h

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -354,13 +354,31 @@ typedef double UDate;
354354
#endif
355355

356356
#if defined(U_COMBINED_IMPLEMENTATION)
357-
#define U_DATA_API U_EXPORT
358-
#define U_COMMON_API U_EXPORT
359-
#define U_I18N_API U_EXPORT
360-
#define U_LAYOUT_API U_EXPORT
361-
#define U_LAYOUTEX_API U_EXPORT
362-
#define U_IO_API U_EXPORT
363-
#define U_TOOLUTIL_API U_EXPORT
357+
// SwiftFoundationICU Changes: hide all C++ public symbols
358+
// Rationale: When FoundationInternationalization tests are executed,
359+
// we effectively load two ICU instances into memory:
360+
//
361+
// 1) The system ICU loaded by XCTest via system Foundation;
362+
// 2) The package ICU SwiftFoundation utilizes.
363+
//
364+
// These two ICUs cause symbol collisions for dyld due to the fact that
365+
// all public C++ symbols share a global namespace and coalesce across all loaded dylibs.
366+
// Consequently, we encounter sporadic test failures in SwiftFoundation as dyld
367+
// arbitrarily selects ICU symbols and occasionally chooses the system one.
368+
//
369+
// To address this issue, we resolved to hide all C++ APIs,
370+
// ensuring they are not weakly referenced and potentially bound to
371+
// the system ICU implementation.
372+
//
373+
// This solution proves effective for SwiftFoundation,
374+
// as it does not actually utilize the C++ APIs.
375+
#define U_DATA_API __attribute__((visibility("hidden")))
376+
#define U_COMMON_API __attribute__((visibility("hidden")))
377+
#define U_I18N_API __attribute__((visibility("hidden")))
378+
#define U_LAYOUT_API __attribute__((visibility("hidden")))
379+
#define U_LAYOUTEX_API __attribute__((visibility("hidden")))
380+
#define U_IO_API __attribute__((visibility("hidden")))
381+
#define U_TOOLUTIL_API __attribute__((visibility("hidden")))
364382
#elif defined(U_STATIC_IMPLEMENTATION)
365383
#define U_DATA_API
366384
#define U_COMMON_API

0 commit comments

Comments
 (0)