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 51set -eu 52 53ARTIFACT_DIR="/artifact" 54TOXIC_SRC_DIR="/toxic" 55 56# Make sure we run in the expected environment 57if ! grep -q 'docker' /proc/1/cgroup 58then 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 61fi 62 63if [ ! -f /etc/os-release ] || ! grep -qi 'Alpine Linux' /etc/os-release 64then 65 echo "Error: This script expects to be run on Alpine Linux." 66 exit 1 67fi 68 69if [ ! -d "$ARTIFACT_DIR" ] || [ ! -d "$TOXIC_SRC_DIR" ] 70then 71 echo "Error: At least one of $ARTIFACT_DIR or $TOXIC_SRC_DIR directories inside the container is missing." 72 exit 1 73fi 74 75if [ "$(id -u)" != "0" ] 76then 77 echo "Error: This script expects to be run as root." 78 exit 1 79fi 80 81set -x 82 83# Use all cores for building 84MAKEFLAGS=j$(nproc) 85export MAKEFLAGS 86 87check_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 100apk update 101apk upgrade 102apk 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 127BUILD_DIR="/tmp/build" 128mkdir -p "$BUILD_DIR" 129 130 131# Build Toxcore 132cd "$BUILD_DIR" 133 134# The git hash of the c-toxcore version we're using 135TOXCORE_VERSION="v0.2.13" 136 137# The sha256sum of the c-toxcore tarball for TOXCORE_VERSION 138TOXCORE_HASH="67114fa57504c58b695f5dce8ef85124d555f2c3c353d0d2615e6d4845114ab8" 139 140TOXCORE_FILENAME="c-toxcore-$TOXCORE_VERSION.tar.gz" 141 142wget --timeout=10 -O "$TOXCORE_FILENAME" "https://github.com/TokTok/c-toxcore/archive/$TOXCORE_VERSION.tar.gz" 143check_sha256 "$TOXCORE_HASH" "$TOXCORE_FILENAME" 144tar -o -xf "$TOXCORE_FILENAME" 145rm "$TOXCORE_FILENAME" 146cd c-toxcore* 147 148cmake -B_build -H. \ 149 -DENABLE_STATIC=ON \ 150 -DENABLE_SHARED=OFF \ 151 -DCMAKE_BUILD_TYPE=Release \ 152 -DBUILD_TOXAV=OFF \ 153 -DBOOTSTRAP_DAEMON=OFF \ 154 -DDHT_BOOTSTRAP=OFF \ 155 -DCMAKE_INSTALL_PREFIX="$BUILD_DIR/prefix-toxcore" 156cmake --build _build --target install 157 158 159# Build cURL 160# While Alpine does provide a static cURL build, it's not built with 161# --with-ca-fallback, which is needed for better cross-distro portability. 162# Basically, some distros put their ca-certificates in different places, and 163# with --with-ca-fallback we or the user can provide the cert bundle file 164# location with SSL_CERT_FILE env variable. 165cd "$BUILD_DIR" 166 167CURL_VERSION="7.80.0" 168CURL_HASH="dab997c9b08cb4a636a03f2f7f985eaba33279c1c52692430018fae4a4878dc7" 169CURL_FILENAME="curl-$CURL_VERSION.tar.gz" 170 171wget --timeout=10 -O "$CURL_FILENAME" "https://curl.haxx.se/download/$CURL_FILENAME" 172check_sha256 "$CURL_HASH" "$CURL_FILENAME" 173tar -xf curl*.tar.gz 174rm curl*.tar.gz 175cd curl* 176 177./configure \ 178 --prefix="$BUILD_DIR/prefix-curl" \ 179 --disable-shared \ 180 --enable-static \ 181 --without-ca-bundle \ 182 --without-ca-path \ 183 --with-ca-fallback \ 184 --with-nghttp2 \ 185 --with-brotli \ 186 --with-openssl 187make 188make install 189sed -i 's|-lbrotlidec |-lbrotlidec-static -lbrotlicommon-static |g' $BUILD_DIR/prefix-curl/lib/pkgconfig/libcurl.pc 190 191# Build Toxic 192cd "$BUILD_DIR" 193cp -a "$TOXIC_SRC_DIR" toxic 194cd toxic 195 196if [ -z "$(git describe --tags --exact-match HEAD)" ] 197then 198 set +x 199 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 200 printf "Do you wish to proceed? (y/N): " 201 read -r answer 202 if echo "$answer" | grep -v -iq "^y" ; then 203 echo "Exiting." 204 exit 1 205 fi 206 set -x 207fi 208 209sed -i 's|pkg-config|pkg-config --static|' cfg/global_vars.mk 210sed -i 's|<limits.h|<linux/limits.h|' src/* 211 212CFLAGS="-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 \ 213 DISABLE_X11=1 \ 214 DISABLE_AV=1 \ 215 DISABLE_SOUND_NOTIFY=1 \ 216 DISABLE_QRCODE=1 \ 217 DISABLE_QRPNG=1 \ 218 DISABLE_DESKTOP_NOTIFY=1 \ 219 ENABLE_PYTHON=0 \ 220 ENABLE_RELEASE=1 \ 221 ENABLE_ASAN=0 \ 222 DISABLE_GAMES=0 \ 223 install 224 225 226# Prepare the build artifact 227PREPARE_ARTIFACT_DIR="$BUILD_DIR/artifact" 228cp -a "$BUILD_DIR/prefix-toxic/bin" "$PREPARE_ARTIFACT_DIR" 229strip "$PREPARE_ARTIFACT_DIR"/* 230 231cp -a "$BUILD_DIR/toxic/misc"/* "$PREPARE_ARTIFACT_DIR" 232mv "$PREPARE_ARTIFACT_DIR/toxic.conf.example" "$PREPARE_ARTIFACT_DIR/toxic.conf" 233 234cp -aL /usr/share/terminfo "$PREPARE_ARTIFACT_DIR" 235 236echo "A minimal statically compiled Toxic. 237Doesn't support X11 integration, video/audio calls, desktop & sound 238notifications, QR codes and Python scripting. 239However, it is rather portable. 240 241Toxic $(git -C "$BUILD_DIR/toxic" describe --tags --exact-match HEAD) ($(git -C "$BUILD_DIR/toxic" rev-parse HEAD)) 242 243Build date time: $(TZ=UTC date +"%Y-%m-%dT%H:%M:%S%z") 244 245OS: 246$(cat /etc/os-release) 247 248List of self-built software statically compiled into Toxic: 249libcurl $CURL_VERSION 250libtoxcore $TOXCORE_VERSION 251 252List of OS-packaged software statically compiled into Toxic: 253$(apk list -I | grep 'static' | sort -i) 254 255List of all packages installed during the build: 256$(apk list -I | sort -i)" > "$PREPARE_ARTIFACT_DIR/build_info" 257 258echo '#!/usr/bin/env sh 259 260DEBIAN_SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt 261RHEL_SSL_CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt 262OPENSUSE_CERT_FILE=/etc/ssl/ca-bundle.pem 263 264if [ ! -f "$SSL_CERT_FILE" ] ; then 265 if [ -f "$DEBIAN_SSL_CERT_FILE" ] ; then 266 SSL_CERT_FILE="$DEBIAN_SSL_CERT_FILE" 267 elif [ -f "$RHEL_SSL_CERT_FILE" ] ; then 268 SSL_CERT_FILE="$RHEL_SSL_CERT_FILE" 269 elif [ -f "$OPENSUSE_CERT_FILE" ] ; then 270 SSL_CERT_FILE="$OPENSUSE_CERT_FILE" 271 fi 272fi 273 274if [ -z "$SSL_CERT_FILE" ] ; then 275 echo "Warning: Couldn'\''t find the SSL CA certificate store file." | fold -sw 80 276 echo 277 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 278 echo 279 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 280 echo 281 printf "Do you wish to run Toxic without SSL CA certificate store file found? (y/N): " 282 read -r answer 283 if echo "$answer" | grep -v -iq "^y" ; then 284 echo "Exiting." 285 exit 286 fi 287fi 288 289cd "$(dirname -- $0)" 290 291SSL_CERT_FILE="$SSL_CERT_FILE" TERMINFO=./terminfo ./toxic -c toxic.conf' > "$PREPARE_ARTIFACT_DIR/run_toxic.sh" 292chmod a+x "$PREPARE_ARTIFACT_DIR/run_toxic.sh" 293 294 295# Tar it 296cd "$PREPARE_ARTIFACT_DIR" 297cd .. 298ARCH="$(tr '_' '-' < /etc/apk/arch)" 299ARTIFACT_NAME="toxic-minimal-static-musl_linux_$ARCH" 300mv "$PREPARE_ARTIFACT_DIR" "$PREPARE_ARTIFACT_DIR/../$ARTIFACT_NAME" 301tar -cJf "$ARTIFACT_NAME.tar.xz" "$ARTIFACT_NAME" 302mv "$ARTIFACT_NAME.tar.xz" "$ARTIFACT_DIR" 303chmod 777 -R "$ARTIFACT_DIR" 304 305