-
-
Save zenofile/d2acef1a0423e5081e74162cd5a0ae2d to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash | |
set -o errexit | |
MUSL_VERSION=1.2.5 | |
LIBEVENT_VERSION=2.1.12 | |
NCURSES_VERSION=6.5 | |
TMUX_VERSION=3.5a | |
TARGETDIR=$1 | |
if [[ "${TARGETDIR}" = "" ]]; then | |
TARGETDIR="${PWD}/out" | |
fi | |
mkdir -p "${TARGETDIR}" | |
TASKS=$(nproc) | |
CC=( "${TARGETDIR}/bin/musl-gcc" -static ) | |
_CFLAGS=( -Os -ffunction-sections -fdata-sections -no-pie) | |
_LDFLAGS=( "-Wl,--gc-sections" -flto ) | |
_musl() { | |
if [[ ! -e musl-${MUSL_VERSION}.tar.gz ]]; then | |
curl -LO https://www.musl-libc.org/releases/musl-${MUSL_VERSION}.tar.gz | |
fi | |
tar zxf musl-${MUSL_VERSION}.tar.gz --skip-old-files | |
pushd . | |
cd musl-${MUSL_VERSION} | |
CFLAGS="${_CFLAGS[*]}" LDFLAGS="${_LDFLAGS[*]}" ./configure --prefix="${TARGETDIR}" --disable-shared --enable-wrapper=gcc | |
make -j $TASKS | |
make install | |
make clean | |
popd | |
} | |
_libevent() { | |
if [[ ! -e libevent-${LIBEVENT_VERSION}-stable.tar.gz ]]; then | |
curl -LO https://github.com/libevent/libevent/releases/download/release-${LIBEVENT_VERSION}-stable/libevent-${LIBEVENT_VERSION}-stable.tar.gz | |
fi | |
tar zxf libevent-${LIBEVENT_VERSION}-stable.tar.gz --skip-old-files | |
pushd . | |
cd libevent-${LIBEVENT_VERSION}-stable | |
_cflags=("${_CFLAGS[@]}" -flto) | |
CC="${CC[*]}" CFLAGS="${_cflags[*]}" LDFLAGS="${_LDFLAGS[*]}" ./configure --prefix="${TARGETDIR}" --disable-shared --disable-openssl --disable-samples | |
make -j $TASKS | |
make install | |
make clean | |
popd | |
} | |
_ncurses() { | |
if [[ ! -e ncurses-${NCURSES_VERSION}.tar.gz ]]; then | |
curl -LO https://ftp.gnu.org/pub/gnu/ncurses/ncurses-${NCURSES_VERSION}.tar.gz | |
fi | |
tar zxvf ncurses-${NCURSES_VERSION}.tar.gz --skip-old-files | |
pushd . | |
cd ncurses-${NCURSES_VERSION} | |
_cflags=( "${_CFLAGS[@]}" -flto ) | |
CC="${CC[*]}" CFLAGS="${_cflags[*]}" LDFLAGS="${_LDFLAGS[*]}" ./configure --prefix $TARGETDIR \ | |
--with-default-terminfo-dir=/usr/share/terminfo \ | |
--with-terminfo-dirs="/etc/terminfo:/lib/terminfo:/usr/share/terminfo" \ | |
--enable-pc-files \ | |
--with-pkg-config-libdir="${TARGETDIR}/lib/pkgconfig" \ | |
--without-ada \ | |
--without-debug \ | |
--with-termlib \ | |
--without-cxx \ | |
--without-progs \ | |
--without-manpages \ | |
--disable-db-install \ | |
--without-tests | |
make -j $TASKS | |
make install | |
make clean | |
popd | |
} | |
_tmux() { | |
if [[ ! -e tmux-${TMUX_VERSION}.tar.gz ]]; then | |
curl -LO https://github.com/tmux/tmux/releases/download/${TMUX_VERSION}/tmux-${TMUX_VERSION}.tar.gz | |
fi | |
tar zxf tmux-${TMUX_VERSION}.tar.gz --skip-old-files | |
pushd . | |
cd tmux-${TMUX_VERSION} | |
_cflags=( "${_CFLAGS[@]}" -flto ) | |
CC="${CC[*]}" CFLAGS="${_cflags[*]}" LDFLAGS="${_LDFLAGS[*]}" PKG_CONFIG_PATH="${TARGETDIR}/lib/pkgconfig" ./configure --enable-static --prefix="${TARGETDIR}" | |
make -j $TASKS | |
make install | |
make clean | |
popd | |
cp "${TARGETDIR}/bin/tmux" . | |
strip --strip-all ./tmux | |
if command -v upx &> /dev/null; then | |
upx -k --best ./tmux | |
fi | |
} | |
rm -rf "${TARGETDIR}/out" | |
if [[ ! -x "${TARGETDIR}/bin/musl-gcc" ]]; then | |
_musl | |
fi | |
_libevent | |
_ncurses | |
_tmux |
And for anyone interested, I wrote a Vagrantfile that runs this script in a clean Ubuntu 20.04 LTS install:
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "bento/ubuntu-20.04"
config.vm.provision "Install compiler etc",
type: "shell",
inline: <<-SHELL
apt-get update
apt-get install -y build-essential
SHELL
config.vm.provision "Download script",
type: "shell",
privileged: false,
inline: <<-SHELL
wget -qO build.sh https://gist.github.com/zenofile/d2acef1a0423e5081e74162cd5a0ae2d/raw/2c2e73a298c0d822773ceeca69c3cace8fce4c96/build.sh
SHELL
config.vm.provision "Patch script",
type: "shell",
privileged: false,
inline: <<-SHELL
DATA="
ZGlmZiAtLWdpdCBhL2J1aWxkLnNoIGIvYnVpbGQuc2gKaW5kZXggM2FkMDRmMC4uMTNmY2JmZCAx
MDA2NDQKLS0tIGEvYnVpbGQuc2gKKysrIGIvYnVpbGQuc2gKQEAgLTEzLDcgKzEzLDcgQEAgaWYg
W1sgIiR7VEFSR0VURElSfSIgPSAiIiBdXTsgdGhlbgogZmkKIG1rZGlyIC1wICIke1RBUkdFVERJ
Un0iCiAKLVRBU0tTPTIKK1RBU0tTPSQobnByb2MpCiBDQz0oICIke1RBUkdFVERJUn0vYmluL211
c2wtZ2NjIiAtc3RhdGljICkKIF9DRkxBR1M9KCAtT3MgLWZmdW5jdGlvbi1zZWN0aW9ucyAtZmRh
dGEtc2VjdGlvbnMgLW5vLXBpZSkKIF9MREZMQUdTPSggIi1XbCwtLWdjLXNlY3Rpb25zIiAtZmx0
byApCkBAIC04Myw3ICs4Myw3IEBAIF90bXV4KCkgewogCXRhciB6eGYgdG11eC0ke1RNVVhfVkVS
U0lPTn0udGFyLmd6IC0tc2tpcC1vbGQtZmlsZXMKIAlwdXNoZCAuCiAJY2QgdG11eC0ke1RNVVhf
VkVSU0lPTn0KLQlfY2ZsYWdzPSggIiR7X0NGTEFHU1tAXX0iIC1mbHRvICkKKwlfY2ZsYWdzPSgg
IiR7X0NGTEFHU1tAXX0iIC1mbHRvICItSSR7VEFSR0VURElSfS9pbmNsdWRlL25jdXJzZXMvIiAp
CiAJQ0M9IiR7Q0NbKl19IiBDRkxBR1M9IiR7X2NmbGFnc1sqXX0iIExERkxBR1M9IiR7X0xERkxB
R1NbKl19IiBQS0dfQ09ORklHX1BBVEg9IiR7VEFSR0VURElSfS9saWIvcGtnY29uZmlnIiAuL2Nv
bmZpZ3VyZSAtLWVuYWJsZS1zdGF0aWMgLS1wcmVmaXg9IiR7VEFSR0VURElSfSIKIAltYWtlIC1q
ICRUQVNLUwogCW1ha2UgaW5zdGFsbAo=
"
base64 --decode --ignore-garbage <<<$DATA > build.diff
patch -p1 < build.diff
SHELL
config.vm.provision "Build TMUX",
type: "shell",
privileged: false,
inline: <<-SHELL
bash -x ./build.sh
SHELL
config.vm.provision "Copy out TMUX binary",
type: "shell",
privileged: false,
inline: <<-SHELL
cp -v tmux /vagrant/
SHELL
end
That's awesome, thanks!
I was building it in an Archlinux container using podman and didn't test any other build environment.
podman run --rm -it --hostname archns --userns=host --tmpfs /tmp:exec,rw -v ./build.sh:/tmp/build/build.sh -v /tmp/build-tmux:/tmp/build --workdir=/tmp/build --security-opt label=disable gitlab.archlinux.org:5050/archlinux/archlinux-docker:base-devel-master /bin/bash /tmp/build/build.sh
For anyone that might be preferring podman or docker.
hello, thanks so much,
i am using a shared linux vm, no root access, spent days trying replace the very old tmux, lacked the skills.
wanted to let you know your script works with tmux 3.2a,
TMUX_VERSION=3.2a
really, thanks!
Fantastic. In order to build on older systems, with a gcc that doesn't support -no-pie
, add the following patch:
diff --git a/build.sh b/build.sh
index e7f6c33..720226e 100755
--- a/build.sh
+++ b/build.sh
@@ -15,7 +15,10 @@ mkdir -p "${TARGETDIR}"
TASKS=2
CC=( "${TARGETDIR}/bin/musl-gcc" -static )
-_CFLAGS=( -Os -ffunction-sections -fdata-sections -no-pie)
+_CFLAGS=( -Os -ffunction-sections -fdata-sections )
+if "${REALGCC:-gcc}" -v 2>&1 | grep -q -- --enable-default-pie; then
+ _CFLAGS+=( -no-pie )
+fi
_LDFLAGS=( "-Wl,--gc-sections" -flto )
The -no-pie
flag is illegal if gcc wasn't compiled with --enable-default-pie
; in this case omitting it has the same effect.
With this change, it builds perfectly on CentOS 7. (For example in a centos:7
Dockerfile, use yum install -y gcc make autoconf
and run build.sh
.)
Adding @meermanr's patch above, it also builds in an ubuntu:20.04
container. In theory, it should build in a standard GitHub Actions runner.
I applied some of the suggested patches and bumped the versions. Also smoke tested with gcc-11 on aarch64 and x86_64.
Thanks for posting this! I had to modify line 86 to avoid an error from autoconf about not being able to find
curses.h
I also changed the TASK setting to detect the number of processors: