编写可返回空目标的CMake Find模块是否合法可行?及实现方案
编写支持可选系统替代的Find模块:以libtirpc为例
这种做法完全符合CMake惯例,而且是处理这类"系统功能可替代第三方库"场景的标准方式。CMake的Find模块设计本身就允许根据目标环境的差异调整查找逻辑,官方不少模块也采用类似思路。
核心思路
先判断目标系统是否已经提供了所需功能(比如部分Linux发行版的glibc已集成RPC能力),如果是,就标记依赖已满足;否则再尝试查找第三方库(libtirpc)。同时兼容find_package的REQUIRED参数,当用户明确要求必须依赖时,若两种情况都不满足则报错。
完整的FindTIRPC.cmake示例
# - Try to find TIRPC # Once done, this will define: # TIRPC_FOUND - System has TIRPC or built-in RPC support # TIRPC_INCLUDE_DIRS - The TIRPC include directories # TIRPC_LIBRARIES - The libraries needed to use TIRPC # First check if system has built-in RPC support include(CheckSymbolExists) check_symbol_exists(rpc_createerr rpc/rpc.h HAVE_RPC_IN_STDLIB) if(HAVE_RPC_IN_STDLIB) # System provides RPC functionality natively, no need for libtirpc set(TIRPC_FOUND TRUE) set(TIRPC_INCLUDE_DIRS "") set(TIRPC_LIBRARIES "") else() # Look for libtirpc headers and library find_path(TIRPC_INCLUDE_DIR NAMES tirpc/rpc.h PATHS /usr/include /usr/local/include ) find_library(TIRPC_LIBRARY NAMES tirpc PATHS /usr/lib /usr/local/lib ) set(TIRPC_INCLUDE_DIRS ${TIRPC_INCLUDE_DIR}) set(TIRPC_LIBRARIES ${TIRPC_LIBRARY}) # Handle the REQUIRED argument include(FindPackageHandleStandardArgs) find_package_handle_standard_args(TIRPC DEFAULT_MSG TIRPC_INCLUDE_DIR TIRPC_LIBRARY ) # Mark cache variables for user override mark_as_advanced(TIRPC_INCLUDE_DIR TIRPC_LIBRARY) endif()
在项目中使用
在你的CMakeLists.txt里这样调用:
find_package(TIRPC) # Build your target add_executable(your_rpc_app src/main.c) # Link libraries - CMake ignores empty variables automatically target_link_libraries(your_rpc_app PRIVATE ${TIRPC_LIBRARIES}) # Add include dirs only if needed if(TIRPC_INCLUDE_DIRS) target_include_directories(your_rpc_app PRIVATE ${TIRPC_INCLUDE_DIRS}) endif()
如果代码需要区分两种场景(比如头文件路径不同:rpc/rpc.h vs tirpc/rpc.h),可以在代码里用预编译宏处理:
#ifdef HAVE_RPC_IN_STDLIB #include <rpc/rpc.h> #else #include <tirpc/rpc.h> #endif
然后在CMake中传递这个宏:
if(HAVE_RPC_IN_STDLIB) target_compile_definitions(your_rpc_app PRIVATE HAVE_RPC_IN_STDLIB) endif()
关于合法性与CMake惯例
完全合规。CMake的Find模块体系就是为了处理这类"依赖存在多种形式"的场景:
- 优先使用系统原生功能,减少第三方依赖,符合Linux生态的常规做法
- 兼容
find_package的标准参数(如REQUIRED、QUIET),保持接口一致性 - 官方的Find模块(比如
FindThreads)也会根据系统环境调整查找逻辑,这种模式是被官方认可的
内容的提问来源于stack exchange,提问作者einpoklum
相关产品推荐
相关产品推荐

