#!/usr/bin/env bash CONFIG="config.mk" PREFIX="/usr/local" VERSION=$(grep LIQ_VERSION_STRING lib/libimagequant.h | grep -Eo "2\.[0-9.]+") DEBUG= SSE=auto OPENMP= if [[ "$OSTYPE" =~ "darwin" ]]; then COCOA_READER=auto LCMS2=0 else COCOA_READER=0 LCMS2=auto fi EXTRA_CFLAGS= EXTRA_LDFLAGS= # make gcc default compiler unless CC is already set CC=${CC:-gcc} help() { printf "%4s %s\n" "" "$1" } for i in "$@"; do case $i in --help) echo help "--prefix= installation directory [$PREFIX]" help "--extra-cflags= append to CFLAGS" help "--extra-ldflags= append to LDFLAGS" echo help "--enable-debug" help "--enable-sse/--disable-sse enable/disable SSE instructions" echo help "--with-openmp compile with multicore support" help "--with-lcms2/--without-lcms2 compile with color profile support" if [[ "$OSTYPE" =~ "darwin" ]]; then help "--with-cocoa/--without-cocoa use Cocoa framework to read images" fi echo help "CC= use given compiler command" help "CFLAGS= pass options to the compiler" help "LDFLAGS= pass options to the linker" echo exit 0 ;; # Can be set before or after configure. Latter overrides former. CC=*) CC=${i#*=} ;; CFLAGS=*) CFLAGS=${i#*=} ;; LDFLAGS=*) LDFLAGS=${i#*=} ;; --enable-debug) DEBUG=1 ;; --enable-sse) SSE=1 ;; --disable-sse) SSE=0 ;; --with-openmp) OPENMP=1 ;; --with-lcms2) LCMS2=1 COCOA_READER=0 ;; --without-lcms2) LCMS2=0 ;; --with-cocoa) COCOA_READER=1 LCMS2=0 ;; --without-cocoa) COCOA_READER=0 ;; --prefix=*) PREFIX=${i#*=} ;; # can be used multiple times or in quotes to set multiple flags --extra-cflags=*) EXTRA_CFLAGS="$EXTRA_CFLAGS ${i#*=}" ;; --extra-ldflags=*) EXTRA_LDFLAGS="$EXTRA_LDFLAGS ${i#*=}" ;; *) echo "error: unknown switch ${i%%=*} (see $0 --help for the list)" exit 1 ;; esac done # If someone runs sudo make install as very first command, and configure later, # $CONFIG cannot be overwritten, and must be deleted before continuing. if [[ -f "$CONFIG" && ! -w "$CONFIG" ]]; then echo "Cannot overwrite file $CONFIG! Please delete it." exit 1 fi cflags() { CFLAGS="$CFLAGS $1" } lflags() { LDFLAGS="$LDFLAGS $1" } status() { printf "%10s: %s\n" "$1" "$2" } # Append to CFLAGS if compiler supports flag, with optional prerequisite. # Fails on errors and warnings. conditional_cflags() { if [ -z "echo | $("$CC" -xc -S -o /dev/null $2 $1 2>&1)" ]; then cflags "$1" fi } # returns first matching file in directory find_f() { echo $(find "$1" -not -type d -name "$2" -print -quit 2> /dev/null) } # returns first matching file in directory (no symlinks) find_h() { echo $(find "$1" -type f -name "$2" -print -quit 2> /dev/null) } find_pkgconfig() { LIBNAME=$1 if pkg-config --exists "$LIBNAME" &> /dev/null; then cflags "$(pkg-config --cflags "$LIBNAME")" lflags "$(pkg-config --libs "$LIBNAME")" status "$LIBNAME" "shared ($(pkg-config --modversion "$LIBNAME"))" return 0 fi return 1 } find_static() { LIBNAME=$1 HEADERPATTERN=$2 STATICPATTERN=$3 HPATH=$(find_h . "$HEADERPATTERN") if [ -n "$HPATH" ]; then APATH=$(find_f . "$STATICPATTERN") if [ -n "$APATH" ]; then cflags "-I${HPATH%/*}" lflags "${APATH}" status "$LIBNAME" "static" return 0 fi fi return 1 } find_library() { LIBNAME=$1 DYNAMICLIBNAME=$2 HEADERPATTERN=$3 STATICPATTERN=$4 DYNAMICPATTERN=$5 # try static in current directory first if find_static "$LIBNAME" "$HEADERPATTERN" "$STATICPATTERN"; then return 0; fi # try shared if find_pkgconfig "$LIBNAME"; then return 0 fi for i in "${DIRS[@]}"; do DIR=($i) HPATH=$(find_h "${DIR[0]}" "$HEADERPATTERN") if [ -n "$HPATH" ]; then SOPATH=$(find_f "${DIR[1]}" "$DYNAMICPATTERN") if [ -n "$SOPATH" ]; then cflags "-I${HPATH%/*}" lflags "-L${SOPATH%/*} -l$DYNAMICLIBNAME" status "$LIBNAME" "shared ... $SOPATH" return 0 fi fi done return 1 } # returns full png.h version string pngh_string() { echo "$(grep -m1 "define PNG_LIBPNG_VER_STRING" "$1" | \ grep -Eo '"[^"]+"' | grep -Eo '[^"]+')" } # returns major minor version numbers from png.h pngh_majmin() { local MAJ=$(grep -m1 "define PNG_LIBPNG_VER_MAJOR" "$1" | grep -Eo "[0-9]+") local MIN=$(grep -m1 "define PNG_LIBPNG_VER_MINOR" "$1" | grep -Eo "[0-9]+") echo "${MAJ}${MIN}" } error() { status "$1" "error ... $2" echo exit 1 } echo # basic check if ! echo "int main(){}" | "$CC" -xc -std=c99 -o /dev/null - &> /dev/null; then error "Compiler" "$CC failed to compile anything (make sure it's installed and supports C99)" fi status "Compiler" "$CC" # init flags CFLAGS=${CFLAGS:--O3 -fno-math-errno -funroll-loops -fomit-frame-pointer -Wall} cflags "-std=c99 -I." # DEBUG if [ -z "$DEBUG" ]; then cflags "-DNDEBUG" status "Debug" "no" else cflags "-g" status "Debug" "yes" fi # SSE if [ "$SSE" = 'auto' ]; then if [[ "$(uname -m)" =~ (amd|x86_)64 || "$(grep -E -m1 "^flags" /proc/cpuinfo)" =~ "sse" ]]; then SSE=1 fi fi if [ "$SSE" -eq 1 ]; then status "SSE" "yes" cflags "-DUSE_SSE=1" cflags "-msse" # Silence a later ICC warning due to -msse working slightly different. conditional_cflags "-wd10121" # Must be set explicitly for GCC on x86_32. Other compilers imply it. conditional_cflags "-mfpmath=sse" "-msse" elif [ "$SSE" -eq 0 ]; then status "SSE" "no" cflags "-DUSE_SSE=0" fi # OpenMP if [ -n "$OPENMP" ]; then if [[ "$("$CC" -xc -E -fopenmp <(echo "#ifdef _OPENMP #include #endif") 2>&1)" =~ "omp_get_thread_num" ]]; then cflags "-fopenmp" lflags "-fopenmp" status "OpenMP" "yes" else error "OpenMP" "not supported by compiler (please install a compiler that supports OpenMP (e.g. gcc) and specify it with the CC= argument)" fi else # silence warnings about omp pragmas cflags "-Wno-unknown-pragmas" conditional_cflags "-wd3180" # ICC status "OpenMP" "no" fi # Cocoa if [[ "$OSTYPE" =~ "darwin" ]]; then cflags "-mmacosx-version-min=10.6" lflags "-mmacosx-version-min=10.6" if [ "$COCOA_READER" != 0 ] && "$CC" 2>/dev/null 1>/dev/null -xc -E <(echo "#import "); then COCOA_READER=1 cflags "-DUSE_COCOA=1" lflags "-framework Cocoa" status "Cocoa" "yes" else status "Cocoa" "no" fi fi # pairs of possible *.h and lib*.so locations DIRS=("/usr/local/include /usr/local/lib" "/usr/include /usr/lib" "/opt/local/include /opt/local/lib" # macports ) if [[ "$OSTYPE" =~ "darwin" ]]; then SOLIBSUFFIX=dylib # Search Developer SDK paths, since Apple seems to have dropped the standard Unixy ones XCODE_CMD="xcode-select" XCODE_PATH=$($XCODE_CMD -p) DIRS+=("$XCODE_PATH/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include $XCODE_PATH/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib") DIRS+=("$XCODE_PATH/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/usr/include $XCODE_PATH/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/usr/lib") else SOLIBSUFFIX=so fi # libpng SUCCESS=0 # try static in current directory first PNGH=$(find_h . "png.h") if [ -n "$PNGH" ]; then PNGH_STRING=$(pngh_string "$PNGH") PNGH_MAJMIN=$(pngh_majmin "$PNGH") if [[ -n "$PNGH_STRING" && -n "$PNGH_MAJMIN" ]]; then LIBPNGA=$(find_f . "libpng${PNGH_MAJMIN}.a") if [ -n "$LIBPNGA" ]; then cflags "-I${PNGH%/*}" lflags "${LIBPNGA}" status "libpng" "static (${PNGH_STRING})" SUCCESS=1 fi fi fi # try shared if [ "$SUCCESS" -eq 0 ]; then if find_pkgconfig libpng; then SUCCESS=1 else for i in "${DIRS[@]}"; do DIR=($i) PNGH=$(find_h "${DIR[0]}" "png.h") if [ -n "$PNGH" ]; then PNGH_STRING=$(pngh_string "$PNGH") PNGH_MAJMIN=$(pngh_majmin "$PNGH") if [[ -n "$PNGH_STRING" && -n "$PNGH_MAJMIN" ]]; then LIBPNGSO=$(find_f "${DIR[1]}" "libpng${PNGH_MAJMIN}.$SOLIBSUFFIX*") if [ -n "$LIBPNGSO" ]; then cflags "-I${PNGH%/*}" lflags "-L${LIBPNGSO%/*} -lpng${PNGH_MAJMIN}" status "libpng" "shared (${PNGH_STRING})" SUCCESS=1 break fi fi fi done fi fi if [ "$SUCCESS" -eq 0 ]; then if [[ "$OSTYPE" =~ "darwin" ]]; then LIBPNG_CMD='`brew install libpng`' else LIBPNG_CMD='`apt-get install libpng-dev` or `yum install libpng-devel`' fi error "libpng" "not found (try: $LIBPNG_CMD)" fi # zlib if ! find_library "zlib" "z" "zlib.h" "libz.a" "libz.$SOLIBSUFFIX*"; then error "zlib" "not found (please install zlib-devel package)" fi # lcms2 if [ "$LCMS2" != 0 ]; then if find_library "lcms2" "lcms2" "lcms2.h" "liblcms2.a" "liblcms2.$SOLIBSUFFIX*"; then cflags "-DUSE_LCMS=1" else if [ "$LCMS2" = 'auto' ]; then status "lcms2" "no" else error "lcms2" "not found (please install libcms2-devel package)" fi fi else status "lcms2" "no" fi echo # As of GCC 4.5, 387 fp math is significantly slower in C99 mode without this. # Note: CPUs without SSE2 use 387 for doubles, even when SSE fp math is set. conditional_cflags "-fexcess-precision=fast" # Intel C++ Compiler # ICC does usually only produce fast(er) code when it can optimize to the full # capabilites of the (Intel) CPU. This is equivalent to -march=native for GCC. conditional_cflags "-xHOST" # Disable unsafe fp optimizations and enforce fp precision as set in the source. conditional_cflags "-fp-model source" # Silence a gold linker warning about string misalignment. conditional_cflags "-falign-stack=maintain-16-byte" lflags "-lm" # Ubuntu requires this library last, issue #38 if [ -n "$EXTRA_CFLAGS" ]; then cflags "$EXTRA_CFLAGS" fi if [ -n "$EXTRA_LDFLAGS" ]; then lflags "$EXTRA_LDFLAGS" fi # Overwrite previous configuration. echo " # auto-generated by configure PREFIX = $PREFIX VERSION = $VERSION CC = $CC CFLAGS = $CFLAGS LDFLAGS = $LDFLAGS COCOA_READER = $COCOA_READER " > "$CONFIG" # Configure static library the same way cp "$CONFIG" lib/