# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, # 2001, 2002, 2003 Free Software Foundation, Inc. # # This file is part of DejaGnu. # # DejaGnu is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # This file was written by Rob Savoye. (rob@welcomehome.org) # this contains a list of gcc options and their respective directories. # # Find the pieces of libgloss for testing the GNU development tools # needed to link a set of object files into an executable. # This usually means setting the -L and -B paths correctly. # proc libgloss_link_flags { args } { global target_cpu global srcdir # libgloss doesn't work native if [isnative] { return "" } # if we're on a remote host, we can't search for the file, so we can only # use an installed compiler, so we don't add any paths here. if [is_remote host] { return "" } set gccpath "[get_multilibs]" # map the target_cpu to the proper libgloss directory. unfortunately, these # directory names are hardcoded into libgloss. switch -glob -- $target_cpu { "sparc86x" { set cpu sparc } "sparclite" { set cpu sparc } "sparclet" { set cpu sparc } "sparc64*" { set cpu sparc } "hppa*" { set cpu pa } "mips*" { set cpu mips } "powerpc*" { set cpu rs6000 } "d10v*" { set cpu libnosys } "xscale*" { set cpu arm } default { set cpu $target_cpu } } set gloss_srcdir "" # look for the libgloss srcdir sp we can find the linker scripts set gloss_srcdir [lookfor_file ${srcdir} libgloss/$cpu] # set the proper paths for gcc if the target subdir exists, else assume we # have no libgloss support for this target. if { $gloss_srcdir == "" } { return "" } if [file exists $gccpath/libgloss/$cpu] { verbose "Libgloss path is $gccpath/libgloss/$cpu" 2 return "-B$gccpath/libgloss/$cpu/ -L$gccpath/libgloss/$cpu -L$gloss_srcdir" } else { verbose -log "No libgloss support for this target." 2 return "" } } # There aren't any, but we'll be orthogonal here. proc libgloss_include_flags { args } { return "" } # # Find the newlib libraries in the current source tree. # proc newlib_link_flags { args } { global tool_root_dir # libgloss doesn't work native if [isnative] { return "" } # if we're on a remote host, we can't search for the file, so we can only # use an installed compiler, so we don't add any paths here. if [is_remote host] { return "" } set ld_script_path [lookfor_file ${tool_root_dir} "ld/ldscripts"] if { $ld_script_path != "" } { set result "-L[file dirname $ld_script_path]" } else { set result "" } set gccpath "[get_multilibs]" verbose "Looking for $gccpath/newlib" if [file exists $gccpath/newlib] { verbose "Newlib path is $gccpath/newlib" return "$result -B$gccpath/newlib/ -L$gccpath/newlib" } else { verbose "No newlib support for this target" return "$result" } } proc newlib_include_flags { args } { global srcdir if [isnative] { return "" } if [is_remote host] { return "" } set gccpath "[get_multilibs]" if [file exists $gccpath/newlib] { verbose "Newlib path is $gccpath/newlib" set newlib_dir [lookfor_file ${srcdir} newlib/libc/include/assert.h] if { ${newlib_dir} != "" } { set newlib_dir [file dirname ${newlib_dir}] } return " -isystem $gccpath/newlib/targ-include -isystem ${newlib_dir}" } else { verbose "No newlib support for this target" } } proc libio_include_flags { args } { global srcdir global tool_root_dir if [is_remote host] { return "" } set gccpath "[get_multilibs]" if { $gccpath == "" } { set gccpath "$tool_root_dir" } set libio_bin_dir [lookfor_file ${gccpath} libio/_G_config.h] # linux doesn't build _G_config.h and the test above fails, so # we search for iostream.list too. if { $libio_bin_dir == "" } { set libio_bin_dir [lookfor_file ${gccpath} libio/iostream.list] } set libio_src_dir [lookfor_file ${srcdir} libio/Makefile.in] if { $libio_bin_dir != "" && $libio_src_dir != "" } { set libio_src_dir [file dirname ${libio_src_dir}] set libio_bin_dir [file dirname ${libio_bin_dir}] return " -isystem ${libio_src_dir} -isystem ${libio_bin_dir}" } else { return "" } } proc libio_link_flags { args } { if [is_remote host] { return "" } set gccpath "[get_multilibs]" set libio_dir [lookfor_file ${gccpath} libio/libio.a] if { $libio_dir != "" } { return "-L[file dirname ${libio_dir}]" } else { return "" } } proc g++_include_flags { args } { global srcdir global target_alias if [is_remote host] { return "" } set gccpath [get_multilibs] set libio_dir "" set flags "" set dir [lookfor_file ${srcdir} libg++] if { ${dir} != "" } { append flags " -isystem ${dir} -isystem ${dir}/src" } set dir [lookfor_file ${srcdir} libstdc++-v3] if { ${dir} != "" } { append flags " -isystem ${dir}/include -isystem ${dir}/include/std" append flags " -isystem ${dir}/include/c_std -isystem ${dir}/libsupc++" } set dir [lookfor_file ${gccpath} libstdc++-v3] if { ${dir} != "" } { append flags " -isystem ${dir}/include -isystem ${dir}/include/${target_alias}" } set dir [lookfor_file ${srcdir} libstdc++] if { ${dir} != "" } { append flags " -isystem ${dir} -isystem ${dir}/stl" } return "$flags" } proc g++_link_flags { args } { global srcdir global ld_library_path set gccpath [get_multilibs] set libio_dir "" set flags "" set ld_library_path "." if { $gccpath != "" } { if [file exists "${gccpath}/lib/libstdc++.a"] { append ld_library_path ":${gccpath}/lib" } if [file exists "${gccpath}/libg++/libg++.a"] { append flags "-L${gccpath}/libg++ " append ld_library_path ":${gccpath}/libg++" } if [file exists "${gccpath}/libstdc++/libstdc++.a"] { append flags "-L${gccpath}/libstdc++ " append ld_library_path ":${gccpath}/libstdc++" } if [file exists "${gccpath}/libstdc++-v3/src/.libs/libstdc++.a"] { append flags "-L${gccpath}/libstdc++-v3/src/.libs " append ld_library_path ":${gccpath}/libstdc++-v3/src/.libs" } if [file exists "${gccpath}/libiberty/libiberty.a"] { append flags "-L${gccpath}/libiberty " } if [file exists "${gccpath}/librx/librx.a"] { append flags "-L${gccpath}/librx " } } else { global tool_root_dir set libgpp [lookfor_file ${tool_root_dir} libg++] if { $libgpp != "" } { append flags "-L${libgpp} " append ld_library_path ":${libgpp}" } set libstdcpp [lookfor_file ${tool_root_dir} libstdc++] if { $libstdcpp != "" } { append flags "-L${libstdcpp} " append ld_library_path ":${libstdcpp}" } set libiberty [lookfor_file ${tool_root_dir} libiberty] if { $libiberty != "" } { append flags "-L${libiberty} " } set librx [lookfor_file ${tool_root_dir} librx] if { $librx != "" } { append flags "-L${librx} " } } return "$flags" } proc libstdc++_include_flags { args } { global srcdir global target_alias if [is_remote host] { return "" } set gccpath [get_multilibs] set libio_dir "" set flags "" set dir [lookfor_file ${srcdir} libstdc++-v3] if { ${dir} != "" } { append flags " -isystem ${dir}/include -isystem ${dir}/include/std" append flags " -isystem ${dir}/include/c_std -isystem ${dir}/libsupc++" } set gccpath [get_multilibs] set dir [lookfor_file ${gccpath} libstdc++-v3] if { ${dir} != "" } { append flags " -isystem ${dir}/include -isystem ${dir}/include/${target_alias}" } set dir [lookfor_file ${srcdir} libstdc++] if { ${dir} != "" } { append flags " -isystem ${dir} -isystem ${dir}/stl" } return "$flags" } proc libstdc++_link_flags { args } { global srcdir global ld_library_path set gccpath [get_multilibs] set libio_dir "" set flags "" if { $gccpath != "" } { if [file exists "${gccpath}/libstdc++/libstdc++.a"] { append flags "-L${gccpath}/libstdc++ " append ld_library_path ":${gccpath}/libstdc++" } if [file exists "${gccpath}/libiberty/libiberty.a"] { append flags "-L${gccpath}/libiberty " } if [file exists "${gccpath}/librx/librx.a"] { append flags "-L${gccpath}/librx " } } else { global tool_root_dir set libstdcpp [lookfor_file ${tool_root_dir} libstdc++] if { $libstdcpp != "" } { append flags "-L${libstdcpp} " append ld_library_path ":${libstdcpp}" } set libiberty [lookfor_file ${tool_root_dir} libiberty] if { $libiberty != "" } { append flags "-L${libiberty} " } set librx [lookfor_file ${tool_root_dir} librx] if { $librx != "" } { append flags "-L${librx} " } } return "$flags" } # # Get the list of directories and -m options for gcc. This is kinda bogus that # generic testing software needs support for gcc hardwired in, but to make # testing the GNU tools work right, there didn't seem to be any other way. # proc get_multilibs { args } { global target_alias global board global board_info # if we're on a remote host, we can't search for the file, so we can only # use an installed compiler, so we don't add any paths here. if [is_remote host] { return "" } if [info exists board] { set target_board $board } else { set target_board [target_info name] } if { [llength $args] == 0 } { if [board_info $target_board exists multitop] { return "[board_info $target_board multitop]" } set board_info($target_board,multitop) "" } if { [board_info $target_board exists compiler] } { set compiler [board_info $target_board compiler] } else { set compiler [find_gcc] } if { $compiler == "" } { return "" } foreach x "$compiler" { if [regexp "^-B" "$x"] { regsub "^-B" "$x" "" comp_base_dir set comp_base_dir [file dirname $comp_base_dir] break } } regexp "/.* " $compiler compiler set compiler [string trimright $compiler " "] verbose "compiler is $compiler" if { [which $compiler] == 0 } { return "" } if { [llength $args] > 0 } { set mopts [lindex $args 0] } else { if { [board_info $target_board exists multilib_flags] } { set mopts [board_info $target_board multilib_flags] } else { set mopts "" } } set default_multilib [exec $compiler --print-multi-lib] set default_multilib [lindex $default_multilib 0] set extra [string trimleft $default_multilib ".;@@"] # extract the options and their directory names as know by gcc foreach i "[exec $compiler --print-multi-lib]" { if {$extra != ""} { # string trimright would do the wrong thing if we included # the leading @@ in $extra set i [string trimright $i $extra] set i [string trimright $i "@@"] } set opts "" set dir "" regexp -- "\[a-z0-9=/\.-\]*;" $i dir set dir [string trimright $dir "\;@"] regexp -- "\;@*\[\@a-zA-Z0-9=/\.-\]*" $i opts set opts [split [string trimleft $opts "\;@@"] "@@"] lappend multilibs "$dir {$opts }" # If args contains arguments don't use the first one as # multilib option unless it qualifies as a multilib option. if { [llength $args] > 0 } { set override_opt [lindex $args 0] foreach j $opts { if {$j == $override_opt} { set mopts $override_opt } } } } regsub "^-" $mopts "" moptions regsub -all " -" $moptions " " dirty_moptions set moptions "" foreach x [split $dirty_moptions " "] { if { $x != "" && [lsearch -exact $moptions $x] < 0 } { lappend moptions $x } } if ![info exists comp_base_dir] { set comp_base_dir [file dirname [file dirname [file dirname [file dirname [file dirname [exec $compiler --print-prog-name=cc1]]]]]] } # search for the top level multilib directory set multitop [lookfor_file "${comp_base_dir}" "${target_alias}"] if { $multitop == "" } { set multitop [lookfor_file "${comp_base_dir}" "libraries"] if { $multitop == "" } { set multitop "[lookfor_file ${comp_base_dir} gcc/xgcc]" if { $multitop != "" } { set multitop [file dirname [file dirname $multitop]] } else { return "" } } } set gccpath [eval exec "$compiler" --print-multi-directory $mopts] set gccpath [lindex $gccpath 0] if { $gccpath != "" } { verbose "GCC path is $gccpath" if { [llength $args] == 0 } { set board_info($target_board,multitop) "$multitop/$gccpath" } return "$multitop/$gccpath" } # extract the MULTILIB_MATCHES from dumpspecs set multimatches "" set lines [split [exec $compiler -dumpspecs] "\n"] for {set i 0} {$i <= [llength $lines] - 1} {incr i 1} { if {"*multilib_matches:" == "[lindex $lines $i]"} { set multimatches [lindex $lines [expr $i + 1]] break } } # if we find some if {$multimatches != ""} { # Split it into a list of pairs. If an moptions are the first # of a pair, then replace it with the second. If an moption # is not in multimatches, we assume it's not a multilib option set splitmatches [split $multimatches ";"] set multimatches "" foreach i $splitmatches { lappend multimatches [split $i " "] } verbose "multimatches: $multimatches" 3 verbose "options before multimatches: $moptions" 3 set toptions $moptions set moptions "" foreach i $toptions { foreach j $multimatches { verbose "comparing [lindex $j 0] == $i" 3 if {[lindex $j 0] == $i} { lappend moptions [lindex $j 1] } } } verbose "options after multimatches: $moptions" 3 } # make a list of -m options from the various compiler config variables set gccpath "" # compare the lists of gcc options with the list of support multilibs verbose "Supported multilibs are: $multilibs" 3 set best 0 foreach i "$multilibs" { set hits 0 set opts [lindex $i 1] if { [llength $opts] <= [llength $moptions] } { foreach j "$moptions" { # see if all the -m options match any of the multilibs verbose "Looking in $i for $j" 3 if { [lsearch -exact $opts $j] >= 0 } { incr hits } } if { $hits > $best } { verbose "[lindex $i 0] is better, using as gcc path" 2 set gccpath "[lindex $i 0]" set best $hits } } } if ![info exists multitop] { return "" } verbose "gccpath is $gccpath" 3 if [file exists $multitop/$gccpath] { verbose "GCC path is $multitop/$gccpath" 3 if { [llength $args] == 0 } { set board_info($target_board,multitop) "$multitop/$gccpath" } return "$multitop/$gccpath" } else { verbose "GCC path is $multitop" 3 if { [llength $args] == 0 } { set board_info($target_board,multitop) "$multitop" } return "$multitop" } } proc find_binutils_prog { name } { global tool_root_dir if ![is_remote host] { set file [lookfor_file $tool_root_dir $name] if { $file == "" } { set file [lookfor_file $tool_root_dir ${name}-new] } if { $file == "" } { set file [lookfor_file $tool_root_dir binutils/$name] } if { $file == "" } { set file [lookfor_file $tool_root_dir binutils/${name}-new] } if { $file != "" } { set NAME "$file" } else { set NAME [transform $name] } } else { set NAME [transform $name] } return $NAME } proc find_gcc {} { global tool_root_dir if ![is_remote host] { set file [lookfor_file $tool_root_dir xgcc] if { $file == "" } { set file [lookfor_file $tool_root_dir gcc/xgcc] } if { $file != "" } { set CC "$file -B[file dirname $file]/" } else { set CC [transform gcc] } } else { set CC [transform gcc] } return $CC } proc find_gcj {} { global tool_root_dir if ![is_remote host] { set file [lookfor_file $tool_root_dir gcj] if { $file == "" } { set file [lookfor_file $tool_root_dir gcc/gcj] } if { $file != "" } { set CC "$file -B[file dirname $file]/" } else { set CC [transform gcj] } } else { set CC [transform gcj] } return $CC } proc find_g++ {} { global tool_root_dir if ![is_remote host] { set file [lookfor_file $tool_root_dir g++] if { $file == "" } { set file [lookfor_file $tool_root_dir gcc/g++] } if { $file != "" } { set CC "$file -B[file dirname $file]/" } else { set CC [transform g++] } } else { set CC [transform g++] } return $CC } proc find_g77 {} { global tool_root_dir if ![is_remote host] { set file [lookfor_file $tool_root_dir g77] if { $file == "" } { set file [lookfor_file $tool_root_dir gcc/g77] } if { $file != "" } { set CC "$file -B[file dirname $file]/" } else { set CC [transform g77] } } else { set CC [transform g77] } return $CC } proc find_nm {} { global tool_root_dir set NM "" if ![is_remote host] { set NM [lookfor_file $tool_root_dir nm-new] if {$NM == ""} { set NM [lookfor_file $tool_root_dir binutils/nm-new] } } if { $NM == ""} { set NM [transform nm] } return $NM } proc process_multilib_options { args } { global board global board_variant_list global is_gdb_remote set is_gdb_remote 0 if [board_info $board exists multilib_flags] { return } eval add_multilib_option $args set multilib_flags "" foreach x $board_variant_list { regsub -all "^\[ \t\]*" "$x" "" x regsub -all "\[ \t\]*$" "$x" "" x if { $x == "" } { continue } case $x in { { aout } { set_board_info obj_format "a.out" } { elf } { set_board_info obj_format "elf" } { pe } { set_board_info obj_format "pe" } { ecoff } { set_board_info obj_format "ecoff" } { stabs } { set_board_info debug_flags "-gstabs" } { dwarf2 } { set_board_info debug_flags "-gdwarf2" } { gdb:*=* } { regsub "^gdb:\[^=\]*=(.*)$" "$x" "\\1" value regsub "^gdb:(\[^=\]*)=.*$" "$x" "\\1" variable set_board_info $variable "$value" } { gdb*remote } { set is_gdb_remote 1 } { little*endian el EL } { append multilib_flags " -EL" } { big*endian eb EB } { append multilib_flags " -EB" } { "soft*float" } { append multilib_flags " -msoft-float" } { "-*" } { append multilib_flags " $x" } default { append multilib_flags " -m$x" } } } set_board_info multilib_flags $multilib_flags } proc add_multilib_option { args } { global board_variant_list if ![info exists board_variant_list] { set board_variant_list "" } set board_variant_list [concat $args $board_variant_list] } proc find_gas { } { global tool_root_dir set AS "" if ![is_remote host] { set AS [lookfor_file $tool_root_dir as-new] if { $AS == "" } { set AS [lookfor_file $tool_root_dir gas/as-new] } } if { $AS == "" } { set AS [transform as] } return $AS } proc find_ld { } { global tool_root_dir set LD "" if ![is_remote host] { set LD [lookfor_file $tool_root_dir ld-new] if { $LD == "" } { set LD [lookfor_file $tool_root_dir ld/ld-new] } } if { $LD == "" } { set LD [transform ld] } return $LD } proc build_wrapper { gluefile } { global libdir global tool if [target_info exists wrap_m68k_aout] { set flags "additional_flags=-DWRAP_M68K_AOUT" set result "" } elseif [target_info exists uses_underscores] { set flags "additional_flags=-DUNDERSCORES" set result "-Wl,-wrap,_exit -Wl,-wrap,__exit -Wl,-wrap,_main -Wl,-wrap,_abort" } else { set flags "" if [target_info exists is_vxworks] { set flags "additional_flags=-DVXWORKS" set result "-Wl,-wrap,exit -Wl,-wrap,main -Wl,-wrap,abort" set result "-Wl,-wrap,exit -Wl,-wrap,_exit -Wl,-wrap,main -Wl,-wrap,abort" } else { set result "-Wl,-wrap,exit -Wl,-wrap,_exit -Wl,-wrap,main -Wl,-wrap,abort" } } if [target_info exists wrap_compile_flags] { lappend flags "additional_flags=[target_info wrap_compile_flags]" } if { [target_compile ${libdir}/testglue.c ${gluefile} object $flags] == "" } { set gluefile [remote_download host ${gluefile} ${tool}_tg.o] return [list $gluefile $result] } else { return "" } } proc winsup_include_flags { args } { global srcdir if [isnative] { return "" } if [is_remote host] { return "" } set gccpath "[get_multilibs]" if [file exists $gccpath/winsup] { verbose "Winsup path is $gccpath/winsup" set winsup_dir [lookfor_file ${srcdir} winsup/include/windows.h] if { ${winsup_dir} != "" } { set winsup_dir [file dirname ${winsup_dir}] return " -isystem ${winsup_dir}" } } verbose "No winsup support for this target" } # # Find the winsup libraries in the current source tree. # proc winsup_link_flags { args } { # libgloss doesn't work native if [isnative] { return "" } # if we're on a remote host, we can't search for the file, so we can only # use an installed compiler, so we don't add any paths here. if [is_remote host] { return "" } set gccpath "[get_multilibs]" verbose "Looking for $gccpath/winsup" if [file exists $gccpath/winsup] { verbose "Winsup path is $gccpath/newlib" return "-B$gccpath/winsup/ -L$gccpath/winsup" } else { verbose "No winsup support for this target" return "" } }