#!/usr/bin/env bash # # IRIX-MIPSpro-wrapper, Copyright 2008,2009 Stuart Shelton # # This program is free software: you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # # IRIX-MIPSpro-wrapper: A tool to mangle binutils arguments to # automagically insert the library paths and includes required # to build software successfully in a prefix-portage environment. # # Required tools: # /bin/uname, /sbin/hinv, tr, grep, cut, GNU sed, sort, head # # Version 20090212.1 # #set -o xtrace # # Try to confirm that essential GNU versions of tools are available... # sed -r -h &>/dev/null case $? in 2) # SGI sed? echo -e "\nWARNING: SGI sed (rather than GNU sed) seems to first in your \$PATH" echo " Disabling wrapper" echo MIPSPRO_WRAPPER=0 ;; 4) # GNU sed? : ;; *) # Not a clue! echo -e "\nWARNING: Unknown sed found - here be dragons" echo " Please check your \$PATH" echo ;; esac # # Environment variables which will affect operation... # wrapper="${MIPSPRO_WRAPPER:-1}" debug="${MIPSPRO_DEBUG:-0}" verbose="${MIPSPRO_VERBOSE:-0}" allownostd="${MIPSPRO_ALLOWNOSTD:-0}" mangle="${MIPSPRO_MANGLE:-1}" permissive="${MIPSPRO_PERMISSIVE:-1}" abort="${MIPSPRO_ABORT:-0}" # These should be auto-detected, but you may wish to change # OLIMIT or MIPSPRO_OPT. MIPSPRO_PLATFORM="${MIPSPRO_PLATFORM:-$( /bin/uname -m | \ tr [:upper:] [:lower:] )}" MIPSPRO_CPU="${MIPSPRO_CPU:-$( /sbin/hinv -c processor | \ grep ^CPU | cut -d" " -f 3 | tr [:upper:] [:lower:] )}" MIPSPRO_ISA="${MIPSPRO_ISA:-mips4}" MIPSPRO_ABI="${MIPSPRO_ABI:--n32}" OLIMIT="${OLIMIT:-8192}" OPTIMISE="${MIPSPRO_OPT:--O2}" # # Change nothing below here... # tool="$( basename "$0" )" name="IRIX-MIPSpro-wrapper" function die() { echo >&2 "$@" exit 1 } # die() function ifverbose() { (( verbose )) && echo -e "$name: $*" >&2 return $(( ! verbose )) } # ifverbose() function ifdebug() { (( debug )) && echo -e "\n$name$*\n" >&2 return $(( ! debug )) } # ifdebug() # FIXME for broken sys-libs/db test "$tool" = "none" && exit 0 test "$tool" = "ranlib" && exit 0 if test "$USER" != "portage"; then echo -e "\nWARNING: Not using MIPSpro wrapper for non-portage build!" echo " Please check your \$PATH" wrapper=0 fi test -n "${EPREFIX}" || die "FATAL: \${EPREFIX} is not set, cannot continue" case $tool in cc|c89|c99|CC|ld) (( wrapper )) || exec "/bin/$tool" "$@" ;; cpp) ifdebug ": !!BUG!!: Incorrect use of legacy (non-ANSI)/Fortran cpp" >&2 (( wrapper )) || exec /lib/cpp "$@" ;; *) die "FATAL: Unknown utility \"$tool\"" ;; esac # Shortcut attempts to find the version (only) case "$( printf -- "$@" | sed -r 's/[[:space:]]//g' )" in -v|-dumpversion|-V) ifdebug ": Shortcutting wrapper for version-check" >&2 exec /bin/$tool -version ;; *) ifdebug ": No short-cut" >&2 ;; esac shopt -s extglob || die "FATAL: Cannot enable shell option 'extglob'," \ "is $( type -p bash ) really bash?" function main() { local input=( "$@" ) local -a output[] ifdebug ": input:\t$tool ${input[@]}" # NB: The same $output array is used throughout the following sub-functions # Pass 1 - Join arguments where possible # # (This code attempts to do this entirely in-shell, but could be greatly # simplified through the use of sed...) # function pass1() { local input=( "$@" ) local prefix expect argument local skip=0 squash=0 unset output for argument in "${input[@]}"; do case $argument in -v|-verbose|--verbose) verbose=1 ;; esac if test -n "$prefix"; then case $prefix in -Ofast=) expect="ip*" squash=1 ;; esac if test -n "$expect"; then case $argument in $expect) ifverbose "NOTICE: pass1: Found expected" \ "argument sequence $prefix $argument" if (( squash )); then prefix="$prefix$argument" else ifverbose "INFO: pass1: Adding unsquashable argument $prefix" output=( "${output[@]}" "${prefix}" ) prefix="$argument" fi unset argument unset expect squash=0 continue ;; *) ifverbose "INFO: pass1: Didn't find" \ "anticipated follow-on argument, adding $prefix" output=( "${output[@]}" "${prefix}" ) unset prefix unset expect squash=0 esac else ifdebug ": DEBUG: pass1: Squashing \"$prefix $argument\"" argument="$prefix$argument" unset prefix fi fi # NB: -L is a synonym for -nostdlib, but -Ldir is the same as -L dir # so we need to know whether the following argument is an option # -I has different meanings to the compiler and linker (where it # must be a stand-alone option) so don't squash it # if ! (( skip )); then case $argument in -D|-J|-l|-U|-W|-Y) prefix="$argument" ;; -G) prefix="$argument" expect="[0-9]*" squash=1 ;; -g) prefix="$argument" expect="[0-3s]*" squash=1 ;; -L) prefix="$argument" expect="[^-]*" squash=1 ;; -Ofast) prefix="$argument" expect="=*" squash=1 ;; --) skip=1 ;; esac fi test -z "$prefix" && output=( "${output[@]}" "${argument}" ) done test -n "$prefix" && output=( "${output[@]}" "${prefix}" ) } # pass1() function checkcppflags() { local input=( "$@" ) local skip argument swallow local found=1 local result=0 unset output # Check for unknown arguments... # while (( found )); do found=0 skip=0 swallow=0 if [ -n "$output" ]; then input=( "${output[@]}" ) unset output fi for argument in "${input[@]}"; do if ! (( skip )) && ! (( swallow )); then case $argument in -W*([fbalR])p*([fbalR]),*) local arguments="$( printf -- "$argument" | \ sed 's!^-W[fbalR]*p[fbalR]*,!!' | \ sed 's!,-! -!g' )" local newarguments for newarguments in ${arguments}; do output=( "${output[@]}" "${newarguments}" ) done unset newarguments unset arguments # Now we have that, let's go around again... # found=1 skip=1 ;; --) output=( "${output[@]}" "${argument}" ) skip=1 ;; # These options are correct for MIPSpro 7.4.4m # Earlier verions may only support a subset, but there # should be no false negatives. # -C|-D*|-I*|-M|-max_rec_depth\=+([0-9])|-MDtarget|-MDupdate?(,*)|-P|-U*) output=( "${output[@]}" "${argument}" ) ;; -*) # Try to catch some common issues with passing # C(XX)FLAGS to cpp... case $argument in *) if (( permissive )); then ifverbose "WARNING: cpp: Unrecognised preprocessor option \"$argument\" passed" output=( "${output[@]}" "${argument}" ) else ifverbose "WARNING: cpp: Unrecognised preprocessor option \"$argument\" dropped" (( abort )) && exit 1 fi result=1 ;; esac ;; *) output=( "${output[@]}" "${argument}" ) ;; esac elif (( swallow )); then ifverbose "WARNING: cpp: Dropping follow-on argument \"$argument\"" swallow=0 else output=( "${output[@]}" "${argument}" ) fi done done return $result } # checkcppflags() function checkldflags() { local input=( "$@" ) local argument skip swallow local found=1 local result=0 unset output # Check for unknown arguments... # while (( found )); do found=0 skip=0 swallow=0 if [ -n "$output" ]; then input=( "${output[@]}" ) unset output fi for argument in "${input[@]}"; do if ! (( skip )) && ! (( swallow )); then case $argument in -W*([pfbaR])l*([pfbaR]),*) local arguments="$( printf -- "$argument" | \ sed 's!^-W[pfbaR]*l[pfbaR]*,!!' | \ sed 's!,-! -!g' )" local newarguments for newarguments in ${arguments}; do output=( "${output[@]}" "${newarguments}" ) done unset newarguments unset arguments # Now we have that, let's go around again... # found=1 skip=1 ;; --) output=( "${output[@]}" "${argument}" ) skip=1 ;; -L|-nostdlib) if (( allownostd )); then output=( "${output[@]}" "${argument}" ) else ifverbose "WARNING: ld: $argument passed to $tool, option dropped" result=1 fi ;; # These options are correct for MIPSpro 7.4.4m # Earlier verions may only support a subset, but there should be no false negatives. # Note that the -V (version) option also attempts to link objects, so shouldn't receive special treatment # -B?(direct)|-cckr|-cxx|-l*|-L*|-std|-no_archive|-u| \ -?(not)all|-exclude|-from|-make_cmdfile|-MDignore|-MDupdate?(,*)|-objectlist| \ -aoutkeep|-f|-?(no)info|-m|-M|-show?(_unref)|-split_common|-v|-V|-y*| \ -LD_MSG:*|-allow_missing|-demangle|-?(dont_)warn_unused|-ignore_unresolved|-no_unresolved|-wall|-woff| \ -s|-x| \ -?(n)32|-64|-abi|-call_shared|-elf|-mips[2-4]|-?(non_)shared|-r| \ -d|-D*([0-9])|-elsmap|-elspec|-G*([0-9])|-?(no)ivpad|-LD_LAYOUT:*|-n|-N|-rdata_writable|-rdata_shared| \ -T*([0-9a-fA-F])|-Xlocal|-z| \ -LD_DYNAMIC\:rhf_mips_flags\=*|-?(default_)delay_load|-e|-exact_version|-exports?(_file)| \ -exported_symbol|-fini|-force_load|-full_transitive_link|-hiddens_file|-hidden_symbol|-hides|-I| \ -ignore_minor|-ignore_version|-init|-no_library_replacement|-no_rqs|-?(no_)transitive_link| \ -require_minor|-rpath|-set_version| \ -mmap|-read| \ -allow_jump_at_eop|-no_jump_at_eop| \ -check_registry|-update_registry|-create_registry| \ -_SYSTYPE_SVR4|-o|-VS| \ -Wx,-G) output=( "${output[@]}" "${argument}" ) ;; -a) output=( "${output[@]}" "-non_shared" ) ;; -ajeop) output=( "${output[@]}" "-allow_jump_at_eop" ) ;; -dn) output=( "${output[@]}" "-non_shared" ) ;; -dy) output=( "${output[@]}" "-call_shared" ) ;; -h) output=( "${output[@]}" "-shared" "-soname" ) ;; -hides_files) output=( "${output[@]}" "-hiddens_file" ) ;; -none) output=( "${output[@]}" "-notall" ) ;; -o32) output=( "${output[@]}" "-32" ) ;; -OPT:reorg_common) output=( "${output[@]}" "-ivpad" ) ;; -rpath,*) output=( "${output[@]}" "$( printf -- "${argument}" | sed -r 's!-rpath,(.*)$!-rpath \1!' )" ) ;; -soname) output=( "${output[@]}" "-shared" "${argument}" ) ;; -SYSTYPE_SVR4) output=( "${output[@]}" "-_SYSTYPE_SVR4" ) ;; -U) output=( "${output[@]}" "-ignore_unresolved" ) ;; -w) output=( "${output[@]}" "-wall" ) ;; -Xlocaldata) output=( "${output[@]}" "-Xlocal" ) ;; -?(no)count|-gpinfo|-quickstart_info| \ -Xnobsschange|-X?(no)sortbss|-X?(nd)block|-Xblockrange|-Xndlocaldata|-X?(no)alignbss|-Xcachemisalign| \ -Xcache?(line)size|-Xdefmovemax|-Xsetalign|-Xdebug) ifverbose "WARNING: ld: Obsolete option \"$argument\" dropped" result=1 ;; -*) # Try to catch some common issues with passing C(XX)FLAGS to ld... case $argument in -diag_*) if (( permissive )); then ifverbose "WARNING: ld: Invalid linker option \"$argument\" passed" output=( "${output[@]}" "${argument}" ) else ifverbose "WARNING: ld: Invalid linker option \"$argument\" dropped" swallow=1 fi result=1 ;; *) if (( permissive )); then ifverbose "WARNING: ld: Unrecognised linker option \"$argument\" passed" output=( "${output[@]}" "${argument}" ) else ifverbose "WARNING: ld: Unrecognised linker option \"$argument\" dropped" (( abort )) && exit 1 fi result=1 ;; esac ;; *) output=( "${output[@]}" "${argument}" ) ;; esac elif (( swallow )); then ifverbose "WARNING: ld: Dropping follow-on to invalid argument \"$argument\"" swallow=0 else output=( "${output[@]}" "${argument}" ) fi done done return $result } # checkldflags() function checkcflags() { local input=( "$@" ) local argument local -a progress[] local skip=0 local result=0 unset output # Check for unknown arguments... # for argument in "${input[@]}"; do if ! (( skip )); then case $argument in -?(-)help) exec "/bin/$tool" "-help" ;; -?(-)version) exec "/bin/$tool" "-version" ;; --) output=( "${output[@]}" "${argument}" ) skip=1 ;; -nostdinc) if (( allownostd )); then output=( "${output[@]}" "${argument}" ) else ifverbose "WARNING: cc/CC: $argument passed to $tool, option dropped" fi result=1 ;; # These options are correct for MIPSpro 7.4.4m # Earlier verions may only support a subset, but there should be no false negatives. # -?([on])32|-64| \ -all|-anach|-?(x)ansi|-cckr|-ansi[EW]|-apo|-apokeep|-apolist|-ar|-?(no_)auto_include| \ -bigp_off|-bigp_on|-brief_diagnostics| \ -c|-cfront|-clist|-CLIST:*|-common| \ -D*|-DEBUG:*|-diag_error|-diag_remark|-diag_suppress|-diag_warning|-dollar| \ -E|-EP|-P| \ -fb|-fb_create|-fb_opt|-FE:*|-float?(_const)|-fullwarn| \ -G+([0-9])|-g?([023])?(slim)|-I*|-INLINE:*|-IPA:*|-ignore_suffix| \ -J*([0-9])| \ -KPIC| \ -L*|-l*|-LANG:*|-LIST:*|-LNO:*| \ -M|-MDupdate?(,*)|-MDtarget|-mips[1-4]|-MP:*|-mp?(list)| \ -nocpp|-noinline|-none| \ -o|-O?([0-3])|-Ofast?(=ip+([0-9]))|-OPT:*| \ -pca|-pcakeep|-pcalist|-pch|-pedantic|-?(no_)prelink|-pta?(ll)|-ptnone|-ptused|-ptv| \ -quiet_prelink| \ -r|-r[458]k|-r[458]000|-r1[0246]k|-r1[0246]000| \ -S|-?(non_)shared|-show|-signed| \ -TARG:*|-TENV:*|-trapuv| \ -U*|-use_readonly_const|-use_readwrite_const|-use_command|-use_suffix| \ -v|-version| \ -w?(off)| \ -Xcpluscomm|-x| \ -Y|-Y+([pfbalRISL]),*) output=( "${output[@]}" "${argument}" ) ;; -c99) if [ "$tool" = "c89" ]; then ifverbose "WARNING: c89: Cannot run this front-end in C99 mode, \"$argument\" dropped" result=1 else output=( "${output[@]}" "${argument}" ) fi ;; # NB: -W by itself should have been squashed by pass1 -W+([pfbalR]),*|-w?(off)) # We need to be careful here, because we don't want to clobber $output case $argument in -W*([fbalR])p*([fbalR]),*) progress=( "${output[@]}" ) unset output checkcppflags ${argument} for arguments in "${output[@]}"; do local checkedargument="$( printf -- "$arguments" | \ sed -r 's/(^|\s)-/\1-Wp,-/g' | \ sed -r 's/(^|\s)([^-])/\1-Wp,\2/g' )" local newarguments for newarguments in ${checkedargument}; do progress=( "${progress[@]}" "${newarguments}" ) done unset checkedargument done unset arguments output=( "${progress[@]}" ) unset progress ;; -W*([pfbaR])l*([pfbaR]),*) progress=( "${output[@]}" ) unset output checkldflags ${argument} for arguments in "${output[@]}"; do local checkedargument="$( printf -- "$arguments" | \ sed -r 's/(^|\s)-/\1-Wl,-/g' | \ sed -r 's/(^|\s)([^-])/\1-Wl,\2/g' )" local newarguments for newarguments in ${checkedargument}; do progress=( "${progress[@]}" "${newarguments}" ) done unset checkedargument done unset arguments output=( "${progress[@]}" ) unset progress ;; *) # There should be no linker or preprocessor options remaining, # so we'll silently pass remaining values... output=( "${output[@]}" "${argument}" ) ;; esac ;; -|--) # Pass these through regardless, so we don't get tripped up below... output=( "${output[@]}" "${argument}" ) ;; -*) if (( permissive )); then ifverbose "WARNING: cc/CC: Unrecognised compiler option \"$argument\" passed" output=( "${output[@]}" "${argument}" ) else # Some builds throw LDFLAGS and CFLAGS in together, without a -Wl to denote what # they actually are... progress=( "${output[@]}" ) unset output checkldflags "${argument}" &>/dev/null if (( $? )); then # No idea what it is ;) ifverbose "WARNING: cc/CC: Unrecognised compiler option \"$argument\" dropped" output=( "${progress[@]}" ) unset progress (( abort )) && exit 1 else # The argument appears to be an LDFLAG # ... but don't prepend -Wl, since we don't know whether it takes further # arguments. Additionally, some options such as '-shared' need to be common # to compiler and linker. ifverbose "WARNING: cc/CC: Unrecognised compiler option \"$argument\" passed as ld option" output=( "${progress[@]}" "${output[@]}" ) unset progress fi fi result=1 ;; *) output=( "${output[@]}" "${argument}" ) ;; esac else output=( "${output[@]}" "${argument}" ) fi done unset progress local lastarg currentarg for argument in "${output[@]}"; do currentarg="$argument" if [ -n "$lastarg" ]; then case "$lastarg" in -Wl,-rpath*) if [ -n "$( printf -- "$lastarg $currentarg" | grep -- '-Wl,-rpath -Wl,' )" ]; then argument="$( printf -- "$lastarg $currentarg" | sed -r 's!-Wl,-rpath -Wl,!-Wl,-rpath,!g' )" progress=( "${progress[@]}" "${argument}" ) unset lastarg currentarg fi ;; *) progress=( "${progress[@]}" "${lastarg}" ) unset lastarg ;; esac fi lastarg="$currentarg" done [ -n "$currentarg" ] && progress=( "${progress[@]}" "${currentarg}" ) unset lastarg currentarg output=( "${progress[@]}" ) unset progress return $result } # checkcflags() function checkcxxflags() { local input=( "$@" ) checkcflags "${input[@]}" return $? } # checkcxxflags # Pass 2 - Set default values and filter out GNU arguments # function pass2() { local input=( "$@" ) local argument skip progress local skip=0 unset output for argument in "${input[@]}"; do (( ! skip )) && case $argument in --) skip=1 ;; -32|-o32|-n32|-64) if test "$argument" != "${MIPSPRO_ABI}"; then ifverbose "WARNING: pass2: ABI $argument upgraded to ${MIPSPRO_ABI}" argument="${MIPSPRO_ABI}" fi ;; # We don't really support O32 code, so this is entirely spurious -L/usr/lib) ifverbose "WARNING: pass2: Library option $argument dropped" unset argument ;; -mips?) if test "$argument" != "-${MIPSPRO_ISA}"; then ifverbose "WARNING: pass2: ISA $argument upgraded to -${MIPSPRO_ISA}" argument="-${MIPSPRO_ISA}" fi ;; esac (( ! skip )) && case $tool in cpp|cc|c89|c99|CC) case $tool in cpp) case $argument in # FIXME for x11-libs/libX11 -undef) # This is a hack to work around the libX11 'cpp' checks... ifverbose "WARNING: pass2: GNU option $argument changed to -Uunix (as libX11 workaround)" argument="-Uunix" ;; -traditional) # This is a hack to work around the libX11 'cpp' checks... ifverbose "WARNING: pass2: GNU option $argument dropped" unset argument continue ;; esac ;; cc|c89|c99) case $argument in -anach|-ansiE|-ansiW|-?(no_)auto_include|-cfront|-FE:*|-g?([023])slim|-J*([0-9])|-?(no_)prelink|-pch|-pta?(ll)|-ptnone|-ptused|-ptv|-quiet_prelink) ifverbose "WARNING: pass2: CC-only option $argument dropped" unset argument continue ;; esac ;; CC) case $argument in -?(x)ansi|-cckr|-clist|-CLIST:*|-nocpp|-pca|-pcakeep|-pcalist) ifverbose "WARNING: pass2: cc-only option $argument dropped" unset argument continue ;; esac ;; esac case $argument in -MD) ifverbose "WARNING: pass2: -MD does not exist on IRIX, $argument changed to -M -MDupdate" ifverbose "WARNING: pass2: Output is approximated!" output=( "${output[@]}" "-M" "-MDupdate" ) unset argument ;; -MF) ifverbose "WARNING: pass2: -MF does not exist on IRIX, $argument changed to -MDupdate" argument="-MDupdate" ;; -MT) # Although not documented -MDtarget is a valid cc/CC option! # (it is documented for cpp, but this is supposed to be for legacy # non-ANSI usage only...) ifverbose "WARNING: pass2: -MT does not exist on IRIX, $argument changed to -MDtarget" argument="-MDtarget" ;; esac [ "$tool" != "cpp" ] && case $argument in -fpic|-fPIC) ifverbose "WARNING: pass2: -KPIC is default on IRIX, $argument dropped" unset argument continue ;; -g?([023])?(slim)) ifverbose "WARNING: pass2: Debug level $argument dropped" unset argument continue ;; # We generally need our standard includes... # -nostdinc) if ! (( allownostd )); then ifverbose "WARNING: pass2: Standard includes are required, $argument dropped" unset argument continue fi ;; # Some programs seem keen on uber-optimisation... # -O?([0-3])) # Remember the lowest value of this argument... [ "$OPTIMISE" = "-O" ] && OPTIMISE="-O2" [ "$argument" = "-O" ] && argument="-O2" ifverbose "WARNING: pass2: Changing optimisation to lowest of \"$OPTIMISE\" and \"$argument\"..." OPTIMISE="$( for argument in $OPTIMISE $argument; do printf -- "$argument\n"; done | sort -g | head -n 1 )" unset argument ifverbose "INFO: pass2: Optimisation level is now $OPTIMISE" ;; -rdynamic) # I don't know what the MIPSpro equivalent is! ifverbose "WARNING: pass2: $argument equivalent is unknown, argument dropped" unset argument continue ;; -W+([pfbalR]),*) # Do nothing here - it's merely a placeholder to make the # match below easier... : ;; -Werror-implicit-function-declaration) ifverbose "WARNING: pass2: GNU option $argument changed to -diag_error 1196" output=( "${output[@]}" "-diag_error 1196" ) unset argument continue ;; -W*) # For -Wall, -Wstrict-prototypes, etc. # ifverbose "WARNING: pass2: GNU option $argument changed to -fullwarn" argument="-fullwarn" ;; --version) ifverbose "WARNING: pass2: GNU option $argument changed to -version" argument="-version" ;; -v) # For cosmetic reasons only: -v may not be what was # intended # argument="-show" ;; esac ;; ld) case $argument in # We generally need our standard libraries... # -L|-nostdlib) if ! (( allownostd )); then ifverbose "WARNING: pass2: Standard libraries are required, $argument dropped" unset argument continue fi ;; -version|--version) argument="-V" ;; esac ;; esac test -n "$argument" && output=( "${output[@]}" "${argument}" ) done # Common options with different meanings: # -x # case $tool in cc|c89|c99) checkcflags "${output[@]}" ;; CC) checkcxxflags "${output[@]}" ;; cpp) checkcppflags "${output[@]}" ;; ld) checkldflags "${output[@]}" ;; esac } # pass2() # Pass 3 - Ensure standard arguments are present # function pass3() { local input=( "$@" ) local prefix options argument item found skip pass quotepass drop quiet unset output if (( mangle )); then case "$tool" in cc|c99|CC) options="$options -TARG:isa=${MIPSPRO_ISA}:platform=${MIPSPRO_PLATFORM}:processor=${MIPSPRO_CPU} -${MIPSPRO_CPU}" options="$options -float_const -use_readonly_const -TENV:zeroinit_in_bss=ON" options="$options -OPT:fast_io=ON:Olimit=${OLIMIT}:reorg_common=ON:swp=ON" options="$options -LNO:auto_dist=ON:fusion_peeling_limit=8:gather_scatter=2" (( verbose )) && \ options="$options -Wl,-v" options="$options -Wl,-s -Wl,-x -Wl,${MIPSPRO_ABI} -Wl,-${MIPSPRO_ISA}" options="$options -Wl,-allow_jump_at_eop -Wl,-rpath,${EPREFIX}/usr/lib:${EPREFIX}/lib" options="$options -L${EPREFIX}/usr/lib -L${EPREFIX}/lib" options="$options -woff 1174,1183,1185,1552,3968,3970" options="$options -diag_error 1035" case "$tool" in # Preprocessor needs -c99 for headers such as stdint.h # This may generate incorrect results when compiling with # c89, but there's no way to detect if this will be the case # if cpp is invoked directly. # Likewise, we assume that cc really wants C99 compliance. cpp|cc|c99) options="-D__attribute__(x)=\"\" $options" options="-c99 $options" ;; CC) # Enable prelinker concurrent compilation #options="-J4 $options" options="$options -FE:eliminate_duplicate_inline_copies:template_in_elf_section" ;; esac ;; ld) prefix="-L${EPREFIX}/usr/lib -L${EPREFIX}/lib" (( verbose )) && options="$options -v" options="$options -s -x -allow_jump_at_eop -rpath ${EPREFIX}/usr/lib:${EPREFIX}/lib" ;; esac else case "$tool" in cc|c99|CC) (( verbose )) && options="$options -Wl,-v" options="$options -Wl,-rpath,${EPREFIX}/usr/lib:${EPREFIX}/lib" options="$options -L${EPREFIX}/usr/lib -L${EPREFIX}/lib" ;; ld) prefix="-L${EPREFIX}/usr/lib -L${EPREFIX}/lib" (( verbose )) && options="$options -v" options="$options -rpath ${EPREFIX}/usr/lib:${EPREFIX}/lib" ;; esac fi if test "$tool" != "cpp"; then # -I (alone) is also a linker option, so we can't pass the modified # include path when $tool is being invoked as a linker. case "$tool" in ld) : ;; *) options="$options -I${EPREFIX}/usr/include" ;; esac input=( "${MIPSPRO_ABI}" "-${MIPSPRO_ISA}" "${prefix}" "${input[@]}" ) for argument in $options; do input=( "${input[@]}" "$argument" ) done # If no optimisation options are set, use ${OPTIMISE} # NB: -O is equivalent to -O2 # No -O is equivalent to -O0 - so technically this is cheating... if test "$tool" != "ld"; then found=0 for argument in "${input[@]}"; do case $argument in -O?) found=1 break ;; esac done (( found )) || input=( "${OPTIMISE}" "${input[@]}" ) fi fi local lastarg currentarg for argument in "${input[@]}"; do currentarg="$argument" if [ -n "$lastarg" ]; then case "$lastarg" in -diag_*) if [ -n "$( printf -- "$lastarg $currentarg" | grep -E -- '^-diag_[^ ]+ [0-9]+' )" ]; then argument="$( printf -- "$lastarg $currentarg" | sed -r 's!^(-diag_[^ ]+) ([0-9]+)!\1 \2!g' )" output=( "${output[@]}" "${argument}" ) unset lastarg currentarg fi ;; -rpath*) if [ -n "$( printf -- "$lastarg $currentarg" | grep -E -- '^-rpath[, ][^ ]+' )" ]; then argument="$( printf -- "$lastarg $currentarg" | sed -r 's!^-rpath([, ])([^ ]+)!-rpath \2!g' )" output=( "${output[@]}" "${argument}" ) unset lastarg currentarg fi ;; -woff*) if [ -n "$( printf -- "$lastarg $currentarg" | grep -E -- '^-woff [0-9,]+' )" ]; then argument="$( printf -- "$lastarg $currentarg" | sed -r 's!^-woff ([0-9,]+)!-woff \1!g' )" output=( "${output[@]}" "${argument}" ) unset lastarg currentarg fi ;; *) output=( "${output[@]}" "${lastarg}" ) unset lastarg ;; esac fi lastarg="$currentarg" done [ -n "$currentarg" ] && output=( "${output[@]}" "${currentarg}" ) unset lastarg currentarg input=( "${output[@]}" ) unset output skip=0 pass=0 quotepass=0 drop=0 quiet=0 for argument in "${input[@]}"; do # Eliminate duplicate arguments before any optional "--" only test "$argument" = "--" && skip=1 if ! (( skip )); then if (( quotepass )); then pass=0 drop=0 ifverbose "NOTICE: pass3: Quoted string <$argument> passed..." output=( "${output[@]}" "$argument" ) continue elif (( pass )); then pass=0 drop=0 if [ -n "$( printf -- "$argument" | grep -- "^-" )" ]; then ifverbose "NOTICE: pass3: Passing follow-on option <$argument>" else ifverbose "NOTICE: pass3: Passing follow-on argument <$argument>" fi output=( "${output[@]}" "$argument" ) continue elif (( drop )); then drop=0 if [ -n "$( printf -- "$argument" | grep -- "^-" )" ]; then ifverbose "NOTICE: pass3: Passing follow-on option <$argument>" else ifverbose "NOTICE: pass3: Dropping follow-on argument <$argument>" fi unset argument continue fi found=0 case $argument in -c) ifverbose "NOTICE: pass3: Option <$argument> will always be passed..." quiet=1 ;; # FIXME for dev-lang/tcl -DTCL_PACKAGE_PATH=\"*) if [ -z "$( printf -- "$argument" | grep '"$' )" ]; then ifverbose "NOTICE: pass3: Correcting trailing space in define when building Tcl" argument="$( printf -- "$argument" | sed 's/$/"/' )" drop=1 fi ;; -MD*) ifverbose "NOTICE: pass3: Option <$argument> will always be passed..." pass=1 quiet=1 ;; -o) ifverbose "NOTICE: pass3: Option <$argument> will always be passed..." pass=1 quiet=1 ;; ?(-W*([pfbaR])l*([pfbaR]),)-rpath) pass=1 ;; \"|\'|\`) ifverbose "NOTICE: pass3: Quote character <$argument> passed..." quiet=1 ;; *\'*\'|*\"*\"|*\`*\`) if [ -n "$( printf -- "$argument" | grep -- "^-" )" ]; then ifverbose "NOTICE: pass3: Option with quoted string <$argument> passed..." else ifverbose "NOTICE: pass3: Argument with quoted string <$argument> passed..." fi quotedpass=0 quiet=1 ;; \'*|\"*|\`*) ifverbose "NOTICE: pass3: Start of quoted string <$argument> passed..." quotedpass=1 quiet=1 ;; *\'|*\"|*\`) ifverbose "NOTICE: pass3: End of quoted string <$argument> passed..." quotedpass=0 quiet=1 ;; -*) for item in "${output[@]}"; do if test "$item" = "$argument"; then ifverbose "WARNING: pass3: Dropping duplicate option <$argument>" found=1 break fi done ;; esac if ! (( found )); then (( quiet )) || case $argument in -*) ifverbose "NOTICE: pass3: Passing option <$argument>" ;; *) [ -n "$argument" ] && ifverbose "NOTICE: pass3: Passing argument <$argument>" ;; esac [ -n "$argument" ] && output=( "${output[@]}" "$argument" ) quiet=0 fi else case $argument in -*) ifverbose "NOTICE: pass3: Passing all remaining, option <$argument>" ;; *) [ -n "$argument" ] && ifverbose "NOTICE: pass3: Passing all remaining, argument <$argument>" ;; esac [ -n "$argument" ] && output=( "${output[@]}" "$argument" ) fi done unset input for argument in "${output[@]}"; do if [ -n "$( printf -- "$argument" | grep -E -- '^-diag_[^ ]+ [0-9]+$|^-rpath [^ ]+$|^-woff [0-9,]+' )" ]; then input=( "${input[@]}" "$( printf -- "$argument" | cut -d" " -f 1 )" "$( printf -- "$argument" | cut -d" " -f 2- )" ) else input=( "${input[@]}" "${argument}" ) fi done output=( "${input[@]}" ) } # pass3() # At each stage, function output is stored in $output output=( "${input[@]}" ) unset input pass1 "${output[@]}" pass2 "${output[@]}" # Ensure that we actually have some options left to work with... [ -n "$( printf -- "${output[@]}" | tr -s [:space:] | grep -v "^ *$" )" ] || exit 1 pass3 "${output[@]}" # This path is weird, because /bin is actually a symlink to /usr/bin test "$tool" = "cpp" && tool="../../lib/cpp" ifdebug ": output:\t/bin/$tool" "${output[@]}" exec "/bin/$tool" "${output[@]}" } # main() ifdebug ": INFO: IMpw: Received input \"$@\"" ifdebug ": INFO: IMpw: Optimising at no more than $OPTIMISE" main "$@" exit 0 # vi:set syntax=sh ts=4: