如何在Github上创建C++项目并实现代码持续集成和文档自动发布

通过本教程,你将学会如何:

  • 在Github上创建C++代码仓库

  • 通过持续构建工具(Travis CIAppVeyor)实现代码的自动编译、测试

  • 采用Markdown编写用户手册

  • 采用Doxygen编写代码开发文档

  • 实现用户手册和开发文档的自动发布

准备开始吧!

1. 在Github上新建代码仓库并克隆至本地

  • 打开Github,注册账号并登录后找到“New”按钮,或通过新建Github仓库进入新建仓库页面。 输入仓库名即可点击“Create repository”完成空白仓库的创建。 通常建议在建库的时候输入简短仓库介绍信息、勾选“Initialize this repository with a README”创建README.md文档、 以及添加适合于当前建库主要编程语言的.gitignore文件。

create_a_new_repo 
  • 初始代码仓库构建完成如下图所示:

new_repo 
  • 点击“Clone or download”按钮,利用“Clone with SSH”,点击右边按钮复制仓库地址:

copy_clone_ssh_link 
  • 在本地目录下(强烈建议全英文路径且不含空格),通过git clone命令将Github上的远程仓库克隆至本地。

git clone git@github.com:crazyzlj/TutorialCppProject.git

# 屏幕输出:
Cloning into 'TutorialCppProject'...
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (4/4), done.

2. 新建一个简单的C++源码文件,利用CMake构建项目工程,并编译运行

  • 在仓库根目录下新建文件夹,命名为src,用于存放所有项目相关源代码

  • src目录下,创建一个hello_world.cpp的源码文件:

/*!
 * Simple C++ program to display "Hello World"
 */
// Header file <span class="statement">for</span> input output functions
#include<iostream>

// Using the cout and endl function in the std namespace
using std::cout;
using std::endl;

// main function where the execution of program begins
int main() {
    // prints hello world
    cout << "Hello World" << endl;
    return 0;
}
  • 在仓库根目录下新建CMakeLists.txt文件,输入如下代码用于利用src/hello_world.cpp创建可执行程序hello_world。关于CMake的更多介绍请阅读 CMake基础入门CMake语法速查表

cmake_minimum_required (VERSION 3.1)
project (hello_world C CXX)
add_executable(hello_world src/hello_world.cpp)
  • 此时便可以通过运行CMake创建工程,进一步通过C++编译器编译为可执行程序。使用CMake组织源码工程的程序的一般编译步骤为:

cd /path/to/repository  # 进入仓库文件夹
mkdir build             # 创建build文件夹用于编译项目
cd build                # 进入build文件夹
cmake ..                # 采用默认设置运行CMake命令构建项目,如果配置了多个编译环境,我们可以通过 -G 命令指定编译环境和程序位数,如 -G "Visual Studio 14 2015 Win64"
make -j4                # make命令为Unix/Linux平台下GCC、Intel C++等编译器的编译-链接命令
  • 以Visual Studio 2015的开发者命令行工具为例:

cmake_build_vsproj 
  • 利用Visual Studio 2015打开build目录下的hello_world.sln文件,设置hello_world工程为启动项,即可通过Ctrl+F5组合调试程序了:

open_vs_debug 
  • 此外,Visual Studio同样提供了命令行形式的构建工具msbuild,以上两步可以通过命令操作如下:

mkdir build_nmake
cd build
cmake -G "Visual Studio 14 2015 Win64" ..
msbuild.exe ALL_BUILD.vcxproj
# p.s.1 如果编译release版本:
# msbuild.exe ALL_BUILD.vcxproj /p:Configuration=Release
# p.s.2 可通过添加/maxcpucount:4 来并行编译,提高速度
# p.s.3 可通过msbuild.exe INSTALL.vcxproj命令将可执行文件安装至默认或指定目录
#       同样地,如果安装release版本:msbuild.exe INSTALL.vcxproj /p:Configuration=Release

# 编译完成无错误之后,可在Debug或Release文件夹下找到可执行程序hello_world.exe
cd Debug
hello_world.exe
  • 至此,我们已经通过一个简单的hello_world程序跑通了CMake管理源码的基本流程,可以利用git将此阶段性成果进行保存并推送至远程库了。

  • 通过git status命令查看当前仓库的代码变化,如下图所示:

git_status_check_changes 
  • 我们新增了CMakeLists.txtsrc/hello_world.cpp文件,同时也增加了buildbuild_nmake文件夹作为本地的编译目录, 而这些目录我们是不希望上传至Github远程库的,因此,我们首先需要在.gitignore文件中增加对这两个文件夹的过滤规则:

# Build directories
build*/
  • 这时候再次输入git status命令便可看到修改项已变为:修改了.gitignore文件,新增了CMakeLists.txt文件和src文件夹

  • 接下来,通过git命令将所做修改进行保存(git add),并附加上有意义的简要评论git commit -m)以方便日后查找,最后推送至远程库(git push):

git add .gitignore
git commit -m "ignore build folders"
git add .
git commit -m "add hello_world executable for the demo of CMake"
git push origin master
  • 执行完上述命令之后,再次查看Github上的仓库主页,则可以看到刚才提交的两次commit, 点击这里查看示例。

first_push_to_remote_repo 

3. 安装Doxygen、生成默认配置文件,并修改配置以初步生成HTML

  • 通过Doxygen官网下载并安装适合自己的版本

  • 在项目根目录下新建doc文件夹,通过doxygen -s -g创建默认配置文件,-s参数意为忽略注释行以缩减文件大小(~111 kb -> ~13 kb), 其中Doxygen的具体参数含义请查阅官网。相关命令参考如下:

cd /path/to/repository
mkdir doc
cd doc
doxygen -v    # 查看Doxygen版本
doxygen -s -g # 创建默认配置文件

# 屏幕输出:
Configuration file `Doxyfile' created.

Now edit the configuration file and enter

  doxygen Doxyfile

to generate the documentation for your project
  • 接下来,用文本编辑器打开Doxyfile.in进行编辑,下面介绍几个主要设置项:

    • DOXYFILE_ENCODING:文档编码格式,默认的UTF-8适合绝大多数中英文混排场景

    • PROJECT_NAME:项目名

    • PROJECT_NUMBER:项目版本号

    • PROJECT_BRIEF:一句话简短介绍项目,该介绍会显示在帮助页面的主页标题处

    • OUTPUT_DIRECTORY:Doxygen生成文件的输出目录,如果是相对路径,则是相对执行doxygen时的路径, 比如我们最终是要在仓库根目录下执行doxygen的,所以可以设置OUTPUT_DIRECTORY = build_doxygen

    • CREATE_SUBDIRS:默认设置为NO,如果设为YES,Doxygen会在输出文件夹中创建两层共4096个子文件夹以分布式地 存储输出文件,这对于源码非常庞大的项目的性能提升是很有帮助的

    • OUTPUT_LANGUAGE:输出文件语言,默认为English,中文可选的为ChineseChinese-Traditional

    • JAVADOC_AUTOBRIEF:如果设为YES,则会将注释的第一行(直到遇到第一个句点.)解析为简要描述,如果设置为NO, 则需要显式的\brief,因此建议设置为YES

    • QT_AUTOBRIEF:同上,建议设置为YES

    • TOC_INCLUDE_HEADINGS:设置目录中最多包含多少级标题,目前只对Markdown文本有用,需要MARKDOWN_SUPPORT设为YES, 推荐设为3

    • INPUT:指定需要处理的文件/文件夹,多个路径之间用空格分隔,换行用\符,建议使用相对路径,相对执行doxygen时的路径, 比如我们最终是要在仓库根目录下执行doxygen的,所以可以设置INPUT = README.md doc src, 其中README.md即为项目的根目录下的README.md文档,doc文件夹内可以创建多个Markdown文件用于生成用户手册

    • FILE_PATTERNS:如果INPUT中有指定文件夹,则可通过该参数指定多个文件后缀通配符

    • RECURSIVE:是否搜索INPUT中文件夹的子文件夹内容,一般设置为YES

    • EXCLUDE:指定需要排除的文件/文件夹,比如我们并不需要构建hello_world.cpp中的代码注释,则可设置 EXCLUDE = src/hello_world.cpp

    • IMAGE_PATH:图片路径,如我们希望将所有用户手册相关的图片都保存在doc文件夹下,则可设置IMAGE_PATH = ./doc

    • USE_MDFILE_AS_MAINPAGE:是否使用Markdown文档作为网站主页,如果使用则指定其路径,为了便于管理,通常直接使用 项目README.md作为主页

    • GENERATE_HTML:是否生成HTML文档,设置为YES

    • HTML_OUTPUT:设置HTML文档输出路径,默认为相对路径html,即OUTPUT_DIRECTORY/html

    • GENERATE_LATEX:是否生成LaTeX文档, 默认为YES,但是我们目的是生成HTML,所以该参数设置为NO

  • 至此,我们已经初步配置完成了Doxyfile,可以运行查看下效果了:

cd /path/to/repository
doxygen doc/Doxyfile
doxygen_default_blank_homepage 
  • 对于该项目我们希望能够同时有中文主页,该怎么做呢?解决思路很简单,再准备一个用于生成中文网页的Doxyfile和对应的中文文档就OK!

    • 复制README.md,重命名为README-zh-cn.md(如无特殊说明,约定同名文档的中文版为文件名后加上-zh-cn,按照以往惯例中文版 常常命名为.zh-cn,但是Doxygen在处理有两个.的Markdown文件链接时有问题),并修改内容

    • 复制Doxyfile,重命名为Doxyfile.zh-cn,修改相关配置:

      • PROJECT_NAME

      • PROJECT_BRIEF

      • OUTPUT_LANGUAGE

      • INPUT修改为README-zh-cn.md doc src

      • USE_MDFILE_AS_MAINPAGE修改为README-zh-cn.md

      • HTML_OUTPUT:为了与英文版输出路径区分,这里建议设置为html/zh-cn

    • 运行doxygen doc/Doxyfile.zh-cn命令即可得到中文版主页,如下图所示:

doxygen_default_blank_homepage_zh-cn 
  • 点击这里查看示例代码

4. 定制Doxygen的HTML样式

Doxygen允许用户对生成的HTML样式进行定制。

  • 一般地,我们习惯在doc文件夹下新建misc文件夹用于存放HTML的样式文件等,按照如下命令生成Doxygen的默认样式文件:

cd /path/to/repository/doc
mkdir misc
cd misc
doxygen -w html header.html footer.html doxygen.css
  • 目前我们采用RapidJSON的帮助文档样式,因此从其Github库 中下载doxygenextra.css样式文件放在doc/misc文件夹中,然后删除doxygen.css,最后根据RapidJSON库中的header.htmlfooter.html对应修改刚 生成的HTML文件

  • 为了更好地展示Doxygen生成用户手册和代码文档的功能,增加了doc/intro.mddoc/intro-zh-cn.md文档,增加了Doxygen代码注释示例 src/doxygen_google_coding_style_examples.hsrc/doxygen_google_coding_style_examples.cpp源代码

  • 同时为了使用RapidJSON样式,还需要对DoxyfileDoxyfile.zh-cn进行修改:

    • HTML_HEADER = ./doc/misc/header.html

    • HTML_FOOTER = ./doc/misc/footer.html

    • HTML_EXTRA_STYLESHEET = ./doc/misc/doxygenextra.css

    • GENERATE_TREEVIEW = YES

    • DISABLE_INDEX = YES

  • 值得一提的是,Doxygen直到1.8.16版本才修复了Markdown文件链接问题,详见这里- issue-#7151,因此教程到这里我也把 Doxygen的版本更新为1.8.16了

  • 重新生成主页、Markdown文件的目录结构、以及C++类文档如下图所示, 点击这里查看示例代码

doxygen_customized_homepage 
doxygen_customized_homepage_md_toc 
doxygen_customized_homepage_api_class_demo 
« Back