On 10/06/2011 08:14 AM, Michael Hertling wrote: > 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
You still could compile b_or_c.cpp into a static library first, no trickery with IMPORTED required. However, if that static library is going to be linked to a shared library, you would need to make sure that CMAKE_SHARED_LIBRARY_CXX_FLAGS is included in the COMPILE_FLAGS of the static library. OTOH, putting the content of b_or_c.cpp into a file that is unconditionally compiled would solve the whole problem in one go... That file would naturally be the client code of what is defined in b.cpp or c.cpp. 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