1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4#[=======================================================================[.rst:
5FindJNI
6-------
7
8Find Java Native Interface (JNI) libraries.
9
10JNI enables Java code running in a Java Virtual Machine (JVM) to call
11and be called by native applications and libraries written in other
12languages such as C, C++.
13
14This module finds if Java is installed and determines where the
15include files and libraries are.  It also determines what the name of
16the library is.  The caller may set variable ``JAVA_HOME`` to specify a
17Java installation prefix explicitly.
18
19Result Variables
20^^^^^^^^^^^^^^^^
21
22This module sets the following result variables:
23
24``JNI_INCLUDE_DIRS``
25  the include dirs to use
26``JNI_LIBRARIES``
27  the libraries to use (JAWT and JVM)
28``JNI_FOUND``
29  TRUE if JNI headers and libraries were found.
30
31Cache Variables
32^^^^^^^^^^^^^^^
33
34The following cache variables are also available to set or use:
35
36``JAVA_AWT_LIBRARY``
37  the path to the Java AWT Native Interface (JAWT) library
38``JAVA_JVM_LIBRARY``
39  the path to the Java Virtual Machine (JVM) library
40``JAVA_INCLUDE_PATH``
41  the include path to jni.h
42``JAVA_INCLUDE_PATH2``
43  the include path to jni_md.h and jniport.h
44``JAVA_AWT_INCLUDE_PATH``
45  the include path to jawt.h
46#]=======================================================================]
47
48# Expand {libarch} occurrences to java_libarch subdirectory(-ies) and set ${_var}
49macro(java_append_library_directories _var)
50    # Determine java arch-specific library subdir
51    # Mostly based on openjdk/jdk/make/common/shared/Platform.gmk as of openjdk
52    # 1.6.0_18 + icedtea patches. However, it would be much better to base the
53    # guess on the first part of the GNU config.guess platform triplet.
54    if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
55      if(CMAKE_LIBRARY_ARCHITECTURE STREQUAL "x86_64-linux-gnux32")
56        set(_java_libarch "x32" "amd64" "i386")
57      else()
58        set(_java_libarch "amd64" "i386")
59      endif()
60    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^i.86$")
61        set(_java_libarch "i386")
62    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64")
63        set(_java_libarch "arm64" "aarch64")
64    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^alpha")
65        set(_java_libarch "alpha")
66    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
67        # Subdir is "arm" for both big-endian (arm) and little-endian (armel).
68        set(_java_libarch "arm" "aarch32")
69    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
70        # mips* machines are bi-endian mostly so processor does not tell
71        # endianness of the underlying system.
72        set(_java_libarch "${CMAKE_SYSTEM_PROCESSOR}"
73            "mips" "mipsel" "mipseb" "mipsr6" "mipsr6el"
74            "mips64" "mips64el" "mips64r6" "mips64r6el"
75            "mipsn32" "mipsn32el" "mipsn32r6" "mipsn32r6el")
76    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le")
77        set(_java_libarch "ppc64" "ppc64le")
78    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64")
79        set(_java_libarch "ppc64" "ppc")
80    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
81        set(_java_libarch "ppc" "ppc64")
82    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^sparc")
83        # Both flavors can run on the same processor
84        set(_java_libarch "${CMAKE_SYSTEM_PROCESSOR}" "sparc" "sparcv9")
85    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(parisc|hppa)")
86        set(_java_libarch "parisc" "parisc64")
87    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^s390")
88        # s390 binaries can run on s390x machines
89        set(_java_libarch "${CMAKE_SYSTEM_PROCESSOR}" "s390" "s390x")
90    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^sh")
91        set(_java_libarch "sh")
92    else()
93        set(_java_libarch "${CMAKE_SYSTEM_PROCESSOR}")
94    endif()
95
96    # Append default list architectures if CMAKE_SYSTEM_PROCESSOR was empty or
97    # system is non-Linux (where the code above has not been well tested)
98    if(NOT _java_libarch OR NOT (CMAKE_SYSTEM_NAME MATCHES "Linux"))
99        list(APPEND _java_libarch "i386" "amd64" "ppc")
100    endif()
101
102    # Sometimes ${CMAKE_SYSTEM_PROCESSOR} is added to the list to prefer
103    # current value to a hardcoded list. Remove possible duplicates.
104    list(REMOVE_DUPLICATES _java_libarch)
105
106    foreach(_path ${ARGN})
107        if(_path MATCHES "{libarch}")
108            foreach(_libarch ${_java_libarch})
109                string(REPLACE "{libarch}" "${_libarch}" _newpath "${_path}")
110                if(EXISTS ${_newpath})
111                    list(APPEND ${_var} "${_newpath}")
112                endif()
113            endforeach()
114        else()
115            if(EXISTS ${_path})
116                list(APPEND ${_var} "${_path}")
117            endif()
118        endif()
119    endforeach()
120endmacro()
121
122include(${CMAKE_CURRENT_LIST_DIR}/CMakeFindJavaCommon.cmake)
123
124# Save CMAKE_FIND_FRAMEWORK
125if(DEFINED CMAKE_FIND_FRAMEWORK)
126  set(_JNI_CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK})
127else()
128  unset(_JNI_CMAKE_FIND_FRAMEWORK)
129endif()
130
131if(_JAVA_HOME_EXPLICIT)
132  set(CMAKE_FIND_FRAMEWORK NEVER)
133endif()
134
135set(JAVA_AWT_LIBRARY_DIRECTORIES)
136if(_JAVA_HOME)
137  JAVA_APPEND_LIBRARY_DIRECTORIES(JAVA_AWT_LIBRARY_DIRECTORIES
138    ${_JAVA_HOME}/jre/lib/{libarch}
139    ${_JAVA_HOME}/jre/lib
140    ${_JAVA_HOME}/lib/{libarch}
141    ${_JAVA_HOME}/lib
142    ${_JAVA_HOME}
143    )
144endif()
145
146if (WIN32)
147  set (_JNI_HINTS)
148  execute_process(COMMAND REG QUERY HKLM\\SOFTWARE\\JavaSoft\\JDK
149    RESULT_VARIABLE _JNI_RESULT
150    OUTPUT_VARIABLE _JNI_VERSIONS
151    ERROR_QUIET)
152  if (NOT  _JNI_RESULT)
153    string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\JDK\\\\[0-9.]+" _JNI_VERSIONS "${_JNI_VERSIONS}")
154    if (_JNI_VERSIONS)
155      # sort versions. Most recent first
156      ## handle version 9 apart from other versions to get correct ordering
157      set (_JNI_V9 ${_JNI_VERSIONS})
158      list (FILTER _JNI_VERSIONS EXCLUDE REGEX "JDK\\\\9")
159      list (SORT _JNI_VERSIONS)
160      list (REVERSE _JNI_VERSIONS)
161      list (FILTER _JNI_V9 INCLUDE REGEX "JDK\\\\9")
162      list (SORT _JNI_V9)
163      list (REVERSE _JNI_V9)
164      list (APPEND _JNI_VERSIONS ${_JNI_V9})
165      foreach (_JNI_HINT IN LISTS _JNI_VERSIONS)
166        list(APPEND _JNI_HINTS "[${_JNI_HINT};JavaHome]")
167      endforeach()
168    endif()
169  endif()
170
171  foreach (_JNI_HINT IN LISTS _JNI_HINTS)
172    list(APPEND JAVA_AWT_LIBRARY_DIRECTORIES "${_JNI_HINT}/lib")
173  endforeach()
174
175  get_filename_component(java_install_version
176    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit;CurrentVersion]" NAME)
177
178  list(APPEND JAVA_AWT_LIBRARY_DIRECTORIES
179    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/lib"
180    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/lib"
181    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.7;JavaHome]/lib"
182    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.6;JavaHome]/lib"
183    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/lib"
184    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/lib"
185    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/lib"
186    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\${java_install_version};JavaHome]/lib"
187    )
188endif()
189
190set(_JNI_JAVA_DIRECTORIES_BASE
191  /usr/lib/jvm/java
192  /usr/lib/java
193  /usr/lib/jvm
194  /usr/local/lib/java
195  /usr/local/share/java
196  /usr/lib/j2sdk1.4-sun
197  /usr/lib/j2sdk1.5-sun
198  /opt/sun-jdk-1.5.0.04
199  /usr/lib/jvm/java-6-sun
200  /usr/lib/jvm/java-1.5.0-sun
201  /usr/lib/jvm/java-6-sun-1.6.0.00       # can this one be removed according to #8821 ? Alex
202  /usr/lib/jvm/java-6-openjdk
203  /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0        # fedora
204  # Debian specific paths for default JVM
205  /usr/lib/jvm/default-java
206  # Arch Linux specific paths for default JVM
207  /usr/lib/jvm/default
208  # Ubuntu specific paths for default JVM
209  /usr/lib/jvm/java-11-openjdk-{libarch}    # Ubuntu 18.04 LTS
210  /usr/lib/jvm/java-8-openjdk-{libarch}     # Ubuntu 15.10
211  /usr/lib/jvm/java-7-openjdk-{libarch}     # Ubuntu 15.10
212  /usr/lib/jvm/java-6-openjdk-{libarch}     # Ubuntu 15.10
213  # OpenBSD specific paths for default JVM
214  /usr/local/jdk-1.7.0
215  /usr/local/jre-1.7.0
216  /usr/local/jdk-1.6.0
217  /usr/local/jre-1.6.0
218  # FreeBSD specific paths for default JVM
219  /usr/local/openjdk15
220  /usr/local/openjdk14
221  /usr/local/openjdk13
222  /usr/local/openjdk12
223  /usr/local/openjdk11
224  /usr/local/openjdk8
225  /usr/local/openjdk7
226  # SuSE specific paths for default JVM
227  /usr/lib64/jvm/java
228  /usr/lib64/jvm/jre
229  )
230
231set(_JNI_JAVA_AWT_LIBRARY_TRIES)
232set(_JNI_JAVA_INCLUDE_TRIES)
233
234foreach(_java_dir IN LISTS _JNI_JAVA_DIRECTORIES_BASE)
235  list(APPEND _JNI_JAVA_AWT_LIBRARY_TRIES
236    ${_java_dir}/jre/lib/{libarch}
237    ${_java_dir}/jre/lib
238    ${_java_dir}/lib/{libarch}
239    ${_java_dir}/lib
240    ${_java_dir}
241  )
242  list(APPEND _JNI_JAVA_INCLUDE_TRIES
243    ${_java_dir}/include
244  )
245endforeach()
246
247JAVA_APPEND_LIBRARY_DIRECTORIES(JAVA_AWT_LIBRARY_DIRECTORIES
248    ${_JNI_JAVA_AWT_LIBRARY_TRIES}
249  )
250
251set(JAVA_JVM_LIBRARY_DIRECTORIES)
252foreach(dir ${JAVA_AWT_LIBRARY_DIRECTORIES})
253  list(APPEND JAVA_JVM_LIBRARY_DIRECTORIES
254    "${dir}"
255    "${dir}/client"
256    "${dir}/server"
257    # IBM SDK, Java Technology Edition, specific paths
258    "${dir}/j9vm"
259    "${dir}/default"
260    )
261endforeach()
262
263set(JAVA_AWT_INCLUDE_DIRECTORIES)
264if(_JAVA_HOME)
265  list(APPEND JAVA_AWT_INCLUDE_DIRECTORIES ${_JAVA_HOME}/include)
266endif()
267if (WIN32)
268  foreach (_JNI_HINT IN LISTS _JNI_HINTS)
269    list(APPEND JAVA_AWT_INCLUDE_DIRECTORIES "${_JNI_HINT}/include")
270  endforeach()
271  list(APPEND JAVA_AWT_INCLUDE_DIRECTORIES
272    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/include"
273    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/include"
274    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.7;JavaHome]/include"
275    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.6;JavaHome]/include"
276    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/include"
277    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/include"
278    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/include"
279    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\${java_install_version};JavaHome]/include"
280    )
281endif()
282
283JAVA_APPEND_LIBRARY_DIRECTORIES(JAVA_AWT_INCLUDE_DIRECTORIES
284  ${_JNI_JAVA_INCLUDE_TRIES}
285  )
286
287foreach(JAVA_PROG "${JAVA_RUNTIME}" "${JAVA_COMPILE}" "${JAVA_ARCHIVE}")
288  get_filename_component(jpath "${JAVA_PROG}" PATH)
289  foreach(JAVA_INC_PATH ../include ../java/include ../share/java/include)
290    if(EXISTS ${jpath}/${JAVA_INC_PATH})
291      list(APPEND JAVA_AWT_INCLUDE_DIRECTORIES "${jpath}/${JAVA_INC_PATH}")
292    endif()
293  endforeach()
294  foreach(JAVA_LIB_PATH
295    ../lib ../jre/lib ../jre/lib/i386
296    ../java/lib ../java/jre/lib ../java/jre/lib/i386
297    ../share/java/lib ../share/java/jre/lib ../share/java/jre/lib/i386)
298    if(EXISTS ${jpath}/${JAVA_LIB_PATH})
299      list(APPEND JAVA_AWT_LIBRARY_DIRECTORIES "${jpath}/${JAVA_LIB_PATH}")
300    endif()
301  endforeach()
302endforeach()
303
304if(APPLE)
305  if(CMAKE_FIND_FRAMEWORK STREQUAL "ONLY")
306    set(_JNI_SEARCHES FRAMEWORK)
307  elseif(CMAKE_FIND_FRAMEWORK STREQUAL "NEVER")
308    set(_JNI_SEARCHES NORMAL)
309  elseif(CMAKE_FIND_FRAMEWORK STREQUAL "LAST")
310    set(_JNI_SEARCHES NORMAL FRAMEWORK)
311  else()
312    set(_JNI_SEARCHES FRAMEWORK NORMAL)
313  endif()
314  set(_JNI_FRAMEWORK_JVM NAMES JavaVM)
315  set(_JNI_FRAMEWORK_JAWT "${_JNI_FRAMEWORK_JVM}")
316else()
317  set(_JNI_SEARCHES NORMAL)
318endif()
319
320set(_JNI_NORMAL_JVM
321  NAMES jvm
322  PATHS ${JAVA_JVM_LIBRARY_DIRECTORIES}
323  )
324
325set(_JNI_NORMAL_JAWT
326  NAMES jawt
327  PATHS ${JAVA_AWT_LIBRARY_DIRECTORIES}
328  )
329
330foreach(search ${_JNI_SEARCHES})
331  find_library(JAVA_JVM_LIBRARY ${_JNI_${search}_JVM})
332  find_library(JAVA_AWT_LIBRARY ${_JNI_${search}_JAWT})
333  if(JAVA_JVM_LIBRARY)
334    break()
335  endif()
336endforeach()
337unset(_JNI_SEARCHES)
338unset(_JNI_FRAMEWORK_JVM)
339unset(_JNI_FRAMEWORK_JAWT)
340unset(_JNI_NORMAL_JVM)
341unset(_JNI_NORMAL_JAWT)
342
343# Find headers matching the library.
344if("${JAVA_JVM_LIBRARY};${JAVA_AWT_LIBRARY};" MATCHES "(/JavaVM.framework|-framework JavaVM);")
345  set(CMAKE_FIND_FRAMEWORK ONLY)
346else()
347  set(CMAKE_FIND_FRAMEWORK NEVER)
348endif()
349
350# add in the include path
351find_path(JAVA_INCLUDE_PATH jni.h
352  ${JAVA_AWT_INCLUDE_DIRECTORIES}
353)
354
355find_path(JAVA_INCLUDE_PATH2 NAMES jni_md.h jniport.h
356  PATHS
357  ${JAVA_INCLUDE_PATH}
358  ${JAVA_INCLUDE_PATH}/darwin
359  ${JAVA_INCLUDE_PATH}/win32
360  ${JAVA_INCLUDE_PATH}/linux
361  ${JAVA_INCLUDE_PATH}/freebsd
362  ${JAVA_INCLUDE_PATH}/openbsd
363  ${JAVA_INCLUDE_PATH}/solaris
364  ${JAVA_INCLUDE_PATH}/hp-ux
365  ${JAVA_INCLUDE_PATH}/alpha
366  ${JAVA_INCLUDE_PATH}/aix
367)
368
369find_path(JAVA_AWT_INCLUDE_PATH jawt.h
370  ${JAVA_INCLUDE_PATH}
371)
372
373# Restore CMAKE_FIND_FRAMEWORK
374if(DEFINED _JNI_CMAKE_FIND_FRAMEWORK)
375  set(CMAKE_FIND_FRAMEWORK ${_JNI_CMAKE_FIND_FRAMEWORK})
376  unset(_JNI_CMAKE_FIND_FRAMEWORK)
377else()
378  unset(CMAKE_FIND_FRAMEWORK)
379endif()
380
381include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
382FIND_PACKAGE_HANDLE_STANDARD_ARGS(JNI  DEFAULT_MSG  JAVA_AWT_LIBRARY
383                                                    JAVA_JVM_LIBRARY
384                                                    JAVA_INCLUDE_PATH
385                                                    JAVA_INCLUDE_PATH2
386                                                    JAVA_AWT_INCLUDE_PATH)
387
388mark_as_advanced(
389  JAVA_AWT_LIBRARY
390  JAVA_JVM_LIBRARY
391  JAVA_AWT_INCLUDE_PATH
392  JAVA_INCLUDE_PATH
393  JAVA_INCLUDE_PATH2
394)
395
396set(JNI_LIBRARIES
397  ${JAVA_AWT_LIBRARY}
398  ${JAVA_JVM_LIBRARY}
399)
400
401set(JNI_INCLUDE_DIRS
402  ${JAVA_INCLUDE_PATH}
403  ${JAVA_INCLUDE_PATH2}
404  ${JAVA_AWT_INCLUDE_PATH}
405)
406