0

I have a project that contains a visual debugger that I want to build only if a group of packages were found. I don't want to force a user that just want to build the base application to install all the debugger dependencies, so I don't mark then as REQUIRED when running find_package().

Right now my build looks like this:

./CMakeList

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

add_subdirectory(debugger)

./debugger/CMakeList

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

This works just fine, but as the list of dependencies for the debugger grows, using this if to enable/disable the debugger build looks clumsy.

Is there a better alternative to enable the build of this sub-directory base on the result of find_package()?

The debugger is not the only thing in my project that I enable/disable this way, so I need a generic solution for enabling features based on the packages found.

Rodrigo Chiossi
  • 591
  • 5
  • 8
  • Have you considered using [`FindPkgConfig`](https://cmake.org/cmake/help/latest/module/FindPkgConfig.html) module to combine the search for packages into a single call/result variable? Something like `pkg_check_modules(DebuggerDeps gazebo gl glu)`? Some more information on the pros/cons can be found e.g. [here](http://stackoverflow.com/questions/10220946/pkg-check-modules-considered-harmful). – Florian Nov 04 '16 at 20:32
  • Or use [`CMakeDependentOption`](https://cmake.org/cmake/help/latest/module/CMakeDependentOption.html) module with something like `CMAKE_DEPENDENT_OPTION(BUILD_DEBUGGER "Build debugger" ON "gazebo_FOUND;OpenGL_FOUND;GLUT_FOUND" OFF)`. But I would - if the project is huge - maybe just write my own `my_target_link_libraries()` function which includes the necessary `if (TARGET ...)` dependency checks and removes the main target from `all`/default build if it fails. – Florian Nov 06 '16 at 20:49

2 Answers2

1

CMake has no already-made a macro or a function to check list of variables at once.

But it is not a difficult to write a function which do that. 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)

So, in you case you may use

# 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)
...
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
0

Turning my comments into an answer

I see three alternatives:

  1. Using FindPkgConfig module to combine the search for packages into a single call/result variable? Something like:

    pkg_check_modules(DEBUGGER_DEPS gazebo gl glu)
    

    would - on platforms with pkg-config - also make the find_package() calls obsolete by using the results of the above call:

    target_compile_options(debugger PUBLIC ${DEBUGGER_DEPS_CFLAGS})
    target_link_libraries(debugger PUBLIC ${DEBUGGER_DEPS_LDFLAGS})
    
  2. Using CMakeDependentOption module to combine the boolean values into a single option to check with something like

    CMAKE_DEPENDENT_OPTION(
         BUILD_DEBUGGER "Build debugger" ON
                        "gazebo_FOUND;OpenGL_FOUND;GLUT_FOUND" OFF
    )
    
  3. Or - if the project is huge - maybe just write my own my_target_link_libraries() function which includes the necessary if (TARGET ...) dependency checks and removes the main target from all/default build if it fails:

    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 ...)
    
Florian
  • 39,996
  • 9
  • 133
  • 149