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

Reply via email to