}
}
+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];
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);
// 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)
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;
}
}
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;
}
}
// 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;
}
}
// 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--)
{
{
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;
}
}
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__
if (libicuuc != nullptr)
{
dlclose(libicuuc);
+ libicuuc = nullptr;
}
if (libicui18n != nullptr)
{
dlclose(libicui18n);
+ libicui18n = nullptr;
}
-}
+}
\ No newline at end of file