定义ICU_ROOT时FindICU.cmake头文件目录错误的问题排查
Homebrew安装的ICU在CMake中头文件路径识别异常问题
默认FindICU.cmake的头文件查找逻辑
默认的FindICU.cmake查找头文件目录的逻辑如下:
find_path(ICU_INCLUDE_DIR NAMES "unicode/utypes.h" HINTS ${icu_roots} PATH_SUFFIXES ${icu_include_suffixes} DOC "ICU include directory")
其中icu_roots由ICU_ROOT构建:
list(APPEND icu_roots "${ICU_ROOT}")
icu_include_suffixes固定为include:
list(APPEND icu_include_suffixes "include")
问题现象
当ICU_ROOT设置为macOS下Homebrew的ICU安装路径/usr/local/opt/icu4c时,出现头文件目录识别错误:
-- Found the following ICU libraries: -- uc (required): /usr/local/opt/icu4c/lib/libicuuc.dylib -- i18n (required): /usr/local/opt/icu4c/lib/libicui18n.dylib -- --------FindICU.cmake search debug-------- -- ICU binary path search order: /usr/local/opt/icu4c -- ICU include path search order: /usr/local/opt/icu4c -- ICU library path search order: /usr/local/opt/icu4c -- ---------------- -- --------FindICU.cmake results debug-------- -- ICU found: TRUE -- ICU_VERSION number: 70.1 -- ICU_ROOT directory: /usr/local/opt/icu4c -- ICU_INCLUDE_DIR directory: /Applications/Xcode14.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.0.sdk/usr/include -- ICU_LIBRARIES: /usr/local/opt/icu4c/lib/libicuuc.dylib;/usr/local/opt/icu4c/lib/libicui18n.dylib -- gencnval program: ICU_GENCNVAL_EXECUTABLE=/usr/local/opt/icu4c/bin/gencnval -- icuinfo program: ICU_ICUINFO_EXECUTABLE=/usr/local/opt/icu4c/bin/icuinfo -- genbrk program: ICU_GENBRK_EXECUTABLE=/usr/local/opt/icu4c/bin/genbrk -- icu-config program: ICU_ICU-CONFIG_EXECUTABLE=/usr/local/opt/icu4c/bin/icu-config -- genrb program: ICU_GENRB_EXECUTABLE=/usr/local/opt/icu4c/bin/genrb -- gendict program: ICU_GENDICT_EXECUTABLE=/usr/local/opt/icu4c/bin/gendict -- derb program: ICU_DERB_EXECUTABLE=/usr/local/opt/icu4c/bin/derb -- pkgdata program: ICU_PKGDATA_EXECUTABLE=/usr/local/opt/icu4c/bin/pkgdata -- uconv program: ICU_UCONV_EXECUTABLE=/usr/local/opt/icu4c/bin/uconv -- gencfu program: ICU_GENCFU_EXECUTABLE=/usr/local/opt/icu4c/bin/gencfu -- makeconv program: ICU_MAKECONV_EXECUTABLE=/usr/local/opt/icu4c/bin/makeconv -- gennorm2 program: ICU_GENNORM2_EXECUTABLE=/usr/local/opt/icu4c/sbin/gennorm2 -- genccode program: ICU_GENCCODE_EXECUTABLE=/usr/local/opt/icu4c/sbin/genccode -- gensprep program: ICU_GENSPREP_EXECUTABLE=/usr/local/opt/icu4c/sbin/gensprep -- icupkg program: ICU_ICUPKG_EXECUTABLE=/usr/local/opt/icu4c/sbin/icupkg -- gencmn program: ICU_GENCMN_EXECUTABLE=/usr/local/opt/icu4c/sbin/gencmn -- Makefile.inc data: ICU_MAKEFILE_INC=/usr/local/opt/icu4c/lib/icu/Makefile.inc -- pkgdata.inc data: ICU_PKGDATA_INC=/usr/local/opt/icu4c/lib/icu/pkgdata.inc -- uc library found: ICU_UC_FOUND=ON -- uc library found (compat name): UC_FOUND=ON -- uc library: ICU_UC_LIBRARIES=/usr/local/opt/icu4c/lib/libicuuc.dylib -- i18n library found: ICU_I18N_FOUND=ON -- i18n library found (compat name): I18N_FOUND=ON -- i18n library: ICU_I18N_LIBRARIES=/usr/local/opt/icu4c/lib/libicui18n.dylib -- ----------------
可见ICU_INCLUDE_DIR被错误识别为Xcode SDK路径,而非Homebrew安装路径下的/usr/local/opt/icu4c/include。
已尝试的解决方案(均无效)
NO_CACHENO_DEFAULT_PATHNO_CMAKE_SYSTEM_PATHNO_PACKAGE_ROOT_PATHNO_CMAKE_PATHNO_CMAKE_ENVIRONMENT_PATHNO_SYSTEM_ENVIRONMENT_PATHNO_CMAKE_FIND_ROOT_PATH
问题根源分析
问题出在find_path的查找优先级:尽管指定了HINTS ${icu_roots},但CMake在查找unicode/utypes.h时,会优先在系统SDK路径中找到匹配文件(Xcode SDK中自带旧版ICU头文件),且find_path默认会返回第一个找到的路径,而非HINTS中指定路径下的文件。
另外,Homebrew安装的ICU路径/usr/local/opt/icu4c/include/unicode/utypes.h确实存在,但由于系统SDK路径的优先级更高,导致find_path跳过了HINTS中的路径。
补丁方案
方案一:强制优先从指定路径查找
修改FindICU.cmake中的find_path调用,添加NO_CMAKE_SYSTEM_PATH参数,强制优先从HINTS指定的路径中查找头文件:
find_path(ICU_INCLUDE_DIR NAMES "unicode/utypes.h" HINTS ${icu_roots} PATH_SUFFIXES ${icu_include_suffixes} NO_CMAKE_SYSTEM_PATH DOC "ICU include directory")
方案二:调整路径优先级
将HINTS改为PATHS(PATHS的优先级高于系统默认路径),既保留系统路径作为备选,又优先使用指定路径:
find_path(ICU_INCLUDE_DIR NAMES "unicode/utypes.h" PATHS ${icu_roots} PATH_SUFFIXES ${icu_include_suffixes} DOC "ICU include directory")
临时解决方法(无需修改CMake模块)
直接手动指定ICU_INCLUDE_DIR:
set(ICU_INCLUDE_DIR "/usr/local/opt/icu4c/include" CACHE PATH "ICU include directory") find_package(ICU REQUIRED)
内容的提问来源于stack exchange,提问作者danilabagroff
相关产品推荐
相关产品推荐

