mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-20 13:03:50 +00:00
Modernize C builds with offline dependencies and portable runtime helpers (#3050)
Bundle pinned offline dependencies, remove libcork/libipset and submodule requirements, and add portable runtime helpers with relocatable static/shared library installations.
Add Clang static build validation for Linux/musl, macOS and Windows, real TCP/UDP and SIP003 interoperability coverage, and recorded performance tradeoffs. All 21 hosted checks pass at the reviewed PR head 8d504e6218.
This commit is contained in:
@@ -15,8 +15,6 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
@@ -31,7 +29,7 @@ jobs:
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir -p build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DSS_DEPENDENCY_MODE=system -DWITH_STATIC=OFF
|
||||
jobs="$(nproc 2>/dev/null || sysctl -n hw.ncpu)"
|
||||
make -j"$jobs"
|
||||
|
||||
@@ -39,15 +37,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libpcre2-dev libmbedtls-dev libsodium-dev libev-dev libc-ares-dev
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential debhelper dpkg-dev fakeroot asciidoc-base xmlto pkg-config
|
||||
build-essential cmake debhelper dpkg-dev fakeroot asciidoc-base xmlto pkg-config
|
||||
|
||||
- name: Debian package build test
|
||||
run: bash tests/test_deb_build.sh
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
name: portability
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
bundled:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-24.04, ubuntu-24.04-arm, macos-latest]
|
||||
minimal: ['OFF', 'ON']
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Build without installed third-party development packages
|
||||
run: |
|
||||
cmake -S . -B build -DSS_MINIMAL=${{ matrix.minimal }}
|
||||
cmake --build build --parallel 4
|
||||
ctest --test-dir build -L 'unit|vendor' --output-on-failure --no-tests=error
|
||||
- name: Real TCP and UDP relay
|
||||
run: python3 tests/interop.py --self --bin build/bin
|
||||
- name: SIP003 transport and child cleanup
|
||||
if: matrix.minimal == 'OFF'
|
||||
run: python3 tests/interop.py --self --bin build/bin --plugin tests/sip003_fixture.py
|
||||
- name: Relocated installation and public API consumers
|
||||
run: |
|
||||
cmake --install build --prefix "$PWD/install"
|
||||
mv install relocated
|
||||
cmake -S tests/consumer -B consumer -DCMAKE_PREFIX_PATH="$PWD/relocated"
|
||||
cmake --build consumer
|
||||
./consumer/consumer_static
|
||||
./consumer/consumer_shared
|
||||
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: UCRT64
|
||||
update: true
|
||||
install: >-
|
||||
mingw-w64-ucrt-x86_64-gcc
|
||||
mingw-w64-ucrt-x86_64-cmake
|
||||
mingw-w64-ucrt-x86_64-ninja
|
||||
mingw-w64-ucrt-x86_64-python
|
||||
- name: Build and run native Windows binaries
|
||||
run: |
|
||||
cmake -S . -B build -G Ninja
|
||||
cmake --build build --parallel 4
|
||||
ctest --test-dir build -L 'unit|vendor' --output-on-failure --no-tests=error
|
||||
objdump -p build/bin/ss-server.exe | sed -n '/DLL Name/p'
|
||||
python tests/interop.py --self --bin build/bin --isolate-windows-runtime
|
||||
- name: Installed consumers
|
||||
run: |
|
||||
cmake --install build --prefix "$PWD/install"
|
||||
cmake -S tests/consumer -B consumer -G Ninja -DCMAKE_PREFIX_PATH="$PWD/install"
|
||||
cmake --build consumer
|
||||
- name: Run installed consumers without toolchain DLLs
|
||||
shell: pwsh
|
||||
run: |
|
||||
$env:PATH = "$env:GITHUB_WORKSPACE\install\bin;$env:SystemRoot\System32;$env:SystemRoot"
|
||||
& ./consumer/consumer_static.exe
|
||||
if ($LASTEXITCODE -ne 0) { throw "Static consumer failed: $LASTEXITCODE" }
|
||||
& ./consumer/consumer_shared.exe
|
||||
if ($LASTEXITCODE -ne 0) { throw "Shared consumer failed: $LASTEXITCODE" }
|
||||
|
||||
static-macos:
|
||||
runs-on: macos-latest
|
||||
env:
|
||||
CC: clang
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Build Clang static-only installation
|
||||
run: |
|
||||
cmake -S . -B build-static -DCMAKE_C_COMPILER=clang -DSS_DEPENDENCY_MODE=bundled -DWITH_STATIC=ON -DSS_BUILD_STATIC_LIBRARY=ON -DSS_BUILD_SHARED_LIBRARY=OFF
|
||||
cmake --build build-static --parallel 4
|
||||
ctest --test-dir build-static -L 'unit|vendor' --output-on-failure --no-tests=error
|
||||
cmake --install build-static --prefix "$PWD/install-static"
|
||||
mv install-static relocated-static
|
||||
cmake -S tests/consumer -B consumer-static -DCMAKE_C_COMPILER=clang -DCMAKE_PREFIX_PATH="$PWD/relocated-static"
|
||||
cmake --build consumer-static
|
||||
test ! -e consumer-static/consumer_shared
|
||||
./consumer-static/consumer_static
|
||||
- name: Reject third-party dynamic libraries
|
||||
run: python3 tests/check_static_runtime.py relocated-static/bin/ss-* consumer-static/consumer_static
|
||||
- name: Exercise installed static programs
|
||||
run: |
|
||||
python3 tests/interop.py --self --bin relocated-static/bin
|
||||
python3 tests/interop.py --self --bin relocated-static/bin --plugin tests/sip003_fixture.py
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: static-macos-${{ runner.arch }}
|
||||
path: relocated-static/
|
||||
if-no-files-found: error
|
||||
|
||||
static-windows:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: CLANG64
|
||||
update: true
|
||||
install: >-
|
||||
mingw-w64-clang-x86_64-clang
|
||||
mingw-w64-clang-x86_64-llvm
|
||||
mingw-w64-clang-x86_64-cmake
|
||||
mingw-w64-clang-x86_64-ninja
|
||||
mingw-w64-clang-x86_64-python
|
||||
- name: Build Clang static-only installation
|
||||
run: |
|
||||
cmake -S . -B build-static -G Ninja -DCMAKE_C_COMPILER=clang -DSS_DEPENDENCY_MODE=bundled -DWITH_STATIC=ON -DSS_BUILD_STATIC_LIBRARY=ON -DSS_BUILD_SHARED_LIBRARY=OFF
|
||||
cmake --build build-static --parallel 4
|
||||
ctest --test-dir build-static -L 'unit|vendor' --output-on-failure --no-tests=error
|
||||
cmake --install build-static --prefix "$PWD/install-static"
|
||||
mv install-static relocated-static
|
||||
cmake -S tests/consumer -B consumer-static -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_PREFIX_PATH="$PWD/relocated-static"
|
||||
cmake --build consumer-static
|
||||
test ! -e consumer-static/consumer_shared.exe
|
||||
- name: Reject third-party DLL imports, including delay imports
|
||||
run: python tests/check_static_runtime.py relocated-static/bin/ss-*.exe consumer-static/consumer_static.exe
|
||||
- name: Exercise installed programs without toolchain DLLs
|
||||
run: python tests/interop.py --self --bin relocated-static/bin --isolate-windows-runtime
|
||||
- name: Run static consumer with only Windows system directories on PATH
|
||||
shell: pwsh
|
||||
run: |
|
||||
$env:PATH = "$env:SystemRoot\System32;$env:SystemRoot"
|
||||
& ./consumer-static/consumer_static.exe
|
||||
if ($LASTEXITCODE -ne 0) { throw "Static consumer failed: $LASTEXITCODE" }
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: static-windows-${{ runner.arch }}
|
||||
path: relocated-static/
|
||||
if-no-files-found: error
|
||||
|
||||
static-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Build and test fully static Clang/musl executables
|
||||
run: docker build -f docker/static/Dockerfile --target artifacts --output type=local,dest=static-linux .
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: static-linux-${{ runner.arch }}
|
||||
path: static-linux/
|
||||
if-no-files-found: error
|
||||
|
||||
freebsd:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: vmactions/freebsd-vm@v1
|
||||
with:
|
||||
release: '14.3'
|
||||
usesh: true
|
||||
prepare: pkg install -y cmake ninja python3
|
||||
run: |
|
||||
cmake -S . -B build -G Ninja
|
||||
cmake --build build --parallel 4
|
||||
ctest --test-dir build -L 'unit|vendor' --output-on-failure --no-tests=error
|
||||
python3 tests/interop.py --self --bin build/bin
|
||||
cmake --install build --prefix "$PWD/install"
|
||||
cmake -S tests/consumer -B consumer -G Ninja -DCMAKE_PREFIX_PATH="$PWD/install"
|
||||
cmake --build consumer
|
||||
./consumer/consumer_static
|
||||
./consumer/consumer_shared
|
||||
|
||||
offline-musl:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Source archive
|
||||
run: python3 scripts/source_archive.py release/shadowsocks-libev.tar.gz
|
||||
- name: Prepare compiler image
|
||||
run: |
|
||||
printf 'FROM alpine:3.24\nRUN apk add --no-cache build-base cmake python3 linux-headers\n' > /tmp/ss-toolchain.Dockerfile
|
||||
docker build -t ss-toolchain -f /tmp/ss-toolchain.Dockerfile /tmp
|
||||
- name: Build release archive with network disabled
|
||||
run: |
|
||||
docker run --rm --network none -v "$PWD/release:/release:ro" ss-toolchain sh -ec '
|
||||
mkdir /src
|
||||
tar xzf /release/shadowsocks-libev.tar.gz -C /src --strip-components=1
|
||||
cmake -S /src -B /build -DCMAKE_DISABLE_FIND_PACKAGE_Python3=TRUE
|
||||
cmake --build /build --parallel 4
|
||||
ctest --test-dir /build -L "unit|vendor" --output-on-failure --no-tests=error
|
||||
python3 /src/tests/interop.py --self --bin /build/bin
|
||||
'
|
||||
+21
-13
@@ -15,8 +15,6 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
@@ -47,21 +45,19 @@ jobs:
|
||||
|
||||
- name: Stress test
|
||||
run: |
|
||||
python3 tests/stress_test.py --bin build/shared/bin/ --size 10
|
||||
python3 tests/stress_test.py --bin build/bin/ --size 10
|
||||
|
||||
- name: ss-redir transparent proxy test (QEMU)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get install -y qemu-system-x86
|
||||
bash tests/test_redir_qemu.sh build/shared/bin/
|
||||
bash tests/test_redir_qemu.sh build/bin/
|
||||
timeout-minutes: 8
|
||||
|
||||
asan:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
@@ -78,7 +74,7 @@ jobs:
|
||||
run: ctest --test-dir build -LE memcheck --output-on-failure --no-tests=error
|
||||
|
||||
- name: Stress test (ASan + UBSan)
|
||||
run: python3 tests/stress_test.py --bin build/shared/bin/ --size 10
|
||||
run: python3 tests/stress_test.py --bin build/bin/ --size 10
|
||||
|
||||
clang-tidy:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -91,8 +87,6 @@ jobs:
|
||||
MAX_WARNINGS: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
@@ -104,7 +98,7 @@ jobs:
|
||||
|
||||
- name: Run clang-tidy on project sources
|
||||
run: |
|
||||
run-clang-tidy-18 -quiet -p build '/src/[^/]+\.c$' 2>/dev/null | tee tidy.log || true
|
||||
run-clang-tidy-18 -quiet -p build "$PWD/src/[^/]+\.c$" 2>/dev/null | tee tidy.log || true
|
||||
grep 'warning:' tidy.log | sort -u > warnings.txt || true
|
||||
count="$(wc -l < warnings.txt)"
|
||||
echo "clang-tidy warnings: $count (max allowed: $MAX_WARNINGS)"
|
||||
@@ -128,8 +122,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
@@ -145,7 +137,7 @@ jobs:
|
||||
- name: Run tests
|
||||
run: |
|
||||
ctest --test-dir build -LE memcheck --output-on-failure --no-tests=error
|
||||
python3 tests/stress_test.py --bin build/shared/bin/ --size 10
|
||||
python3 tests/stress_test.py --bin build/bin/ --size 10
|
||||
|
||||
- name: Generate coverage report
|
||||
run: |
|
||||
@@ -162,3 +154,19 @@ jobs:
|
||||
with:
|
||||
name: coverage-html
|
||||
path: build/coverage-html/
|
||||
|
||||
interop:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install dependencies and independent peer
|
||||
run: brew install mbedtls@3 libsodium libev c-ares pcre2 shadowsocks-rust
|
||||
- name: Build
|
||||
run: |
|
||||
cmake -S . -B build -DSS_DEPENDENCY_MODE=system -DWITH_STATIC=OFF
|
||||
cmake --build build --parallel
|
||||
- name: Required interoperability
|
||||
env:
|
||||
SS_REQUIRE_INTEROP: '1'
|
||||
SS_BIN_DIR: build/bin
|
||||
run: bash tests/test_interop_rust.sh
|
||||
|
||||
Reference in New Issue
Block a user