Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# clang-tidy configuration for shadowsocks-libev project sources (src/ only).
# Bundled submodules (libcork/, libipset/, libbloom/) are third-party code and
# Bundled sources under third_party/ and src/blake3/ are third-party code and
# are excluded by the file regex used in CI:
# run-clang-tidy -p build '/src/[^/]+\.c$'
#
Expand Down
8 changes: 2 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -31,23 +29,21 @@ 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"

debian-package:
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
Expand Down
199 changes: 199 additions & 0 deletions .github/workflows/portability.yml
Original file line number Diff line number Diff line change
@@ -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
'
34 changes: 21 additions & 13 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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: |
Expand All @@ -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
Expand All @@ -91,8 +87,6 @@ jobs:
MAX_WARNINGS: 0
steps:
- uses: actions/checkout@v6
with:
submodules: recursive

- name: Install dependencies
run: |
Expand All @@ -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)"
Expand All @@ -128,8 +122,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
submodules: recursive

- name: Install dependencies
run: |
Expand All @@ -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: |
Expand All @@ -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
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,15 @@ doc/*.html

# CMake objection
obj-*

# Pinned source archives are part of offline release builds.
!third_party/dist/*.tar.gz
!third_party/dist/*.tar.bz2

# Former dependency checkouts retained locally during migration.
/libipset/
/libbloom/
/libcork/

# Python integration-test bytecode.
__pycache__/
12 changes: 0 additions & 12 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,12 +0,0 @@
[submodule "libcork"]
path = libcork
url = https://github.com/shadowsocks/libcork.git
ignore = dirty
[submodule "libipset"]
path = libipset
url = https://github.com/shadowsocks/ipset.git
ignore = dirty
[submodule "libbloom"]
path = libbloom
url = https://github.com/shadowsocks/libbloom.git
ignore = dirty
Loading
Loading