覆盖单个文件的编译标志


109

我想使用一组全局标志来编译项目,这意味着在我的顶级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。
卡梅伦

相关内容,请参阅如何仅更改CMake中的一个可执行文件的编译器标志?Andre的答案显示了用新选项替换现有选项的方法。
jww

Answers:


126

上面的尝试是在文件/目标中添加更多标志,而不是像您期望的那样覆盖。例如,从文档中获取源文件的属性-COMPILE_FLAGS

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

您应该能够通过-Weffc++以下方式反击foo.cpp 的标志

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

这应该具有在编译器命令中添加-Wno-effc++after 的效果-Weffc++,并且后者设置为胜。要查看完整的命令并检查是否确实如此,可以执行以下操作

make VERBOSE=1

顺便说一句,在GNU C ++标准库的维护者之一呈现在一个漂亮的负面看法-Weffc++这个答案

另一点是,您add_definitions在某种意义上误用了您将其用于编译器标志,而不是预期的预处理器定义。

最好使用 add_compile_options

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

或对于<3.0的CMake版本,可以执行以下操作:

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

针对以下评论中的其他问题,我相信无法可靠地删除单个文件上的标志。原因是,对于任何给定的源文件,它具有COMPILE_OPTIONS1应用于其目标,但这些不以任何为该源文件的属性显示。COMPILE_FLAGS

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

但是,尽管这在许多情况下都可行,但它有两个问题。

首先- 源文件的属性不包括COMPILE_OPTIONS只,COMPILE_FLAGS。这是一个问题,因为COMPILE_OPTIONS目标的可以包含生成器表达式,但COMPILE_FLAGS不支持它们。因此,在搜索标志时,您必须容纳生成器表达式,实际上,如果您的标志包含在一个或多个标志中,您甚至可能必须“解析”生成器表达式,以查看是否应将其重新应用于其余标志源文件。

其次-自CMake v3.0起,目标可以指定INTERFACE_COMPILE_OPTIONS。这意味着目标的依赖项可以COMPILE_OPTIONS通过的目标添加或覆盖目标的INTERFACE_COMPILE_OPTIONS。因此,您还必须递归地遍历所有目标的依赖项(这不是一个特别容易的任务,因为LINK_LIBRARIES目标的列表也可以包含生成器表达式),以找到所有正在应用问题标记的对象,然后尝试从中将其删除也是目标INTERFACE_COMPILE_OPTIONS

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


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


6
但是,实际上如何分别设置文件的编译标志而不附加它们。例如,我想对生成的目标使用与文件不同的编译标志,但是由于附加了文件,因此必须手动删除它们。没有没有不附加但实际上仅为指定文件/目标设置的属性?
Baradé

2
当-fno-flag不可用(并且已设置-fflag)时,我们该怎么办?
gnzlbg 2015年

@Baradé您不能-不适用于源文件。
弗雷泽2015年

@gnzlbg同样,我们几乎陷入了困境。我已经更新了答案,以提供更多信息(以及在某些情况下可能可行的解决方法)。
弗雷泽

单个文件编译选项设置真的没有解决方法吗?我必须为gcov崩溃的某些文件禁用gcc coverage生成。
Lothar'1

5

只需添加到@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++)

请注意,不建议使用此处讨论的GLOB


0

使用@Fraser答案,我创建了以下代码来处理Qt包含的内容,因为该变量包含由分号分隔的多个路径。这意味着我必须首先添加一个foreach()循环并手动创建include标志。但这使我有一个例外: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标头否则会生成的一些警告(我打开了大量警告)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.