From 845da035a50199f53ae805840c92845d0a3573c7 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Fri, 22 Dec 2017 13:25:43 +0100 Subject: [PATCH] icushim: try using the build-time libicu version (#15562) * icushim: try using the build-time libicu version * Based on ICU packaging doc, use major instead of (major, minor) * Verify we can look-up symbols on the build version * First find Major; add FEATURE_FIXED_ICU_VERSION * Move FindSymbolVersion check in OpenICULibraries * Remove FEATURE_FIXED_ICU_VERSION --- src/corefx/System.Globalization.Native/icushim.cpp | 123 ++++++++++----------- 1 file changed, 61 insertions(+), 62 deletions(-) diff --git a/src/corefx/System.Globalization.Native/icushim.cpp b/src/corefx/System.Globalization.Native/icushim.cpp index e97896a..42193ba 100644 --- a/src/corefx/System.Globalization.Native/icushim.cpp +++ b/src/corefx/System.Globalization.Native/icushim.cpp @@ -79,8 +79,38 @@ void GetVersionedLibFileName(const char* baseFileName, int majorVer, int minorVe } } +bool FindSymbolVersion(int majorVer, int minorVer, int subVer, char* symbolName, char* symbolVersion) +{ + // Find out the format of the version string added to each symbol + // First try just the unversioned symbol + if (dlsym(libicuuc, "u_strlen") == nullptr) + { + // Now try just the _majorVer added + sprintf(symbolVersion, "_%d", majorVer); + sprintf(symbolName, "u_strlen%s", symbolVersion); + if ((dlsym(libicuuc, symbolName) == nullptr) && (minorVer != -1)) + { + // Now try the _majorVer_minorVer added + sprintf(symbolVersion, "_%d_%d", majorVer, minorVer); + sprintf(symbolName, "u_strlen%s", symbolVersion); + if ((dlsym(libicuuc, symbolName) == nullptr) && (subVer != -1)) + { + // Finally, try the _majorVer_minorVer_subVer added + sprintf(symbolVersion, "_%d_%d_%d", majorVer, minorVer, subVer); + sprintf(symbolName, "u_strlen%s", symbolVersion); + if (dlsym(libicuuc, symbolName) == nullptr) + { + return false; + } + } + } + } + + return true; +} + // Try to open the necessary ICU libraries -bool OpenICULibraries(int majorVer, int minorVer, int subVer) +bool OpenICULibraries(int majorVer, int minorVer, int subVer, char* symbolName, char* symbolVersion) { char libicuucName[64]; char libicui18nName[64]; @@ -94,7 +124,10 @@ bool OpenICULibraries(int majorVer, int minorVer, int subVer) libicuuc = dlopen(libicuucName, RTLD_LAZY); if (libicuuc != nullptr) { - libicui18n = dlopen(libicui18nName, RTLD_LAZY); + if (FindSymbolVersion(majorVer, minorVer, subVer, symbolName, symbolVersion)) + { + libicui18n = dlopen(libicui18nName, RTLD_LAZY); + } if (libicui18n == nullptr) { dlclose(libicuuc); @@ -109,7 +142,7 @@ bool OpenICULibraries(int majorVer, int minorVer, int subVer) // environment variable. // The format of the string in this variable is majorVer[.minorVer[.subVer]] (the brackets // indicate optional parts). -bool FindLibUsingOverride(int* majorVer, int* minorVer, int* subVer) +bool FindLibUsingOverride(char* symbolName, char* symbolVersion) { char* versionOverride = getenv("CLR_ICU_VERSION_OVERRIDE"); if (versionOverride != nullptr) @@ -121,11 +154,8 @@ bool FindLibUsingOverride(int* majorVer, int* minorVer, int* subVer) int matches = sscanf(versionOverride, "%d.%d.%d", &first, &second, &third); if (matches > 0) { - if (OpenICULibraries(first, second, third)) + if (OpenICULibraries(first, second, third, symbolName, symbolVersion)) { - *majorVer = first; - *minorVer = second; - *subVer = third; return true; } } @@ -134,15 +164,23 @@ bool FindLibUsingOverride(int* majorVer, int* minorVer, int* subVer) return false; } -// Select the highest supported version of ICU present on the local machine // Search for library files with names including the major version. -bool FindLibWithMajorVersion(int* majorVer) +bool FindLibWithMajorVersion(char* symbolName, char* symbolVersion) { - for (int i = MaxICUVersion; i >= MinICUVersion; i--) + // ICU packaging documentation (http://userguide.icu-project.org/packaging) + // describes applications link against the major (e.g. libicuuc.so.54). + + // Select the version of ICU present at build time. + if (OpenICULibraries(MinICUVersion, -1, -1, symbolName, symbolVersion)) { - if (OpenICULibraries(i, -1, -1)) + return true; + } + + // Select the highest supported version of ICU present on the local machine + for (int i = MaxICUVersion; i > MinICUVersion; i--) + { + if (OpenICULibraries(i, -1, -1, symbolName, symbolVersion)) { - *majorVer = i; return true; } } @@ -152,16 +190,14 @@ bool FindLibWithMajorVersion(int* majorVer) // Select the highest supported version of ICU present on the local machine // Search for library files with names including the major and minor version. -bool FindLibWithMajorMinorVersion(int* majorVer, int* minorVer) +bool FindLibWithMajorMinorVersion(char* symbolName, char* symbolVersion) { for (int i = MaxICUVersion; i >= MinICUVersion; i--) { for (int j = MaxMinorICUVersion; j >= MinMinorICUVersion; j--) { - if (OpenICULibraries(i, j, -1)) + if (OpenICULibraries(i, j, -1, symbolName, symbolVersion)) { - *majorVer = i; - *minorVer = j; return true; } } @@ -172,7 +208,7 @@ bool FindLibWithMajorMinorVersion(int* majorVer, int* minorVer) // Select the highest supported version of ICU present on the local machine // Search for library files with names including the major, minor and sub version. -bool FindLibWithMajorMinorSubVersion(int* majorVer, int* minorVer, int* subVer) +bool FindLibWithMajorMinorSubVersion(char* symbolName, char* symbolVersion) { for (int i = MaxICUVersion; i >= MinICUVersion; i--) { @@ -180,11 +216,8 @@ bool FindLibWithMajorMinorSubVersion(int* majorVer, int* minorVer, int* subVer) { for (int k = MaxSubICUVersion; k >= MinSubICUVersion; k--) { - if (OpenICULibraries(i, j, k)) + if (OpenICULibraries(i, j, k, symbolName, symbolVersion)) { - *majorVer = i; - *minorVer = j; - *subVer = k; return true; } } @@ -196,46 +229,10 @@ bool FindLibWithMajorMinorSubVersion(int* majorVer, int* minorVer, int* subVer) bool FindICULibs(char* symbolName, char* symbolVersion) { - int majorVer = -1; - int minorVer = -1; - int subVer = -1; - - if (!FindLibUsingOverride(&majorVer, &minorVer, &subVer) && - !FindLibWithMajorMinorVersion(&majorVer, &minorVer) && - !FindLibWithMajorMinorSubVersion(&majorVer, &minorVer, &subVer) && - // This is a fallback for the rare case when there are only lib files with major version - !FindLibWithMajorVersion(&majorVer)) - { - // No usable ICU version found - return false; - } - // Find out the format of the version string added to each symbol - // First try just the unversioned symbol - if (dlsym(libicuuc, "u_strlen") == nullptr) - { - // Now try just the _majorVer added - sprintf(symbolVersion, "_%d", majorVer); - sprintf(symbolName, "u_strlen%s", symbolVersion); - if ((dlsym(libicuuc, symbolName) == nullptr) && (minorVer != -1)) - { - // Now try the _majorVer_minorVer added - sprintf(symbolVersion, "_%d_%d", majorVer, minorVer); - sprintf(symbolName, "u_strlen%s", symbolVersion); - if ((dlsym(libicuuc, symbolName) == nullptr) && (subVer != -1)) - { - // Finally, try the _majorVer_minorVer_subVer added - sprintf(symbolVersion, "_%d_%d_%d", majorVer, minorVer, subVer); - sprintf(symbolName, "u_strlen%s", symbolVersion); - if (dlsym(libicuuc, symbolName) == nullptr) - { - return false; - } - } - } - } - - return true; - + return FindLibUsingOverride(symbolName, symbolVersion) || + FindLibWithMajorVersion(symbolName, symbolVersion) || + FindLibWithMajorMinorVersion(symbolName, symbolVersion) || + FindLibWithMajorMinorSubVersion(symbolName, symbolVersion); } #endif // __APPLE__ @@ -285,10 +282,12 @@ void ShutdownICUShim() if (libicuuc != nullptr) { dlclose(libicuuc); + libicuuc = nullptr; } if (libicui18n != nullptr) { dlclose(libicui18n); + libicui18n = nullptr; } -} +} \ No newline at end of file -- 2.7.4