覆盖单个文件的编译标志

时间:2012-11-30 03:02:37

标签: c++ cmake compiler-warnings

我想使用一组全局标志来编译项目,这意味着在我指定的顶级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 ,但这没有帮助。

对此没有优雅的解决方案吗?

3 个答案:

答案 0 :(得分:107)

您的上述尝试是在您的文件/目标中添加更多标记,而不是像您期望的那样覆盖。例如,来自Properties on Source Files - COMPILE_FLAGS的文档:

  

这个源文件构建时,这些标志将被添加到编译标志列表中。

你应该能够通过

来反击foo.cpp的-Weffc++标志
set_source_files_properties(foo.cpp PROPERTIES COMPILE_FLAGS -Wno-effc++)

这应该具有在-Wno-effc++之后在编译器命令中添加-Weffc++的效果,后一个设置获胜。要查看完整命令并检查确实如此,您可以执行

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_FLAGS 1 ,但这些不会出现在任何一个该源文件的属性。

您可以查看从目标COMPILE_OPTIONS中剥离问题标记,然后将其单独应用于每个目标来源,并根据需要从特定源文件中省略它。 / p>

然而,虽然这可以在许多情况下起作用,但它有几个问题。

首先 - source files' properties不要包含COMPILE_OPTIONS,仅包括COMPILE_FLAGS。这是一个问题,因为目标的COMPILE_OPTIONS可以包含generator expressions,但COMPILE_FLAGS不支持它们。因此,您在搜索国旗时必须适应生成器表达式,实际上您甚至可能需要解析""生成器表达式,如果您的标志包含在一个或多个中,以查看是否应将其重新应用于剩余的源文件。

第二 - 自CMake v3.0起,目标可以指定INTERFACE_COMPILE_OPTIONS。这意味着您的目标的相关性可以通过其COMPILE_OPTIONS添加或覆盖您的目标INTERFACE_COMPILE_OPTIONS。因此,您还必须递归遍历所有目标的依赖项(这不是一项特别简单的任务,因为目标的LINK_LIBRARIES列表也可以包含生成器表达式)以查找正在应用的任何内容问题标志,并尝试将其从这些目标中删除' INTERFACE_COMPILE_OPTIONS也是。

在这个复杂的阶段,我正在寻求向CMake提交补丁,以提供无条件从源文件中删除特定标志的功能。


1:请注意,与源文件上的COMPILE_FLAGS属性不同,不推荐使用目标上的COMPILE_FLAGS属性。

答案 1 :(得分:3)

只需添加到@Fraser的正确答案即可。

如果要向特殊文件夹添加特殊标志,可以执行以下操作:

file(GLOB SPECIAL_SRC_FILES
        "path/one/src/*.cpp"
        "path/two/src/*.cpp")
set_property(SOURCE ${SPECIAL_SRC_FILES} PROPERTY COMPILE_FLAGS -Wno-effc++)

file(GLOB SPECIAL_SRC_FILES
        "path/one/src/*.cpp"
        "path/two/src/*.cpp")
set_source_files_properties(${SPECIAL_SRC_FILES} PROPERTIES COMPILE_FLAGS -Wno-effc++)

请注意,不建议像讨论的here那样使用GLOB

答案 2 :(得分:0)

使用@Fraser答案,我创建了以下代码来处理Qt包含的内容,因为变量包含用分号分隔的多个路径。这意味着我必须首先添加一个foreach()循环并手动创建包含标志 。但是,这让我有一个例外: foo.cpp (该文件现在暂时使用Qt,但是从长远来看,我想删除该依赖关系,并希望确保Qt不会在其他任何地方蔓延)。

find_package(Qt5Core REQUIRED)
set(QT_INCLUDE_PROPERTIES "")
foreach(DIR ${Qt5Core_INCLUDE_DIRS})
    set(QT_INCLUDE_PROPERTIES "${QT_INCLUDE_PROPERTIES} -isystem ${DIR}")
endforeach()
set_source_files_properties(foo.cpp PROPERTIES
    COMPILE_FLAGS
        ${QT_INCLUDE_PROPERTIES}
)

还请注意,我使用-isystem而不是-I来避免Qt标头生成的某些警告(我已启用了大量警告)。

相关问题