# Copyright (C) 1992-2016 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 3 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. # This file was written by Rob Savoye . # 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 } "aarch64*" { set cpu aarch64 } 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 [file join $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 [file join $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 [file join $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}] } # Note - we use -isystem rather than -I because newlib contains # system header files. This is especially important for the # limits.h header which makes use of the #include_next directive. # #include_next will generate error messages from GCC if compiling # in strict ANSI mode or if another limits.h header cannot be found. # When it is included via -isystem these things do not happen. 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}] # Note - unlike the newlib_include_flags proc above we use the -I # switch to specify the include paths. This is because these headers # are not system headers, and if -isystem were to be used GCC would # generate an implicit extern "C" { ... } surrounding them. This # will break targets which do not define NO_IMPLICIT_EXTERN_C. return " -I${libio_src_dir} -I${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} != "" } { # See comment in libio_include_flags about using -I. append flags " -I${dir} -I${dir}/src" } set dir [lookfor_file ${srcdir} libstdc++-v3] if { ${dir} != "" } { append flags " -I${dir}/include -I${dir}/include/std -I${dir}/include/c_std -I${dir}/libsupc++" } set dir [lookfor_file ${gccpath} libstdc++-v3] if { ${dir} != "" } { append flags " -I${dir}/include -I${dir}/include/${target_alias}" } set dir [lookfor_file ${srcdir} libstdc++] if { ${dir} != "" } { append flags " -I${dir} -I${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 [file join ${gccpath} lib libstdc++.a]]} { append ld_library_path ":${gccpath}/lib" } if {[file exists [file join ${gccpath} libg++ libg++.a]]} { append flags "-L${gccpath}/libg++ " append ld_library_path ":${gccpath}/libg++" } if {[file exists [file join ${gccpath} libstdc++ libstdc++.a]]} { append flags "-L${gccpath}/libstdc++ " append ld_library_path ":${gccpath}/libstdc++" } if {[file exists [file join ${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 [file join ${gccpath} libiberty libiberty.a]]} { append flags "-L${gccpath}/libiberty " } if {[file exists [file join ${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} != "" } { # See comment in libio_include_flags about using -I. append flags " -I${dir}/include -I${dir}/include/std -I${dir}/include/c_std -I${dir}/libsupc++" } set gccpath [get_multilibs] set dir [lookfor_file ${gccpath} libstdc++-v3] if { ${dir} != "" } { append flags " -I${dir}/include -I${dir}/include/${target_alias}" } set dir [lookfor_file ${srcdir} libstdc++] if { ${dir} != "" } { append flags " -I${dir} -I${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 [file join ${gccpath} libstdc++ libstdc++.a]]} { append flags "-L${gccpath}/libstdc++ " append ld_library_path ":${gccpath}/libstdc++" } if {[file exists [file join ${gccpath} libiberty libiberty.a]]} { append flags "-L${gccpath}/libiberty " } if {[file exists [file join ${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 [file join $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 xg++] if { $file == "" } { set file [lookfor_file $tool_root_dir gcc/xg++] } if { $file == "" } { set file [lookfor_file $tool_root_dir g++] } if { $file != "" } { set CC "$file -B[file dirname $file]/" } else { set CC [transform g++] } } else { set CC [transform g++] } return $CC } proc find_gdc {} { global tool_root_dir if {![is_remote host]} { set file [lookfor_file $tool_root_dir gdc] if { $file == "" } { set file [lookfor_file $tool_root_dir gcc/gdc] } if { $file != "" } { set CC "$file -B[file dirname $file]/" } else { set CC [transform gdc] } } else { set CC [transform gdc] } 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_gfortran {} { global tool_root_dir if {![is_remote host]} { set file [lookfor_file $tool_root_dir gfortran] if { $file == "" } { set file [lookfor_file $tool_root_dir gcc/gfortran] } if { $file != "" } { set CC "$file -B[file dirname $file]/" } else { set CC [transform gfortran] } } else { set CC [transform gfortran] } return $CC } proc find_gnatmake {} { global tool_root_dir if {![is_remote host]} { set file [lookfor_file $tool_root_dir gnatmake] if { $file == "" } { set file [lookfor_file $tool_root_dir gcc/gnatmake] } if { $file != "" } { set root [file dirname $file] set CC "$file -I$root/ada/rts --GCC=$root/xgcc --GNATBIND=$root/gnatbind --GNATLINK=$root/gnatlink -cargs -B$root -largs --GCC=$root/xgcc -B$root -margs" } else { set CC [transform gnatmake] } } else { set CC [transform gnatmake] } 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 } switch -glob -- $x { "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,_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 [file join $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}] # See comment in libio_include_flags about using -I. return " -I${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 [file join $gccpath winsup]]} { verbose "Winsup path is $gccpath/newlib" return "-B$gccpath/winsup/ -L$gccpath/winsup" } else { verbose "No winsup support for this target" return "" } }