#!/bin/sh prefix=/usr/local OUR_CPPFLAGS= # Get a temporary filename fail() { printf "%s\n" "$1" >&2 ; exit 1 ; } i=0 set -C while : ; do i=$(($i+1)) tmpc="./conf$$-$PPID-$i.c" 2>|/dev/null > "$tmpc" && break test "$i" -gt 50 && fail "$0: cannot create temporary file $tmpc" done set +C trap 'rm "$tmpc"' EXIT INT QUIT TERM HUP check_compile() { printf "checking %s ... " "$1" printf "$3" > "$tmpc" local res=0 $CC $OUR_CPPFLAGS $CPPFLAGS $2 $CFLAGS "$tmpc" -o "$tmpc".out >/dev/null 2>&1 \ || res=1 test x$res = x0 && \ { printf "yes\n" ; test x"$2" = x || OUR_CPPFLAGS="$OUR_CPPFLAGS $2" ; } \ || printf "no\n" rm -f "$tmpc".out return $res } get_define() { $CC $OUR_CPPFLAGS $CPPFLAGS $CFLAGS -dM -E - /dev/null && res=0 test x$res = x0 && printf "yes\n" || printf "no\n" return $res } check_compile_run() { printf "checking %s ... " "$1" printf "$2" > "$tmpc" local res=0 $CC $OUR_CPPFLAGS $CPPFLAGS $CFLAGS "$tmpc" -o "$tmpc".out >/dev/null 2>&1 \ || res=1 test x$res = x0 && { "$tmpc".out || res=1 ; } rm -f "$tmpc".out test x$res = x0 && printf "yes\n" || printf "no\n" return $res } check_link_silent() { printf "$2" > "$tmpc" local res=0 $CC $OUR_CPPFLAGS $CPPFLAGS $1 $CFLAGS "$tmpc" -o "$tmpc".out >/dev/null 2>&1 || res=1 rm -f "$tmpc".out return $res } check_link() { printf "checking %s ... " "$1" local res=0 check_link_silent "$2" "$3" || res=1 test x$res = x0 && printf "yes\n" || printf "no\n" return $res } usage() { echo "supported arguments" echo "--prefix=/path default: $prefix" echo "--exec_prefix=/path default: $prefix/bin" echo "--bindir=/path default: $prefix/bin" echo "--libdir=/path default: $prefix/lib" echo "--includedir=/path default: $prefix/include" echo "--sysconfdir=/path default: $prefix/etc" echo "--ignore-cve default: no" echo " if set to yes ignores CVE-2015-3887 and makes it possible" echo " to preload from current dir (possibly insecure, but handy)" echo "--fat-binary : build for both i386 and x86_64 architectures on 64-bit Macs" echo "--fat-binary-m1 : build for both arm64e and x86_64 architectures on M1 Macs" echo "--fat-binary-m2 : build for arm64, arm64e and x86_64 architectures on M2+ Macs" echo "--hookmethod=dlsym|dyld hook method for osx. default: auto" echo " if OSX >= 12 is detected, dyld method will be used if auto." echo "--help : show this text" exit 1 } spliteq() { arg=$1 echo "${arg#*=}" #alternatives echo "$arg" | cut -d= -f2- # or echo "$arg" | sed 's/[^=]*=//' } fat_binary= fat_binary_m1= fat_binary_m2= ignore_cve=no hookmethod=auto parsearg() { case "$1" in --prefix=*) prefix=`spliteq $1`;; --exec_prefix=*) exec_prefix=`spliteq $1`;; --bindir=*) bindir=`spliteq $1`;; --libdir=*) libdir=`spliteq $1`;; --includedir=*) includedir=`spliteq $1`;; --sysconfdir=*) sysconfdir=`spliteq $1`;; --ignore-cve) ignore_cve=1;; --ignore-cve=*) ignore_cve=`spliteq $1`;; --hookmethod=*) hookmethod=`spliteq $1`;; --fat-binary) fat_binary=1;; --fat-binary-m1) fat_binary_m1=1;; --fat-binary-m2) fat_binary_m2=1;; --help) usage;; esac } while true ; do case $1 in -*) parsearg "$1"; shift;; *) break ;; esac done if [ -z "$exec_prefix" ] ; then exec_prefix=$prefix fi if [ -z "$libdir" ] ; then libdir=$prefix/lib fi if [ -z "$includedir" ] ; then includedir=$prefix/include fi if [ -z "$sysconfdir" ] ; then sysconfdir=$prefix/etc fi if [ -z "$bindir" ] ; then bindir=$exec_prefix/bin fi if [ -z "$CC" ] ; then CC=cc fi echo > config.mak bsd_detected=false isbsd() { $bsd_detected } mac_detected=false ismac() { $mac_detected } mac_64=false ismac64() { $mac_64 } solaris_detected=false issolaris() { $solaris_detected } haiku_detected=false ishaiku() { $haiku_detected } check_compile 'whether C compiler works' '' 'int main() {return 0;}' || fail 'error: install a C compiler and library' check_compile 'whether libc headers are complete' '' '#include \nint main() {return 0;}' || fail 'error: necessary libc headers are not installed' check_compile 'whether C compiler understands -Wno-unknown-pragmas' '-Wno-unknown-pragmas' 'int main() {return 0;}' if ! check_compile 'whether getnameinfo() servlen argument is POSIX compliant (socklen_t)' "-DGN_NODELEN_T=socklen_t -DGN_SERVLEN_T=socklen_t -DGN_FLAGS_T=int" \ '#define _GNU_SOURCE\n#include \nint getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t, char *, socklen_t, int);int main() {\nreturn 0;}' ; then # GLIBC < 2.14 if ! check_compile 'whether getnameinfo() flags argument is unsigned' "-DGN_NODELEN_T=socklen_t -DGN_SERVLEN_T=socklen_t -DGN_FLAGS_T=unsigned" \ '#define _GNU_SOURCE\n#include \nint getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t, char *, socklen_t, unsigned);int main() {\nreturn 0;}' ; then if ! check_compile 'whether getnameinfo() servlen argument is size_t' "-DGN_NODELEN_T=socklen_t -DGN_SERVLEN_T=size_t -DGN_FLAGS_T=int" \ '#define _GNU_SOURCE\n#include \nint getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t, char *, size_t, int);int main() {\nreturn 0;}' ; then # OpenBSD & FreeBSD if ! check_compile 'whether getnameinfo() servlen and nodelen argument is size_t' "-DGN_NODELEN_T=size_t -DGN_SERVLEN_T=size_t -DGN_FLAGS_T=int" \ '#define _GNU_SOURCE\n#include \nint getnameinfo(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int);int main() {\nreturn 0;}' ; then fail "failed to detect getnameinfo signature" fi fi fi fi check_compile 'whether we have GNU-style getservbyname_r()' "-DHAVE_GNU_GETSERVBYNAME_R" \ '#define _GNU_SOURCE\n#include \nint main() {\nstruct servent *se = 0;struct servent se_buf;char buf[1024];\ngetservbyname_r("foo", (void*) 0, &se_buf, buf, sizeof(buf), &se);\nreturn 0;}' check_compile 'whether we have pipe2() and O_CLOEXEC' "-DHAVE_PIPE2" \ '#define _GNU_SOURCE\n#include \n#include \nint main() {\nint pipefd[2];\npipe2(pipefd, O_CLOEXEC);\nreturn 0;}' check_compile 'whether we have SOCK_CLOEXEC' "-DHAVE_SOCK_CLOEXEC" \ '#define _GNU_SOURCE\n#include \nint main() {\nreturn socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);}' check_compile 'whether we have clock_gettime' "-DHAVE_CLOCK_GETTIME" \ '#define _GNU_SOURCE\n#include \nint main() {\nstruct timespec now;clock_gettime(CLOCK_REALTIME, &now);\nreturn now.tv_sec ^ now.tv_nsec;}' check_define __APPLE__ && { mac_detected=true check_define __x86_64__ && mac_64=true if test "$hookmethod" = auto ; then osver=$(get_define_stripped __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ 2>/dev/null) test "$osver" -gt $((120000 - 1)) && hookmethod=dyld fi } check_define __FreeBSD__ && bsd_detected=true check_define __OpenBSD__ && { bsd_detected=true echo "CFLAGS+=-DIS_OPENBSD">>config.mak check_compile_run 'whether OpenBSDs fclose() (illegally) calls close()' \ '#include \n#include\nint close(int x){exit(0);}int main(){fclose(stdin);return 1;}' && \ OUR_CPPFLAGS="$OUR_CPPFLAGS -DBROKEN_FCLOSE" } check_define __sun && check_define __SVR4 && solaris_detected=true check_define __HAIKU__ && haiku_detected=true echo "CC=$CC">>config.mak [ -z "$CPPFLAGS" ] || echo "CPPFLAGS=$CPPFLAGS">>config.mak [ -z "$CFLAGS" ] || echo "USER_CFLAGS=$CFLAGS">>config.mak [ -z "$LDFLAGS" ] || echo "USER_LDFLAGS=$LDFLAGS">>config.mak echo prefix=$prefix>>config.mak echo exec_prefix=$exec_prefix>>config.mak echo bindir=$bindir>>config.mak echo libdir=$libdir>>config.mak echo includedir=$includedir>>config.mak echo sysconfdir=$sysconfdir>>config.mak [ "$ignore_cve" = "no" ] && echo "CPPFLAGS+= -DSUPER_SECURE">>config.mak [ -z "$OUR_CPPFLAGS" ] || echo "CPPFLAGS+= $OUR_CPPFLAGS" >>config.mak check_link "whether we can use -Wl,--no-as-needed" "-Wl,--no-as-needed" \ "int main() { return 0; }" || echo NO_AS_NEEDED= >> config.mak LD_SONAME_FLAG= printf "checking what's the option to use in linker to set library name ... " for o in --soname -h -soname -install_name; do check_link_silent "-shared -Wl,$o,libconftest.so" "void test_func(int a) {}" && LD_SONAME_FLAG=$o && break done if [ -z "$LD_SONAME_FLAG" ]; then printf '\ncannot find an option to set library name\n' exit 1 fi echo "$LD_SONAME_FLAG" echo "LD_SET_SONAME = -Wl,$LD_SONAME_FLAG," >> config.mak if check_link "checking whether we can use -ldl" "-ldl" \ "int main(){return 0;}" ; then echo "LIBDL = -ldl" >> config.mak fi if check_link "checking whether we can use -lpthread" "-lpthread" \ "int main(){return 0;}" ; then echo "PTHREAD = -lpthread" >> config.mak else check_link "checking whether we can use -pthread" "-pthread" \ "int main(){return 0;}" || fail "no pthread support detected" echo "PTHREAD = -pthread" >> config.mak fi make_cmd=make if ismac ; then echo LDSO_SUFFIX=dylib>>config.mak echo MAC_CFLAGS+=-DIS_MAC=1>>config.mak if test "$hookmethod" = dyld ; then echo "using Monterey style DYLD hooking" echo "CFLAGS+=-DMONTEREY_HOOKING">>config.mak fi if ismac64 && [ "$fat_binary" = 1 ] ; then echo "Configuring a fat binary for i386 and x86_64" echo "MAC_CFLAGS+=-arch i386 -arch x86_64">>config.mak echo "FAT_LDFLAGS=-arch i386 -arch x86_64">>config.mak echo "FAT_BIN_LDFLAGS=-arch i386 -arch x86_64">>config.mak fi if [ "$fat_binary_m1" = 1 ] ; then echo "Configuring a fat binary for arm64[e] and x86_64" echo "MAC_CFLAGS+=-arch arm64 -arch arm64e -arch x86_64">>config.mak echo "FAT_LDFLAGS=-arch arm64 -arch arm64e -arch x86_64">>config.mak echo "FAT_BIN_LDFLAGS=-arch arm64 -arch x86_64">>config.mak fi if [ "$fat_binary_m2" = 1 ] ; then echo "Configuring a fat binary for arm64[e] and x86_64" echo "MAC_CFLAGS+=-arch arm64 -arch arm64e -arch x86_64">>config.mak echo "FAT_LDFLAGS=-arch arm64 -arch arm64e -arch x86_64">>config.mak echo "FAT_BIN_LDFLAGS=-arch arm64 -arch arm64e -arch x86_64">>config.mak fi elif isbsd ; then echo LIBDL=>>config.mak echo "CFLAGS+=-DIS_BSD">>config.mak make_cmd=gmake elif issolaris; then echo "CFLAGS+=-DIS_SOLARIS -D__EXTENSIONS__" >> config.mak echo "SOCKET_LIBS=-lsocket -lnsl" >> config.mak elif ishaiku ; then echo LIBDL=>>config.mak echo "CFLAGS+=-DIS_HAIKU" >> config.mak fi echo "Done, now run $make_cmd && $make_cmd install" if [ "$fat_binary_m2" = 1 ] ; then echo "Don't forget to run csrutil disable and sudo nvram boot-args=-arm64e_preview_abi" fi