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]} {
109 # if {! [bytecompile_file $file [pwd]]} {
110 # fail "bytecompile $file"
111 # # FIXME - should use `untested' on all remaining tests.
112 # # But that is hard.
115 # pass "bytecompile $file"
117 # set bytefile [file rootname [file tail $file]].class
118 # if {! [gcj_jni_build_header $bytefile]} {
123 set cfile [file rootname $file].c
126 # If there is no `.c' file, assume there is a `.cc' file.
127 if {! [file exists $cfile]} {
128 set cfile [file rootname $file].cc
131 foreach arg [split [libjava_find_lib libstdc++-v3/src stdc++] " "] {
132 switch -glob -- $arg {
134 set arg [string range $arg 2 end]
135 lappend cxxldlibflags $arg
136 # Strip the `.libs' directory; we link with libtool which
138 set arg "-L[file dirname $arg]"
141 lappend cxxflaglist $arg
142 # In case the libstdc++ is not installed yet, we pass the build
143 # directory of it to the cxxflaglist.
144 lappend cxxflaglist "-L$cxxldlibflags"
147 # If you're building the compiler with --prefix set to a place
148 # where it's not yet installed, then the linker won't be able to
149 # find the libgcc used by libffi.dylib. We could pass the
150 # -dylib_file option, but that's complicated, and it's much easier
151 # to just make the linker find libgcc using -L options.
152 if { [istarget "*-*-darwin*"] } {
153 lappend cxxflaglist "-shared-libgcc -lstdc++"
155 lappend cxxflaglist "-lstdc++"
158 set cxxflags [join $cxxflaglist]
161 if {! [gcj_jni_compile_c_to_so $cfile $cxxflags]} {
166 set args [list "additional_flags=-fjni"]
167 if {! [gcj_link $main $main $file $args]} {
172 set resultfile [file rootname $file].out
174 if {! [gcj_invoke $main $resultfile $cxxldlibflags]} {
179 # We purposely ignore errors here; we still want to run the other
181 set errname [file rootname [file tail $file]]
182 set gij [libjava_find_gij]
183 # libjava_find_gij will return "" if it couldn't find the
184 # program; in this case we want to skip the test.
185 # If the libraries are not installed yet, we have to pass them via
186 # cxxldlibflags to libjava_invoke.
187 if {$INTERPRETER == "yes" && $gij != ""} {
188 libjava_invoke $errname "gij test" opts $gij \
189 "" $resultfile $cxxldlibflags \
190 -classpath $file $main
193 # When we succeed we remove all our clutter.
194 eval gcj_cleanup [glob -nocomplain -- ${main}.*] \
195 [list $main lib${main}.${so_extension}]
200 # Compile a single C file and produce a binary. OPTIONS is a list of
201 # options to pass to the compiler. Returns 0 on failure, 1 on
203 proc gcj_jni_invocation_compile_c_to_binary {file {options {}}} {
206 verbose "options: $options"
207 set options_cxx $options
210 set filename [file tail $file]
211 set name [file rootname $filename]
213 # Set some darwin specific options
214 if { [istarget "*-*-darwin*"] } {
215 lappend options "additional_flags= -bind_at_load -multiply_defined suppress"
217 # Find the generated header.
218 lappend options "additional_flags=-I. -I.. -I$srcdir/$subdir"
220 # Find jni.h and jni_md.h.
221 lappend options "additional_flags=-I$srcdir/../include -I$srcdir/../classpath/include"
224 lappend options "additional_flags=$options_cxx"
226 set x [libjava_prune_warnings \
227 [target_compile $file $name executable $options]]
229 verbose "target_compile failed: $x" 2
230 fail "$filename compilation"
234 pass "$filename compilation"
238 # Do all the work for a single invocation API test. Return 0 on
240 proc gcj_jni_invocation_test_one {file} {
246 # The base name. We use it for several purposes.
247 set main [file rootname [file tail $file]]
248 if {! [runtest_file_p $runtests $main]} {
253 # if {! [bytecompile_file $file [pwd]]} {
254 # fail "bytecompile $file"
255 # # FIXME - should use `untested' on all remaining tests.
256 # # But that is hard.
259 # pass "bytecompile $file"
261 set cfile [file rootname $file].c
262 # Darwin needs -liconv linked, otherwise we get some unresolved.
263 # If you're building the compiler with --prefix set to a place
264 # where it's not yet installed, then the linker won't be able to
265 # find the libgcc used by libffi.dylib. We could pass the
266 # -dylib_file option, but that's complicated, and it's much easier
267 # to just make the linker find libgcc using -L options.
268 # Similar logic applies to libgcj.
269 if { [istarget "*-*-darwin*"] } {
270 set cxxflags "-L../.libs -shared-libgcc -ljvm -lgcj -liconv"
273 if [info exists LIBJAVA] {
274 set libjava $LIBJAVA;
276 set libjava [libjava_find_lib libjava gcj]
278 set cxxflags "$libjava -ljvm"
281 if { [istarget "*-*-solaris*"] } {
282 lappend cxxflags "-lsocket"
285 if {! [gcj_jni_invocation_compile_c_to_binary $cfile $cxxflags]} {
290 set resultfile [file rootname $file].out
292 set env(CLASSPATH) $file
293 verbose "CLASSPATH = $env(CLASSPATH)"
294 if {! [gcj_invoke $main $resultfile ""]} {
301 # We purposely ignore errors here; we still want to run the other
303 set errname [file rootname [file tail $file]]
305 # When we succeed we remove all our clutter.
306 eval gcj_cleanup [glob -nocomplain -- ${main}.*] \
313 proc gcj_jni_run {} {
315 global build_triplet host_triplet
317 # For now we only test JNI on native builds.
318 if {$build_triplet == $host_triplet} {
319 catch { lsort [glob -nocomplain ${srcdir}/${subdir}/*.jar] } srcfiles
321 foreach x $srcfiles {
325 # Run JNI invocation API tests
326 catch { lsort [glob -nocomplain ${srcdir}/${subdir}/invocation/*.jar] } srcfiles
328 foreach x $srcfiles {
329 gcj_jni_invocation_test_one $x
332 verbose "JNI tests not run in cross-compilation environment"