如何使cMake仅对项目中的一部分目录使用Debug编译模式?

时间:2015-04-24 12:58:43

标签: cmake

重新提出问题。

我有以下问题:

我的项目有几个二进制文件和库,它们位于主项目文件夹下的不同子目录中。 能够仅调试它们的一部分是有用的,而无需在调试模式下重新编译整个项目。

我希望只能以半自动方式更改此子集的编译模式。

如何使用CMake完成此操作?

2 个答案:

答案 0 :(得分:3)

如果更改构建类型,将从头开始重新编译整个项目。通常,您保留2个独立的构建树,一个配置的调试和一个配置的版本。

请注意CMAKE_BUILD_TYPE可以从命令行或cmake-gui设置,您不应该在CMakeLists.txt文件中设置它。

<小时/> 要在调试模式下仅编译项目的某些部分,可以按以下步骤操作。在主CMakeLists.txt中,在包含任何子目录之前,定义以下宏:

macro (CHECK_IF_DEBUG)
  if (NOT (CMAKE_BUILD_TYPE MATCHES Debug))
    get_filename_component(THIS_DIR ${CMAKE_CURRENT_SOURCE_DIR} NAME)
    STRING(REGEX REPLACE " " "_" THIS_DIR ${THIS_DIR}) #Replace spaces with underscores
    if (DEFINED DEBUG_${THIS_DIR})
      message(STATUS "Note: Targets in directory ${THIS_DIR} will be built Debug") #A reminder
      set (CMAKE_BUILD_TYPE Debug)
    endif()
  endif()
endmacro()

然后,在每个子目录中添加(在CMakelists.txt的开头)宏调用

 CHECK_IF_DEBUG()

当您需要临时调试项目的一个部分(子目录)时,在cmake-gui中打开您的项目,并定义一个名为DEBUG_<DirectoryName>的变量(&#34; Add Entry&#34;)。您可以定义多个。 如果您的目录名称包含空格,则在变量名称中将其替换为下划线。不要忘记点击cmake-gui的ConfigureGenerate以使更改生效。分配给变量的值并不重要,可以保留为空。

完成调试后,返回cmake-gui并删除相应的条目。 别忘了ConfigureGenerate

我在一个小项目中对它进行了测试,似乎工作正常。

注意:如果您在相同的CMakeLists.txt(=在同一子目录中)中创建了多个目标(add_libraryadd_executable),我还没有办法让一个目标构建在一个目标中,一个目标构建在另一个目标中:唯一可以计算的是CMake完成解析文件时CMAKE_BUILD_TYPE目录的值。

在回答您的评论时,您可以在构建时打印提醒,方法是在块中添加以下行:

add_custom_target(info_${THIS_DIR} ALL COMMAND echo Targets in directory ${THIS_DIR} are built Debug)

请参阅add_custom_target

答案 1 :(得分:-2)

我带来的解决方案如下:

我创建了一个宏,它将读取二进制目录中的配置文件,并根据其内容设置编译类型。

当此文件发生更改时,cMake将仅在该目录上重新运行,并且还将重新编译它,因为其依赖项已更改。这正是我所需要的。

宏如下:

macro(set_buildmode _local_app_name)
  if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/BUILDMODE)
    file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/BUILDMODE ${CMAKE_BUILD_TYPE})
    message(" *** Creating file 'BUILDMODE' with type '${CMAKE_BUILD_TYPE}' for '${_local_app_name}'")
  endif()
  configure_file( ${CMAKE_CURRENT_BINARY_DIR}/BUILDMODE 
                  ${CMAKE_CURRENT_BINARY_DIR}/BUILDMODE.junk)
  file(READ ${CMAKE_CURRENT_BINARY_DIR}/BUILDMODE CMAKE_BUILD_TYPE)
  string(STRIP ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE)
endmacro()

为了确保我总是知道我是否已经在发布以外的任何其他模式下编译,我也有这个宏:

macro(add_buildmode_message _local_app_name_full)
  get_filename_component(_local_app_name ${_local_app_name_full} NAME)
  add_custom_target(Checking_BUILDMODE_for_${_local_app_name} ALL
                    COMMAND bash -c "if [ \"${CMAKE_BUILD_TYPE}\" != \"Release\" ] ; then echo -e \"       ${BoldRed}${_local_app_name} was built with type '${CMAKE_BUILD_TYPE}'${ColourReset}\" ; fi"
                 VERBATIM)
endmacro()

以下是其用法示例:

set(appname example)
###### Call set_buildmode here
set_buildmode(${appname})
set(${appname}_SRCS
example.cpp
main.cpp)

set(${appname}_HDRS
example.h)

set(${appname}_LIBS)

set(BUILD_SHARED_LIBS ON)

execute_process(COMMAND ln -frs ${${appname}_HDRS} ${CMAKE_BINARY_DIR}/include/
                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

set(MYLIB_VERSION_MAJOR 2)
set(MYLIB_VERSION_MINOR 1)
set(MYLIB_VERSION_PATCH 0)
set(MYLIB_VERSION_STRING
    ${MYLIB_VERSION_MAJOR}.${MYLIB_VERSION_MINOR}.${MYLIB_VERSION_PATCH})
add_library(${appname} ${${appname}_SRCS})
target_link_libraries (${appname} ${${appname}_LIBS} ${CMAKE_THREAD_LIBS_INIT})

##### Add the fake target for checking the build mode
add_buildmode_message(${appname})
set_target_properties(${appname} PROPERTIES VERSION ${MYLIB_VERSION_STRING}
                       SOVERSION ${MYLIB_VERSION_MAJOR})
install(TARGETS ${appname} DESTINATION lib)