#!/bin/sh ## ## Installs package dependencies and builds the application. ## # Don't exit if some command fails. set +e # Disable file globbing. set -f # Boolean variables are true if non-empty and false otherwise. # Command to install packages. PKGCMD= # Args to pass to $PKGCMD. PKGARGS= # Required packages. PACKAGES= # Whether package installation requires root permissions. PKG_INSTALL_AS_ROOT=true # Whether to skip package installation altogether. PKG_INSTALL_SKIP= # Whether to force package installation, even if it does not seem # necessary. PKG_INSTALL_FORCE= # Only test if the OS is handled by this script. DRY_RUN= # If and where to install the program. INSTALL_DIR= # Whether we can install packages. OS_IS_HANDLED=true # Which OSs installer to use OS= ## +-----------------------------------------------------------+ ## * Utility Functions ## +-----------------------------------------------------------+ usage() { cat <()$\`"'\'' ]/\\&/g') if [ -z "$quoted" ]; then quoted=$qarg else quoted="$quoted $qarg" fi done printf "%s" "$quoted" } # Attempt to exec $@ as root. exec_privileged() { if [ -z "$1" ]; then echo "internal error: command is empty" exit 2 fi if [ -w / ]; then "$@" elif which sudo >/dev/null 2>&1; then sudo -- "$@" retval=$? sudo -k return $retval elif which su >/dev/null 2>&1; then su -c "$(quote "$@")" else echo "No such program: sudo or su" exit 1 fi } # Test if $1 is in PATH or exit with a failure status. assert_program() { if ! which "$1" >/dev/null 2>&1; then echo "No such program: $1" exit 1 fi } # Source filename $1 and echo variable $2. source_var() { if ! [ -f "$1" ] || ! [ -r "$1" ] || [ -z "$2" ]; then return 1 fi # shellcheck source=/dev/null . "$1" eval "printf '%s\n' \$$2" return 0 } exit_success() { echo "===========================" echo " Build succeeded. :O) " echo "===========================" exit 0 } exit_fail() { echo "===========================" echo " Build failed. ;o( " echo "===========================" if [ -z "$PKG_INSTALL_FORCE" ]; then echo "Note: maybe try the '-d' option." fi exit 1 } # Return 0, if all required packages seem to be installed. have_packages_installed() { { which pkg-config || return 1 if ! [ -f configure ];then which autoreconf || return 1 which automake || return 1 fi for lib in libpng glib-2.0 poppler poppler-glib zlib; do pkg-config --exists $lib || return 1 done which make || return 1 which gcc || which cc || return 1 which g++ || which c++ || return 1 cc $(pkg-config --cflags poppler) -o /dev/null -E - 2>/dev/null < EOF [ $? -eq 0 ] || return 1 return 0 } >/dev/null 2>&1 } handle_options() { while [ $# -gt 0 ]; do case $1 in --help) usage 0;; -n) DRY_RUN=true;; -d) PKG_INSTALL_FORCE=true ;; -D) PKG_INSTALL_SKIP=true ;; -i) shift [ $# -gt 0 ] || usage 1 if [ "${1%%/}" != "${PWD%%/}" ]; then INSTALL_DIR=$1 fi ;; --os) shift [ $# -gt 0 ] || usage 1 OS="$1" ;; *) usage 1 ;; esac shift done if [ -n "$PKG_INSTALL_SKIP" ] && [ -n "$PKG_INSTALL_FORCE" ]; then usage 1 fi } ## +-----------------------------------------------------------+ ## * OS Functions ## +-----------------------------------------------------------+ # Archlinux os_arch() { if ! [ -e "/etc/arch-release" ]; then return 1; fi PKGCMD=pacman PKGARGS="-S --needed" PACKAGES="base-devel libpng zlib poppler-glib" return 0; } # CentOS os_centos() { if ! [ -e "/etc/centos-release" ]; then return 1 fi PKGCMD=yum if yum help install-n >/dev/null 2>&1; then PKGARGS=install-n else PKGARGS=install fi PACKAGES="autoconf automake gcc gcc-c++ libpng-devel make pkgconfig poppler-devel poppler-glib-devel zlib-devel" return 0 } # FreeBSD os_freebsd() { if ! which uname >/dev/null 2>&1 || [ "$(uname -s)" != "FreeBSD" ]; then return 1 fi PKGCMD=pkg PKGARGS=install PACKAGES="autotools poppler-glib png pkgconf" return 0 } # OpenBSD os_openbsd() { if ! which uname >/dev/null 2>&1 || [ "$(uname -s)" != "OpenBSD" ]; then return 1 fi PKGCMD=pkg_add PKGARGS="-uU" PACKAGES="autoconf-2.69p2 automake-1.15.1 poppler poppler-utils png" export AUTOCONF_VERSION=2.69 export AUTOMAKE_VERSION=1.15 if whereis clang++ ;then export CXX=clang++ elif whereis eg++ ;then export CXX=eg++ else export CXX=eg++ PACKAGES="${PACKAGES} g++" fi export CXXFLAGS="-std=c++11 -I/usr/local/include/poppler -I/usr/local/include" return 0 } # Fedora os_fedora() { if ! [ -e "/etc/fedora-release" ]; then return 1 fi PKGCMD=dnf PKGARGS=install PACKAGES="autoconf automake gcc gcc-c++ libpng-devel make poppler-devel poppler-glib-devel zlib-devel" VERSION=$(source_var /etc/os-release VERSION_ID) if [ -n "$VERSION" ] && [ "$VERSION" -ge 26 ]; then PACKAGES="$PACKAGES pkgconf" else PACKAGES="$PACKAGES pkgconfig" fi return 0 } # Debian/Ubuntu os_debian() { if ! [ -e "/etc/debian_version" ]; then return 1 fi PACKAGES="autoconf automake g++ gcc libpng-dev libpoppler-dev libpoppler-glib-dev libpoppler-private-dev libz-dev make pkg-config" PKGCMD=apt-get PKGARGS=install return 0 } # Msys2 os_msys2() { if [ -z "$MSYSTEM" ] || ! [ -r "/etc/profile" ]; then return 1 fi case $MSYSTEM in MINGW64) PACKAGES="base-devel mingw-w64-x86_64-libpng mingw-w64-x86_64-poppler mingw-w64-x86_64-toolchain mingw-w64-x86_64-zlib" ;; MINGW32) PACKAGES="base-devel mingw-w64-i686-libpng mingw-w64-i686-poppler mingw-w64-i686-toolchain mingw-w64-i686-zlib" ;; MSYS) case $(uname -m) in x86_64) MSYSTEM=MINGW64 ;; *) MSYSTEM=MINGW32 ;; esac export MSYSTEM # shellcheck source=/dev/null . /etc/profile eval "exec $(quote "$0" "$@")" ;; *) echo "Unrecognized MSYSTEM value: $MSYSTEM" exit 1 ;; esac PKGCMD=pacman PKGARGS="-S --needed" PKG_INSTALL_AS_ROOT= return 0 } # MacOS os_macos() { if ! which uname >/dev/null 2>&1 || [ "$(uname -s)" != "Darwin" ]; then return 1 elif which brew >/dev/null 2>&1; then PKGCMD=brew PKGARGS=install PACKAGES="pkg-config poppler automake" PKG_INSTALL_AS_ROOT= # homebrew install libffi as keg-only, meaning we need to set # PKG_CONFIG_PATH manually so configure can find it export PKG_CONFIG_PATH="$(brew --prefix libffi)/lib/pkgconfig/" elif which port >/dev/null 2>&1; then PKGCMD=port PKGARGS=install PACKAGES="pkgconfig poppler automake libpng" else return 1 fi return 0 } # NixOS os_nixos() { # Already in the nix-shell. if [ -n "$AUTOBUILD_NIX_SHELL" ]; then return 0 fi if ! which nix-shell >/dev/null 2>&1; then return 1 fi if [ -n "$DRY_RUN" ]; then return 0 fi command="AUTOBUILD_NIX_SHELL=true" command="$command;export AUTOBUILD_NIX_SHELL" command="$command;$(quote "$0" "$@")" exec nix-shell --pure --command "$command" \ -p gcc gnumake automake autoconf pkgconfig libpng zlib poppler } # Gentoo os_gentoo() { if ! [ -e "/etc/gentoo-release" ]; then return 1 fi PKGCMD=emerge PKGARGS=--noreplace PACKAGES="app-text/poppler dev-util/pkgconfig media-libs/libpng sys-devel/autoconf sys-devel/automake sys-devel/gcc sys-devel/make sys-libs/zlib" return 0 } # By Parameter --os os_argument() { [ -z "$OS" ] && return 1 case $OS in macos) os_macos "$@";; freebsd) os_freebsd "$@";; arch) os_arch "$@";; centos) os_centos "$@";; openbsd) os_openbsd "$@";; fedora) os_fedora "$@";; debian) os_debian "$@";; gentoo) os_gentoo "$@";; msys2) os_msys2 "$@";; nixos) os_nixos "$@";; *) echo "Invalid --os argument: $OS" exit 1 esac || { echo "Unable to install on this system as $OS" exit 1 } } ## +-----------------------------------------------------------+ ## * Figure out were we are, install deps and build the program ## +-----------------------------------------------------------+ handle_options "$@" os_argument "$@" || \ os_macos "$@" || \ os_freebsd "$@" || \ os_arch "$@" || \ os_centos "$@" || \ os_openbsd "$@" || \ os_fedora "$@" || \ os_debian "$@" || \ os_gentoo "$@" || \ os_msys2 "$@" || \ os_nixos "$@" || \ { OS_IS_HANDLED= if [ -z "$DRY_RUN" ]; then echo "Failed to recognize this system, trying to continue." fi } if [ -n "$DRY_RUN" ]; then [ -n "$OS_IS_HANDLED" ] exit $? fi if [ -n "$PKGCMD" ];then echo "---------------------------" echo " Installing packages " echo "---------------------------" if [ -n "$PKG_INSTALL_SKIP" ]; then echo "Skipping package installation (as requested)" elif [ -z "$PKG_INSTALL_FORCE" ] && have_packages_installed; then echo "Skipping package installation (already installed)" else assert_program "$PKGCMD" echo "$PKGCMD $PKGARGS $PACKAGES" if [ -n "$PKG_INSTALL_AS_ROOT" ]; then exec_privileged $PKGCMD $PKGARGS $PACKAGES else $PKGCMD $PKGARGS $PACKAGES fi fi echo fi echo "---------------------------" echo " Configuring and compiling " echo "---------------------------" # Try to be in the correct directory. if which dirname >/dev/null 2>&1; then cd "$(dirname "$0")" || { echo "Failed to change into the source directory" exit 1 } fi # Create the configure script. if ! [ -f ./configure ]; then assert_program autoreconf echo "autoreconf -i" autoreconf -i [ -f ./configure ] || exit_fail fi # Build the program. if [ -n "$INSTALL_DIR" ]; then prefix=--bindir=$INSTALL_DIR fi echo "./configure -q $prefix && make -s" eval "./configure -q $(quote "$prefix") && make -s || exit_fail" echo if [ -n "$INSTALL_DIR" ]; then echo "---------------------------" echo " Installing " echo "---------------------------" echo make -s install if mkdir -p -- "$INSTALL_DIR" && [ -w "$INSTALL_DIR" ]; then make install || exit_fail else exec_privileged make install || exit_fail fi # Copy dynamic libraries on windows. if [ -f epdfinfo.exe ]; then assert_program awk assert_program ldd for dll in $(ldd epdfinfo.exe | awk '/\/mingw/ {print $3}'); do cp -u "$dll" "$INSTALL_DIR" done fi echo fi exit_success # Local Variables: # compile-command: "shellcheck autobuild" # End: