icushim: try using the build-time libicu version (#15562)
authorTom Deseyn <tom.deseyn@gmail.com>
Fri, 22 Dec 2017 12:25:43 +0000 (13:25 +0100)
committerJan Vorlicek <janvorli@microsoft.com>
Fri, 22 Dec 2017 12:25:43 +0000 (13:25 +0100)
* 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

index e97896a..42193ba 100644 (file)
@@ -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