覆盖单个文件的编译标志

我想使用全局标志来编译一个项目,这意味着在我指定的顶层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++ ) 

,也没有工作(这意味着,我收到了很多关于商业图书馆的风格警告)。 (**注意:如果在构build可执行文件之后不重新包含-Weffc ++指令,则警告被抑制。)

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

有没有一个优雅的解决scheme呢?

您的上述尝试将更多的标志添加到您的文件/目标,而不是像您期望的那样覆盖。 例如,从源文件上的属性文件 – COMPILE_FLAGS :

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

你应该能够通过这样做来反制-Weffc++标志

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

这应该会在编译命令后添加-Wno-effc++之后的-Weffc++ ,后者设置-Weffc++获胜。 要查看完整的命令并检查确实如此,可以这样做

 make VERBOSE=1 

另外,GNU C ++标准库的-Weffc++在这个答案中对-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中剥离问题标志,然后将其分别应用于每个目标源,并根据需要从特定的源文件中省略它。

但是,虽然这可以在许多情况下工作,但它有一些问题。

第一个源文件的属性不包括COMPILE_OPTIONS ,只COMPILE_FLAGS 。 这是一个问题,因为目标的COMPILE_OPTIONS可以包含生成器expression式 ,但是COMPILE_FLAGS不支持它们。 所以你必须在search你的旗子的时候适应生成器的expression式,如果你的标志被包含在一个或者多个中,你甚至可能需要“parsing”生成器expression式,看它是否应该被重新应用到其余的源文件。

其次 – 自CMake v3.0以来,目标可以指定INTERFACE_COMPILE_OPTIONS 。 这意味着目标的依赖关系可以通过INTERFACE_COMPILE_OPTIONS添加或覆盖目标的COMPILE_OPTIONS 。 所以你还需要迭代遍历所有目标的依赖关系(不是一个特别容易的任务,因为目标的LINK_LIBRARIES列表也可以包含生成器expression式)来查找正在应用问题标志的任何应用程序,并尝试将其从那些目标也是INTERFACE_COMPILE_OPTIONS

在这个复杂的阶段,我会考虑向CMake提交一个补丁,以提供从源文件中无条件移除特定标志的function。


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