Skip to content

Commit 6423c8e

Browse files
madeyeclaude
andcommitted
Add Debian package build test and statically link bundled submodules
Add tests/test_deb_build.sh with four phases: 1. Build .deb packages via dpkg-buildpackage 2. Verify all three packages contain expected files (binaries, man pages, shared library, headers, pkg-config) 3. Install packages and resolve dependencies 4. Smoke-test installed binaries, ldconfig, and headers Add a Linux-only CI step in build.yml to run the test. Statically link the bundled submodule libraries (libcork, libipset, libbloom) into all targets instead of building them as shared libs. These are vendored code built from git submodules, not system libraries, so static linking is correct and eliminates dpkg-shlibdeps warnings about missing .so files. Pass -DWITH_STATIC=OFF in debian/rules since debian build-depends only provide shared library dev packages. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent d52d401 commit 6423c8e

6 files changed

Lines changed: 208 additions & 27 deletions

File tree

.github/workflows/build.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,11 @@ jobs:
5252
sudo apt-get install -y qemu-system-x86
5353
bash tests/test_redir_qemu.sh build/shared/bin/
5454
timeout-minutes: 8
55+
56+
- name: Debian package build test
57+
if: runner.os == 'Linux'
58+
run: |
59+
sudo apt-get install -y --no-install-recommends \
60+
build-essential debhelper dpkg-dev fakeroot asciidoc-base xmlto pkg-config
61+
bash tests/test_deb_build.sh
62+
timeout-minutes: 10

CMakeLists.txt

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,10 @@ else ()
137137
set(LIBCORK_SOURCE ${LIBCORK_SOURCE} libcork/src/libcork/posix/mingw.c)
138138
endif ()
139139

140-
if (WITH_STATIC)
141140
add_library(cork STATIC ${LIBCORK_SOURCE})
142141
target_compile_definitions(cork PUBLIC -DCORK_API=CORK_LOCAL)
143-
endif ()
144-
145-
add_library(cork-shared SHARED ${LIBCORK_SOURCE})
146-
target_compile_definitions(cork-shared PUBLIC -DCORK_API=CORK_EXPORT)
147-
set_target_properties(cork-shared PROPERTIES OUTPUT_NAME cork)
148142
if (MINGW)
149-
target_link_libraries(cork-shared ws2_32)
143+
target_link_libraries(cork ws2_32)
150144
endif ()
151145

152146
set(LIBIPSET_SOURCE
@@ -171,28 +165,17 @@ set(LIBIPSET_SOURCE
171165
libipset/src/libipset/set/storage.c
172166
)
173167

174-
if (WITH_STATIC)
175168
add_library(ipset STATIC ${LIBIPSET_SOURCE})
176-
endif ()
177-
178-
add_library(ipset-shared SHARED ${LIBIPSET_SOURCE})
179-
set_target_properties(ipset-shared PROPERTIES OUTPUT_NAME ipset)
180169

181170
set(LIBBLOOM_SOURCE
182171
libbloom/bloom.c
183172
libbloom/murmur2/MurmurHash2.c
184173
)
185174

186-
if (WITH_STATIC)
187175
add_library(bloom STATIC ${LIBBLOOM_SOURCE})
188176
target_link_libraries(ipset cork bloom)
189177
endif ()
190178

191-
add_library(bloom-shared SHARED ${LIBBLOOM_SOURCE})
192-
target_link_libraries(ipset-shared cork-shared bloom-shared)
193-
set_target_properties(bloom-shared PROPERTIES OUTPUT_NAME bloom)
194-
endif ()
195-
196179
add_subdirectory(src)
197180
add_subdirectory(doc)
198181

debian/rules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ override_dh_auto_install:
1111
dh_auto_install
1212

1313
override_dh_auto_configure:
14-
dh_auto_configure
14+
dh_auto_configure -- -DWITH_STATIC=OFF
1515

1616
override_dh_installchangelogs:
1717
dh_installchangelogs -XChanges

src/CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ find_library(LIBPCRE2_SHARED pcre2-8)
138138
if (WITH_EMBEDDED_SRC)
139139
list(APPEND DEPS_SHARED
140140
m
141-
bloom-shared
142-
cork-shared
143-
ipset-shared
141+
bloom
142+
cork
143+
ipset
144144
${LIBEV_SHARED}
145145
${LIBUDNS_SHARED}
146146
${LIBPCRE2_SHARED}

tests/CMakeLists.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ set(TEST_NETUTILS_LIBS
4343
${LIBUDNS_SHARED}
4444
)
4545
if(WITH_EMBEDDED_SRC)
46-
list(APPEND TEST_NETUTILS_LIBS cork-shared)
46+
list(APPEND TEST_NETUTILS_LIBS cork)
4747
else()
4848
list(APPEND TEST_NETUTILS_LIBS ${LIBCORK_SHARED})
4949
endif()
@@ -59,7 +59,7 @@ ss_add_test(test_cache
5959
# test_ppbloom - needs bloom
6060
set(TEST_PPBLOOM_LIBS "")
6161
if(WITH_EMBEDDED_SRC)
62-
list(APPEND TEST_PPBLOOM_LIBS bloom-shared)
62+
list(APPEND TEST_PPBLOOM_LIBS bloom)
6363
else()
6464
list(APPEND TEST_PPBLOOM_LIBS ${LIBBLOOM_SHARED})
6565
endif()
@@ -73,7 +73,7 @@ set(TEST_RULE_LIBS
7373
${LIBSODIUM_SHARED}
7474
)
7575
if(WITH_EMBEDDED_SRC)
76-
list(APPEND TEST_RULE_LIBS cork-shared)
76+
list(APPEND TEST_RULE_LIBS cork)
7777
else()
7878
list(APPEND TEST_RULE_LIBS ${LIBCORK_SHARED})
7979
endif()
@@ -88,7 +88,7 @@ set(TEST_JCONF_LIBS
8888
${LIBUDNS_SHARED}
8989
)
9090
if(WITH_EMBEDDED_SRC)
91-
list(APPEND TEST_JCONF_LIBS cork-shared)
91+
list(APPEND TEST_JCONF_LIBS cork)
9292
else()
9393
list(APPEND TEST_JCONF_LIBS ${LIBCORK_SHARED})
9494
endif()
@@ -109,7 +109,7 @@ set(TEST_CRYPTO_LIBS
109109
${LIBEV_SHARED}
110110
)
111111
if(WITH_EMBEDDED_SRC)
112-
list(APPEND TEST_CRYPTO_LIBS bloom-shared)
112+
list(APPEND TEST_CRYPTO_LIBS bloom)
113113
else()
114114
list(APPEND TEST_CRYPTO_LIBS ${LIBBLOOM_SHARED})
115115
endif()

tests/test_deb_build.sh

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
#!/bin/bash
2+
#
3+
# Test that Debian packages build, contain expected files, install, and work.
4+
#
5+
# Usage: bash tests/test_deb_build.sh
6+
#
7+
# Requirements (Linux only):
8+
# - dpkg-buildpackage, debhelper, fakeroot
9+
# - Build dependencies listed in debian/control
10+
# - sudo (for install phase)
11+
#
12+
13+
set -euo pipefail
14+
15+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16+
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
17+
18+
# --- helpers ----------------------------------------------------------------
19+
20+
PASS_COUNT=0
21+
FAIL_COUNT=0
22+
FAILURES=""
23+
24+
log() {
25+
echo "=== [test_deb_build] $* ==="
26+
}
27+
28+
check_pass() {
29+
PASS_COUNT=$((PASS_COUNT + 1))
30+
echo " PASS: $*"
31+
}
32+
33+
check_fail() {
34+
FAIL_COUNT=$((FAIL_COUNT + 1))
35+
FAILURES="${FAILURES} FAIL: $*"$'\n'
36+
echo " FAIL: $*"
37+
}
38+
39+
# check_file_in_deb DEB_FILE PATTERN DESCRIPTION
40+
# Verifies that at least one file matching PATTERN exists in the .deb
41+
check_file_in_deb() {
42+
local deb="$1" pattern="$2" desc="$3"
43+
# Avoid grep -q: with pipefail, early grep exit causes SIGPIPE on dpkg-deb
44+
if dpkg-deb -c "$deb" | grep -E "$pattern" >/dev/null; then
45+
check_pass "$desc"
46+
else
47+
check_fail "$desc"
48+
fi
49+
}
50+
51+
# check_command CMD DESCRIPTION
52+
# Verifies that a command runs successfully (exit 0)
53+
check_command() {
54+
local desc="$2"
55+
if eval "$1" >/dev/null 2>&1; then
56+
check_pass "$desc"
57+
else
58+
check_fail "$desc"
59+
fi
60+
}
61+
62+
summary() {
63+
echo ""
64+
log "Results: $PASS_COUNT passed, $FAIL_COUNT failed"
65+
if [ "$FAIL_COUNT" -gt 0 ]; then
66+
echo ""
67+
echo "Failures:"
68+
printf '%s' "$FAILURES"
69+
exit 1
70+
fi
71+
}
72+
73+
# --- phase 1: build --------------------------------------------------------
74+
75+
log "Phase 1: Build Debian packages"
76+
77+
cd "$PROJECT_DIR"
78+
79+
# dpkg-buildpackage -b builds binary-only packages (no .orig.tar.gz needed)
80+
dpkg-buildpackage -b -us -uc -j"$(nproc)"
81+
82+
# .deb files are placed in the parent directory
83+
PARENT_DIR="$(dirname "$PROJECT_DIR")"
84+
85+
DEB_MAIN=""
86+
DEB_LIB=""
87+
DEB_DEV=""
88+
for f in "$PARENT_DIR"/shadowsocks-libev_*.deb; do
89+
[ -f "$f" ] && DEB_MAIN="$f" && break
90+
done
91+
for f in "$PARENT_DIR"/libshadowsocks-libev2_*.deb; do
92+
[ -f "$f" ] && DEB_LIB="$f" && break
93+
done
94+
for f in "$PARENT_DIR"/libshadowsocks-libev-dev_*.deb; do
95+
[ -f "$f" ] && DEB_DEV="$f" && break
96+
done
97+
98+
# --- phase 2: verify contents ----------------------------------------------
99+
100+
log "Phase 2: Verify package contents"
101+
102+
# Check all three .deb files exist
103+
if [ -n "$DEB_MAIN" ] && [ -f "$DEB_MAIN" ]; then
104+
check_pass "shadowsocks-libev .deb exists: $(basename "$DEB_MAIN")"
105+
else
106+
check_fail "shadowsocks-libev .deb not found"
107+
fi
108+
109+
if [ -n "$DEB_LIB" ] && [ -f "$DEB_LIB" ]; then
110+
check_pass "libshadowsocks-libev2 .deb exists: $(basename "$DEB_LIB")"
111+
else
112+
check_fail "libshadowsocks-libev2 .deb not found"
113+
fi
114+
115+
if [ -n "$DEB_DEV" ] && [ -f "$DEB_DEV" ]; then
116+
check_pass "libshadowsocks-libev-dev .deb exists: $(basename "$DEB_DEV")"
117+
else
118+
check_fail "libshadowsocks-libev-dev .deb not found"
119+
fi
120+
121+
# Bail early if any .deb is missing - remaining checks would all fail
122+
if [ "$FAIL_COUNT" -gt 0 ]; then
123+
summary
124+
fi
125+
126+
# Main package: binaries
127+
for bin in ss-local ss-server ss-redir ss-tunnel ss-manager; do
128+
check_file_in_deb "$DEB_MAIN" "usr/bin/${bin}" "$bin binary in main package"
129+
done
130+
131+
# Main package: man pages
132+
for bin in ss-local ss-server ss-redir ss-tunnel ss-manager; do
133+
check_file_in_deb "$DEB_MAIN" "usr/share/man/man1/$bin\\.1" "$bin man page in main package"
134+
done
135+
136+
# Shared library package
137+
check_file_in_deb "$DEB_LIB" "usr/lib/.*/libshadowsocks-libev\\.so\\." "shared library in lib package"
138+
139+
# Dev package: header
140+
check_file_in_deb "$DEB_DEV" "usr/include/shadowsocks\\.h" "shadowsocks.h header in dev package"
141+
142+
# Dev package: pkg-config
143+
check_file_in_deb "$DEB_DEV" "usr/lib/.*/pkgconfig/shadowsocks-libev\\.pc" "pkg-config file in dev package"
144+
145+
# Dev package: unversioned .so symlink
146+
check_file_in_deb "$DEB_DEV" "usr/lib/.*/libshadowsocks-libev\\.so[^.]" "unversioned .so symlink in dev package"
147+
148+
# --- phase 3: install -------------------------------------------------------
149+
150+
log "Phase 3: Install packages"
151+
152+
sudo dpkg -i "$DEB_LIB" "$DEB_DEV" "$DEB_MAIN" || true
153+
sudo apt-get -f install -y
154+
155+
# Verify dpkg thinks they are installed
156+
for pkg in shadowsocks-libev libshadowsocks-libev2 libshadowsocks-libev-dev; do
157+
if dpkg -s "$pkg" >/dev/null 2>&1; then
158+
check_pass "$pkg installed"
159+
else
160+
check_fail "$pkg not installed"
161+
fi
162+
done
163+
164+
# --- phase 4: smoke-test ----------------------------------------------------
165+
166+
log "Phase 4: Smoke-test installed binaries"
167+
168+
# Each binary should respond to --help
169+
for bin in ss-local ss-server ss-redir ss-tunnel ss-manager; do
170+
check_command "$bin --help" "$bin --help runs"
171+
done
172+
173+
# Shared library should be findable by ldconfig
174+
sudo ldconfig
175+
if ldconfig -p | grep -q libshadowsocks-libev; then
176+
check_pass "libshadowsocks-libev found by ldconfig"
177+
else
178+
check_fail "libshadowsocks-libev not found by ldconfig"
179+
fi
180+
181+
# Header should be in the include path
182+
if [ -f /usr/include/shadowsocks.h ]; then
183+
check_pass "shadowsocks.h installed in /usr/include"
184+
else
185+
check_fail "shadowsocks.h not installed in /usr/include"
186+
fi
187+
188+
# --- summary ----------------------------------------------------------------
189+
190+
summary

0 commit comments

Comments
 (0)