2007-02-13 Andrew Haley <aph@redhat.com>
[gcc.git] / libjava / testsuite / libjava.jni / jni.exp
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.
6 proc gcj_jni_compile_c_to_so {file {options {}}} {
7 global srcdir subdir
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.
16 # HP-UX uses sl, so we check this too, otherwise we take so.
17
18 if { [istarget "*-*-darwin*"] } {
19 set so_extension "dylib"
20 set so_flag "-dynamiclib"
21 } elseif { [istarget "hppa*-hp-hpux*"] } {
22 set so_extension "sl"
23 set so_flag "-shared"
24 } else {
25 set so_extension "so"
26 set so_flag "-shared"
27 }
28 set filename [file tail $file]
29 set name [file rootname $filename]
30 set soname lib${name}.${so_extension}
31
32 lappend options "additional_flags=${so_flag} -fPIC"
33 # Find the generated header.
34 lappend options "additional_flags=-I. -I.. -I$srcdir/$subdir"
35
36 # Ensure that the generated header has correct prototypes.
37 set cfile [file rootname $file].c
38 if { [file exists $cfile]} {
39 # This option is only valid for C sources.
40 lappend options "additional_flags=-Wmissing-prototypes"
41 }
42
43 # Find jni.h and jni_md.h.
44 lappend options "additional_flags=-I$srcdir/../include -I$srcdir/../classpath/include"
45
46 # Append C++ options
47 lappend options "additional_flags=$options_cxx"
48
49 set x [libjava_prune_warnings \
50 [target_compile $file $soname executable $options]]
51 if {$x != ""} {
52 verbose "target_compile failed: $x" 2
53 fail "$filename compilation"
54 return 0
55 }
56
57 pass "$filename compilation"
58 return 1
59 }
60
61 # Build a header file from a .class file. Return 0 on failure.
62 proc gcj_jni_build_header {file} {
63 global libgcj_jar
64
65 set gcjh [find_gcjh]
66 set file [file rootname $file]
67
68 set cmd "$gcjh -jni -force -classpath .:$libgcj_jar $file"
69 verbose $cmd
70
71 set x [string trim [libjava_prune_warnings \
72 [lindex [local_exec $cmd "" "" 300] 1]]]
73 if {$x != ""} {
74 verbose "local_exec failed: $x" 2
75 fail "$file header generation"
76 return 0
77 }
78
79 pass "$file header generation"
80 return 1
81 }
82
83 # Do all the work for a single JNI test. Return 0 on failure.
84 proc gcj_jni_test_one {file} {
85 global runtests
86 global host_triplet
87 global INTERPRETER
88
89 # Apple uses a different extension for shared/dynamic libraries
90 # so we check against powerpc-apple-darwin and set them to
91 # dylib.
92 # HP-UX uses sl, so we check this too, otherwise we take so.
93
94 if { [istarget "*-*-darwin*"] } {
95 set so_extension "dylib"
96 } elseif { [istarget "hppa*-hp-hpux*"] } {
97 set so_extension "sl"
98 } else {
99 set so_extension "so"
100 }
101
102 # The base name. We use it for several purposes.
103 set main [file rootname [file tail $file]]
104 if {! [runtest_file_p $runtests $main]
105 || $main == "pr29812" || $main == "pr29812_injar"} {
106 # Simply skip it.
107 return 1
108 }
109
110 # if {! [bytecompile_file $file [pwd]]} {
111 # fail "bytecompile $file"
112 # # FIXME - should use `untested' on all remaining tests.
113 # # But that is hard.
114 # return 0
115 # }
116 # pass "bytecompile $file"
117
118 # set bytefile [file rootname [file tail $file]].class
119 # if {! [gcj_jni_build_header $bytefile]} {
120 # # FIXME
121 # return 0
122 # }
123
124 set cfile [file rootname $file].c
125 set cxxflags ""
126 set cxxldlibflags {}
127 # If there is no `.c' file, assume there is a `.cc' file.
128 if {! [file exists $cfile]} {
129 set cfile [file rootname $file].cc
130
131 set cxxflaglist {}
132 foreach arg [split [libjava_find_lib libstdc++-v3/src stdc++] " "] {
133 switch -glob -- $arg {
134 "-L*" {
135 set arg [string range $arg 2 end]
136 lappend cxxldlibflags $arg
137 # Strip the `.libs' directory; we link with libtool which
138 # doesn't need it.
139 set arg "-L[file dirname $arg]"
140 }
141 }
142 lappend cxxflaglist $arg
143 # In case the libstdc++ is not installed yet, we pass the build
144 # directory of it to the cxxflaglist.
145 lappend cxxflaglist "-L$cxxldlibflags"
146 }
147
148 # If you're building the compiler with --prefix set to a place
149 # where it's not yet installed, then the linker won't be able to
150 # find the libgcc used by libffi.dylib. We could pass the
151 # -dylib_file option, but that's complicated, and it's much easier
152 # to just make the linker find libgcc using -L options.
153 if { [istarget "*-*-darwin*"] } {
154 lappend cxxflaglist "-shared-libgcc -lstdc++"
155 } else {
156 lappend cxxflaglist "-lstdc++"
157 }
158
159 set cxxflags [join $cxxflaglist]
160 }
161
162 if {! [gcj_jni_compile_c_to_so $cfile $cxxflags]} {
163 # FIXME
164 return 0
165 }
166
167 set args [list "additional_flags=-fjni"]
168 if {! [gcj_link $main $main $file $args]} {
169 # FIXME
170 return 0
171 }
172
173 set resultfile [file rootname $file].out
174
175 if {! [gcj_invoke $main $resultfile $cxxldlibflags]} {
176 # FIXME
177 return 0
178 }
179
180 # We purposely ignore errors here; we still want to run the other
181 # appropriate tests.
182 set errname [file rootname [file tail $file]]
183 set gij [libjava_find_gij]
184 # libjava_find_gij will return "" if it couldn't find the
185 # program; in this case we want to skip the test.
186 # If the libraries are not installed yet, we have to pass them via
187 # cxxldlibflags to libjava_invoke.
188 if {$INTERPRETER == "yes" && $gij != ""} {
189 libjava_invoke $errname "gij test" opts $gij \
190 "" $resultfile $cxxldlibflags \
191 -classpath $file $main
192 }
193
194 # When we succeed we remove all our clutter.
195 eval gcj_cleanup [glob -nocomplain -- ${main}.*] \
196 [list $main lib${main}.${so_extension}]
197
198 return 1
199 }
200
201 # Compile a single C file and produce a binary. OPTIONS is a list of
202 # options to pass to the compiler. Returns 0 on failure, 1 on
203 # success.
204 proc gcj_jni_invocation_compile_c_to_binary {file {options {}}} {
205 global srcdir subdir
206 global host_triplet
207 verbose "options: $options"
208 set options_cxx $options
209 set options ""
210
211 set filename [file tail $file]
212 set name [file rootname $filename]
213
214 # Set some darwin specific options
215 if { [istarget "*-*-darwin*"] } {
216 lappend options "additional_flags= -bind_at_load -multiply_defined suppress"
217 }
218 # Find the generated header.
219 lappend options "additional_flags=-I. -I.. -I$srcdir/$subdir"
220
221 # Find jni.h and jni_md.h.
222 lappend options "additional_flags=-I$srcdir/../include -I$srcdir/../classpath/include"
223
224 # Append C++ options
225 lappend options "additional_flags=$options_cxx"
226
227 set x [libjava_prune_warnings \
228 [target_compile $file $name executable $options]]
229 if {$x != ""} {
230 verbose "target_compile failed: $x" 2
231 fail "$filename compilation"
232 return 0
233 }
234
235 pass "$filename compilation"
236 return 1
237 }
238
239 proc gcj_jni_get_cxxflags_invocation {} {
240 # Darwin needs -liconv linked, otherwise we get some unresolved.
241 # If you're building the compiler with --prefix set to a place
242 # where it's not yet installed, then the linker won't be able to
243 # find the libgcc used by libffi.dylib. We could pass the
244 # -dylib_file option, but that's complicated, and it's much easier
245 # to just make the linker find libgcc using -L options.
246 # Similar logic applies to libgcj.
247 if { [istarget "*-*-darwin*"] } {
248 set cxxflags "-L../.libs -shared-libgcc -ljvm -lgcj -liconv"
249 } else {
250 global LIBJAVA
251 if [info exists LIBJAVA] {
252 set libjava $LIBJAVA;
253 } else {
254 set libjava [libjava_find_lib libjava gcj]
255 }
256 set cxxflags "$libjava -ljvm"
257 }
258
259 if { [istarget "*-*-solaris*"] } {
260 lappend cxxflags "-lsocket"
261 }
262
263 return $cxxflags
264 }
265
266 # Do all the work for a single invocation API test. Return 0 on
267 # failure.
268 proc gcj_jni_invocation_test_one {file} {
269 global env
270 global runtests
271 global host_triplet
272 global INTERPRETER
273
274 # The base name. We use it for several purposes.
275 set main [file rootname [file tail $file]]
276 if {! [runtest_file_p $runtests $main]} {
277 # Simply skip it.
278 return 1
279 }
280
281 # if {! [bytecompile_file $file [pwd]]} {
282 # fail "bytecompile $file"
283 # # FIXME - should use `untested' on all remaining tests.
284 # # But that is hard.
285 # return 0
286 # }
287 # pass "bytecompile $file"
288
289 set cfile [file rootname $file].c
290
291 set cxxflags [gcj_jni_get_cxxflags_invocation]
292 if {! [gcj_jni_invocation_compile_c_to_binary $cfile $cxxflags]} {
293 # FIXME
294 return 0
295 }
296
297 set resultfile [file rootname $file].out
298
299 set env(CLASSPATH) $file
300 verbose "CLASSPATH = $env(CLASSPATH)"
301 if {! [gcj_invoke $main $resultfile ""]} {
302 unset env(CLASSPATH)
303 # FIXME
304 return 0
305 }
306 unset env(CLASSPATH)
307
308 # We purposely ignore errors here; we still want to run the other
309 # appropriate tests.
310 set errname [file rootname [file tail $file]]
311
312 # When we succeed we remove all our clutter.
313 eval gcj_cleanup [glob -nocomplain -- ${main}.*] \
314 [list $main]
315
316 return 1
317 }
318
319 proc gcj_jni_pr29812 {} {
320 global srcdir subdir
321 global INTERPRETER runtests
322
323 # Set up a global we need.
324 libjava_arguments
325
326 set b ${srcdir}/${subdir}
327
328 if {! [runtest_file_p $runtests pr29812]} {
329 # Simply skip it.
330 return 1
331 }
332
333 if {! [gcj_jni_compile_c_to_so $b/pr29812.c ""]} {
334 return 0
335 }
336 if {! [gcj_jni_compile_c_to_so $b/pr29812_injar.c ""]} {
337 return 0
338 }
339
340 set gij [libjava_find_gij]
341 if {$INTERPRETER == "yes" && $gij != ""} {
342 if {! [libjava_invoke pr29812 "gij test" opts $gij \
343 "" $b/pr29812.out "" \
344 -classpath $b/pr29812.jar pr29812 $b/pr29812_injar.jar]} {
345 return 0
346 }
347 }
348
349 # When we succeed we remove all our clutter.
350 eval gcj_cleanup [glob -nocomplain -- *pr29812*]
351 }
352
353 # Run the JNI tests.
354 proc gcj_jni_run {} {
355 global srcdir subdir
356 global build_triplet host_triplet
357
358 # For now we only test JNI on native builds.
359 if {$build_triplet == $host_triplet} {
360 catch { lsort [glob -nocomplain ${srcdir}/${subdir}/*.jar] } srcfiles
361
362 foreach x $srcfiles {
363 gcj_jni_test_one $x
364 }
365
366 # Run JNI invocation API tests
367 catch { lsort [glob -nocomplain ${srcdir}/${subdir}/invocation/*.jar] } srcfiles
368
369 foreach x $srcfiles {
370 gcj_jni_invocation_test_one $x
371 }
372
373 gcj_jni_pr29812
374 } else {
375 verbose "JNI tests not run in cross-compilation environment"
376 }
377 }
378
379 gcj_jni_run