16 {
18
19 void* dlhnd = nullptr;
20 for (const auto path : gLibPaths) {
21 dlhnd = dlopen(path, RTLD_LAZY);
22 if (dlhnd) {
23 break;
24 }
25 }
26
27 if (!dlhnd) {
28 SkDEBUGF(
"ICU loader: failed to open libicuuc.\n");
29 return nullptr;
30 }
31
32 int icu_ver = -1;
33
34 bool resolved_required_syms = true;
35
36 auto resolve_sym = [&](
void* hnd,
const char name[],
bool required =
false) ->
void* {
37 static constexpr int kMinVer = 44,
38 kMaxVer = 100;
39
40
41
42 const auto search_to = icu_ver > 0 ? icu_ver : kMaxVer;
43 icu_ver = icu_ver > 0 ? icu_ver : kMinVer;
44
45 for (;;) {
47 if (
auto* addr = dlsym(dlhnd,
sym.c_str())) {
49 }
50
51 if (icu_ver == search_to) {
52 break;
53 }
54
55 icu_ver++;
56 }
57
58 if (required) {
59 resolved_required_syms = false;
60 }
61 return nullptr;
62 };
63
65
66
67
68
69
70
71 #define SKICU_FUNC(fname) *(void**)(&lib.f_##fname) = resolve_sym(dlhnd, #fname, true);
73
74 *(void**)(&lib.f_ubrk_clone_) = resolve_sym(dlhnd, "ubrk_clone");
75 *(void**)(&lib.f_ubrk_safeClone_) = resolve_sym(dlhnd, "ubrk_safeClone");
76 *(void**)(&lib.f_ubrk_getLocaleByType) = resolve_sym(dlhnd, "ubrk_getLocaleByType");
77
78 if (!resolved_required_syms || (!lib.f_ubrk_clone_ && !lib.f_ubrk_safeClone_)) {
79 SkDEBUGF(
"ICU loader: failed to resolve required symbols.");
80 dlclose(dlhnd);
81 return nullptr;
82 }
83
84 return std::make_unique<SkICULib>(lib);
85}
SK_API SkString static SkString SkStringPrintf()
#define SK_RUNTIME_ICU_PATHS