重新提出问题。
我有以下问题:
我的项目有几个二进制文件和库,它们位于主项目文件夹下的不同子目录中。 能够仅调试它们的一部分是有用的,而无需在调试模式下重新编译整个项目。
我希望只能以半自动方式更改此子集的编译模式。
如何使用CMake完成此操作?
答案 0 :(得分:3)
如果更改构建类型,将从头开始重新编译整个项目。通常,您保留2个独立的构建树,一个配置的调试和一个配置的版本。
请注意CMAKE_BUILD_TYPE
可以从命令行或cmake-gui设置,您不应该在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的Configure
和Generate
以使更改生效。分配给变量的值并不重要,可以保留为空。
完成调试后,返回cmake-gui并删除相应的条目。 别忘了Configure
和Generate
。
我在一个小项目中对它进行了测试,似乎工作正常。
注意:如果您在相同的CMakeLists.txt(=在同一子目录中)中创建了多个目标(add_library
或add_executable
),我还没有办法让一个目标构建在一个目标中,一个目标构建在另一个目标中:唯一可以计算的是CMake完成解析文件时CMAKE_BUILD_TYPE
目录的值。
在回答您的评论时,您可以在构建时打印提醒,方法是在块中添加以下行:
add_custom_target(info_${THIS_DIR} ALL COMMAND echo Targets in directory ${THIS_DIR} are built Debug)
答案 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)