On 10/06/2011 07:04 AM, Michael Wild wrote: > On Thu 06 Oct 2011 05:17:00 AM CEST, Michael Hertling wrote: >> On 10/05/2011 10:47 PM, Robert Dailey wrote: >>> In my particular CMake project, I have three CPP files: >>> >>> a.cpp >>> b.cpp >>> c.cpp >>> >>> I want 'a.cpp' to be compiled in all configurations (release & debug).<br> >>> I only want 'b.cpp' to be compiled in DEBUG configuration.<br> >>> I only want 'c.cpp' to be compiled in RELEASE configuration. >>> >>> How can I do this? I need something similar to the `debug` and `optimized` >>> keywords that are accepted by the `target_link_libraries()` CMake operation. >> >> If it's okay that b.cpp and c.cpp are compiled in all configurations but >> incorporated in the final binaries only in the DEBUG or in the RELEASE >> configuration, respectively, you might do the following: >> >> CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) >> PROJECT(IMPORTEDEMPTY C) >> SET(CMAKE_VERBOSE_MAKEFILE ON) >> # Add library for DEBUG: >> FILE(WRITE ${CMAKE_BINARY_DIR}/b.c "void b(void){}\n") >> ADD_LIBRARY(b STATIC b.c) >> # Add library for RELEASE: >> FILE(WRITE ${CMAKE_BINARY_DIR}/c.c "void c(void){}\n") >> ADD_LIBRARY(c STATIC c.c) >> # Add empty static library: >> FILE(WRITE ${CMAKE_BINARY_DIR}/empty.c "") >> ADD_LIBRARY(empty STATIC empty.c) >> # Reimport empty static library: >> EXPORT(TARGETS empty NAMESPACE imported FILE importedempty.cmake) >> INCLUDE(${CMAKE_BINARY_DIR}/importedempty.cmake) >> # Impose IMPORTED_LINK_INTERFACE_LIBRARIES_{DEBUG,RELEASE} properties: >> FOREACH(i IN LISTS CMAKE_CONFIGURATION_TYPES ITEMS ${CMAKE_BUILD_TYPE}) >> STRING(TOUPPER "${i}" i) >> IF(i STREQUAL "DEBUG") >> SET_TARGET_PROPERTIES(importedempty PROPERTIES >> IMPORTED_LINK_INTERFACE_LIBRARIES_${i} b) >> ELSEIF(i STREQUAL "RELEASE") >> SET_TARGET_PROPERTIES(importedempty PROPERTIES >> IMPORTED_LINK_INTERFACE_LIBRARIES_${i} c) >> ENDIF() >> ENDFOREACH() >> # Specify required dependencies: >> ADD_DEPENDENCIES(importedempty empty b c) >> # Add final binary: >> FILE(WRITE ${CMAKE_BINARY_DIR}/a.c "int main(void){return 0;}\n") >> ADD_EXECUTABLE(a a.c) >> TARGET_LINK_LIBRARIES(a importedempty) >> >> Adventurous, but somewhat clean; see [1] for an explanation, and be >> especially careful with a file named "libc.a" on *nix systems. ;-) >> >> If you really need to avoid the compilation of b.cpp or c.cpp in >> certain configurations, you might try the following approach: >> >> CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) >> PROJECT(RECONF C) >> SET(CMAKE_VERBOSE_MAKEFILE ON) >> FILE(WRITE ${CMAKE_BINARY_DIR}/a.c "int main(void){return 0;}\n") >> FILE(WRITE ${CMAKE_BINARY_DIR}/b.c "void b(void){}\n") >> FILE(WRITE ${CMAKE_BINARY_DIR}/c.c "void c(void){}\n") >> STRING(TOUPPER "${CONF}" CONF) >> IF(CONF STREQUAL "DEBUG") >> ADD_EXECUTABLE(a0 EXCLUDE_FROM_ALL a.c b.c) >> ELSEIF(CONF STREQUAL "RELEASE") >> ADD_EXECUTABLE(a0 EXCLUDE_FROM_ALL a.c c.c) >> ELSE() >> ADD_EXECUTABLE(a0 EXCLUDE_FROM_ALL a.c) >> ENDIF() >> ADD_CUSTOM_TARGET(a ALL >> COMMAND ${CMAKE_COMMAND} >> -DCONF="$<CONFIGURATION>" >> ${CMAKE_BINARY_DIR} >> COMMAND ${CMAKE_COMMAND} >> --build ${CMAKE_BINARY_DIR} >> --config "$<CONFIGURATION>" >> --target a0) >> >> Effectively, when target "a" is built, the project reconfigures itself >> with the current configuration passed in via "CONF" and with a helper >> target "a0" which is made up from the configuration-specific sources; >> finally, this target "a0" is built with the current configuration. >> This can be seen working on *nix with Makefiles, but there might >> be issues with other generators and IDEs. >> >> 'hope that helps. >> >> Regards, >> >> Michael >> >> [1] http://www.mail-archive.com/cmake@cmake.org/msg34680.html > > I think it would be much easier to have a wrapper file, say b_or_c.cpp > which #include's b.cpp or c.cpp at compile time depending on the current > configuration. E.g. like this: > > /////////////////////////////////////////////////////////// > #if defined USE_B_CPP > # include "b.cpp" > #elseif defined USE_C_CPP > # include "c.cpp" > #else // what should happen otherwise? > # error Either USE_B_CPP or USE_C_CPP must be defined! > #endif > /////////////////////////////////////////////////////////// > > > And then in your CMakeLists.txt you do: > > ########################################################### > set_source_files_properties(b_or_c.cpp PROPERTIES > COMPILE_DEFINITIONS_DEBUG USE_B_CPP > COMPILE_DEFINITIONS_RELEASE USE_C_CPP > # what should happen in a default build? > # Or RELWITHDEBINFO and MINSIZEREL? > ) > ###########################################################
Yes, this would work, too, but if neither b.cpp nor c.cpp should be compiled if the current configuration is neither DEBUG nor RELEASE, the b_or_c.cpp file would be effectively empty, and adding an object file compiled from an empty source file to a binary is not 100 % the same as dropping the object file completely - at least with gcc and even with -Os. However, it's a quite negligible effect, but linking against an empty static library or building a reconfigured project means *exactly* the same as if b.cpp and c.cpp have been left out. Regards, Michael -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake