1# Tests for JNI code.
2
3# Compile a single C file and produce a .so file.  OPTIONS is a list
4# of options to pass to the compiler.  Returns 0 on failure, 1 on
5# success.
6proc gcj_jni_compile_c_to_so {file {options {}}} {
7  global srcdir
8  global host_triplet
9  verbose "options: $options"
10  set options_cxx $options
11  set options ""
12
13# apple uses a different extension for shared/dynamic libraries
14# so we check against powerpc-apple-darwin and set them to
15# dylib, else we assume it's .so
16
17  if { [ regexp {powerpc-apple-darwin} $host_triplet] } {
18      set so_extension "dylib"
19      set so_flag "-dynamiclib"
20  } else {
21      set so_extension "so"
22      set so_flag "-shared"
23  }
24  set name [file rootname [file tail $file]]
25  set soname lib${name}.${so_extension}
26
27  lappend options "additional_flags=${so_flag} -fPIC"
28  # Find the generated header.
29  lappend options "additional_flags=-I. -I.."
30  # Find jni.h.
31  lappend options "additional_flags=-I$srcdir/../include"
32
33  set x [libjava_prune_warnings \
34	   [target_compile $file $soname executable $options]]
35  if {$x != ""} {
36    verbose "target_compile failed: $x" 2
37    fail "$name.c compilation"
38    return 0
39  }
40
41  pass "$name.c compilation"
42  return 1
43}
44
45# Build a header file from a .class file.  Return 0 on failure.
46proc gcj_jni_build_header {file} {
47  set gcjh [find_gcjh]
48  set file [file rootname $file]
49  set x [string trim [libjava_prune_warnings \
50			[lindex [local_exec "$gcjh -jni $file" "" "" 300] 1]]]
51  if {$x != ""} {
52    verbose "local_exec failed: $x" 2
53    fail "$file header generation"
54    return 0
55  }
56
57  pass "$file header generation"
58  return 1
59}
60
61# Do all the work for a single JNI test.  Return 0 on failure.
62proc gcj_jni_test_one {file} {
63  global runtests
64  global host_triplet
65
66# apple uses a different extension for shared/dynamic libraries
67# so we check against powerpc-apple-darwin and set them to
68# dylib, else we assume it's .so
69
70  if { [ regexp {powerpc-apple-darwin} $host_triplet] } {
71      set so_extension "dylib"
72  } else {
73      set so_extension "so"
74  }
75
76  # The base name.  We use it for several purposes.
77  set main [file rootname [file tail $file]]
78  if {! [runtest_file_p $runtests $main]} {
79    # Simply skip it.
80    return 1
81  }
82
83  if {! [bytecompile_file $file [pwd]]} {
84    fail "bytecompile $file"
85    # FIXME - should use `untested' on all remaining tests.
86    # But that is hard.
87    return 0
88  }
89  pass "bytecompile $file"
90
91  set bytefile [file rootname [file tail $file]].class
92  if {! [gcj_jni_build_header $bytefile]} {
93    # FIXME
94    return 0
95  }
96
97  set cfile [file rootname $file].c
98  set cxxflags ""
99  set cxxldlibflags {}
100  # If there is no `.c' file, assume there is a `.cc' file.
101  if {! [file exists $cfile]} {
102    set cfile [file rootname $file].cc
103
104    set cxxflaglist {}
105    foreach arg [split [libjava_find_lib libstdc++-v3/src stdc++] " "] {
106      switch -glob -- $arg {
107	"-L*" {
108	  set arg [string range $arg 2 end]
109	  lappend cxxldlibflags $arg
110	  # Strip the `.libs' directory; we link with libtool which
111	  # doesn't need it.
112	  set arg "-L[file dirname $arg]"
113	}
114      }
115      lappend cxxflaglist $arg
116    }
117
118    lappend cxxflaglist "-lstdc++"
119    set cxxflags [join $cxxflaglist]
120  }
121
122  if {! [gcj_jni_compile_c_to_so $cfile]} {
123    # FIXME
124    return 0
125  }
126
127  # We use -l$main because the .so is named the same as the main
128  # program.
129  set args [list "additional_flags=-fjni -L. -l$main $cxxflags"]
130  if {! [gcj_link $main $main $file $args]} {
131    # FIXME
132    return 0
133  }
134
135  if {! [gcj_invoke $main [file rootname $file].out $cxxldlibflags]} {
136    # FIXME
137    return 0
138  }
139
140  # When we succeed we remove all our clutter.
141  eval gcj_cleanup [glob -nocomplain -- ${main}.*] [list $main lib${main}.${so_extension}]
142
143  return 1
144}
145
146# Run the JNI tests.
147proc gcj_jni_run {} {
148  global srcdir subdir
149  global build_triplet host_triplet
150
151  # For now we only test JNI on native builds.
152  if {$build_triplet == $host_triplet} {
153    catch { lsort [glob -nocomplain ${srcdir}/${subdir}/*.java] } srcfiles
154
155    foreach x $srcfiles {
156      gcj_jni_test_one $x
157    }
158  } else {
159    verbose "JNI tests not run in cross-compilation environment"
160  }
161}
162
163gcj_jni_run
164