3

In a CMake superbuild it is desirable to run the dependency build and project build the first time and then never again (unless desired). The problem I'm having with options and set is that I haven't found a way to set an initial value and then override it.

Top-Level CMakeLists.txt

if( NOT DEFINED USE_SUPERBUILD )
    set( USE_SUPERBUILD on CACHE BOOL "Set the superbuild to run once" )
else()
    set( USE_SUPERBUILD ${USE_SUPERBUILD} CACHE BOOL "Set the superbuild to run once" FORCE )
    message( "Forcing USE_SUPERBUILD AFTER: ${USE_SUPERBUILD}" )
endif()

superbuild.cmake

ExternalProject_Add( my_proj
        DEPENDS ${MYPROJ_DEPENDENCIES}
        SOURCE_DIR ${PROJECT_SOURCE_DIR}
        CMAKE_ARGS -DUSE_SUPERBUILD:BOOL=off ${EXTRA_CMAKE_ARGS}
        INSTALL_COMMAND ""
        BINARY_DIR ${INSTALL_DIR} ) 

Running it

Forcing USE_SUPERBUILD AFTER: off

CMakeCache.txt

//Set the superbuild to run once
USE_SUPERBUILD:BOOL=on

When the superbuild gets to the end, it calls this script with USE_SUPERBUILD=off and it should store this value. For some reason even though it is getting to the else() block and setting off but the CMakeCache.txt still contains on. So the problem here is clearly the ExternalProject_add not calling the build such that it uses the root of the CMAKE_BINARY_DIR when you started. Is there a way to make ExternalProject_add work the same as calling cmake -DUSE_SUPERBUILD=off ../project_source_folder?

Cameron Lowell Palmer
  • 21,528
  • 7
  • 125
  • 126
  • Would it be acceptable to just have the dependency build create an empty file when it succeeded and then just do an `if(EXISTS that_file)` from within the suberbuild `CMakeLists`? – ComicSansMS Jan 19 '18 at 11:16
  • 1
    Wouldn't it a solution to just negate your variables meaning? If you check in your code for something like `if (NOT SKIP_SUPERBUILD)` it would handle both cases `off` and undefined. And at the end `set( SKIP_SUPERBUILD 1 CACHE BOOL "Set the skip superbuild to run once" FORCE)`. – Florian Jan 19 '18 at 11:41
  • @Florian you could just cache on the first call, the issue is that the CACHE call the second time NEVER updates even with FORCE. It stays on. – Cameron Lowell Palmer Jan 19 '18 at 12:07
  • @CameronLowellPalmer Overwriting with `FORCE` does work every time.I use that a lot. There has to be another problem. Can you go more into detail what you mean with "it calls this script with `USE_SUPERBUILD=off`"? I think we need a [mcve] here to reproduce your problem. – Florian Jan 19 '18 at 12:12
  • And I suspect that it is ExternalProject_Add is the issue. – Cameron Lowell Palmer Jan 19 '18 at 12:28

2 Answers2

1

Turning my comment into an answer

I would just negate your variables meaning. To run superbuild only once I would do:

superbuild.cmake

if (SKIP_SUPERBUILD) 
    return()
endif()

[...]

# superbuild run finished, don't run again
set(SKIP_SUPERBUILD ON CACHE BOOL "Set to skip superbuild")

Reference

Florian
  • 39,996
  • 9
  • 133
  • 149
0

Switch from ExternalProject_add

The working directory is wrong with ExternalProject_add can be replaced with add_custom_target.

add_custom_target( my_proj ALL
        DEPENDS ${MYPROJ_DEPENDENCIES}
        COMMAND cmake -DUSE_SUPERBUILD:BOOL=off ${EXTRA_CMAKE_ARGS} --build ${CMAKE_BINARY_DIR}
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
        COMMENT "Starting build ${CMAKE_BINARY_DIR}" )
Cameron Lowell Palmer
  • 21,528
  • 7
  • 125
  • 126