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:
5UseJava
6-------
7
8This file provides support for ``Java``.  It is assumed that
9:module:`FindJava` has already been loaded.  See :module:`FindJava` for
10information on how to load Java into your ``CMake`` project.
11
12Synopsis
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
35Creating 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
277Header 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 <http://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
347Exporting 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
414Finding 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
451Creating 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
549function (__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        )
559endfunction ()
560
561function(__java_lcat VAR)
562    foreach(_line IN LISTS ARGN)
563        string(APPEND ${VAR} "${_line}\n")
564    endforeach()
565
566    set(${VAR} "${${VAR}}" PARENT_SCOPE)
567endfunction()
568
569function(__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)
582endfunction()
583
584function(__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)
634endfunction()
635
636# define helper scripts
637set(_JAVA_EXPORT_TARGETS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJava/javaTargets.cmake.in)
638set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJava/Symlinks.cmake)
639
640if (CMAKE_HOST_WIN32 AND NOT CYGWIN AND CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
641    set(_UseJava_PATH_SEP "$<SEMICOLON>")
642else ()
643    set(_UseJava_PATH_SEP ":")
644endif()
645
646function(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()
1016endfunction()
1017
1018function(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 ()
1063endfunction()
1064
1065function(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 ()
1103endfunction()
1104
1105function (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)
1195endfunction ()
1196
1197function(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    )
1509endfunction()
1510
1511function (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()
1608endfunction()
1609
1610function(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    )
1641endfunction()
1642
1643function(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})
1701endfunction()
1702