| # 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 |
| 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, else we assume it's .so |
| |
| if { [istarget "*-*-darwin*"] } { |
| set so_extension "dylib" |
| set so_flag "-dynamiclib" |
| } 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} |
| |
| lappend options "additional_flags=${so_flag} -fPIC" |
| # Find the generated header. |
| lappend options "additional_flags=-I. -I.." |
| |
| # 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. |
| lappend options "additional_flags=-I$srcdir/../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} { |
| set gcjh [find_gcjh] |
| set file [file rootname $file] |
| set x [string trim [libjava_prune_warnings \ |
| [lindex [local_exec "$gcjh -jni $file" "" "" 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, else we assume it's .so |
| |
| if { [istarget "*-*-darwin*"] } { |
| set so_extension "dylib" |
| } 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]} { |
| # 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" |
| } |
| |
| # Darwin does not yet have a libgcc_s.dylib library. |
| # So we add it here. If the libgcc_s is installed, the libstdc++ |
| # would pick it up. |
| if { [istarget "*-*-darwin*"] } { |
| lappend cxxflaglist "-lgcc_s -lstdc++" |
| } else { |
| lappend cxxflaglist "-lstdc++" |
| } |
| |
| 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 $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 |
| 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=-multiply_defined suppress" |
| } |
| # Find the generated header. |
| lappend options "additional_flags=-I. -I.." |
| |
| # Find jni.h. |
| lappend options "additional_flags=-I$srcdir/../include" |
| |
| # 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 |
| } |
| |
| # Do all the work for a single invocation API test. Return 0 on |
| # failure. |
| proc gcj_jni_invocation_test_one {file} { |
| 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 |
| # Darwin needs -liconv linked, otherwise we get some unresolved. |
| # Also, like in the cxxtest we need to add -lgcc_s since Darwin |
| # has no libgcc_s.dylib installed yet. |
| if { [istarget "*-*-darwin*"] } { |
| set cxxflags "-L../.libs -lgcc_s -lgcj -liconv" |
| } else { |
| set cxxflags "-L../.libs -lgcj" |
| } |
| |
| if { [istarget "*-*-solaris*"] } { |
| lappend cxxflags "-lsocket" |
| } |
| |
| if {! [gcj_jni_invocation_compile_c_to_binary $cfile $cxxflags]} { |
| # FIXME |
| return 0 |
| } |
| |
| set resultfile [file rootname $file].out |
| |
| if {! [gcj_invoke $main $resultfile ""]} { |
| # FIXME |
| return 0 |
| } |
| |
| # 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 |
| } |
| |
| # 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}/*.java] } srcfiles |
| |
| foreach x $srcfiles { |
| gcj_jni_test_one $x |
| } |
| |
| # Run JNI invocation API tests |
| catch { lsort [glob -nocomplain ${srcdir}/${subdir}/invocation/*.java] } srcfiles |
| |
| foreach x $srcfiles { |
| gcj_jni_invocation_test_one $x |
| } |
| } else { |
| verbose "JNI tests not run in cross-compilation environment" |
| } |
| } |
| |
| gcj_jni_run |