CMake中PUBLIC/PRIVATE/INTERFACE关键字使用场景示例咨询
CMake 三个依赖关键字对应场景示例
1. PRIVATE:依赖仅用于库实现,未出现在头文件
场景说明:依赖的所有内容都只在库的.cpp/.c等实现文件中使用,对外暴露的头文件完全不涉及该依赖的任何类型、函数、宏定义。
示例代码:
- 头文件
math_utils.h
#pragma once // 完全不涉及spdlog的任何内容 int add(int a, int b);
- 实现文件
math_utils.cpp
#include "math_utils.h" // 仅在实现中引入spdlog依赖 #include <spdlog/spdlog.h> int add(int a, int b) { spdlog::info("调用add方法,参数a={}, b={}", a, b); return a + b; }
- CMakeLists.txt 片段
add_library(math_utils math_utils.cpp math_utils.h) # spdlog仅实现用,用PRIVATE target_link_libraries(math_utils PRIVATE spdlog::spdlog)
说明:这种情况下,链接math_utils的其他目标不需要知道spdlog的存在,也不会继承spdlog的头文件路径、链接选项
2. PUBLIC:依赖同时用于库的实现和头文件
场景说明:依赖的内容不仅在实现中用到,对外暴露的头文件也用到了该依赖的类型、函数、宏,所有使用该库的目标都需要访问该依赖的内容。
示例代码:
- 头文件
custom_button.h
#pragma once // 头文件中用到Qt的QPushButton类型,必须引入Qt头文件 #include <QPushButton> class CustomButton : public QPushButton { Q_OBJECT public: explicit CustomButton(QWidget* parent = nullptr); };
- 实现文件
custom_button.cpp
#include "custom_button.h" CustomButton::CustomButton(QWidget* parent) : QPushButton(parent) { // 实现中也用到Qt的接口 setText("自定义按钮"); }
- CMakeLists.txt 片段
add_library(ui_widgets custom_button.cpp custom_button.h) # Qt依赖头文件和实现都用,用PUBLIC target_link_libraries(ui_widgets PUBLIC Qt::Widgets)
说明:链接ui_widgets的其他目标会自动继承Qt::Widgets的头文件路径、链接选项,因为要编译用到custom_button.h的代码时,必须能找到QPushButton的定义
3. INTERFACE:依赖仅用于库的头文件,未被实现使用
场景说明:依赖的内容只出现在对外暴露的头文件中,库自身的实现完全没有用到该依赖的任何功能,仅使用该库的目标需要访问该依赖的内容。
示例代码:
- 头文件
callback_registry.h
#pragma once // 头文件中用到absl::FunctionRef类型 #include <absl/functional/function_ref.h> #include <functional> class CallbackRegistry { public: void register_callback(absl::FunctionRef<void(int)> cb); private: std::function<void(int)> m_stored_cb; };
- 实现文件
callback_registry.cpp
#include "callback_registry.h" // 实现中没有引入任何absl的头文件,也没有调用absl的任何接口 void CallbackRegistry::register_callback(absl::FunctionRef<void(int)> cb) { // 仅做类型转换,absl::FunctionRef的隐式转换由编译器处理 m_stored_cb = cb; }
- CMakeLists.txt 片段
add_library(callback_registry callback_registry.cpp callback_registry.h) # absl仅头文件用到,实现没用,用INTERFACE target_link_libraries(callback_registry INTERFACE abseil::absl_function_ref)
说明:这种情况下,callback_registry自身编译的时候不需要链接absl的对应库,只有使用callback_registry的目标,在编译包含callback_registry.h的代码时,需要找到absl的头文件,因此会继承该依赖
内容的提问来源于stack exchange,提问作者Alex Armbruster
相关产品推荐
相关产品推荐

