使用 GitLab CI 构建 Windows 版 qBittorrent

IT, 其他

考虑到官方预编译的 Windows 版 qBittorrent 有些时候不能满足自己稳定运行的要求,因此我决定尝试 GitLab CI 自动构建。

准备 Windows 容器

运行 Windows 容器只需要 WSL 或者 WSL2 支持,但 GitLab Runner 仅支持 Windows Server 平台,因此需要准备一台 Windows Server 宿主机。Windows Server 可以是裸机或者通过虚拟化 Intel VT-x/AMD-v 做到 Nested Virtualization。我使用的是 Windows Server 2019 (version 1809)。

可以在 PowerShell 运行如下命令:

Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/microsoft/Windows-Containers/Main/helpful_tools/Install-DockerCE/install-docker-ce.ps1" -o install-docker-ce.ps1.\install-docker-ce.ps1

这会为系统启用 WSL/WSL2 功能,并安装 Docker Engine。

注册 GitLab Runner

为 GitLab Runner 创建一个文件夹例如:C:\\GitLab-Runner二进制文件下载到文件夹中。运行如下指令注册 runner:

.\gitlab-runner.exe register

填写相关信息:

  • 输入 GitLab 的网址,自建或者官网。
  • 输入用以注册 runner 的 token
  • 输入你对 runner 的描述,或者保留默认值,通常它会选择你的系统 hostname
  • 输入 runner 关联的 tag。
  • 输入其他维护信息

顺利的话你就可以在 GitLab runner 状态页面找到这台 runner。

准备 Windows 镜像

你只能运行与宿主系统相同版本的 Windows Server Core 镜像。因此如果运行的是 Windows Server 2019 就应该拉取 mcr.microsoft.com/windows/servercore:1809。其他镜像可以在 Docker Hub 查到。此外相关的 dotnet 镜像等也可以被用来运行 CI 环境。由于 qBittorrent 编译以来的 Visual Studio 2019 CE 依赖 dotnet 环境,因此直接拉取 mcr.microsoft.com/dotnet/framework/runtime:4.8-20220913-windowsservercore-ltsc2019 可以方便后续操作。

除了准备基础镜像,我还需要收集编译依赖的组件。根据 qBittorrent 的 Wiki 我需要为这个系统安装

其中 VS2019CE, cmake, ninja, git 可以通过 chocolatey 安装。剩下的 libboost, openssl, qt5, 可以使用 vcpkg 编译安装。而 Libtorrent 则通过手动编译完成安装。由于大部分的编译依赖并不需要经常更新,因此我决定先将一部分常用的依赖安装并制作成镜像,编译 qBittorrent 时直接使用这个环境。

我使用了如下配置(Dockerfile)创建 Docker 镜像

FROM mcr.microsoft.com/dotnet/framework/runtime:4.8-20220913-windowsservercore-ltsc2019SHELL [ "powershell", "-Command" ]# install chocolateyRUN echo \"**** installing chocolatey ****\"RUN Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))# install buildtoolsRUN echo \"**** installing build-essential ****\"RUN choco install visualstudio2019community -y --params \"--add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.CoreIde --add Microsoft.VisualStudio.Component.VC.CoreBuildTools --add Microsoft.VisualStudio.Component.TextTemplating --add Microsoft.VisualStudio.Component.VC.Redist.14.Latest --add Microsoft.VisualStudio.Component.VC.ATL --add Microsoft.VisualStudio.Component.VC.ATLMFC --add Microsoft.VisualStudio.Component.VC.14.29.16.10.x86.x64 --add Microsoft.VisualStudio.Component.Windows10SDK.19041\"RUN choco install git -yRUN choco install cmake -y --installargs 'ADD_CMAKE_TO_PATH=System'RUN choco install ninja -y# active build environmentRUN $env:Path = [Environment]::GetEnvironmentVariable('Path', [System.EnvironmentVariableTarget]::Machine);RUN Import-Module \"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\Microsoft.VisualStudio.DevShell.dll\"; Enter-VsDevShell -VsInstallPath \"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\" -DevCmdArguments \"-host_arch=amd64 -arch=amd64\"# prepare vcpkgRUN echo \"**** installing vcpkg ****\" WORKDIR "C:\\"RUN git clone https://github.com/microsoft/vcpkgWORKDIR "C:\\vcpkg"RUN .\bootstrap-vcpkg.bat -disableMetricsRUN .\vcpkg integrate installRUN .\vcpkg install \    boost-circular-buffer:x64-windows-static \    boost-stacktrace:x64-windows-static \    openssl:x64-windows-static \    qt5-base:x64-windows-static \    qt5-svg:x64-windows-static \    qt5-tools:x64-windows-static \    qt5-translations:x64-windows-static \    qt5-winextras:x64-windows-static \    --clean-after-build# Storage layer consumed downstreamFROM scratch# set version labelARG BUILD_DATEARG VERSIONLABEL build_version="efs.zone version:- ${VERSION} Build-date:- ${BUILD_DATE}"LABEL maintainer="EFS"

使用上述配置的镜像体积高达 43.6GB 因此并不适合上传到 Docker Hub,但我可以通过上传到本地的 docker registry 完成对镜像的管理。可以通过上一篇日志所叙述的方式搭建本地的 docker registry。

配置 GitLab CI

使用上一个步骤生成的镜像就可以编译 qBittorrent。编译 qBittorrent 需要如下步骤。

  • 通过 vcpkg 安装然后删除 Libtorrent 以完成 Libtorrent 的编译依赖
  • 编译 Libtorrent
  • 编译 qBittorrent
  • 提取打包所需二进制及其他必要文件
  • 安装 NSIS 打包环境
  • 打包并上传 artifacts

以下配置为实现方法(.gitlab-ci.yml):

.shared_windows_runners:    tags:    - build-windows    image: local.registry/efs/qt5-cmake-vs2019:lateststages:    - build-binary    - packagingbuild:    extends:        - .shared_windows_runners    stage: build-binary    timeout: 8h    script:        # prepare base environment        - Import-Module "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"; Enter-VsDevShell -VsInstallPath "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community" -DevCmdArguments "-host_arch=amd64 -arch=amd64"        # install build environment        - cd "C:\vcpkg"        - .\vcpkg integrate install        - .\vcpkg install libtorrent:x64-windows-static        - .\vcpkg remove libtorrent:x64-windows-static        # build binary        # Libtorrent-Rasterbar        - cd "$CI_PROJECT_DIR"        - git clone `            --branch RC_1_2_EFS `            --depth 1 `            --recurse-submodules `            https://gitlab-ci-token:${CI_JOB_TOKEN}@selfhost.gitlab.com/efs/libtorrent.git        - cd ".\libtorrent"        - cmake `            -B build `            -G "Ninja" `            -DCMAKE_BUILD_TYPE=Release `            -DCMAKE_EXPORT_COMPILE_COMMANDS=ON `            -DCMAKE_INSTALL_PREFIX="$CI_PROJECT_DIR/buildd" `            -DCMAKE_TOOLCHAIN_FILE="C:/vcpkg/scripts/buildsystems/vcpkg.cmake" `            -DVCPKG_TARGET_TRIPLET="x64-windows-static" `            -DBUILD_SHARED_LIBS=OFF `            -Ddeprecated-functions=OFF `            -Dstatic_runtime=ON        - cmake --build build        - cmake --install build        # qBittorrent        - cd "$CI_PROJECT_DIR"        - git clone `            https://gitlab-ci-token:${CI_JOB_TOKEN}@selfhost.gitlab.com/efs/qbittorrent.git        - cd ".\qBittorrent"        - cmake `            -B build `            -G "Ninja" `            -DCMAKE_BUILD_TYPE=Release `            -DCMAKE_EXPORT_COMPILE_COMMANDS=ON `            -DCMAKE_TOOLCHAIN_FILE="C:/vcpkg/scripts/buildsystems/vcpkg.cmake" `            -DLibtorrentRasterbar_DIR="$CI_PROJECT_DIR/buildd/lib/cmake/LibtorrentRasterbar" `            -DMSVC_RUNTIME_DYNAMIC=OFF `            -DVCPKG_TARGET_TRIPLET=x64-windows-static `            -DVERBOSE_CONFIGURE=ON `            --graphviz=build/target_graph.dot        - cmake --build build        # prepare uploads        - cd $CI_PROJECT_DIR        - If(!(test-path -PathType container upload)){New-Item -ItemType Directory -Path upload}        - Copy-Item "$CI_PROJECT_DIR/qBittorrent/build/qbittorrent.exe" "upload"        - Copy-Item "$CI_PROJECT_DIR/qBittorrent/build/qbittorrent.pdb" "upload"        - Copy-Item "$CI_PROJECT_DIR/qBittorrent/dist/windows/qt.conf" "upload"        # cmake additionals        - If(!(test-path -PathType container upload/cmake)){New-Item -ItemType Directory -Path upload/cmake}        - Copy-Item "$CI_PROJECT_DIR/qBittorrent/build/compile_commands.json" "upload/cmake"        - Copy-Item "$CI_PROJECT_DIR/qBittorrent/build/target_graph.dot" "upload/cmake"        - If(!(test-path -PathType container upload/cmake/libtorrent)){New-Item -ItemType Directory -Path upload/cmake/libtorrent}        - Copy-Item "$CI_PROJECT_DIR/libtorrent/build/compile_commands.json" "upload/cmake/libtorrent"        # qt-translations        - Copy-Item "C:/vcpkg/installed/x64-windows-static/share/qt5/translations" "$CI_PROJECT_DIR/translations/" -Recurse    cache:        key: build-cache        paths:            - upload/            - translations/packaging:    extends:        - .shared_windows_runners    stage: packaging    timeout: 8h    script:        # prepare base environment        - Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))        - choco install git -y        - choco install nsis -y        - choco install 7zip -y        - $env:Path = [Environment]::GetEnvironmentVariable('Path', [System.EnvironmentVariableTarget]::Machine);        - cd "$CI_PROJECT_DIR"        - git clone `            https://gitlab-ci-token:${CI_JOB_TOKEN}@selfhost.gitlab.com/efs/qbittorrent.git        - cd ".\qBittorrent\dist\windows\nsis plugins"        - 7z x -o".\FindProcDLL" .\FindProcDLL_mod_by_hnedka.7z        - Copy-Item ".\FindProcDLL\Unicode\FindProcDLL.dll" "C:\Program Files (x86)\NSIS\Plugins\x86-unicode"        - 7z x -o".\nsisFirewall" .\nsisFirewall.zip        - Copy-Item ".\nsisFirewall\bin\nsisFirewallW.dll" "C:\Program Files (x86)\NSIS\Plugins\x86-unicode"        - 7z x -o".\UAC" .\UAC.zip        - Copy-Item ".\UAC\Plugins\x86-unicode\UAC.dll" "C:\Program Files (x86)\NSIS\Plugins\x86-unicode"        # prepare binary        - Copy-Item "$CI_PROJECT_DIR\upload\qbittorrent.exe" "$CI_PROJECT_DIR\qBittorrent\dist\windows"        - Copy-Item "$CI_PROJECT_DIR\upload\qbittorrent.pdb" "$CI_PROJECT_DIR\qBittorrent\dist\windows"        - Copy-Item "$CI_PROJECT_DIR\upload\qt.conf" "$CI_PROJECT_DIR\qBittorrent\dist\windows" -Force        - Copy-Item "$CI_PROJECT_DIR\qBittorrent\COPYING" "$CI_PROJECT_DIR\qBittorrent\dist\windows\license.txt"        - Copy-Item "$CI_PROJECT_DIR\translations\" "$CI_PROJECT_DIR\qBittorrent\dist\windows\translations\" -Recurse        # run package        - cd "$CI_PROJECT_DIR\qBittorrent\dist\windows"        - Start-Process -NoNewWindow -FilePath "C:\Program Files (x86)\NSIS\makensis.exe" -ArgumentList "qbittorrent.nsi" -Wait        - Copy-Item "$CI_PROJECT_DIR\qBittorrent\dist\windows\qbittorrent*setup.exe" "$CI_PROJECT_DIR\upload"    cache:        key: build-cache        paths:            - upload/            - translations/    artifacts:      paths:           - upload/qbittorrent*setup.exe      name: qBittorrent-installer_Windows-x64_libtorrent-1.2.x      expire_in: 2 hr

其中以 https://gitlab-ci-token:${CI_JOB_TOKEN}@selfhost.gitlab.com/efs/qbittorrent.git 形式存在的 git url 可以在开启 Limit CI_JOB_TOKEN access 并赋予相应 Repo 权限后自动完成鉴权以达到拉取其他 Repo 完成编译的效果。

参考文档

https://docs.gitlab.com/runner/install/windows.html

https://docs.gitlab.com/runner/register/

https://docs.gitlab.com/runner/executors/docker.html#supported-windows-versions

https://learn.microsoft.com/en-us/virtualization/windowscontainers/quick-start/set-up-environment?tabs=dockerce

https://github.com/qbittorrent/qBittorrent/wiki/Compilation:-Windows-(MSVC-2019,-64-bit,-static-linkage)

https://github.com/c0re100/qBittorrent-Enhanced-Edition/blob/v4_4_x/.github/workflows/ci_windows.yaml

, , , ,
上一篇文章
自建本地 docker registry 简易教程

发表回复

您的电子邮箱地址不会被公开。

Fill out this field
Fill out this field
请输入有效的电子邮箱地址。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据