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
6 proc gcj_jni_compile_c_to_so {file {options {}}} {
9 verbose "options: $options"
10 set options_cxx $options
13 # Apple uses a different extension for shared/dynamic libraries
14 # so we check against powerpc-apple-darwin and set them to
16 # HP-UX uses sl, so we check this too, otherwise we take so.
18 if { [istarget "*-*-darwin*"] } {
19 set so_extension "dylib"
20 set so_flag "-dynamiclib"
21 } elseif { [istarget "hppa*-hp-hpux*"] } {
28 set filename [file tail $file]
29 set name [file rootname $filename]
30 set soname lib${name}.${so_extension}
32 lappend options "additional_flags=${so_flag} -fPIC"
33 # Find the generated header.
34 lappend options "additional_flags=-I. -I.. -I$srcdir/$subdir"
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"
43 # Find jni.h and jni_md.h.
44 lappend options "additional_flags=-I$srcdir/../include -I$srcdir/../classpath/include"
47 lappend options "additional_flags=$options_cxx"
49 set x [libjava_prune_warnings \
50 [target_compile $file $soname executable $options]]
52 verbose "target_compile failed: $x" 2
53 fail "$filename compilation"
57 pass "$filename compilation"
61 # Build a header file from a .class file. Return 0 on failure.
62 proc gcj_jni_build_header {file} {
66 set file [file rootname $file]
68 set cmd "$gcjh -jni -force -classpath .:$libgcj_jar $file"
71 set x [string trim [libjava_prune_warnings \
72 [lindex [local_exec $cmd "" "" 300] 1]]]
74 verbose "local_exec failed: $x" 2
75 fail "$file header generation"
79 pass "$file header generation"
83 # Do all the work for a single JNI test. Return 0 on failure.
84 proc gcj_jni_test_one {file} {
89 # Apple uses a different extension for shared/dynamic libraries
90 # so we check against powerpc-apple-darwin and set them to
92 # HP-UX uses sl, so we check this too, otherwise we take so.
94 if { [istarget "*-*-darwin*"] } {
95 set so_extension "dylib"
96 } elseif { [istarget "hppa*-hp-hpux*"] } {
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"} {
110 # if {! [bytecompile_file $file [pwd]]} {
111 # fail "bytecompile $file"
112 # # FIXME - should use `untested' on all remaining tests.
113 # # But that is hard.
116 # pass "bytecompile $file"
118 # set bytefile [file rootname [file tail $file]].class
119 # if {! [gcj_jni_build_header $bytefile]} {
124 set cfile [file rootname $file].c
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
132 foreach arg [split [libjava_find_lib libstdc++-v3/src stdc++] " "] {
133 switch -glob -- $arg {
135 set arg [string range $arg 2 end]
136 lappend cxxldlibflags $arg
137 # Strip the `.libs' directory; we link with libtool which
139 set arg "-L[file dirname $arg]"
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"
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++"
156 lappend cxxflaglist "-lstdc++"
159 set cxxflags [join $cxxflaglist]
162 if {! [gcj_jni_compile_c_to_so $cfile $cxxflags]} {
167 set args [list "additional_flags=-fjni"]
168 if {! [gcj_link $main $main $file $args]} {
173 set resultfile [file rootname $file].out
175 if {! [gcj_invoke $main $resultfile $cxxldlibflags]} {
180 # We purposely ignore errors here; we still want to run the other
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
194 # When we succeed we remove all our clutter.
195 eval gcj_cleanup [glob -nocomplain -- ${main}.*] \
196 [list $main lib${main}.${so_extension}]
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
204 proc gcj_jni_invocation_compile_c_to_binary {file {options {}}} {
207 verbose "options: $options"
208 set options_cxx $options
211 set filename [file tail $file]
212 set name [file rootname $filename]
214 # Set some darwin specific options
215 if { [istarget "*-*-darwin*"] } {
216 lappend options "additional_flags= -bind_at_load -multiply_defined suppress"
218 # Find the generated header.
219 lappend options "additional_flags=-I. -I.. -I$srcdir/$subdir"
221 # Find jni.h and jni_md.h.
222 lappend options "additional_flags=-I$srcdir/../include -I$srcdir/../classpath/include"
225 lappend options "additional_flags=$options_cxx"
227 set x [libjava_prune_warnings \
228 [target_compile $file $name executable $options]]
230 verbose "target_compile failed: $x" 2
231 fail "$filename compilation"
235 pass "$filename compilation"
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"
251 if [info exists LIBJAVA] {
252 set libjava $LIBJAVA;
254 set libjava [libjava_find_lib libjava gcj]
256 set cxxflags "$libjava -ljvm"
259 if { [istarget "*-*-solaris*"] } {
260 lappend cxxflags "-lsocket"
266 # Do all the work for a single invocation API test. Return 0 on
268 proc gcj_jni_invocation_test_one {file} {
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]} {
281 # if {! [bytecompile_file $file [pwd]]} {
282 # fail "bytecompile $file"
283 # # FIXME - should use `untested' on all remaining tests.
284 # # But that is hard.
287 # pass "bytecompile $file"
289 set cfile [file rootname $file].c
291 set cxxflags [gcj_jni_get_cxxflags_invocation]
292 if {! [gcj_jni_invocation_compile_c_to_binary $cfile $cxxflags]} {
297 set resultfile [file rootname $file].out
299 set env(CLASSPATH) $file
300 verbose "CLASSPATH = $env(CLASSPATH)"
301 if {! [gcj_invoke $main $resultfile ""]} {
308 # We purposely ignore errors here; we still want to run the other
310 set errname [file rootname [file tail $file]]
312 # When we succeed we remove all our clutter.
313 eval gcj_cleanup [glob -nocomplain -- ${main}.*] \
319 proc gcj_jni_pr29812 {} {
321 global INTERPRETER runtests
323 # Set up a global we need.
326 set b ${srcdir}/${subdir}
328 if {! [runtest_file_p $runtests pr29812]} {
333 if {! [gcj_jni_compile_c_to_so $b/pr29812.c ""]} {
336 if {! [gcj_jni_compile_c_to_so $b/pr29812_injar.c ""]} {
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]} {
349 # When we succeed we remove all our clutter.
350 eval gcj_cleanup [glob -nocomplain -- *pr29812*]
354 proc gcj_jni_run {} {
356 global build_triplet host_triplet
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
362 foreach x $srcfiles {
366 # Run JNI invocation API tests
367 catch { lsort [glob -nocomplain ${srcdir}/${subdir}/invocation/*.jar] } srcfiles
369 foreach x $srcfiles {
370 gcj_jni_invocation_test_one $x
375 verbose "JNI tests not run in cross-compilation environment"