diff options
author | romkatv <roman.perepelitsa@gmail.com> | 2020-05-10 16:58:05 +0300 |
---|---|---|
committer | romkatv <roman.perepelitsa@gmail.com> | 2020-05-10 16:58:05 +0300 |
commit | 1531d6e5439daae01627b2645684876b75eaf5eb (patch) | |
tree | 05ed820f16dbb04be4b4b8ec3055f93431518773 /build |
Squashed 'gitstatus/' content from commit 6b9ba17
git-subtree-dir: gitstatus
git-subtree-split: 6b9ba179c6655286c4c399e7926d5098dd6bd706
Diffstat (limited to 'build')
-rwxr-xr-x | build | 442 |
1 files changed, 442 insertions, 0 deletions
@@ -0,0 +1,442 @@ +#!/bin/sh +# +# Type `build -h` for help and see https://github.com/romkatv/gitstatus +# for full documentation. + +set -ue + +if [ -n "${ZSH_VERSION:-}" ]; then + emulate sh -o err_exit -o no_unset +fi + +usage="$(cat <<\END +Usage: build [-m ARCH] [-c CPU] [-d CMD] [-i IMAGE] [-s] [-w] + +Options: + + -m ARCH `uname -m` from the target machine; defaults to `uname -m` + from the local machine + -c CPU generate machine instructions for CPU of this type; this + value gets passed as `-march` to gcc; inferred from ARCH + if not set explicitly + -d CMD build in a Docker container and use CMD as the `docker` + command; e.g., `-d docker` or `-d podman` + -i IMAGE build in this Docker image; inferred from ARCH if not set + explicitly + -s install whatever software is necessary for build to + succeed; on some operating systems this option is not + supported; on others it can have partial effect + -w automatically download tarballs for dependencies if they + don't already exist in ./deps; dependencies are described + in ./build.info +END +)" + +build="$(cat <<\END +outdir="$(pwd)" + +if command -v mktemp >/dev/null 2>&1; then + workdir="$(mktemp -d "${TMPDIR:-/tmp}"/gitstatus-build.XXXXXXXXXX)" +else + workdir="${TMPDIR:-/tmp}/gitstatus-build.tmp.$$" + mkdir -- "$workdir" +fi + +cd -- "$workdir" +workdir="$(pwd)" + +narg() { echo $#; } + +if [ "$(narg $workdir)" != 1 -o -z "${workdir##*:*}" ]; then + >&2 echo "[error] cannot build in this directory: $workdir" + exit 1 +fi + +appname=gitstatusd-"$gitstatus_kernel"-"$gitstatus_arch" +libgit2_tmp="$outdir"/deps/"$appname".libgit2.tmp + +cleanup() { + cd / + rm -rf -- "$workdir" "$outdir"/usrbin/"$appname".tmp "$libgit2_tmp" + trap - INT QUIT TERM EXIT ILL PIPE +} +trap cleanup INT QUIT TERM EXIT ILL PIPE + +if [ -n "$gitstatus_install_tools" ]; then + case "$gitstatus_kernel" in + linux) + apk update + apk add binutils cmake gcc g++ git make musl-dev + ;; + freebsd) + pkg install -y cmake gmake binutils gcc git + ;; + netbsd) + pkgin -y install cmake gmake binutils git + ;; + darwin) + if ! command -v make >/dev/null 2>&1 || ! command -v gcc >/dev/null 2>&1; then + >&2 echo "[error] please run 'xcode-select --install' and retry" + exit 1 + fi + if ! command -v brew >/dev/null 2>&1; then + >&2 echo "[error] please install homebrew from https://brew.sh/ and retry" + exit 1 + fi + for formula in libiconv cmake git wget; do + if brew list "$formula" &>/dev/null; then + brew upgrade "$formula" + else + brew install "$formula" + fi + done + ;; + msys*|mingw*) + pacman -Syu --noconfirm + pacman -S --needed --noconfirm binutils cmake gcc git make + ;; + *) + >&2 echo "[internal error] unhandled kernel: $gitstatus_kernel" + exit 1 + ;; + esac +fi + +cpus="$(getconf _NPROCESSORS_ONLN)" || cpus="$(sysctl -n hw.ncpu)" || cpus=8 + +libgit2_cmake_flags= +libgit2_cflags="-march=$gitstatus_cpu" + +gitstatus_cxx=g++ +gitstatus_cxxflags="-I${workdir}/libgit2/include -DGITSTATUS_ZERO_NSEC -D_GNU_SOURCE -march=$gitstatus_cpu" +gitstatus_ldflags="-L${workdir}/libgit2/build" +gitstatus_ldlibs= +gitstatus_make=make + +case "$gitstatus_kernel" in + linux) + gitstatus_ldflags="$gitstatus_ldflags -static" + ;; + freebsd) + gitstatus_make=gmake + gitstatus_ldflags="$gitstatus_ldflags -static" + ;; + netbsd) + gitstatus_make=gmake + gitstatus_ldflags="$gitstatus_ldflags -static" + ;; + darwin) + mkdir -- "$workdir"/lib + ln -s -- /usr/local/opt/libiconv/lib/libiconv.a "$workdir"/lib + libgit2_cmake_flags="$libgit2_cmake_flags -DUSE_ICONV=ON" + libgit2_cflags="$libgit2_cflags -I/usr/local/opt/libiconv/include" + gitstatus_cxxflags="$gitstatus_cxxflags -I/usr/local/opt/libiconv/include" + gitstatus_ldlibs="$gitstatus_ldlibs -liconv" + gitstatus_ldflags="$gitstatus_ldflags -L${workdir}/lib" + ;; + msys*|mingw*) + gitstatus_ldflags="$gitstatus_ldflags -static" + ;; + cygwin*) + gitstatus_ldflags="$gitstatus_ldflags -static" + ;; + *) + >&2 echo "[internal error] unhandled kernel: $gitstatus_kernel" + exit 1 + ;; +esac + +for cmd in cmake gcc g++ git ld "$gitstatus_make" wget; do + if ! command -v "$cmd" >/dev/null 2>&1; then + if [ -n "$gitstatus_install_tools" ]; then + >&2 echo "[internal error] $cmd not found" + exit 1 + else + >&2 echo "[error] command not found: $cmd" + exit 1 + fi + fi +done + +. "$outdir"/build.info +if [ -z "$libgit2_version" ]; then + >&2 echo "[internal error] libgit2_version not set" + exit 1 +fi +libgit2_tarball="$outdir"/deps/libgit2-"$libgit2_version".tar.gz +if [ ! -e "$libgit2_tarball" ]; then + if [ -n "$gitstatus_download_deps" ]; then + libgit2_url=https://github.com/romkatv/libgit2/archive/"$libgit2_version".tar.gz + wget -O "$libgit2_tmp" -- "$libgit2_url" + mv -f -- "$libgit2_tmp" "$libgit2_tarball" + else + >&2 echo "[error] file not found: deps/libgit2-"$libgit2_version".tar.gz" + exit 1 + fi +fi + +cd -- "$workdir" +tar -xzf "$libgit2_tarball" +mv -- libgit2-"$libgit2_version" libgit2 +mkdir libgit2/build +cd libgit2/build + +CFLAGS="$libgit2_cflags" cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DZERO_NSEC=ON \ + -DTHREADSAFE=ON \ + -DUSE_BUNDLED_ZLIB=ON \ + -DREGEX_BACKEND=builtin \ + -DUSE_HTTP_PARSER=builtin \ + -DUSE_SSH=OFF \ + -DUSE_HTTPS=OFF \ + -DBUILD_CLAR=OFF \ + -DUSE_GSSAPI=OFF \ + -DUSE_NTLMCLIENT=OFF \ + -DBUILD_SHARED_LIBS=OFF \ + -DENABLE_REPRODUCIBLE_BUILDS=OFF \ + $libgit2_cmake_flags \ + .. +make -j "$cpus" VERBOSE=1 + +APPNAME="$appname".tmp \ + OBJDIR="$workdir"/gitstatus \ + CXX="$gitstatus_cxx" \ + CXXFLAGS="$gitstatus_cxxflags" \ + LDFLAGS="$gitstatus_ldflags" \ + LDLIBS="$gitstatus_ldlibs" \ + "$gitstatus_make" -C "$outdir" -j "$cpus" + +app="$outdir"/usrbin/"$appname" + +strip "$app".tmp + +mkdir -- "$workdir"/repo +git -C "$workdir"/repo init -- +git -C "$workdir"/repo config user.email "you@example.com" +git -C "$workdir"/repo commit --allow-empty --allow-empty-message -m '' + +resp="$(printf "hello\037$workdir/repo\036" | "$app".tmp)" +[ -n "$resp" -a -z "${resp##hello*1*$workdir/repo*master*}" ] + +resp="$(printf 'hello\037\036' | "$app".tmp)" +[ -n "$resp" -a -z "${resp##hello*0*}" ] + +mv -f -- "$app".tmp "$app" + +cleanup + +cat >&2 <<-END + ------------------------------------------------- + SUCCESS: created usrbin/$appname + END +END +)" + +docker_image= +docker_cmd= + +gitstatus_arch= +gitstatus_cpu= +gitstatus_install_tools= +gitstatus_download_deps= + +while getopts ':m:c:i:d:swh' opt "$@"; do + case "$opt" in + h) + printf '%s\n' "$usage" + exit + ;; + m) + if [ -n "$gitstatus_arch" ]; then + >&2 echo "[error] duplicate option: -$opt" + exit 1 + fi + if [ -z "$OPTARG" ]; then + >&2 echo "[error] incorrect value of -$opt: $OPTARG" + exit 1 + fi + gitstatus_arch="$OPTARG" + ;; + c) + if [ -n "$gitstatus_cpu" ]; then + >&2 echo "[error] duplicate option: -$opt" + exit 1 + fi + if [ -z "$OPTARG" ]; then + >&2 echo "[error] incorrect value of -$opt: $OPTARG" + exit 1 + fi + gitstatus_cpu="$OPTARG" + ;; + i) + if [ -n "$docker_image" ]; then + >&2 echo "[error] duplicate option: -$opt" + exit 1 + fi + if [ -z "$OPTARG" ]; then + >&2 echo "[error] incorrect value of -$opt: $OPTARG" + exit 1 + fi + docker_image="$OPTARG" + ;; + d) + if [ -n "$docker_cmd" ]; then + >&2 echo "[error] duplicate option: -$opt" + exit 1 + fi + if [ -z "$OPTARG" ]; then + >&2 echo "[error] incorrect value of -$opt: $OPTARG" + exit 1 + fi + docker_cmd="$OPTARG" + ;; + s) + if [ -n "$gitstatus_install_tools" ]; then + >&2 echo "[error] duplicate option: -$opt" + exit 1 + fi + gitstatus_install_tools=1 + ;; + w) + if [ -n "$gitstatus_download_deps" ]; then + >&2 echo "[error] duplicate option: -$opt" + exit 1 + fi + gitstatus_download_deps=1 + ;; + \?) >&2 echo "[error] invalid option: -$OPTARG" ; exit 1;; + :) >&2 echo "[error] missing required argument: -$OPTARG"; exit 1;; + *) >&2 echo "[internal error] unhandled option: -$opt" ; exit 1;; + esac +done + +if [ "$OPTIND" -le $# ]; then + >&2 echo "[error] unexpected positional argument" + exit 1 +fi + +if [ -n "$docker_image" -a -z "$docker_cmd" ]; then + >&2 echo "[error] cannot use -i without -d" + exit 1 +fi + +if [ -z "$gitstatus_arch" ]; then + gitstatus_arch="$(uname -m)" + gitstatus_arch="$(printf '%s' "$gitstatus_arch" | tr '[A-Z]' '[a-z]')" +fi + +if [ -z "$gitstatus_cpu" ]; then + case "$gitstatus_arch" in + armv6l) gitstatus_cpu=armv6;; + armv7l) gitstatus_cpu=armv7;; + aarch64) gitstatus_cpu=armv8-a;; + x86_64|amd64) gitstatus_cpu=x86-64;; + i386|i586|i686) gitstatus_cpu="$gitstatus_arch";; + *) + >&2 echo '[error] unable to infer target CPU architecture' + >&2 echo 'Please specify explicitly with `-c CPU`.' + exit 1 + ;; + esac +fi + +gitstatus_kernel="$(uname -s)" +gitstatus_kernel="$(printf '%s' "$gitstatus_kernel" | tr '[A-Z]' '[a-z]')" + +case "$gitstatus_kernel" in + linux) + if [ -n "$docker_cmd" ]; then + if [ -z "${docker_cmd##*/*}" ]; then + if [ ! -x "$docker_cmd" ]; then + >&2 echo "[error] not an executable file: $docker_cmd" + exit 1 + fi + else + if ! command -v "$docker_cmd" >/dev/null 2>&1; then + >&2 echo "[error] command not found: $docker_cmd" + exit 1 + fi + fi + if [ -z "$docker_image" ]; then + case "$gitstatus_arch" in + x86_64) docker_image=alpine:3.11.6;; + i386|i586|i686) docker_image=i386/alpine:3.11.6;; + armv6l) docker_image=arm32v6/alpine:3.11.6;; + armv7l) docker_image=arm32v7/alpine:3.11.6;; + aarch64) docker_image=arm64v8/alpine:3.11.6;; + *) + >&2 echo '[error] unable to infer docker image' + >&2 echo 'Please specify explicitly with `-i IMAGE`.' + exit 1 + ;; + esac + fi + elif [ -n "$gitstatus_install_tools" ]; then + >&2 echo '[error] -s without -d is not supported on linux' + exit 1 + fi + ;; + freebsd|netbsd|darwin) + if [ -n "$docker_cmd" ]; then + >&2 echo "[error] docker (-d) is not supported on $gitstatus_kernel" + exit 1 + fi + ;; + msys_nt-*|mingw32_nt-*|mingw64_nt-*|cygwin_nt-*) + if ! printf '%s' "$gitstatus_kernel" | grep -Eqx '[^-]+-[0-9]+\.[0-9]+(-.*)?'; then + >&2 echo '[error] unsupported kernel, sorry!' + exit 1 + fi + gitstatus_kernel="$(printf '%s' "$gitstatus_kernel" | sed 's/^\([^-]*-[0-9]*\.[0-9]*\).*/\1/')" + if [ -n "$docker_cmd" ]; then + >&2 echo '[error] docker (-d) is not supported on windows' + exit 1 + fi + if [ -n "$gitstatus_install_tools" -a -z "${gitstatus_kernel##cygwin_nt-*}" ]; then + >&2 echo '[error] -s is not supported on cygwin' + exit 1 + fi + ;; + *) + >&2 echo '[error] unsupported kernel, sorry!' + exit 1 + ;; +esac + +dir="$(dirname -- "$0")" +cd -- "$dir" +dir="$(pwd)" + +>&2 echo "Building gitstatusd..." +>&2 echo "" +>&2 echo " kernel := $gitstatus_kernel" +>&2 echo " arch := $gitstatus_arch" +>&2 echo " cpu := $gitstatus_cpu" +[ -z "$docker_cmd" ] || >&2 echo " docker command := $docker_cmd" +[ -z "$docker_image" ] || >&2 echo " docker image := $docker_image" +if [ -n "$gitstatus_install_tools" ]; then + >&2 echo " install tools := yes" +else + >&2 echo " install tools := no" +fi +if [ -n "$gitstatus_download_deps" ]; then + >&2 echo " download deps := yes" +else + >&2 echo " download deps := no" +fi + +if [ -n "$docker_cmd" ]; then + "$docker_cmd" run \ + -e gitstatus_kernel="$gitstatus_kernel" \ + -e gitstatus_arch="$gitstatus_arch" \ + -e gitstatus_cpu="$gitstatus_cpu" \ + -e gitstatus_install_tools="$gitstatus_install_tools" \ + -e gitstatus_download_deps="$gitstatus_download_deps" \ + -v "$dir":/out \ + -w /out \ + --rm \ + -- "$docker_image" /bin/sh -uexc "$build" +else + eval "$build" +fi |