C++ 覆盖单个文件的编译标志

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13638408/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:34:21  来源:igfitidea点击:

Override compile flags for single files

c++cmakecompiler-warnings

提问by J.B. Brown

I would like to use a global set of flags for compiling a project, meaning that at my top-level CMakeLists.txt file I have specified:

我想使用一组全局标志来编译项目,这意味着在我的顶级 CMakeLists.txt 文件中我指定了:

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

However, for a specific file (let's say "foo.cpp") in a subdirectory, I want to switch the compile flags to not apply -Weffc++ (included commercial library I cannot change). To simplify the situation to use only -Wall, I tried:

但是,对于子目录中的特定文件(比如“foo.cpp”),我想将编译标志切换为不应用 -Weffc++(包含的商业库,我无法更改)。为了简化仅使用 -Wall 的情况,我尝试了:

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

, which did not work. I also tried

,这不起作用。我也试过

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

and

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

, in which neither worked.

,其中都没有工作。

Finally, I tried removing this defintion:

最后,我尝试删除此定义:

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

, which also did not work (meaning, I get a lot of style warnings about the commercial library). (**Note: The warnings ARE suppressed if I DO NOT re-include the -Weffc++ directive after the executable is built.)

,这也不起作用(意思是,我收到了很多关于商业库的样式警告)。(**注意:如果在构建可执行文件后我不重新包含 -Weffc++ 指令,则会抑制警告。)

I also tried temporarily removing the compile flags: http://www.cmake.org/pipermail/cmake/2007-June/014614.html, but that didn't help.

我还尝试暂时删除编译标志:http: //www.cmake.org/pipermail/cmake/2007-June/014614.html,但这没有帮助。

Is there not an elegant solution to this?

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

回答by Fraser

Your attempts above are adding further flags to your file/target rather than overwriting as you seem to expect. For example, from the docs for Properties on Source Files - COMPILE_FLAGS:

您上面的尝试是向您的文件/目标添加更多标志,而不是像您预期的那样覆盖。例如,来自源文件属性的文档- COMPILE_FLAGS

These flags will be added to the list of compile flags when this source file builds.

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

You should be able to countermand the -Weffc++flag for foo.cpp by doing

您应该可以-Weffc++通过执行以下操作来取消 foo.cpp的标志

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

This should have the effect of adding -Wno-effc++after -Weffc++in the compiler command, and the latter setting wins. To see the full command and check that this is indeed the case, you can do

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

make VERBOSE=1

As an aside, one of the maintainers of the GNU C++ Standard Library presents a pretty negative opinion on -Weffc++in this answer.

顺便说一句,GNU C++ 标准库的维护者之一-Weffc++这个答案中提出了非常负面的意见。

Another point is that you're misusing add_definitionsin the sense that you're using this for compiler flags rather than the intended preprocessor definitions.

另一点是,您正在滥用add_definitions,因为您将它用于编译器标志而不是预期的预处理器定义。

It would be preferable to use add_compile_options

最好使用 add_compile_options

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

or for CMake versions < 3.0 to do something more like:

或者对于 CMake 版本 < 3.0 做一些更像:

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


In response to further questions in the comments below, I believe it's impossible to reliably removea flag on a single file. The reason is that for any given source file, it has the COMPILE_OPTIONSand COMPILE_FLAGS1of its target applied, but these don't show up in any of the properties for that source file.

针对以下评论中的进一步问题,我认为不可能可靠地删除单个文件上的标志。原因是对于任何给定的源文件,它应用了目标的COMPILE_OPTIONS1,但这些不会显示在该源文件的任何属性中。COMPILE_FLAGS

You could look at stripping the problem flag from the target's COMPILE_OPTIONS, then applying it to each of the target's sources individually, omitting it from the specific source file as required.

您可以考虑从目标的 中剥离问题标志COMPILE_OPTIONS,然后将其单独应用于每个目标的源,根据需要从特定的源文件中省略它。

However, while this could work in many scenarios, it has a couple of problems.

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

First - source files' propertiesdon't include COMPILE_OPTIONS, only COMPILE_FLAGS. This is a problem because the COMPILE_OPTIONSof a target can include generator expressions, but COMPILE_FLAGSdoesn't support them. So you'd have to accommodate generator expressions while searching for your flag, and indeed you'd maybe even have to "parse" generator expressions if your flag was contained in one or more to see whether it should be re-applied to the remaining source files.

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

Second - since CMake v3.0, targets can specify INTERFACE_COMPILE_OPTIONS. This means that a dependency of your target can add or override your target's COMPILE_OPTIONSvia its INTERFACE_COMPILE_OPTIONS. So you'd further have to recursively iterate through all your target's dependencies (not a particularly easy task since the list of LINK_LIBRARIESfor the target can also contain generator expressions) to find any which are applying the problem flag, and try and remove it from those targets' INTERFACE_COMPILE_OPTIONStoo.

其次 - 从 CMake v3.0 开始,目标可以指定INTERFACE_COMPILE_OPTIONS. 这意味着您的目标的依赖项可以COMPILE_OPTIONS通过其INTERFACE_COMPILE_OPTIONS. 因此,您还必须递归遍历所有目标的依赖项(这不是一项特别容易的任务,因为LINK_LIBRARIES目标的列表还可以包含生成器表达式)以找到任何应​​用问题标志的项,并尝试将其从那些项中删除目标”INTERFACE_COMPILE_OPTIONS也是。

At this stage of complexity, I'd be looking to submit a patch to CMake to provide the functionality to remove a specific flag unconditionally from a source file.

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



1: Note that unlike the COMPILE_FLAGSproperty on source files, the COMPILE_FLAGSproperty on targets is deprecated.

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

回答by Levon

Just adding to @Fraser's correct answer.

只是添加到@Fraser 的正确答案。

In case if you want to add the special flag to specific folders you could do:

如果您想将特殊标志添加到特定文件夹,您可以执行以下操作:

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

or

或者

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++)

Note that its not recommended to use GLOB as discussed here

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

回答by Alexis Wilke

Using @Fraser answer, I created the following to handle the Qt includes because the variable includes multiple paths separated by semicolons. This means I had to first add a foreach()loop and create the include flags by hand. But that allows me to have one exception: foo.cpp(that one file uses Qt for now but long term I want to remove that dependency and I want to make sure not Qt creeps in anywhere else).

使用@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}
)

Notice also that I use the -isysteminstead of -Ito avoid some warnings that Qt headers otherwise generate (I have a ton of warnings turned on).

另请注意,我使用-isystem代替-I来避免 Qt 标头以其他方式生成的一些警告(我打开了大量警告)。