Imported Upstream version 3.25.0
[platform/upstream/cmake.git] / Modules / UseJava.cmake
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:
5 UseJava
6 -------
7
8 This file provides support for ``Java``.  It is assumed that
9 :module:`FindJava` has already been loaded.  See :module:`FindJava` for
10 information on how to load Java into your ``CMake`` project.
11
12 Synopsis
13 ^^^^^^^^
14
15 .. parsed-literal::
16
17   `Creating and Installing JARS`_
18     `add_jar`_ (<target_name> [SOURCES] <source1> [<source2>...] ...)
19     `install_jar`_ (<target_name> DESTINATION <destination> [COMPONENT <component>])
20     `install_jni_symlink`_ (<target_name> DESTINATION <destination> [COMPONENT <component>])
21
22   `Header Generation`_
23     `create_javah`_ ((TARGET <target> | GENERATED_FILES <VAR>) CLASSES <class>... ...)
24
25   `Exporting JAR Targets`_
26     `install_jar_exports`_ (TARGETS <jars>... FILE <filename> DESTINATION <destination> ...)
27     `export_jars`_ (TARGETS <jars>... [NAMESPACE <namespace>] FILE <filename>)
28
29   `Finding JARs`_
30     `find_jar`_ (<VAR> NAMES <name1> [<name2>...] [PATHS <path1> [<path2>... ENV <var>]] ...)
31
32   `Creating Java Documentation`_
33     `create_javadoc`_ (<VAR> (PACKAGES <pkg1> [<pkg2>...] | FILES <file1> [<file2>...]) ...)
34
35 Creating And Installing JARs
36 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37
38 .. _add_jar:
39
40 .. command:: add_jar
41
42   Creates a jar file containing java objects and, optionally, resources::
43
44     add_jar(<target_name>
45             [SOURCES] <source1> [<source2>...] [<resource1>...]
46             [RESOURCES NAMESPACE <ns1> <resource1>... [NAMESPACE <nsX> <resourceX>...]... ]
47             [INCLUDE_JARS <jar1> [<jar2>...]]
48             [ENTRY_POINT <entry>]
49             [VERSION <version>]
50             [MANIFEST <manifest>]
51             [OUTPUT_NAME <name>]
52             [OUTPUT_DIR <dir>]
53             [GENERATE_NATIVE_HEADERS <target>
54                                      [DESTINATION (<dir>|INSTALL <dir> [BUILD <dir>])]]
55             )
56
57   This command creates a ``<target_name>.jar``.  It compiles the given
58   ``<source>`` files and adds the given ``<resource>`` files to
59   the jar file.  Source files can be java files or listing files
60   (prefixed by ``@``).  If only resource files are given then just a jar file
61   is created.
62
63   ``SOURCES``
64     Compiles the specified source files and adds the result in the jar file.
65
66     .. versionadded:: 3.4
67       Support for response files, prefixed by ``@``.
68
69   ``RESOURCES``
70     .. versionadded:: 3.21
71
72     Adds the named ``<resource>`` files to the jar by stripping the source file
73     path and placing the file beneath ``<ns>`` within the jar.
74
75     For example::
76
77       RESOURCES NAMESPACE "/com/my/namespace" "a/path/to/resource.txt"
78
79     results in a resource accessible via ``/com/my/namespace/resource.txt``
80     within the jar.
81
82     Resources may be added without adjusting the namespace by adding them to
83     the list of ``SOURCES`` (original behavior), in this case, resource
84     paths must be relative to ``CMAKE_CURRENT_SOURCE_DIR``.  Adding resources
85     without using the ``RESOURCES`` parameter in out of source builds will
86     almost certainly result in confusion.
87
88     .. note::
89
90       Adding resources via the ``SOURCES`` parameter relies upon a hard-coded
91       list of file extensions which are tested to determine whether they
92       compile (e.g. File.java). ``SOURCES`` files which match the extensions
93       are compiled. Files which do not match are treated as resources. To
94       include uncompiled resources matching those file extensions use
95       the ``RESOURCES`` parameter.
96
97   ``INCLUDE_JARS``
98     The list of jars are added to the classpath when compiling the java sources
99     and also to the dependencies of the target. ``INCLUDE_JARS`` also accepts
100     other target names created by ``add_jar()``. For backwards compatibility,
101     jar files listed as sources are ignored (as they have been since the first
102     version of this module).
103
104   ``ENTRY_POINT``
105     Defines an entry point in the jar file.
106
107   ``VERSION``
108     Adds a version to the target output name.
109
110     The following example will create a jar file with the name
111     ``shibboleet-1.2.0.jar`` and will create a symlink ``shibboleet.jar``
112     pointing to the jar with the version information.
113
114     .. code-block:: cmake
115
116       add_jar(shibboleet shibbotleet.java VERSION 1.2.0)
117
118   ``MANIFEST``
119     Defines a custom manifest for the jar.
120
121   ``OUTPUT_NAME``
122     Specify a different output name for the target.
123
124   ``OUTPUT_DIR``
125     Sets the directory where the jar file will be generated. If not specified,
126     :variable:`CMAKE_CURRENT_BINARY_DIR` is used as the output directory.
127
128   ``GENERATE_NATIVE_HEADERS``
129     .. versionadded:: 3.11
130
131     Generates native header files for methods declared as native. These files
132     provide the connective glue that allow your Java and C code to interact.
133     An INTERFACE target will be created for an easy usage of generated files.
134     Sub-option ``DESTINATION`` can be used to specify the output directory for
135     generated header files.
136
137     This option requires, at least, version 1.8 of the JDK.
138
139     For an optimum usage of this option, it is recommended to include module
140     JNI before any call to ``add_jar()``. The produced target for native
141     headers can then be used to compile C/C++ sources with the
142     :command:`target_link_libraries` command.
143
144     .. code-block:: cmake
145
146       find_package(JNI)
147       add_jar(foo foo.java GENERATE_NATIVE_HEADERS foo-native)
148       add_library(bar bar.cpp)
149       target_link_libraries(bar PRIVATE foo-native)
150
151     .. versionadded:: 3.20
152       ``DESTINATION`` sub-option now supports the possibility to specify
153       different output directories for ``BUILD`` and ``INSTALL`` steps. If
154       ``BUILD`` directory is not specified, a default directory will be used.
155
156       To export the interface target generated by ``GENERATE_NATIVE_HEADERS``
157       option, sub-option ``INSTALL`` of ``DESTINATION`` is required:
158
159       .. code-block:: cmake
160
161         add_jar(foo foo.java GENERATE_NATIVE_HEADERS foo-native
162                              DESTINATION INSTALL include)
163         install(TARGETS foo-native EXPORT native)
164         install(DIRECTORY "$<TARGET_PROPERTY:foo-native,NATIVE_HEADERS_DIRECTORY>/"
165                 DESTINATION include)
166         install(EXPORT native DESTINATION /to/export NAMESPACE foo)
167
168   Some variables can be set to customize the behavior of ``add_jar()`` as well
169   as the java compiler:
170
171   ``CMAKE_JAVA_COMPILE_FLAGS``
172     Specify additional flags to java compiler.
173
174   ``CMAKE_JAVA_INCLUDE_PATH``
175     Specify additional paths to the class path.
176
177   ``CMAKE_JNI_TARGET``
178     If the target is a JNI library, sets this boolean variable to ``TRUE`` to
179     enable creation of a JNI symbolic link (see also
180     :ref:`install_jni_symlink() <install_jni_symlink>`).
181
182   ``CMAKE_JAR_CLASSES_PREFIX``
183     If multiple jars should be produced from the same java source filetree,
184     to prevent the accumulation of duplicate class files in subsequent jars,
185     set/reset ``CMAKE_JAR_CLASSES_PREFIX`` prior to calling the ``add_jar()``:
186
187     .. code-block:: cmake
188
189       set(CMAKE_JAR_CLASSES_PREFIX com/redhat/foo)
190       add_jar(foo foo.java)
191
192       set(CMAKE_JAR_CLASSES_PREFIX com/redhat/bar)
193       add_jar(bar bar.java)
194
195   The ``add_jar()`` function sets the following target properties on
196   ``<target_name>``:
197
198   ``INSTALL_FILES``
199     The files which should be installed.  This is used by
200     :ref:`install_jar() <install_jar>`.
201   ``JNI_SYMLINK``
202     The JNI symlink which should be installed.  This is used by
203     :ref:`install_jni_symlink() <install_jni_symlink>`.
204   ``JAR_FILE``
205     The location of the jar file so that you can include it.
206   ``CLASSDIR``
207     The directory where the class files can be found.  For example to use them
208     with ``javah``.
209   ``NATIVE_HEADERS_DIRECTORY``
210     .. versionadded:: 3.20
211
212     The directory where native headers are generated. Defined when option
213     ``GENERATE_NATIVE_HEADERS`` is specified.
214
215 .. _install_jar:
216
217 .. command:: install_jar
218
219   This command installs the jar file to the given destination::
220
221    install_jar(<target_name> <destination>)
222    install_jar(<target_name> DESTINATION <destination> [COMPONENT <component>])
223
224   This command installs the ``<target_name>`` file to the given
225   ``<destination>``.  It should be called in the same scope as
226   :ref:`add_jar() <add_jar>` or it will fail.
227
228   .. versionadded:: 3.4
229     The second signature with ``DESTINATION`` and ``COMPONENT`` options.
230
231   ``DESTINATION``
232     Specify the directory on disk to which a file will be installed.
233
234   ``COMPONENT``
235     Specify an installation component name with which the install rule is
236     associated, such as "runtime" or "development".
237
238   The ``install_jar()`` command sets the following target properties
239   on ``<target_name>``:
240
241   ``INSTALL_DESTINATION``
242     Holds the ``<destination>`` as described above, and is used by
243     :ref:`install_jar_exports() <install_jar_exports>`.
244
245 .. _install_jni_symlink:
246
247 .. command:: install_jni_symlink
248
249   Installs JNI symlinks for target generated by :ref:`add_jar() <add_jar>`::
250
251    install_jni_symlink(<target_name> <destination>)
252    install_jni_symlink(<target_name> DESTINATION <destination> [COMPONENT <component>])
253
254   This command installs the ``<target_name>`` JNI symlinks to the given
255   ``<destination>``.  It should be called in the same scope as
256   :ref:`add_jar() <add_jar>` or it will fail.
257
258   .. versionadded:: 3.4
259     The second signature with ``DESTINATION`` and ``COMPONENT`` options.
260
261   ``DESTINATION``
262     Specify the directory on disk to which a file will be installed.
263
264   ``COMPONENT``
265     Specify an installation component name with which the install rule is
266     associated, such as "runtime" or "development".
267
268   Utilize the following commands to create a JNI symbolic link:
269
270   .. code-block:: cmake
271
272     set(CMAKE_JNI_TARGET TRUE)
273     add_jar(shibboleet shibbotleet.java VERSION 1.2.0)
274     install_jar(shibboleet ${LIB_INSTALL_DIR}/shibboleet)
275     install_jni_symlink(shibboleet ${JAVA_LIB_INSTALL_DIR})
276
277 Header Generation
278 ^^^^^^^^^^^^^^^^^
279
280 .. _create_javah:
281
282 .. command:: create_javah
283
284   .. versionadded:: 3.4
285
286   Generates C header files for java classes::
287
288    create_javah(TARGET <target> | GENERATED_FILES <VAR>
289                 CLASSES <class>...
290                 [CLASSPATH <classpath>...]
291                 [DEPENDS <depend>...]
292                 [OUTPUT_NAME <path>|OUTPUT_DIR <path>]
293                 )
294
295   .. deprecated:: 3.11
296     This command will no longer be supported starting with version 10 of the JDK
297     due to the `suppression of javah tool <https://openjdk.java.net/jeps/313>`_.
298     The :ref:`add_jar(GENERATE_NATIVE_HEADERS) <add_jar>` command should be
299     used instead.
300
301   Create C header files from java classes. These files provide the connective
302   glue that allow your Java and C code to interact.
303
304   There are two main signatures for ``create_javah()``.  The first signature
305   returns generated files through variable specified by the ``GENERATED_FILES``
306   option.  For example:
307
308   .. code-block:: cmake
309
310     create_javah(GENERATED_FILES files_headers
311       CLASSES org.cmake.HelloWorld
312       CLASSPATH hello.jar
313     )
314
315   The second signature for ``create_javah()`` creates a target which
316   encapsulates header files generation. E.g.
317
318   .. code-block:: cmake
319
320     create_javah(TARGET target_headers
321       CLASSES org.cmake.HelloWorld
322       CLASSPATH hello.jar
323     )
324
325   Both signatures share same options.
326
327   ``CLASSES``
328     Specifies Java classes used to generate headers.
329
330   ``CLASSPATH``
331     Specifies various paths to look up classes. Here ``.class`` files, jar
332     files or targets created by command add_jar can be used.
333
334   ``DEPENDS``
335     Targets on which the javah target depends.
336
337   ``OUTPUT_NAME``
338     Concatenates the resulting header files for all the classes listed by
339     option ``CLASSES`` into ``<path>``.  Same behavior as option ``-o`` of
340     ``javah`` tool.
341
342   ``OUTPUT_DIR``
343     Sets the directory where the header files will be generated.  Same behavior
344     as option ``-d`` of ``javah`` tool.  If not specified,
345     :variable:`CMAKE_CURRENT_BINARY_DIR` is used as the output directory.
346
347 Exporting JAR Targets
348 ^^^^^^^^^^^^^^^^^^^^^
349
350 .. _install_jar_exports:
351
352 .. command:: install_jar_exports
353
354   .. versionadded:: 3.7
355
356   Installs a target export file::
357
358    install_jar_exports(TARGETS <jars>...
359                        [NAMESPACE <namespace>]
360                        FILE <filename>
361                        DESTINATION <destination> [COMPONENT <component>])
362
363   This command installs a target export file ``<filename>`` for the named jar
364   targets to the given ``<destination>`` directory.  Its function is similar to
365   that of :command:`install(EXPORT)`.
366
367   ``TARGETS``
368     List of targets created by :ref:`add_jar() <add_jar>` command.
369
370   ``NAMESPACE``
371     .. versionadded:: 3.9
372
373     The ``<namespace>`` value will be prepend to the target names as they are
374     written to the import file.
375
376   ``FILE``
377     Specify name of the export file.
378
379
380   ``DESTINATION``
381     Specify the directory on disk to which a file will be installed.
382
383   ``COMPONENT``
384     Specify an installation component name with which the install rule is
385     associated, such as "runtime" or "development".
386
387 .. _export_jars:
388
389 .. command:: export_jars
390
391   .. versionadded:: 3.7
392
393   Writes a target export file::
394
395    export_jars(TARGETS <jars>...
396                [NAMESPACE <namespace>]
397                FILE <filename>)
398
399   This command writes a target export file ``<filename>`` for the named ``<jars>``
400   targets.  Its function is similar to that of :command:`export`.
401
402   ``TARGETS``
403     List of targets created by :ref:`add_jar() <add_jar>` command.
404
405   ``NAMESPACE``
406     .. versionadded:: 3.9
407
408     The ``<namespace>`` value will be prepend to the target names as they are
409     written to the import file.
410
411   ``FILE``
412     Specify name of the export file.
413
414 Finding JARs
415 ^^^^^^^^^^^^
416
417 .. _find_jar:
418
419 .. command:: find_jar
420
421   Finds the specified jar file::
422
423     find_jar(<VAR>
424              <name> | NAMES <name1> [<name2>...]
425              [PATHS <path1> [<path2>... ENV <var>]]
426              [VERSIONS <version1> [<version2>]]
427              [DOC "cache documentation string"]
428             )
429
430   This command is used to find a full path to the named jar.  A cache
431   entry named by ``<VAR>`` is created to store the result of this command.
432   If the full path to a jar is found the result is stored in the
433   variable and the search will not repeated unless the variable is
434   cleared.  If nothing is found, the result will be ``<VAR>-NOTFOUND``, and
435   the search will be attempted again next time ``find_jar()`` is invoked with
436   the same variable.
437
438   ``NAMES``
439     Specify one or more possible names for the jar file.
440
441   ``PATHS``
442     Specify directories to search in addition to the default locations.
443     The ``ENV`` var sub-option reads paths from a system environment variable.
444
445   ``VERSIONS``
446     Specify jar versions.
447
448   ``DOC``
449     Specify the documentation string for the ``<VAR>`` cache entry.
450
451 Creating Java Documentation
452 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
453
454 .. _create_javadoc:
455
456 .. command:: create_javadoc
457
458   Creates java documentation based on files and packages::
459
460     create_javadoc(<VAR>
461                    (PACKAGES <pkg1> [<pkg2>...] | FILES <file1> [<file2>...])
462                    [SOURCEPATH <sourcepath>]
463                    [CLASSPATH <classpath>]
464                    [INSTALLPATH <install path>]
465                    [DOCTITLE <the documentation title>]
466                    [WINDOWTITLE <the title of the document>]
467                    [AUTHOR (TRUE|FALSE)]
468                    [USE (TRUE|FALSE)]
469                    [VERSION (TRUE|FALSE)]
470                    )
471
472   The ``create_javadoc()`` command can be used to create java documentation.
473   There are two main signatures for ``create_javadoc()``.
474
475   The first signature works with package names on a path with source files:
476
477   .. code-block:: cmake
478
479     create_javadoc(my_example_doc
480                    PACKAGES com.example.foo com.example.bar
481                    SOURCEPATH "${CMAKE_CURRENT_SOURCE_DIR}"
482                    CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
483                    WINDOWTITLE "My example"
484                    DOCTITLE "<h1>My example</h1>"
485                    AUTHOR TRUE
486                    USE TRUE
487                    VERSION TRUE
488                   )
489
490   The second signature for ``create_javadoc()`` works on a given list of files:
491
492   .. code-block:: cmake
493
494     create_javadoc(my_example_doc
495                    FILES java/A.java java/B.java
496                    CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
497                    WINDOWTITLE "My example"
498                    DOCTITLE "<h1>My example</h1>"
499                    AUTHOR TRUE
500                    USE TRUE
501                    VERSION TRUE
502                   )
503
504   Both signatures share most of the options. For more details please read the
505   javadoc manpage.
506
507   ``PACKAGES``
508     Specify java packages.
509
510   ``FILES``
511     Specify java source files. If relative paths are specified, they are
512     relative to :variable:`CMAKE_CURRENT_SOURCE_DIR`.
513
514   ``SOURCEPATH``
515     Specify the directory where to look for packages. By default,
516     :variable:`CMAKE_CURRENT_SOURCE_DIR` directory is used.
517
518   ``CLASSPATH``
519     Specify where to find user class files. Same behavior as option
520     ``-classpath`` of ``javadoc`` tool.
521
522   ``INSTALLPATH``
523     Specify where to install the java documentation. If you specified, the
524     documentation will be installed to
525     ``${CMAKE_INSTALL_PREFIX}/share/javadoc/<VAR>``.
526
527   ``DOCTITLE``
528     Specify the title to place near the top of the overview summary file.
529     Same behavior as option ``-doctitle`` of ``javadoc`` tool.
530
531   ``WINDOWTITLE``
532     Specify the title to be placed in the HTML ``<title>`` tag. Same behavior
533     as option ``-windowtitle`` of ``javadoc`` tool.
534
535   ``AUTHOR``
536     When value ``TRUE`` is specified, includes the ``@author`` text in the
537     generated docs. Same behavior as option  ``-author`` of ``javadoc`` tool.
538
539   ``USE``
540     When value ``TRUE`` is specified, creates class and package usage pages.
541     Includes one Use page for each documented class and package. Same behavior
542     as option ``-use`` of ``javadoc`` tool.
543
544   ``VERSION``
545     When value ``TRUE`` is specified, includes the version text in the
546     generated docs. Same behavior as option ``-version`` of ``javadoc`` tool.
547 #]=======================================================================]
548
549 function (__java_copy_file src dest comment)
550     add_custom_command(
551         OUTPUT  ${dest}
552         COMMAND ${CMAKE_COMMAND} -E copy_if_different
553         ARGS    ${src}
554                 ${dest}
555         DEPENDS ${src}
556         COMMENT ${comment}
557         VERBATIM
558         )
559 endfunction ()
560
561 function(__java_lcat VAR)
562     foreach(_line IN LISTS ARGN)
563         string(APPEND ${VAR} "${_line}\n")
564     endforeach()
565
566     set(${VAR} "${${VAR}}" PARENT_SCOPE)
567 endfunction()
568
569 function(__java_export_jar VAR TARGET PATH)
570     get_target_property(_jarpath ${TARGET} JAR_FILE)
571     get_filename_component(_jarname ${_jarpath} NAME)
572     set(_target "${_jar_NAMESPACE}${TARGET}")
573     __java_lcat(${VAR}
574       "# Create imported target ${_target}"
575       "add_library(${_target} IMPORTED STATIC)"
576       "set_target_properties(${_target} PROPERTIES"
577       "  IMPORTED_LOCATION \"${PATH}/${_jarname}\""
578       "  JAR_FILE \"${PATH}/${_jarname}\")"
579       ""
580     )
581     set(${VAR} "${${VAR}}" PARENT_SCOPE)
582 endfunction()
583
584 function(__java_copy_resource_namespaces VAR DEST JAVA_RESOURCE_FILES JAVA_RESOURCE_FILES_RELATIVE)
585
586     set(_ns_ID "")
587     set(_ns_VAL "")
588
589     foreach(_item IN LISTS VAR)
590         if(NOT _ns_ID)
591             if(NOT _item STREQUAL "NAMESPACE")
592                 message(FATAL_ERROR "UseJava: Expecting \"NAMESPACE\", got\t\"${_item}\"")
593                 return()
594             endif()
595         endif()
596
597         if(_item STREQUAL "NAMESPACE")
598             set(_ns_VAL "")               # Prepare for next namespace
599             set(_ns_ID "${_item}")
600             continue()
601         endif()
602
603         if( NOT _ns_VAL)
604             # we're expecting the next token to be a namespace value
605             # whatever it is, we're treating it like a namespace
606             set(_ns_VAL "${_item}")
607             continue()
608         endif()
609
610         if(_ns_ID AND _ns_VAL)
611             # We're expecting a file name, check to see if we got one
612             cmake_path(ABSOLUTE_PATH _item OUTPUT_VARIABLE _test_file_name)
613             if (NOT EXISTS "${_test_file_name}")
614                 message(FATAL_ERROR "UseJava: File does not exist:\t${_item}")
615                 return()
616             endif()
617         endif()
618
619         cmake_path(ABSOLUTE_PATH _item OUTPUT_VARIABLE _abs_file_name)
620         cmake_path(GET _item FILENAME _resource_file_name)
621         set(_dest_resource_file_name "${_ns_VAL}/${_resource_file_name}" )
622
623         __java_copy_file( ${_abs_file_name}
624                           ${DEST}/${_dest_resource_file_name}
625                           "Copying ${_item} to the build directory")
626
627         list(APPEND RESOURCE_FILES_LIST           ${DEST}/${_dest_resource_file_name})
628         list(APPEND RELATIVE_RESOURCE_FILES_LIST  ${_dest_resource_file_name})
629
630     endforeach()
631
632     set(${JAVA_RESOURCE_FILES} "${RESOURCE_FILES_LIST}" PARENT_SCOPE)
633     set(${JAVA_RESOURCE_FILES_RELATIVE} "${RELATIVE_RESOURCE_FILES_LIST}" PARENT_SCOPE)
634 endfunction()
635
636 # define helper scripts
637 set(_JAVA_EXPORT_TARGETS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJava/javaTargets.cmake.in)
638 set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJava/Symlinks.cmake)
639
640 if (CMAKE_HOST_WIN32 AND NOT CYGWIN AND CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
641     set(_UseJava_PATH_SEP "$<SEMICOLON>")
642 else ()
643     set(_UseJava_PATH_SEP ":")
644 endif()
645
646 function(add_jar _TARGET_NAME)
647
648     set(options)  # currently there are no zero value args (aka: options)
649     set(oneValueArgs "ENTRY_POINT;MANIFEST;OUTPUT_DIR;;OUTPUT_NAME;VERSION" )
650     set(multiValueArgs "GENERATE_NATIVE_HEADERS;INCLUDE_JARS;RESOURCES;SOURCES" )
651
652     cmake_parse_arguments(PARSE_ARGV 1 _add_jar
653                     "${options}"
654                     "${oneValueArgs}"
655                     "${multiValueArgs}" )
656
657     # In CMake < 2.8.12, add_jar used variables which were set prior to calling
658     # add_jar for customizing the behavior of add_jar. In order to be backwards
659     # compatible, check if any of those variables are set, and use them to
660     # initialize values of the named arguments. (Giving the corresponding named
661     # argument will override the value set here.)
662     #
663     # New features should use named arguments only.
664     if(NOT DEFINED _add_jar_VERSION AND DEFINED CMAKE_JAVA_TARGET_VERSION)
665         set(_add_jar_VERSION "${CMAKE_JAVA_TARGET_VERSION}")
666     endif()
667     if(NOT DEFINED _add_jar_OUTPUT_DIR AND DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR)
668         set(_add_jar_OUTPUT_DIR "${CMAKE_JAVA_TARGET_OUTPUT_DIR}")
669     endif()
670     if(NOT DEFINED _add_jar_OUTPUT_NAME AND DEFINED CMAKE_JAVA_TARGET_OUTPUT_NAME)
671         set(_add_jar_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}")
672         # reset
673         set(CMAKE_JAVA_TARGET_OUTPUT_NAME)
674     endif()
675     if(NOT DEFINED _add_jar_ENTRY_POINT AND DEFINED CMAKE_JAVA_JAR_ENTRY_POINT)
676         set(_add_jar_ENTRY_POINT "${CMAKE_JAVA_JAR_ENTRY_POINT}")
677     endif()
678
679     # This *should* still work if <resources1>... are included without a
680     # named RESOURCES argument.  In that case, the old behavior of potentially
681     # misplacing the within the Jar will behave as previously (incorrectly)
682     set(_JAVA_SOURCE_FILES ${_add_jar_SOURCES} ${_add_jar_UNPARSED_ARGUMENTS})
683
684     if (NOT DEFINED _add_jar_OUTPUT_DIR)
685         set(_add_jar_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
686     else()
687         get_filename_component(_add_jar_OUTPUT_DIR ${_add_jar_OUTPUT_DIR} ABSOLUTE)
688     endif()
689     # ensure output directory exists
690     file (MAKE_DIRECTORY "${_add_jar_OUTPUT_DIR}")
691
692     if (_add_jar_ENTRY_POINT)
693         set(_ENTRY_POINT_OPTION e)
694         set(_ENTRY_POINT_VALUE ${_add_jar_ENTRY_POINT})
695     endif ()
696
697     if (_add_jar_MANIFEST)
698         set(_MANIFEST_OPTION m)
699         get_filename_component (_MANIFEST_VALUE "${_add_jar_MANIFEST}" ABSOLUTE)
700     endif ()
701
702     unset (_GENERATE_NATIVE_HEADERS)
703     if (_add_jar_GENERATE_NATIVE_HEADERS)
704       # Raise an error if JDK version is less than 1.8 because javac -h is not supported
705       # by earlier versions.
706       if (Java_VERSION VERSION_LESS 1.8)
707         message (FATAL_ERROR "ADD_JAR: GENERATE_NATIVE_HEADERS is not supported with this version of Java.")
708       endif()
709
710       unset (_GENERATE_NATIVE_HEADERS_OUTPUT_DESC)
711
712       cmake_parse_arguments (_add_jar_GENERATE_NATIVE_HEADERS "" "" "DESTINATION" ${_add_jar_GENERATE_NATIVE_HEADERS})
713       if (NOT _add_jar_GENERATE_NATIVE_HEADERS_UNPARSED_ARGUMENTS)
714         message (FATAL_ERROR "ADD_JAR: GENERATE_NATIVE_HEADERS: missing required argument.")
715       endif()
716       list (LENGTH _add_jar_GENERATE_NATIVE_HEADERS_UNPARSED_ARGUMENTS length)
717       if (length GREATER 1)
718         list (REMOVE_AT _add_jar_GENERATE_NATIVE_HEADERS_UNPARSED_ARGUMENTS 0)
719         message (FATAL_ERROR "ADD_JAR: GENERATE_NATIVE_HEADERS: ${_add_jar_GENERATE_NATIVE_HEADERS_UNPARSED_ARGUMENTS}: unexpected argument(s).")
720       endif()
721       if (NOT _add_jar_GENERATE_NATIVE_HEADERS_DESTINATION)
722         set (_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir/native_headers")
723       else()
724         list (LENGTH _add_jar_GENERATE_NATIVE_HEADERS_DESTINATION length)
725         if (NOT length EQUAL 1)
726           cmake_parse_arguments (_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION "" "BUILD;INSTALL" "" "${_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION}")
727           if (_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_UNPARSED_ARGUMENTS)
728             message (FATAL_ERROR "ADD_JAR: GENERATE_NATIVE_HEADERS: DESTINATION: ${_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_UNPARSED_ARGUMENTS}: unexpected argument(s).")
729           endif()
730           if (NOT _add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_INSTALL)
731             message (FATAL_ERROR "ADD_JAR: GENERATE_NATIVE_HEADERS: DESTINATION: INSTALL sub-option is required.")
732           endif()
733           if (NOT _add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_BUILD)
734             set(_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_BUILD "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir/native_headers")
735           endif()
736           set(_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION "${_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_BUILD}")
737           set(_GENERATE_NATIVE_HEADERS_OUTPUT_DESC "$<BUILD_INTERFACE:${_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_BUILD}>" "$<INSTALL_INTERFACE:${_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_INSTALL}>")
738         endif()
739       endif()
740
741       set (_GENERATE_NATIVE_HEADERS_TARGET ${_add_jar_GENERATE_NATIVE_HEADERS_UNPARSED_ARGUMENTS})
742       set (_GENERATE_NATIVE_HEADERS_OUTPUT_DIR "${_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION}")
743       set (_GENERATE_NATIVE_HEADERS -h "${_GENERATE_NATIVE_HEADERS_OUTPUT_DIR}")
744       if(NOT _GENERATE_NATIVE_HEADERS_OUTPUT_DESC)
745         set(_GENERATE_NATIVE_HEADERS_OUTPUT_DESC "${_GENERATE_NATIVE_HEADERS_OUTPUT_DIR}")
746       endif()
747     endif()
748
749     if (LIBRARY_OUTPUT_PATH)
750         set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH})
751     else ()
752         set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${_add_jar_OUTPUT_DIR})
753     endif ()
754
755     set(CMAKE_JAVA_INCLUDE_PATH
756         ${CMAKE_JAVA_INCLUDE_PATH}
757         ${CMAKE_CURRENT_SOURCE_DIR}
758         ${CMAKE_JAVA_OBJECT_OUTPUT_PATH}
759         ${CMAKE_JAVA_LIBRARY_OUTPUT_PATH}
760     )
761
762     foreach (JAVA_INCLUDE_DIR IN LISTS CMAKE_JAVA_INCLUDE_PATH)
763        string(APPEND CMAKE_JAVA_INCLUDE_PATH_FINAL "${_UseJava_PATH_SEP}${JAVA_INCLUDE_DIR}")
764     endforeach()
765
766     set(CMAKE_JAVA_CLASS_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir")
767
768     set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}.jar")
769     if (_add_jar_OUTPUT_NAME AND _add_jar_VERSION)
770         set(_JAVA_TARGET_OUTPUT_NAME "${_add_jar_OUTPUT_NAME}-${_add_jar_VERSION}.jar")
771         set(_JAVA_TARGET_OUTPUT_LINK "${_add_jar_OUTPUT_NAME}.jar")
772     elseif (_add_jar_VERSION)
773         set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}-${_add_jar_VERSION}.jar")
774         set(_JAVA_TARGET_OUTPUT_LINK "${_TARGET_NAME}.jar")
775     elseif (_add_jar_OUTPUT_NAME)
776         set(_JAVA_TARGET_OUTPUT_NAME "${_add_jar_OUTPUT_NAME}.jar")
777     endif ()
778
779     set(_JAVA_CLASS_FILES)
780     set(_JAVA_COMPILE_FILES)
781     set(_JAVA_COMPILE_FILELISTS)
782     set(_JAVA_DEPENDS)
783     set(_JAVA_COMPILE_DEPENDS)
784     set(_JAVA_RESOURCE_FILES)
785     set(_JAVA_RESOURCE_FILES_RELATIVE)
786     foreach(_JAVA_SOURCE_FILE IN LISTS _JAVA_SOURCE_FILES)
787         get_filename_component(_JAVA_EXT ${_JAVA_SOURCE_FILE} EXT)
788         get_filename_component(_JAVA_FILE ${_JAVA_SOURCE_FILE} NAME_WE)
789         get_filename_component(_JAVA_PATH ${_JAVA_SOURCE_FILE} PATH)
790         get_filename_component(_JAVA_FULL ${_JAVA_SOURCE_FILE} ABSOLUTE)
791
792         if (_JAVA_SOURCE_FILE MATCHES "^@(.+)$")
793             get_filename_component(_JAVA_FULL ${CMAKE_MATCH_1} ABSOLUTE)
794             list(APPEND _JAVA_COMPILE_FILELISTS ${_JAVA_FULL})
795
796         elseif (_JAVA_EXT MATCHES ".java")
797             file(RELATIVE_PATH _JAVA_REL_BINARY_PATH ${CMAKE_CURRENT_BINARY_DIR} ${_JAVA_FULL})
798             file(RELATIVE_PATH _JAVA_REL_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${_JAVA_FULL})
799             string(LENGTH ${_JAVA_REL_BINARY_PATH} _BIN_LEN)
800             string(LENGTH ${_JAVA_REL_SOURCE_PATH} _SRC_LEN)
801             if (_BIN_LEN LESS _SRC_LEN)
802                 set(_JAVA_REL_PATH ${_JAVA_REL_BINARY_PATH})
803             else ()
804                 set(_JAVA_REL_PATH ${_JAVA_REL_SOURCE_PATH})
805             endif ()
806             get_filename_component(_JAVA_REL_PATH ${_JAVA_REL_PATH} PATH)
807
808             list(APPEND _JAVA_COMPILE_FILES ${_JAVA_SOURCE_FILE})
809             set(_JAVA_CLASS_FILE "${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${_JAVA_REL_PATH}/${_JAVA_FILE}.class")
810             set(_JAVA_CLASS_FILES ${_JAVA_CLASS_FILES} ${_JAVA_CLASS_FILE})
811
812         elseif (_JAVA_EXT MATCHES ".jar"
813                 OR _JAVA_EXT MATCHES ".war"
814                 OR _JAVA_EXT MATCHES ".ear"
815                 OR _JAVA_EXT MATCHES ".sar")
816             # Ignored for backward compatibility
817
818         elseif (_JAVA_EXT STREQUAL "")
819             list(APPEND CMAKE_JAVA_INCLUDE_PATH ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}} ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}_CLASSPATH})
820             list(APPEND _JAVA_DEPENDS ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}})
821
822         else ()
823             __java_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/${_JAVA_SOURCE_FILE}
824                              ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${_JAVA_SOURCE_FILE}
825                              "Copying ${_JAVA_SOURCE_FILE} to the build directory")
826             list(APPEND _JAVA_RESOURCE_FILES ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${_JAVA_SOURCE_FILE})
827             list(APPEND _JAVA_RESOURCE_FILES_RELATIVE ${_JAVA_SOURCE_FILE})
828         endif ()
829     endforeach()
830
831     if(_add_jar_RESOURCES)         # Process RESOURCES if it exists
832         __java_copy_resource_namespaces("${_add_jar_RESOURCES}"
833                                         ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
834                                         _JAVA_RESOURCE_FILES
835                                         _JAVA_RESOURCE_FILES_RELATIVE)
836     endif()
837
838     foreach(_JAVA_INCLUDE_JAR IN LISTS _add_jar_INCLUDE_JARS)
839         if (TARGET ${_JAVA_INCLUDE_JAR})
840             get_target_property(_JAVA_JAR_PATH ${_JAVA_INCLUDE_JAR} JAR_FILE)
841             if (_JAVA_JAR_PATH)
842                 string(APPEND CMAKE_JAVA_INCLUDE_PATH_FINAL "${_UseJava_PATH_SEP}${_JAVA_JAR_PATH}")
843                 list(APPEND CMAKE_JAVA_INCLUDE_PATH ${_JAVA_JAR_PATH})
844                 list(APPEND _JAVA_DEPENDS ${_JAVA_INCLUDE_JAR})
845                 list(APPEND _JAVA_COMPILE_DEPENDS ${_JAVA_JAR_PATH})
846             else ()
847                 message(SEND_ERROR "add_jar: INCLUDE_JARS target ${_JAVA_INCLUDE_JAR} is not a jar")
848             endif ()
849         else ()
850             string(APPEND CMAKE_JAVA_INCLUDE_PATH_FINAL "${_UseJava_PATH_SEP}${_JAVA_INCLUDE_JAR}")
851             list(APPEND CMAKE_JAVA_INCLUDE_PATH "${_JAVA_INCLUDE_JAR}")
852             list(APPEND _JAVA_DEPENDS "${_JAVA_INCLUDE_JAR}")
853             list(APPEND _JAVA_COMPILE_DEPENDS "${_JAVA_INCLUDE_JAR}")
854         endif ()
855     endforeach()
856
857     if (_JAVA_COMPILE_FILES OR _JAVA_COMPILE_FILELISTS)
858         set (_JAVA_SOURCES_FILELISTS)
859
860         if (_JAVA_COMPILE_FILES)
861             # Create the list of files to compile.
862             set(_JAVA_SOURCES_FILE ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_sources)
863             string(REPLACE ";" "\"\n\"" _JAVA_COMPILE_STRING "\"${_JAVA_COMPILE_FILES}\"")
864             set(CMAKE_CONFIGURABLE_FILE_CONTENT "${_JAVA_COMPILE_STRING}")
865             configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
866               "${_JAVA_SOURCES_FILE}" @ONLY)
867             unset(CMAKE_CONFIGURABLE_FILE_CONTENT)
868             list (APPEND _JAVA_SOURCES_FILELISTS "@${_JAVA_SOURCES_FILE}")
869         endif()
870         if (_JAVA_COMPILE_FILELISTS)
871             foreach (_JAVA_FILELIST IN LISTS _JAVA_COMPILE_FILELISTS)
872                 list (APPEND _JAVA_SOURCES_FILELISTS "@${_JAVA_FILELIST}")
873             endforeach()
874         endif()
875
876         # Compile the java files and create a list of class files
877         add_custom_command(
878             # NOTE: this command generates an artificial dependency file
879             OUTPUT ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
880             COMMAND ${CMAKE_COMMAND}
881                 -DCMAKE_JAVA_CLASS_OUTPUT_PATH=${CMAKE_JAVA_CLASS_OUTPUT_PATH}
882                 -DCMAKE_JAR_CLASSES_PREFIX=${CMAKE_JAR_CLASSES_PREFIX}
883                 -P ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/UseJava/ClearClassFiles.cmake
884             COMMAND ${Java_JAVAC_EXECUTABLE}
885                 ${CMAKE_JAVA_COMPILE_FLAGS}
886                 -classpath "${CMAKE_JAVA_INCLUDE_PATH_FINAL}"
887                 -d ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
888                 ${_GENERATE_NATIVE_HEADERS}
889                 ${_JAVA_SOURCES_FILELISTS}
890             COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
891             DEPENDS ${_JAVA_COMPILE_FILES} ${_JAVA_COMPILE_FILELISTS} ${_JAVA_COMPILE_DEPENDS} ${_JAVA_SOURCES_FILE}
892             WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
893             COMMENT "Building Java objects for ${_TARGET_NAME}.jar"
894             VERBATIM
895         )
896         add_custom_command(
897             OUTPUT ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist
898             COMMAND ${CMAKE_COMMAND}
899                 -DCMAKE_JAVA_CLASS_OUTPUT_PATH=${CMAKE_JAVA_CLASS_OUTPUT_PATH}
900                 -DCMAKE_JAR_CLASSES_PREFIX=${CMAKE_JAR_CLASSES_PREFIX}
901                 -P ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/UseJava/ClassFilelist.cmake
902             DEPENDS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
903             WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
904             VERBATIM
905         )
906     else ()
907         # create an empty java_class_filelist
908         if (NOT EXISTS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist)
909             file(WRITE ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist "")
910         endif()
911     endif ()
912
913     # create the jar file
914     set(_JAVA_JAR_OUTPUT_PATH
915       "${_add_jar_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_NAME}")
916     if (CMAKE_JNI_TARGET)
917         add_custom_command(
918             OUTPUT ${_JAVA_JAR_OUTPUT_PATH}
919             COMMAND ${Java_JAR_EXECUTABLE}
920                 -cf${_ENTRY_POINT_OPTION}${_MANIFEST_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE} ${_MANIFEST_VALUE}
921                 ${_JAVA_RESOURCE_FILES_RELATIVE} @java_class_filelist
922             COMMAND ${CMAKE_COMMAND}
923                 -D_JAVA_TARGET_DIR=${_add_jar_OUTPUT_DIR}
924                 -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME}
925                 -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK}
926                 -P ${_JAVA_SYMLINK_SCRIPT}
927             COMMAND ${CMAKE_COMMAND}
928                 -D_JAVA_TARGET_DIR=${_add_jar_OUTPUT_DIR}
929                 -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_JAR_OUTPUT_PATH}
930                 -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK}
931                 -P ${_JAVA_SYMLINK_SCRIPT}
932             DEPENDS ${_JAVA_RESOURCE_FILES} ${_JAVA_DEPENDS} ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist
933             WORKING_DIRECTORY ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
934             COMMENT "Creating Java archive ${_JAVA_TARGET_OUTPUT_NAME}"
935             VERBATIM
936         )
937     else ()
938         add_custom_command(
939             OUTPUT ${_JAVA_JAR_OUTPUT_PATH}
940             COMMAND ${Java_JAR_EXECUTABLE}
941                 -cf${_ENTRY_POINT_OPTION}${_MANIFEST_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE} ${_MANIFEST_VALUE}
942                 ${_JAVA_RESOURCE_FILES_RELATIVE} @java_class_filelist
943             COMMAND ${CMAKE_COMMAND}
944                 -D_JAVA_TARGET_DIR=${_add_jar_OUTPUT_DIR}
945                 -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME}
946                 -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK}
947                 -P ${_JAVA_SYMLINK_SCRIPT}
948             WORKING_DIRECTORY ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
949             DEPENDS ${_JAVA_RESOURCE_FILES} ${_JAVA_DEPENDS} ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist
950             COMMENT "Creating Java archive ${_JAVA_TARGET_OUTPUT_NAME}"
951             VERBATIM
952         )
953     endif ()
954
955     # Add the target and make sure we have the latest resource files.
956     add_custom_target(${_TARGET_NAME} ALL DEPENDS ${_JAVA_JAR_OUTPUT_PATH})
957
958     set_property(
959         TARGET
960             ${_TARGET_NAME}
961         PROPERTY
962             INSTALL_FILES
963                 ${_JAVA_JAR_OUTPUT_PATH}
964     )
965
966     if (_JAVA_TARGET_OUTPUT_LINK)
967         set_property(
968             TARGET
969                 ${_TARGET_NAME}
970             PROPERTY
971                 INSTALL_FILES
972                     ${_JAVA_JAR_OUTPUT_PATH}
973                     ${_add_jar_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK}
974         )
975
976         if (CMAKE_JNI_TARGET)
977             set_property(
978                 TARGET
979                     ${_TARGET_NAME}
980                 PROPERTY
981                     JNI_SYMLINK
982                         ${_add_jar_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK}
983             )
984         endif ()
985     endif ()
986
987     set_property(
988         TARGET
989             ${_TARGET_NAME}
990         PROPERTY
991             JAR_FILE
992                 ${_JAVA_JAR_OUTPUT_PATH}
993     )
994
995     set_property(
996         TARGET
997             ${_TARGET_NAME}
998         PROPERTY
999             CLASSDIR
1000                 ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
1001     )
1002
1003   if (_GENERATE_NATIVE_HEADERS)
1004     # create an INTERFACE library encapsulating include directory for generated headers
1005     add_library (${_GENERATE_NATIVE_HEADERS_TARGET} INTERFACE)
1006     target_include_directories (${_GENERATE_NATIVE_HEADERS_TARGET} INTERFACE
1007       "${_GENERATE_NATIVE_HEADERS_OUTPUT_DESC}"
1008       ${JNI_INCLUDE_DIRS})
1009     set_property(TARGET ${_GENERATE_NATIVE_HEADERS_TARGET} PROPERTY NATIVE_HEADERS_DIRECTORY "${_GENERATE_NATIVE_HEADERS_OUTPUT_DIR}")
1010     # this INTERFACE library depends on jar generation
1011     add_dependencies (${_GENERATE_NATIVE_HEADERS_TARGET} ${_TARGET_NAME})
1012
1013     set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_CLEAN_FILES
1014       "${_GENERATE_NATIVE_HEADERS_OUTPUT_DIR}")
1015   endif()
1016 endfunction()
1017
1018 function(INSTALL_JAR _TARGET_NAME)
1019     if (ARGC EQUAL 2)
1020       set (_DESTINATION ${ARGV1})
1021     else()
1022       cmake_parse_arguments(_install_jar
1023         ""
1024         "DESTINATION;COMPONENT"
1025         ""
1026         ${ARGN})
1027       if (_install_jar_DESTINATION)
1028         set (_DESTINATION ${_install_jar_DESTINATION})
1029       else()
1030         message(SEND_ERROR "install_jar: ${_TARGET_NAME}: DESTINATION must be specified.")
1031       endif()
1032
1033       if (_install_jar_COMPONENT)
1034         set (_COMPONENT COMPONENT ${_install_jar_COMPONENT})
1035       endif()
1036     endif()
1037
1038     get_property(__FILES
1039         TARGET
1040             ${_TARGET_NAME}
1041         PROPERTY
1042             INSTALL_FILES
1043     )
1044     set_property(
1045         TARGET
1046             ${_TARGET_NAME}
1047         PROPERTY
1048             INSTALL_DESTINATION
1049             ${_DESTINATION}
1050     )
1051
1052     if (__FILES)
1053         install(
1054             FILES
1055                 ${__FILES}
1056             DESTINATION
1057                 ${_DESTINATION}
1058             ${_COMPONENT}
1059         )
1060     else ()
1061         message(SEND_ERROR "install_jar: The target ${_TARGET_NAME} is not known in this scope.")
1062     endif ()
1063 endfunction()
1064
1065 function(INSTALL_JNI_SYMLINK _TARGET_NAME)
1066     if (ARGC EQUAL 2)
1067       set (_DESTINATION ${ARGV1})
1068     else()
1069       cmake_parse_arguments(_install_jni_symlink
1070         ""
1071         "DESTINATION;COMPONENT"
1072         ""
1073         ${ARGN})
1074       if (_install_jni_symlink_DESTINATION)
1075         set (_DESTINATION ${_install_jni_symlink_DESTINATION})
1076       else()
1077         message(SEND_ERROR "install_jni_symlink: ${_TARGET_NAME}: DESTINATION must be specified.")
1078       endif()
1079
1080       if (_install_jni_symlink_COMPONENT)
1081         set (_COMPONENT COMPONENT ${_install_jni_symlink_COMPONENT})
1082       endif()
1083     endif()
1084
1085     get_property(__SYMLINK
1086         TARGET
1087             ${_TARGET_NAME}
1088         PROPERTY
1089             JNI_SYMLINK
1090     )
1091
1092     if (__SYMLINK)
1093         install(
1094             FILES
1095                 ${__SYMLINK}
1096             DESTINATION
1097                 ${_DESTINATION}
1098             ${_COMPONENT}
1099         )
1100     else ()
1101         message(SEND_ERROR "install_jni_symlink: The target ${_TARGET_NAME} is not known in this scope.")
1102     endif ()
1103 endfunction()
1104
1105 function (find_jar VARIABLE)
1106     set(_jar_names)
1107     set(_jar_files)
1108     set(_jar_versions)
1109     set(_jar_paths
1110         /usr/share/java/
1111         /usr/local/share/java/
1112         ${Java_JAR_PATHS})
1113     set(_jar_doc "NOTSET")
1114
1115     set(_state "name")
1116
1117     foreach (arg IN LISTS ARGN)
1118         if (_state STREQUAL "name")
1119             if (arg STREQUAL "VERSIONS")
1120                 set(_state "versions")
1121             elseif (arg STREQUAL "NAMES")
1122                 set(_state "names")
1123             elseif (arg STREQUAL "PATHS")
1124                 set(_state "paths")
1125             elseif (arg STREQUAL "DOC")
1126                 set(_state "doc")
1127             else ()
1128                 set(_jar_names ${arg})
1129                 if (_jar_doc STREQUAL "NOTSET")
1130                     set(_jar_doc "Finding ${arg} jar")
1131                 endif ()
1132             endif ()
1133         elseif (_state STREQUAL "versions")
1134             if (arg STREQUAL "NAMES")
1135                 set(_state "names")
1136             elseif (arg STREQUAL "PATHS")
1137                 set(_state "paths")
1138             elseif (arg STREQUAL "DOC")
1139                 set(_state "doc")
1140             else ()
1141                 set(_jar_versions ${_jar_versions} ${arg})
1142             endif ()
1143         elseif (_state STREQUAL "names")
1144             if (arg STREQUAL "VERSIONS")
1145                 set(_state "versions")
1146             elseif (arg STREQUAL "PATHS")
1147                 set(_state "paths")
1148             elseif (arg STREQUAL "DOC")
1149                 set(_state "doc")
1150             else ()
1151                 set(_jar_names ${_jar_names} ${arg})
1152                 if (_jar_doc STREQUAL "NOTSET")
1153                     set(_jar_doc "Finding ${arg} jar")
1154                 endif ()
1155             endif ()
1156         elseif (_state STREQUAL "paths")
1157             if (arg STREQUAL "VERSIONS")
1158                 set(_state "versions")
1159             elseif (arg STREQUAL "NAMES")
1160                 set(_state "names")
1161             elseif (arg STREQUAL "DOC")
1162                 set(_state "doc")
1163             else ()
1164                 set(_jar_paths ${_jar_paths} ${arg})
1165             endif ()
1166         elseif (_state STREQUAL "doc")
1167             if (arg STREQUAL "VERSIONS")
1168                 set(_state "versions")
1169             elseif (arg STREQUAL "NAMES")
1170                 set(_state "names")
1171             elseif (arg STREQUAL "PATHS")
1172                 set(_state "paths")
1173             else ()
1174                 set(_jar_doc ${arg})
1175             endif ()
1176         endif ()
1177     endforeach ()
1178
1179     if (NOT _jar_names)
1180         message(FATAL_ERROR "find_jar: No name to search for given")
1181     endif ()
1182
1183     foreach (jar_name IN LISTS _jar_names)
1184         foreach (version IN LISTS _jar_versions)
1185             set(_jar_files ${_jar_files} ${jar_name}-${version}.jar)
1186         endforeach ()
1187         set(_jar_files ${_jar_files} ${jar_name}.jar)
1188     endforeach ()
1189
1190     find_file(${VARIABLE}
1191         NAMES   ${_jar_files}
1192         PATHS   ${_jar_paths}
1193         DOC     ${_jar_doc}
1194         NO_DEFAULT_PATH)
1195 endfunction ()
1196
1197 function(create_javadoc _target)
1198     set(_javadoc_packages)
1199     set(_javadoc_files)
1200     set(_javadoc_sourcepath)
1201     set(_javadoc_classpath)
1202     set(_javadoc_installpath "${CMAKE_INSTALL_PREFIX}/share/javadoc")
1203     set(_javadoc_doctitle)
1204     set(_javadoc_windowtitle)
1205     set(_javadoc_author FALSE)
1206     set(_javadoc_version FALSE)
1207     set(_javadoc_use FALSE)
1208
1209     set(_state "package")
1210
1211     foreach (arg IN LISTS ARGN)
1212         if (_state STREQUAL "package")
1213             if (arg STREQUAL "PACKAGES")
1214                 set(_state "packages")
1215             elseif (arg STREQUAL "FILES")
1216                 set(_state "files")
1217             elseif (arg STREQUAL "SOURCEPATH")
1218                 set(_state "sourcepath")
1219             elseif (arg STREQUAL "CLASSPATH")
1220                 set(_state "classpath")
1221             elseif (arg STREQUAL "INSTALLPATH")
1222                 set(_state "installpath")
1223             elseif (arg STREQUAL "DOCTITLE")
1224                 set(_state "doctitle")
1225             elseif (arg STREQUAL "WINDOWTITLE")
1226                 set(_state "windowtitle")
1227             elseif (arg STREQUAL "AUTHOR")
1228                 set(_state "author")
1229             elseif (arg STREQUAL "USE")
1230                 set(_state "use")
1231             elseif (arg STREQUAL "VERSION")
1232                 set(_state "version")
1233             else ()
1234                 set(_javadoc_packages ${arg})
1235                 set(_state "packages")
1236             endif ()
1237         elseif (_state STREQUAL "packages")
1238             if (arg STREQUAL "FILES")
1239                 set(_state "files")
1240             elseif (arg STREQUAL "SOURCEPATH")
1241                 set(_state "sourcepath")
1242             elseif (arg STREQUAL "CLASSPATH")
1243                 set(_state "classpath")
1244             elseif (arg STREQUAL "INSTALLPATH")
1245                 set(_state "installpath")
1246             elseif (arg STREQUAL "DOCTITLE")
1247                 set(_state "doctitle")
1248             elseif (arg STREQUAL "WINDOWTITLE")
1249                 set(_state "windowtitle")
1250             elseif (arg STREQUAL "AUTHOR")
1251                 set(_state "author")
1252             elseif (arg STREQUAL "USE")
1253                 set(_state "use")
1254             elseif (arg STREQUAL "VERSION")
1255                 set(_state "version")
1256             else ()
1257                 list(APPEND _javadoc_packages ${arg})
1258             endif ()
1259         elseif (_state STREQUAL "files")
1260             if (arg STREQUAL "PACKAGES")
1261                 set(_state "packages")
1262             elseif (arg STREQUAL "SOURCEPATH")
1263                 set(_state "sourcepath")
1264             elseif (arg STREQUAL "CLASSPATH")
1265                 set(_state "classpath")
1266             elseif (arg STREQUAL "INSTALLPATH")
1267                 set(_state "installpath")
1268             elseif (arg STREQUAL "DOCTITLE")
1269                 set(_state "doctitle")
1270             elseif (arg STREQUAL "WINDOWTITLE")
1271                 set(_state "windowtitle")
1272             elseif (arg STREQUAL "AUTHOR")
1273                 set(_state "author")
1274             elseif (arg STREQUAL "USE")
1275                 set(_state "use")
1276             elseif (arg STREQUAL "VERSION")
1277                 set(_state "version")
1278             else ()
1279                 list(APPEND _javadoc_files ${arg})
1280             endif ()
1281         elseif (_state STREQUAL "sourcepath")
1282             if (arg STREQUAL "PACKAGES")
1283                 set(_state "packages")
1284             elseif (arg STREQUAL "FILES")
1285                 set(_state "files")
1286             elseif (arg STREQUAL "CLASSPATH")
1287                 set(_state "classpath")
1288             elseif (arg STREQUAL "INSTALLPATH")
1289                 set(_state "installpath")
1290             elseif (arg STREQUAL "DOCTITLE")
1291                 set(_state "doctitle")
1292             elseif (arg STREQUAL "WINDOWTITLE")
1293                 set(_state "windowtitle")
1294             elseif (arg STREQUAL "AUTHOR")
1295                 set(_state "author")
1296             elseif (arg STREQUAL "USE")
1297                 set(_state "use")
1298             elseif (arg STREQUAL "VERSION")
1299                 set(_state "version")
1300             else ()
1301                 list(APPEND _javadoc_sourcepath ${arg})
1302             endif ()
1303         elseif (_state STREQUAL "classpath")
1304             if (arg STREQUAL "PACKAGES")
1305                 set(_state "packages")
1306             elseif (arg STREQUAL "FILES")
1307                 set(_state "files")
1308             elseif (arg STREQUAL "SOURCEPATH")
1309                 set(_state "sourcepath")
1310             elseif (arg STREQUAL "INSTALLPATH")
1311                 set(_state "installpath")
1312             elseif (arg STREQUAL "DOCTITLE")
1313                 set(_state "doctitle")
1314             elseif (arg STREQUAL "WINDOWTITLE")
1315                 set(_state "windowtitle")
1316             elseif (arg STREQUAL "AUTHOR")
1317                 set(_state "author")
1318             elseif (arg STREQUAL "USE")
1319                 set(_state "use")
1320             elseif (arg STREQUAL "VERSION")
1321                 set(_state "version")
1322             else ()
1323                 list(APPEND _javadoc_classpath ${arg})
1324             endif ()
1325         elseif (_state STREQUAL "installpath")
1326             if (arg STREQUAL "PACKAGES")
1327                 set(_state "packages")
1328             elseif (arg STREQUAL "FILES")
1329                 set(_state "files")
1330             elseif (arg STREQUAL "SOURCEPATH")
1331                 set(_state "sourcepath")
1332             elseif (arg STREQUAL "DOCTITLE")
1333                 set(_state "doctitle")
1334             elseif (arg STREQUAL "WINDOWTITLE")
1335                 set(_state "windowtitle")
1336             elseif (arg STREQUAL "AUTHOR")
1337                 set(_state "author")
1338             elseif (arg STREQUAL "USE")
1339                 set(_state "use")
1340             elseif (arg STREQUAL "VERSION")
1341                 set(_state "version")
1342             else ()
1343                 set(_javadoc_installpath ${arg})
1344             endif ()
1345         elseif (_state STREQUAL "doctitle")
1346             if (${arg} STREQUAL "PACKAGES")
1347                 set(_state "packages")
1348             elseif (arg STREQUAL "FILES")
1349                 set(_state "files")
1350             elseif (arg STREQUAL "SOURCEPATH")
1351                 set(_state "sourcepath")
1352             elseif (arg STREQUAL "INSTALLPATH")
1353                 set(_state "installpath")
1354             elseif (arg STREQUAL "CLASSPATH")
1355                 set(_state "classpath")
1356             elseif (arg STREQUAL "WINDOWTITLE")
1357                 set(_state "windowtitle")
1358             elseif (arg STREQUAL "AUTHOR")
1359                 set(_state "author")
1360             elseif (arg STREQUAL "USE")
1361                 set(_state "use")
1362             elseif (arg STREQUAL "VERSION")
1363                 set(_state "version")
1364             else ()
1365                 set(_javadoc_doctitle ${arg})
1366             endif ()
1367         elseif (_state STREQUAL "windowtitle")
1368             if (${arg} STREQUAL "PACKAGES")
1369                 set(_state "packages")
1370             elseif (arg STREQUAL "FILES")
1371                 set(_state "files")
1372             elseif (arg STREQUAL "SOURCEPATH")
1373                 set(_state "sourcepath")
1374             elseif (arg STREQUAL "CLASSPATH")
1375                 set(_state "classpath")
1376             elseif (arg STREQUAL "INSTALLPATH")
1377                 set(_state "installpath")
1378             elseif (arg STREQUAL "DOCTITLE")
1379                 set(_state "doctitle")
1380             elseif (arg STREQUAL "AUTHOR")
1381                 set(_state "author")
1382             elseif (arg STREQUAL "USE")
1383                 set(_state "use")
1384             elseif (arg STREQUAL "VERSION")
1385                 set(_state "version")
1386             else ()
1387                 set(_javadoc_windowtitle ${arg})
1388             endif ()
1389         elseif (_state STREQUAL "author")
1390             if (arg STREQUAL "PACKAGES")
1391                 set(_state "packages")
1392             elseif (arg STREQUAL "FILES")
1393                 set(_state "files")
1394             elseif (arg STREQUAL "SOURCEPATH")
1395                 set(_state "sourcepath")
1396             elseif (arg STREQUAL "CLASSPATH")
1397                 set(_state "classpath")
1398             elseif (arg STREQUAL "INSTALLPATH")
1399                 set(_state "installpath")
1400             elseif (arg STREQUAL "DOCTITLE")
1401                 set(_state "doctitle")
1402             elseif (arg STREQUAL "WINDOWTITLE")
1403                 set(_state "windowtitle")
1404             elseif (arg STREQUAL "AUTHOR")
1405                 set(_state "author")
1406             elseif (arg STREQUAL "USE")
1407                 set(_state "use")
1408             elseif (arg STREQUAL "VERSION")
1409                 set(_state "version")
1410             else ()
1411                 set(_javadoc_author ${arg})
1412             endif ()
1413         elseif (_state STREQUAL "use")
1414             if (arg STREQUAL "PACKAGES")
1415                 set(_state "packages")
1416             elseif (arg STREQUAL "FILES")
1417                 set(_state "files")
1418             elseif (arg STREQUAL "SOURCEPATH")
1419                 set(_state "sourcepath")
1420             elseif (arg STREQUAL "CLASSPATH")
1421                 set(_state "classpath")
1422             elseif (arg STREQUAL "INSTALLPATH")
1423                 set(_state "installpath")
1424             elseif (arg STREQUAL "DOCTITLE")
1425                 set(_state "doctitle")
1426             elseif (arg STREQUAL "WINDOWTITLE")
1427                 set(_state "windowtitle")
1428             elseif (arg STREQUAL "AUTHOR")
1429                 set(_state "author")
1430             elseif (arg STREQUAL "USE")
1431                 set(_state "use")
1432             elseif (arg STREQUAL "VERSION")
1433                 set(_state "version")
1434             else ()
1435                 set(_javadoc_use ${arg})
1436             endif ()
1437         elseif (_state STREQUAL "version")
1438             if (arg STREQUAL "PACKAGES")
1439                 set(_state "packages")
1440             elseif (arg STREQUAL "FILES")
1441                 set(_state "files")
1442             elseif (arg STREQUAL "SOURCEPATH")
1443                 set(_state "sourcepath")
1444             elseif (arg STREQUAL "CLASSPATH")
1445                 set(_state "classpath")
1446             elseif (arg STREQUAL "INSTALLPATH")
1447                 set(_state "installpath")
1448             elseif (arg STREQUAL "DOCTITLE")
1449                 set(_state "doctitle")
1450             elseif (arg STREQUAL "WINDOWTITLE")
1451                 set(_state "windowtitle")
1452             elseif (arg STREQUAL "AUTHOR")
1453                 set(_state "author")
1454             elseif (arg STREQUAL "USE")
1455                 set(_state "use")
1456             elseif (arg STREQUAL "VERSION")
1457                 set(_state "version")
1458             else ()
1459                 set(_javadoc_version ${arg})
1460             endif ()
1461         endif ()
1462     endforeach ()
1463
1464     set(_javadoc_builddir ${CMAKE_CURRENT_BINARY_DIR}/javadoc/${_target})
1465     set(_javadoc_options -d ${_javadoc_builddir})
1466
1467     if (_javadoc_sourcepath)
1468         list(JOIN _javadoc_sourcepath "${_UseJava_PATH_SEP}" _javadoc_sourcepath)
1469         list(APPEND _javadoc_options -sourcepath "\"${_javadoc_sourcepath}\"")
1470     endif ()
1471
1472     if (_javadoc_classpath)
1473         list(JOIN _javadoc_classpath "${_UseJava_PATH_SEP}" _javadoc_classpath)
1474         list(APPEND _javadoc_options -classpath "\"${_javadoc_classpath}\"")
1475     endif ()
1476
1477     if (_javadoc_doctitle)
1478         list(APPEND _javadoc_options -doctitle '${_javadoc_doctitle}')
1479     endif ()
1480
1481     if (_javadoc_windowtitle)
1482         list(APPEND _javadoc_options -windowtitle '${_javadoc_windowtitle}')
1483     endif ()
1484
1485     if (_javadoc_author)
1486         list(APPEND _javadoc_options -author)
1487     endif ()
1488
1489     if (_javadoc_use)
1490         list(APPEND _javadoc_options -use)
1491     endif ()
1492
1493     if (_javadoc_version)
1494         list(APPEND _javadoc_options -version)
1495     endif ()
1496
1497     add_custom_target(${_target}_javadoc ALL
1498         COMMAND ${Java_JAVADOC_EXECUTABLE}
1499                 ${_javadoc_options}
1500                 ${_javadoc_files}
1501                 ${_javadoc_packages}
1502         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
1503     )
1504
1505     install(
1506         DIRECTORY ${_javadoc_builddir}
1507         DESTINATION ${_javadoc_installpath}
1508     )
1509 endfunction()
1510
1511 function (create_javah)
1512   if (Java_VERSION VERSION_GREATER_EQUAL 10)
1513     message (FATAL_ERROR "create_javah: not supported with this Java version. Use add_jar(GENERATE_NATIVE_HEADERS) instead.")
1514   elseif (Java_VERSION VERSION_GREATER_EQUAL 1.8)
1515     message (DEPRECATION "create_javah: this command will no longer be supported starting with version 10 of JDK. Update your project by using command add_jar(GENERATE_NATIVE_HEADERS) instead.")
1516   endif()
1517
1518     cmake_parse_arguments(_create_javah
1519       ""
1520       "TARGET;GENERATED_FILES;OUTPUT_NAME;OUTPUT_DIR"
1521       "CLASSES;CLASSPATH;DEPENDS"
1522       ${ARGN})
1523
1524     # ckeck parameters
1525     if (NOT _create_javah_TARGET AND NOT _create_javah_GENERATED_FILES)
1526       message (FATAL_ERROR "create_javah: TARGET or GENERATED_FILES must be specified.")
1527     endif()
1528     if (_create_javah_OUTPUT_NAME AND _create_javah_OUTPUT_DIR)
1529       message (FATAL_ERROR "create_javah: OUTPUT_NAME and OUTPUT_DIR are mutually exclusive.")
1530     endif()
1531
1532     if (NOT _create_javah_CLASSES)
1533       message (FATAL_ERROR "create_javah: CLASSES is a required parameter.")
1534     endif()
1535
1536     set (_output_files)
1537
1538     # handle javah options
1539     set (_javah_options)
1540
1541     if (_create_javah_CLASSPATH)
1542       # CLASSPATH can specify directories, jar files or targets created with add_jar command
1543       set (_classpath)
1544       foreach (_path IN LISTS _create_javah_CLASSPATH)
1545         if (TARGET ${_path})
1546           get_target_property (_jar_path ${_path} JAR_FILE)
1547           if (_jar_path)
1548             list (APPEND _classpath "${_jar_path}")
1549             list (APPEND _create_javah_DEPENDS "${_path}")
1550           else()
1551             message(SEND_ERROR "create_javah: CLASSPATH target ${_path} is not a jar.")
1552           endif()
1553         elseif (EXISTS "${_path}")
1554           list (APPEND _classpath "${_path}")
1555           if (NOT IS_DIRECTORY "${_path}")
1556             list (APPEND _create_javah_DEPENDS "${_path}")
1557           endif()
1558         else()
1559           message(SEND_ERROR "create_javah: CLASSPATH entry ${_path} does not exist.")
1560         endif()
1561       endforeach()
1562       string (REPLACE ";" "${_UseJava_PATH_SEP}" _classpath "${_classpath}")
1563       list (APPEND _javah_options -classpath "${_classpath}")
1564     endif()
1565
1566     if (_create_javah_OUTPUT_DIR)
1567       list (APPEND _javah_options -d "${_create_javah_OUTPUT_DIR}")
1568     endif()
1569
1570     if (_create_javah_OUTPUT_NAME)
1571       list (APPEND _javah_options -o "${_create_javah_OUTPUT_NAME}")
1572       set (_output_files "${_create_javah_OUTPUT_NAME}")
1573
1574       get_filename_component (_create_javah_OUTPUT_DIR "${_create_javah_OUTPUT_NAME}" DIRECTORY)
1575       get_filename_component (_create_javah_OUTPUT_DIR "${_create_javah_OUTPUT_DIR}" ABSOLUTE)
1576     endif()
1577
1578     if (NOT _create_javah_OUTPUT_DIR)
1579       set (_create_javah_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
1580     endif()
1581
1582     if (NOT _create_javah_OUTPUT_NAME)
1583       # compute output names
1584       foreach (_class IN LISTS _create_javah_CLASSES)
1585         string (REPLACE "." "_" _c_header "${_class}")
1586         set (_c_header  "${_create_javah_OUTPUT_DIR}/${_c_header}.h")
1587         list (APPEND _output_files "${_c_header}")
1588       endforeach()
1589     endif()
1590
1591     # finalize custom command arguments
1592     if (_create_javah_DEPENDS)
1593       list (INSERT _create_javah_DEPENDS 0 DEPENDS)
1594     endif()
1595
1596     add_custom_command (OUTPUT ${_output_files}
1597       COMMAND "${Java_JAVAH_EXECUTABLE}" ${_javah_options} -jni ${_create_javah_CLASSES}
1598       ${_create_javah_DEPENDS}
1599       WORKING_DIRECTORY ${_create_javah_OUTPUT_DIR}
1600       COMMENT "Building C header files from classes...")
1601
1602     if (_create_javah_TARGET)
1603       add_custom_target (${_create_javah_TARGET} ALL DEPENDS ${_output_files})
1604     endif()
1605     if (_create_javah_GENERATED_FILES)
1606       set (${_create_javah_GENERATED_FILES} ${_output_files} PARENT_SCOPE)
1607     endif()
1608 endfunction()
1609
1610 function(export_jars)
1611     # Parse and validate arguments
1612     cmake_parse_arguments(_export_jars
1613       ""
1614       "FILE;NAMESPACE"
1615       "TARGETS"
1616       ${ARGN}
1617     )
1618     if (NOT _export_jars_FILE)
1619       message(SEND_ERROR "export_jars: FILE must be specified.")
1620     endif()
1621     if (NOT _export_jars_TARGETS)
1622       message(SEND_ERROR "export_jars: TARGETS must be specified.")
1623     endif()
1624     set(_jar_NAMESPACE "${_export_jars_NAMESPACE}")
1625
1626     # Set content of generated exports file
1627     string(REPLACE ";" " " __targets__ "${_export_jars_TARGETS}")
1628     set(__targetdefs__ "")
1629     foreach(_target IN LISTS _export_jars_TARGETS)
1630         get_target_property(_jarpath ${_target} JAR_FILE)
1631         get_filename_component(_jarpath ${_jarpath} PATH)
1632         __java_export_jar(__targetdefs__ ${_target} "${_jarpath}")
1633     endforeach()
1634
1635     # Generate exports file
1636     configure_file(
1637       ${_JAVA_EXPORT_TARGETS_SCRIPT}
1638       ${_export_jars_FILE}
1639       @ONLY
1640     )
1641 endfunction()
1642
1643 function(install_jar_exports)
1644     # Parse and validate arguments
1645     cmake_parse_arguments(_install_jar_exports
1646       ""
1647       "FILE;DESTINATION;COMPONENT;NAMESPACE"
1648       "TARGETS"
1649       ${ARGN}
1650     )
1651     if (NOT _install_jar_exports_FILE)
1652       message(SEND_ERROR "install_jar_exports: FILE must be specified.")
1653     endif()
1654     if (NOT _install_jar_exports_DESTINATION)
1655       message(SEND_ERROR "install_jar_exports: DESTINATION must be specified.")
1656     endif()
1657     if (NOT _install_jar_exports_TARGETS)
1658       message(SEND_ERROR "install_jar_exports: TARGETS must be specified.")
1659     endif()
1660     set(_jar_NAMESPACE "${_install_jar_exports_NAMESPACE}")
1661
1662     if (_install_jar_exports_COMPONENT)
1663       set (_COMPONENT COMPONENT ${_install_jar_exports_COMPONENT})
1664     endif()
1665
1666     # Determine relative path from installed export file to install prefix
1667     if(IS_ABSOLUTE "${_install_jar_exports_DESTINATION}")
1668       file(RELATIVE_PATH _relpath
1669         ${_install_jar_exports_DESTINATION}
1670         ${CMAKE_INSTALL_PREFIX}
1671       )
1672     else()
1673       file(RELATIVE_PATH _relpath
1674         ${CMAKE_INSTALL_PREFIX}/${_install_jar_exports_DESTINATION}
1675         ${CMAKE_INSTALL_PREFIX}
1676       )
1677     endif()
1678
1679     # Set up unique location for generated exports file
1680     string(SHA256 _hash "${_install_jar_exports_DESTINATION}")
1681     set(_tmpdir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/JavaExports/${_hash})
1682
1683     # Set content of generated exports file
1684     string(REPLACE ";" " " __targets__ "${_install_jar_exports_TARGETS}")
1685     set(__targetdefs__ "set(_prefix \${CMAKE_CURRENT_LIST_DIR}/${_relpath})\n\n")
1686     foreach(_target IN LISTS _install_jar_exports_TARGETS)
1687         get_target_property(_dir ${_target} INSTALL_DESTINATION)
1688         __java_export_jar(__targetdefs__ ${_target} "\${_prefix}/${_dir}")
1689     endforeach()
1690     __java_lcat(__targetdefs__ "\nunset(_prefix)")
1691
1692     # Generate and install exports file
1693     configure_file(
1694       ${_JAVA_EXPORT_TARGETS_SCRIPT}
1695       ${_tmpdir}/${_install_jar_exports_FILE}
1696       @ONLY
1697     )
1698     install(FILES ${_tmpdir}/${_install_jar_exports_FILE}
1699             DESTINATION ${_install_jar_exports_DESTINATION}
1700             ${_COMPONENT})
1701 endfunction()