#!/bin/sh # Copyright (c) 2024-2024 刘富频 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. set -e # If IFS is not set, the default value will be # https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_03 unset IFS COLOR_RED='\033[0;31m' # Red COLOR_GREEN='\033[0;32m' # Green COLOR_YELLOW='\033[0;33m' # Yellow COLOR_BLUE='\033[0;94m' # Blue COLOR_PURPLE='\033[0;35m' # Purple COLOR_OFF='\033[0m' # Reset print() { printf '%b' "$*" } echo() { printf '%b\n' "$*" } note() { printf '%b\n' "${COLOR_YELLOW}🔔 $*${COLOR_OFF}" >&2 } warn() { printf '%b\n' "${COLOR_YELLOW}🔥 $*${COLOR_OFF}" >&2 } success() { printf '%b\n' "${COLOR_GREEN}[✔] $*${COLOR_OFF}" >&2 } error() { printf '%b\n' "${COLOR_RED}💔 xbuilder: $*${COLOR_OFF}" >&2 } abort() { EXIT_STATUS_CODE="$1" shift printf '%b\n' "${COLOR_RED}💔 xbuilder: $*${COLOR_OFF}" >&2 exit "$EXIT_STATUS_CODE" } run() { echo "${COLOR_PURPLE}==>${COLOR_OFF} ${COLOR_GREEN}$@${COLOR_OFF}" eval "$@" } isInteger() { case "${1#[+-]}" in (*[!0123456789]*) return 1 ;; ('') return 1 ;; (*) return 0 ;; esac } # wfetch [--uri=] [--sha256=] [-o ] [--no-buffer] # # If -o option is unspecified, the result will be written to /$(basename ). # # If is . .. ./ ../ or ends with slash(/), then it will be treated as a directory, otherwise, it will be treated as a filepath. # # If is -, then it will be treated as /dev/stdout. # # If is treated as a directory, then it will be expanded to /$(basename ) # wfetch() { unset FETCH_UTS unset FETCH_SHA unset FETCH_URL unset FETCH_URI unset FETCH_PATH unset FETCH_OUTPUT_DIR unset FETCH_OUTPUT_FILEPATH unset FETCH_OUTPUT_FILENAME unset FETCH_BUFFER_FILEPATH unset FETCH_SHA256_EXPECTED unset NOT_BUFFER [ -z "$1" ] && abort 1 "wfetch [OPTION]... , must be non-empty." if [ -z "$URL_TRANSFORM" ] ; then FETCH_URL="$1" else FETCH_URL="$("$URL_TRANSFORM" "$1")" || return 1 fi shift while [ -n "$1" ] do case $1 in --uri=*) FETCH_URI="${1#*=}" ;; --sha256=*) FETCH_SHA256_EXPECTED="${1#*=}" ;; -o) shift if [ -z "$1" ] ; then abort 1 "wfetch -o , must be non-empty." else FETCH_PATH="$1" fi ;; --no-buffer) NOT_BUFFER=1 ;; *) abort 1 "wfetch [--uri=] [--sha256=] [-o ] [-q] , unrecognized option: $1" esac shift done if [ -z "$FETCH_URI" ] ; then # remove query params FETCH_URI="${FETCH_URL%%'?'*}" FETCH_URI="https://fossies.org/linux/misc/${FETCH_URI##*/}" else if [ -n "$URL_TRANSFORM" ] ; then FETCH_URI="$("$URL_TRANSFORM" "$FETCH_URI")" || return 1 fi fi case $FETCH_PATH in -) FETCH_BUFFER_FILEPATH='-' ;; .|'') FETCH_OUTPUT_DIR='.' FETCH_OUTPUT_FILEPATH="$FETCH_OUTPUT_DIR/${FETCH_URL##*/}" ;; ..) FETCH_OUTPUT_DIR='..' FETCH_OUTPUT_FILEPATH="$FETCH_OUTPUT_DIR/${FETCH_URL##*/}" ;; */) FETCH_OUTPUT_DIR="${FETCH_PATH%/}" FETCH_OUTPUT_FILEPATH="$FETCH_OUTPUT_DIR/${FETCH_URL##*/}" ;; *) FETCH_OUTPUT_DIR="$(dirname "$FETCH_PATH")" FETCH_OUTPUT_FILEPATH="$FETCH_PATH" esac if [ -n "$FETCH_OUTPUT_FILEPATH" ] ; then if [ -f "$FETCH_OUTPUT_FILEPATH" ] ; then if [ -n "$FETCH_SHA256_EXPECTED" ] ; then if [ "$(sha256sum "$FETCH_OUTPUT_FILEPATH" | cut -d ' ' -f1)" = "$FETCH_SHA256_EXPECTED" ] ; then success "$FETCH_OUTPUT_FILEPATH already have been fetched." return 0 fi fi fi if [ "$NOT_BUFFER" = 1 ] ; then FETCH_BUFFER_FILEPATH="$FETCH_OUTPUT_FILEPATH" else FETCH_UTS="$(date +%s)" FETCH_SHA="$(printf '%s\n' "$FETCH_URL:$$:$FETCH_UTS" | sha256sum | cut -d ' ' -f1)" FETCH_BUFFER_FILEPATH="$FETCH_OUTPUT_DIR/$FETCH_SHA.tmp" fi fi for FETCH_TOOL in curl wget http lynx aria2c axel do if command -v "$FETCH_TOOL" > /dev/null ; then break else unset FETCH_TOOL fi done if [ -z "$FETCH_TOOL" ] ; then abort 1 "no fetch tool found, please install one of curl wget http lynx aria2c axel, then try again." fi if [ -n "$FETCH_OUTPUT_DIR" ] ; then if [ ! -d "$FETCH_OUTPUT_DIR" ] ; then run install -d "$FETCH_OUTPUT_DIR" || return 1 fi fi case $FETCH_TOOL in curl) CURL_OPTIONS="--fail --retry 20 --retry-delay 30 --location" if [ "$DUMP_HTTP" = 1 ] ; then CURL_OPTIONS="$CURL_OPTIONS --verbose" fi if [ -n "$SSL_CERT_FILE" ] ; then CURL_OPTIONS="$CURL_OPTIONS --cacert $SSL_CERT_FILE" fi run "curl $CURL_OPTIONS -o '$FETCH_BUFFER_FILEPATH' '$FETCH_URL'" || run "curl $CURL_OPTIONS -o '$FETCH_BUFFER_FILEPATH' '$FETCH_URI'" ;; wget) run "wget --timeout=60 -O '$FETCH_BUFFER_FILEPATH' '$FETCH_URL'" || run "wget --timeout=60 -O '$FETCH_BUFFER_FILEPATH' '$FETCH_URI'" ;; http) run "http --timeout=60 -o '$FETCH_BUFFER_FILEPATH' '$FETCH_URL'" || run "http --timeout=60 -o '$FETCH_BUFFER_FILEPATH' '$FETCH_URI'" ;; lynx) run "lynx -source '$FETCH_URL' > '$FETCH_BUFFER_FILEPATH'" || run "lynx -source '$FETCH_URI' > '$FETCH_BUFFER_FILEPATH'" ;; aria2c) run "aria2c -d '$FETCH_OUTPUT_DIR' -o '$FETCH_OUTPUT_FILENAME' '$FETCH_URL'" || run "aria2c -d '$FETCH_OUTPUT_DIR' -o '$FETCH_OUTPUT_FILENAME' '$FETCH_URI'" ;; axel) run "axel -o '$FETCH_BUFFER_FILEPATH' '$FETCH_URL'" || run "axel -o '$FETCH_BUFFER_FILEPATH' '$FETCH_URI'" ;; *) abort 1 "wfetch() unimplementation: $FETCH_TOOL" ;; esac [ $? -eq 0 ] || return 1 if [ -n "$FETCH_OUTPUT_FILEPATH" ] ; then if [ -n "$FETCH_SHA256_EXPECTED" ] ; then FETCH_SHA256_ACTUAL="$(sha256sum "$FETCH_BUFFER_FILEPATH" | cut -d ' ' -f1)" if [ "$FETCH_SHA256_ACTUAL" != "$FETCH_SHA256_EXPECTED" ] ; then abort 1 "sha256sum mismatch.\n expect : $FETCH_SHA256_EXPECTED\n actual : $FETCH_SHA256_ACTUAL\n" fi fi if [ "$NOT_BUFFER" != 1 ] ; then run mv "$FETCH_BUFFER_FILEPATH" "$FETCH_OUTPUT_FILEPATH" fi fi } filetype_from_url() { # remove query params URL="${1%%'?'*}" FNAME="${URL##*/}" case $FNAME in *.tar.gz|*.tgz) printf '%s\n' '.tgz' ;; *.tar.lz|*.tlz) printf '%s\n' '.tlz' ;; *.tar.xz|*.txz) printf '%s\n' '.txz' ;; *.tar.bz2|*.tbz2) printf '%s\n' '.tbz2' ;; *.*)printf '%s\n' ".${FNAME##*.}" esac } inspect_install_arguments() { unset PROFILE unset LOG_LEVEL unset BUILD_NJOBS unset ENABLE_LTO unset ENABLE_STRIP unset ENABLE_CCACHE unset REQUEST_TO_KEEP_SESSION_DIR unset REQUEST_TO_UPGRADE_IF_POSSIBLE unset REQUEST_TO_EXPORT_COMPILE_COMMANDS_JSON unset SPECIFIED_PACKAGE_LIST unset SESSION_DIR unset DOWNLOAD_DIR unset PACKAGE_INSTALL_ROOT unset DUMP_ENV unset DUMP_HTTP unset DUMP_UPPM unset VERBOSE_GMAKE unset DEBUG_CC unset DEBUG_LD unset DEBUG_GO unset DEBUG_CARGO unset DEBUG_GMAKE unset DEBUG_XMAKE unset DEBUG_PKG_CONFIG while [ -n "$1" ] do case $1 in -q) LOG_LEVEL=0 ;; -v) LOG_LEVEL=2 DUMP_ENV=1 DUMP_HTTP=1 DUMP_UPPM=1 VERBOSE_GMAKE=1 ;; -x) LOG_LEVEL=3 DUMP_ENV=1 DUMP_HTTP=1 DUMP_UPPM=1 VERBOSE_GMAKE=1 DEBUG_CC=1 DEBUG_LD=1 DEBUG_GMAKE=1 DEBUG_PKG_CONFIG=1 ;; -v-env) DUMP_ENV=1 ;; -v-http) DUMP_HTTP=1 ;; -v-uppm) DUMP_UPPM=1 ;; -v-gmake) VERBOSE_GMAKE=1 ;; -x-sh) set -x ;; -x-cc) DEBUG_CC=1 ;; -x-ld) DEBUG_LD=1 ;; -x-gmake) DEBUG_GMAKE=1 ;; -x-pkg-config) DEBUG_PKG_CONFIG=1 ;; --disable-ccache) ENABLE_CCACHE=0 ;; --enable-lto) ENABLE_LTO=1 ;; --enable-strip) ENABLE_STRIP=all ;; --enable-strip=*) ENABLE_STRIP="${1#*=}" case $ENABLE_STRIP in no|all|debug|unneeded) ;; *) abort 1 "--strip=, VALUE must be one of no, all, debug, unneeded" esac ;; --profile=*) PROFILE="${1#*=}" ;; --session-dir=*) SESSION_DIR="${1#*=}" case $SESSION_DIR in '') abort 1 "--session-dir= , must be a non-empty string." ;; /*) ;; ~) SESSION_DIR="$HOME" ;; ~/) SESSION_DIR="$HOME" ;; ~/.) SESSION_DIR="$HOME" ;; ~/*) SESSION_DIR="$HOME/${SESSION_DIR#~/}" ;; *) SESSION_DIR="$PWD/$SESSION_DIR" esac ;; --download-dir=*) DOWNLOAD_DIR="${1#*=}" case $DOWNLOAD_DIR in '') abort 1 "--download-dir= , must be a non-empty string." ;; /*) ;; ~) DOWNLOAD_DIR="$HOME" ;; ~/) DOWNLOAD_DIR="$HOME" ;; ~/.) DOWNLOAD_DIR="$HOME" ;; ~/*) DOWNLOAD_DIR="$HOME/${DOWNLOAD_DIR#~/}" ;; *) DOWNLOAD_DIR="$PWD/$DOWNLOAD_DIR" esac ;; --prefix=*) PACKAGE_INSTALL_ROOT="${1#*=}" case $PACKAGE_INSTALL_ROOT in '') abort 1 "--prefix= , must be a non-empty string." ;; /*) ;; ~) PACKAGE_INSTALL_ROOT="$HOME" ;; ~/) PACKAGE_INSTALL_ROOT="$HOME" ;; ~/.) PACKAGE_INSTALL_ROOT="$HOME" ;; ~/*) PACKAGE_INSTALL_ROOT="$HOME/${PACKAGE_INSTALL_ROOT#~/}" ;; *) PACKAGE_INSTALL_ROOT="$PWD/$PACKAGE_INSTALL_ROOT" esac ;; -j) shift isInteger "$1" || abort 1 "-j , must be an integer." BUILD_NJOBS="$1" ;; -K) REQUEST_TO_KEEP_SESSION_DIR=1 ;; -U) REQUEST_TO_UPGRADE_IF_POSSIBLE=1 ;; -E) REQUEST_TO_EXPORT_COMPILE_COMMANDS_JSON=1 ;; -*) abort 1 "unrecognized option: $1" ;; *) SPECIFIED_PACKAGE_LIST="$SPECIFIED_PACKAGE_LIST $1" esac shift done ######################################################################################### : ${PROFILE:=release} : ${ENABLE_LTO:=1} : ${SESSION_DIR:="$HOME/.xbuilder/run/$$"} : ${DOWNLOAD_DIR:="$HOME/.xbuilder/downloads"} : ${PACKAGE_INSTALL_ROOT:="$HOME/.xbuilder/installed"} ######################################################################################### if [ -z "$ENABLE_STRIP" ] ; then case $PROFILE in debug) ENABLE_STRIP=no ;; release) ENABLE_STRIP=all ;; esac fi ######################################################################################### NATIVE_PLATFORM_KIND="$(uname -s | tr A-Z a-z)" NATIVE_PLATFORM_ARCH="$(uname -m)" ######################################################################################### if [ -z "$BUILD_NJOBS" ] ; then if [ "$NATIVE_PLATFORM_KIND" = darwin ] ; then NATIVE_PLATFORM_NCPU="$(sysctl -n machdep.cpu.thread_count)" else NATIVE_PLATFORM_NCPU="$(nproc)" fi BUILD_NJOBS="$NATIVE_PLATFORM_NCPU" fi ######################################################################################### if [ "$LOG_LEVEL" = 0 ] ; then exec 1>/dev/null exec 2>&1 else if [ -z "$LOG_LEVEL" ] ; then LOG_LEVEL=1 fi fi ######################################################################################### unset CC_ARGS unset PP_ARGS unset LD_ARGS if [ "$NATIVE_PLATFORM_KIND" = darwin ] ; then [ -z "$CC" ] && CC="$(xcrun --sdk macosx --find clang)" [ -z "$CXX" ] && CXX="$(xcrun --sdk macosx --find clang++)" [ -z "$AS" ] && AS="$(xcrun --sdk macosx --find as)" [ -z "$LD" ] && LD="$(xcrun --sdk macosx --find ld)" [ -z "$AR" ] && AR="$(xcrun --sdk macosx --find ar)" [ -z "$RANLIB" ] && RANLIB="$(xcrun --sdk macosx --find ranlib)" [ -z "$SYSROOT" ] && SYSROOT="$(xcrun --sdk macosx --show-sdk-path)" MACOSX_DEPLOYMENT_TARGET="$(sw_vers -productVersion)" CC_ARGS="-isysroot $SYSROOT -mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET -arch $NATIVE_PLATFORM_ARCH -Qunused-arguments" PP_ARGS="-isysroot $SYSROOT -Qunused-arguments" LD_ARGS="-isysroot $SYSROOT -mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET -arch $NATIVE_PLATFORM_ARCH" else [ -z "$CC" ] && { CC="$(command -v cc || command -v clang || command -v gcc)" || abort 1 "C Compiler not found." } [ -z "$CXX" ] && { CXX="$(command -v c++ || command -v clang++ || command -v g++)" || abort 1 "C++ Compiler not found." } [ -z "$AS" ] && { AS="$(command -v as)" || abort 1 "command not found: as" } [ -z "$LD" ] && { LD="$(command -v ld)" || abort 1 "command not found: ld" } [ -z "$AR" ] && { AR="$(command -v ar)" || abort 1 "command not found: ar" } [ -z "$RANLIB" ] && { RANLIB="$(command -v ranlib)" || abort 1 "command not found: ranlib" } CC_ARGS="-fPIC -fno-common" # https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html LD_ARGS="-Wl,--as-needed -Wl,-z,muldefs -Wl,--allow-multiple-definition" fi ######################################################################################### CPP="$CC -E" ######################################################################################### [ "$DEBUG_CC" = 1 ] && CC_ARGS="$CC_ARGS -v" [ "$DEBUG_LD" = 1 ] && LD_ARGS="$LD_ARGS -Wl,-v" case $PROFILE in debug) CC_ARGS="$CC_ARGS -O0 -g" ;; release) CC_ARGS="$CC_ARGS -Os" if [ "$ENABLE_LTO" = 1 ] ; then LD_ARGS="$LD_ARGS -flto" fi if [ "$NATIVE_PLATFORM_KIND" = darwin ] ; then LD_ARGS="$LD_ARGS -Wl,-S" else LD_ARGS="$LD_ARGS -Wl,-s" fi esac case $NATIVE_PLATFORM_KIND in netbsd) LD_ARGS="$LD_ARGS -lpthread" ;; openbsd) LD_ARGS="$LD_ARGS -lpthread" ;; esac ######################################################################################### CFLAGS="$CC_ARGS" CXXFLAGS="$CC_ARGS" CPPFLAGS="$PP_ARGS" LDFLAGS="$LD_ARGS" ######################################################################################### for TOOL in CC CXX CPP AS AR RANLIB LD SYSROOT CFLAGS CXXFLAGS CPPFLAGS LDFLAGS do export "${TOOL}" done ######################################################################################### unset LIBS # autoreconf --help unset AUTOCONF unset AUTOHEADER unset AUTOM4TE unset AUTOMAKE unset AUTOPOINT unset ACLOCAL unset GTKDOCIZE unset INTLTOOLIZE unset LIBTOOLIZE unset M4 unset MAKE unset MACOSX_DEPLOYMENT_TARGET unset IPHONEOS_DEPLOYMENT_TARGET unset WATCHOS_DEPLOYMENT_TARGET # https://stackoverflow.com/questions/18476490/what-is-purpose-of-target-arch-variable-in-makefiles unset TARGET_ARCH # https://keith.github.io/xcode-man-pages/xcrun.1.html unset SDKROOT } configure() { for FILENAME in config.sub config.guess do FILEPATH="$SESSION_DIR/$FILENAME" [ -f "$FILEPATH" ] || { wfetch "https://git.savannah.gnu.org/cgit/config.git/plain/$FILENAME" -o "$FILEPATH" run chmod a+x "$FILEPATH" if [ "$FILENAME" = 'config.sub' ] ; then sed -i.bak 's/arm64-*/arm64-*|arm64e-*/g' "$FILEPATH" fi } find . -name "$FILENAME" -exec cp -vf "$FILEPATH" {} \; done run ./configure "--prefix=$PACKAGE_INSTALL_DIR" "$@" run "$GMAKE" "--jobs=$BUILD_NJOBS" run "$GMAKE" install } install_the_given_package() { [ -z "$1" ] && abort 1 "install_the_given_package , is unspecified." unset PACKAGE_SRC_URL unset PACKAGE_SRC_URI unset PACKAGE_SRC_SHA unset PACKAGE_DEP_PKG unset PACKAGE_DOPATCH unset PACKAGE_INSTALL unset PACKAGE_DOTWEAK if [ "$1" = 'perl-XML-Parser' ] ; then package_info_perl_XML_Parser else package_info_$1 fi ######################################################################################### for PACKAGE_DEPENDENCY in $PACKAGE_DEP_PKG do (install_the_given_package "$PACKAGE_DEPENDENCY") done ######################################################################################### printf '\n%b\n' "${COLOR_PURPLE}=>> xbuilder: install package : $1${COLOR_OFF}" if [ -f "$PACKAGE_INSTALL_ROOT/$1/receipt.txt" ] ; then note "package '$1' already has been installed, skipped." return 0 fi ######################################################################################### PACKAGE_INSTALL_UTS= PACKAGE_INSTALL_UTS="$(date +%s)" PACKAGE_INSTALL_SHA= PACKAGE_INSTALL_SHA="$( { sha256sum < toolchain.txt < receipt.txt <... [OPTIONS]${COLOR_OFF} install the specified packages. Influential environment variables: URL_TRANSFORM, GMAKE, PKG_CONFIG, CC, CXX, CPP, AS, LD, AR, RANLIB, CFLAGS, CXXFLAGS, CPPFLAGS, LDFLAGS OPTIONS: ${COLOR_BLUE}--prefix=${COLOR_OFF} specify where to be installed into. ${COLOR_BLUE}--session-dir=${COLOR_OFF} specify the session directory. ${COLOR_BLUE}--download-dir=${COLOR_OFF} specify the download directory. ${COLOR_BLUE}-j ${COLOR_OFF} specify the number of jobs you can run in parallel. ${COLOR_BLUE}-E${COLOR_OFF} export compile_commands.json ${COLOR_BLUE}-U${COLOR_OFF} upgrade packages if possible. ${COLOR_BLUE}-K${COLOR_OFF} keep the session directory even if this packages are successfully installed. ${COLOR_BLUE}-q${COLOR_OFF} silent mode. no any messages will be output to terminal. ${COLOR_BLUE}-v${COLOR_OFF} verbose mode. many messages will be output to terminal. This option is equivalent to -v-* options all are supplied. ${COLOR_BLUE}-x${COLOR_OFF} very verbose mode. many many messages will be output to terminal. This option is equivalent to -v-* and -x-* options all are supplied. ${COLOR_BLUE}-v-env${COLOR_OFF} show all environment variables before starting to build. ${COLOR_BLUE}-v-http${COLOR_OFF} show http request/response. ${COLOR_BLUE}-v-uppm${COLOR_OFF} pass -v argument to uppm command. ${COLOR_BLUE}-v-gmake${COLOR_OFF} pass V=1 argument to gmake command. ${COLOR_BLUE}-x-sh${COLOR_OFF} set -x to debug current running shell. ${COLOR_BLUE}-x-cc${COLOR_OFF} pass -v argument to clang command. ${COLOR_BLUE}-x-ld${COLOR_OFF} pass -Wl,-v argument to linker. ${COLOR_BLUE}-x-gmake${COLOR_OFF} pass --debug argument to gmake command. ${COLOR_BLUE}-x-pkg-config${COLOR_OFF} export PKG_CONFIG_DEBUG_SPEW=1 ${COLOR_GREEN}xbuilder exec [--prefix=] ${COLOR_OFF} execute command in environment. " } RUNTIME_BUILDER_VERSION=7.0.0 case $1 in ''|--help|-h) help ;; --version|-V) printf '%s\n' "$RUNTIME_BUILDER_VERSION" ;; ls-available) PACKAGE_NAMES='libz libbz2 liblzma libffi libgdbm libyaml libpcre2 libsqlite3 libopenssl ruby perl python3 autoconf automake texinfo help2man intltool libtool swig perl-XML-Parser' if [ "$2" = -v ] ; then for PACKAGE_NAME in $PACKAGE_NAMES do unset PACKAGE_SRC_URL unset PACKAGE_SRC_URI unset PACKAGE_SRC_SHA unset PACKAGE_DEP_PKG unset PACKAGE_DOPATCH unset PACKAGE_INSTALL unset PACKAGE_DOTWEAK if [ "$PACKAGE_NAME" = 'perl-XML-Parser' ] ; then package_info_perl_XML_Parser else package_info_$PACKAGE_NAME fi cat < , is unspecified.' ;; --prefix=*) PACKAGE_INSTALL_ROOT="${1#*=}" case $PACKAGE_INSTALL_ROOT in '') abort 1 "--prefix= , must be a non-empty string." ;; /*) ;; ~) PACKAGE_INSTALL_ROOT="$HOME" ;; ~/) PACKAGE_INSTALL_ROOT="$HOME" ;; ~/.) PACKAGE_INSTALL_ROOT="$HOME" ;; ~/*) PACKAGE_INSTALL_ROOT="$HOME/${PACKAGE_INSTALL_ROOT#~/}" ;; *) PACKAGE_INSTALL_ROOT="$PWD/$PACKAGE_INSTALL_ROOT" esac [ -d "$PACKAGE_INSTALL_ROOT" ] && abort 1 "directory $PACKAGE_INSTALL_ROOT does not exist." shift [ -z "$1" ] && abort 1 'xbuilder exec --prefix= , is unspecified.' ;; esac if [ -z "$PACKAGE_INSTALL_ROOT" ] ; then [ -z "$HOME" ] && abort 1 'HOME environment is not set.' PACKAGE_INSTALL_ROOT="$HOME/.xbuilder/installed" fi PACKAGE_NAMES="$(cd "$PACKAGE_INSTALL_ROOT" && find . -maxdepth 1 -mindepth 1 -type l -printf '%P\n')" for PACKAGE_NAME in $PACKAGE_NAMES do PACKAGE_INSTALLED_DIR="$PACKAGE_INSTALL_ROOT/$PACKAGE_NAME" if [ ! -f "$PACKAGE_INSTALLED_DIR/receipt.txt" ] ; then continue fi if [ -d "$PACKAGE_INSTALLED_DIR/include" ] ; then CPPFLAGS="-I$PACKAGE_INSTALLED_DIR/include $CPPFLAGS" fi if [ -d "$PACKAGE_INSTALLED_DIR/lib" ] ; then LDFLAGS="-L$PACKAGE_INSTALLED_DIR/lib -Wl,-rpath,$PACKAGE_INSTALLED_DIR/lib $LDFLAGS" fi if [ -d "$PACKAGE_INSTALLED_DIR/bin" ] ; then PATH="$PACKAGE_INSTALLED_DIR/bin:$PATH" fi if [ -d "$PACKAGE_INSTALLED_DIR/sbin" ] ; then PATH="$PACKAGE_INSTALLED_DIR/sbin:$PATH" fi if [ -d "$PACKAGE_INSTALLED_DIR/share/aclocal" ] ; then ACLOCAL_PATH="$PACKAGE_INSTALLED_DIR/share/aclocal:$ACLOCAL_PATH" fi done export CPPFLAGS export LDFLAGS export PATH export ACLOCAL_PATH pwd exec "$@" ;; *) abort 1 "unrecognized argument: $1" esac