# libstdc++ "tool init file" for DejaGNU# Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.## This program 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.## 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, write to the Free Software# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA# 02110-1301, USA.# Define callbacks and load other libraries. This file is loaded relatively# early, and before any other file we write ourselves. "load_lib" will# find anything in the DejaGNU installation tree, or in our lib directory.# "load_gcc_lib" will search the core compiler's .exp collection instead.## The naming rule is that dg.exp looks for "tool-" and runtest.exp looks# for "tool_" when finding callbacks. Utility routines we define for# our callbacks begin with "v3-".## libstdc++_* callbacks we don't define, but could:# ..._option_help prints additional --help output# ..._option_proc (--foo) process our own options# ..._init (normal.exp) called once per test file# ..._finish bracketing function for libstdc++_init# ...-dg-prune removing output text, see top of system dg.exp## Useful hook: if ${hostname}_init exists, it will be called, almost# the last thing before testing begins. This can be defined in, e.g.,# ~/.dejagnurc or $DEJAGNU.proc load_gcc_lib { filename } {global srcdirload_file $srcdir/../../gcc/testsuite/lib/$filename}# system routinesload_lib dg.expload_lib libgloss.exp# compiler routines, then oursload_gcc_lib target-supports.expload_gcc_lib target-supports-dg.expload_lib prune.expload_lib dg-options.expload_gcc_lib target-libpath.expload_gcc_lib wrapper.exp# Useful for debugging. Pass the name of a variable and the verbosity# threshold (number of -v's on the command line).proc v3track { var n } {upvar $var valverbose "++ $var is $val" $n}# Called by v3-init below. "Static" to this file.proc v3-copy-files {srcfiles} {foreach f $srcfiles {if { [catch { set symlink [file readlink $f] } x] } then {remote_download target $f} else {if { [regexp "^/" "$symlink"] } then {remote_download target $symlink} else {set dirname [file dirname $f]remote_download target $dirname/$symlink}}}}# Called once, during runtest.exp setup.proc libstdc++_init { testfile } {global envglobal v3-sharedlibglobal srcdir blddir objdir tool_root_dirglobal cxx cxxflagsglobal includesglobal gluefile wrap_flagsglobal ld_library_pathglobal target_triplet# We set LC_ALL and LANG to C so that we get the same error# messages as expected.setenv LC_ALL Csetenv LANG Cset blddir [lookfor_file [get_multilibs] libstdc++-v3]set flags_file "${blddir}/scripts/testsuite_flags"v3track flags_file 2# If a test doesn't have special options, use DEFAULT_CXXFLAGS.# Use this variable if the behavior# 1) only applies to libstdc++ testing# 2) might need to be negated# In particular, some tests have to be run without precompiled# headers, or without assertions.global DEFAULT_CXXFLAGSif ![info exists DEFAULT_CXXFLAGS] then {set DEFAULT_CXXFLAGS ""# Host specific goo here.if { [string match "powerpc-*-darwin*" $target_triplet] } {append DEFAULT_CXXFLAGS " -multiply_defined suppress"}}v3track DEFAULT_CXXFLAGS 2# By default, we assume we want to run program images.global dg-do-what-defaultset dg-do-what-default run# Copy any required data files.v3-copy-files [glob -nocomplain "$srcdir/data/*.tst"]v3-copy-files [glob -nocomplain "$srcdir/data/*.txt"]# Locate libgcc.a so we don't need to account for different values of# SHLIB_EXT on different platformsset gccdir [lookfor_file $tool_root_dir gcc/libgcc.a]if {$gccdir != ""} {set gccdir [file dirname $gccdir]}v3track gccdir 3# Look for shared library. (ie libstdc++.so.)set v3-sharedlib 0set sharedlibdir [lookfor_file $blddir src/.libs/libstdc++.so]if {$sharedlibdir != ""} {if { [string match "*-*-linux*" $target_triplet] && [isnative] } {set v3-sharedlib 1verbose -log "shared library support detected"}}v3track v3-sharedlib 3# Compute what needs to be added to the existing LD_LIBRARY_PATH.if {$gccdir != ""} {set ld_library_path ""append ld_library_path ":${gccdir}"set compiler ${gccdir}/g++append ld_library_path ":${blddir}/src/.libs"if { [is_remote host] == 0 && [which $compiler] != 0 } {foreach i "[exec $compiler --print-multi-lib]" {set mldir ""regexp -- "\[a-z0-9=_/\.-\]*;" $i mldirset mldir [string trimright $mldir "\;@"]if { "$mldir" == "." } {continue}if { [llength [glob -nocomplain ${gccdir}/${mldir}/libgcc_s*.so.*]] >= 1 } {append ld_library_path ":${gccdir}/${mldir}"}}}set_ld_library_path_env_varsif [info exists env(LD_LIBRARY_PATH)] {verbose -log "LD_LIBRARY_PATH = $env(LD_LIBRARY_PATH)"}} else {set compiler [transform "g++"]}# Do a bunch of handstands and backflips for cross compiling and# finding simulators...if [is_remote host] {set header [remote_download host ${blddir}/testsuite/testsuite_hooks.h]if { $header == "" } {verbose -log "Unable to download ${blddir}/testsuite/testsuite_hooks.h to host."return "untested"}set cxx [transform "g++"]set cxxflags "-ggdb3"set includes "-I./"} else {# If we find a testsuite_flags file, we're testing in the build dir.if { [file exists $flags_file] } {set cxx [exec sh $flags_file --build-cxx]set cxxflags [exec sh $flags_file --cxxflags]set includes [exec sh $flags_file --build-includes]} else {set cxx [transform "g++"]set cxxflags "-g -O2 -D_GLIBCXX_ASSERT -fmessage-length=0"set includes "-I${srcdir}"# Guess at the location of the installed locale files.# (It would be nice if "gcc --print-file-name" could find# message files, but it cannot.)set absolute_cxx [which $cxx]if { $absolute_cxx != "" } {set localedir "[file dirname $absolute_cxx]/../share/locale"}set cxxflags "$cxxflags -DLOCALEDIR=\"$localedir\""}}# If a PCH file is available, use it. We must delay performing# this check until $cxx and such have been initialized because we# perform a test compilation. (Ideally, gcc --print-file-name would# list PCH files, but it does not.)global PCH_CXXFLAGSif ![info exists PCH_CXXFLAGS] then {set src "config[pid].cc"set f [open $src "w"]puts $f "int main () {}"close $fset lines [v3_target_compile $src "config[pid].o" object \"additional_flags=-include additional_flags=bits/stdc++.h"]if {$lines == "" } {set PCH_CXXFLAGS "-include bits/stdc++.h"} else {set PCH_CXXFLAGS ""}file delete $srcv3track PCH_CXXFLAGS 2}libstdc++_maybe_build_wrapper "${objdir}/testglue.o"}# Callback for cleanup routines.proc libstdc++_exit { } {global gluefile;if [info exists gluefile] {file_on_build delete $gluefile;unset gluefile;}}# Callback from system dg-test.proc libstdc++-dg-test { prog do_what extra_tool_flags } {# Set up the compiler flags, based on what we're going to do.switch $do_what {"preprocess" {set compile_type "preprocess"set output_file "[file rootname [file tail $prog]].i"}"compile" {set compile_type "assembly"set output_file "[file rootname [file tail $prog]].s"}"assemble" {set compile_type "object"set output_file "[file rootname [file tail $prog]].o"}"link" {set compile_type "executable"set output_file "./[file rootname [file tail $prog]].exe"}"run" {set compile_type "executable"# FIXME: "./" is to cope with "." not being in $PATH.# Should this be handled elsewhere?# YES.set output_file "./[file rootname [file tail $prog]].exe"# This is the only place where we care if an executable was# created or not. If it was, dg.exp will try to run it.remote_file build delete $output_file;}default {perror "$do_what: not a valid dg-do keyword"return ""}}set options ""if { $extra_tool_flags != "" } {verbose -log "extra_tool_flags are:"verbose -log $extra_tool_flagsif { [string first "-x c" $extra_tool_flags ] != -1 } {# Short-circut a bunch of complicated goo here for the# special case of compiling a test file as a "C" file, not# as C++: just use target_compile, instead of the usual# gimmicks.verbose -log "compiling and executing as C, not C++"set compile_type "executable"set output_file "./[file rootname [file tail $prog]].exe"remote_file build delete $output_file;lappend options "additional_flags=$extra_tool_flags"set comp_output [target_compile "$prog" "$output_file" "$compile_type" $options];set comp_output [ prune_g++_output $comp_output ];return [list $comp_output $output_file]} else {lappend options "additional_flags=$extra_tool_flags"}}# There is a libstdc++_compile made for us by default (via the tool-# and-target file), but the defaults are lacking in goodness.set comp_output [v3_target_compile "$prog" "$output_file" "$compile_type" $options];set comp_output [ prune_g++_output $comp_output ];return [list $comp_output $output_file]}# True if the library supports wchar_t.set v3-wchar_t 0# True if the library supports threads.set v3-threads 0# True if the library supports symbol versioning.set v3-symver 0# A string naming object files to be linked into all tests.set v3-test_objs ""# Called from libstdc++-dg-test above. Calls back into system's# target_compile to actually do the work.proc v3_target_compile { source dest type options } {global gluefileglobal wrap_flagsglobal cxxglobal cxxflagsglobal includesglobal blddirglobal v3-test_objsif { [target_info needs_status_wrapper] != "" && [info exists gluefile] } {lappend options "libs=${gluefile}"lappend options "ldflags=${wrap_flags}"}set cxx_final $cxxset cxxlibglossflags [libgloss_link_flags]set cxx_final [concat $cxx_final $cxxlibglossflags]set cxx_final [concat $cxx_final $cxxflags]set cxx_final [concat $cxx_final $includes]# Flag setting based on type argument.if { $type == "executable" } {# Link the support objects into executables.set cxx_final [concat $cxx_final ${v3-test_objs}]} else {if { $type == "sharedlib" } {# Don't link in anything.set type "executable"}}lappend options "compiler=$cxx_final"return [target_compile $source $dest $type $options]}# Build the support objects linked in with the libstdc++ tests. In# addition, set v3-wchar_t, v3-threads, v3-test_objs, and v3-symver# appropriately.proc v3-build_support { } {global srcdirglobal v3-wchar_tglobal v3-threadsglobal v3-test_objsglobal v3-symverglobal v3-sharedlib# Figure out whether or not the library supports certain features.set v3-wchar_t 0set v3-threads 0set v3-symver 0set v3-test_objs ""set config_src "config.cc"set f [open $config_src "w"]puts $f "#include <bits/c++config.h>"puts $f "#include <bits/gthr.h>"close $fset preprocessed [v3_target_compile $config_src "" \preprocess "additional_flags=-dN"]if { [string first "_GLIBCXX_USE_WCHAR_T" $preprocessed] != -1 } {verbose -log "wchar_t support detected"set v3-wchar_t 1}if { [string first "_GLIBCXX_SYMVER" $preprocessed] != -1 } {verbose -log "symbol versioning support detected"set v3-symver 1}if { [string first "__GTHREADS" $preprocessed] != -1 } {verbose -log "thread support detected"set v3-threads 1}# Build the support objects.set source_files \[list testsuite_abi.cc testsuite_allocator.cc testsuite_character.cc testsuite_hooks.cc ]foreach f $source_files {set object_file [file rootname $f].o# Compile with "-w" so that warnings issued by the compiler# do not prevent compilation.if { [v3_target_compile $srcdir/$f $object_file "object" \[list "incdir=$srcdir" "additional_flags=-w"]]!= "" } {error "could not compile $f"}append v3-test_objs "$object_file "}# Build the shared support objects.if { ${v3-sharedlib} == 1 } {set source_files \[list testsuite_shared.cc]foreach f $source_files {set object_file [file rootname $f].so# Compile with "-w" so that warnings issued by the compiler# do not prevent compilation.if { [v3_target_compile $srcdir/$f $object_file "sharedlib" \[list "incdir=$srcdir" "additional_flags=-w -shared -fPIC -DPIC"]]!= "" } {error "could not compile $f"}}}}proc check_v3_target_sharedlib { } {global v3-sharedlibreturn ${v3-sharedlib}}proc check_v3_target_namedlocale { } {global et_namedlocale_savedglobal et_namedlocale_target_nameglobal toolif { ![info exists et_namedlocale_target_name] } {set et_namedlocale_target_name ""}# If the target has changed since we set the cached value, clear it.set current_target [current_target_name]if { $current_target != $et_namedlocale_target_name } {verbose "check_v3_target_namedlocale: `$et_namedlocale_target_name'" 2set et_namedlocale_target_name $current_targetif [info exists et_namedlocale_saved] {verbose "check_v3_target_namedlocale: removing cached result" 2unset et_namedlocale_saved}}if [info exists et_namedlocale_saved] {verbose "check_v3_target_namedlocale: using cached result" 2} else {set et_namedlocale_saved 0# Set up, compile, and execute a C++ test program that tries to use# all the required named locales.set src nlocale[pid].ccset exe nlocale[pid].xset f [open $src "w"]puts $f "#include <locale>"puts $f "using namespace std;"puts $f "int main ()"puts $f "{"puts $f " try"puts $f " {"puts $f " locale(\"\");"puts $f " locale(\"de_DE\");"puts $f " locale(\"de_DE.ISO-8859-15@euro\");"puts $f " locale(\"de_DE@euro\");"puts $f " locale(\"en_HK\");"puts $f " locale(\"en_PH\");"puts $f " locale(\"en_US\");"puts $f " locale(\"en_US.ISO-8859-1\");"puts $f " locale(\"en_US.ISO-8859-15\");"puts $f " locale(\"en_US.UTF-8\");"puts $f " locale(\"es_ES\");"puts $f " locale(\"es_MX\");"puts $f " locale(\"fr_FR\");"puts $f " locale(\"fr_FR@euro\");"puts $f " locale(\"is_IS\");"puts $f " locale(\"is_IS.UTF-8\");"puts $f " locale(\"it_IT\");"puts $f " locale(\"ja_JP.eucjp\");"puts $f " locale(\"se_NO.UTF-8\");"puts $f " locale(\"ta_IN\");"puts $f " locale(\"zh_TW\");"puts $f " return 0;"puts $f " }"puts $f " catch(...)"puts $f " {"puts $f " return 1;"puts $f " }"puts $f "}"close $fset lines [v3_target_compile $src $exe executable ""]file delete $srcif [string match "" $lines] {# No error message, compilation succeeded.set result [${tool}_load "./$exe" "" ""]set status [lindex $result 0]remote_file build delete $exeverbose "check_v3_target_namedlocale: status is <$status>" 2if { $status == "pass" } {set et_namedlocale_saved 1}} else {verbose "check_v3_target_namedlocale: compilation failed" 2}}return $et_namedlocale_saved}proc check_v3_target_cxa_atexit { } {global et_cxa_atexitglobal et_cxa_atexit_target_nameglobal toolif { ![info exists et_cxa_atexit_target_name] } {set et_cxa_atexit_target_name ""}# If the target has changed since we set the cached value, clear it.set current_target [current_target_name]if { $current_target != $et_cxa_atexit_target_name } {verbose "check_v3_target_cxa_atexit: `$et_cxa_atexit_target_name'" 2set et_cxa_atexit_target_name $current_targetif [info exists et_cxa_atexit] {verbose "check_v3_target_cxa_atexit: removing cached result" 2unset et_cxa_atexit}}if [info exists et_cxa_atexit] {verbose "check_v3_target_cxa_atexit: using cached result" 2} else {set et_cxa_atexit 0# Set up, compile, and execute a C++ test program that depends# on correct ordering of static object destructors. This is# indicative of the presence and use of __cxa_atexit.set src cxaatexit[pid].ccset exe cxaatexit[pid].xset f [open $src "w"]puts $f "#include <stdlib.h>"puts $f "static unsigned int count;"puts $f "struct X"puts $f "{"puts $f " X() { count = 1; }"puts $f " ~X()"puts $f " {"puts $f " if (count != 3)"puts $f " exit(1);"puts $f " count = 4;"puts $f " }"puts $f "};"puts $f "void f()"puts $f "{"puts $f " static X x;"puts $f "}"puts $f "struct Y"puts $f "{"puts $f " Y() { f(); count = 2; }"puts $f " ~Y()"puts $f " {"puts $f " if (count != 2)"puts $f " exit(1);"puts $f " count = 3;"puts $f " }"puts $f "};"puts $f "Y y;"puts $f "int main()"puts $f "{ return 0; }"close $fset lines [v3_target_compile $src $exe executable ""]file delete $srcif [string match "" $lines] {# No error message, compilation succeeded.set result [${tool}_load "./$exe" "" ""]set status [lindex $result 0]remote_file build delete $exeverbose "check_v3_target_cxa_atexit: status is <$status>" 2if { $status == "pass" } {set et_cxa_atexit 1}} else {verbose "check_v3_target_cxa_atexit: compilation failed" 2}}return $et_cxa_atexit}proc check_v3_target_debug_mode { } {global cxxflagsglobal et_debug_modeglobal toolif { ![info exists et_debug_mode_target_name] } {set et_debug_mode_target_name ""}# If the target has changed since we set the cached value, clear it.set current_target [current_target_name]if { $current_target != $et_debug_mode_target_name } {verbose "check_v3_target_debug_mode: `$et_debug_mode_target_name'" 2set et_debug_mode_target_name $current_targetif [info exists et_debug_mode] {verbose "check_v3_target_debug_mode: removing cached result" 2unset et_debug_mode}}if [info exists et_debug_mode] {verbose "check_v3_target_debug_mode: using cached result" 2} else {set et_debug_mode 0# Set up, compile, and execute a C++ test program that depends# on debug mode working.set src debug_mode[pid].ccset exe debug_mode[pid].exeset f [open $src "w"]puts $f "#include <string>"puts $f "using namespace std;"puts $f "int main()"puts $f "{ return 0; }"close $fset cxxflags_saved $cxxflagsset cxxflags "$cxxflags -Werror -O0 -D_GLIBCXX_DEBUG"set lines [v3_target_compile $src $exe executable ""]set cxxflags $cxxflags_savedfile delete $srcif [string match "" $lines] {# No error message, compilation succeeded.set et_debug_mode 1}}verbose "check_v3_target_debug_mode: $et_debug_mode" 2return $et_debug_mode}