使用 CMake 在库中查找符号

Posted

技术标签:

【中文标题】使用 CMake 在库中查找符号【英文标题】:Using CMake to find symbols in libraries 【发布时间】:2018-02-20 03:40:49 【问题描述】:

我正在尝试使用 CMake 来查找外部库是否依赖于另一个库。

示例:HDF5 库可以选择与 zlib 链接 在 Linux 中,这可以通过

找到
readelf -Ws /usr/local/lib/libhdf5.so | grep inflateEnd
54: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND inflateEnd

使用 CMake 似乎可以使用 CheckLibraryExists 找到它

https://cmake.org/cmake/help/v3.0/module/CheckLibraryExists.html

在 Cmake 脚本中

set(CMAKE_REQUIRED_LIBRARIES $HDF5_LIBRARY)
check_library_exists($HDF5_LIBRARY inflateEnd "" NEED_ZLIB)
message($NEED_ZLIB)
if (NEED_ZLIB)
 message("-- ZLIB library is needed...")
else()
 message("-- ZLIB library is not needed...")
endif()

找不到输出

-- Looking for inflateEnd in /usr/local/lib/libhdf5.so - not found
-- ZLIB library is not needed...

因此我做了使用 readelf 的 Cmake 版本,它找到了符号

但是,仍然想知道为什么上面的 Cmake 脚本会失败 :-)

工作版本是

set(have_read_symbols "no")
find_program(read_symbols_prg readelf)
if ($read_symbols_prg MATCHES "readelf")
  set(have_read_symbols "yes")
  message("-- Readelf program found: " $read_symbols_prg) 
  execute_process(COMMAND $read_symbols_prg -Ws $HDF5_LIBRARY OUTPUT_FILE $CMAKE_CURRENT_BINARY_DIR/symbols.txt)
endif()

if ($have_read_symbols MATCHES "yes")
  message("-- Detecting if HDF5 library $HDF5_LIBRARY needs the ZLIB library...")
  file(STRINGS $CMAKE_CURRENT_BINARY_DIR/symbols.txt NEED_ZLIB REGEX "inflateEnd")
  if (NEED_ZLIB)
    message("$color_blue-- ZLIB library is needed...$color_reset")
  else()
    message("-- ZLIB library is not needed...")
  endif(NEED_ZLIB)
endif()

找到符号

-- Detecting if HDF5 library /usr/local/lib/libhdf5.so needs the ZLIB library...
-- ZLIB library is needed...

【问题讨论】:

您可以查阅CMakeError.log 文件了解check_library_exists 失败的原因。实际上,它尝试编译和链接包含函数调用的代码。我猜链接会导致“未定义的引用”,因为 hdf5 本身并没有定义 inflateEnd 函数,而是使用 zlib 中定义的函数。 【参考方案1】:

好的,checkLibraryExists() 的 Cmake 文档没有详细说明如何完成,他们只是说“检查函数是否存在”。 checkLibraryExists() 尝试链接测试程序,根据成功与否,输出变量参数设置为值 1 或为空。

在这种情况下,要查看的符号必须是在 libhdf5.so 中定义的符号,只能使用 zlib 库。对于这种情况,只有一个符号,一个名为“H5Z_DEFLATE”的结构,根据 zlib 案例的#ifdef 添加到库中。

所以,这就是诀窍

check_library_exists($HDF5_LIBRARY H5Z_DEFLATE "" NEED_ZLIB)

但是,对于使用 Visual Studio 的 Windows 案例,这很容易出错,因为要让 check_library_exists() 检测到它,Visual Studio 必须设置一个选项作为 zlib 库的附加依赖项,这不是成功构建库的要求.所以,如果设置了这个选项,check_library_exists 会检测依赖,如果没有设置,则不会。

【讨论】:

对于msbuild 中的check_library_exists(),你可以设置CLLINK env 像set $env:CL="/I\C:\users\user\local\include"set $env:LINK="/LIBPATH:C:\users\user\local\lib" 来帮助它找到zlib 库。

以上是关于使用 CMake 在库中查找符号的主要内容,如果未能解决你的问题,请参考以下文章

在库中使用 CMake "set(XXXX CACHE ...)" 是一个错误吗?

C ++中库中未解析的外部符号

无法解析 android 库中的符号“日志”

arcgis在库中怎么搜索选中

如何在 C++ 静态库中隐藏符号?

如何检测二进制/库中的未定义符号?