Skip to content

Commit b37e28c

Browse files
committed
Add a script for building minimal static toxic
The intention is that JFreegman would run it locally on his machine for every Toxic release and publish the build artifacts on GitHub for download, similarly to how the qTox team makes release builds. This should mitigate the loss of the Jenkins build server to some extent, which used to provide Toxic builds before.
1 parent 973e60e commit b37e28c

1 file changed

Lines changed: 297 additions & 0 deletions

File tree

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
#!/usr/bin/env sh
2+
3+
# MIT License
4+
#
5+
# Copyright (c) 2021 Maxim Biro <nurupo.contributions@gmail.com>
6+
#
7+
# Permission is hereby granted, free of charge, to any person obtaining a copy
8+
# of this software and associated documentation files (the "Software"), to deal
9+
# in the Software without restriction, including without limitation the rights
10+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
# copies of the Software, and to permit persons to whom the Software is
12+
# furnished to do so, subject to the following conditions:
13+
#
14+
# The above copyright notice and this permission notice shall be included in
15+
# all copies or substantial portions of the Software.
16+
#
17+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
# THE SOFTWARE.
24+
25+
# Script for building a minimal statically compiled Toxic. While it doesn't
26+
# support X11 integration, video/audio calls, desktop & sound notifications, QR
27+
# codes and Python scripting, it is rather portable.
28+
#
29+
# Run as:
30+
#
31+
# sudo docker run -it --rm \
32+
# -v /tmp/artifact:/artifact \
33+
# -v /home/jfreegman/git/toxic:/toxic \
34+
# amd64/alpine:latest \
35+
# /bin/sh /toxic/script/build-minimal-static-toxic.sh
36+
#
37+
# that would use Toxic code from /home/jfreegman/git/toxic and place the build
38+
# artifact at /tmp/artifact.
39+
# You can change between amd64/alpine:latest and i386/alpine:latest, for 64-bit
40+
# and 32-bit builds.
41+
#
42+
# To debug, run:
43+
#
44+
# sudo docker run -it --rm \
45+
# -v /tmp/artifact:/artifact \
46+
# -v /home/jfreegman/git/toxic:/toxic \
47+
# amd64/alpine:latest \
48+
# /bin/sh
49+
# # sh /toxic/script/build-minimal-static-toxic.sh
50+
51+
set -eu
52+
53+
ARTIFACT_DIR="/artifact"
54+
TOXIC_SRC_DIR="/toxic"
55+
56+
# Make sure we run in the expected environment
57+
if ! grep -q 'docker' /proc/1/cgroup
58+
then
59+
echo "Error: This script should be run inside a disposable Docker container as it might modify system files in ways that would break a real system."
60+
exit 1
61+
fi
62+
63+
if [ ! -f /etc/os-release ] || ! grep -qi 'Alpine Linux' /etc/os-release
64+
then
65+
echo "Error: This script expects to be run on Alpine Linux."
66+
exit 1
67+
fi
68+
69+
if [ ! -d "$ARTIFACT_DIR" ] || [ ! -d "$TOXIC_SRC_DIR" ]
70+
then
71+
echo "Error: At least one of $ARTIFACT_DIR or $TOXIC_SRC_DIR directories inside the container is missing."
72+
exit 1
73+
fi
74+
75+
if [ "$(id -u)" != "0" ]
76+
then
77+
echo "Error: This script expects to be run as root."
78+
exit 1
79+
fi
80+
81+
set -x
82+
83+
# Use all cores for building
84+
MAKEFLAGS=j$(nproc)
85+
export MAKEFLAGS
86+
87+
check_sha256()
88+
{
89+
if ! ( echo "$1 $2" | sha256sum -cs - )
90+
then
91+
echo "Error: sha256 of $2 doesn't match the known one."
92+
echo "Expected: $1 $2"
93+
echo "Got: $(sha256sum "$2")"
94+
exit 1
95+
else
96+
echo "sha256 matches the expected one: $1"
97+
fi
98+
}
99+
100+
apk update
101+
apk upgrade
102+
apk add \
103+
brotli-dev \
104+
brotli-static \
105+
build-base \
106+
cmake \
107+
git \
108+
libconfig-dev \
109+
libconfig-static \
110+
libsodium-dev \
111+
libsodium-static \
112+
linux-headers \
113+
ncurses-dev \
114+
ncurses-static \
115+
ncurses-terminfo \
116+
ncurses-terminfo-base \
117+
nghttp2-dev \
118+
nghttp2-static \
119+
openssl-dev \
120+
openssl-libs-static \
121+
pkgconf \
122+
wget \
123+
xz \
124+
zlib-dev \
125+
zlib-static
126+
127+
BUILD_DIR="/tmp/build"
128+
mkdir -p "$BUILD_DIR"
129+
130+
131+
# Build Toxcore
132+
cd "$BUILD_DIR"
133+
134+
TOXCORE_VERSION="0.2.12"
135+
TOXCORE_HASH="30ae3263c9b68d3bef06f799ba9d7a67e3fad447030625f0ffa4bb22684228b0"
136+
TOXCORE_FILENAME="c-toxcore-$TOXCORE_VERSION.tar.gz"
137+
138+
wget --timeout=10 -O "$TOXCORE_FILENAME" "https://github.com/TokTok/c-toxcore/archive/v$TOXCORE_VERSION.tar.gz"
139+
check_sha256 "$TOXCORE_HASH" "$TOXCORE_FILENAME"
140+
tar -o -xf "$TOXCORE_FILENAME"
141+
rm "$TOXCORE_FILENAME"
142+
cd c-toxcore*
143+
144+
cmake -B_build -H. \
145+
-DENABLE_STATIC=ON \
146+
-DENABLE_SHARED=OFF \
147+
-DCMAKE_BUILD_TYPE=Release \
148+
-DBUILD_TOXAV=OFF \
149+
-DBOOTSTRAP_DAEMON=OFF \
150+
-DDHT_BOOTSTRAP=OFF \
151+
-DCMAKE_INSTALL_PREFIX="$BUILD_DIR/prefix-toxcore"
152+
cmake --build _build --target install
153+
154+
155+
# Build cURL
156+
# While Alpine does provide a static cURL build, it's not built with
157+
# --with-ca-fallback, which is needed for better cross-distro portability.
158+
# Basically, some distros put their ca-certificates in different places, and
159+
# with --with-ca-fallback we or the user can provide the cert bundle file
160+
# location with SSL_CERT_FILE env variable.
161+
cd "$BUILD_DIR"
162+
163+
CURL_VERSION="7.74.0"
164+
CURL_HASH="e56b3921eeb7a2951959c02db0912b5fcd5fdba5aca071da819e1accf338bbd7"
165+
CURL_FILENAME="curl-$CURL_VERSION.tar.gz"
166+
167+
wget --timeout=10 -O "$CURL_FILENAME" "https://curl.haxx.se/download/$CURL_FILENAME"
168+
check_sha256 "$CURL_HASH" "$CURL_FILENAME"
169+
tar -xf curl*.tar.gz
170+
rm curl*.tar.gz
171+
cd curl*
172+
173+
./configure \
174+
--prefix="$BUILD_DIR/prefix-curl" \
175+
--disable-shared \
176+
--enable-static \
177+
--without-ca-bundle \
178+
--without-ca-path \
179+
--with-ca-fallback \
180+
--with-nghttp2 \
181+
--with-brotli
182+
make
183+
make install
184+
sed -i 's|-lbrotlidec |-lbrotlidec-static -lbrotlicommon-static |g' $BUILD_DIR/prefix-curl/lib/pkgconfig/libcurl.pc
185+
186+
# Build Toxic
187+
cd "$BUILD_DIR"
188+
cp -a "$TOXIC_SRC_DIR" toxic
189+
cd toxic
190+
191+
if [ -z "$(git describe --tags --exact-match HEAD)" ]
192+
then
193+
set +x
194+
echo "Didn't find a git tag on the HEAD commit. You seem to be building an in-development release of Toxic rather than a release version." | fold -sw 80
195+
printf "Do you wish to proceed? (y/N): "
196+
read -r answer
197+
if echo "$answer" | grep -v -iq "^y" ; then
198+
echo "Exiting."
199+
exit 1
200+
fi
201+
set -x
202+
fi
203+
204+
sed -i 's|pkg-config|pkg-config --static|' cfg/global_vars.mk
205+
sed -i 's|<limits.h|<linux/limits.h|' src/*
206+
207+
CFLAGS="-static" PKG_CONFIG_PATH="$BUILD_DIR/prefix-toxcore/lib64/pkgconfig:$BUILD_DIR/prefix-toxcore/lib/pkgconfig:$BUILD_DIR/prefix-curl/lib/pkgconfig" PREFIX="$BUILD_DIR/prefix-toxic" make \
208+
DISABLE_X11=1 \
209+
DISABLE_AV=1 \
210+
DISABLE_SOUND_NOTIFY=1 \
211+
DISABLE_QRCODE=1 \
212+
DISABLE_QRPNG=1 \
213+
DISABLE_DESKTOP_NOTIFY=1 \
214+
ENABLE_PYTHON=0 \
215+
ENABLE_RELEASE=1 \
216+
ENABLE_ASAN=0 \
217+
install
218+
219+
220+
# Prepare the build artifact
221+
PREPARE_ARTIFACT_DIR="$BUILD_DIR/artifact"
222+
cp -a "$BUILD_DIR/prefix-toxic/bin" "$PREPARE_ARTIFACT_DIR"
223+
strip "$PREPARE_ARTIFACT_DIR"/*
224+
225+
cp -a "$BUILD_DIR/toxic/misc"/* "$PREPARE_ARTIFACT_DIR"
226+
mv "$PREPARE_ARTIFACT_DIR/toxic.conf.example" "$PREPARE_ARTIFACT_DIR/toxic.conf"
227+
228+
cp -aL /usr/share/terminfo "$PREPARE_ARTIFACT_DIR"
229+
230+
echo "A minimal statically compiled Toxic.
231+
Doesn't support X11 integration, video/audio calls, desktop & sound
232+
notifications, QR codes and Python scripting.
233+
However, it is rather portable.
234+
235+
Toxic $(git -C "$BUILD_DIR/toxic" describe --tags --exact-match HEAD) ($(git -C "$BUILD_DIR/toxic" rev-parse HEAD))
236+
237+
Build date time: $(TZ=UTC date +"%Y-%m-%dT%H:%M:%S%z")
238+
239+
OS:
240+
$(cat /etc/os-release)
241+
242+
List of self-built software statically compiled into Toxic:
243+
libcurl $CURL_VERSION
244+
libtoxcore $TOXCORE_VERSION
245+
246+
List of OS-packaged software statically compiled into Toxic:
247+
$(apk list -I | grep 'static' | sort -i)
248+
249+
List of all packages installed during the build:
250+
$(apk list -I | sort -i)" > "$PREPARE_ARTIFACT_DIR/build_info"
251+
252+
echo '#!/usr/bin/env sh
253+
254+
DEBIAN_SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
255+
RHEL_SSL_CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt
256+
OPENSUSE_CERT_FILE=/etc/ssl/ca-bundle.pem
257+
258+
if [ ! -f "$SSL_CERT_FILE" ] ; then
259+
if [ -f "$DEBIAN_SSL_CERT_FILE" ] ; then
260+
SSL_CERT_FILE="$DEBIAN_SSL_CERT_FILE"
261+
elif [ -f "$RHEL_SSL_CERT_FILE" ] ; then
262+
SSL_CERT_FILE="$RHEL_SSL_CERT_FILE"
263+
elif [ -f "$OPENSUSE_CERT_FILE" ] ; then
264+
SSL_CERT_FILE="$OPENSUSE_CERT_FILE"
265+
fi
266+
fi
267+
268+
if [ -z "$SSL_CERT_FILE" ] ; then
269+
echo "Warning: Couldn'\''t find the SSL CA certificate store file." | fold -sw 80
270+
echo
271+
echo "Toxic uses HTTPS to download a list of DHT bootstrap nodes in order to connect to the Tox DHT. This functionality is optional, you should be able to use Toxic without it. If you choose to use Toxic without it, you might need to manually enter DHT bootstrap node information using the '\''/connect'\'' command in order to come online." | fold -sw 80
272+
echo
273+
echo "To fix this issue, install SSL CAs as provided by your Linux distribution, e.g. '\''ca-certificates'\'' package on Debian/Ubuntu. If it'\''s already installed and you still see this message, run this script with SSL_CERT_FILE variable set to point to the SSL CA certificate store file location. The file is usually named '\''ca-certificates.crt'\'' or '\''ca-bundle.pem'\''." | fold -sw 80
274+
echo
275+
printf "Do you wish to run Toxic without SSL CA certificate store file found? (y/N): "
276+
read -r answer
277+
if echo "$answer" | grep -v -iq "^y" ; then
278+
echo "Exiting."
279+
exit
280+
fi
281+
fi
282+
283+
cd "$(dirname -- $0)"
284+
285+
SSL_CERT_FILE="$SSL_CERT_FILE" TERMINFO=./terminfo ./toxic -c toxic.conf' > "$PREPARE_ARTIFACT_DIR/run_toxic.sh"
286+
chmod a+x "$PREPARE_ARTIFACT_DIR/run_toxic.sh"
287+
288+
289+
# Tar it
290+
cd "$PREPARE_ARTIFACT_DIR"
291+
cd ..
292+
ARCH="$(tr '_' '-' < /etc/apk/arch)"
293+
ARTIFACT_NAME="toxic-minimal-static-musl_linux_$ARCH"
294+
mv "$PREPARE_ARTIFACT_DIR" "$PREPARE_ARTIFACT_DIR/../$ARTIFACT_NAME"
295+
tar -cJf "$ARTIFACT_NAME.tar.xz" "$ARTIFACT_NAME"
296+
mv "$ARTIFACT_NAME.tar.xz" "$ARTIFACT_DIR"
297+
chmod 777 -R "$ARTIFACT_DIR"

0 commit comments

Comments
 (0)