You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
#!/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
export LC_ALL=C
if [ -z "${ZSH_VERSION-}" ] && command -v zsh >/dev/null 2>&1; then # Avoid bash 3.*. case "${BASH_VERSION-}" in [0-3].*) exec zsh "$0" "$@";; esac fi
# Avoid ksh: https://github.com/romkatv/gitstatus/issues/282. if [ -n "${KSH_VERSION-}" ]; then if [ -z "${ZSH_VERSION-}" ] && command -v zsh >/dev/null 2>&1; then exec zsh "$0" "$@" elif [ -z "${BASH_VERSION-}" ] && command -v bash >/dev/null 2>&1 && bash_version="$(bash --version 2>&1)"; then case "$bash_version" in *version\ [4-9]*|*version\ [1-9][0-9]*) exec bash "$0" "$@";; esac fi fi
usage="$(command 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` (or `-mcpu` for ppc64le) 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 do not already exist in ./deps; dependencies are described in ./build.info END )"
build="$(command cat <<\END outdir="$(command pwd)"
if command -v mktemp >/dev/null 2>&1; then workdir="$(command mktemp -d "${TMPDIR:-/tmp}"/gitstatus-build.XXXXXXXXXX)" else workdir="${TMPDIR:-/tmp}/gitstatus-build.tmp.$$" command mkdir -- "$workdir" fi
cd -- "$workdir" workdir="$(command pwd)"
narg() { echo $#; }
if [ "$(narg $workdir)" != 1 -o -z "${workdir##*:*}" -o -z "${workdir##*=*}" ]; then >&2 echo "[error] cannot build in this directory: $workdir" exit 1 fi
appname=gitstatusd libgit2_tmp="$outdir"/deps/"$appname".libgit2.tmp
cleanup() { trap - INT QUIT TERM ILL PIPE cd / if ! command rm -rf -- "$workdir" "$outdir"/usrbin/"$appname".tmp "$libgit2_tmp"; then command sleep 5 command rm -rf -- "$workdir" "$outdir"/usrbin/"$appname".tmp "$libgit2_tmp" fi } trap cleanup INT QUIT TERM ILL PIPE
if [ -n "$gitstatus_install_tools" ]; then case "$gitstatus_kernel" in linux) if command -v apk >/dev/null 2>&1; then command apk update command apk add binutils cmake gcc g++ git make musl-dev perl-utils elif command -v apt-get >/dev/null 2>&1; then apt-get update apt-get install -y binutils cmake gcc g++ make wget else >&2 echo "[error] -s is not supported on this system" exit 1 fi ;; freebsd) command pkg install -y cmake gmake binutils git perl5 wget ;; openbsd) command pkg_add cmake gmake gcc g++ git wget ;; netbsd) command 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 port >/dev/null 2>&1; then sudo port -N install libiconv cmake wget elif command -v brew >/dev/null 2>&1; then for formula in libiconv cmake git wget; do if command brew ls --version "$formula" &>/dev/null; then command brew upgrade "$formula" else command brew install "$formula" fi done else >&2 echo "[error] please install MacPorts or Homebrew and retry" exit 1 fi ;; msys*|mingw*) command pacman -Syu --noconfirm command pacman -S --needed --noconfirm binutils cmake gcc git make perl ;; *) >&2 echo "[internal error] unhandled kernel: $gitstatus_kernel" exit 1 ;; esac fi
cpus="$(command getconf _NPROCESSORS_ONLN 2>/dev/null)" || cpus="$(command sysctl -n hw.ncpu 2>/dev/null)" || cpus=8
case "$gitstatus_cpu" in powerpc64le) archflag="-mcpu";; *) archflag="-march";; esac
cflags="$archflag=$gitstatus_cpu -fno-plt -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fpie" ldflags= static_pie=
if [ -z "${CC-}" ]; then case "$gitstatus_kernel" in freebsd) export CC=clang;; *) export CC=cc;; esac fi
printf 'int main() {}\n' >"$workdir"/cc-test.c if 2>/dev/null "$CC" \ -ffile-prefix-map=x=y \ -Werror \ -c "$workdir"/cc-test.c \ -o "$workdir"/cc-test.o; then cflags="$cflags -ffile-prefix-map=$workdir/=" fi
command rm -f -- "$workdir"/cc-test "$workdir"/cc-test.o if 2>/dev/null "$CC" \ -fstack-clash-protection -fcf-protection \ -Werror \ -c "$workdir"/cc-test.c \ -o "$workdir"/cc-test.o; then cflags="$cflags -fstack-clash-protection -fcf-protection" fi
command rm -f -- "$workdir"/cc-test "$workdir"/cc-test.o if 2>/dev/null "$CC" \ -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now \ -Werror \ "$workdir"/cc-test.c \ -o "$workdir"/cc-test; then ldflags="$ldflags -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now" fi
command rm -f -- "$workdir"/cc-test "$workdir"/cc-test.o if 2>/dev/null "$CC" \ -fpie -static-pie \ -Werror \ "$workdir"/cc-test.c \ -o "$workdir"/cc-test; then static_pie='-static-pie' fi
if [ "$gitstatus_cpu" = x86-64 ]; then cflags="$cflags -mtune=generic" fi
libgit2_cmake_flags= libgit2_cflags="${CFLAGS-} $cflags -O3 -DNDEBUG"
gitstatus_cxx=g++ gitstatus_cxxflags="${CXXFLAGS-} $cflags -I${workdir}/libgit2/include -DGITSTATUS_ZERO_NSEC -D_GNU_SOURCE -D_GLIBCXX_ASSERTIONS" gitstatus_ldflags="${LDFLAGS-} $ldflags -L${workdir}/libgit2/build" gitstatus_ldlibs= gitstatus_make=make
case "$gitstatus_kernel" in linux) gitstatus_ldflags="$gitstatus_ldflags ${static_pie:--static}" libgit2_cmake_flags="$libgit2_cmake_flags -DENABLE_REPRODUCIBLE_BUILDS=ON" ;; freebsd) gitstatus_cxx=clang++ gitstatus_make=gmake gitstatus_ldflags="$gitstatus_ldflags ${static_pie:--static}" libgit2_cmake_flags="$libgit2_cmake_flags -DENABLE_REPRODUCIBLE_BUILDS=ON" ;; openbsd) gitstatus_cxx=eg++ gitstatus_make=gmake gitstatus_ldflags="$gitstatus_ldflags ${static_pie:--static}" libgit2_cmake_flags="$libgit2_cmake_flags -DENABLE_REPRODUCIBLE_BUILDS=ON" ;; netbsd) gitstatus_make=gmake gitstatus_ldflags="$gitstatus_ldflags ${static_pie:--static}" libgit2_cmake_flags="$libgit2_cmake_flags -DENABLE_REPRODUCIBLE_BUILDS=ON" ;; darwin) command mkdir -- "$workdir"/lib if [ -e /opt/local/lib/libiconv.a ]; then command ln -s -- /opt/local/lib/libiconv.a "$workdir"/lib libgit2_cflags="$libgit2_cflags -I/opt/local/include" gitstatus_cxxflags="$gitstatus_cxxflags -I/opt/local/include" else brew_prefix="$(command brew --prefix)" command ln -s -- "$brew_prefix"/opt/libiconv/lib/libiconv.a "$workdir"/lib libgit2_cflags="$libgit2_cflags -I"$brew_prefix"/opt/libiconv/include" gitstatus_cxxflags="$gitstatus_cxxflags -I"$brew_prefix"/opt/libiconv/include" fi libgit2_cmake_flags="$libgit2_cmake_flags -DUSE_ICONV=ON" gitstatus_ldlibs="$gitstatus_ldlibs -liconv" gitstatus_ldflags="$gitstatus_ldflags -L${workdir}/lib" libgit2_cmake_flags="$libgit2_cmake_flags -DENABLE_REPRODUCIBLE_BUILDS=OFF" ;; msys*|mingw*) gitstatus_ldflags="$gitstatus_ldflags ${static_pie:--static}" libgit2_cmake_flags="$libgit2_cmake_flags -DENABLE_REPRODUCIBLE_BUILDS=ON" ;; cygwin*) gitstatus_ldflags="$gitstatus_ldflags ${static_pie:--static}" libgit2_cmake_flags="$libgit2_cmake_flags -DENABLE_REPRODUCIBLE_BUILDS=ON" ;; *) >&2 echo "[internal error] unhandled kernel: $gitstatus_kernel" exit 1 ;; esac
for cmd in cat cmake git ld ln mkdir rm strip tar "$gitstatus_make"; 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 if [ -z "${libgit2_sha256:-}" ]; then >&2 echo "[internal error] libgit2_sha256 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 if ! command -v wget >/dev/null 2>&1; then if [ -n "$gitstatus_install_tools" ]; then >&2 echo "[internal error] wget not found" exit 1 else >&2 echo "[error] command not found: wget" exit 1 fi fi libgit2_url=https://github.com/romkatv/libgit2/archive/"$libgit2_version".tar.gz if ! >"$libgit2_tmp" command wget --no-config -qO- -- "$libgit2_url" && ! >"$libgit2_tmp" command wget -qO- -- "$libgit2_url"; then set -x >&2 command which wget >&2 command ls -lAd -- "$(command which wget)" >&2 command ls -lAd -- "$outdir" >&2 command ls -lA -- "$outdir" >&2 command ls -lAd -- "$outdir"/deps >&2 command ls -lA -- "$outdir"/deps set +x exit 1 fi command mv -f -- "$libgit2_tmp" "$libgit2_tarball" else >&2 echo "[error] file not found: deps/libgit2-"$libgit2_version".tar.gz" exit 1 fi fi
libgit2_actual_sha256= if command -v shasum >/dev/null 2>/dev/null; then libgit2_actual_sha256="$(command shasum -b -a 256 -- "$libgit2_tarball")" libgit2_actual_sha256="${libgit2_actual_sha256%% *}" elif command -v sha256sum >/dev/null 2>/dev/null; then libgit2_actual_sha256="$(command sha256sum -b -- "$libgit2_tarball")" libgit2_actual_sha256="${libgit2_actual_sha256%% *}" elif command -v sha256 >/dev/null 2>/dev/null; then libgit2_actual_sha256="$(command sha256 -- "$libgit2_tarball" </dev/null)" # Ignore sha256 output if it's from hashalot. It's incompatible. if [ ${#libgit2_actual_sha256} -lt 64 ]; then libgit2_actual_sha256= else libgit2_actual_sha256="${libgit2_actual_sha256##* }" fi fi
if [ -z "$libgit2_actual_sha256" ]; then >&2 echo "[error] command not found: shasum or sha256sum" exit 1 fi
if [ "$libgit2_actual_sha256" != "$libgit2_sha256" ]; then >&2 echo "[error] sha256 mismatch" >&2 echo "" >&2 echo " file : deps/libgit2-$libgit2_version.tar.gz" >&2 echo " expected: $libgit2_sha256" >&2 echo " actual : $libgit2_actual_sha256" exit 1 fi
cd -- "$workdir" command tar -xzf "$libgit2_tarball" command mv -- libgit2-"$libgit2_version" libgit2 command mkdir libgit2/build cd libgit2/build
CFLAGS="$libgit2_cflags" command cmake \ -DCMAKE_BUILD_TYPE=None \ -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 \ $libgit2_cmake_flags \ .. command make -j "$cpus" VERBOSE=1
APPNAME="$appname".tmp \ OBJDIR="$workdir"/gitstatus \ CXX="${CXX:-$gitstatus_cxx}" \ CXXFLAGS="$gitstatus_cxxflags" \ LDFLAGS="$gitstatus_ldflags" \ LDLIBS="$gitstatus_ldlibs" \ command "$gitstatus_make" -C "$outdir" -j "$cpus"
app="$outdir"/usrbin/"$appname"
command strip "$app".tmp
command mkdir -- "$workdir"/repo printf '[init]\n defaultBranch = master\n' >"$workdir"/.gitconfig ( cd -- "$workdir"/repo GIT_CONFIG_NOSYSTEM=1 HOME="$workdir" command git init GIT_CONFIG_NOSYSTEM=1 HOME="$workdir" command git config user.name "Your Name" GIT_CONFIG_NOSYSTEM=1 HOME="$workdir" command git config user.email "[email protected]" GIT_CONFIG_NOSYSTEM=1 HOME="$workdir" command git commit \ --allow-empty --allow-empty-message --no-gpg-sign -m '' )
resp="$(printf "hello\037$workdir/repo\036" | "$app".tmp)" case "$resp" in hello*1*/repo*master*);; *) >&2 echo 'error: invalid gitstatusd response for a git repo' exit 1 ;; esac
resp="$(printf 'hello\037\036' | "$app".tmp)" case "$resp" in hello*0*);; *) >&2 echo 'error: invalid gitstatusd response for a non-repo' exit 1 ;; esac
command mv -f -- "$app".tmp "$app"
cleanup
command 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 armel) gitstatus_cpu=armv5;; armv6l|armhf) gitstatus_cpu=armv6;; armv7l) gitstatus_cpu=armv7;; arm64|aarch64) gitstatus_cpu=armv8-a;; ppc64le) gitstatus_cpu=powerpc64le;; riscv64) gitstatus_cpu=rv64imafdc;; loongarch64) gitstatus_cpu=loongarch64;; x86_64|amd64) gitstatus_cpu=x86-64;; x86) gitstatus_cpu=i586;; s390x) gitstatus_cpu=z900;; 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;; x86|i386|i586|i686) docker_image=i386/alpine:3.11.6;; armv6l|armhf) docker_image=arm32v6/alpine:3.11.6;; armv7l) docker_image=arm32v7/alpine:3.11.6;; aarch64) docker_image=arm64v8/alpine:3.11.6;; ppc64le) docker_image=ppc64le/alpine:3.11.6;; s390x) docker_image=s390x/alpine:3.11.6;; *) >&2 echo '[error] unable to infer docker image' >&2 echo 'Please specify explicitly with `-i IMAGE`.' exit 1 ;; esac fi fi ;; freebsd|openbsd|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 docker_cmd="$docker_cmd" \ -e docker_image="$docker_image" \ -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
|