cmake:根据多个find_package()调用的结果启用功能

时间:2016-11-04 18:33:03

标签: build cmake

我有一个包含可视调试器的项目,只有在找到一组软件包时我才想构建它。我不想强制只想构建基础应用程序的用户安装所有调试器依赖项,因此在运行find_package()时我不会将其标记为REQUIRED。

现在我的构建看起来像这样:

  

./ CMakeList

find_package(gazebo)
find_package(OpenGL)
find_package(GLUT)

add_subdirectory(debugger)
  

./调试器/ CMakeList

if(NOT gazebo_FOUND OR NOT OpenGL_FOUND OR NOT GLUT_FOUND)
    return()
endif()

这很好用,但随着调试器依赖项列表的增长,使用 if 来启用/禁用调试器构建看起来很笨拙。

是否有更好的替代方法可以根据find_package()的结果启用此子目录的构建?

调试器不是我项目中唯一能够以这种方式启用/禁用的东西,所以我需要一个通用的解决方案来根据找到的包启用功能。

2 个答案:

答案 0 :(得分:1)

CMake已经没有已经制作了一个宏或一个函数来一次检查变量列表。

但编写一个能够做到这一点的函数并不困难。 E.g:

# Usage: feature_check(FEATURE_VAR REQUIRED_VAR [REQUIRED_VAR2 ...])
#
# Set FEATURE_VAR to TRUE if all required vars are TRUE,
# Otherwise set FEATURE_VAR to FALSE.
function(feature_check FEATURE_VAR REQUIRED_VAR)
    foreach(var ${REQUIRED_VAR} ${ARGN})
        if(NOT ${var})
            set(${FEATURE_VAR} "FALSE" PARENT_SCOPE)
            return()
        endif(NOT ${var})
    endforeach(var ${REQUIRED_VAR} ${ARGN})
    set(${FEATURE_VAR} "TRUE" PARENT_SCOPE)
endfunction(feature_check FEATURE_VAR REQUIRED_VAR)

所以,在你的情况下你可以使用

# In CMakeList.txt, after find_package()
feature_check(USE_DEBUGGER gazebo_FOUND OpenGL_FOUND GLUT_FOUND)

# In debugger/CMakeList.txt
if(NOT USE_DEBUGGER)
    return()
endif(NOT USE_DEBUGGER)
...

答案 1 :(得分:0)

将我的评论转化为答案

我看到三种选择:

  1. 使用FindPkgConfig模块将搜索包合并为一个调用/结果变量?类似的东西:

    pkg_check_modules(DEBUGGER_DEPS gazebo gl glu)
    

    会在pkg-config的平台上 - 通过使用上述调用的结果也使find_package()调用过时:

    target_compile_options(debugger PUBLIC ${DEBUGGER_DEPS_CFLAGS})
    target_link_libraries(debugger PUBLIC ${DEBUGGER_DEPS_LDFLAGS})
    
  2. 使用CMakeDependentOption模块将布尔值组合成一个选项,以检查

    之类的内容
    CMAKE_DEPENDENT_OPTION(
         BUILD_DEBUGGER "Build debugger" ON
                        "gazebo_FOUND;OpenGL_FOUND;GLUT_FOUND" OFF
    )
    
  3. 或者 - 如果项目很大 - 也许只编写我自己的my_target_link_libraries()函数,其中包含必要的if (TARGET ...)依赖项检查,如果失败则从所有/默认构建中删除主目标:

    function(my_target_link_libraries _target)
        foreach(_dep IN ITEMS ${ARGN})
            if (TARGET _dep)
                target_link_libraries(${_target} ${_dep})
            else()
                message(STATUS "No target '${_dep}' found. Disabling '${_target}' build")
                set_target_properties(${_target} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD 1)
            endif()
        endforach()
    endfunction()
    
    my_target_link_libraries(debugger GLUT::GLUT ...)