Ralfizzle
Ralfizzle

Reputation: 517

CMake directory hierarchy, building a sub-directory independently

I'm currently dealing with a less than ideal CMake setup that I am trying to rectify. The top level CMakeListsMain.txt contains compiler settings, include directories, macros, etc, which all projects depend on and use. My source tree contains many projects, but I've scaled it down here.

src/ 
  CMakeListsMain.txt  
  project1/  
    -->CMakeLists.txt  
  project2/  
    -->CMakeLists.txt  
  headers/
    -->source headers for every project  

For example CMakeListsMain.txt looks something like this, yet way more complex:

MACRO(USE_BOOST target)  
   target_link_libraries(${target} boost_thread-mt boost_filesystem-mt boost_regex-mt boost_system-mt)  
ENDMACRO(USE_BOOST)  

MACRO(USE_PTHREAD target)  
   target_link_libraries(${target} pthread)  
ENDMACRO(USE_PTHREAD)

add_subdirectory(project1)
add_subdirectory(project2)

Project 1 and 2 both use the macros and other settings in the top level CMakeListsTop.txt

Previously if I wanted to build one project, CMake would have to run on every directory, which is not good.

My question is if I wanted to build each project separately from each other how would I get access to these macros and other settings. Currently I have abstracted out the macros into a different file and have been including that file in the CMakeLists.txt of each project. Doing it this way I would also have to use absolute paths to reference the header files in the source tree instead of using CMAKE_SOURCE_DIR/headers.

I can't really change the layout of the source tree without getting approval, but is there an easier way to do this or something I have overlooked?

Upvotes: 2

Views: 2135

Answers (2)

Roberto
Roberto

Reputation: 3083

Add this macro

MACRO(ADD_PROJECT PROJECT)
  IF(${PROJECT} OR ALL)
    add_subdirectory(${PROJECT})
  ENDIF()
ENDMACRO()

to your top-level CMakeLists.txt, and replace all occurrences of add_subdirectory with

ADD_PROJECT(project1)
ADD_PROJECT(project2)

and so on. Now you can build any single project by calling cmake with the flag -Dproject1=1 etc., or the whole project with -DALL=1.

Upvotes: 1

user1937198
user1937198

Reputation: 5348

You could move the macros and settings out into a module. You can then wrap the module in an include guard to ensure it is only executed once and include it from each of the CMakeLists.txt that need to be built independently.

So for your example, the module file would look like:

IF(NOT DEFINED MAIN_SETTINGS_INCLUDED)
   SET(MAIN_SETTINGS_INCLUDED ON)
   MACRO(USE_BOOST target)  
       target_link_libraries(${target} boost_thread-mt boost_filesystem-mt boost_regex-mt boost_system-mt)  
   ENDMACRO(USE_BOOST)  

   MACRO(USE_PTHREAD target)  
       target_link_libraries(${target} pthread)  
   ENDMACRO(USE_PTHREAD)
ENDIF()

Upvotes: 1

Related Questions