为了抑制来自我在应用程序中使用的库的编译器警告,我在使用target_link_libraries
添加它们之前,手动将它们的目录作为系统库包含在target_include_directories(myapp SYSTEM ...)
中,如下所示:
add_executable(myapp myapp.cpp)
target_include_directories(myapp SYSTEM
PRIVATE "extern/lib/include"
)
target_link_libraries(myapp lib::lib)
但是,如果lib
的开发者决定改变include路径,这会让人觉得很麻烦,也会被破坏。如果只使用target_link_library
,这不会是一个问题,但是,当然,它们是通过-I
包含的,我会再次收到来自这个include的编译器警告。
有没有更优雅、更安全的方法来实现这一点?如果target_link_libraries
有一个SYSTEM
选项来告诉cmake将其作为系统库包含进来,那就太好了。
5条答案
按热度按时间2izufjch1#
我定义了一个函数来处理这个问题:
我现在可以调用
target_link_libraries_system(myapp lib::lib)
,并从目标的属性中读取包含目录。这可以扩展为选择性地指定
PUBLIC|PRIVATE|INTERFACE
范围:如果库没有设置其
INTERFACE_INCLUDE_DIRECTORIES
属性,这个扩展版本也会输出一个警告。js5cn81o2#
我修改了塞巴斯蒂安的解决方案以包括范围。
svmlkihl3#
这是在CMake discourse和@ben.boeckel(CMake开发人员)中提出的问题,回答说:
IMPORTED目标应该已经将其包含目录视为SYSTEM。可以使用NO_SYSTEM_FROM_IMPORTED目标属性来禁用它。
ovfsdjhp4#
可能的陷阱:如果你和我一样,通过启用toplevel目录中的所有警告来启动每个项目...
...那么,这显然会被所有子项目继承(比如git子模块,或者其他)。
如果是 * 这种 * 情况,解决方案很简单-请具体说明:在子目录中执行此操作,并且/或者使用
target_compile_options
,以获得更好的效果:nwlqm0z15#
首先,您还没有指定要链接的目标是否为
IMPORTED
。我假设它是IMPORTED
,因为IMPORTED
目标的包含目录默认为SYSTEM
。注意:可以禁用此行为。在CMake v3.25之前,可以使用NO_SYSTEM_FROM_IMPORTED
或IMPORTED_NO_SYSTEM
之一。对于CMake 3.25和更高版本,可以修改目标的SYSTEM
属性。这通常只剩下通过
add_subdirectory
添加的目标,其中包括FetchContent
在非find_package
模式下添加的目标。在这种情况下,您可以看到FetchContent
Q&A here和add_subdirectory
Q&A here。总之,对于CMake v3.25之前的版本,请使用一种解决方法,将INTERFACE_INCLUDE_DIRECTORIES
目标属性复制/移动到INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
目标属性。对于CMake v3.25或更高版本,您可以修改SYSTEM
目标属性或SYSTEM
目录属性,或者使用add_subdirectory
/FetchContent_Declare
的SYSTEM
参数。