Files
shadowsocks-libev/docker/static/Dockerfile
T
Max Lv bcb3731968 C++20 port 1/14: build, ownership core and allocation audit (#3065)
* Enable C++20 alongside C11 in the build

Add CXX to the project with C++20 (no extensions) and build C++ sources
with -Wextra -fno-exceptions -fno-rtti -fno-threadsafe-statics on top of
the existing warning flags. Give every toolchain a C++ compiler: the zig
Windows toolchain, the static macOS/Windows CI jobs, the static musl
image (clang++ plus libstdc++ headers) and the RPM spec.

* Add C++20 ownership and allocation core

Header-only primitives for the no-heap-after-startup design:
Result/Status, Region, ObjectPool with PoolPtr (std::unique_ptr with a
pool deleter), generation-checked Handle and asynchronous close support,
intrusive RefPtr, FixedBuffer, MonotonicArena, FixedHashMap and FixedLru,
IntrusiveList, and a bounded FixedHeap for third-party allocator hooks.

Unit tests cover each primitive (test_core_*). scripts/check_no_heap.py
rejects heap allocation in C++ sources under src/ and runs as a ctest.
clang-tidy now also analyses C++ sources and the core headers.

* Add heap allocation audit for relayed connections

alloc_counter is a preloadable malloc counter (glibc, macOS) that writes
a snapshot on SIGUSR2. measure_alloc.py warms ss-local and ss-server up,
snapshots both, relays more connections and reports allocations per
connection. It runs report-only as the alloc_audit_report ctest.
interop.peers() now yields the started processes.

* Document the C++20 port and allocation baseline

docs/cpp-core.md describes the language profile, the core primitives,
the phase plan and the measured C baseline (77-89 allocations per
connection in ss-server, 27-39 in ss-local). The compatibility contract
now keeps the C11 public header instead of a C11 code base. CLAUDE.md
drops stale libev, submodule and gnu99 references.

* Fix CI for the C++ core: libstdc++ headers, static unwinder, newer clang

- docker/static: Alpine's libstdc++ headers come with g++, and the C++
  tests' static libstdc++ needs an unwinder that compiler-rt lacks; add
  g++ and llvm-libunwind.
- FixedBuffer: drop the unused kCapacity (clang-tidy 18 reports it as a
  dynamically initialized header static).
- ss-server on Windows: manager_addr was only read in POSIX-only code,
  which newer clang rejects (-Wunused-but-set-global); say that the
  option is ignored there.

* CI: allow running the test and build workflows by hand

Stacked PRs target their parent branch, which these workflows do not
trigger on; workflow_dispatch lets each layer run the full matrix.

* CI: let clang-tidy ignore GCC-only warning flags

The compile database comes from a GCC build, whose flags (for example
-Wno-class-memaccess) clang-tidy does not know and reports as errors.
2026-10-15 09:45:54 +08:00

42 lines
1.9 KiB
Docker

ARG ALPINE_IMAGE=alpine:3.24
FROM ${ALPINE_IMAGE} AS build
ARG ALPINE_MIRROR=https://dl-cdn.alpinelinux.org/alpine
RUN sed -i "s|https://dl-cdn.alpinelinux.org/alpine|${ALPINE_MIRROR}|g" /etc/apk/repositories \
&& apk add --no-cache clang lld make musl-dev compiler-rt llvm-libunwind-static g++ libstdc++-dev cmake linux-headers python3 binutils file
ENV CC=clang CXX=clang++
WORKDIR /src
COPY . .
ARG SS_MINIMAL=OFF
RUN --network=none cmake -S . -B /build \
-DCMAKE_BUILD_TYPE=Release \
-DSS_DEPENDENCY_MODE=bundled -DWITH_STATIC=ON \
-DSS_BUILD_STATIC_LIBRARY=OFF -DSS_BUILD_SHARED_LIBRARY=OFF \
-DSS_MINIMAL=${SS_MINIMAL} -DCMAKE_EXE_LINKER_FLAGS="-static -fuse-ld=lld --rtlib=compiler-rt --unwindlib=libunwind" \
-DCMAKE_INSTALL_PREFIX=/out \
&& 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 \
&& python3 tests/async_dns_interop.py --bin /build/bin \
&& cmake --install /build --strip \
&& for binary in /out/bin/ss-*; do \
file "$binary"; \
! readelf -l "$binary" | grep -q INTERP || exit 1; \
! readelf -d "$binary" | grep -q NEEDED || exit 1; \
done
# Export binaries and their license files with --target artifacts --output.
FROM scratch AS artifacts
COPY --from=build /out/ /
# No libc, dynamic loader, package manager or shell in the runtime image.
FROM scratch AS runtime
LABEL org.opencontainers.image.title="shadowsocks-c" \
org.opencontainers.image.description="Self-contained Shadowsocks in C with libuv" \
org.opencontainers.image.source="https://github.com/shadowsocks/shadowsocks-c" \
org.opencontainers.image.licenses="GPL-3.0-or-later"
COPY --from=build /out/ /usr/local/
USER 65532:65532
EXPOSE 8388/tcp 8388/udp
ENTRYPOINT ["/usr/local/bin/ss-server"]
CMD ["-c", "/etc/shadowsocks-c/config.json"]