CMake接口库的文件可见性设置

编程语言 2026-07-09

我在研究接口库中文件集合的可见性时有一个问题。若我有一个接口库,它有一个头文件集合且其可见性为接口可见,那么使用这个库的消费者能看到的内容就很清楚。可是当我把可见性改为 PRIVATE 时,消费者仍然可以看到头文件的内容,这点让我困惑。

下面有一个示例。请看 CMakeLists.txt 中标注的1.与 2.的注释。共有两个接口库 gggggg1ggg 包含 include/g.hggg1 包含 ggginclude/g1.h。主目标链接到 ggg1。如果这些文件集合的可见性为 INTERFACE,主目标可以访问 include/g.hinclude/g1.h。但如果第二个文件集合被设为 PRIVATE(见下文),我原本以为会失败。不过构建却成功了。

项目根目录包含 CMakeLists.txt,以及子目录 srcbuild。以下是 CMakeLists.txt

# file: CMakeLists.txt
cmake_minimum_required(VERSION 3.30)
project(test20 VERSION 1.0 LANGUAGES CXX)

add_library(ggg INTERFACE)
target_sources(ggg
    INTERFACE 
        FILE_SET  ggg_headers
        TYPE      HEADERS
        BASE_DIRS include
        FILES
            include/g.h
)

add_library(ggg1 INTERFACE)
target_sources(ggg1
    PRIVATE
        FILE_SET  ggg1_headers
        TYPE      HEADERS
        BASE_DIRS include
        FILES
            include/g1.h
)
target_link_libraries(ggg1
    INTERFACE ggg 
)

add_executable(main)
target_sources(main
    PRIVATE
        src/main.cpp
)
target_link_libraries(main
    PRIVATE ggg1
)

以下是主C++源文件:

// file: src/main.cpp
#include <iostream>
#include "g.h"
#include "g1.h"

int main()
{
    g();
    g1();
    return 0;
}

包含目录中有两个文件,g.hg1.h

// file: include/g.h
#ifndef G_H
#define G_H

#include <iostream>
inline void g()
{
    std::cout << "g()\n";
}

#endif

以下是 include/g1.h

// file: include/g1.h
#ifndef G1_H
#define G1_H

#include <iostream>
inline void g1()
{
    std::cout << "g1()\n";
}

#endif

解决方案

这是预期的行为。

  • 因为 include/g.hinclude/g1.h 位于同一个基础目录,
  • gggggg1 的一个接口依赖,ggg1 获得 ggg-Iinclude
  • ggg1main 的一个依赖,main 继承 ggg-Iinclude
  • 构建成功。

如果将文件位置改为 include/g/g.hinclude/g1/g1.h,则构建会失败,因为 main 会获得 -Iinclude/g,而得不到 -Iinclude/g1

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章