mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			405 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			405 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| # Tests for JNI code.
 | |
| 
 | |
| # Compile a single C file and produce a .so file.  OPTIONS is a list
 | |
| # of options to pass to the compiler.  Returns 0 on failure, 1 on
 | |
| # success.
 | |
| proc gcj_jni_compile_c_to_so {file {options {}}} {
 | |
|   global srcdir subdir
 | |
|   global host_triplet
 | |
|   verbose "options: $options"
 | |
|   set options_cxx $options
 | |
|   set options ""
 | |
| 
 | |
| # Apple uses a different extension for shared/dynamic libraries
 | |
| # so we check against powerpc-apple-darwin and set them to
 | |
| # dylib.
 | |
| # HP-UX uses sl, so we check this too, otherwise we take so.
 | |
| 
 | |
|   if { [istarget "*-*-darwin*"] } {
 | |
|       set so_extension "dylib"
 | |
|       set so_flag "-dynamiclib"
 | |
|   } elseif { [istarget "hppa*-hp-hpux*"] } {
 | |
|       set so_extension "sl"
 | |
|       set so_flag "-shared"
 | |
|   } elseif { [istarget "*-*-cygwin*"] || [istarget "*-*-mingw*"] } {
 | |
|       set so_extension "dll"
 | |
|       set so_flag "-shared"
 | |
|   } else {
 | |
|       set so_extension "so"
 | |
|       set so_flag "-shared"
 | |
|   }
 | |
|   set filename [file tail $file]
 | |
|   set name [file rootname $filename]
 | |
|   set soname lib${name}.${so_extension}
 | |
| 
 | |
|   if { [istarget "*arm-*eabi*"] } {
 | |
|       lappend options "additional_flags=-fexceptions"
 | |
|   }
 | |
| 
 | |
|   lappend options "additional_flags=${so_flag} -fPIC"
 | |
|   # Find the generated header.
 | |
|   lappend options "additional_flags=-I. -I.. -I$srcdir/$subdir -fdollars-in-identifiers"
 | |
| 
 | |
|   # Ensure that the generated header has correct prototypes.
 | |
|   set cfile [file rootname $file].c
 | |
|   if { [file exists $cfile]} {
 | |
|     # This option is only valid for C sources.
 | |
|     lappend options "additional_flags=-Wmissing-prototypes"
 | |
|   }
 | |
| 
 | |
|   # Find jni.h and jni_md.h.
 | |
|   lappend options "additional_flags=-I$srcdir/../include -I$srcdir/../classpath/include"
 | |
| 
 | |
|   # Append C++ options
 | |
|   lappend options "additional_flags=$options_cxx"
 | |
| 
 | |
|   set x [libjava_prune_warnings \
 | |
| 	   [target_compile $file $soname executable $options]]
 | |
|   if {$x != ""} {
 | |
|     verbose "target_compile failed: $x" 2
 | |
|     fail "$filename compilation"
 | |
|     return 0
 | |
|   }
 | |
| 
 | |
|   pass "$filename compilation"
 | |
|   return 1
 | |
| }
 | |
| 
 | |
| # Build a header file from a .class file.  Return 0 on failure.
 | |
| proc gcj_jni_build_header {file} {
 | |
|   global libgcj_jar
 | |
| 
 | |
|   set gcjh [find_gcjh]
 | |
|   set file [file rootname $file]
 | |
| 
 | |
|   set cmd "$gcjh -jni -force -classpath .:$libgcj_jar $file"
 | |
|   verbose $cmd
 | |
| 
 | |
|   set x [string trim [libjava_prune_warnings \
 | |
| 			[lindex [local_exec $cmd "" "" 300] 1]]]
 | |
|   if {$x != ""} {
 | |
|     verbose "local_exec failed: $x" 2
 | |
|     fail "$file header generation"
 | |
|     return 0
 | |
|   }
 | |
| 
 | |
|   pass "$file header generation"
 | |
|   return 1
 | |
| }
 | |
| 
 | |
| # Do all the work for a single JNI test.  Return 0 on failure.
 | |
| proc gcj_jni_test_one {file} {
 | |
|   global runtests
 | |
|   global host_triplet
 | |
|   global INTERPRETER
 | |
| 
 | |
| # Apple uses a different extension for shared/dynamic libraries
 | |
| # so we check against powerpc-apple-darwin and set them to
 | |
| # dylib.
 | |
| # HP-UX uses sl, so we check this too, otherwise we take so.
 | |
| 
 | |
|   if { [istarget "*-*-darwin*"] } {
 | |
|       set so_extension "dylib"
 | |
|   } elseif { [istarget "hppa*-hp-hpux*"] } {
 | |
|       set so_extension "sl"
 | |
|   } elseif { [istarget "*-*-cygwin*"] || [istarget "*-*-mingw*"] } {
 | |
|       set so_extension "dll"
 | |
|   } else {
 | |
|       set so_extension "so"
 | |
|   }
 | |
| 
 | |
|   # The base name.  We use it for several purposes.
 | |
|   set main [file rootname [file tail $file]]
 | |
|   if {! [runtest_file_p $runtests $main]
 | |
|       || $main == "pr29812" || $main == "pr29812_injar"} {
 | |
|     # Simply skip it.
 | |
|     return 1
 | |
|   }
 | |
| 
 | |
| #   if {! [bytecompile_file $file [pwd]]} {
 | |
| #     fail "bytecompile $file"
 | |
| #     # FIXME - should use `untested' on all remaining tests.
 | |
| #     # But that is hard.
 | |
| #     return 0
 | |
| #   }
 | |
| #   pass "bytecompile $file"
 | |
| 
 | |
| #   set bytefile [file rootname [file tail $file]].class
 | |
| #   if {! [gcj_jni_build_header $bytefile]} {
 | |
| #     # FIXME
 | |
| #     return 0
 | |
| #   }
 | |
| 
 | |
|   set cfile [file rootname $file].c
 | |
|   set cxxflags ""
 | |
|   set cxxldlibflags {}
 | |
|   # If there is no `.c' file, assume there is a `.cc' file.
 | |
|   if {! [file exists $cfile]} {
 | |
|     set cfile [file rootname $file].cc
 | |
| 
 | |
|     set cxxflaglist {}
 | |
|     foreach arg [split [libjava_find_lib libstdc++-v3/src stdc++] " "] {
 | |
|       switch -glob -- $arg {
 | |
| 	"-L*" {
 | |
| 	  set arg [string range $arg 2 end]
 | |
| 	  lappend cxxldlibflags $arg
 | |
| 	  # Strip the `.libs' directory; we link with libtool which
 | |
| 	  # doesn't need it.
 | |
| 	  set arg "-L[file dirname $arg]"
 | |
| 	}
 | |
|       }
 | |
|       lappend cxxflaglist $arg
 | |
|       # In case the libstdc++ is not installed yet, we pass the build
 | |
|       # directory of it to the cxxflaglist.
 | |
|       lappend cxxflaglist "-L$cxxldlibflags"
 | |
|     }
 | |
| 
 | |
|     # If you're building the compiler with --prefix set to a place
 | |
|     # where it's not yet installed, then the linker won't be able to
 | |
|     # find the libgcc used by libffi.dylib.  We could pass the
 | |
|     # -dylib_file option, but that's complicated, and it's much easier
 | |
|     # to just make the linker find libgcc using -L options.
 | |
|     if { [istarget "*-*-darwin*"] } {
 | |
| 	lappend cxxflaglist "-shared-libgcc -lstdc++"
 | |
|     } else {
 | |
| 	lappend cxxflaglist "-lstdc++"
 | |
|     }
 | |
| 
 | |
|     # ARM C++ emits an ABI warning for varargs.
 | |
|     if { [istarget "arm*"] } {
 | |
| 	lappend cxxflaglist "-Wno-abi"
 | |
|     }
 | |
|     
 | |
|     set cxxflags [join $cxxflaglist]
 | |
|   }
 | |
| 
 | |
|   if {! [gcj_jni_compile_c_to_so $cfile $cxxflags]} {
 | |
|     # FIXME
 | |
|     return 0
 | |
|   }
 | |
| 
 | |
|   set args [list "additional_flags=-fjni"]
 | |
|   if {! [gcj_link $main $main $file $args]} {
 | |
|     # FIXME
 | |
|     return 0
 | |
|   }
 | |
| 
 | |
|   set resultfile [file rootname $file].out
 | |
| 
 | |
|   if {! [gcj_invoke $main $resultfile $cxxldlibflags]} {
 | |
|     # FIXME
 | |
|     return 0
 | |
|   }
 | |
| 
 | |
|   # We purposely ignore errors here; we still want to run the other
 | |
|   # appropriate tests.
 | |
|   set errname [file rootname [file tail $file]]
 | |
|   set gij [libjava_find_gij]
 | |
|   # libjava_find_gij will return "" if it couldn't find the
 | |
|   # program; in this case we want to skip the test.
 | |
|   # If the libraries are not installed yet, we have to pass them via
 | |
|   # cxxldlibflags to libjava_invoke.
 | |
|   if {$INTERPRETER == "yes" && $gij != ""} {
 | |
|     libjava_invoke $errname "gij test" opts $gij \
 | |
|       "" $resultfile $cxxldlibflags \
 | |
|       -classpath $file $main
 | |
|   }
 | |
| 
 | |
|   # When we succeed we remove all our clutter.
 | |
|   eval gcj_cleanup [glob -nocomplain -- ${main}.*] \
 | |
|     [list $main lib${main}.${so_extension}]
 | |
| 
 | |
|   return 1
 | |
| }
 | |
| 
 | |
| # Compile a single C file and produce a binary.  OPTIONS is a list of
 | |
| # options to pass to the compiler.  Returns 0 on failure, 1 on
 | |
| # success.
 | |
| proc gcj_jni_invocation_compile_c_to_binary {file {options {}}} {
 | |
|   global srcdir subdir
 | |
|   global host_triplet
 | |
|   verbose "options: $options"
 | |
|   set options_cxx $options
 | |
|   set options ""
 | |
| 
 | |
|   set filename [file tail $file]
 | |
|   set name [file rootname $filename]
 | |
| 
 | |
|   # Set some darwin specific options
 | |
|   if { [istarget "*-*-darwin*"] } {
 | |
|       lappend options "additional_flags= -bind_at_load -multiply_defined suppress"
 | |
|   }
 | |
|   # Find the generated header.
 | |
|   lappend options "additional_flags=-I. -I.. -I$srcdir/$subdir"
 | |
| 
 | |
|   # Find jni.h and jni_md.h.
 | |
|   lappend options "additional_flags=-I$srcdir/../include -I$srcdir/../classpath/include -fdollars-in-identifiers"
 | |
| 
 | |
|   # Append C++ options
 | |
|   lappend options "additional_flags=$options_cxx"
 | |
| 
 | |
|   set x [libjava_prune_warnings \
 | |
| 	   [target_compile $file $name executable $options]]
 | |
|   if {$x != ""} {
 | |
|     verbose "target_compile failed: $x" 2
 | |
|     fail "$filename compilation"
 | |
|     return 0
 | |
|   }
 | |
| 
 | |
|   pass "$filename compilation"
 | |
|   return 1
 | |
| }
 | |
| 
 | |
| proc gcj_jni_get_cxxflags_invocation {} {
 | |
|   global libiconv
 | |
|   global LIBJAVA
 | |
|   if {$libiconv == ""} {
 | |
|       set libiconv "-liconv"
 | |
|   }
 | |
|   if [info exists LIBJAVA] {
 | |
|       set libjava $LIBJAVA;
 | |
|   } else {
 | |
|       set libjava [libjava_find_lib libjava gcj]
 | |
|   }
 | |
|   set cxxflags "$libjava -ljvm"
 | |
| 
 | |
|   # Darwin needs -liconv linked, otherwise we get some unresolved.
 | |
|   # If you're building the compiler with --prefix set to a place
 | |
|   # where it's not yet installed, then the linker won't be able to
 | |
|   # find the libgcc used by libffi.dylib.  We could pass the
 | |
|   # -dylib_file option, but that's complicated, and it's much easier
 | |
|   # to just make the linker find libgcc using -L options.
 | |
|   # Similar logic applies to libgcj.
 | |
|   if { [istarget "*-*-darwin*"] } {
 | |
|     eval lappend cxxflags "-shared-libgcc -lgcj $libiconv"
 | |
|   }
 | |
| 
 | |
|   # FreeBSD needs -liconv linked, otherwise we get some unresolved.
 | |
|   if { [istarget "*-*-freebsd*"] } {
 | |
|     eval lappend cxxflags "$libiconv"
 | |
|   }
 | |
| 
 | |
|   # Make sure libgcc unwinder is used on 64-bit Solaris 10+/x86 rather than
 | |
|   # the libc one.
 | |
|   if { [istarget "*-*-solaris*"] } {
 | |
|     lappend cxxflags "-shared-libgcc"
 | |
|   }
 | |
| 
 | |
|   return $cxxflags
 | |
| }
 | |
| 
 | |
| # Do all the work for a single invocation API test.  Return 0 on
 | |
| # failure.
 | |
| proc gcj_jni_invocation_test_one {file} {
 | |
|   global env
 | |
|   global runtests
 | |
|   global host_triplet
 | |
|   global INTERPRETER
 | |
| 
 | |
|   # The base name.  We use it for several purposes.
 | |
|   set main [file rootname [file tail $file]]
 | |
|   if {! [runtest_file_p $runtests $main]} {
 | |
|     # Simply skip it.
 | |
|     return 1
 | |
|   }
 | |
| 
 | |
| #   if {! [bytecompile_file $file [pwd]]} {
 | |
| #     fail "bytecompile $file"
 | |
| #     # FIXME - should use `untested' on all remaining tests.
 | |
| #     # But that is hard.
 | |
| #     return 0
 | |
| #   }
 | |
| #   pass "bytecompile $file"
 | |
| 
 | |
|   set cfile [file rootname $file].c
 | |
| 
 | |
|   set cxxflags [gcj_jni_get_cxxflags_invocation]
 | |
|   if {! [gcj_jni_invocation_compile_c_to_binary $cfile $cxxflags]} {
 | |
|     # FIXME
 | |
|     return 0
 | |
|   }
 | |
| 
 | |
|   set resultfile [file rootname $file].out
 | |
| 
 | |
|   set env(CLASSPATH) $file
 | |
|   verbose "CLASSPATH = $env(CLASSPATH)"
 | |
|   if {! [gcj_invoke $main $resultfile ""]} {
 | |
|     unset env(CLASSPATH)
 | |
|     # FIXME
 | |
|     return 0
 | |
|   }
 | |
|   unset env(CLASSPATH)
 | |
| 
 | |
|   # We purposely ignore errors here; we still want to run the other
 | |
|   # appropriate tests.
 | |
|   set errname [file rootname [file tail $file]]
 | |
| 
 | |
|   # When we succeed we remove all our clutter.
 | |
|   eval gcj_cleanup [glob -nocomplain -- ${main}.*] \
 | |
|     [list $main]
 | |
| 
 | |
|   return 1
 | |
| }
 | |
| 
 | |
| proc gcj_jni_pr29812 {} {
 | |
|   global srcdir subdir
 | |
|   global INTERPRETER runtests
 | |
| 
 | |
|   # Set up a global we need.
 | |
|   libjava_arguments
 | |
| 
 | |
|   set b ${srcdir}/${subdir}
 | |
| 
 | |
|   if {! [runtest_file_p $runtests pr29812]} {
 | |
|     # Simply skip it.
 | |
|     return 1
 | |
|   }
 | |
| 
 | |
|   if {! [gcj_jni_compile_c_to_so $b/pr29812.c ""]} {
 | |
|     return 0
 | |
|   }
 | |
|   if {! [gcj_jni_compile_c_to_so $b/pr29812_injar.c ""]} {
 | |
|     return 0
 | |
|   }
 | |
| 
 | |
|   set gij [libjava_find_gij]
 | |
|   if {$INTERPRETER == "yes" && $gij != ""} {
 | |
|     if {! [libjava_invoke pr29812 "gij test" opts $gij \
 | |
| 	     "" $b/pr29812.out "" \
 | |
| 	     -classpath $b/pr29812.jar pr29812 $b/pr29812_injar.jar]} {
 | |
|       return 0
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   # When we succeed we remove all our clutter.
 | |
|   eval gcj_cleanup [glob -nocomplain -- *pr29812*]
 | |
| }
 | |
| 
 | |
| # Run the JNI tests.
 | |
| proc gcj_jni_run {} {
 | |
|   global srcdir subdir
 | |
|   global build_triplet host_triplet
 | |
| 
 | |
|   # For now we only test JNI on native builds.
 | |
|   if {$build_triplet == $host_triplet} {
 | |
|     catch { lsort [glob -nocomplain ${srcdir}/${subdir}/*.jar] } srcfiles
 | |
| 
 | |
|     foreach x $srcfiles {
 | |
|       gcj_jni_test_one $x
 | |
|     }
 | |
| 
 | |
|     # Run JNI invocation API tests
 | |
|     catch { lsort [glob -nocomplain ${srcdir}/${subdir}/invocation/*.jar] } srcfiles
 | |
| 
 | |
|     foreach x $srcfiles {
 | |
|       gcj_jni_invocation_test_one $x
 | |
|     }
 | |
| 
 | |
|     gcj_jni_pr29812
 | |
|   } else {
 | |
|     verbose "JNI tests not run in cross-compilation environment"
 | |
|   }
 | |
| }
 | |
| 
 | |
| gcj_jni_run
 |