2012-11-30 29 views
73

我想用一個全局組標誌編譯一個項目,這意味着在我的頂層的CMakeLists.txt文件我已經指定:覆蓋編譯標誌爲單個文件

ADD_DEFINITIONS (-Wall -Weffc++ -pedantic -std=c++0x) 

然而,對於一個(我們說「foo.cpp」)在一個子目錄中,我想切換 編譯標誌爲不適用-WeffC++(包含的商業庫,我無法更改)。爲了簡化,只-Wall使用的情況下,我想:

SET_SOURCE_FILES_PROPERTIES(foo.cpp PROPERTIES COMPILE_FLAGS -Wall) 
ADD_EXECUTABLE(foo foo.cpp) 

,沒有工作。 我也試過

SET_PROPERTY(SOURCE foo.cpp PROPERTY COMPILE_FLAGS -Wall) 
ADD_EXECUTABLE(foo foo.cpp) 

ADD_EXECUTABLE(foo foo.cpp) 
SET_TARGET_PROPERTIES(foo PROPERTIES COMPILE_FLAGS -Wall) 

,其中既不工作。

最後,我試圖消除這種確定指標:

REMOVE_DEFINITIONS(-Weffc++) 
ADD_EXECUTABLE(foo foo.cpp) 
ADD_DEFINITIONS(-Weffc++) 

,也沒有工作(意思是,我得到一個關於商業庫很多風格的警告)。 (**注:被抑制的警告,如果我不重新包括-WeffC++指令可執行建成後)

我也試着暫時刪除編譯標誌: http://www.cmake.org/pipermail/cmake/2007-June/014614.html ,但沒有幫幫我。

有沒有一個優雅的解決方案呢?

+1

等待,如果你的最後一次嘗試的作品,它的建成,但只後,可能這不是一個緩存的問題?進行更改後嘗試刪除CMakeCache。 – Cameron

+0

相關,請參閱[如何更改編譯器標誌在CMake的只是一個可執行文件?(https://stackoverflow.com/q/24238937/608639)安德烈的回答表明這似乎是更換了新的選擇現有選項的方式。 – jww

回答

87

您的上述嘗試將更多標誌添加到您的文件/目標中,而不是像您期望的那樣覆蓋。例如,從文檔的Properties on Source Files - COMPILE_FLAGS

這些標誌將在這個源文件建立加入到編譯標誌的列表。

你應該能夠做

set_source_files_properties(foo.cpp PROPERTIES COMPILE_FLAGS -Wno-effc++) 

這應該在編譯器命令-Weffc++後加入-Wno-effc++的效果,而後者設定勝反對命令的-Weffc++標誌Foo.cpp中。要查看完整的命令和檢查,這確實是這樣,你可以做

make VERBOSE=1 

順便說一句,在GNU C++標準庫的維護者之一呈現this answer-Weffc++一個漂亮的負面看法。

另一點是,您正在誤用add_definitions,因爲您將此用於編譯器標誌而不是預期的預處理器定義。

這將是優選使用add_compile_options

add_compile_options(-Wall -Weffc++ -pedantic -std=c++0x) 

或CMake的版本< 3。0做更多的東西一樣:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Weffc++ -pedantic -std=c++0x") 

爲了應對進一步在下面的意見的問題,我認爲這是不可能可靠地刪除上的一個文件的標誌。原因是,對於任何給定的源文件,它具有COMPILE_OPTIONSCOMPILE_FLAGS1應用於其目標的,但這些不以任何爲該源文件的屬性顯示。

您可以查看從目標的COMPILE_OPTIONS中剝離問題標誌,然後將其分別應用到每個目標源,並根據需要從特定源文件中省略該標誌。

然而,雖然這可能在許多情況下工作,它有幾個問題。

首先 - source files' properties不包括COMPILE_OPTIONS,只有COMPILE_FLAGS。這是一個問題,因爲目標的COMPILE_OPTIONS可能包含generator expressions,但COMPILE_FLAGS不支持它們。所以你必須在搜索你的旗子的時候適應生成器表達式,如果你的旗子被包含在一個或多個標記中,你甚至可能需要「解析」生成器表達式,看看它是否應該被重新應用到剩餘的源文件。

二 - 因爲CMake的3.0版,目標可以指定INTERFACE_COMPILE_OPTIONS。這意味着目標的依賴關係可以通過其INTERFACE_COMPILE_OPTIONS添加或覆蓋目標的COMPILE_OPTIONS。因此,您還必須遞歸遍歷所有目標的依賴關係(因爲目標的LINK_LIBRARIES列表還可以包含生成器表達式),所以您必須遞歸遍歷所有目標的依賴關係(並非特別簡單的任務),以找到正在應用問題標誌的任何應用程序,並嘗試將其從那些目標也是INTERFACE_COMPILE_OPTIONS

在這個階段的複雜性,我會尋找到一個補丁提交的CMake提供的功能從源文件無條件地刪除特定的標記。


1:請注意,與源文件COMPILE_FLAGS特性,COMPILE_FLAGS財產上的目標已經過時了。

+5

但是,您如何實際設置文件的編譯標誌而不附加它們。例如,我想爲結果目標使用不同的編譯標誌而不是文件,但是因爲它們被追加了,我不得不手動刪除它們。是否沒有屬性不會追加,而只是爲指定的文件/目標設置它們? –

+2

當-fno-flag不可用(並且設置了-flag)時,我們可以做些什麼? – gnzlbg

+0

@Baradé你不能 - 不是源文件。 – Fraser