这两天在尝试画像素,为接下来的游戏做点资源,最开始用的是Pixilart,但毕竟是个在线客户端,保存到本地很麻烦,而且受网络影响很大,于是搜索了一下,打算使用大名鼎鼎的Aseprite。
这也是个很有名的像素绘画软件了,但是在steam上售价高达70,对于我这种没钱的学生党很不友好,但是好在这个是也是个开源项目,本着先上车再补票的原则,我于是来到Github上Aseprite的开源库,打算自己编译一个先用着。
于是我愉快的clone了aseprite的库,然后打开官方的编译文档,愉快的配置好Visual Studio, cmake, ninja开始编译后,我才刚开始领略到编译C++项目是个多痛苦的事。
首先是各种依赖库的安装,官方文档上说需要安装Skia,SDL2,Freetype,libpng,libwebp,zlib等一大堆库,然后还要配置环境变量,最后还要设置cmake参数,整个过程繁琐且容易出错。更绝望的是,VS2022和VS2026有些API是不互通的,而当我打开VS Installer后更绝望的发现:VS2022已经被划入Legacy,无法从Installer上下载了。
太真实了
经过一番折腾还是失败了,我想找一个依赖齐全,版本控制容易,甚至直接在云端编译好了直接下载,有没有这样的东西呢?
答案是有的,那就是Github Actions。
什么是Github Actions
Github Actions是Github提供的CI/CD服务,可以让我们在云端运行脚本,进行编译、测试、部署等操作。更重要的是,我们可以利用别人的Actions来完成我们的任务。
更多的大家可以自行谷歌,不过今天我们就来讲讲可以拿Actions完成的骚操作
编译开箱即用的开源项目
对于一些简单的项目,我们可以直接利用Github Actions来完成编译,而不需要自己配置环境。
下面以Aseprite为例,展示如何利用Github Actions来编译开源库。
我们先去Aseprite的官方Actions页面,可以看到已经有一些预定义的Workflow,正好有build,但是,如果我们仔细观察这个Workflow,会发现它只是编译测试,并没有产生任何构建产物。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| name: build on: [push, pull_request] jobs: build: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [windows-latest, macos-latest, ubuntu-latest] build_type: [RelWithDebInfo, Debug] ui: [gui, cli] scripting: [lua, noscripts] exclude: - build_type: Debug ui: gui - build_type: RelWithDebInfo ui: cli - build_type: RelWithDebInfo scripting: noscripts steps: - uses: actions/checkout@v4 with: submodules: 'recursive' - name: Install Dependencies if: runner.os == 'Linux' shell: bash run: | sudo apt-get update -qq sudo apt-get install -y \ libpixman-1-dev libfreetype6-dev libharfbuzz-dev zlib1g-dev \ libx11-dev libxcursor-dev libxi-dev libxrandr-dev libgl1-mesa-dev \ libfontconfig1-dev - name: Install Skia if: ${{ matrix.ui == 'gui' }} shell: bash run: | if [[ "${{ runner.os }}" == "Windows" ]] ; then this_dir=$(cygpath "${{ github.workspace }}") else this_dir="${{ github.workspace }}" fi skia_url=$(source $this_dir/laf/misc/skia-url.sh | xargs) skia_file=$(basename $skia_url) curl --ssl-revoke-best-effort -L -o "$skia_file" "$skia_url" unzip "$skia_file" -d skia - name: ccache uses: hendrikmuhs/ccache-action@v1.2.17 if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }} with: key: ${{ matrix.os }}-${{ matrix.ui }}-${{ matrix.scripting }}-${{ matrix.build_type }} - uses: aseprite/get-ninja@main - uses: ilammy/msvc-dev-cmd@v1 if: runner.os == 'Windows' - name: Generating Makefiles shell: bash run: | if [[ "${{ runner.os }}" == "Windows" ]] ; then export enable_ccache=off else export enable_ccache=on fi
if [[ "${{ matrix.ui }}" == "gui" ]] ; then export laf_backend=skia else export laf_backend=none fi
if [[ "${{ matrix.scripting }}" == "lua" ]] ; then export enable_scripting=on else export enable_scripting=off fi
if [[ "${{ runner.os }}" == "macOS" ]] ; then export skia_arch=arm64 else export skia_arch=x64 fi
cmake -S . -B build -G Ninja \ -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ -DCMAKE_OSX_DEPLOYMENT_TARGET=10.14 \ -DENABLE_TESTS=ON \ -DENABLE_SCRIPTING=$enable_scripting \ -DENABLE_CCACHE=$enable_ccache \ -DLAF_BACKEND=$laf_backend \ -DSKIA_DIR=$(realpath skia) \ -DSKIA_LIBRARY_DIR=$(realpath skia/out/Release-$skia_arch) - name: Compiling shell: bash run: | cd build && ninja - name: Running C++ Tests shell: bash run: | if [[ "${{ runner.os }}" == "Linux" ]] ; then export XVFB=xvfb-run fi cd build && $XVFB ctest --output-on-failure - name: Running CLI Tests if: ${{ matrix.scripting == 'lua' }} shell: bash run: | if [[ "${{ runner.os }}" == "Linux" ]] ; then export XVFB=xvfb-run fi export ASEPRITE=$PWD/build/bin/aseprite cd tests $XVFB bash run-tests.sh
|
那么,我们可以怎么做呢?
首先,这个Workflow本身用于在提交和PR时尝试编译,并看看有没有问题,虽然其没有产生任何构建产物,但是其实它已经完整的完成了一次编译。我们可以对这个Workflow进行修改,使其在编译完成后,将构建产物上传。
具体操作
首先,fork一个Aseprite的仓库然后克隆到本地或者直接在线编辑
/.github/workflows/build.yml
在Compiling步骤后、Run C++ Tests步骤前添加:
1 2 3 4 5 6 7 8 9 10 11
| - name: Upload Build Artifact uses: actions/upload-artifact@v4 with: name: aseprite-${{ matrix.os }}-${{ matrix.build_type }}-${{ matrix.ui }}-${{ matrix.scripting }} path: | build/bin/ retention-days: 30
|
这里定义了一个名为Upload Build Artifact的步骤,其使用了官方的actions/upload-artifact@v4动作,并附上了在编译阶段生成的build/bin/目录,并按照matrix中设置好的os、build_type、ui、scripting等参数进行命名。而且由于我们实际上不需要测试,所以我们可以把Run tests的几步都删掉。
修改好后,保存或者push。该Workflow应当会自动触发。
如果没有,我们也可以添加手动触发的触发器。
1
| on: [push, pull_request, workflow_dispatch]
|
也可以详细定义workflow_dispatch的触发条件和参数。
然后我们就可以在Actions页面查看构建进度

等待一会,我们就能看见构建产物了

不过由于我们原来的脚本是用于开发环境的,会包含很多输出,所以体积会很大,所以更推荐下一种方法。
利用他人写好的单一平台构建脚本(推荐)
如果你还是觉得麻烦,可以直接利用他人写好的单一平台构建脚本,如aseprite-bin,不过这种方法看运气,因为本来这种双重License的项目就少,而且不会每个项目都有人写好构建脚本。
fork一个aseprite-bin仓库
fork下来的仓库的Actions默认禁用,开启。

这个仓库已经写好Workflow了并且有一个workflow_dispatch触发器,我们可以直接使用。

最后等待构建完成,在刚才的Actions页面可以看到构建产物。


为什么选择Github Actions?
Github Actions的优势在于:
- 免费:Github Actions对于公开仓库是免费的,不需要额外的费用。
- 方便:Github Actions的配置文件是YAML格式的。并且每个Workflow的环境都是在触发时从零创建,不需要在本地搭建环境以及维护版本。
- 可定制:Github Actions可以根据需要定制,例如添加自定义的构建步骤、触发条件等。
利用Github Actions构建开源库只能算是Github Action用法的冰山一角,但是它已经可以满足很多简单的构建需求,例如编译、测试、打包等。
总结
通过本文,我们了解了如何利用Github Actions来编译开源库,并且直接下载现成的可执行文件。对于一些简单的项目,这种方法可以大大简化编译过程,提高效率。
希望大家能够尝试一下这种方法,享受开源的乐趣!
不过,一定要阅读每个库的EULA和LICENSE,确保不会违反任何法律规定,并且有能力了能补票的尽量补票,毕竟开源项目开发者可是互联网和开源社区的支柱。
