2016-12-28 227 views
5

我有一個C++項目,它使用CMake作爲其構建系統。我想以下行爲:在默認情況下優化CMake

如果cmake的被調用爲cmake ..,然後CMAKE_CXX_FLAGS-O3 -Wall -Wextra

如果cmake的被調用爲cmake .. -DCMAKE_BUILD_TYPE=Debug,然後CMAKE_CXX_FLAGS-g -Wall -Wextra

我嘗試以下

message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") 

set(CMAKE_CXX_FLAGS "-O3 -Wall -Wextra") 
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra") 

但這有一個大問題。首先,如果使用第二次調用,則將-O3-g標誌傳遞給編譯器。此外,如果我使用第二次調用並且之後的第一次調用,CMAKE_BUILD_TYPE保留Debug,雖然沒有明確命令 - 所以我得到一個調試版本,雖然我想要一個優化版本。

爲什麼?我能做些什麼來獲得理想的行爲?

回答

10

首先:CMake的推薦使用是始終在命令行上明確指定CMAKE_BUILD_TYPE(當且僅當使用單配置生成器時)。你的用例偏離了這個最佳實踐,所以把這個答案當作「你怎麼做到的」,不一定是「你應該怎麼做」。

爲了解決第一個問題,你應該能夠做到在您的CMakeList早期:

if(NOT CMAKE_BUILD_TYPE) 
    set(CMAKE_BUILD_TYPE Release) 
endif() 

set(CMAKE_CXX_FLAGS "-Wall -Wextra") 
set(CMAKE_CXX_FLAGS_DEBUG "-g") 
set(CMAKE_CXX_FLAGS_RELEASE "-O3") 

這將確保,如果你沒有在所有指定生成類型,它會默認爲「釋放「,因此將使用CMAKE_CXX_FLAGS_RELEASE

第二個難以解決。在命令行(如CMAKE_BUILD_TYPE=Debug)傳遞的變量是由CMake的緩存並且因此在以後的調用重新使用(即是必要的,因爲CMake的可重新觸發本身如果修改它的輸入構建之間)。

唯一的解決方案是讓用戶使用cmake .. -DCMAKE_BUILD_TYPE=Release再次明確地切換構建類型。如果CMake的輸入(CMakeLists.txt文件或它們的依賴關係)自上次CMake運行以來發生了變化,那麼CMake可以重新觸發自己作爲構建的一部分。在這種情況下,它也將在沒有命令行參數(如-DCMAKE_BUILD_TYPE=whatever)的情況下運行,並且將依靠緩存提供與上次相同的值。這種情況與您手動運行cmake ..時無法區分,無需其他參數。

如果沒有在命令行中明確指定,我可以提供一個hacky解決方案來始終將CMAKE_BUILD_TYPE重設爲Release。然而,這也意味着一個構建系統產生的Debug將得到重新生成作爲Release如果自動重新生成發生。我很確定那不是你想要的。

+0

這工作,直到我進行調試構建。在一個調試版本之後,即使使用'cmake ..',所有後續版本都是調試版本 – marmistrz

+0

我不記得我在哪裏讀過它,但從CMakeLists.txt中設置CMAKE_BUILD_TYPE被認爲是不好的做法。喜歡從CMake命令行傳遞它。 – roalz

+0

@marmistrz我已經添加了爲什麼發生這種情況的更新,以及如何「重置」它。我試圖想出一種實現隱式重置的方法,但這並不容易。 – Angew

4

對於具體的發行對象CXX標誌,你應該設置
CMAKE_CXX_FLAGS_RELEASE而不是

CMAKE_CXX_FLAGS

你的情況,你可以使用:

集(CMAKE_CXX_FLAGS「-Wall -Wextra 「)
set(CMAKE_CXX_FLAGS_DEBUG」-g「)
set(CMAKE_CXX_FLAGS_RELEASE」-O3「)

一個更現代的CMake的做法(我建議,如果你正在使用CMake的版本2.8.12或更高版本),在this StackOverflow answer有很好的描述,涉及使用target_compile_options

+0

我會說「-g -O0」。 –

+0

但是當'cmake ..' – marmistrz

+1

@ n.m時,'-O3'不會傳遞給編譯器。 gcc默認不會優化 – marmistrz