CMake target_include_directories的PUBLIC/PRIVATE/INTERFACE区别
target_include_directories 三个可见性参数的差异与适用场景 三个参数的核心区别是对「包含路径是否作用于当前库自身编译」、「包含路径是否传递给链接当前库的下游目标」两个规则的组合,没有通用最优选项,匹配场景使用即可:
PRIVATE
规则:配置的包含路径仅在编译当前helpers库时生效,所有链接helpers的其他目标都不会继承这条路径配置。
适用场景:路径下的头文件仅在helpers的内部实现文件(.cpp/.c等源码文件)中被引用,完全不会出现在helpers对外暴露的公开头文件里。比如helpers内部实现用了第三方日志库,但是日志库的头文件只在helpers.cpp里include,对外的helpers.h完全没有涉及日志库的内容,那日志库的头文件路径就应该设为PRIVATE,下游链接helpers的目标根本不需要感知这个日志库的存在。INTERFACE
规则:配置的包含路径完全不作用于helpers库自身的编译流程,只有链接了helpers的下游目标才会继承这条路径配置。
适用场景:最典型的就是你当前定义的仅头文件(header-only)库场景——你现在写的add_library(helpers helpers.h)没有添加需要编译的源码文件,库本身不需要编译,自然不需要给自己配置头文件路径,只需要把路径传递给引用它的下游目标即可(注意正规写法是把仅头文件库声明为INTERFACE类型:add_library(helpers INTERFACE helpers.h),对应包含路径也配成INTERFACE即可)。另外给预先编译好的第三方静态/动态库配置头文件路径时也常用这个参数,毕竟预编译库已经是编译完成的二进制文件,不需要再给它传包含路径,只要让链接它的下游能找到对应头文件就行。PUBLIC
规则:配置的包含路径既会在编译helpers自身时生效,也会自动传递给所有链接helpers的下游目标,相当于PRIVATE和INTERFACE的组合效果。
适用场景:路径下的头文件不仅helpers自身的实现源码需要引用,helpers对外暴露的公开头文件(比如你对外提供的helpers.h)里也include了这些头文件,下游只要引用helpers.h就必须能找到这些依赖。比如你在helpers.h里include了Eigen数学库的头文件,helpers自身的cpp实现也需要引用Eigen,那Eigen的头文件路径就必须设为PUBLIC,否则下游编译时会直接报找不到Eigen头文件的错误。
小提示:不要为了省事全用
PUBLIC,不必要的路径传递会导致下游的编译参数污染,增加编译冲突的概率。
内容的提问来源于stack exchange,提问作者Chris

