TsFile C++ 安装与打包规范

本文档定义 TsFile C++ 动态库、公共头文件、CMake package、pkg-config module、 命令行工具和平台软件包的统一发布接口。

发布边界

Apache 社区投票通过的源码发布是正式发布物。Homebrew、Debian/Ubuntu 等平台 软件包和便携归档包均由对应源码发布构建。各产物的名称、版本和来源信息遵循对应 平台的打包规范,并可追溯到该源码发布。

安装布局

CMake 安装使用 GNUInstallDirs,安装位置由 CMAKE_INSTALL_PREFIXDESTDIR 以及各平台的标准目录变量共同确定。

内容安装路径
动态库${CMAKE_INSTALL_LIBDIR}/libtsfile.*
公共头文件${CMAKE_INSTALL_INCLUDEDIR}/tsfile/...
CMake package${CMAKE_INSTALL_LIBDIR}/cmake/TsFile/
pkg-config module${CMAKE_INSTALL_LIBDIR}/pkgconfig/libtsfile.pc
命令行工具${CMAKE_INSTALL_BINDIR}/tsfile-cli
项目声明文件${CMAKE_INSTALL_DATADIR}/doc/tsfile/

公共头文件位于:

<prefix>/<includedir>/tsfile/...

CMake package 和 pkg-config module 向消费者提供的 include 根目录是:

<prefix>/<includedir>

用户代码使用:

#include <tsfile/reader/tsfile_reader.h>
#include <tsfile/writer/tsfile_writer.h>

开发组件包含用户使用 TsFile C++ API 所需的全部头文件。安装完成后,用户无需 访问源码树或构建目录即可编译使用这些头文件的程序。

CMake 用户接口

安装内容包括:

  • TsFileConfig.cmake
  • TsFileConfigVersion.cmake
  • TsFileTargets.cmake
  • imported target TsFile::tsfile

标准用法为:

find_package(TsFile CONFIG REQUIRED)

add_executable(my_application main.cpp)
target_link_libraries(my_application PRIVATE TsFile::tsfile)

TsFile::tsfile 提供以下 usage requirements:

  • <prefix>/<includedir> include 根目录;
  • TsFile 公共接口要求的 C++ 标准;
  • 公共接口要求的平台库;
  • 公共头文件可观察到的编译定义;
  • 公共接口中出现的依赖 target。

用户通过 CMAKE_PREFIX_PATHTsFile_DIR 指定 TsFile 的安装位置:

cmake -S . -B build -DCMAKE_PREFIX_PATH=/opt/tsfile

生成的 CMake package 使用相对安装路径,可随安装 prefix 一起移动,不包含源码树 或构建目录的绝对路径。

pkg-config 用户接口

pkg-config module 名称为 libtsfile

pkg-config --cflags --libs libtsfile

libtsfile.pc 的核心字段为:

Name: Apache TsFile
Version: <source-release-version>
Libs: -L${libdir} -ltsfile
Cflags: -I${includedir}

其中 includedir 对应 <prefix>/<includedir>,CMake 和 pkg-config 因此产生相同 的头文件使用形式:

#include <tsfile/...>

仅在动态库内部使用的依赖不进入公开的 include 和 link 参数。类型出现在公共头 文件中的依赖通过 Requires 表达。

公共 API

公共 API 包括:

  • 公共头文件清单中的入口头文件;
  • 入口头文件公开并记录的类型、函数、常量和枚举;
  • 面向外部用户安装的 C wrapper;
  • CMake target TsFile::tsfile
  • pkg-config module libtsfile
  • 命令行工具的稳定参数和退出码。

动态库使用默认隐藏的符号可见性,只导出公共 API 和 C wrapper 所需符号。私有 实现符号和捆绑依赖符号不进入公开符号表。

动态库版本与 ABI

TsFile C++ 对外发布动态库,不发布公共静态 libtsfile

源码发布版本和 ABI epoch 分别设置:

set(TSFILE_VERSION <source-release-version>)
set(TSFILE_ABI_VERSION 1)

set_target_properties(tsfile PROPERTIES
    VERSION "${TSFILE_VERSION}"
    SOVERSION "${TSFILE_ABI_VERSION}")

在 ELF 平台上,源码版本 2.4.0、ABI epoch 1 对应:

libtsfile.so -> libtsfile.so.1
libtsfile.so.1 -> libtsfile.so.2.4.0
libtsfile.so.2.4.0

动态库记录的 SONAME 为:

libtsfile.so.1

在 macOS 上对应:

libtsfile.dylib -> libtsfile.1.dylib
libtsfile.1.dylib -> libtsfile.2.4.0.dylib
libtsfile.2.4.0.dylib

ABI epoch 仅在发生 ABI 不兼容修改时增加。以下修改改变 ABI epoch:

  • 删除或修改已导出的函数和符号;
  • 修改公共函数的参数或返回类型;
  • 修改公共类或结构体的二进制布局;
  • 修改虚函数表;
  • 修改公共枚举的值或底层类型;
  • 修改编译选项或功能宏并导致公共类型布局变化;
  • 修改平台工具链或 C++ runtime 基线并破坏既有二进制兼容性。

新增不改变既有二进制布局的 API、修复内部实现以及保持 ABI 的功能扩展沿用原 ABI epoch。开发版本后缀不进入 SONAME。

依赖配置

构建使用显式的依赖来源配置:

TSFILE_DEPENDENCY_PROVIDER=system
TSFILE_DEPENDENCY_PROVIDER=bundled

原生软件包

Homebrew 和 Debian/Ubuntu 软件包使用 system 配置:

  • 依赖由平台软件包管理器安装和升级;
  • libtsfile 动态链接平台提供的依赖;
  • 软件包元数据声明准确的运行时和开发依赖;
  • 软件包中不安装依赖库的私有副本;
  • 公共 CMake 和 pkg-config 元数据不包含依赖源码树或构建树路径。

All-in-one 便携包

All-in-one 便携包使用 bundled 配置:

  • 第三方依赖版本固定;
  • 对外提供的 TsFile 库仍然是动态库;
  • 第三方依赖私有链接到 libtsfile,或放入归档包的私有动态库目录;
  • 私有动态库使用相对于归档目录的运行时查找路径;
  • 第三方符号不进入 TsFile 公共 ABI;
  • 归档包包含与实际内容一致的第三方 LICENSENOTICE
  • 归档包不捆绑 glibc;
  • 每个归档包对应明确的操作系统、CPU 架构、工具链和最低系统版本。

systembundled 配置分别生成独立产物。

软件包组成

软件包使用三个逻辑组件:

组件内容Debian/Ubuntu 名称
runtime带 ABI 版本的动态库和声明文件libtsfile1
development公共头文件、无版本链接名、CMake package、pkg-config modulelibtsfile-dev
toolstsfile-cli 和声明文件tsfile-tools

Homebrew Formula 在一个安装单元中提供动态库、开发文件和命令行工具。

All-in-one 便携包的目录结构为:

tsfile-<version>-<platform>/
├── bin/
   └── tsfile-cli
├── include/
   └── tsfile/
├── lib/
   ├── libtsfile.*
   ├── cmake/TsFile/
   └── pkgconfig/libtsfile.pc
├── LICENSE
└── NOTICE

当前平台软件包范围包括:

  • macOS Homebrew;
  • Debian/Ubuntu DEB;
  • Linux all-in-one TGZ。

RPM 不在当前软件包范围内。

软件包生成

公开的 Homebrew 和 Debian/Ubuntu 软件包使用各平台的原生打包元数据。

CPack 用于:

  • 生成 all-in-one TGZ
  • 生成本地 DEB 验证产物;
  • 验证 runtime、development 和 tools 的文件归属;
  • 验证版本、架构、依赖、许可证和组件关系。

CPack 配置由 TsFile 顶层项目统一生成,第三方依赖不修改 TsFile 的 CPack package 名称、版本、许可证或维护者信息。

验收标准

每个受支持的平台配置通过以下检查:

  1. 使用临时非默认 prefix 和 DESTDIR 完成安装。
  2. 安装结果只包含动态库、公共头文件、CMake package、pkg-config module、CLI 和 对应声明文件。
  3. 独立 CMake consumer 通过 find_package(TsFile CONFIG REQUIRED)TsFile::tsfile 完成编译、链接和运行。
  4. 独立 pkg-config consumer 通过 libtsfile.pc 完成编译、链接和运行。
  5. Consumer 代码使用 #include <tsfile/...> 完成小型 TsFile 读写。
  6. 每个公共入口头文件均可在独立 translation unit 中编译。
  7. CMake package 和 pkg-config module 不包含源码目录或构建目录路径。
  8. 动态库的文件名、SONAME、软链接和导出符号与 ABI epoch 一致。
  9. 同一 ABI epoch 内的新版本通过二进制兼容检查。
  10. 原生软件包使用平台依赖,不包含依赖库的私有副本。
  11. 软件包完成安装、升级和卸载后没有非预期残留文件。
  12. All-in-one 包移动目录后仍可运行,并只从归档包内部解析私有动态库。
  13. 每个产物的 LICENSENOTICE、版本、架构和来源信息与实际内容一致。