[CMake] Multiple makefile builds in a single in-source tree.

KSpam keesling_spam at cox.net
Thu Oct 4 12:35:41 EDT 2007


Joe,

Although I cannot help you with your specific question, I can tell you how I 
have accomplished multiple builds in a single out-of-source tree.  This same 
process should translate to an in-source tree as well.

I create a build directory in the top-level of my project.  To build, I use 
the following process:

mkdir build;
cd build;
cmake -D CBAKE_BUILD_TYPE:STRING=Debug ..
make -j 3;
cmake -D CBAKE_BUILD_TYPE:STRING=Release ..
make -j 3;

I have to reconfigure the build type, but I took steps in my CMakeLists.txt 
files to ensure that the Debug and Release targets do not clobber each other.  
This allows me to switch between Debug and Release at will without building 
from scratch everytime or having to have separate build directories.

Here is the general process that I used:

-----------------------------------

The main problem I had was making sure that the object files were placed in 
configuration-dependent directories.  I used the following macro to determine 
the target name:

MACRO(__GetTargetName _targetName)
    IF (CMAKE_CONFIGURATION_TYPES)
        set(${_targetName} ${PROJECT_NAME})
    ELSE (CMAKE_CONFIGURATION_TYPES)
        set(${_targetName} "${PROJECT_NAME}-${CMAKE_BUILD_TYPE}")
    ENDIF (CMAKE_CONFIGURATION_TYPES)
ENDMACRO(__GetTargetName)

In my case, CMAKE_CONFIGURATION_TYPES is always set for Visual Studio 
generators (they already handle multiple builds in a single tree).  Also, my 
project names correlate directly to my target names.

The next step is to make sure that the library and executable targets are 
generated with unique names, as I put them all in a common bin or lib 
directory.  To do this, I simply set the "DEBUG_POSTFIX" property 
with "SET_TARGET_PROPERTIES".

Finally I set up an alias, so I do not have to add "-Debug" or "-Release" to 
my arguments to make.

MACRO(__SetAlias)
    IF (NOT CMAKE_CONFIGURATION_TYPES)
        __GetTargetName(targetName)
        ADD_CUSTOM_TARGET(${PROJECT_NAME})
        ADD_DEPENDENCIES(${PROJECT_NAME} ${targetName})
    ENDIF (NOT CMAKE_CONFIGURATION_TYPES)
ENDMACRO(__SetAlias)

-----------------------------------

This process works pretty well for me, but I would like to make improvements.  
For instance, I originally thought I could run the CMake scripts with a 
two-pass process.  From the top-level CMakeLists.txt, I would do the 
following:

# Build Debug targets during the first pass
SET(CMAKE_BUILD_TYPE Debug)
ADD_SUBDIRECTORY(src)

# Build Release targets during the second pass
SET(CMAKE_BUILD_TYPE Release
ADD_SUBDIRECTORY(src)

Such a process would theoretically allow me to build both configurations in 
the same tree without having to reconfigure.  Unfortunately, it does not 
work.

I wonder how difficult it would be to allow this two-pass process.

Thanks,
Justin


More information about the CMake mailing list