The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

#!/bin/sh
usage() {
cat <<EOF
usage: $0 --<option>=<value> <var>=<value> ..
--prefix=<dir>
--target=<platform> uname/special targets: macos,iOS,iPhoneSimulator
use "?" to get a list of explicitly specifiable
targets
--sdk=<version> Mac OS X/iOS SDK version (e.g. '6.1' or '10.9.3')
Tested iOS SDK versions: 4.3, 6.1, 8.1
--sdkroot=<dir>
Useful variables CC, CXX, CFLAGS, CXXFLAGS, etc..
EOF
}
C=Makefile.config
# get full path to this file (portable way), and set where to build
SRCTOP="`cd \`dirname "$0"\` && pwd`"
BLDTOP="$PWD"
printf "# auto-generated by $0\n" >$C
while [ $# -gt 0 ]; do
X=$1
shift 1
case $X in
# Shell common:
--help|-h|-?)
usage
exit 1
;;
# GNU Compatibility:
--prefix=*)
PREFIX=`printf -- "${X}" | cut -c 10-`
;;
--target=*)
TARGET=`printf -- "${X}" | cut -c 10-`
;;
--sdk=*)
SDK=`printf -- "${X}" | cut -c 7-`
;;
--sdkroot=*)
SDKROOT=`printf -- "${X}" | cut -c 11-`
;;
# Environment variables:
[A-Za-z_]*=*)
printf "${X}\n" >>$C
k=`printf "${X}" | cut -d = -f 1`
v=`printf "${X}" | cut -d = -f 2`
export $k="$v"
;;
# Others fail:
*)
printf "error: invalid option ${X}\n" >&2
exit 1
;;
esac
done
printf "PREFIX=${PREFIX:=/usr/local}\n" >>$C
case ${TARGET:=`uname`} in
Linux|GNU/kFreeBSD)
if [ -z "${CFLAGS}" ]; then
printf "CFLAGS=-fPIC\n" >>$C
fi
printf "LDLIBS=-lm -ldl\n" >>$C
;;
OpenBSD)
if [ -z "${CFLAGS}" ]; then
# dl_iterate_phdr() got introduced in 3.7, so for older versions force DL_DLADDR_TO_LIBPATH
if (uname -r | grep '^\([0-2]\.\|3\.[0-6]\)' > /dev/null); then
printf "CFLAGS=-fPIC -DDL_DLADDR_TO_LIBPATH\n" >>$C
else
printf "CFLAGS=-fPIC\n" >>$C
fi
fi
printf "LDLIBS=-lm\n" >>$C
;;
NetBSD|DragonFly)
if [ -z "${CFLAGS}" ]; then
printf "CFLAGS=-fPIC\n" >>$C
fi
printf "LDLIBS=-lm\n" >>$C
;;
FreeBSD)
if [ -z "${CFLAGS}" ]; then
if [ `uname -m` = "mips" ] && make -V MACHINE_ARCH | grep 'hf$' >/dev/null 2>&1; then
# FBSD12-CURRENT/mipshf needs to be told explicitly to use -mhard-float (at least as of may 2018)
printf "CFLAGS=-fPIC -mhard-float\n" >>$C
else
printf "CFLAGS=-fPIC\n" >>$C
fi
fi
printf "LDLIBS=-lm\n" >>$C
printf "RM=rm -f\n" >>$C
;;
MacOSX|macos|Darwin)
# if Apple's libtool (not to be confused with GNU's) is available, which is according to libtool(1) "with -static [...] intended
# to replace ar(5) and ranlib", use it - if it is shadowed by some install of GNU's libtool assume that a foreign environment is
# intentionally used, and fall back to using 'ar rs' (the equivalent to 'libtool -static'), for compatibility:
if libtool -V >/dev/null 2>/dev/null; then # Apple's libtool has -V for version, which GNU does not.
printf "AR=libtool\n" >>$C
printf "ARFLAGS=-static -o\n" >>$C
else
printf "AR=ar\n" >>$C
printf "ARFLAGS=rs\n" >>$C # 's' is crucial for universal binary archives
fi
if [ `uname -n` = 'iPhone' ]; then # building on iPhone itself, uname yields Darwin (gcc setup for current/correct arch)
printf "CC=gcc\n" >>$C
elif [ -z ${SDK} ]; then
case `sw_vers -productVersion` in
10.4.*) # == tiger (10.4.*)
ARCHS="-arch ppc -arch i386 -arch x86_64"
;;
10.5.*) # == leopard (10.5.*)
ARCHS="-arch i386 -arch x86_64 -arch ppc"
;;
10.6.*) # == snow leopard (10.6.*)
ARCHS="-arch i386 -arch x86_64" # no more ppc
;;
10.[789].*|10.1[0123].*|10.1[0123]) # >= lion (10.7.*), <= high sierra (10.13.*)
ARCHS="-arch x86_64 -arch i386"
;;
10.1?.*|10.1?) # >= mojave (10.14.*)
ARCHS="-arch x86_64" # mojave is final os to run x86 code, but removed build support for it
;;
esac
printf "ASFLAGS=${ARCHS}\n" >>$C
printf "CFLAGS=${ARCHS}\n" >>$C
printf "CXXFLAGS=${ARCHS}\n" >>$C
else
if [ -z ${SDKROOT} ]; then
SDKROOT="`xcode-select -print-path`/Platforms/MacOSX.platform/Developer/SDKs/MacOSX${SDK}.sdk"
fi
printf "CFLAGS=-isysroot ${SDKROOT}\n" >>$C
printf "CXXFLAGS=-isysroot ${SDKROOT}\n" >>$C
fi
;;
iPhoneOS|iOS)
if [ -z ${SDKROOT} ]; then
SDKROOT="`xcode-select -print-path`/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS${SDK}.sdk"
fi
if [ -z "${ARCHS}" ]; then
case "${SDK}" in
[45].*)
ARCHS="-arch armv6"
;;
[67].*)
ARCHS="-arch armv7"
;;
[89].*|1[0-9].*)
ARCHS="-arch armv7 -arch arm64"
;;
esac
fi
printf "ARFLAGS=rs\n" >>$C # 's' is crucial for universal binary archives
printf "ASFLAGS=${ARCHS} -isysroot ${SDKROOT}\n" >>$C
printf "CFLAGS=${ARCHS} -isysroot ${SDKROOT}\n" >>$C
printf "CXXFLAGS=${ARCHS} -isysroot ${SDKROOT}\n" >>$C
printf "LDFLAGS=-Wl,-syslibroot ${SDKROOT}\n" >>$C
;;
iPhoneSimulator)
if [ -z ${SDKROOT} ]; then
SDKROOT="`xcode-select -print-path`/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator${SDK}.sdk"
fi
ARCHS="-arch i386"
printf "ASFLAGS=${ARCHS} -isysroot ${SDKROOT}\n" >>$C
printf "CFLAGS=${ARCHS} -isysroot ${SDKROOT}\n" >>$C
printf "CXXFLAGS=${ARCHS} -isysroot ${SDKROOT}\n" >>$C
printf "LDFLAGS=-Wl,-syslibroot ${SDKROOT}\n" >>$C
;;
SunOS)
# open distributions often don't come with default cc and CC, check for common alternatives.
printf "CC=` (which cc gcc clang ) | grep -v '^no ' | head -1`\n" >>$C
printf "CXX=`(which CC g++ clang++) | grep -v '^no ' | head -1`\n" >>$C # C++ compiler traditionally named CC
printf "LDLIBS=-lm -ldl\n" >>$C
# make use of native instruction set, many open 64bit distributions execute
# 32 bit code and might default to that (also use PIC for 64 bit platforms)
if which isainfo >/dev/null && [ `isainfo -b` -eq 64 ]; then
printf "CFLAGS=-m64 -fPIC\n" >>$C
printf "CXXFLAGS=-m64 -fPIC\n" >>$C
printf "ASFLAGS=-m64 -fPIC\n" >>$C
fi
# Sun make's rules use CCC and CCFLAGS for c++
printf "CCC=\${CXX}\n" >>$C
printf "CCFLAGS=\${CXXFLAGS}\n" >>$C
;;
Minix)
printf "CC=gcc\n" >>$C
printf "CXX=g++\n">>$C
printf "AR=ar\n" >>$C
;;
PSP)
SDKROOT="`psp-config --pspsdk-path`"
printf "CC=psp-gcc\n" >>$C
printf "CXX=psp-gcc\n">>$C # don't use psp-g++, buggy
printf "AR=psp-ar\n" >>$C
printf "CFLAGS=-I${SDKROOT}/include/\n" >>$C
printf "CXXFLAGS=-I${SDKROOT}/include/\n" >>$C
# Pulling in dyncall libs below is a hack, for some reason psp-ld is super-picky about order.
# Use your C lib of choice, from the PSPSDK, or...
#printf "LDLIBS=-L${SDKROOT}/lib/ -L${SRCTOP}/dyncall -L${SRCTOP}/dyncallback -ldyncall_s -ldyncallback_s -lm -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lstdc++ -lpsplibc -lpspnet -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputility -lpspuser \n" >>$C
# ... newlib.
printf "LDLIBS=-L${SDKROOT}/lib/ -L${SRCTOP}/dyncall -L${SRCTOP}/dyncallback -ldyncall_s -ldyncallback_s -lm -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lstdc++ -lc -lpspnet -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputility -lpspuser \n" >>$C
;;
?)
cat $0 | awk '/^esac$/{b=0}/^ [A-Za-z0-9|]+\)/{if(b==1) print substr($1,1,length($1)-1)}BEGIN{b=0}/^case.*TARGET.*uname.*in$/{b=1}' | tr '|' '\n'
exit 0
;;
esac
# removed, b/c platform support not consistent and ELF flags checked often not having any result
#
## Assure objects not asking for an execstack (or binary that links dyncall might end
## up with one, for no reason).
#
## .s.o/.S.o rules often use ${CC} which then invokes the tools needed. GCC and
## others might (annoyingly) assume that an executable stack may be required for
## those sources, if not told explicitly that it isn't.
## Neither specifying this per source (e.g. via .section .note.GNU-stack,"",...), nor
## per toolchain flags (e.g. as' --noexecstack) turned out to be portable across our
## supported platforms, toolchains, and different versions of the latter (some even
## producing the opposite result).
## Find needed build flags by running a few tests; use default if none result in "rw-".
#
#RWXTESTPREFIX="rwxtest" # @@@ put this maybe all in Makefile.generic? out of source builds?
#for s in S s ; do (
# cd "$BLDTOP"
# # asm test file, with main and _main for portability.
# (echo '.text';(echo '.globl main';echo 'main:') | sed 'p;s/m/_m/') > $RWXTESTPREFIX.$s
#
# # Check var to be used, which depends on inference rules of this platform. E.g. ASFLAGS is only common on GNU, and
# # on some other platforms only CFLAGS is the only one used, others use AFLAGS with cc and thus need -Wa,... Check
# # makes use of the config written so far, so use '+=' to not overwrite vars.
# for f in "" "ASFLAGS+=-Wa,--noexecstack" "ACFLAGS+=-Wa,--noexecstack" "AFLAGS+=--noexecstack" "AFLAGS+=-Wa,--noexecstack" "CFLAGS+=-Wa,--noexecstack"; do
# # dummy makefile triggering inference rules, reflecting dyncall's build
# make -f - <<MAKEFILE
#include $C
#$f
## Force dependency via .o, to avoid .[sS].out rules that might be set - also set command as not all platforms set .o.out
#$RWXTESTPREFIX.out: $RWXTESTPREFIX.o
# \${CC} \${CFLAGS} \${LDFLAGS} $RWXTESTPREFIX.o \${LDLIBS} -o $RWXTESTPREFIX.out
#MAKEFILE
#
# # Check what stack of a built test binary would result in.
## @@@ add xxd hexdump based versions for when objdump is not available; also check for those if we deal with ELF files
## @@@ maybe also limit to ELF files
# STACKFLAGS=`(which objdump && objdump -p $RWXTESTPREFIX.out) | sed -e '/STACK/bx' -e 'd' -e ':x' -e 'N' -e 's/^.*flags[ \t]\([^ \t]*\).*/\1/'`
# rm $RWXTESTPREFIX.out $RWXTESTPREFIX.o
# if [ "$STACKFLAGS" = "rw-" ]; then
# printf "$f\n"
# break
# fi
#
# done
#
# rm $RWXTESTPREFIX.$s
#
#) done 2>&1 | grep '^[ASC]\+FLAGS.*noexecstack$' | uniq >>$C
# Generate all makefiles needed
FILES=`( cd $SRCTOP ; find . -name "Makefile.generic" )`
for FILE in $FILES ; do
SRCFILE="$SRCTOP/$FILE"
BLDFILE="$BLDTOP/$FILE"
SRCDIR=`dirname $SRCFILE`
BLDDIR=`dirname $BLDFILE`
mkdir -p "$BLDDIR"
cat <<EOF >$BLDDIR/Makefile
VPATH = $SRCDIR
include $BLDTOP/Makefile.config
include \${VPATH}/Makefile.generic
EOF
done
echo "Configuration written to $C"