Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

icushim: try using the build-time libicu version #15562

Merged
merged 6 commits into from
Dec 22, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 61 additions & 62 deletions src/corefx/System.Globalization.Native/icushim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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);
Expand All @@ -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)
Expand All @@ -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;
}
}
Expand All @@ -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;
}
}
Expand All @@ -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;
}
}
Expand All @@ -172,19 +208,16 @@ 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--)
{
for (int j = MaxMinorICUVersion; j >= MinMinorICUVersion; j--)
{
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;
}
}
Expand All @@ -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__
Expand Down Expand Up @@ -285,10 +282,12 @@ void ShutdownICUShim()
if (libicuuc != nullptr)
{
dlclose(libicuuc);
libicuuc = nullptr;
}

if (libicui18n != nullptr)
{
dlclose(libicui18n);
libicui18n = nullptr;
}
}
}