CMake 库的默认类型与不支持动态库警告
2025-02-20 11:23:59+08:00

CMake 库的默认类型与不支持动态库警告

构建库的默认类

在 CMake 中,添加库目标时,如果不指定库的类型(STATICSHARED),则会根据变量 BUILD_SHARED_LIBS 的值来决定库的类型。

BUILD_SHARED_LIBSON 时默认构建动态库,OFF 时则默认构建静态库。

BUILD_SHARED_LIBS 自身的默认值通常为 ON

add_library(${LIB_NAME} ${LIB_SOURCE})

不支持动态库的警告

现象

我在构建 WebAssembly 应用时,经常在引入第三方库时看到这样的警告:

CMake Warning (dev) at 3rdparty/zlib/CMakeLists.txt:153 (add_library):
  ADD_LIBRARY called with SHARED option but the target platform does not
  support dynamic linking.  Building a STATIC library instead.  This may lead
  to problems.
This warning is for project developers.  Use -Wno-dev to suppress it.

这是因为 WebAssembly 不支持动态库,CMake 将所有构建动态库的目标都转换为了构建静态库。

遇到的问题

但是我自己添加的库目标却没有产生这样的警告,而是构建出了动态库。并且在之后构建可执行文件时产生错误。

CMake 是怎么判断当前平台不支持动态库的?

为什么第三方库产生了警告并自动转换为了构建静态库,而我添加的目标没有警告直接构建了动态库?

现象的原理

通过查阅资料,发现 CMake 是通过 TARGET_SUPPORTS_SHARED_LIBS 属性来判断是否支持动态库的。

emcmake 自动将该属性设为了 FALSE,因此遇到构建静态库时发出了警告并转换为构建静态库。

而引入 Qt 时,Qt 将该值又改为了 TRUE,导致我在这之后添加的目标没有产生警告。

问题的解决办法

解决办法是在引入 Qt 之前将 BUILD_SHARED_LIBS 的值设为和 TARGET_SUPPORTS_SHARED_LIBS 一样。

CMake 中 ON/OFFYES/NOTRUE/FALSE 都是布尔值,可以等价。

get_property(BUILD_SHARED_LIBS GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)

补充

由于设置了变量 BUILD_SHARED_LIBS 的值,如果引入的第三方库中将该变量设为了 option 会产生警告,此类问题的消除方法:

if (POLICY CMP0077)
  cmake_policy(SET CMP0077 NEW)
endif (POLICY CMP0077)

旧版本 Qt 使用 qt_addlibrary 时,会忽略 BUILD_SHARED_LIBS,采用和 Qt 库相同的构建方式。

在 Qt 6.7 版本新增了 QTP0003 来决定策略,为 NEW 时和 BUILD_SHARED_LIBS 一致,为 OLD 时采用和 Qt 库相同的构建方式。

qt_policy(SET QTP0003 NEW)

但是无法通过 if (POLICY QTP0003) 来判断 QTP0003 是否存在,在旧版本上会报错,可以通过判断 Qt 版本来决定是否设置 QTP0003,或者使用 addlibrary 代替 qt_addlibrary

CMake 子目录依赖处理
2024-12-18 21:18:31+08:00

CMake 子目录依赖处理

最近开发的一个项目依赖 libgeotiff,同时 libgeotiff 又依赖 libtiff,我将他们都加入 thirdparty 中,通过 add_subdirectory 添加进项目中。

  • thirdparty
    • CMakeLists.txt
    • libgeotiff
    • libtiff
add_subdirectory(libtiff)
add_subdirectory(libgeotiff/libgeotiff)

这样 CMake 仍会报错:

CMake Error at /usr/local/lib/python3.10/dist-packages/cmake/data/share/cmake-3.25/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find TIFF (missing: TIFF_LIBRARY TIFF_INCLUDE_DIR)

因为 find_package 无法查找项目内的目标。

可以通过 FetchContent 来解决这个问题:

include(FetchContent)
FetchContent_Declare(
    TIFF
    SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libtiff"
    OVERRIDE_FIND_PACKAGE
)
add_subdirectory(libgeotiff)
CMake 忽略第三方库的安装指令
2024-12-18 21:18:31+08:00

CMake 忽略第三方库的安装指令

通过 CMake 在项目中包含第三方库的源码时,如果直接包含,install 的时候会同时安装第三方库。如果不想安装第三方库,可以添加 EXCLUDE_FROM_ALL

add_subdirectory(${目录} EXCLUDE_FROM_ALL)