jni.exp 11 KB

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