: # Glenn Fowler # AT&T Research # # @(#)C probe (AT&T Research) 2010-08-20 # # probe [ -d ] c-compiler-path [ attributes ] # # common C probe preamble for the tool specific probes # # NOTE: some cc -E's do syntax analysis! # # probe_* are first eval'd and then attempted from left to right # probe_binding="-dy -dn -Bdynamic -Bstatic '-Wl,-ashared -Wl,+s' -Wl,-aarchive -call_shared -non_shared -dynamic -static -bshared -bstatic '' -static" probe_env="CC_OPTIONS CCOPTS LD_OPTIONS LDOPTS LIBPATH LPATH" probe_include="stdio.h iostream.h complex.h ctype.h plot.h stdarg.h varargs.h ranlib.h hash.h sys/types.h stab.h cmath cstdio iostream string" probe_longlong="long 'long long'" probe_longlong_t="__int64_t _int64_t __int64 _int64 int64" probe_l="l yyreject m sin mopt sin" probe_lxx="C exit ++ exit g++ exit" probe_ppprefix="a n" probe_size="size" probe_src="cxx C cc c" probe_sa=".sa" probe_sd=".dll .lib .dll .x" probe_sdb=".pdb" probe_so=".dylib .sl .so" probe_symprefix="_" probe_verbose="'-v -v' '-# -#' '-d -d' -dryrun '-V -V'" probe_version="--version -V -version -v" # # the following are set by the preamble for the tool specific probe # cc=cc debug= dir=. dll=.dll dynamic= exe=exe executable="test -x" hosted= ifs=${IFS-' '} obj=o ppenv= ppopt= predef= prepred= sa= sd= sdb= so= sov= static= stdlib= stdpp= suffix_command= if test "" != "$TMPDIR" -a -d "$TMPDIR" then tmpdir=$TMPDIR else tmpdir=/tmp fi tmpdir=$tmpdir/probe$$ undef="define defined elif else endif error if ifdef ifndef include line pragma undef __STDC__ __STDPP__ __ARGC__ __BASE__ __BASE_FILE__ __DATE__ __FILE__ __FUNCTION__ __INCLUDE_LEVEL__ __LINE__ __PATH__ __TIME__ __VERSION__" version_flags= version_stamp= version_string= # # constrain the environment # DISPLAY= LC_ALL=C export DISPLAY LC_ALL # # now the common probes # while : do case $1 in -d) debug=1 ;; -*) set ''; break ;; *) break ;; esac shift done cc=$1 case $cc in [\\/]*|[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:\\*) ;; *) echo "Usage: $0 [ -d ] c-compiler-path [ attributes ]" >&2 exit 1 ;; esac ATTRIBUTES= eval $2 _probe_PATH=$PATH PATH=/usr/bin:/bin:$PATH case $0 in *[\\/]*) dir=`echo $0 | sed -e 's,[\\/][\\/]*[^\\/]*\$,,'` ;; esac $executable . 2>/dev/null || executable='test -r' case $SHELL in [\\/]*|[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:\\*) sh=$SHELL ;; *) sh=/bin/sh ;; esac trap 'code=$?; cd ..; rm -rf $tmpdir; exit $code' 0 1 2 3 mkdir $tmpdir cd $tmpdir exec 3>&1 4>&2 /dev/null 2>&1 (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0 ;; *) PS4='+$LINENO+ ' set -x ;; esac if (xxx=xxx; unset xxx) then UNSET=1 else UNSET= fi eval set x $probe_env while : do shift case $# in 0) break ;; esac eval x='$'$1 case $x in '') continue ;; esac case $1 in *PATH) _probe_export="$_probe_export $1='$x'" ;; esac case $UNSET in '') eval $1= export $1 ;; *) unset $1 ;; esac done if test -f "$dir/probe.ini" then . "$dir/probe.ini" IFS=$ifs fi mkdir suffix cd suffix for src in $probe_src do echo "int main(){return 0;}" > ../test.$src rm -f test* if $cc -c ../test.$src then set test.* if test -f "$1" then o="$*" mv $* .. for i in $o do if $cc -o test.exe ../$i then obj=`echo "$i" | sed -e 's,test.,,'` $executable test.exe || executable="test -r" set test* rm * if $cc -o test ../$i then rm $* set test.* if $executable "$1" then exe=`echo "$1" | sed -e 's,test.,,'` suffix_command=.$exe fi fi break 2 fi done fi fi done cd .. case $src in c) ;; *) echo '// ( int main() { class { public: int i; } j; j.i = 0; int k = j.i + 1; return k; }' > dialect.$src if $cc -c dialect.$src && $cc -o dialect.$exe dialect.$obj && $executable dialect.$exe then mv dialect.$src dialect.c rm -f dialect.$obj dialect.$exe if $cc -c dialect.c && $cc -o dialect.$exe dialect.$obj && $executable dialect.$exe then src=c else set x $cc while : do shift case $# in 0) break ;; esac case $1 in *=*) continue ;; esac case `echo $1 | sed -e 's,.*/,,'` in *CC*|*++*|*[xX][xX]*|*[pP][lL][uU][sS]*) ;; *) src=c ;; esac break done fi else src=c fi ;; esac set x x '(' 1 'int x;' 0 while : do shift shift case $# in [01]) break ;; esac rm -f test.$obj echo "$1" > test.$src $cc -c test.$src r=$? case $r in 0) test -f test.$obj || r=1 ;; *) r=1 ;; esac case $2:$r in 0:0) ;; 0:1) echo "$cc: not a C compiler: failed to compile \`\`$1''" >&4 exit 1 ;; 1:0) echo "$cc: not a C compiler: successfully compiled \`\`$1''" >&4 exit 1 ;; esac done hosttype=`package CC="$cc" || $SHELL -c "package CC='$cc'"` case $hosttype in *[Uu][Ss][Aa][Gg][Ee]:*) hosttype=`PATH=$_probe_PATH; export PATH; package CC="$cc" || $SHELL -c "package CC='$cc'"` ;; esac echo '#include int main(){printf("hello");return 0;}' > dynamic.$src echo 'extern int sfclose() { return 0; }' > fun.$src if $cc -c dynamic.$src && $cc -c fun.$src then eval set x $probe_so while : do shift case $# in 0) break ;; esac for i in foo junk do rm -f dynamic.$exe if $cc -L. -o dynamic.$exe dynamic.$obj -l$i then : "there's really a -l$i"? else rm -f dynamic.$exe cat fun.$obj > lib$i$1 $cc -L. -o dynamic.$exe dynamic.$obj -l$i && $executable dynamic.$exe x=$? rm lib$i$1 case $x in 0) so=$1 rm -f dynamic.$exe > lib$i$1.1 $cc -L. -o dynamic.$exe dynamic.$obj -l$i && $executable dynamic.$exe x=$? rm lib$i$1.1 case $x in 0) sov=1 ;; esac break 2 ;; *) break ;; esac fi done k= for i in "" .1 .2 .3 .4 .5 .6 .7 .8 .9 do rm -f dynamic.$exe > libc$1$i $cc -L. -o dynamic.$exe dynamic.$obj && $executable dynamic.$exe x=$? (cd ..; rm $tmpdir/libc$1$i) case $x in 0) ;; *) k=X$k case $k in XXX) break ;; esac ;; esac done case $k in XXX) so=$1 sov=1 break ;; ?*) so=$1 break ;; esac done rm -f dynamic.$exe if $cc -o dynamic.$exe dynamic.$obj 2>e && $executable dynamic.$exe then e=`wc -l e` maybe= eval set x x $probe_binding while : do shift shift case $# in 0) break ;; esac rm -f dynamic.$exe $cc -o dynamic.$exe $1 dynamic.$obj 2>e && $executable dynamic.$exe || continue case $1 in ?*) case $maybe in "") maybe=$1 ;; *) maybe=-- ;; esac ;; esac case `wc -l e` in $e) ;; *) continue ;; esac d=`ls -s dynamic.$exe` rm -f dynamic.$exe $cc -o dynamic.$exe $2 dynamic.$obj 2>e && $executable dynamic.$exe || continue case `wc -l e` in $e) ;; *) continue ;; esac case `ls -s dynamic.$exe` in $d) ;; *) dynamic=$1 static=$2 maybe= break ;; esac done case $maybe in ""|--) ;; *) rm -f dynamic.$exe if $cc -o dynamic.$exe $maybe dynamic.$obj 2>e && $executable dynamic.$exe then e=`wc -l e` if $cc -o dynamic.$exe $maybe-bogus-bogus-bogus dynamic.$obj 2>e && $executable dynamic.$exe then case `wc -l e` in $e) ;; *) dynamic=$maybe ;; esac else dynamic=$maybe fi fi ;; esac fi fi eval set x $probe_version shift for o in "$@" do if $cc $o > version.out 2>&1 then version_string=`sed -e '/ is /d' -e 's/;/ /g' version.out | sed -e 1q` case $version_string in ''|*[Ee][Rr][Rr][Oo][Rr]*|*[Ff][Aa][Tt][Aa][Ll]*|*[Ww][Aa][Rr][Nn][Ii][Nn][Gg]*|*[Oo][Pp][Tt][Ii][Oo][Nn]*) ;; *) version_flags=$o version_stamp=";VERSION;$o;$version_string;PATH;$cc" break ;; esac fi done case $version_stamp in '') eval set x $probe_version shift echo 'int main() { return 0; }' > version.i for o in "$@" do if $cc -c $o version.i > version.out 2>&1 then version_string=`sed -e '/ is /d' -e 's/;/ /g' version.out | sed -e 1q` case $version_string in ''|*[Ee][Rr][Rr][Oo][Rr]*|*[Ff][Aa][Tt][Aa][Ll]*|*[Ww][Aa][Rr][Nn][Ii][Nn][Gg]*|*[Oo][Pp][Tt][Ii][Oo][Nn]*) ;; *) version_flags=$o break ;; esac fi done ;; esac echo 'int main(){return 0;}' > hosted.$src $cc -o hosted.$exe hosted.$src && ./hosted.$exe && hosted=1 echo '#!'$sh' echo "" $@' > cpp chmod +x cpp case `./cpp -Dprobe` in *-Dprobe*) ;; *) cp /bin/echo cpp chmod u+w cpp ;; esac for prefix in $probe_ppprefix `echo $cc | sed -e '/cc\$/!d' -e 's,cc\$,,' -e 's,.*/,,'` do cp cpp ${prefix}cpp done echo "" > flags.$src echo '#pragma pp:version' > libpp.$src if test `realcppC=./cpp $cc -Dprobe -E flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 then ppenv='realcppC=${ppcmd}' elif test `cppC=./cpp $cc -Dprobe -E flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 then ppenv='cppC=${ppcmd}' elif test `_CPPNAME=./cpp $cc -Dprobe -E flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 then ppenv='_CPPNAME=${ppcmd}' elif test `_CPP=./cpp $cc -Dprobe -E flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 then ppenv='_CPP=${ppcmd}' elif test `$cc -Dprobe -E -%p+. flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 && test `$cc -Dprobe -E -%p+. flags.$src | wc -l` -eq 1 then ppopt='-%p+${ppdir}' elif test `$cc -Dprobe -E -Yp,. flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 then ppopt='-Yp,${ppdir}' elif test `$cc -Dprobe -E -Qpath $tmpdir flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 then ppopt='-Qpath ${ppdir}' elif test `$cc -Dprobe -E -tp -B./ flags.$src 2>err.out | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 -a ! -s err.out then ppopt='-tp -B${ppdir}/' elif test `$cc -Dprobe -E -B./ flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 then ppopt='-B${ppdir}/' elif test `$cc -Dprobe -E -tp -h./ -B flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 then ppopt='-tp -h${ppdir}/ -B' elif test `$cc -Dprobe -E -t p,./cpp flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 then ppopt='-t p,${ppcmd}' else { eval set x $probe_verbose shift for o in "$@" do $cc -E $o flags.$src done } 2>&1 | sed -e "s/['\"]//g" > cpp.out fi set x `sed -e 's,[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:\\\\,/,g' -e 's,\\\\,/,g' cpp.out` def= definclude="-I+C -I-H" stdinclude=$definclude case $hosted in "") usrinclude= ;; esac cmdinclude= while : do case $# in 0|1) break ;; esac shift case $1 in -A) case $2 in *\(*\)) shift prepred="$prepred `echo $1 | sed 's/\(.*\)(\(.*\))/\1 \2/'`" ;; esac ;; -A\(*\)) prepred="$prepred `echo $1 | sed 's/-A\(.*\)(\(.*\))/\1 \2/'`" ;; -[DI][-+][ABCDEFGHIJKLMNOPQRSTUVWXYZ]*) stdpp=1 case $1 in -I?[CH]) case $def in ?*) definclude="$definclude $1" ;; *) stdinclude="$stdinclude $1" ;; esac ;; -I-S*|-YI,*) usrinclude="`echo $1 | sed 's/....//'`" ;; -Y?,*) ;; -Y*) usrinclude="`echo $1 | sed 's/..//'`" ;; esac ;; -D) shift case $1 in [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*=*) predef="$predef `echo $1 | sed -e 's/=.*//'`" ;; [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*) predef="$predef $1" ;; esac ;; -Dprobe);; -D*) case $1 in -D[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*=*) predef="$predef `echo $1 | sed -e 's/^-D//' -e 's/=.*//'`" ;; -D[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*) predef="$predef `echo $1 | sed -e 's/^-D//'`" ;; esac ;; -I) shift case $1 in /*) case $def in ?*) definclude="$definclude $1" ;; *) stdinclude="$stdinclude $1" ;; esac cmdinclude="$cmdinclude $1" ;; esac ;; -I/*) f=`echo X$1 | sed 's/X-I//'` case $def in ?*) definclude="$definclude $f" ;; *) stdinclude="$stdinclude $f" ;; esac cmdinclude="$cmdinclude $f" ;; -U) shift undef="$undef $1" ;; -U*) undef="$undef `echo $1 | sed 's/^-U//'`" ;; flags.$src)def= ;; esac done stdinclude="$stdinclude $definclude" case " $stdinclude " in *\ $usrinclude\ *) case $usrinclude in /usr/include) usrinclude= ;; *) case " $stdinclude " in *\ /usr/include\ *) usrinclude= ;; *) usrinclude=/usr/include ;; esac ;; esac ;; esac tstinclude=`$cc -v -E flags.$src 2>&1 | sed -e '1,/[iI][nN][cC][lL][uU][dD][eE][ ]*<[.][.][.]>/d' -e '/^[eE][nN][dD] [oO][fF] [sS][eE][aA][rR][cC][hH]/,\$d'` j=$tstinclude case $j in */*) ;; *) j=$cmdinclude ;; esac tstinclude= good= nogood= c_hdr="stdio.h ctype.h" C_hdr="libc.h" for i in $j do if test -d "$i" then tstinclude="$tstinclude $i" h= for f in $c_hdr do if test -f "$i/$f" then case $i in */CC) nogood=1 ;; *) good=1 ;; esac else h="$h $f" fi done c_hdr=$h h= for f in $C_hdr do if test -f "$i/$f" then case $i in */CC) nogood=1 ;; *) good=1 ;; esac else h="$h $f" fi done C_hdr=$h fi done case $nogood in 1) good=0 ;; esac case $good in 1) case $c_hdr in ?*) bad=1 usrinclude=/usr/include set '' $tstinclude /usr/include ;; *) set '' $tstinclude ;; esac shift stdinclude=$* echo "#include " > include.$src $cc -E include.$src | sed -e '/# 1 "[\\/]/!d' -e 's,[^"]*",,' -e 's,[\\/][^\\/]*".*,,' -e 's,[\\/]sys,,' > include.out for f in `cat include.out` do if test -d "$f" then g=`echo $f | sed -e 's,[\\/][\\/]*[^\\/]*$,,'` case " $stdinclude " in *\ $f\ *|*\ $g\ *) ;; *) stdinclude="$stdinclude $f" case $f in /usr/include) usrinclude=$f ;; esac bad=1 ;; esac fi done ;; *) case $ppopt$ppenv in ?*) echo '#!'$sh' echo $VIRTUAL_ROOT | sed "s/:.*//"' > cpp chmod +x cpp ppcmd=cpp ppdir=. eval x='`'$ppenv '$'cc -E $ppopt flags.$src'`' case $x in ?*) tstinclude=$x/usr/include ;; esac cp /bin/echo cpp chmod u+w cpp ;; esac eval set x $probe_include while : do shift case $# in 0) break ;; esac echo "#include <$1>" > include.$src $cc -E include.$src done > include.out ccinclude= x=$stdinclude stdinclude= subinclude= for f in $x $tstinclude `sed -e 's,\\\\,/,g' -e 's,///*,/,g' -e 's,"[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:/,"/,g' -e '/^#[line ]*[0123456789][0123456789]*[ ][ ]*"[\\/]/!d' -e 's/^#[line ]*[0123456789][0123456789]*[ ][ ]*"\(.*\)[\\/].*".*/\1/' include.out | sort -u` do case $f in -*) ;; */) f=`echo $f | sed -e 's,//*\$,,'` ;; */.) f=`echo $f | sed -e 's,//*.\$,,'` ;; esac case $f in -I*) ;; */cc) ccinclude=1 ;; */sys) continue ;; */include/*/*) ;; */include/*) subinclude="$subinclude $f" continue ;; esac if test -d "$f" then case " $stdinclude " in *\ $f\ *) ;; *) stdinclude="$stdinclude $f" ;; esac fi done rm include.out case $ccinclude in ?*) eval set x $probe_include while : do shift case $# in 0) break ;; esac echo "#include " > include.$src if $cc -E include.$src > /dev/null then break fi done case $# in 0) ;; *) x=$stdinclude stdinclude= for f in $x do case $f in */cc) ;; *) stdinclude="$stdinclude $f" ;; esac done ;; esac ;; esac case $subinclude in ?*) for i in $subinclude do for j in $stdinclude do case $i in $j/*/*) ;; $j/*) both= eval set x $probe_include while : do shift case $# in 0) for k in $both do echo "#include <$k>" > include.$src $cc -E include.$src > include.out I=`grep -c $i/$k < include.out` J=`grep -c $j/$k < include.out` case $I:$J in 0:*) ;; *:0) stdinclude="$i $stdinclude" break ;; esac done continue 3 ;; esac if test -f $i/$1 then if test ! -f $j/$1 then break 2 fi both="$both $1" fi done ;; $j) continue 2 ;; esac done stdinclude="$i $stdinclude" done ;; esac { for i in $stdinclude do case $i in $usrinclude) ;; *) echo $i $i ;; esac done eval set x $probe_include while : do shift case $# in 0) break ;; esac echo "#include <$1>" > t.c p= for j in `$cc -E t.c | grep "$1" | sed -e 's,\\\\,/,g' -e 's,"[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:/,"/,g' -e '/^#[line ]*1[ ][ ]*"[\\/]/!d' -e 's/^#[line ]*1[ ][ ]*"\(.*\)[\\/].*".*/\1/'` do j=`echo $j | sed -e 's,///*,/,g' -e 's,/$,,'` case $p in ?*) echo $p $j ;; esac p=$j done done case $usrinclude in ?*) echo $usrinclude $usrinclude ;; esac } | tsort > tmp.tmp tstinclude=`cat tmp.tmp` bad= for i in $stdinclude do case " $tstinclude " in *" $i "*) ;; *) bad=1 break ;; esac done ;; esac case $bad in "") x=$stdinclude stdinclude= z= for i in $tstinclude do case " $x " in *" $i "*) stdinclude="$stdinclude $i" z=$i ;; esac done case $usrinclude in '') usrinclude=$z ;; esac ;; esac case $hosted in "") case $usrinclude in /usr/include) usrinclude= ;; esac ;; esac case $usrinclude in ?*) case " $stdinclude " in *\ $usrinclude\ *) x=$stdinclude stdinclude= for f in $x do case $f in $usrinclude) ;; *) stdinclude="$stdinclude $f" ;; esac done ;; esac ;; esac # drop dups -- they creep in somehow x=$stdinclude stdinclude= for f in $x do case " $stdinclude $usrinclude " in *" $f "*) ;; *) stdinclude="$stdinclude $f" ;; esac done