開發環境
- Ubuntu18.04 or Ubuntu20.04
- Qt Creator 4.6.x (Based on Qt 5.11.x)
- APT list: apt-transport-https git dh-make build-essential autoconf autotools-dev qt5-default libssl-dev qt5keychain-dev devscripts
項目結構
項目主體結構是根據Qt, 用.pro文件組織, 項目最外層TEMPLATE用subdirs, 用於引入項目主pro文件, 這樣便於將源代碼放入子目錄, 實際的項目pro文件在子目錄下. 最外層還有對應的說明文件, 授權文件和Gitlab CI配置等.
├── .git
├── .gitignore
├── .gitlab-ci.yml # Gitlab CI配置文件
├── LICENSE
├── README.md # 項目Readme
├── rockbb # 實際源代碼目錄
│ ├── app-entry # 為debian/ubuntu提供的桌面圖標配置文件及圖標文件
│ │ ├── rockbb.desktop
│ │ └── rockbb.png
│ ├── *.cpp
│ ├── *.h, *.ui
│ ├── config.h # 全局配置, namespace rockbb
│ ├── debian # deb打包時需要的文件
│ │ ├── changelog # 軟件歷史版本信息, 有格式要求
│ │ ├── compat # debhelper壓縮級別, 最新的是10, 如果要兼容可以用9
│ │ ├── control # 軟件的包名, 維護者, 編譯工具依賴, 安裝依賴等
│ │ ├── copyright # 標准版權信息, 例如GPLv3
│ │ └── rules # 編譯和打包命令, 在這里將資源文件復制到deb包的標准位置
│ ├── res.qrc # 資源文件, 在這個文件里記錄images目錄里的各個文件
│ ├── images
│ │ ├── rockbb-off.png
│ │ ├── rockbb-on.png
│ │ ├── rockbb.png
│ ├── main.cpp # 程序入口
│ └── rockbb.pro # 主要項目文件
├── rockbb-project.pro # 項目入口文件(用於引入rockbb.pro)
└── rockbb-project.pro.user # Qt Creator產生的本地開發配置文件, 需要從gitignore中排除
Qt對非Qt項目文件的支持不好, 在project視圖下默認不展示不相關的文件, 如果要顯示, 需要在.pro文件中使用 OTHER_FILES 將需要顯示在工作區的文件包含進來.
如果切換到File System視圖, 默認不顯示點開頭的隱藏文件, 需要在模塊右上角選項中勾上"Show Hidden Files", 才會展示.gitlab-ci.yml這些文件.
開發編譯和測試
在本地通過Qt Creator完成, 編譯, Debug和運行有Ctrl+B, F5, Ctrl+R等快捷方式.
項目文件中常用的變量及說明
- QT
指定項目用到的Qt模塊, 在編譯階段, 被指定的Qt模塊頭文件會被include並且被鏈接. 默認Qt會包含core和gui, 如果項目不需要gui, 需要用 QT -= gui 顯式排除. - QTPLUGIN
指定需要鏈接到最終可執行文件的靜態Qt插件, 成為內建資源. - CONFIG
在這里設置項目編譯選項, 不同的值對應qmake內部不同的處理, 常用值包括 release, debug, debug_and_release, warn_on, warn_off, c99, c11, c++11, static等 - DEFINES
qmake adds the values of this variable as compiler C preprocessor macros (-D option). - DESTDIR
指定最終生成的可執行文件的路徑. - OBJECTS_DIR
指定存放編譯過程中中間對象的存放路徑 - MOC_DIR
Specifies the directory where all intermediate moc files should be placed. - RCC_DIR
Specifies the directory for Qt Resource Compiler output files. - LIBS
指定需要被鏈接到項目的庫. 如果使用Unix形式的 -l(library) 和 -L (library path) 參數, qmake 可以在Windows下正確識別處理. - QMAKE_CXXFLAGS
Specifies the C++ compiler flags for building a project. The value of this variable is typically handled by qmake or qmake.conf and rarely needs to be modified. The flags specific to debug and release modes can be adjusted by modifying the QMAKE_CXXFLAGS_DEBUG and QMAKE_CXXFLAGS_RELEASE variables, respectively. - SOURCES
Specifies the names of all source files in the project - HEADERS
Defines the header files for the project. - PWD
解析為包含被解析的當前文件的完整路徑. This can be useful to refer to files within the source tree when writing project files to support shadow builds. - INCLUDEPATH
指定編譯時 #include 應該查找的目錄, 如果目錄帶空格, 需要用雙引號包圍. - TARGET
指定最后生成的可執行文件名. 默認等於項目文件名.
項目文件中的語法
變量賦值方式
VAR = foobar => 在qmake執行的時候給VAR變量賦值(值為foobar)
$$VAR => 在qmake執行的時候, 使用VAR對應的QMake變量值, 例如$$PWD
$${VAR} => 和上面一樣只不過將變量顯式指出
$(VAR) => 在Makefile運行時取環境變量的值
$$(VAR) => 在qmake運行時取環境變量的值
包含第三方項目的pri文件
include(path/to/some.pri)
區分debug和release做不同配置
debug: {
...
}
release: {
...
}
代碼倉庫
在本地通過 git remote add 將github添加為上游倉庫, 這樣項目對應的就有 origin 和 github 兩個上游, 在本地編譯通過后, push origin master可以觸發測試環境的gitlab進行集成, 在gitlab測試通過后, 可以push gitlab master將代碼提交到github.
測試集成
測試環境的持續集成, 使用Gitlab + Gitlab Runner實現. 有條件的話Gitlab Runner應當跑在獨立的服務器上, 另外如果需要構建異構系統例如Windows, OSX等, 都需要將Runner跑在獨立的服務器上. 如果只需要構建Linux下的發行版, 可以放在一起. Gitlab Runner需要Docker環境, 最好使用Ubuntu較新的發行版.
gitlab 12.10.6, gitlab-runner 12.10.2, docker 19.03.6
Gitlab配置
略. 這里主要是創建group, project, user, 獲取group下的runner token
Gitlab Runner配置
准備Docker鏡像, 對於不同的發行版發布, 要准備對應的發行版鏡像, 再將這些鏡像作為Runner, 注冊到Gitlab. 舉例Ubuntu18.04的Dockerfile
from ubuntu:bionic
ADD setup.sh /opt/
RUN /bin/bash /opt/setup.sh
和setup.sh, 這個腳本用於切換到較快的apt源, 以及准備編譯環境.
#!/bin/sh
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic main restricted" > /etc/apt/sources.list
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-updates main restricted" >> /etc/apt/sources.list
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic universe" >> /etc/apt/sources.list
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-updates universe" >> /etc/apt/sources.list
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic multiverse" >> /etc/apt/sources.list
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-updates multiverse" >> /etc/apt/sources.list
echo "deb http://mirrors.ustc.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse" >> /etc/apt/sources.list
echo "deb http://security.ubuntu.com/ubuntu bionic-security main restricted" >> /etc/apt/sources.list
echo "deb http://security.ubuntu.com/ubuntu bionic-security universe" >> /etc/apt/sources.list
echo "deb http://security.ubuntu.com/ubuntu bionic-security multiverse" >> /etc/apt/sources.list
#requirements
apt-get update
apt-get -y install apt-transport-https git dh-make build-essential autoconf autotools-dev qt5-default libssl-dev qt5keychain-dev devscripts
對於Ubuntu20.04, 在apt install 過程中會出現tzdata等需要交互的安裝導致鏡像制作失敗, 需要在apt-get update前加上這句
export DEBIAN_FRONTEND=noninteractive
制作鏡像, 將鏡像注冊為Runner
# 制作鏡像
docker build -t ubuntu_focal_runner:1.0 ubuntu_focal/
# 注冊到gitlab
gitlab-runner register --non-interactive --url "http://172.17.54.139/" --registration-token "x7sx4rte_acSXrmznJBz" --description "Ubuntu 20.04 x64 runner" --executor "docker" --docker-image "ubuntu_focal_runner:1.0" --tag-list "ubuntu-2004-64" --run-untagged="false" --locked="false" --access-level="not_protected"
測試鏡像是否可用:
對於剛建好的容器鏡像, 需要在跑任務前實際執行一下構建, 可以通過 docker run -it --rm [image] bash 的方式, 在命令行下手動git clone項目文件, 執行編譯. 如果有問題, 需要在這一步重新制作鏡像來解決. 不同的發行版, gcc/g++版本可能會不一樣, Ubuntu16.04(GCC 5.4), Ubuntu18.04(GCC 7.5), Ubuntu20.04(GCC9.3), Debian8&10(GCC 8.3)
對於runner, 需要注意的有兩點:
- 每個runner需要帶一個 --tag-list "ubuntu-2004-64" 參數, 里面可以配一個或多個tag, 這個tag-list 結合 .gitlab-ci.yml文件里的 tags 參數, 可以讓發行版各自執行對應的任務.
- 如果希望Runner就近pull鏡像, 在注冊完runner后, 需要修改 /etc/gitlab-runner/config.toml 文件, 在每個runner的[runners.docker]配置下, 增加一行配置. 默認為"always", 會主動去docker hub 拉取, 因為自建的鏡像只存在本地, 從而導致任務失敗.
volumes = ["/cache"]
pull_policy = "if-not-present" # 增加這行
shm_size = 0
項目 .gitlab-ci.yml 配置
參考
https://docs.gitlab.com/ee/ci/quick_start/
https://docs.gitlab.com/ee/ci/yaml/
根據.gitlab-ci.yml里的任務配置, gitlab在收到新的push后, 會觸發產生pipeline, 里面是滿足條件的, 分配到對應runner的job. 如果中途有job失敗, 整個pipeline就會失敗, 不再往下執行.
Github發布
對於版本間一個完整的開發周期, 以上一個版本號Tag提交為開始, 以下一個版本號提交為結束.
開發階段
假設已經發布的版本號為1.1, 進入當前開發周期后, 首先修改以下文件
- config.h: 版本號修改為 1.2-dev
因為測試集成產生的版本號為特殊版本號, 並且會完全覆蓋debian/changelog, 故這一階段還不需要修改changelog
預發布階段
在測試結束后, 進入發布准備工作, 需要修改以下文件
- config.h: 版本號修改為 1.2
- debian/changelog: 加入自上個版本至今的改動說明
對commit ID打tag, 並生成正式版的release
# 加tag
git tag -a 0.1.0 94ca32cbc4bd685774f22d95c66d58c79dccf95f
# 觸發測試執行任務, 打包正式版
push origin --tags
本地對release進行測試
發布階段
將tag推送到github
git push github --tags
之后, github會自動對新tag產生release, 可以手工在此release下添加文字和對應的release軟件包