本项目尽量不造轮子,而是选择符合作者口味的开源库进行组合成一个框架,在开发项目时可以快速完成搭建。以下是本项目的特点:
- 禁止混合C/C++特性:该项目模板可以用于 C/C++ 开发,尽管 C++ 兼容 C,但不推荐混合使用 C/C++,使用 C++ 时应使用纯 C++ 特性,除非有必须使用的 C 库。
- 采用
cmake构建:跨平台和流行度都较好。 - 使用
header-only依赖库:将其全部放置于3rd目录中,这样做的好处是无需配置链接、依赖等库环境,尤其是代码需要经常移动、运行环境无法联网/没有权限安装库、或需要交叉编译部署在不同平台上时,比较方便。 - 采用大规模使用的库:有些库已经成为事实上的“标准库”了,学习这些库的使用具有较好的普适性。
- 使用 c++ 20:主要是使用
coroutine模型进行开发。
项目采用许多好用的第三方库,其中一些已经成为了事实上的标准,被大量程序所使用。选取的过程也是不断寻找、对比、学习、思考、积累的过程。选取标准:
- 具有较好的流行度。
header-only库,没有依赖或依赖库也是header-only的。- 简洁设计、API 清晰易用,生态活跃。
| lib | standard | desc |
|---|---|---|
| asio (non-Boost) | 11/14/17/20 | Boost 网络编程库独立版本 |
| CLI11 | 11 | 命令行参数解析,支持子命令,支持联动配置文件和环境变量。 |
| json | 11 | JSON 编解码库 |
| toml11 | 11/14/17/20 | TOML 编解码 |
| cli | 14 | REPL 库,支持标准输入、文件以及 Telnet 协议(依赖 asio)。 |
| spdlog | 11 | 日志库,其实使用的是一个 fork 版本structlog,支持 JSON 结构化日志。如果你不需要这个特性,使用原版即可。 |
| cinatra | 20 | 高性能、易用 HTTP 库,依赖了另一个 header-only 的 async_simple 库,不再赘述。 |
| backward-cpp | 11 | 调用栈追踪,库本身 header-only,但依赖底层的库,可以接受。 |
| tabulate | 11 | Table maker 库,用于控制台美化输出表格。 |
| sigslot | 14 | 精简发布订阅库,源于 UI 编程中的 signal/slot 机制。 |
| sqlite_orm | 14/17/20 | TODO |
| cereal | 11 | TODO |
| frozen | 14 | 提供编译期冻结的容器,适用于快速启动或只读数据高速查找。 |
| catch2 | 11 | TODO |
| redis | TODO | TODO |
| flatbuffers | TODO | TODO |
如果有好用的库推荐,欢迎 issue!
.
├── 3rd # 第三方依赖库
│ ├── include # 头文件(每个库独立目录)
│ │ ├── ... # 依赖 A
│ │ └── ... # 依赖 B
│ └── lib # 库文件(一般不再细分目录)
├── build # 构建目录/分发目录
├── cmake # cmake 工具
│ └── toolchain # 编译链工具
├── CMakeLists.txt # cmake 构建脚本(推荐使用 cmake 构建项目)
├── config.h # config.h.in 生成的项目配置头文件
├── config.h.in # 项目配置头文件
├── doc # 文档目录
│ ├── CHANGELOG.md # 版本变更文档
│ └── USAGE.md # 软件使用文档
├── etc # 配置文件目录
├── include # 本项目生成 lib 对外提供 API 头文件。若是纯 exe 项目,则为空。
├── lib # 本项目生成 lib 库文件。若是纯 exe 项目,则为空。
├── examples # 一些独立的示例程序
├── README.md # 本项目说明文档
├── scripts # 脚本(部署、备份等)
├── src # 源代码目录
│ ├── app # app 可执行模块
│ ├── cppdemo # cppdemo 可执行模块
│ └── util # C 常用工具模块
├── test # 测试代码目录
├── tmp # 临时文件/未归档文件
└── tools # 工具在 C/C++ 中,依赖搜索包括头文件和库文件。
头文件搜索路径包括:
- 默认搜索路径:系统头文件目录、编译器内置头文件目录等,不需要本项目特别指定的。
- config.h:本项目自身 config 头文件
- include:本项目提供的 lib 对外接口头文件
- 3rd/include:本项目提供的第三方库头文件目录
库文件搜索路径包括:
- 默认搜索路径:系统库文件目录、编译器内置库文件目录等,不需要本项目特别指定的。
- lib:本项目提供的 lib 库目录。
- 3rd/lib:本项目内置的第三方库目录。
当依赖是仅头文件库(header only)时,推荐将其直接放入 3rd/include 目录中,这样第三方库会直接集成进可执行文件中,便于使用,但带来了代码膨胀的问题,不过大部分情况下是可以接受的。
当依赖是预编译库(pre-compiled)时,有两种选择:
- 通过包管理器或源码编译安装依赖:如未特殊指定安装目录,则一般安装到
/usr/local或/usr目录下,一般情况下,上述两个目录都是系统默认的搜索目录。在某些系统中/usr/local并没有加入默认搜索路径,推荐设置加入。 - 下载对应的头文件和库文件,将其放置于
3rd目录下。
通过 CMakeLists.txt 中 project(proj VERSION 0.1.0) 定义与管理项目版本,最终生成 config.h 中版本宏,在代码中可直接使用。
printf("VERSION: %d.%d.%d\n", MYPROJECT_VERSION_MAJOR, MYPROJECT_VERSION_MINOR, MYPROJECT_VERSION_PATCH);
// output:
// VERSION: 0.1.0| standard | GCC | key feature |
|---|---|---|
| c++11 | 4.8 | .. |
| c++14 | 4.9~5.0 | 泛型 lambda 表达式、普通函数返回类型推导 |
| c++17 | 7 | string_view, option |
| c++20 | 10 | coroutine, module |
标准的 cmake 三板斧构建方式:
mkdir build; cd build
cmake ..
cmake --build . # make交叉编译时,项目内置了 arm 和 aarch64 交叉编译工具链设置,如果采用其他的交叉编译链,修改 TOOLCHAIN_PATH 即可。
mkdir build-arm; cd build-arm
cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain/arm-linux-gnueabihf.cmake ..
# cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain/aarch64-linux-gnu.cmake ..
# ...
cmake --build .项目构建完成后,主要包括如下目录
build
├── bin
│ ├── cppdemo # execute file
│ └── etc # copy from ./etc
├── doc
│ ├── CHANGELOG.md # copy from ./doc/CHANGELOG.md
│ └── USAGE.md # copy from ./doc/USAGE.md
└── etc # copy from ./etc, same as bin/etc项目分发即:将项目可执行文件或库部署到目标平台。库的分发比较简单,直接将生成的头文件和目标平台库文件复制到目标平台即可。
可执行程序的分发提供 ./scripts/release.sh 将 build 内容打包为 proj-v{X.Y.Z}.tar.gz 包。
若需分发到其他目标,则使用 tar xfv proj-v0.1.0.tar.gz 解压包即可。
$ tar xfv proj-v0.1.0.tar.gz
proj/bin/
proj/bin/...
proj/doc/
proj/doc/USAGE.md
proj/doc/CHANGELOG.md
proj/etc/
proj/etc/config.json如果项目需要分发源码,使用 ./scripts/archive.sh 将项目所有内容打包为 proj-v{X.Y.Z}-t{%Y%m%d.%H%M}.zip 包。
| ARCH | OS |
|---|---|
| armv7l | Linux 4.19.90-rt35-JARI-WORKS |
| aarch64 | Linux 4.19.90-rt35-JARI-WORKS+ |
| x86_64 | Linux 6.5.0-27-generic #28~22.04.1-Ubuntu |
lynx 是一个服务器守护进程。
started 是一个常规的 cpp 入门程序,里面简明扼要的介绍了 cpp 的常规写法,以及 cpp 项目文件组织的一般原则。该程序仅使用 c++11 及以下标准的 cpp 标准库。
- string
- vector-deque-array
- list-forward list
- map-set-multimap-multiset
- unordered_*
- stack-queue-priority queue
- iterator
- algorithms
app 是一个常规的 app 服务
demo 是一个
daemon 是一个守护进程
- cpplint: Cpplint is a command-line tool to check C/C++ files for style issues according to Google's C++ style guide.