@@ -79,8 +79,38 @@ void GetVersionedLibFileName(const char* baseFileName, int majorVer, int minorVe
7979 }
8080}
8181
82+ bool FindSymbolVersion (int majorVer, int minorVer, int subVer, char * symbolName, char * symbolVersion)
83+ {
84+ // Find out the format of the version string added to each symbol
85+ // First try just the unversioned symbol
86+ if (dlsym (libicuuc, " u_strlen" ) == nullptr )
87+ {
88+ // Now try just the _majorVer added
89+ sprintf (symbolVersion, " _%d" , majorVer);
90+ sprintf (symbolName, " u_strlen%s" , symbolVersion);
91+ if ((dlsym (libicuuc, symbolName) == nullptr ) && (minorVer != -1 ))
92+ {
93+ // Now try the _majorVer_minorVer added
94+ sprintf (symbolVersion, " _%d_%d" , majorVer, minorVer);
95+ sprintf (symbolName, " u_strlen%s" , symbolVersion);
96+ if ((dlsym (libicuuc, symbolName) == nullptr ) && (subVer != -1 ))
97+ {
98+ // Finally, try the _majorVer_minorVer_subVer added
99+ sprintf (symbolVersion, " _%d_%d_%d" , majorVer, minorVer, subVer);
100+ sprintf (symbolName, " u_strlen%s" , symbolVersion);
101+ if (dlsym (libicuuc, symbolName) == nullptr )
102+ {
103+ return false ;
104+ }
105+ }
106+ }
107+ }
108+
109+ return true ;
110+ }
111+
82112// Try to open the necessary ICU libraries
83- bool OpenICULibraries (int majorVer, int minorVer, int subVer)
113+ bool OpenICULibraries (int majorVer, int minorVer, int subVer, char * symbolName, char * symbolVersion )
84114{
85115 char libicuucName[64 ];
86116 char libicui18nName[64 ];
@@ -94,7 +124,10 @@ bool OpenICULibraries(int majorVer, int minorVer, int subVer)
94124 libicuuc = dlopen (libicuucName, RTLD_LAZY);
95125 if (libicuuc != nullptr )
96126 {
97- libicui18n = dlopen (libicui18nName, RTLD_LAZY);
127+ if (FindSymbolVersion (majorVer, minorVer, subVer, symbolName, symbolVersion))
128+ {
129+ libicui18n = dlopen (libicui18nName, RTLD_LAZY);
130+ }
98131 if (libicui18n == nullptr )
99132 {
100133 dlclose (libicuuc);
@@ -109,7 +142,7 @@ bool OpenICULibraries(int majorVer, int minorVer, int subVer)
109142// environment variable.
110143// The format of the string in this variable is majorVer[.minorVer[.subVer]] (the brackets
111144// indicate optional parts).
112- bool FindLibUsingOverride (int * majorVer, int * minorVer, int * subVer )
145+ bool FindLibUsingOverride (char * symbolName, char * symbolVersion )
113146{
114147 char * versionOverride = getenv (" CLR_ICU_VERSION_OVERRIDE" );
115148 if (versionOverride != nullptr )
@@ -121,11 +154,8 @@ bool FindLibUsingOverride(int* majorVer, int* minorVer, int* subVer)
121154 int matches = sscanf (versionOverride, " %d.%d.%d" , &first, &second, &third);
122155 if (matches > 0 )
123156 {
124- if (OpenICULibraries (first, second, third))
157+ if (OpenICULibraries (first, second, third, symbolName, symbolVersion ))
125158 {
126- *majorVer = first;
127- *minorVer = second;
128- *subVer = third;
129159 return true ;
130160 }
131161 }
@@ -134,15 +164,23 @@ bool FindLibUsingOverride(int* majorVer, int* minorVer, int* subVer)
134164 return false ;
135165}
136166
137- // Select the highest supported version of ICU present on the local machine
138167// Search for library files with names including the major version.
139- bool FindLibWithMajorVersion (int * majorVer )
168+ bool FindLibWithMajorVersion (char * symbolName, char * symbolVersion )
140169{
141- for (int i = MaxICUVersion; i >= MinICUVersion; i--)
170+ // ICU packaging documentation (http://userguide.icu-project.org/packaging)
171+ // describes applications link against the major (e.g. libicuuc.so.54).
172+
173+ // Select the version of ICU present at build time.
174+ if (OpenICULibraries (MinICUVersion, -1 , -1 , symbolName, symbolVersion))
142175 {
143- if (OpenICULibraries (i, -1 , -1 ))
176+ return true ;
177+ }
178+
179+ // Select the highest supported version of ICU present on the local machine
180+ for (int i = MaxICUVersion; i > MinICUVersion; i--)
181+ {
182+ if (OpenICULibraries (i, -1 , -1 , symbolName, symbolVersion))
144183 {
145- *majorVer = i;
146184 return true ;
147185 }
148186 }
@@ -152,16 +190,14 @@ bool FindLibWithMajorVersion(int* majorVer)
152190
153191// Select the highest supported version of ICU present on the local machine
154192// Search for library files with names including the major and minor version.
155- bool FindLibWithMajorMinorVersion (int * majorVer, int * minorVer )
193+ bool FindLibWithMajorMinorVersion (char * symbolName, char * symbolVersion )
156194{
157195 for (int i = MaxICUVersion; i >= MinICUVersion; i--)
158196 {
159197 for (int j = MaxMinorICUVersion; j >= MinMinorICUVersion; j--)
160198 {
161- if (OpenICULibraries (i, j, -1 ))
199+ if (OpenICULibraries (i, j, -1 , symbolName, symbolVersion ))
162200 {
163- *majorVer = i;
164- *minorVer = j;
165201 return true ;
166202 }
167203 }
@@ -172,19 +208,16 @@ bool FindLibWithMajorMinorVersion(int* majorVer, int* minorVer)
172208
173209// Select the highest supported version of ICU present on the local machine
174210// Search for library files with names including the major, minor and sub version.
175- bool FindLibWithMajorMinorSubVersion (int * majorVer, int * minorVer, int * subVer )
211+ bool FindLibWithMajorMinorSubVersion (char * symbolName, char * symbolVersion )
176212{
177213 for (int i = MaxICUVersion; i >= MinICUVersion; i--)
178214 {
179215 for (int j = MaxMinorICUVersion; j >= MinMinorICUVersion; j--)
180216 {
181217 for (int k = MaxSubICUVersion; k >= MinSubICUVersion; k--)
182218 {
183- if (OpenICULibraries (i, j, k))
219+ if (OpenICULibraries (i, j, k, symbolName, symbolVersion ))
184220 {
185- *majorVer = i;
186- *minorVer = j;
187- *subVer = k;
188221 return true ;
189222 }
190223 }
@@ -196,46 +229,10 @@ bool FindLibWithMajorMinorSubVersion(int* majorVer, int* minorVer, int* subVer)
196229
197230bool FindICULibs (char * symbolName, char * symbolVersion)
198231{
199- int majorVer = -1 ;
200- int minorVer = -1 ;
201- int subVer = -1 ;
202-
203- if (!FindLibUsingOverride (&majorVer, &minorVer, &subVer) &&
204- !FindLibWithMajorMinorVersion (&majorVer, &minorVer) &&
205- !FindLibWithMajorMinorSubVersion (&majorVer, &minorVer, &subVer) &&
206- // This is a fallback for the rare case when there are only lib files with major version
207- !FindLibWithMajorVersion (&majorVer))
208- {
209- // No usable ICU version found
210- return false ;
211- }
212- // Find out the format of the version string added to each symbol
213- // First try just the unversioned symbol
214- if (dlsym (libicuuc, " u_strlen" ) == nullptr )
215- {
216- // Now try just the _majorVer added
217- sprintf (symbolVersion, " _%d" , majorVer);
218- sprintf (symbolName, " u_strlen%s" , symbolVersion);
219- if ((dlsym (libicuuc, symbolName) == nullptr ) && (minorVer != -1 ))
220- {
221- // Now try the _majorVer_minorVer added
222- sprintf (symbolVersion, " _%d_%d" , majorVer, minorVer);
223- sprintf (symbolName, " u_strlen%s" , symbolVersion);
224- if ((dlsym (libicuuc, symbolName) == nullptr ) && (subVer != -1 ))
225- {
226- // Finally, try the _majorVer_minorVer_subVer added
227- sprintf (symbolVersion, " _%d_%d_%d" , majorVer, minorVer, subVer);
228- sprintf (symbolName, " u_strlen%s" , symbolVersion);
229- if (dlsym (libicuuc, symbolName) == nullptr )
230- {
231- return false ;
232- }
233- }
234- }
235- }
236-
237- return true ;
238-
232+ return FindLibUsingOverride (symbolName, symbolVersion) ||
233+ FindLibWithMajorVersion (symbolName, symbolVersion) ||
234+ FindLibWithMajorMinorVersion (symbolName, symbolVersion) ||
235+ FindLibWithMajorMinorSubVersion (symbolName, symbolVersion);
239236}
240237
241238#endif // __APPLE__
@@ -285,10 +282,12 @@ void ShutdownICUShim()
285282 if (libicuuc != nullptr )
286283 {
287284 dlclose (libicuuc);
285+ libicuuc = nullptr ;
288286 }
289287
290288 if (libicui18n != nullptr )
291289 {
292290 dlclose (libicui18n);
291+ libicui18n = nullptr ;
293292 }
294- }
293+ }
0 commit comments