2015-04-24 38 views
2

改寫了這個問題。如何使cMake只爲項目中的子目錄使用調試編譯模式?

我有以下問題:

我的項目有幾個二進制文件和庫駐留在主項目文件夾下不同的子目錄。 只需調試其中的一個子集就可以了,而無需在Debug模式下重新編譯整個項目。

我想只能以半自動方式更改此子集的編譯模式。

我該如何使用CMake來完成這項工作?

+2

在CMake invokation期間傳遞構建類型如何?像'cmake .. -DCMAKE_BUILD_TYPE = Debug'。 – Kamiccolo

+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>的變量(「Add Entry」)。你可以定義多個。 如果您的目錄名稱中包含空格,請在變量名稱中替換爲下劃線。不要忘記點擊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

+0

如果你閱讀我的問題,你會看到我想在調試模式下編譯它的一部分。有時候這是必要的,否則我可能會有太多與手頭問題無關的調試消息。 –

+1

@MarcoCosta正如你從2個反應中看到的那樣,問題根本不明確。它可能會變成一個有趣的,所以它是值得重新修飾它。 – Antonio

+0

我編輯了問題和標題。感謝您對如何更好地提出問題的意見。 –

-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) 
相關問題