我想使用一组全局标志来编译项目,这意味着在我指定的顶级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 ,但这没有帮助。
对此没有优雅的解决方案吗?
答案 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(-Wall -Weffc++ -pedantic -std=c++0x)
或CMake版本< 3.0做更像的事情:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Weffc++ -pedantic -std=c++0x")
在回答下面评论中的其他问题时,我认为无法可靠地删除单个文件上的标记。原因是对于任何给定的源文件,它的目标都应用COMPILE_OPTIONS
和COMPILE_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标头生成的某些警告(我已启用了大量警告)。