Imported Upstream version 3.22.1
[platform/upstream/cmake.git] / Modules / ExternalProject.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 include_guard(GLOBAL)
5
6 #[=======================================================================[.rst:
7 ExternalProject
8 ---------------
9
10 .. only:: html
11
12    .. contents::
13
14 Commands
15 ^^^^^^^^
16
17 External Project Definition
18 """""""""""""""""""""""""""
19
20 .. command:: ExternalProject_Add
21
22   The ``ExternalProject_Add()`` function creates a custom target to drive
23   download, update/patch, configure, build, install and test steps of an
24   external project:
25
26   .. code-block:: cmake
27
28     ExternalProject_Add(<name> [<option>...])
29
30   The individual steps within the process can be driven independently if
31   required (e.g. for CDash submission) and extra custom steps can be defined,
32   along with the ability to control the step dependencies. The directory
33   structure used for the management of the external project can also be
34   customized. The function supports a large number of options which can be used
35   to tailor the external project behavior.
36
37   **Directory Options:**
38     Most of the time, the default directory layout is sufficient. It is largely
39     an implementation detail that the main project usually doesn't need to
40     change. In some circumstances, however, control over the directory layout
41     can be useful or necessary. The directory options are potentially more
42     useful from the point of view that the main build can use the
43     :command:`ExternalProject_Get_Property` command to retrieve their values,
44     thereby allowing the main project to refer to build artifacts of the
45     external project.
46
47     ``PREFIX <dir>``
48       Root directory for the external project. Unless otherwise noted below,
49       all other directories associated with the external project will be
50       created under here.
51
52     ``TMP_DIR <dir>``
53       Directory in which to store temporary files.
54
55     ``STAMP_DIR <dir>``
56       Directory in which to store the timestamps of each step. Log files from
57       individual steps are also created in here unless overridden by LOG_DIR
58       (see *Logging Options* below).
59
60     ``LOG_DIR <dir>``
61       .. versionadded:: 3.14
62
63       Directory in which to store the logs of each step.
64
65     ``DOWNLOAD_DIR <dir>``
66       Directory in which to store downloaded files before unpacking them. This
67       directory is only used by the URL download method, all other download
68       methods use ``SOURCE_DIR`` directly instead.
69
70     ``SOURCE_DIR <dir>``
71       Source directory into which downloaded contents will be unpacked, or for
72       non-URL download methods, the directory in which the repository should be
73       checked out, cloned, etc. If no download method is specified, this must
74       point to an existing directory where the external project has already
75       been unpacked or cloned/checked out.
76
77       .. note::
78          If a download method is specified, any existing contents of the source
79          directory may be deleted. Only the URL download method checks whether
80          this directory is either missing or empty before initiating the
81          download, stopping with an error if it is not empty. All other
82          download methods silently discard any previous contents of the source
83          directory.
84
85     ``BINARY_DIR <dir>``
86       Specify the build directory location. This option is ignored if
87       ``BUILD_IN_SOURCE`` is enabled.
88
89     ``INSTALL_DIR <dir>``
90       Installation prefix to be placed in the ``<INSTALL_DIR>`` placeholder.
91       This does not actually configure the external project to install to
92       the given prefix. That must be done by passing appropriate arguments
93       to the external project configuration step, e.g. using ``<INSTALL_DIR>``.
94
95     If any of the above ``..._DIR`` options are not specified, their defaults
96     are computed as follows. If the ``PREFIX`` option is given or the
97     ``EP_PREFIX`` directory property is set, then an external project is built
98     and installed under the specified prefix::
99
100       TMP_DIR      = <prefix>/tmp
101       STAMP_DIR    = <prefix>/src/<name>-stamp
102       DOWNLOAD_DIR = <prefix>/src
103       SOURCE_DIR   = <prefix>/src/<name>
104       BINARY_DIR   = <prefix>/src/<name>-build
105       INSTALL_DIR  = <prefix>
106       LOG_DIR      = <STAMP_DIR>
107
108     Otherwise, if the ``EP_BASE`` directory property is set then components
109     of an external project are stored under the specified base::
110
111       TMP_DIR      = <base>/tmp/<name>
112       STAMP_DIR    = <base>/Stamp/<name>
113       DOWNLOAD_DIR = <base>/Download/<name>
114       SOURCE_DIR   = <base>/Source/<name>
115       BINARY_DIR   = <base>/Build/<name>
116       INSTALL_DIR  = <base>/Install/<name>
117       LOG_DIR      = <STAMP_DIR>
118
119     If no ``PREFIX``, ``EP_PREFIX``, or ``EP_BASE`` is specified, then the
120     default is to set ``PREFIX`` to ``<name>-prefix``. Relative paths are
121     interpreted with respect to :variable:`CMAKE_CURRENT_BINARY_DIR` at the
122     point where ``ExternalProject_Add()`` is called.
123
124   **Download Step Options:**
125     A download method can be omitted if the ``SOURCE_DIR`` option is used to
126     point to an existing non-empty directory. Otherwise, one of the download
127     methods below must be specified (multiple download methods should not be
128     given) or a custom ``DOWNLOAD_COMMAND`` provided.
129
130     ``DOWNLOAD_COMMAND <cmd>...``
131       Overrides the command used for the download step
132       (:manual:`generator expressions <cmake-generator-expressions(7)>` are
133       supported). If this option is specified, all other download options will
134       be ignored. Providing an empty string for ``<cmd>`` effectively disables
135       the download step.
136
137     *URL Download*
138       ``URL <url1> [<url2>...]``
139         List of paths and/or URL(s) of the external project's source. When more
140         than one URL is given, they are tried in turn until one succeeds. A URL
141         may be an ordinary path in the local file system (in which case it
142         must be the only URL provided) or any downloadable URL supported by the
143         :command:`file(DOWNLOAD)` command. A local filesystem path may refer to
144         either an existing directory or to an archive file, whereas a URL is
145         expected to point to a file which can be treated as an archive. When an
146         archive is used, it will be unpacked automatically unless the
147         ``DOWNLOAD_NO_EXTRACT`` option is set to prevent it. The archive type
148         is determined by inspecting the actual content rather than using logic
149         based on the file extension.
150
151         .. versionchanged:: 3.7
152           Multiple URLs are allowed.
153
154       ``URL_HASH <algo>=<hashValue>``
155         Hash of the archive file to be downloaded. The argument should be of
156         the form ``<algo>=<hashValue>`` where ``algo`` can be any of the hashing
157         algorithms supported by the :command:`file()` command. Specifying this
158         option is strongly recommended for URL downloads, as it ensures the
159         integrity of the downloaded content. It is also used as a check for a
160         previously downloaded file, allowing connection to the remote location
161         to be avoided altogether if the local directory already has a file from
162         an earlier download that matches the specified hash.
163
164       ``URL_MD5 <md5>``
165         Equivalent to ``URL_HASH MD5=<md5>``.
166
167       ``DOWNLOAD_NAME <fname>``
168         File name to use for the downloaded file. If not given, the end of the
169         URL is used to determine the file name. This option is rarely needed,
170         the default name is generally suitable and is not normally used outside
171         of code internal to the ``ExternalProject`` module.
172
173       ``DOWNLOAD_NO_EXTRACT <bool>``
174         .. versionadded:: 3.6
175
176         Allows the extraction part of the download step to be disabled by
177         passing a boolean true value for this option. If this option is not
178         given, the downloaded contents will be unpacked automatically if
179         required. If extraction has been disabled, the full path to the
180         downloaded file is available as ``<DOWNLOADED_FILE>`` in subsequent
181         steps or as the property ``DOWNLOADED_FILE`` with the
182         :command:`ExternalProject_Get_Property` command.
183
184       ``DOWNLOAD_NO_PROGRESS <bool>``
185         Can be used to disable logging the download progress. If this option is
186         not given, download progress messages will be logged.
187
188       ``TIMEOUT <seconds>``
189         Maximum time allowed for file download operations.
190
191       ``INACTIVITY_TIMEOUT <seconds>``
192         .. versionadded:: 3.19
193
194         Terminate the operation after a period of inactivity.
195
196       ``HTTP_USERNAME <username>``
197         .. versionadded:: 3.7
198
199         Username for the download operation if authentication is required.
200
201       ``HTTP_PASSWORD <password>``
202         .. versionadded:: 3.7
203
204         Password for the download operation if authentication is required.
205
206       ``HTTP_HEADER <header1> [<header2>...]``
207         .. versionadded:: 3.7
208
209         Provides an arbitrary list of HTTP headers for the download operation.
210         This can be useful for accessing content in systems like AWS, etc.
211
212       ``TLS_VERIFY <bool>``
213         Specifies whether certificate verification should be performed for
214         https URLs. If this option is not provided, the default behavior is
215         determined by the :variable:`CMAKE_TLS_VERIFY` variable (see
216         :command:`file(DOWNLOAD)`). If that is also not set, certificate
217         verification will not be performed. In situations where ``URL_HASH``
218         cannot be provided, this option can be an alternative verification
219         measure.
220
221         .. versionchanged:: 3.6
222           This option also applies to ``git clone`` invocations.
223
224       ``TLS_CAINFO <file>``
225         Specify a custom certificate authority file to use if ``TLS_VERIFY``
226         is enabled. If this option is not specified, the value of the
227         :variable:`CMAKE_TLS_CAINFO` variable will be used instead (see
228         :command:`file(DOWNLOAD)`)
229
230       ``NETRC <level>``
231         .. versionadded:: 3.11
232
233         Specify whether the ``.netrc`` file is to be used for operation.
234         If this option is not specified, the value of the :variable:`CMAKE_NETRC`
235         variable will be used instead (see :command:`file(DOWNLOAD)`)
236         Valid levels are:
237
238         ``IGNORED``
239           The ``.netrc`` file is ignored.
240           This is the default.
241         ``OPTIONAL``
242           The ``.netrc`` file is optional, and information in the URL
243           is preferred.  The file will be scanned to find which ever
244           information is not specified in the URL.
245         ``REQUIRED``
246           The ``.netrc`` file is required, and information in the URL
247           is ignored.
248
249       ``NETRC_FILE <file>``
250         .. versionadded:: 3.11
251
252         Specify an alternative ``.netrc`` file to the one in your home directory
253         if the ``NETRC`` level is ``OPTIONAL`` or ``REQUIRED``. If this option
254         is not specified, the value of the :variable:`CMAKE_NETRC_FILE` variable
255         will be used instead (see :command:`file(DOWNLOAD)`)
256
257       .. versionadded:: 3.1
258         Added support for `tbz2`, `.tar.xz`, `.txz`, and `.7z` extensions.
259
260     *Git*
261       NOTE: A git version of 1.6.5 or later is required if this download method
262       is used.
263
264       ``GIT_REPOSITORY <url>``
265         URL of the git repository. Any URL understood by the ``git`` command
266         may be used.
267
268       ``GIT_TAG <tag>``
269         Git branch name, tag or commit hash. Note that branch names and tags
270         should generally be specified as remote names (i.e. ``origin/myBranch``
271         rather than simply ``myBranch``). This ensures that if the remote end
272         has its tag moved or branch rebased or history rewritten, the local
273         clone will still be updated correctly. In general, however, specifying
274         a commit hash should be preferred for a number of reasons:
275
276         - If the local clone already has the commit corresponding to the hash,
277           no ``git fetch`` needs to be performed to check for changes each time
278           CMake is re-run. This can result in a significant speed up if many
279           external projects are being used.
280         - Using a specific git hash ensures that the main project's own history
281           is fully traceable to a specific point in the external project's
282           evolution. If a branch or tag name is used instead, then checking out
283           a specific commit of the main project doesn't necessarily pin the
284           whole build to a specific point in the life of the external project.
285           The lack of such deterministic behavior makes the main project lose
286           traceability and repeatability.
287
288         If ``GIT_SHALLOW`` is enabled then ``GIT_TAG`` works only with
289         branch names and tags.  A commit hash is not allowed.
290
291       ``GIT_REMOTE_NAME <name>``
292         The optional name of the remote. If this option is not specified, it
293         defaults to ``origin``.
294
295       ``GIT_SUBMODULES <module>...``
296         Specific git submodules that should also be updated. If this option is
297         not provided, all git submodules will be updated.
298
299         .. versionchanged:: 3.16
300           When :policy:`CMP0097` is set to ``NEW``, if this value is set
301           to an empty string then no submodules are initialized or updated.
302
303       ``GIT_SUBMODULES_RECURSE <bool>``
304         .. versionadded:: 3.17
305
306         Specify whether git submodules (if any) should update recursively by
307         passing the ``--recursive`` flag to ``git submodule update``.
308         If not specified, the default is on.
309
310       ``GIT_SHALLOW <bool>``
311         .. versionadded:: 3.6
312
313         When this option is enabled, the ``git clone`` operation will be given
314         the ``--depth 1`` option. This performs a shallow clone, which avoids
315         downloading the whole history and instead retrieves just the commit
316         denoted by the ``GIT_TAG`` option.
317
318       ``GIT_PROGRESS <bool>``
319         .. versionadded:: 3.8
320
321         When enabled, this option instructs the ``git clone`` operation to
322         report its progress by passing it the ``--progress`` option. Without
323         this option, the clone step for large projects may appear to make the
324         build stall, since nothing will be logged until the clone operation
325         finishes. While this option can be used to provide progress to prevent
326         the appearance of the build having stalled, it may also make the build
327         overly noisy if lots of external projects are used.
328
329       ``GIT_CONFIG <option1> [<option2>...]``
330         .. versionadded:: 3.8
331
332         Specify a list of config options to pass to ``git clone``. Each option
333         listed will be transformed into its own ``--config <option>`` on the
334         ``git clone`` command line, with each option required to be in the
335         form ``key=value``.
336
337       ``GIT_REMOTE_UPDATE_STRATEGY <strategy>``
338         .. versionadded:: 3.18
339
340         When ``GIT_TAG`` refers to a remote branch, this option can be used to
341         specify how the update step behaves.  The ``<strategy>`` must be one of
342         the following:
343
344         ``CHECKOUT``
345           Ignore the local branch and always checkout the branch specified by
346           ``GIT_TAG``.
347
348         ``REBASE``
349           Try to rebase the current branch to the one specified by ``GIT_TAG``.
350           If there are local uncommitted changes, they will be stashed first
351           and popped again after rebasing.  If rebasing or popping stashed
352           changes fail, abort the rebase and halt with an error.
353           When ``GIT_REMOTE_UPDATE_STRATEGY`` is not present, this is the
354           default strategy unless the default has been overridden with
355           ``CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY`` (see below).
356
357         ``REBASE_CHECKOUT``
358           Same as ``REBASE`` except if the rebase fails, an annotated tag will
359           be created at the original ``HEAD`` position from before the rebase
360           and then checkout ``GIT_TAG`` just like the ``CHECKOUT`` strategy.
361           The message stored on the annotated tag will give information about
362           what was attempted and the tag name will include a timestamp so that
363           each failed run will add a new tag.  This strategy ensures no changes
364           will be lost, but updates should always succeed if ``GIT_TAG`` refers
365           to a valid ref unless there are uncommitted changes that cannot be
366           popped successfully.
367
368         The variable ``CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY`` can be set to
369         override the default strategy.  This variable should not be set by a
370         project, it is intended for the user to set.  It is primarily intended
371         for use in continuous integration scripts to ensure that when history
372         is rewritten on a remote branch, the build doesn't end up with unintended
373         changes or failed builds resulting from conflicts during rebase operations.
374
375     *Subversion*
376       ``SVN_REPOSITORY <url>``
377         URL of the Subversion repository.
378
379       ``SVN_REVISION -r<rev>``
380         Revision to checkout from the Subversion repository.
381
382       ``SVN_USERNAME <username>``
383         Username for the Subversion checkout and update.
384
385       ``SVN_PASSWORD <password>``
386         Password for the Subversion checkout and update.
387
388       ``SVN_TRUST_CERT <bool>``
389         Specifies whether to trust the Subversion server site certificate. If
390         enabled, the ``--trust-server-cert`` option is passed to the ``svn``
391         checkout and update commands.
392
393     *Mercurial*
394       ``HG_REPOSITORY <url>``
395         URL of the mercurial repository.
396
397       ``HG_TAG <tag>``
398         Mercurial branch name, tag or commit id.
399
400     *CVS*
401       ``CVS_REPOSITORY <cvsroot>``
402         CVSROOT of the CVS repository.
403
404       ``CVS_MODULE <mod>``
405         Module to checkout from the CVS repository.
406
407       ``CVS_TAG <tag>``
408         Tag to checkout from the CVS repository.
409
410   **Update/Patch Step Options:**
411     Whenever CMake is re-run, by default the external project's sources will be
412     updated if the download method supports updates (e.g. a git repository
413     would be checked if the ``GIT_TAG`` does not refer to a specific commit).
414
415     ``UPDATE_COMMAND <cmd>...``
416       Overrides the download method's update step with a custom command.
417       The command may use
418       :manual:`generator expressions <cmake-generator-expressions(7)>`.
419
420     ``UPDATE_DISCONNECTED <bool>``
421       .. versionadded:: 3.2
422
423       When enabled, this option causes the update step to be skipped. It does
424       not, however, prevent the download step. The update step can still be
425       added as a step target (see :command:`ExternalProject_Add_StepTargets`)
426       and called manually. This is useful if you want to allow developers to
427       build the project when disconnected from the network (the network may
428       still be needed for the download step though).
429
430       When this option is present, it is generally advisable to make the value
431       a cache variable under the developer's control rather than hard-coding
432       it. If this option is not present, the default value is taken from the
433       ``EP_UPDATE_DISCONNECTED`` directory property. If that is also not
434       defined, updates are performed as normal. The ``EP_UPDATE_DISCONNECTED``
435       directory property is intended as a convenience for controlling the
436       ``UPDATE_DISCONNECTED`` behavior for an entire section of a project's
437       directory hierarchy and may be a more convenient method of giving
438       developers control over whether or not to perform updates (assuming the
439       project also provides a cache variable or some other convenient method
440       for setting the directory property).
441
442       This may cause a step target to be created automatically for the
443       ``download`` step.  See policy :policy:`CMP0114`.
444
445     ``PATCH_COMMAND <cmd>...``
446       Specifies a custom command to patch the sources after an update. By
447       default, no patch command is defined. Note that it can be quite difficult
448       to define an appropriate patch command that performs robustly, especially
449       for download methods such as git where changing the ``GIT_TAG`` will not
450       discard changes from a previous patch, but the patch command will be
451       called again after updating to the new tag.
452
453   **Configure Step Options:**
454     The configure step is run after the download and update steps. By default,
455     the external project is assumed to be a CMake project, but this can be
456     overridden if required.
457
458     ``CONFIGURE_COMMAND <cmd>...``
459       The default configure command runs CMake with a few options based on
460       the main project.  The options added are typically only those needed to
461       use the same generator as the main project, but the ``CMAKE_GENERATOR``
462       option can be given to override this.  The project is responsible for
463       adding any toolchain details, flags or other settings it wants to
464       re-use from the main project or otherwise specify (see ``CMAKE_ARGS``,
465       ``CMAKE_CACHE_ARGS`` and ``CMAKE_CACHE_DEFAULT_ARGS`` below).
466
467       For non-CMake external projects, the ``CONFIGURE_COMMAND`` option must
468       be used to override the default configure command
469       (:manual:`generator expressions <cmake-generator-expressions(7)>` are
470       supported). For projects that require no configure step, specify this
471       option with an empty string as the command to execute.
472
473     ``CMAKE_COMMAND /.../cmake``
474       Specify an alternative cmake executable for the configure step (use an
475       absolute path). This is generally not recommended, since it is
476       usually desirable to use the same CMake version throughout the whole
477       build. This option is ignored if a custom configure command has been
478       specified with ``CONFIGURE_COMMAND``.
479
480     ``CMAKE_GENERATOR <gen>``
481       Override the CMake generator used for the configure step. Without this
482       option, the same generator as the main build will be used. This option is
483       ignored if a custom configure command has been specified with the
484       ``CONFIGURE_COMMAND`` option.
485
486     ``CMAKE_GENERATOR_PLATFORM <platform>``
487       .. versionadded:: 3.1
488
489       Pass a generator-specific platform name to the CMake command (see
490       :variable:`CMAKE_GENERATOR_PLATFORM`). It is an error to provide this
491       option without the ``CMAKE_GENERATOR`` option.
492
493     ``CMAKE_GENERATOR_TOOLSET <toolset>``
494       Pass a generator-specific toolset name to the CMake command (see
495       :variable:`CMAKE_GENERATOR_TOOLSET`). It is an error to provide this
496       option without the ``CMAKE_GENERATOR`` option.
497
498     ``CMAKE_GENERATOR_INSTANCE <instance>``
499       .. versionadded:: 3.11
500
501       Pass a generator-specific instance selection to the CMake command (see
502       :variable:`CMAKE_GENERATOR_INSTANCE`). It is an error to provide this
503       option without the ``CMAKE_GENERATOR`` option.
504
505     ``CMAKE_ARGS <arg>...``
506       The specified arguments are passed to the ``cmake`` command line. They
507       can be any argument the ``cmake`` command understands, not just cache
508       values defined by ``-D...`` arguments (see also
509       :manual:`CMake Options <cmake(1)>`).
510
511       .. versionadded:: 3.3
512         Arguments may use :manual:`generator expressions <cmake-generator-expressions(7)>`.
513
514     ``CMAKE_CACHE_ARGS <arg>...``
515       This is an alternate way of specifying cache variables where command line
516       length issues may become a problem. The arguments are expected to be in
517       the form ``-Dvar:STRING=value``, which are then transformed into
518       CMake :command:`set` commands with the ``FORCE`` option used. These
519       ``set()`` commands are written to a pre-load script which is then applied
520       using the :manual:`cmake -C <cmake(1)>` command line option.
521
522       .. versionadded:: 3.3
523         Arguments may use :manual:`generator expressions <cmake-generator-expressions(7)>`.
524
525     ``CMAKE_CACHE_DEFAULT_ARGS <arg>...``
526       .. versionadded:: 3.2
527
528       This is the same as the ``CMAKE_CACHE_ARGS`` option except the ``set()``
529       commands do not include the ``FORCE`` keyword. This means the values act
530       as initial defaults only and will not override any variables already set
531       from a previous run. Use this option with care, as it can lead to
532       different behavior depending on whether the build starts from a fresh
533       build directory or re-uses previous build contents.
534
535       .. versionadded:: 3.15
536         If the CMake generator is the ``Green Hills MULTI`` and not overridden then
537         the original project's settings for the GHS toolset and target system
538         customization cache variables are propagated into the external project.
539
540     ``SOURCE_SUBDIR <dir>``
541       .. versionadded:: 3.7
542
543       When no ``CONFIGURE_COMMAND`` option is specified, the configure step
544       assumes the external project has a ``CMakeLists.txt`` file at the top of
545       its source tree (i.e. in ``SOURCE_DIR``). The ``SOURCE_SUBDIR`` option
546       can be used to point to an alternative directory within the source tree
547       to use as the top of the CMake source tree instead. This must be a
548       relative path and it will be interpreted as being relative to
549       ``SOURCE_DIR``.
550
551       .. versionadded:: 3.14
552         When ``BUILD_IN_SOURCE`` option is enabled, the ``BUILD_COMMAND``
553         is used to point to an alternative directory within the source tree.
554
555     ``CONFIGURE_HANDLED_BY_BUILD <bool>``
556       .. versionadded:: 3.20
557
558       Enabling this option relaxes the dependencies of the configure step on
559       other external projects to order-only. This means the configure step will
560       be executed after its external project dependencies are built but it will
561       not be marked dirty when one of its external project dependencies is
562       rebuilt. This option can be enabled when the build step is smart enough
563       to figure out if the configure step needs to be rerun. CMake and Meson are
564       examples of build systems whose build step is smart enough to know if the
565       configure step needs to be rerun.
566
567   **Build Step Options:**
568     If the configure step assumed the external project uses CMake as its build
569     system, the build step will also. Otherwise, the build step will assume a
570     Makefile-based build and simply run ``make`` with no arguments as the
571     default build step. This can be overridden with custom build commands if
572     required.
573
574     If both the main project and the external project use make as their build
575     tool, the build step of the external project is invoked as a recursive
576     make using ``$(MAKE)``.  This will communicate some build tool settings
577     from the main project to the external project.  If either the main project
578     or external project is not using make, no build tool settings will be
579     passed to the external project other than those established by the
580     configure step (i.e. running ``ninja -v`` in the main project will not
581     pass ``-v`` to the external project's build step, even if it also uses
582     ``ninja`` as its build tool).
583
584     ``BUILD_COMMAND <cmd>...``
585       Overrides the default build command
586       (:manual:`generator expressions <cmake-generator-expressions(7)>` are
587       supported). If this option is not given, the default build command will
588       be chosen to integrate with the main build in the most appropriate way
589       (e.g. using recursive ``make`` for Makefile generators or
590       ``cmake --build`` if the project uses a CMake build). This option can be
591       specified with an empty string as the command to make the build step do
592       nothing.
593
594     ``BUILD_IN_SOURCE <bool>``
595       When this option is enabled, the build will be done directly within the
596       external project's source tree. This should generally be avoided, the use
597       of a separate build directory is usually preferred, but it can be useful
598       when the external project assumes an in-source build. The ``BINARY_DIR``
599       option should not be specified if building in-source.
600
601     ``BUILD_ALWAYS <bool>``
602       Enabling this option forces the build step to always be run. This can be
603       the easiest way to robustly ensure that the external project's own build
604       dependencies are evaluated rather than relying on the default
605       success timestamp-based method. This option is not normally needed unless
606       developers are expected to modify something the external project's build
607       depends on in a way that is not detectable via the step target
608       dependencies (e.g. ``SOURCE_DIR`` is used without a download method and
609       developers might modify the sources in ``SOURCE_DIR``).
610
611     ``BUILD_BYPRODUCTS <file>...``
612       .. versionadded:: 3.2
613
614       Specifies files that will be generated by the build command but which
615       might or might not have their modification time updated by subsequent
616       builds. These ultimately get passed through as ``BYPRODUCTS`` to the
617       build step's own underlying call to :command:`add_custom_command`.
618
619   **Install Step Options:**
620     If the configure step assumed the external project uses CMake as its build
621     system, the install step will also. Otherwise, the install step will assume
622     a Makefile-based build and simply run ``make install`` as the default build
623     step. This can be overridden with custom install commands if required.
624
625     ``INSTALL_COMMAND <cmd>...``
626       The external project's own install step is invoked as part of the main
627       project's *build*. It is done after the external project's build step
628       and may be before or after the external project's test step (see the
629       ``TEST_BEFORE_INSTALL`` option below). The external project's install
630       rules are not part of the main project's install rules, so if anything
631       from the external project should be installed as part of the main build,
632       these need to be specified in the main build as additional
633       :command:`install` commands. The default install step builds the
634       ``install`` target of the external project, but this can be overridden
635       with a custom command using this option
636       (:manual:`generator expressions <cmake-generator-expressions(7)>` are
637       supported). Passing an empty string as the ``<cmd>`` makes the install
638       step do nothing.
639
640     .. note::
641       If the :envvar:`CMAKE_INSTALL_MODE` environment variable is set when the
642       main project is built, it will only have an effect if the following
643       conditions are met:
644
645       * The main project's configure step assumed the external project uses
646         CMake as its build system.
647       * The external project's install command actually runs. Note that due
648         to the way ``ExternalProject`` may use timestamps internally, if
649         nothing the install step depends on needs to be re-executed, the
650         install command might also not need to run.
651
652       Note also that ``ExternalProject`` does not check whether the
653       :envvar:`CMAKE_INSTALL_MODE` environment variable changes from one run
654       to another.
655
656   **Test Step Options:**
657     The test step is only defined if at least one of the following ``TEST_...``
658     options are provided.
659
660     ``TEST_COMMAND <cmd>...``
661       Overrides the default test command
662       (:manual:`generator expressions <cmake-generator-expressions(7)>` are
663       supported). If this option is not given, the default behavior of the test
664       step is to build the external project's own ``test`` target. This option
665       can be specified with ``<cmd>`` as an empty string, which allows the test
666       step to still be defined, but it will do nothing. Do not specify any of
667       the other ``TEST_...`` options if providing an empty string as the test
668       command, but prefer to omit all ``TEST_...`` options altogether if the
669       test step target is not needed.
670
671     ``TEST_BEFORE_INSTALL <bool>``
672       When this option is enabled, the test step will be executed before the
673       install step. The default behavior is for the test step to run after the
674       install step.
675
676     ``TEST_AFTER_INSTALL <bool>``
677       This option is mainly useful as a way to indicate that the test step is
678       desired but all default behavior is sufficient. Specifying this option
679       with a boolean true value ensures the test step is defined and that it
680       comes after the install step. If both ``TEST_BEFORE_INSTALL`` and
681       ``TEST_AFTER_INSTALL`` are enabled, the latter is silently ignored.
682
683     ``TEST_EXCLUDE_FROM_MAIN <bool>``
684       .. versionadded:: 3.2
685
686       If enabled, the main build's default ALL target will not depend on the
687       test step. This can be a useful way of ensuring the test step is defined
688       but only gets invoked when manually requested.
689       This may cause a step target to be created automatically for either
690       the ``install`` or ``build`` step.  See policy :policy:`CMP0114`.
691
692   **Output Logging Options:**
693     Each of the following ``LOG_...`` options can be used to wrap the relevant
694     step in a script to capture its output to files. The log files will be
695     created in ``LOG_DIR`` if supplied or otherwise the ``STAMP_DIR``
696     directory with step-specific file names.
697
698     ``LOG_DOWNLOAD <bool>``
699       When enabled, the output of the download step is logged to files.
700
701     ``LOG_UPDATE <bool>``
702       When enabled, the output of the update step is logged to files.
703
704     ``LOG_PATCH <bool>``
705       .. versionadded:: 3.14
706
707       When enabled, the output of the patch step is logged to files.
708
709     ``LOG_CONFIGURE <bool>``
710       When enabled, the output of the configure step is logged to files.
711
712     ``LOG_BUILD <bool>``
713       When enabled, the output of the build step is logged to files.
714
715     ``LOG_INSTALL <bool>``
716       When enabled, the output of the install step is logged to files.
717
718     ``LOG_TEST <bool>``
719       When enabled, the output of the test step is logged to files.
720
721     ``LOG_MERGED_STDOUTERR <bool>``
722       .. versionadded:: 3.14
723
724       When enabled, stdout and stderr will be merged for any step whose
725       output is being logged to files.
726
727     ``LOG_OUTPUT_ON_FAILURE <bool>``
728       .. versionadded:: 3.14
729
730       This option only has an effect if at least one of the other ``LOG_<step>``
731       options is enabled.  If an error occurs for a step which has logging to
732       file enabled, that step's output will be printed to the console if
733       ``LOG_OUTPUT_ON_FAILURE`` is set to true.  For cases where a large amount
734       of output is recorded, just the end of that output may be printed to the
735       console.
736
737   **Terminal Access Options:**
738     .. versionadded:: 3.4
739
740     Steps can be given direct access to the terminal in some cases. Giving a
741     step access to the terminal may allow it to receive terminal input if
742     required, such as for authentication details not provided by other options.
743     With the :generator:`Ninja` generator, these options place the steps in the
744     ``console`` :prop_gbl:`job pool <JOB_POOLS>`. Each step can be given access
745     to the terminal individually via the following options:
746
747     ``USES_TERMINAL_DOWNLOAD <bool>``
748       Give the download step access to the terminal.
749
750     ``USES_TERMINAL_UPDATE <bool>``
751       Give the update step access to the terminal.
752
753     ``USES_TERMINAL_CONFIGURE <bool>``
754       Give the configure step access to the terminal.
755
756     ``USES_TERMINAL_BUILD <bool>``
757       Give the build step access to the terminal.
758
759     ``USES_TERMINAL_INSTALL <bool>``
760       Give the install step access to the terminal.
761
762     ``USES_TERMINAL_TEST <bool>``
763       Give the test step access to the terminal.
764
765   **Target Options:**
766     ``DEPENDS <targets>...``
767       Specify other targets on which the external project depends. The other
768       targets will be brought up to date before any of the external project's
769       steps are executed. Because the external project uses additional custom
770       targets internally for each step, the ``DEPENDS`` option is the most
771       convenient way to ensure all of those steps depend on the other targets.
772       Simply doing
773       :command:`add_dependencies(\<name\> \<targets\>) <add_dependencies>` will
774       not make any of the steps dependent on ``<targets>``.
775
776     ``EXCLUDE_FROM_ALL <bool>``
777       When enabled, this option excludes the external project from the default
778       ALL target of the main build.
779
780     ``STEP_TARGETS <step-target>...``
781       Generate custom targets for the specified steps. This is required if the
782       steps need to be triggered manually or if they need to be used as
783       dependencies of other targets. If this option is not specified, the
784       default value is taken from the ``EP_STEP_TARGETS`` directory property.
785       See :command:`ExternalProject_Add_StepTargets` below for further
786       discussion of the effects of this option.
787
788     ``INDEPENDENT_STEP_TARGETS <step-target>...``
789       .. deprecated:: 3.19
790         This is allowed only if policy :policy:`CMP0114` is not set to ``NEW``.
791
792       Generates custom targets for the specified steps and prevent these targets
793       from having the usual dependencies applied to them. If this option is not
794       specified, the default value is taken from the
795       ``EP_INDEPENDENT_STEP_TARGETS`` directory property. This option is mostly
796       useful for allowing individual steps to be driven independently, such as
797       for a CDash setup where each step should be initiated and reported
798       individually rather than as one whole build. See
799       :command:`ExternalProject_Add_StepTargets` below for further discussion
800       of the effects of this option.
801
802   **Miscellaneous Options:**
803     ``LIST_SEPARATOR <sep>``
804       For any of the various ``..._COMMAND`` options, replace ``;`` with
805       ``<sep>`` in the specified command lines. This can be useful where list
806       variables may be given in commands where they should end up as
807       space-separated arguments (``<sep>`` would be a single space character
808       string in this case).
809
810     ``COMMAND <cmd>...``
811       Any of the other ``..._COMMAND`` options can have additional commands
812       appended to them by following them with as many ``COMMAND ...`` options
813       as needed
814       (:manual:`generator expressions <cmake-generator-expressions(7)>` are
815       supported). For example:
816
817       .. code-block:: cmake
818
819         ExternalProject_Add(example
820           ... # Download options, etc.
821           BUILD_COMMAND ${CMAKE_COMMAND} -E echo "Starting $<CONFIG> build"
822           COMMAND       ${CMAKE_COMMAND} --build <BINARY_DIR> --config $<CONFIG>
823           COMMAND       ${CMAKE_COMMAND} -E echo "$<CONFIG> build complete"
824         )
825
826   It should also be noted that each build step is created via a call to
827   :command:`ExternalProject_Add_Step`. See that command's documentation for the
828   automatic substitutions that are supported for some options.
829
830 Obtaining Project Properties
831 """"""""""""""""""""""""""""
832
833 .. command:: ExternalProject_Get_Property
834
835   The ``ExternalProject_Get_Property()`` function retrieves external project
836   target properties:
837
838   .. code-block:: cmake
839
840     ExternalProject_Get_Property(<name> <prop1> [<prop2>...])
841
842   The function stores property values in variables of the same name. Property
843   names correspond to the keyword argument names of ``ExternalProject_Add()``.
844   For example, the source directory might be retrieved like so:
845
846   .. code-block:: cmake
847
848     ExternalProject_Get_property(myExtProj SOURCE_DIR)
849     message("Source dir of myExtProj = ${SOURCE_DIR}")
850
851 Explicit Step Management
852 """"""""""""""""""""""""
853
854 The ``ExternalProject_Add()`` function on its own is often sufficient for
855 incorporating an external project into the main build. Certain scenarios
856 require additional work to implement desired behavior, such as adding in a
857 custom step or making steps available as manually triggerable targets. The
858 ``ExternalProject_Add_Step()``, ``ExternalProject_Add_StepTargets()`` and
859 ``ExternalProject_Add_StepDependencies`` functions provide the lower level
860 control needed to implement such step-level capabilities.
861
862 .. command:: ExternalProject_Add_Step
863
864   The ``ExternalProject_Add_Step()`` function specifies an additional custom
865   step for an external project defined by an earlier call to
866   :command:`ExternalProject_Add`:
867
868   .. code-block:: cmake
869
870     ExternalProject_Add_Step(<name> <step> [<option>...])
871
872   ``<name>`` is the same as the name passed to the original call to
873   :command:`ExternalProject_Add`. The specified ``<step>`` must not be one of
874   the pre-defined steps (``mkdir``, ``download``, ``update``,
875   ``patch``, ``configure``, ``build``, ``install`` or ``test``). The supported
876   options are:
877
878   ``COMMAND <cmd>...``
879     The command line to be executed by this custom step
880     (:manual:`generator expressions <cmake-generator-expressions(7)>` are
881     supported). This option can be repeated multiple times to specify multiple
882     commands to be executed in order.
883
884   ``COMMENT "<text>..."``
885     Text to be printed when the custom step executes.
886
887   ``DEPENDEES <step>...``
888     Other steps (custom or pre-defined) on which this step depends.
889
890   ``DEPENDERS <step>...``
891     Other steps (custom or pre-defined) that depend on this new custom step.
892
893   ``DEPENDS <file>...``
894     Files on which this custom step depends.
895
896   ``INDEPENDENT <bool>``
897     .. versionadded:: 3.19
898
899     Specifies whether this step is independent of the external dependencies
900     specified by the :command:`ExternalProject_Add`'s ``DEPENDS`` option.
901     The default is ``FALSE``.  Steps marked as independent may depend only
902     on other steps marked independent.  See policy :policy:`CMP0114`.
903
904     Note that this use of the term "independent" refers only to independence
905     from external targets specified by the ``DEPENDS`` option and is
906     orthogonal to a step's dependencies on other steps.
907
908     If a step target is created for an independent step by the
909     :command:`ExternalProject_Add` ``STEP_TARGETS`` option or by the
910     :command:`ExternalProject_Add_StepTargets` function, it will not depend
911     on the external targets, but may depend on targets for other steps.
912
913   ``BYPRODUCTS <file>...``
914     .. versionadded:: 3.2
915
916     Files that will be generated by this custom step but which might or might
917     not have their modification time updated by subsequent builds. This list of
918     files will ultimately be passed through as the ``BYPRODUCTS`` option to the
919     :command:`add_custom_command` used to implement the custom step internally.
920
921   ``ALWAYS <bool>``
922     When enabled, this option specifies that the custom step should always be
923     run (i.e. that it is always considered out of date).
924
925   ``EXCLUDE_FROM_MAIN <bool>``
926     When enabled, this option specifies that the external project's main target
927     does not depend on the custom step.
928     This may cause step targets to be created automatically for the steps on
929     which this step depends.  See policy :policy:`CMP0114`.
930
931   ``WORKING_DIRECTORY <dir>``
932     Specifies the working directory to set before running the custom step's
933     command. If this option is not specified, the directory will be the value
934     of the :variable:`CMAKE_CURRENT_BINARY_DIR` at the point where
935     ``ExternalProject_Add_Step()`` was called.
936
937   ``LOG <bool>``
938     If set, this causes the output from the custom step to be captured to files
939     in the external project's ``LOG_DIR`` if supplied or ``STAMP_DIR``.
940
941   ``USES_TERMINAL <bool>``
942     If enabled, this gives the custom step direct access to the terminal if
943     possible.
944
945   The command line, comment, working directory and byproducts of every
946   standard and custom step are processed to replace the tokens
947   ``<SOURCE_DIR>``, ``<SOURCE_SUBDIR>``, ``<BINARY_DIR>``, ``<INSTALL_DIR>``
948   ``<TMP_DIR>``, ``<DOWNLOAD_DIR>`` and ``<DOWNLOADED_FILE>`` with their
949   corresponding property values defined in the original call to
950   :command:`ExternalProject_Add`.
951
952   .. versionadded:: 3.3
953     Token replacement is extended to byproducts.
954
955   .. versionadded:: 3.11
956     The ``<DOWNLOAD_DIR>`` substitution token.
957
958 .. command:: ExternalProject_Add_StepTargets
959
960   The ``ExternalProject_Add_StepTargets()`` function generates targets for the
961   steps listed. The name of each created target will be of the form
962   ``<name>-<step>``:
963
964   .. code-block:: cmake
965
966     ExternalProject_Add_StepTargets(<name> <step1> [<step2>...])
967
968   Creating a target for a step allows it to be used as a dependency of another
969   target or to be triggered manually. Having targets for specific steps also
970   allows them to be driven independently of each other by specifying targets on
971   build command lines. For example, you may be submitting to a sub-project
972   based dashboard where you want to drive the configure portion of the build,
973   then submit to the dashboard, followed by the build portion, followed
974   by tests. If you invoke a custom target that depends on a step halfway
975   through the step dependency chain, then all the previous steps will also run
976   to ensure everything is up to date.
977
978   Internally, :command:`ExternalProject_Add` calls
979   :command:`ExternalProject_Add_Step` to create each step. If any
980   ``STEP_TARGETS`` were specified, then ``ExternalProject_Add_StepTargets()``
981   will also be called after :command:`ExternalProject_Add_Step`.  Even if a
982   step is not mentioned in the ``STEP_TARGETS`` option,
983   ``ExternalProject_Add_StepTargets()`` can still be called later to manually
984   define a target for the step.
985
986   The ``STEP_TARGETS`` option for :command:`ExternalProject_Add` is generally
987   the easiest way to ensure targets are created for specific steps of interest.
988   For custom steps, ``ExternalProject_Add_StepTargets()`` must be called
989   explicitly if a target should also be created for that custom step.
990   An alternative to these two options is to populate the ``EP_STEP_TARGETS``
991   directory property.  It acts as a default for the step target options and
992   can save having to repeatedly specify the same set of step targets when
993   multiple external projects are being defined.
994
995   .. versionadded:: 3.19
996     If :policy:`CMP0114` is set to ``NEW``, step targets are fully responsible
997     for holding the custom commands implementing their steps.  The primary target
998     created by ``ExternalProject_Add`` depends on the step targets, and the
999     step targets depend on each other.  The target-level dependencies match
1000     the file-level dependencies used by the custom commands for each step.
1001     The targets for steps created with :command:`ExternalProject_Add_Step`'s
1002     ``INDEPENDENT`` option do not depend on the external targets specified
1003     by :command:`ExternalProject_Add`'s ``DEPENDS`` option.  The predefined
1004     steps ``mkdir``, ``download``, ``update``, and ``patch`` are independent.
1005
1006   If :policy:`CMP0114` is not ``NEW``, the following deprecated behavior
1007   is available:
1008
1009   * A deprecated ``NO_DEPENDS`` option may be specified immediately after the
1010     ``<name>`` and before the first step.
1011     If the ``NO_DEPENDS`` option is specified, the step target will not depend on
1012     the dependencies of the external project (i.e. on any dependencies of the
1013     ``<name>`` custom target created by :command:`ExternalProject_Add`). This is
1014     usually safe for the ``download``, ``update`` and ``patch`` steps, since they
1015     do not typically require that the dependencies are updated and built. Using
1016     ``NO_DEPENDS`` for any of the other pre-defined steps, however, may break
1017     parallel builds. Only use ``NO_DEPENDS`` where it is certain that the named
1018     steps genuinely do not have dependencies. For custom steps, consider whether
1019     or not the custom commands require the dependencies to be configured, built
1020     and installed.
1021
1022   * The ``INDEPENDENT_STEP_TARGETS`` option for :command:`ExternalProject_Add`,
1023     or the ``EP_INDEPENDENT_STEP_TARGETS`` directory property, tells the
1024     function to call ``ExternalProject_Add_StepTargets()`` internally
1025     using the ``NO_DEPENDS`` option for the specified steps.
1026
1027 .. command:: ExternalProject_Add_StepDependencies
1028
1029   .. versionadded:: 3.2
1030
1031   The ``ExternalProject_Add_StepDependencies()`` function can be used to add
1032   dependencies to a step. The dependencies added must be targets CMake already
1033   knows about (these can be ordinary executable or library targets, custom
1034   targets or even step targets of another external project):
1035
1036   .. code-block:: cmake
1037
1038     ExternalProject_Add_StepDependencies(<name> <step> <target1> [<target2>...])
1039
1040   This function takes care to set both target and file level dependencies and
1041   will ensure that parallel builds will not break. It should be used instead of
1042   :command:`add_dependencies` whenever adding a dependency for some of the step
1043   targets generated by the ``ExternalProject`` module.
1044
1045 Examples
1046 ^^^^^^^^
1047
1048 The following example shows how to download and build a hypothetical project
1049 called *FooBar* from github:
1050
1051 .. code-block:: cmake
1052
1053   include(ExternalProject)
1054   ExternalProject_Add(foobar
1055     GIT_REPOSITORY    git@github.com:FooCo/FooBar.git
1056     GIT_TAG           origin/release/1.2.3
1057   )
1058
1059 For the sake of the example, also define a second hypothetical external project
1060 called *SecretSauce*, which is downloaded from a web server. Two URLs are given
1061 to take advantage of a faster internal network if available, with a fallback to
1062 a slower external server. The project is a typical ``Makefile`` project with no
1063 configure step, so some of the default commands are overridden. The build is
1064 only required to build the *sauce* target:
1065
1066 .. code-block:: cmake
1067
1068   find_program(MAKE_EXE NAMES gmake nmake make)
1069   ExternalProject_Add(secretsauce
1070     URL               http://intranet.somecompany.com/artifacts/sauce-2.7.tgz
1071                       https://www.somecompany.com/downloads/sauce-2.7.zip
1072     URL_HASH          MD5=d41d8cd98f00b204e9800998ecf8427e
1073     CONFIGURE_COMMAND ""
1074     BUILD_COMMAND     ${MAKE_EXE} sauce
1075   )
1076
1077 Suppose the build step of ``secretsauce`` requires that ``foobar`` must already
1078 be built. This could be enforced like so:
1079
1080 .. code-block:: cmake
1081
1082   ExternalProject_Add_StepDependencies(secretsauce build foobar)
1083
1084 Another alternative would be to create a custom target for ``foobar``'s build
1085 step and make ``secretsauce`` depend on that rather than the whole ``foobar``
1086 project. This would mean ``foobar`` only needs to be built, it doesn't need to
1087 run its install or test steps before ``secretsauce`` can be built. The
1088 dependency can also be defined along with the ``secretsauce`` project:
1089
1090 .. code-block:: cmake
1091
1092   ExternalProject_Add_StepTargets(foobar build)
1093   ExternalProject_Add(secretsauce
1094     URL               http://intranet.somecompany.com/artifacts/sauce-2.7.tgz
1095                       https://www.somecompany.com/downloads/sauce-2.7.zip
1096     URL_HASH          MD5=d41d8cd98f00b204e9800998ecf8427e
1097     CONFIGURE_COMMAND ""
1098     BUILD_COMMAND     ${MAKE_EXE} sauce
1099     DEPENDS           foobar-build
1100   )
1101
1102 Instead of calling :command:`ExternalProject_Add_StepTargets`, the target could
1103 be defined along with the ``foobar`` project itself:
1104
1105 .. code-block:: cmake
1106
1107   ExternalProject_Add(foobar
1108     GIT_REPOSITORY git@github.com:FooCo/FooBar.git
1109     GIT_TAG        origin/release/1.2.3
1110     STEP_TARGETS   build
1111   )
1112
1113 If many external projects should have the same set of step targets, setting a
1114 directory property may be more convenient. The ``build`` step target could be
1115 created automatically by setting the ``EP_STEP_TARGETS`` directory property
1116 before creating the external projects with :command:`ExternalProject_Add`:
1117
1118 .. code-block:: cmake
1119
1120   set_property(DIRECTORY PROPERTY EP_STEP_TARGETS build)
1121
1122 Lastly, suppose that ``secretsauce`` provides a script called ``makedoc`` which
1123 can be used to generate its own documentation. Further suppose that the script
1124 expects the output directory to be provided as the only parameter and that it
1125 should be run from the ``secretsauce`` source directory. A custom step and a
1126 custom target to trigger the script can be defined like so:
1127
1128 .. code-block:: cmake
1129
1130   ExternalProject_Add_Step(secretsauce docs
1131     COMMAND           <SOURCE_DIR>/makedoc <BINARY_DIR>
1132     WORKING_DIRECTORY <SOURCE_DIR>
1133     COMMENT           "Building secretsauce docs"
1134     ALWAYS            TRUE
1135     EXCLUDE_FROM_MAIN TRUE
1136   )
1137   ExternalProject_Add_StepTargets(secretsauce docs)
1138
1139 The custom step could then be triggered from the main build like so::
1140
1141   cmake --build . --target secretsauce-docs
1142
1143 #]=======================================================================]
1144
1145 cmake_policy(PUSH)
1146 cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
1147 cmake_policy(SET CMP0057 NEW) # if() supports IN_LIST
1148
1149 macro(_ep_get_hash_algos out_var)
1150   set(${out_var}
1151     MD5
1152     SHA1
1153     SHA224
1154     SHA256
1155     SHA384
1156     SHA512
1157     SHA3_224
1158     SHA3_256
1159     SHA3_384
1160     SHA3_512
1161   )
1162 endmacro()
1163
1164 macro(_ep_get_hash_regex out_var)
1165   _ep_get_hash_algos(${out_var})
1166   list(JOIN ${out_var} "|" ${out_var})
1167   set(${out_var} "^(${${out_var}})=([0-9A-Fa-f]+)$")
1168 endmacro()
1169
1170 function(_ep_parse_arguments f keywords name ns args)
1171   # Transfer the arguments to this function into target properties for the
1172   # new custom target we just added so that we can set up all the build steps
1173   # correctly based on target properties.
1174   #
1175   # Because some keywords can be repeated, we can't use cmake_parse_arguments().
1176   # Instead, we loop through ARGN and consider the namespace starting with an
1177   # upper-case letter followed by at least two more upper-case letters,
1178   # numbers or underscores to be keywords.
1179
1180   set(key)
1181
1182   foreach(arg IN LISTS args)
1183     set(is_value 1)
1184
1185     if(arg MATCHES "^[A-Z][A-Z0-9_][A-Z0-9_]+$" AND
1186         NOT (("x${arg}x" STREQUAL "x${key}x") AND ("x${key}x" STREQUAL "xCOMMANDx")) AND
1187         NOT arg MATCHES "^(TRUE|FALSE)$")
1188       if(arg IN_LIST keywords)
1189         set(is_value 0)
1190       endif()
1191     endif()
1192
1193     if(is_value)
1194       if(key)
1195         # Value
1196         if(NOT arg STREQUAL "")
1197           set_property(TARGET ${name} APPEND PROPERTY ${ns}${key} "${arg}")
1198         else()
1199           get_property(have_key TARGET ${name} PROPERTY ${ns}${key} SET)
1200           if(have_key)
1201             get_property(value TARGET ${name} PROPERTY ${ns}${key})
1202             set_property(TARGET ${name} PROPERTY ${ns}${key} "${value};${arg}")
1203           else()
1204             set_property(TARGET ${name} PROPERTY ${ns}${key} "${arg}")
1205           endif()
1206         endif()
1207       else()
1208         # Missing Keyword
1209         message(AUTHOR_WARNING "value '${arg}' with no previous keyword in ${f}")
1210       endif()
1211     else()
1212       set(key "${arg}")
1213     endif()
1214   endforeach()
1215 endfunction()
1216
1217
1218 define_property(DIRECTORY PROPERTY "EP_BASE" INHERITED
1219   BRIEF_DOCS "Base directory for External Project storage."
1220   FULL_DOCS
1221   "See documentation of the ExternalProject_Add() function in the "
1222   "ExternalProject module."
1223   )
1224
1225 define_property(DIRECTORY PROPERTY "EP_PREFIX" INHERITED
1226   BRIEF_DOCS "Top prefix for External Project storage."
1227   FULL_DOCS
1228   "See documentation of the ExternalProject_Add() function in the "
1229   "ExternalProject module."
1230   )
1231
1232 define_property(DIRECTORY PROPERTY "EP_STEP_TARGETS" INHERITED
1233   BRIEF_DOCS
1234   "List of ExternalProject steps that automatically get corresponding targets"
1235   FULL_DOCS
1236   "These targets will be dependent on the main target dependencies. "
1237   "See documentation of the ExternalProject_Add_StepTargets() function in the "
1238   "ExternalProject module."
1239   )
1240
1241 define_property(DIRECTORY PROPERTY "EP_INDEPENDENT_STEP_TARGETS" INHERITED
1242   BRIEF_DOCS
1243   "List of ExternalProject steps that automatically get corresponding targets"
1244   FULL_DOCS
1245   "These targets will not be dependent on the main target dependencies. "
1246   "See documentation of the ExternalProject_Add_StepTargets() function in the "
1247   "ExternalProject module."
1248   )
1249
1250 define_property(DIRECTORY PROPERTY "EP_UPDATE_DISCONNECTED" INHERITED
1251   BRIEF_DOCS "Never update automatically from the remote repo."
1252   FULL_DOCS
1253   "See documentation of the ExternalProject_Add() function in the "
1254   "ExternalProject module."
1255   )
1256
1257 function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag git_remote_name init_submodules git_submodules_recurse git_submodules git_shallow git_progress git_config src_name work_dir gitclone_infofile gitclone_stampfile tls_verify)
1258   if(NOT GIT_VERSION_STRING VERSION_LESS 1.8.5)
1259     # Use `git checkout <tree-ish> --` to avoid ambiguity with a local path.
1260     set(git_checkout_explicit-- "--")
1261   else()
1262     # Use `git checkout <branch>` even though this risks ambiguity with a
1263     # local path.  Unfortunately we cannot use `git checkout <tree-ish> --`
1264     # because that will not search for remote branch names, a common use case.
1265     set(git_checkout_explicit-- "")
1266   endif()
1267   if("${git_tag}" STREQUAL "")
1268     message(FATAL_ERROR "Tag for git checkout should not be empty.")
1269   endif()
1270
1271   if(GIT_VERSION_STRING VERSION_LESS 2.20 OR 2.21 VERSION_LESS_EQUAL GIT_VERSION_STRING)
1272     set(git_clone_options "--no-checkout")
1273   else()
1274     set(git_clone_options)
1275   endif()
1276   if(git_shallow)
1277     if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.10)
1278       list(APPEND git_clone_options "--depth 1 --no-single-branch")
1279     else()
1280       list(APPEND git_clone_options "--depth 1")
1281     endif()
1282   endif()
1283   if(git_progress)
1284     list(APPEND git_clone_options --progress)
1285   endif()
1286   foreach(config IN LISTS git_config)
1287     list(APPEND git_clone_options --config \"${config}\")
1288   endforeach()
1289   if(NOT ${git_remote_name} STREQUAL "origin")
1290     list(APPEND git_clone_options --origin \"${git_remote_name}\")
1291   endif()
1292
1293   string (REPLACE ";" " " git_clone_options "${git_clone_options}")
1294
1295   set(git_options)
1296   # disable cert checking if explicitly told not to do it
1297   if(NOT "x${tls_verify}" STREQUAL "x" AND NOT tls_verify)
1298     set(git_options
1299       -c http.sslVerify=false)
1300   endif()
1301   string (REPLACE ";" " " git_options "${git_options}")
1302
1303   file(WRITE ${script_filename}
1304 "
1305 if(NOT \"${gitclone_infofile}\" IS_NEWER_THAN \"${gitclone_stampfile}\")
1306   message(STATUS \"Avoiding repeated git clone, stamp file is up to date: '${gitclone_stampfile}'\")
1307   return()
1308 endif()
1309
1310 execute_process(
1311   COMMAND \${CMAKE_COMMAND} -E rm -rf \"${source_dir}\"
1312   RESULT_VARIABLE error_code
1313   )
1314 if(error_code)
1315   message(FATAL_ERROR \"Failed to remove directory: '${source_dir}'\")
1316 endif()
1317
1318 # try the clone 3 times in case there is an odd git clone issue
1319 set(error_code 1)
1320 set(number_of_tries 0)
1321 while(error_code AND number_of_tries LESS 3)
1322   execute_process(
1323     COMMAND \"${git_EXECUTABLE}\" ${git_options} clone ${git_clone_options} \"${git_repository}\" \"${src_name}\"
1324     WORKING_DIRECTORY \"${work_dir}\"
1325     RESULT_VARIABLE error_code
1326     )
1327   math(EXPR number_of_tries \"\${number_of_tries} + 1\")
1328 endwhile()
1329 if(number_of_tries GREATER 1)
1330   message(STATUS \"Had to git clone more than once:
1331           \${number_of_tries} times.\")
1332 endif()
1333 if(error_code)
1334   message(FATAL_ERROR \"Failed to clone repository: '${git_repository}'\")
1335 endif()
1336
1337 execute_process(
1338   COMMAND \"${git_EXECUTABLE}\" ${git_options} checkout ${git_tag} ${git_checkout_explicit--}
1339   WORKING_DIRECTORY \"${work_dir}/${src_name}\"
1340   RESULT_VARIABLE error_code
1341   )
1342 if(error_code)
1343   message(FATAL_ERROR \"Failed to checkout tag: '${git_tag}'\")
1344 endif()
1345
1346 set(init_submodules ${init_submodules})
1347 if(init_submodules)
1348   execute_process(
1349     COMMAND \"${git_EXECUTABLE}\" ${git_options} submodule update ${git_submodules_recurse} --init ${git_submodules}
1350     WORKING_DIRECTORY \"${work_dir}/${src_name}\"
1351     RESULT_VARIABLE error_code
1352     )
1353 endif()
1354 if(error_code)
1355   message(FATAL_ERROR \"Failed to update submodules in: '${work_dir}/${src_name}'\")
1356 endif()
1357
1358 # Complete success, update the script-last-run stamp file:
1359 #
1360 execute_process(
1361   COMMAND \${CMAKE_COMMAND} -E copy
1362     \"${gitclone_infofile}\"
1363     \"${gitclone_stampfile}\"
1364   RESULT_VARIABLE error_code
1365   )
1366 if(error_code)
1367   message(FATAL_ERROR \"Failed to copy script-last-run stamp file: '${gitclone_stampfile}'\")
1368 endif()
1369
1370 "
1371 )
1372
1373 endfunction()
1374
1375 function(_ep_write_hgclone_script script_filename source_dir hg_EXECUTABLE hg_repository hg_tag src_name work_dir hgclone_infofile hgclone_stampfile)
1376   if("${hg_tag}" STREQUAL "")
1377     message(FATAL_ERROR "Tag for hg checkout should not be empty.")
1378   endif()
1379   file(WRITE ${script_filename}
1380 "
1381 if(NOT \"${hgclone_infofile}\" IS_NEWER_THAN \"${hgclone_stampfile}\")
1382   message(STATUS \"Avoiding repeated hg clone, stamp file is up to date: '${hgclone_stampfile}'\")
1383   return()
1384 endif()
1385
1386 execute_process(
1387   COMMAND \${CMAKE_COMMAND} -E rm -rf \"${source_dir}\"
1388   RESULT_VARIABLE error_code
1389   )
1390 if(error_code)
1391   message(FATAL_ERROR \"Failed to remove directory: '${source_dir}'\")
1392 endif()
1393
1394 execute_process(
1395   COMMAND \"${hg_EXECUTABLE}\" clone -U \"${hg_repository}\" \"${src_name}\"
1396   WORKING_DIRECTORY \"${work_dir}\"
1397   RESULT_VARIABLE error_code
1398   )
1399 if(error_code)
1400   message(FATAL_ERROR \"Failed to clone repository: '${hg_repository}'\")
1401 endif()
1402
1403 execute_process(
1404   COMMAND \"${hg_EXECUTABLE}\" update ${hg_tag}
1405   WORKING_DIRECTORY \"${work_dir}/${src_name}\"
1406   RESULT_VARIABLE error_code
1407   )
1408 if(error_code)
1409   message(FATAL_ERROR \"Failed to checkout tag: '${hg_tag}'\")
1410 endif()
1411
1412 # Complete success, update the script-last-run stamp file:
1413 #
1414 execute_process(
1415   COMMAND \${CMAKE_COMMAND} -E copy
1416     \"${hgclone_infofile}\"
1417     \"${hgclone_stampfile}\"
1418   RESULT_VARIABLE error_code
1419   )
1420 if(error_code)
1421   message(FATAL_ERROR \"Failed to copy script-last-run stamp file: '${hgclone_stampfile}'\")
1422 endif()
1423
1424 "
1425 )
1426
1427 endfunction()
1428
1429
1430 function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_remote_name init_submodules git_submodules_recurse git_submodules git_repository work_dir git_update_strategy)
1431   if("${git_tag}" STREQUAL "")
1432     message(FATAL_ERROR "Tag for git checkout should not be empty.")
1433   endif()
1434   set(git_stash_save_options --quiet)
1435   if(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.7)
1436     # This avoids stashing files covered by .gitignore
1437     list(APPEND git_stash_save_options --include-untracked)
1438   elseif(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.6)
1439     # Untracked files, but also ignored files, so potentially slower
1440     list(APPEND git_stash_save_options --all)
1441   endif()
1442
1443   configure_file(
1444       "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject-gitupdate.cmake.in"
1445       "${script_filename}"
1446       @ONLY
1447   )
1448 endfunction()
1449
1450 function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout inactivity_timeout no_progress hash tls_verify tls_cainfo userpwd http_headers netrc netrc_file)
1451   if(timeout)
1452     set(TIMEOUT_ARGS TIMEOUT ${timeout})
1453     set(TIMEOUT_MSG "${timeout} seconds")
1454   else()
1455     set(TIMEOUT_ARGS "# no TIMEOUT")
1456     set(TIMEOUT_MSG "none")
1457   endif()
1458   if(inactivity_timeout)
1459     set(INACTIVITY_TIMEOUT_ARGS INACTIVITY_TIMEOUT ${inactivity_timeout})
1460     set(INACTIVITY_TIMEOUT_MSG "${inactivity_timeout} seconds")
1461   else()
1462     set(INACTIVITY_TIMEOUT_ARGS "# no INACTIVITY_TIMEOUT")
1463     set(INACTIVITY_TIMEOUT_MSG "none")
1464   endif()
1465
1466
1467   if(no_progress)
1468     set(SHOW_PROGRESS "")
1469   else()
1470     set(SHOW_PROGRESS "SHOW_PROGRESS")
1471   endif()
1472
1473   _ep_get_hash_regex(_ep_hash_regex)
1474   if("${hash}" MATCHES "${_ep_hash_regex}")
1475     set(ALGO "${CMAKE_MATCH_1}")
1476     string(TOLOWER "${CMAKE_MATCH_2}" EXPECT_VALUE)
1477   else()
1478     set(ALGO "")
1479     set(EXPECT_VALUE "")
1480   endif()
1481
1482   set(TLS_VERIFY_CODE "")
1483   set(TLS_CAINFO_CODE "")
1484   set(NETRC_CODE "")
1485   set(NETRC_FILE_CODE "")
1486
1487   # check for curl globals in the project
1488   if(DEFINED CMAKE_TLS_VERIFY)
1489     set(TLS_VERIFY_CODE "set(CMAKE_TLS_VERIFY ${CMAKE_TLS_VERIFY})")
1490   endif()
1491   if(DEFINED CMAKE_TLS_CAINFO)
1492     set(TLS_CAINFO_CODE "set(CMAKE_TLS_CAINFO \"${CMAKE_TLS_CAINFO}\")")
1493   endif()
1494   if(DEFINED CMAKE_NETRC)
1495     set(NETRC_CODE "set(CMAKE_NETRC \"${CMAKE_NETRC}\")")
1496   endif()
1497   if(DEFINED CMAKE_NETRC_FILE)
1498     set(NETRC_FILE_CODE "set(CMAKE_NETRC_FILE \"${CMAKE_NETRC_FILE}\")")
1499   endif()
1500
1501   # now check for curl locals so that the local values
1502   # will override the globals
1503
1504   # check for tls_verify argument
1505   string(LENGTH "${tls_verify}" tls_verify_len)
1506   if(tls_verify_len GREATER 0)
1507     set(TLS_VERIFY_CODE "set(CMAKE_TLS_VERIFY ${tls_verify})")
1508   endif()
1509   # check for tls_cainfo argument
1510   string(LENGTH "${tls_cainfo}" tls_cainfo_len)
1511   if(tls_cainfo_len GREATER 0)
1512     set(TLS_CAINFO_CODE "set(CMAKE_TLS_CAINFO \"${tls_cainfo}\")")
1513   endif()
1514   # check for netrc argument
1515   string(LENGTH "${netrc}" netrc_len)
1516   if(netrc_len GREATER 0)
1517     set(NETRC_CODE "set(CMAKE_NETRC \"${netrc}\")")
1518   endif()
1519   # check for netrc_file argument
1520   string(LENGTH "${netrc_file}" netrc_file_len)
1521   if(netrc_file_len GREATER 0)
1522     set(NETRC_FILE_CODE "set(CMAKE_NETRC_FILE \"${netrc_file}\")")
1523   endif()
1524
1525   if(userpwd STREQUAL ":")
1526     set(USERPWD_ARGS)
1527   else()
1528     set(USERPWD_ARGS USERPWD "${userpwd}")
1529   endif()
1530
1531   set(HTTP_HEADERS_ARGS "")
1532   if(NOT http_headers STREQUAL "")
1533     foreach(header ${http_headers})
1534       set(
1535           HTTP_HEADERS_ARGS
1536           "HTTPHEADER \"${header}\"\n        ${HTTP_HEADERS_ARGS}"
1537       )
1538     endforeach()
1539   endif()
1540
1541   # Used variables:
1542   # * TLS_VERIFY_CODE
1543   # * TLS_CAINFO_CODE
1544   # * ALGO
1545   # * EXPECT_VALUE
1546   # * REMOTE
1547   # * LOCAL
1548   # * SHOW_PROGRESS
1549   # * TIMEOUT_ARGS
1550   # * TIMEOUT_MSG
1551   # * USERPWD_ARGS
1552   # * HTTP_HEADERS_ARGS
1553   configure_file(
1554       "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject-download.cmake.in"
1555       "${script_filename}"
1556       @ONLY
1557   )
1558 endfunction()
1559
1560 function(_ep_write_verifyfile_script script_filename LOCAL hash)
1561   _ep_get_hash_regex(_ep_hash_regex)
1562   if("${hash}" MATCHES "${_ep_hash_regex}")
1563     set(ALGO "${CMAKE_MATCH_1}")
1564     string(TOLOWER "${CMAKE_MATCH_2}" EXPECT_VALUE)
1565   else()
1566     set(ALGO "")
1567     set(EXPECT_VALUE "")
1568   endif()
1569
1570   # Used variables:
1571   # * ALGO
1572   # * EXPECT_VALUE
1573   # * LOCAL
1574   configure_file(
1575       "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject-verify.cmake.in"
1576       "${script_filename}"
1577       @ONLY
1578   )
1579 endfunction()
1580
1581
1582 function(_ep_write_extractfile_script script_filename name filename directory)
1583   set(args "")
1584
1585   if(filename MATCHES "(\\.|=)(7z|tar\\.bz2|tar\\.gz|tar\\.xz|tbz2|tgz|txz|zip)$")
1586     set(args xfz)
1587   endif()
1588
1589   if(filename MATCHES "(\\.|=)tar$")
1590     set(args xf)
1591   endif()
1592
1593   if(args STREQUAL "")
1594     message(SEND_ERROR "error: do not know how to extract '${filename}' -- known types are .7z, .tar, .tar.bz2, .tar.gz, .tar.xz, .tbz2, .tgz, .txz and .zip")
1595     return()
1596   endif()
1597
1598   file(WRITE ${script_filename}
1599 "# Make file names absolute:
1600 #
1601 get_filename_component(filename \"${filename}\" ABSOLUTE)
1602 get_filename_component(directory \"${directory}\" ABSOLUTE)
1603
1604 message(STATUS \"extracting...
1605      src='\${filename}'
1606      dst='\${directory}'\")
1607
1608 if(NOT EXISTS \"\${filename}\")
1609   message(FATAL_ERROR \"error: file to extract does not exist: '\${filename}'\")
1610 endif()
1611
1612 # Prepare a space for extracting:
1613 #
1614 set(i 1234)
1615 while(EXISTS \"\${directory}/../ex-${name}\${i}\")
1616   math(EXPR i \"\${i} + 1\")
1617 endwhile()
1618 set(ut_dir \"\${directory}/../ex-${name}\${i}\")
1619 file(MAKE_DIRECTORY \"\${ut_dir}\")
1620
1621 # Extract it:
1622 #
1623 message(STATUS \"extracting... [tar ${args}]\")
1624 execute_process(COMMAND \${CMAKE_COMMAND} -E tar ${args} \${filename}
1625   WORKING_DIRECTORY \${ut_dir}
1626   RESULT_VARIABLE rv)
1627
1628 if(NOT rv EQUAL 0)
1629   message(STATUS \"extracting... [error clean up]\")
1630   file(REMOVE_RECURSE \"\${ut_dir}\")
1631   message(FATAL_ERROR \"error: extract of '\${filename}' failed\")
1632 endif()
1633
1634 # Analyze what came out of the tar file:
1635 #
1636 message(STATUS \"extracting... [analysis]\")
1637 file(GLOB contents \"\${ut_dir}/*\")
1638 list(REMOVE_ITEM contents \"\${ut_dir}/.DS_Store\")
1639 list(LENGTH contents n)
1640 if(NOT n EQUAL 1 OR NOT IS_DIRECTORY \"\${contents}\")
1641   set(contents \"\${ut_dir}\")
1642 endif()
1643
1644 # Move \"the one\" directory to the final directory:
1645 #
1646 message(STATUS \"extracting... [rename]\")
1647 file(REMOVE_RECURSE \${directory})
1648 get_filename_component(contents \${contents} ABSOLUTE)
1649 file(RENAME \${contents} \${directory})
1650
1651 # Clean up:
1652 #
1653 message(STATUS \"extracting... [clean up]\")
1654 file(REMOVE_RECURSE \"\${ut_dir}\")
1655
1656 message(STATUS \"extracting... done\")
1657 "
1658 )
1659
1660 endfunction()
1661
1662
1663 function(_ep_set_directories name)
1664   get_property(prefix TARGET ${name} PROPERTY _EP_PREFIX)
1665   if(NOT prefix)
1666     get_property(prefix DIRECTORY PROPERTY EP_PREFIX)
1667     if(NOT prefix)
1668       get_property(base DIRECTORY PROPERTY EP_BASE)
1669       if(NOT base)
1670         set(prefix "${name}-prefix")
1671       endif()
1672     endif()
1673   endif()
1674   if(prefix)
1675     set(tmp_default "${prefix}/tmp")
1676     set(download_default "${prefix}/src")
1677     set(source_default "${prefix}/src/${name}")
1678     set(binary_default "${prefix}/src/${name}-build")
1679     set(stamp_default "${prefix}/src/${name}-stamp")
1680     set(install_default "${prefix}")
1681   else()
1682     set(tmp_default "${base}/tmp/${name}")
1683     set(download_default "${base}/Download/${name}")
1684     set(source_default "${base}/Source/${name}")
1685     set(binary_default "${base}/Build/${name}")
1686     set(stamp_default "${base}/Stamp/${name}")
1687     set(install_default "${base}/Install/${name}")
1688   endif()
1689   get_property(build_in_source TARGET ${name} PROPERTY _EP_BUILD_IN_SOURCE)
1690   if(build_in_source)
1691     get_property(have_binary_dir TARGET ${name} PROPERTY _EP_BINARY_DIR SET)
1692     if(have_binary_dir)
1693       message(FATAL_ERROR
1694         "External project ${name} has both BINARY_DIR and BUILD_IN_SOURCE!")
1695     endif()
1696   endif()
1697   set(top "${CMAKE_CURRENT_BINARY_DIR}")
1698
1699   # Apply defaults and convert to absolute paths.
1700   set(places stamp download source binary install tmp)
1701   foreach(var ${places})
1702     string(TOUPPER "${var}" VAR)
1703     get_property(${var}_dir TARGET ${name} PROPERTY _EP_${VAR}_DIR)
1704     if(NOT ${var}_dir)
1705       set(${var}_dir "${${var}_default}")
1706     endif()
1707     if(NOT IS_ABSOLUTE "${${var}_dir}")
1708       get_filename_component(${var}_dir "${top}/${${var}_dir}" ABSOLUTE)
1709     endif()
1710     set_property(TARGET ${name} PROPERTY _EP_${VAR}_DIR "${${var}_dir}")
1711   endforeach()
1712
1713   # Special case for default log directory based on stamp directory.
1714   get_property(log_dir TARGET ${name} PROPERTY _EP_LOG_DIR)
1715   if(NOT log_dir)
1716     get_property(log_dir TARGET ${name} PROPERTY _EP_STAMP_DIR)
1717   endif()
1718   if(NOT IS_ABSOLUTE "${log_dir}")
1719     get_filename_component(log_dir "${top}/${log_dir}" ABSOLUTE)
1720   endif()
1721   set_property(TARGET ${name} PROPERTY _EP_LOG_DIR "${log_dir}")
1722
1723   get_property(source_subdir TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR)
1724   if(NOT source_subdir)
1725     set_property(TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR "")
1726   elseif(IS_ABSOLUTE "${source_subdir}")
1727     message(FATAL_ERROR
1728       "External project ${name} has non-relative SOURCE_SUBDIR!")
1729   else()
1730     # Prefix with a slash so that when appended to the source directory, it
1731     # behaves as expected.
1732     set_property(TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR "/${source_subdir}")
1733   endif()
1734   if(build_in_source)
1735     get_property(source_dir TARGET ${name} PROPERTY _EP_SOURCE_DIR)
1736     if(source_subdir)
1737       set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}/${source_subdir}")
1738     else()
1739       set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}")
1740     endif()
1741   endif()
1742
1743   # Make the directories at CMake configure time *and* add a custom command
1744   # to make them at build time. They need to exist at makefile generation
1745   # time for Borland make and wmake so that CMake may generate makefiles
1746   # with "cd C:\short\paths\with\no\spaces" commands in them.
1747   #
1748   # Additionally, the add_custom_command is still used in case somebody
1749   # removes one of the necessary directories and tries to rebuild without
1750   # re-running cmake.
1751   foreach(var ${places})
1752     string(TOUPPER "${var}" VAR)
1753     get_property(dir TARGET ${name} PROPERTY _EP_${VAR}_DIR)
1754     file(MAKE_DIRECTORY "${dir}")
1755     if(NOT EXISTS "${dir}")
1756       message(FATAL_ERROR "dir '${dir}' does not exist after file(MAKE_DIRECTORY)")
1757     endif()
1758   endforeach()
1759 endfunction()
1760
1761
1762 # IMPORTANT: this MUST be a macro and not a function because of the
1763 # in-place replacements that occur in each ${var}
1764 #
1765 macro(_ep_replace_location_tags target_name)
1766   set(vars ${ARGN})
1767   foreach(var ${vars})
1768     if(${var})
1769       foreach(dir SOURCE_DIR SOURCE_SUBDIR BINARY_DIR INSTALL_DIR TMP_DIR DOWNLOAD_DIR DOWNLOADED_FILE LOG_DIR)
1770         get_property(val TARGET ${target_name} PROPERTY _EP_${dir})
1771         string(REPLACE "<${dir}>" "${val}" ${var} "${${var}}")
1772       endforeach()
1773     endif()
1774   endforeach()
1775 endmacro()
1776
1777
1778 function(_ep_command_line_to_initial_cache var args force)
1779   set(script_initial_cache "")
1780   set(regex "^([^:]+):([^=]+)=(.*)$")
1781   set(setArg "")
1782   set(forceArg "")
1783   if(force)
1784     set(forceArg "FORCE")
1785   endif()
1786   foreach(line ${args})
1787     if("${line}" MATCHES "^-D(.*)")
1788       set(line "${CMAKE_MATCH_1}")
1789       if(NOT "${setArg}" STREQUAL "")
1790         # This is required to build up lists in variables, or complete an entry
1791         string(APPEND setArg "${accumulator}\" CACHE ${type} \"Initial cache\" ${forceArg})")
1792         string(APPEND script_initial_cache "\n${setArg}")
1793         set(accumulator "")
1794         set(setArg "")
1795       endif()
1796       if("${line}" MATCHES "${regex}")
1797         set(name "${CMAKE_MATCH_1}")
1798         set(type "${CMAKE_MATCH_2}")
1799         set(value "${CMAKE_MATCH_3}")
1800         set(setArg "set(${name} \"${value}")
1801       else()
1802         message(WARNING "Line '${line}' does not match regex. Ignoring.")
1803       endif()
1804     else()
1805       # Assume this is a list to append to the last var
1806       string(APPEND accumulator ";${line}")
1807     endif()
1808   endforeach()
1809   # Catch the final line of the args
1810   if(NOT "${setArg}" STREQUAL "")
1811     string(APPEND setArg "${accumulator}\" CACHE ${type} \"Initial cache\" ${forceArg})")
1812     string(APPEND script_initial_cache "\n${setArg}")
1813   endif()
1814   set(${var} ${script_initial_cache} PARENT_SCOPE)
1815 endfunction()
1816
1817
1818 function(_ep_write_initial_cache target_name script_filename script_initial_cache)
1819   # Write out values into an initial cache, that will be passed to CMake with -C
1820   # Replace location tags.
1821   _ep_replace_location_tags(${target_name} script_initial_cache)
1822   _ep_replace_location_tags(${target_name} script_filename)
1823   # Replace list separators.
1824   get_property(sep TARGET ${target_name} PROPERTY _EP_LIST_SEPARATOR)
1825   if(sep AND script_initial_cache)
1826     string(REPLACE "${sep}" ";" script_initial_cache "${script_initial_cache}")
1827   endif()
1828   # Write out the initial cache file to the location specified.
1829   file(GENERATE OUTPUT "${script_filename}" CONTENT "${script_initial_cache}")
1830 endfunction()
1831
1832
1833 function(ExternalProject_Get_Property name)
1834   foreach(var ${ARGN})
1835     string(TOUPPER "${var}" VAR)
1836     get_property(is_set TARGET ${name} PROPERTY _EP_${VAR} SET)
1837     if(NOT is_set)
1838       message(FATAL_ERROR "External project \"${name}\" has no ${var}")
1839     endif()
1840     get_property(${var} TARGET ${name} PROPERTY _EP_${VAR})
1841     set(${var} "${${var}}" PARENT_SCOPE)
1842   endforeach()
1843 endfunction()
1844
1845
1846 function(_ep_get_configure_command_id name cfg_cmd_id_var)
1847   get_target_property(cmd ${name} _EP_CONFIGURE_COMMAND)
1848
1849   if(cmd STREQUAL "")
1850     # Explicit empty string means no configure step for this project
1851     set(${cfg_cmd_id_var} "none" PARENT_SCOPE)
1852   else()
1853     if(NOT cmd)
1854       # Default is "use cmake":
1855       set(${cfg_cmd_id_var} "cmake" PARENT_SCOPE)
1856     else()
1857       # Otherwise we have to analyze the value:
1858       if(cmd MATCHES "^[^;]*/configure")
1859         set(${cfg_cmd_id_var} "configure" PARENT_SCOPE)
1860       elseif(cmd MATCHES "^[^;]*/cmake" AND NOT cmd MATCHES ";-[PE];")
1861         set(${cfg_cmd_id_var} "cmake" PARENT_SCOPE)
1862       elseif(cmd MATCHES "config")
1863         set(${cfg_cmd_id_var} "configure" PARENT_SCOPE)
1864       else()
1865         set(${cfg_cmd_id_var} "unknown:${cmd}" PARENT_SCOPE)
1866       endif()
1867     endif()
1868   endif()
1869 endfunction()
1870
1871
1872 function(_ep_get_build_command name step cmd_var)
1873   set(cmd "")
1874   set(args)
1875   _ep_get_configure_command_id(${name} cfg_cmd_id)
1876   if(cfg_cmd_id STREQUAL "cmake")
1877     # CMake project.  Select build command based on generator.
1878     get_target_property(cmake_generator ${name} _EP_CMAKE_GENERATOR)
1879     if("${CMAKE_GENERATOR}" MATCHES "Make" AND
1880        ("${cmake_generator}" MATCHES "Make" OR NOT cmake_generator))
1881       # The project uses the same Makefile generator.  Use recursive make.
1882       set(cmd "$(MAKE)")
1883       if(step STREQUAL "INSTALL")
1884         set(args install)
1885       endif()
1886       if("x${step}x" STREQUAL "xTESTx")
1887         set(args test)
1888       endif()
1889     else()
1890       # Drive the project with "cmake --build".
1891       get_target_property(cmake_command ${name} _EP_CMAKE_COMMAND)
1892       if(cmake_command)
1893         set(cmd "${cmake_command}")
1894       else()
1895         set(cmd "${CMAKE_COMMAND}")
1896       endif()
1897       set(args --build ".")
1898       get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
1899       if(_isMultiConfig)
1900         if (CMAKE_CFG_INTDIR AND
1901             NOT CMAKE_CFG_INTDIR STREQUAL "." AND
1902             NOT CMAKE_CFG_INTDIR MATCHES "\\$")
1903           # CMake 3.4 and below used the CMAKE_CFG_INTDIR placeholder value
1904           # provided by multi-configuration generators.  Some projects were
1905           # taking advantage of that undocumented implementation detail to
1906           # specify a specific configuration here.  They should use
1907           # BUILD_COMMAND to change the default command instead, but for
1908           # compatibility honor the value.
1909           set(config ${CMAKE_CFG_INTDIR})
1910           message(AUTHOR_WARNING "CMAKE_CFG_INTDIR should not be set by project code.\n"
1911             "To get a non-default build command, use the BUILD_COMMAND option.")
1912         else()
1913           set(config $<CONFIG>)
1914         endif()
1915         list(APPEND args --config ${config})
1916       endif()
1917       if(step STREQUAL "INSTALL")
1918         list(APPEND args --target install)
1919       endif()
1920       # But for "TEST" drive the project with corresponding "ctest".
1921       if("x${step}x" STREQUAL "xTESTx")
1922         string(REGEX REPLACE "^(.*/)cmake([^/]*)$" "\\1ctest\\2" cmd "${cmd}")
1923         set(args "")
1924         if(_isMultiConfig)
1925           list(APPEND args -C ${config})
1926         endif()
1927       endif()
1928     endif()
1929   else()
1930     # Non-CMake project.  Guess "make" and "make install" and "make test".
1931     if("${CMAKE_GENERATOR}" MATCHES "Makefiles")
1932       # Try to get the parallel arguments
1933       set(cmd "$(MAKE)")
1934     else()
1935       set(cmd "make")
1936     endif()
1937     if(step STREQUAL "INSTALL")
1938       set(args install)
1939     endif()
1940     if("x${step}x" STREQUAL "xTESTx")
1941       set(args test)
1942     endif()
1943   endif()
1944
1945   # Use user-specified arguments instead of default arguments, if any.
1946   get_property(have_args TARGET ${name} PROPERTY _EP_${step}_ARGS SET)
1947   if(have_args)
1948     get_target_property(args ${name} _EP_${step}_ARGS)
1949   endif()
1950
1951   if(NOT "${args}" STREQUAL "")
1952     # args could have empty items, so we must quote it to prevent them
1953     # from being silently removed
1954     list(APPEND cmd "${args}")
1955   endif()
1956   set(${cmd_var} "${cmd}" PARENT_SCOPE)
1957 endfunction()
1958
1959 function(_ep_write_log_script name step cmd_var)
1960   ExternalProject_Get_Property(${name} log_dir)
1961   ExternalProject_Get_Property(${name} stamp_dir)
1962   set(command "${${cmd_var}}")
1963
1964   set(make "")
1965   set(code_cygpath_make "")
1966   if(command MATCHES "^\\$\\(MAKE\\)")
1967     # GNU make recognizes the string "$(MAKE)" as recursive make, so
1968     # ensure that it appears directly in the makefile.
1969     string(REGEX REPLACE "^\\$\\(MAKE\\)" "\${make}" command "${command}")
1970     set(make "-Dmake=$(MAKE)")
1971
1972     if(WIN32 AND NOT CYGWIN)
1973       set(code_cygpath_make "
1974 if(\${make} MATCHES \"^/\")
1975   execute_process(
1976     COMMAND cygpath -w \${make}
1977     OUTPUT_VARIABLE cygpath_make
1978     ERROR_VARIABLE cygpath_make
1979     RESULT_VARIABLE cygpath_error
1980     OUTPUT_STRIP_TRAILING_WHITESPACE
1981   )
1982   if(NOT cygpath_error)
1983     set(make \${cygpath_make})
1984   endif()
1985 endif()
1986 ")
1987     endif()
1988   endif()
1989
1990   set(config "")
1991   if("${CMAKE_CFG_INTDIR}" MATCHES "^\\$")
1992     string(REPLACE "${CMAKE_CFG_INTDIR}" "\${config}" command "${command}")
1993     set(config "-Dconfig=${CMAKE_CFG_INTDIR}")
1994   endif()
1995
1996   # Wrap multiple 'COMMAND' lines up into a second-level wrapper
1997   # script so all output can be sent to one log file.
1998   if(command MATCHES "(^|;)COMMAND;")
1999     set(code_execute_process "
2000 ${code_cygpath_make}
2001 execute_process(COMMAND \${command} RESULT_VARIABLE result)
2002 if(result)
2003   set(msg \"Command failed (\${result}):\\n\")
2004   foreach(arg IN LISTS command)
2005     set(msg \"\${msg} '\${arg}'\")
2006   endforeach()
2007   message(FATAL_ERROR \"\${msg}\")
2008 endif()
2009 ")
2010     set(code "")
2011     set(cmd "")
2012     set(sep "")
2013     foreach(arg IN LISTS command)
2014       if("x${arg}" STREQUAL "xCOMMAND")
2015         if(NOT "x${cmd}" STREQUAL "x")
2016           string(APPEND code "set(command \"${cmd}\")${code_execute_process}")
2017         endif()
2018         set(cmd "")
2019         set(sep "")
2020       else()
2021         string(APPEND cmd "${sep}${arg}")
2022         set(sep ";")
2023       endif()
2024     endforeach()
2025     string(APPEND code "set(command \"${cmd}\")${code_execute_process}")
2026     file(GENERATE OUTPUT "${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake" CONTENT "${code}")
2027     set(command ${CMAKE_COMMAND} "-Dmake=\${make}" "-Dconfig=\${config}" -P ${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake)
2028   endif()
2029
2030   # Wrap the command in a script to log output to files.
2031   set(script ${stamp_dir}/${name}-${step}-$<CONFIG>.cmake)
2032   set(logbase ${log_dir}/${name}-${step})
2033   get_property(log_merged TARGET ${name} PROPERTY _EP_LOG_MERGED_STDOUTERR)
2034   get_property(log_output_on_failure TARGET ${name} PROPERTY _EP_LOG_OUTPUT_ON_FAILURE)
2035   if (log_merged)
2036     set(stdout_log "${logbase}.log")
2037     set(stderr_log "${logbase}.log")
2038   else()
2039     set(stdout_log "${logbase}-out.log")
2040     set(stderr_log "${logbase}-err.log")
2041   endif()
2042   set(code "
2043 cmake_minimum_required(VERSION 3.15)
2044 ${code_cygpath_make}
2045 set(command \"${command}\")
2046 set(log_merged \"${log_merged}\")
2047 set(log_output_on_failure \"${log_output_on_failure}\")
2048 set(stdout_log \"${stdout_log}\")
2049 set(stderr_log \"${stderr_log}\")
2050 execute_process(
2051   COMMAND \${command}
2052   RESULT_VARIABLE result
2053   OUTPUT_FILE \"\${stdout_log}\"
2054   ERROR_FILE \"\${stderr_log}\"
2055   )
2056 macro(read_up_to_max_size log_file output_var)
2057   file(SIZE \${log_file} determined_size)
2058   set(max_size 10240)
2059   if (determined_size GREATER max_size)
2060     math(EXPR seek_position \"\${determined_size} - \${max_size}\")
2061     file(READ \${log_file} \${output_var} OFFSET \${seek_position})
2062     set(\${output_var} \"...skipping to end...\\n\${\${output_var}}\")
2063   else()
2064     file(READ \${log_file} \${output_var})
2065   endif()
2066 endmacro()
2067 if(result)
2068   set(msg \"Command failed: \${result}\\n\")
2069   foreach(arg IN LISTS command)
2070     set(msg \"\${msg} '\${arg}'\")
2071   endforeach()
2072   if (\${log_merged})
2073     set(msg \"\${msg}\\nSee also\\n  \${stderr_log}\")
2074   else()
2075     set(msg \"\${msg}\\nSee also\\n  ${logbase}-*.log\")
2076   endif()
2077   if (\${log_output_on_failure})
2078     message(SEND_ERROR \"\${msg}\")
2079     if (\${log_merged})
2080       read_up_to_max_size(\"\${stderr_log}\" error_log_contents)
2081       message(STATUS \"Log output is:\\n\${error_log_contents}\")
2082     else()
2083       read_up_to_max_size(\"\${stdout_log}\" out_log_contents)
2084       read_up_to_max_size(\"\${stderr_log}\" err_log_contents)
2085       message(STATUS \"stdout output is:\\n\${out_log_contents}\")
2086       message(STATUS \"stderr output is:\\n\${err_log_contents}\")
2087     endif()
2088     message(FATAL_ERROR \"Stopping after outputting logs.\")
2089   else()
2090     message(FATAL_ERROR \"\${msg}\")
2091   endif()
2092 else()
2093   if(NOT \"${CMAKE_GENERATOR}\" MATCHES \"Ninja\")
2094     set(msg \"${name} ${step} command succeeded.  See also ${logbase}-*.log\")
2095     message(STATUS \"\${msg}\")
2096   endif()
2097 endif()
2098 ")
2099   file(GENERATE OUTPUT "${script}" CONTENT "${code}")
2100   set(command ${CMAKE_COMMAND} ${make} ${config} -P ${script})
2101   set(${cmd_var} "${command}" PARENT_SCOPE)
2102 endfunction()
2103
2104 # This module used to use "/${CMAKE_CFG_INTDIR}" directly and produced
2105 # makefiles with "/./" in paths for custom command dependencies. Which
2106 # resulted in problems with parallel make -j invocations.
2107 #
2108 # This function was added so that the suffix (search below for ${cfgdir}) is
2109 # only set to "/${CMAKE_CFG_INTDIR}" when ${CMAKE_CFG_INTDIR} is not going to
2110 # be "." (multi-configuration build systems like Visual Studio and Xcode...)
2111 #
2112 function(_ep_get_configuration_subdir_suffix suffix_var)
2113   set(suffix "")
2114   get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
2115   if(_isMultiConfig)
2116     set(suffix "/${CMAKE_CFG_INTDIR}")
2117   endif()
2118   set(${suffix_var} "${suffix}" PARENT_SCOPE)
2119 endfunction()
2120
2121
2122 function(_ep_get_step_stampfile name step stampfile_var)
2123   ExternalProject_Get_Property(${name} stamp_dir)
2124
2125   _ep_get_configuration_subdir_suffix(cfgdir)
2126   set(stampfile "${stamp_dir}${cfgdir}/${name}-${step}")
2127
2128   set(${stampfile_var} "${stampfile}" PARENT_SCOPE)
2129 endfunction()
2130
2131
2132 function(_ep_get_complete_stampfile name stampfile_var)
2133   set(cmf_dir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles)
2134   _ep_get_configuration_subdir_suffix(cfgdir)
2135   set(stampfile "${cmf_dir}${cfgdir}/${name}-complete")
2136
2137   set(${stampfile_var} ${stampfile} PARENT_SCOPE)
2138 endfunction()
2139
2140
2141 function(_ep_step_add_target name step no_deps)
2142   if(TARGET ${name}-${step})
2143     return()
2144   endif()
2145   get_property(cmp0114 TARGET ${name} PROPERTY _EP_CMP0114)
2146   _ep_get_step_stampfile(${name} ${step} stamp_file)
2147   cmake_policy(PUSH)
2148   if(cmp0114 STREQUAL "NEW")
2149     # To implement CMP0114 NEW behavior with Makefile generators,
2150     # we need CMP0113 NEW behavior.
2151     cmake_policy(SET CMP0113 NEW)
2152   endif()
2153   add_custom_target(${name}-${step}
2154     DEPENDS ${stamp_file})
2155   cmake_policy(POP)
2156   set_property(TARGET ${name}-${step} PROPERTY _EP_IS_EXTERNAL_PROJECT_STEP 1)
2157   set_property(TARGET ${name}-${step} PROPERTY LABELS ${name})
2158   set_property(TARGET ${name}-${step} PROPERTY FOLDER "ExternalProjectTargets/${name}")
2159
2160   if(cmp0114 STREQUAL "NEW")
2161     # Add target-level dependencies for the step.
2162     get_property(exclude_from_main TARGET ${name} PROPERTY _EP_${step}_EXCLUDE_FROM_MAIN)
2163     if(NOT exclude_from_main)
2164       add_dependencies(${name} ${name}-${step})
2165     endif()
2166     _ep_step_add_target_dependencies(${name} ${step} ${step})
2167     _ep_step_add_target_dependents(${name} ${step} ${step})
2168
2169     get_property(independent TARGET ${name} PROPERTY _EP_${step}_INDEPENDENT)
2170   else()
2171     if(no_deps AND "${step}" MATCHES "^(configure|build|install|test)$")
2172       message(AUTHOR_WARNING "Using NO_DEPENDS for \"${step}\" step  might break parallel builds")
2173     endif()
2174     set(independent ${no_deps})
2175   endif()
2176
2177   # Depend on other external projects (target-level).
2178   if(NOT independent)
2179     get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
2180     foreach(arg IN LISTS deps)
2181       add_dependencies(${name}-${step} ${arg})
2182     endforeach()
2183   endif()
2184 endfunction()
2185
2186
2187 function(_ep_step_add_target_dependencies name step node)
2188   get_property(dependees TARGET ${name} PROPERTY _EP_${node}_INTERNAL_DEPENDEES)
2189   list(REMOVE_DUPLICATES dependees)
2190   foreach(dependee IN LISTS dependees)
2191     get_property(exclude_from_main TARGET ${name} PROPERTY _EP_${step}_EXCLUDE_FROM_MAIN)
2192     get_property(dependee_dependers TARGET ${name} PROPERTY _EP_${dependee}_INTERNAL_DEPENDERS)
2193     if(exclude_from_main OR dependee_dependers MATCHES ";")
2194       # The step on which our step target depends itself has
2195       # dependents in multiple targes.  It needs a step target too
2196       # so that there is a unique place for its custom command.
2197       _ep_step_add_target("${name}" "${dependee}" "FALSE")
2198     endif()
2199
2200     if(TARGET ${name}-${dependee})
2201       add_dependencies(${name}-${step} ${name}-${dependee})
2202     else()
2203       _ep_step_add_target_dependencies(${name} ${step} ${dependee})
2204     endif()
2205   endforeach()
2206 endfunction()
2207
2208
2209 function(_ep_step_add_target_dependents name step node)
2210   get_property(dependers TARGET ${name} PROPERTY _EP_${node}_INTERNAL_DEPENDERS)
2211   list(REMOVE_DUPLICATES dependers)
2212   foreach(depender IN LISTS dependers)
2213     if(TARGET ${name}-${depender})
2214       add_dependencies(${name}-${depender} ${name}-${step})
2215     else()
2216       _ep_step_add_target_dependents(${name} ${step} ${depender})
2217     endif()
2218   endforeach()
2219 endfunction()
2220
2221
2222 function(ExternalProject_Add_StepTargets name)
2223   get_property(cmp0114 TARGET ${name} PROPERTY _EP_CMP0114)
2224   set(steps ${ARGN})
2225   if(ARGC GREATER 1 AND "${ARGV1}" STREQUAL "NO_DEPENDS")
2226     set(no_deps 1)
2227     list(REMOVE_AT steps 0)
2228   else()
2229     set(no_deps 0)
2230   endif()
2231   if(cmp0114 STREQUAL "NEW")
2232     if(no_deps)
2233       message(FATAL_ERROR
2234         "The 'NO_DEPENDS' option is no longer allowed.  "
2235         "It has been superseded by the per-step 'INDEPENDENT' option.  "
2236         "See policy CMP0114."
2237         )
2238     endif()
2239   elseif(cmp0114 STREQUAL "")
2240     cmake_policy(GET_WARNING CMP0114 _cmp0114_warning)
2241     string(APPEND _cmp0114_warning "\n"
2242       "ExternalProject target '${name}' would depend on the targets for "
2243       "step(s) '${steps}' under policy CMP0114, but this is being left out "
2244       "for compatibility since the policy is not set."
2245       )
2246     if(no_deps)
2247       string(APPEND _cmp0114_warning
2248         "  Also, the NO_DEPENDS option is deprecated in favor of policy CMP0114."
2249         )
2250     endif()
2251     message(AUTHOR_WARNING "${_cmp0114_warning}")
2252   endif()
2253   foreach(step ${steps})
2254     _ep_step_add_target("${name}" "${step}" "${no_deps}")
2255   endforeach()
2256 endfunction()
2257
2258
2259 function(ExternalProject_Add_Step name step)
2260   get_property(cmp0114 TARGET ${name} PROPERTY _EP_CMP0114)
2261   _ep_get_complete_stampfile(${name} complete_stamp_file)
2262   _ep_get_step_stampfile(${name} ${step} stamp_file)
2263
2264   set(keywords
2265     COMMAND
2266     COMMENT
2267     DEPENDEES
2268     DEPENDERS
2269     DEPENDS
2270     INDEPENDENT
2271     BYPRODUCTS
2272     ALWAYS
2273     EXCLUDE_FROM_MAIN
2274     WORKING_DIRECTORY
2275     LOG
2276     USES_TERMINAL
2277   )
2278   _ep_parse_arguments(ExternalProject_Add_Step "${keywords}"
2279                       ${name} _EP_${step}_ "${ARGN}")
2280
2281   get_property(independent TARGET ${name} PROPERTY _EP_${step}_INDEPENDENT)
2282   if(independent STREQUAL "")
2283     set(independent FALSE)
2284     set_property(TARGET ${name} PROPERTY _EP_${step}_INDEPENDENT "${independent}")
2285   endif()
2286
2287   get_property(exclude_from_main TARGET ${name} PROPERTY _EP_${step}_EXCLUDE_FROM_MAIN)
2288   if(NOT exclude_from_main)
2289     add_custom_command(APPEND
2290       OUTPUT ${complete_stamp_file}
2291       DEPENDS ${stamp_file}
2292       )
2293   endif()
2294
2295   # Steps depending on this step.
2296   get_property(dependers TARGET ${name} PROPERTY _EP_${step}_DEPENDERS)
2297   set_property(TARGET ${name} APPEND PROPERTY _EP_${step}_INTERNAL_DEPENDERS ${dependers})
2298   foreach(depender IN LISTS dependers)
2299     set_property(TARGET ${name} APPEND PROPERTY _EP_${depender}_INTERNAL_DEPENDEES ${step})
2300     _ep_get_step_stampfile(${name} ${depender} depender_stamp_file)
2301     add_custom_command(APPEND
2302       OUTPUT ${depender_stamp_file}
2303       DEPENDS ${stamp_file}
2304       )
2305     if(cmp0114 STREQUAL "NEW" AND NOT independent)
2306       get_property(dep_independent TARGET ${name} PROPERTY _EP_${depender}_INDEPENDENT)
2307       if(dep_independent)
2308         message(FATAL_ERROR "ExternalProject '${name}' step '${depender}' is marked INDEPENDENT "
2309           "but depends on step '${step}' that is not marked INDEPENDENT.")
2310       endif()
2311     endif()
2312   endforeach()
2313
2314   # Dependencies on files.
2315   get_property(depends TARGET ${name} PROPERTY _EP_${step}_DEPENDS)
2316
2317   # Byproducts of the step.
2318   get_property(byproducts TARGET ${name} PROPERTY _EP_${step}_BYPRODUCTS)
2319
2320   # Dependencies on steps.
2321   get_property(dependees TARGET ${name} PROPERTY _EP_${step}_DEPENDEES)
2322   set_property(TARGET ${name} APPEND PROPERTY _EP_${step}_INTERNAL_DEPENDEES ${dependees})
2323   foreach(dependee IN LISTS dependees)
2324     set_property(TARGET ${name} APPEND PROPERTY _EP_${dependee}_INTERNAL_DEPENDERS ${step})
2325     _ep_get_step_stampfile(${name} ${dependee} dependee_stamp_file)
2326     list(APPEND depends ${dependee_stamp_file})
2327     if(cmp0114 STREQUAL "NEW" AND independent)
2328       get_property(dep_independent TARGET ${name} PROPERTY _EP_${dependee}_INDEPENDENT)
2329       if(NOT dep_independent)
2330         message(FATAL_ERROR "ExternalProject '${name}' step '${step}' is marked INDEPENDENT "
2331           "but depends on step '${dependee}' that is not marked INDEPENDENT.")
2332       endif()
2333     endif()
2334   endforeach()
2335
2336   # The command to run.
2337   get_property(command TARGET ${name} PROPERTY _EP_${step}_COMMAND)
2338   if(command)
2339     set(comment "Performing ${step} step for '${name}'")
2340   else()
2341     set(comment "No ${step} step for '${name}'")
2342   endif()
2343   get_property(work_dir TARGET ${name} PROPERTY _EP_${step}_WORKING_DIRECTORY)
2344
2345   # Replace list separators.
2346   get_property(sep TARGET ${name} PROPERTY _EP_LIST_SEPARATOR)
2347   if(sep AND command)
2348     string(REPLACE "${sep}" "\\;" command "${command}")
2349   endif()
2350
2351   # Replace location tags.
2352   _ep_replace_location_tags(${name} comment command work_dir byproducts)
2353
2354   # Custom comment?
2355   get_property(comment_set TARGET ${name} PROPERTY _EP_${step}_COMMENT SET)
2356   if(comment_set)
2357     get_property(comment TARGET ${name} PROPERTY _EP_${step}_COMMENT)
2358   endif()
2359
2360   # Uses terminal?
2361   get_property(uses_terminal TARGET ${name} PROPERTY _EP_${step}_USES_TERMINAL)
2362   if(uses_terminal)
2363     set(uses_terminal USES_TERMINAL)
2364   else()
2365     set(uses_terminal "")
2366   endif()
2367
2368   # Run every time?
2369   get_property(always TARGET ${name} PROPERTY _EP_${step}_ALWAYS)
2370   if(always)
2371     set_property(SOURCE ${stamp_file} PROPERTY SYMBOLIC 1)
2372     set(touch)
2373     # Remove any existing stamp in case the option changed in an existing tree.
2374     get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
2375     if(_isMultiConfig)
2376       foreach(cfg ${CMAKE_CONFIGURATION_TYPES})
2377         string(REPLACE "/${CMAKE_CFG_INTDIR}" "/${cfg}" stamp_file_config "${stamp_file}")
2378         file(REMOVE ${stamp_file_config})
2379       endforeach()
2380     else()
2381       file(REMOVE ${stamp_file})
2382     endif()
2383   else()
2384     set(touch ${CMAKE_COMMAND} -E touch ${stamp_file})
2385   endif()
2386
2387   # Wrap with log script?
2388   get_property(log TARGET ${name} PROPERTY _EP_${step}_LOG)
2389   if(command AND log)
2390     _ep_write_log_script(${name} ${step} command)
2391   endif()
2392
2393   if("${command}" STREQUAL "")
2394     # Some generators (i.e. Xcode) will not generate a file level target
2395     # if no command is set, and therefore the dependencies on this
2396     # target will be broken.
2397     # The empty command is replaced by an echo command here in order to
2398     # avoid this issue.
2399     set(command ${CMAKE_COMMAND} -E echo_append)
2400   endif()
2401
2402   set(__cmdQuoted)
2403   foreach(__item IN LISTS command)
2404     string(APPEND __cmdQuoted " [==[${__item}]==]")
2405   endforeach()
2406   cmake_language(EVAL CODE "
2407     add_custom_command(
2408       OUTPUT \${stamp_file}
2409       BYPRODUCTS \${byproducts}
2410       COMMENT \${comment}
2411       COMMAND ${__cmdQuoted}
2412       COMMAND \${touch}
2413       DEPENDS \${depends}
2414       WORKING_DIRECTORY \${work_dir}
2415       VERBATIM
2416       ${uses_terminal}
2417     )"
2418   )
2419   set_property(TARGET ${name} APPEND PROPERTY _EP_STEPS ${step})
2420
2421   # Add custom "step target"?
2422   get_property(step_targets TARGET ${name} PROPERTY _EP_STEP_TARGETS)
2423   if(NOT step_targets)
2424     get_property(step_targets DIRECTORY PROPERTY EP_STEP_TARGETS)
2425   endif()
2426   foreach(st ${step_targets})
2427     if("${st}" STREQUAL "${step}")
2428       _ep_step_add_target("${name}" "${step}" "FALSE")
2429       break()
2430     endif()
2431   endforeach()
2432
2433   get_property(independent_step_targets TARGET ${name} PROPERTY _EP_INDEPENDENT_STEP_TARGETS)
2434   if(NOT independent_step_targets)
2435     get_property(independent_step_targets DIRECTORY PROPERTY EP_INDEPENDENT_STEP_TARGETS)
2436   endif()
2437   if(cmp0114 STREQUAL "NEW")
2438     if(independent_step_targets)
2439       message(FATAL_ERROR
2440         "ExternalProject '${name}' option 'INDEPENDENT_STEP_TARGETS' is set to\n"
2441         "  ${independent_step_targets}\n"
2442         "but the option is no longer allowed.  "
2443         "It has been superseded by the per-step 'INDEPENDENT' option.  "
2444         "See policy CMP0114."
2445         )
2446     endif()
2447   else()
2448     if(independent_step_targets AND cmp0114 STREQUAL "")
2449       get_property(warned TARGET ${name} PROPERTY _EP_CMP0114_WARNED_INDEPENDENT_STEP_TARGETS)
2450       if(NOT warned)
2451         set_property(TARGET ${name} PROPERTY _EP_CMP0114_WARNED_INDEPENDENT_STEP_TARGETS 1)
2452         cmake_policy(GET_WARNING CMP0114 _cmp0114_warning)
2453         string(APPEND _cmp0114_warning "\n"
2454           "ExternalProject '${name}' option INDEPENDENT_STEP_TARGETS is set to\n"
2455           "  ${independent_step_targets}\n"
2456           "but the option is deprecated in favor of policy CMP0114."
2457           )
2458         message(AUTHOR_WARNING "${_cmp0114_warning}")
2459       endif()
2460     endif()
2461     foreach(st ${independent_step_targets})
2462       if("${st}" STREQUAL "${step}")
2463         _ep_step_add_target("${name}" "${step}" "TRUE")
2464         break()
2465       endif()
2466     endforeach()
2467   endif()
2468 endfunction()
2469
2470
2471 function(ExternalProject_Add_StepDependencies name step)
2472   set(dependencies ${ARGN})
2473
2474   # Sanity checks on "name" and "step".
2475   if(NOT TARGET ${name})
2476     message(FATAL_ERROR "Cannot find target \"${name}\". Perhaps it has not yet been created using ExternalProject_Add.")
2477   endif()
2478
2479   get_property(type TARGET ${name} PROPERTY TYPE)
2480   if(NOT type STREQUAL "UTILITY")
2481     message(FATAL_ERROR "Target \"${name}\" was not generated by ExternalProject_Add.")
2482   endif()
2483
2484   get_property(is_ep TARGET ${name} PROPERTY _EP_IS_EXTERNAL_PROJECT)
2485   if(NOT is_ep)
2486     message(FATAL_ERROR "Target \"${name}\" was not generated by ExternalProject_Add.")
2487   endif()
2488
2489   get_property(steps TARGET ${name} PROPERTY _EP_STEPS)
2490   list(FIND steps ${step} is_step)
2491   if(is_step LESS 0)
2492     message(FATAL_ERROR "External project \"${name}\" does not have a step \"${step}\".")
2493   endif()
2494
2495   if(TARGET ${name}-${step})
2496     get_property(type TARGET ${name}-${step} PROPERTY TYPE)
2497     if(NOT type STREQUAL "UTILITY")
2498       message(FATAL_ERROR "Target \"${name}-${step}\" was not generated by ExternalProject_Add_StepTargets.")
2499     endif()
2500     get_property(is_ep_step TARGET ${name}-${step} PROPERTY _EP_IS_EXTERNAL_PROJECT_STEP)
2501     if(NOT is_ep_step)
2502       message(FATAL_ERROR "Target \"${name}-${step}\" was not generated by ExternalProject_Add_StepTargets.")
2503     endif()
2504   endif()
2505
2506   # Always add file-level dependency, but add target-level dependency
2507   # only if the target exists for that step.
2508   _ep_get_step_stampfile(${name} ${step} stamp_file)
2509   foreach(dep ${dependencies})
2510     add_custom_command(APPEND
2511       OUTPUT ${stamp_file}
2512       DEPENDS ${dep})
2513     if(TARGET ${name}-${step})
2514       foreach(dep ${dependencies})
2515         add_dependencies(${name}-${step} ${dep})
2516       endforeach()
2517     endif()
2518   endforeach()
2519
2520 endfunction()
2521
2522
2523 function(_ep_add_mkdir_command name)
2524   ExternalProject_Get_Property(${name}
2525     source_dir binary_dir install_dir stamp_dir download_dir tmp_dir log_dir)
2526
2527   _ep_get_configuration_subdir_suffix(cfgdir)
2528
2529   ExternalProject_Add_Step(${name} mkdir
2530     INDEPENDENT TRUE
2531     COMMENT "Creating directories for '${name}'"
2532     COMMAND ${CMAKE_COMMAND} -E make_directory ${source_dir}
2533     COMMAND ${CMAKE_COMMAND} -E make_directory ${binary_dir}
2534     COMMAND ${CMAKE_COMMAND} -E make_directory ${install_dir}
2535     COMMAND ${CMAKE_COMMAND} -E make_directory ${tmp_dir}
2536     COMMAND ${CMAKE_COMMAND} -E make_directory ${stamp_dir}${cfgdir}
2537     COMMAND ${CMAKE_COMMAND} -E make_directory ${download_dir}
2538     COMMAND ${CMAKE_COMMAND} -E make_directory ${log_dir}
2539     )
2540 endfunction()
2541
2542
2543 function(_ep_is_dir_empty dir empty_var)
2544   file(GLOB gr "${dir}/*")
2545   if("${gr}" STREQUAL "")
2546     set(${empty_var} 1 PARENT_SCOPE)
2547   else()
2548     set(${empty_var} 0 PARENT_SCOPE)
2549   endif()
2550 endfunction()
2551
2552 function(_ep_get_git_submodules_recurse git_submodules_recurse)
2553   # Checks for GIT_SUBMODULES_RECURSE property
2554   # Default is ON, which sets git_submodules_recurse output variable to "--recursive"
2555   # Otherwise, the output variable is set to an empty value ""
2556   get_property(git_submodules_recurse_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES_RECURSE SET)
2557   if(NOT git_submodules_recurse_set)
2558     set(recurseFlag "--recursive")
2559   else()
2560     get_property(git_submodules_recurse_value TARGET ${name} PROPERTY _EP_GIT_SUBMODULES_RECURSE)
2561     if(git_submodules_recurse_value)
2562       set(recurseFlag "--recursive")
2563     else()
2564       set(recurseFlag "")
2565     endif()
2566   endif()
2567   set(${git_submodules_recurse} "${recurseFlag}" PARENT_SCOPE)
2568
2569   # The git submodule update '--recursive' flag requires git >= v1.6.5
2570   if(recurseFlag AND GIT_VERSION_STRING VERSION_LESS 1.6.5)
2571     message(FATAL_ERROR "error: git version 1.6.5 or later required for --recursive flag with 'git submodule ...': GIT_VERSION_STRING='${GIT_VERSION_STRING}'")
2572   endif()
2573 endfunction()
2574
2575
2576 function(_ep_add_download_command name)
2577   ExternalProject_Get_Property(${name} source_dir stamp_dir download_dir tmp_dir)
2578
2579   get_property(cmd_set TARGET ${name} PROPERTY _EP_DOWNLOAD_COMMAND SET)
2580   get_property(cmd TARGET ${name} PROPERTY _EP_DOWNLOAD_COMMAND)
2581   get_property(cvs_repository TARGET ${name} PROPERTY _EP_CVS_REPOSITORY)
2582   get_property(svn_repository TARGET ${name} PROPERTY _EP_SVN_REPOSITORY)
2583   get_property(git_repository TARGET ${name} PROPERTY _EP_GIT_REPOSITORY)
2584   get_property(hg_repository  TARGET ${name} PROPERTY _EP_HG_REPOSITORY )
2585   get_property(url TARGET ${name} PROPERTY _EP_URL)
2586   get_property(fname TARGET ${name} PROPERTY _EP_DOWNLOAD_NAME)
2587
2588   # TODO: Perhaps file:// should be copied to download dir before extraction.
2589   string(REGEX REPLACE "file://" "" url "${url}")
2590
2591   set(depends)
2592   set(comment)
2593   set(work_dir)
2594
2595   if(cmd_set)
2596     set(work_dir ${download_dir})
2597   elseif(cvs_repository)
2598     find_package(CVS QUIET)
2599     if(NOT CVS_EXECUTABLE)
2600       message(FATAL_ERROR "error: could not find cvs for checkout of ${name}")
2601     endif()
2602
2603     get_target_property(cvs_module ${name} _EP_CVS_MODULE)
2604     if(NOT cvs_module)
2605       message(FATAL_ERROR "error: no CVS_MODULE")
2606     endif()
2607
2608     get_property(cvs_tag TARGET ${name} PROPERTY _EP_CVS_TAG)
2609
2610     set(repository ${cvs_repository})
2611     set(module ${cvs_module})
2612     set(tag ${cvs_tag})
2613     configure_file(
2614       "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
2615       "${stamp_dir}/${name}-cvsinfo.txt"
2616       @ONLY
2617       )
2618
2619     get_filename_component(src_name "${source_dir}" NAME)
2620     get_filename_component(work_dir "${source_dir}" PATH)
2621     set(comment "Performing download step (CVS checkout) for '${name}'")
2622     set(cmd ${CVS_EXECUTABLE} -d ${cvs_repository} -q co ${cvs_tag} -d ${src_name} ${cvs_module})
2623     list(APPEND depends ${stamp_dir}/${name}-cvsinfo.txt)
2624   elseif(svn_repository)
2625     find_package(Subversion QUIET)
2626     if(NOT Subversion_SVN_EXECUTABLE)
2627       message(FATAL_ERROR "error: could not find svn for checkout of ${name}")
2628     endif()
2629
2630     get_property(svn_revision TARGET ${name} PROPERTY _EP_SVN_REVISION)
2631     get_property(svn_username TARGET ${name} PROPERTY _EP_SVN_USERNAME)
2632     get_property(svn_password TARGET ${name} PROPERTY _EP_SVN_PASSWORD)
2633     get_property(svn_trust_cert TARGET ${name} PROPERTY _EP_SVN_TRUST_CERT)
2634
2635     set(repository "${svn_repository} user=${svn_username} password=${svn_password}")
2636     set(module)
2637     set(tag ${svn_revision})
2638     configure_file(
2639       "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
2640       "${stamp_dir}/${name}-svninfo.txt"
2641       @ONLY
2642       )
2643
2644     get_filename_component(src_name "${source_dir}" NAME)
2645     get_filename_component(work_dir "${source_dir}" PATH)
2646     set(comment "Performing download step (SVN checkout) for '${name}'")
2647     set(svn_user_pw_args "")
2648     if(DEFINED svn_username)
2649       set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}")
2650     endif()
2651     if(DEFINED svn_password)
2652       set(svn_user_pw_args ${svn_user_pw_args} "--password=${svn_password}")
2653     endif()
2654     if(svn_trust_cert)
2655       set(svn_trust_cert_args --trust-server-cert)
2656     endif()
2657     set(cmd ${Subversion_SVN_EXECUTABLE} co ${svn_repository} ${svn_revision}
2658       --non-interactive ${svn_trust_cert_args} ${svn_user_pw_args} ${src_name})
2659     list(APPEND depends ${stamp_dir}/${name}-svninfo.txt)
2660   elseif(git_repository)
2661     # FetchContent gives us these directly, so don't try to recompute them
2662     if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING)
2663       unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
2664       find_package(Git QUIET)
2665       if(NOT GIT_EXECUTABLE)
2666         message(FATAL_ERROR "error: could not find git for clone of ${name}")
2667       endif()
2668     endif()
2669
2670     _ep_get_git_submodules_recurse(git_submodules_recurse)
2671
2672     get_property(git_tag TARGET ${name} PROPERTY _EP_GIT_TAG)
2673     if(NOT git_tag)
2674       set(git_tag "master")
2675     endif()
2676
2677     set(git_init_submodules TRUE)
2678     get_property(git_submodules_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES SET)
2679     if(git_submodules_set)
2680       get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES)
2681       if(git_submodules  STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW")
2682         set(git_init_submodules FALSE)
2683       endif()
2684     endif()
2685
2686     get_property(git_remote_name TARGET ${name} PROPERTY _EP_GIT_REMOTE_NAME)
2687     if(NOT git_remote_name)
2688       set(git_remote_name "origin")
2689     endif()
2690
2691     get_property(tls_verify TARGET ${name} PROPERTY _EP_TLS_VERIFY)
2692     if("x${tls_verify}" STREQUAL "x" AND DEFINED CMAKE_TLS_VERIFY)
2693       set(tls_verify "${CMAKE_TLS_VERIFY}")
2694     endif()
2695     get_property(git_shallow TARGET ${name} PROPERTY _EP_GIT_SHALLOW)
2696     get_property(git_progress TARGET ${name} PROPERTY _EP_GIT_PROGRESS)
2697     get_property(git_config TARGET ${name} PROPERTY _EP_GIT_CONFIG)
2698
2699     # If git supports it, make checkouts quiet when checking out a git hash.
2700     # This avoids the very noisy detached head message.
2701     if(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.7)
2702       list(PREPEND git_config advice.detachedHead=false)
2703     endif()
2704
2705     # For the download step, and the git clone operation, only the repository
2706     # should be recorded in a configured RepositoryInfo file. If the repo
2707     # changes, the clone script should be run again. But if only the tag
2708     # changes, avoid running the clone script again. Let the 'always' running
2709     # update step checkout the new tag.
2710     #
2711     set(repository ${git_repository})
2712     set(module)
2713     set(tag ${git_remote_name})
2714     configure_file(
2715       "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
2716       "${stamp_dir}/${name}-gitinfo.txt"
2717       @ONLY
2718       )
2719
2720     get_filename_component(src_name "${source_dir}" NAME)
2721     get_filename_component(work_dir "${source_dir}" PATH)
2722
2723     # Since git clone doesn't succeed if the non-empty source_dir exists,
2724     # create a cmake script to invoke as download command.
2725     # The script will delete the source directory and then call git clone.
2726     #
2727     _ep_write_gitclone_script(${tmp_dir}/${name}-gitclone.cmake ${source_dir}
2728       ${GIT_EXECUTABLE} ${git_repository} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules_recurse}" "${git_submodules}" "${git_shallow}" "${git_progress}" "${git_config}" ${src_name} ${work_dir}
2729       ${stamp_dir}/${name}-gitinfo.txt ${stamp_dir}/${name}-gitclone-lastrun.txt "${tls_verify}"
2730       )
2731     set(comment "Performing download step (git clone) for '${name}'")
2732     set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-gitclone.cmake)
2733     list(APPEND depends ${stamp_dir}/${name}-gitinfo.txt)
2734   elseif(hg_repository)
2735     find_package(Hg QUIET)
2736     if(NOT HG_EXECUTABLE)
2737       message(FATAL_ERROR "error: could not find hg for clone of ${name}")
2738     endif()
2739
2740     get_property(hg_tag TARGET ${name} PROPERTY _EP_HG_TAG)
2741     if(NOT hg_tag)
2742       set(hg_tag "tip")
2743     endif()
2744
2745     # For the download step, and the hg clone operation, only the repository
2746     # should be recorded in a configured RepositoryInfo file. If the repo
2747     # changes, the clone script should be run again. But if only the tag
2748     # changes, avoid running the clone script again. Let the 'always' running
2749     # update step checkout the new tag.
2750     #
2751     set(repository ${hg_repository})
2752     set(module)
2753     set(tag)
2754     configure_file(
2755       "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
2756       "${stamp_dir}/${name}-hginfo.txt"
2757       @ONLY
2758       )
2759
2760     get_filename_component(src_name "${source_dir}" NAME)
2761     get_filename_component(work_dir "${source_dir}" PATH)
2762
2763     # Since hg clone doesn't succeed if the non-empty source_dir exists,
2764     # create a cmake script to invoke as download command.
2765     # The script will delete the source directory and then call hg clone.
2766     #
2767     _ep_write_hgclone_script(${tmp_dir}/${name}-hgclone.cmake ${source_dir}
2768       ${HG_EXECUTABLE} ${hg_repository} ${hg_tag} ${src_name} ${work_dir}
2769       ${stamp_dir}/${name}-hginfo.txt ${stamp_dir}/${name}-hgclone-lastrun.txt
2770       )
2771     set(comment "Performing download step (hg clone) for '${name}'")
2772     set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-hgclone.cmake)
2773     list(APPEND depends ${stamp_dir}/${name}-hginfo.txt)
2774   elseif(url)
2775     get_filename_component(work_dir "${source_dir}" PATH)
2776     get_property(hash TARGET ${name} PROPERTY _EP_URL_HASH)
2777     _ep_get_hash_regex(_ep_hash_regex)
2778     if(hash AND NOT "${hash}" MATCHES "${_ep_hash_regex}")
2779       _ep_get_hash_algos(_ep_hash_algos)
2780       list(JOIN _ep_hash_algos "|" _ep_hash_algos)
2781       message(FATAL_ERROR "URL_HASH is set to\n  ${hash}\n"
2782         "but must be ALGO=value where ALGO is\n  ${_ep_hash_algos}\n"
2783         "and value is a hex string.")
2784     endif()
2785     get_property(md5 TARGET ${name} PROPERTY _EP_URL_MD5)
2786     if(md5 AND NOT "MD5=${md5}" MATCHES "${_ep_hash_regex}")
2787       message(FATAL_ERROR "URL_MD5 is set to\n  ${md5}\nbut must be a hex string.")
2788     endif()
2789     if(md5 AND NOT hash)
2790       set(hash "MD5=${md5}")
2791     endif()
2792     set(repository "external project URL")
2793     set(module "${url}")
2794     set(tag "${hash}")
2795     configure_file(
2796       "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
2797       "${stamp_dir}/${name}-urlinfo.txt"
2798       @ONLY
2799       )
2800     list(APPEND depends ${stamp_dir}/${name}-urlinfo.txt)
2801
2802     list(LENGTH url url_list_length)
2803     if(NOT "${url_list_length}" STREQUAL "1")
2804       foreach(entry ${url})
2805         if(NOT "${entry}" MATCHES "^[a-z]+://")
2806           message(FATAL_ERROR "At least one entry of URL is a path (invalid in a list)")
2807         endif()
2808       endforeach()
2809       if("x${fname}" STREQUAL "x")
2810         list(GET url 0 fname)
2811       endif()
2812     endif()
2813
2814     if(IS_DIRECTORY "${url}")
2815       get_filename_component(abs_dir "${url}" ABSOLUTE)
2816       set(comment "Performing download step (DIR copy) for '${name}'")
2817       set(cmd   ${CMAKE_COMMAND} -E rm -rf ${source_dir}
2818         COMMAND ${CMAKE_COMMAND} -E copy_directory ${abs_dir} ${source_dir})
2819     else()
2820       get_property(no_extract TARGET "${name}" PROPERTY _EP_DOWNLOAD_NO_EXTRACT)
2821       if("${url}" MATCHES "^[a-z]+://")
2822         # TODO: Should download and extraction be different steps?
2823         if("x${fname}" STREQUAL "x")
2824           set(fname "${url}")
2825         endif()
2826         if("${fname}" MATCHES [[([^/\?#]+(\.|=)(7z|tar|tar\.bz2|tar\.gz|tar\.xz|tbz2|tgz|txz|zip))([/?#].*)?$]])
2827           set(fname "${CMAKE_MATCH_1}")
2828         elseif(no_extract)
2829           get_filename_component(fname "${fname}" NAME)
2830         else()
2831           # Fall back to a default file name.  The actual file name does not
2832           # matter because it is used only internally and our extraction tool
2833           # inspects the file content directly.  If it turns out the wrong URL
2834           # was given that will be revealed during the build which is an easier
2835           # place for users to diagnose than an error here anyway.
2836           set(fname "archive.tar")
2837         endif()
2838         string(REPLACE ";" "-" fname "${fname}")
2839         set(file ${download_dir}/${fname})
2840         get_property(timeout TARGET ${name} PROPERTY _EP_TIMEOUT)
2841         get_property(inactivity_timeout TARGET ${name} PROPERTY _EP_INACTIVITY_TIMEOUT)
2842         get_property(no_progress TARGET ${name} PROPERTY _EP_DOWNLOAD_NO_PROGRESS)
2843         get_property(tls_verify TARGET ${name} PROPERTY _EP_TLS_VERIFY)
2844         get_property(tls_cainfo TARGET ${name} PROPERTY _EP_TLS_CAINFO)
2845         get_property(netrc TARGET ${name} PROPERTY _EP_NETRC)
2846         get_property(netrc_file TARGET ${name} PROPERTY _EP_NETRC_FILE)
2847         get_property(http_username TARGET ${name} PROPERTY _EP_HTTP_USERNAME)
2848         get_property(http_password TARGET ${name} PROPERTY _EP_HTTP_PASSWORD)
2849         get_property(http_headers TARGET ${name} PROPERTY _EP_HTTP_HEADER)
2850         set(download_script "${stamp_dir}/download-${name}.cmake")
2851         _ep_write_downloadfile_script("${download_script}" "${url}" "${file}" "${timeout}" "${inactivity_timeout}" "${no_progress}" "${hash}" "${tls_verify}" "${tls_cainfo}" "${http_username}:${http_password}" "${http_headers}" "${netrc}" "${netrc_file}")
2852         set(cmd ${CMAKE_COMMAND} -P "${download_script}"
2853           COMMAND)
2854         if (no_extract)
2855           set(steps "download and verify")
2856         else ()
2857           set(steps "download, verify and extract")
2858         endif ()
2859         set(comment "Performing download step (${steps}) for '${name}'")
2860         file(WRITE "${stamp_dir}/verify-${name}.cmake" "") # already verified by 'download_script'
2861       else()
2862         set(file "${url}")
2863         if (no_extract)
2864           set(steps "verify")
2865         else ()
2866           set(steps "verify and extract")
2867         endif ()
2868         set(comment "Performing download step (${steps}) for '${name}'")
2869         _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}")
2870       endif()
2871       list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake)
2872       if (NOT no_extract)
2873         _ep_write_extractfile_script("${stamp_dir}/extract-${name}.cmake" "${name}" "${file}" "${source_dir}")
2874         list(APPEND cmd COMMAND ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake)
2875       else ()
2876         set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file})
2877       endif ()
2878     endif()
2879   else()
2880     _ep_is_dir_empty("${source_dir}" empty)
2881     if(${empty})
2882       message(SEND_ERROR
2883         "No download info given for '${name}' and its source directory:\n"
2884         " ${source_dir}\n"
2885         "is not an existing non-empty directory.  Please specify one of:\n"
2886         " * SOURCE_DIR with an existing non-empty directory\n"
2887         " * DOWNLOAD_COMMAND\n"
2888         " * URL\n"
2889         " * GIT_REPOSITORY\n"
2890         " * SVN_REPOSITORY\n"
2891         " * HG_REPOSITORY\n"
2892         " * CVS_REPOSITORY and CVS_MODULE"
2893         )
2894     endif()
2895   endif()
2896
2897   get_property(log TARGET ${name} PROPERTY _EP_LOG_DOWNLOAD)
2898   if(log)
2899     set(log LOG 1)
2900   else()
2901     set(log "")
2902   endif()
2903
2904   get_property(uses_terminal TARGET ${name} PROPERTY
2905     _EP_USES_TERMINAL_DOWNLOAD)
2906   if(uses_terminal)
2907     set(uses_terminal USES_TERMINAL 1)
2908   else()
2909     set(uses_terminal "")
2910   endif()
2911
2912   set(__cmdQuoted)
2913   foreach(__item IN LISTS cmd)
2914     string(APPEND __cmdQuoted " [==[${__item}]==]")
2915   endforeach()
2916   cmake_language(EVAL CODE "
2917     ExternalProject_Add_Step(\${name} download
2918       INDEPENDENT TRUE
2919       COMMENT \${comment}
2920       COMMAND ${__cmdQuoted}
2921       WORKING_DIRECTORY \${work_dir}
2922       DEPENDS \${depends}
2923       DEPENDEES mkdir
2924       ${log}
2925       ${uses_terminal}
2926       )"
2927   )
2928 endfunction()
2929
2930 function(_ep_get_update_disconnected var name)
2931   get_property(update_disconnected_set TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED SET)
2932   if(update_disconnected_set)
2933     get_property(update_disconnected TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED)
2934   else()
2935     get_property(update_disconnected DIRECTORY PROPERTY EP_UPDATE_DISCONNECTED)
2936   endif()
2937   set(${var} "${update_disconnected}" PARENT_SCOPE)
2938 endfunction()
2939
2940 function(_ep_add_update_command name)
2941   ExternalProject_Get_Property(${name} source_dir tmp_dir)
2942
2943   get_property(cmd_set TARGET ${name} PROPERTY _EP_UPDATE_COMMAND SET)
2944   get_property(cmd TARGET ${name} PROPERTY _EP_UPDATE_COMMAND)
2945   get_property(cvs_repository TARGET ${name} PROPERTY _EP_CVS_REPOSITORY)
2946   get_property(svn_repository TARGET ${name} PROPERTY _EP_SVN_REPOSITORY)
2947   get_property(git_repository TARGET ${name} PROPERTY _EP_GIT_REPOSITORY)
2948   get_property(hg_repository  TARGET ${name} PROPERTY _EP_HG_REPOSITORY )
2949
2950   _ep_get_update_disconnected(update_disconnected ${name})
2951
2952   set(work_dir)
2953   set(comment)
2954   set(always)
2955
2956   if(cmd_set)
2957     set(work_dir ${source_dir})
2958     if(NOT "x${cmd}" STREQUAL "x")
2959       set(always 1)
2960     endif()
2961   elseif(cvs_repository)
2962     if(NOT CVS_EXECUTABLE)
2963       message(FATAL_ERROR "error: could not find cvs for update of ${name}")
2964     endif()
2965     set(work_dir ${source_dir})
2966     set(comment "Performing update step (CVS update) for '${name}'")
2967     get_property(cvs_tag TARGET ${name} PROPERTY _EP_CVS_TAG)
2968     set(cmd ${CVS_EXECUTABLE} -d ${cvs_repository} -q up -dP ${cvs_tag})
2969     set(always 1)
2970   elseif(svn_repository)
2971     if(NOT Subversion_SVN_EXECUTABLE)
2972       message(FATAL_ERROR "error: could not find svn for update of ${name}")
2973     endif()
2974     set(work_dir ${source_dir})
2975     set(comment "Performing update step (SVN update) for '${name}'")
2976     get_property(svn_revision TARGET ${name} PROPERTY _EP_SVN_REVISION)
2977     get_property(svn_username TARGET ${name} PROPERTY _EP_SVN_USERNAME)
2978     get_property(svn_password TARGET ${name} PROPERTY _EP_SVN_PASSWORD)
2979     get_property(svn_trust_cert TARGET ${name} PROPERTY _EP_SVN_TRUST_CERT)
2980     set(svn_user_pw_args "")
2981     if(DEFINED svn_username)
2982       set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}")
2983     endif()
2984     if(DEFINED svn_password)
2985       set(svn_user_pw_args ${svn_user_pw_args} "--password=${svn_password}")
2986     endif()
2987     if(svn_trust_cert)
2988       set(svn_trust_cert_args --trust-server-cert)
2989     endif()
2990     set(cmd ${Subversion_SVN_EXECUTABLE} up ${svn_revision}
2991       --non-interactive ${svn_trust_cert_args} ${svn_user_pw_args})
2992     set(always 1)
2993   elseif(git_repository)
2994     # FetchContent gives us these directly, so don't try to recompute them
2995     if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING)
2996       unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
2997       find_package(Git QUIET)
2998       if(NOT GIT_EXECUTABLE)
2999         message(FATAL_ERROR "error: could not find git for fetch of ${name}")
3000       endif()
3001     endif()
3002     set(work_dir ${source_dir})
3003     set(comment "Performing update step for '${name}'")
3004     get_property(git_tag TARGET ${name} PROPERTY _EP_GIT_TAG)
3005     if(NOT git_tag)
3006       set(git_tag "master")
3007     endif()
3008     get_property(git_remote_name TARGET ${name} PROPERTY _EP_GIT_REMOTE_NAME)
3009     if(NOT git_remote_name)
3010       set(git_remote_name "origin")
3011     endif()
3012
3013     set(git_init_submodules TRUE)
3014     get_property(git_submodules_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES SET)
3015     if(git_submodules_set)
3016       get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES)
3017       if(git_submodules  STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW")
3018         set(git_init_submodules FALSE)
3019       endif()
3020     endif()
3021
3022     get_property(git_update_strategy TARGET ${name} PROPERTY _EP_GIT_REMOTE_UPDATE_STRATEGY)
3023     if(NOT git_update_strategy)
3024       set(git_update_strategy "${CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY}")
3025     endif()
3026     if(NOT git_update_strategy)
3027       set(git_update_strategy REBASE)
3028     endif()
3029     set(strategies CHECKOUT REBASE REBASE_CHECKOUT)
3030     if(NOT git_update_strategy IN_LIST strategies)
3031       message(FATAL_ERROR "'${git_update_strategy}' is not one of the supported strategies: ${strategies}")
3032     endif()
3033
3034     _ep_get_git_submodules_recurse(git_submodules_recurse)
3035
3036     _ep_write_gitupdate_script(${tmp_dir}/${name}-gitupdate.cmake
3037       ${GIT_EXECUTABLE} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules_recurse}" "${git_submodules}" ${git_repository} ${work_dir} ${git_update_strategy}
3038       )
3039     set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-gitupdate.cmake)
3040     set(always 1)
3041   elseif(hg_repository)
3042     if(NOT HG_EXECUTABLE)
3043       message(FATAL_ERROR "error: could not find hg for pull of ${name}")
3044     endif()
3045     set(work_dir ${source_dir})
3046     set(comment "Performing update step (hg pull) for '${name}'")
3047     get_property(hg_tag TARGET ${name} PROPERTY _EP_HG_TAG)
3048     if(NOT hg_tag)
3049       set(hg_tag "tip")
3050     endif()
3051     if("${HG_VERSION_STRING}" STREQUAL "2.1")
3052       message(WARNING "Mercurial 2.1 does not distinguish an empty pull from a failed pull:
3053  http://mercurial.selenic.com/wiki/UpgradeNotes#A2.1.1:_revert_pull_return_code_change.2C_compile_issue_on_OS_X
3054  http://thread.gmane.org/gmane.comp.version-control.mercurial.devel/47656
3055 Update to Mercurial >= 2.1.1.
3056 ")
3057     endif()
3058     set(cmd ${HG_EXECUTABLE} pull
3059       COMMAND ${HG_EXECUTABLE} update ${hg_tag}
3060       )
3061     set(always 1)
3062   endif()
3063
3064   get_property(log TARGET ${name} PROPERTY _EP_LOG_UPDATE)
3065   if(log)
3066     set(log LOG 1)
3067   else()
3068     set(log "")
3069   endif()
3070
3071   get_property(uses_terminal TARGET ${name} PROPERTY
3072     _EP_USES_TERMINAL_UPDATE)
3073   if(uses_terminal)
3074     set(uses_terminal USES_TERMINAL 1)
3075   else()
3076     set(uses_terminal "")
3077   endif()
3078
3079   set(__cmdQuoted)
3080   foreach(__item IN LISTS cmd)
3081     string(APPEND __cmdQuoted " [==[${__item}]==]")
3082   endforeach()
3083   cmake_language(EVAL CODE "
3084     ExternalProject_Add_Step(${name} update
3085       INDEPENDENT TRUE
3086       COMMENT \${comment}
3087       COMMAND ${__cmdQuoted}
3088       ALWAYS \${always}
3089       EXCLUDE_FROM_MAIN \${update_disconnected}
3090       WORKING_DIRECTORY \${work_dir}
3091       DEPENDEES download
3092       ${log}
3093       ${uses_terminal}
3094       )"
3095   )
3096
3097 endfunction()
3098
3099
3100 function(_ep_add_patch_command name)
3101   ExternalProject_Get_Property(${name} source_dir)
3102
3103   get_property(cmd_set TARGET ${name} PROPERTY _EP_PATCH_COMMAND SET)
3104   get_property(cmd TARGET ${name} PROPERTY _EP_PATCH_COMMAND)
3105
3106   set(work_dir)
3107
3108   if(cmd_set)
3109     set(work_dir ${source_dir})
3110   endif()
3111
3112   get_property(log TARGET ${name} PROPERTY _EP_LOG_PATCH)
3113   if(log)
3114     set(log LOG 1)
3115   else()
3116     set(log "")
3117   endif()
3118
3119   _ep_get_update_disconnected(update_disconnected ${name})
3120   if(update_disconnected)
3121     set(patch_dep download)
3122   else()
3123     set(patch_dep update)
3124   endif()
3125
3126   set(__cmdQuoted)
3127   foreach(__item IN LISTS cmd)
3128     string(APPEND __cmdQuoted " [==[${__item}]==]")
3129   endforeach()
3130   cmake_language(EVAL CODE "
3131     ExternalProject_Add_Step(${name} patch
3132       INDEPENDENT TRUE
3133       COMMAND ${__cmdQuoted}
3134       WORKING_DIRECTORY \${work_dir}
3135       DEPENDEES \${patch_dep}
3136       ${log}
3137       )"
3138   )
3139 endfunction()
3140
3141 function(_ep_get_file_deps var name)
3142   set(file_deps)
3143
3144   get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
3145   foreach(dep IN LISTS deps)
3146     get_property(dep_type TARGET ${dep} PROPERTY TYPE)
3147     if(dep_type STREQUAL "UTILITY")
3148       get_property(is_ep TARGET ${dep} PROPERTY _EP_IS_EXTERNAL_PROJECT)
3149       if(is_ep)
3150         _ep_get_step_stampfile(${dep} "done" done_stamp_file)
3151         list(APPEND file_deps ${done_stamp_file})
3152       endif()
3153     endif()
3154   endforeach()
3155
3156   set("${var}" "${file_deps}" PARENT_SCOPE)
3157 endfunction()
3158
3159 function(_ep_extract_configure_command var name)
3160   get_property(cmd_set TARGET ${name} PROPERTY _EP_CONFIGURE_COMMAND SET)
3161   if(cmd_set)
3162     get_property(cmd TARGET ${name} PROPERTY _EP_CONFIGURE_COMMAND)
3163   else()
3164     get_target_property(cmake_command ${name} _EP_CMAKE_COMMAND)
3165     if(cmake_command)
3166       set(cmd "${cmake_command}")
3167     else()
3168       set(cmd "${CMAKE_COMMAND}")
3169     endif()
3170
3171     get_property(cmake_args TARGET ${name} PROPERTY _EP_CMAKE_ARGS)
3172     list(APPEND cmd ${cmake_args})
3173
3174     # If there are any CMAKE_CACHE_ARGS or CMAKE_CACHE_DEFAULT_ARGS,
3175     # write an initial cache and use it
3176     get_property(cmake_cache_args TARGET ${name} PROPERTY _EP_CMAKE_CACHE_ARGS)
3177     get_property(cmake_cache_default_args TARGET ${name} PROPERTY _EP_CMAKE_CACHE_DEFAULT_ARGS)
3178
3179     set(has_cmake_cache_args 0)
3180     if(NOT "${cmake_cache_args}" STREQUAL "")
3181       set(has_cmake_cache_args 1)
3182     endif()
3183
3184     set(has_cmake_cache_default_args 0)
3185     if(NOT "${cmake_cache_default_args}" STREQUAL "")
3186       set(has_cmake_cache_default_args 1)
3187     endif()
3188
3189     get_target_property(cmake_generator ${name} _EP_CMAKE_GENERATOR)
3190     get_target_property(cmake_generator_instance ${name} _EP_CMAKE_GENERATOR_INSTANCE)
3191     get_target_property(cmake_generator_platform ${name} _EP_CMAKE_GENERATOR_PLATFORM)
3192     get_target_property(cmake_generator_toolset ${name} _EP_CMAKE_GENERATOR_TOOLSET)
3193     if(cmake_generator)
3194       list(APPEND cmd "-G${cmake_generator}")
3195       if(cmake_generator_platform)
3196         list(APPEND cmd "-A${cmake_generator_platform}")
3197       endif()
3198       if(cmake_generator_toolset)
3199         list(APPEND cmd "-T${cmake_generator_toolset}")
3200       endif()
3201       if(cmake_generator_instance)
3202         list(APPEND cmd "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${cmake_generator_instance}")
3203       endif()
3204     else()
3205       if(CMAKE_EXTRA_GENERATOR)
3206         list(APPEND cmd "-G${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}")
3207       else()
3208         list(APPEND cmd "-G${CMAKE_GENERATOR}")
3209         if("${CMAKE_GENERATOR}" MATCHES "Green Hills MULTI")
3210           set(has_cmake_cache_default_args 1)
3211           set(cmake_cache_default_args ${cmake_cache_default_args}
3212             "-DGHS_TARGET_PLATFORM:STRING=${GHS_TARGET_PLATFORM}"
3213             "-DGHS_PRIMARY_TARGET:STRING=${GHS_PRIMARY_TARGET}"
3214             "-DGHS_TOOLSET_ROOT:STRING=${GHS_TOOLSET_ROOT}"
3215             "-DGHS_OS_ROOT:STRING=${GHS_OS_ROOT}"
3216             "-DGHS_OS_DIR:STRING=${GHS_OS_DIR}"
3217             "-DGHS_BSP_NAME:STRING=${GHS_BSP_NAME}")
3218         endif()
3219       endif()
3220       if(cmake_generator_platform)
3221         message(FATAL_ERROR "Option CMAKE_GENERATOR_PLATFORM not allowed without CMAKE_GENERATOR.")
3222       endif()
3223       if(CMAKE_GENERATOR_PLATFORM)
3224         list(APPEND cmd "-A${CMAKE_GENERATOR_PLATFORM}")
3225       endif()
3226       if(cmake_generator_toolset)
3227         message(FATAL_ERROR "Option CMAKE_GENERATOR_TOOLSET not allowed without CMAKE_GENERATOR.")
3228       endif()
3229       if(CMAKE_GENERATOR_TOOLSET)
3230         list(APPEND cmd "-T${CMAKE_GENERATOR_TOOLSET}")
3231       endif()
3232       if(cmake_generator_instance)
3233         message(FATAL_ERROR "Option CMAKE_GENERATOR_INSTANCE not allowed without CMAKE_GENERATOR.")
3234       endif()
3235       if(CMAKE_GENERATOR_INSTANCE)
3236         list(APPEND cmd "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${CMAKE_GENERATOR_INSTANCE}")
3237       endif()
3238     endif()
3239
3240     if(has_cmake_cache_args OR has_cmake_cache_default_args)
3241       set(_ep_cache_args_script "<TMP_DIR>/${name}-cache-$<CONFIG>.cmake")
3242       if(has_cmake_cache_args)
3243         _ep_command_line_to_initial_cache(script_initial_cache_force "${cmake_cache_args}" 1)
3244       endif()
3245       if(has_cmake_cache_default_args)
3246         _ep_command_line_to_initial_cache(script_initial_cache_default "${cmake_cache_default_args}" 0)
3247       endif()
3248       _ep_write_initial_cache(${name} "${_ep_cache_args_script}" "${script_initial_cache_force}${script_initial_cache_default}")
3249       list(APPEND cmd "-C${_ep_cache_args_script}")
3250       _ep_replace_location_tags(${name} _ep_cache_args_script)
3251       set(_ep_cache_args_script
3252         "${_ep_cache_args_script}"
3253         PARENT_SCOPE)
3254     endif()
3255
3256     list(APPEND cmd "<SOURCE_DIR><SOURCE_SUBDIR>")
3257   endif()
3258
3259   set("${var}" "${cmd}" PARENT_SCOPE)
3260 endfunction()
3261
3262 # TODO: Make sure external projects use the proper compiler
3263 function(_ep_add_configure_command name)
3264   ExternalProject_Get_Property(${name} binary_dir tmp_dir)
3265
3266   set(file_deps)
3267   get_property(configure_handled_by_build TARGET ${name}
3268                PROPERTY _EP_CONFIGURE_HANDLED_BY_BUILD)
3269   if(NOT configure_handled_by_build)
3270     # Depend on other external projects (file-level)
3271     _ep_get_file_deps(file_deps ${name})
3272   endif()
3273
3274   _ep_extract_configure_command(cmd ${name})
3275
3276   # If anything about the configure command changes, (command itself, cmake
3277   # used, cmake args or cmake generator) then re-run the configure step.
3278   # Fixes issue https://gitlab.kitware.com/cmake/cmake/-/issues/10258
3279   #
3280   if(NOT EXISTS ${tmp_dir}/${name}-cfgcmd.txt.in)
3281     file(WRITE ${tmp_dir}/${name}-cfgcmd.txt.in "cmd='\@cmd\@'\n")
3282   endif()
3283   configure_file(${tmp_dir}/${name}-cfgcmd.txt.in ${tmp_dir}/${name}-cfgcmd.txt)
3284   list(APPEND file_deps ${tmp_dir}/${name}-cfgcmd.txt)
3285   list(APPEND file_deps ${_ep_cache_args_script})
3286
3287   get_property(log TARGET ${name} PROPERTY _EP_LOG_CONFIGURE)
3288   if(log)
3289     set(log LOG 1)
3290   else()
3291     set(log "")
3292   endif()
3293
3294   get_property(uses_terminal TARGET ${name} PROPERTY
3295     _EP_USES_TERMINAL_CONFIGURE)
3296   if(uses_terminal)
3297     set(uses_terminal USES_TERMINAL 1)
3298   else()
3299     set(uses_terminal "")
3300   endif()
3301
3302   set(__cmdQuoted)
3303   foreach(__item IN LISTS cmd)
3304     string(APPEND __cmdQuoted " [==[${__item}]==]")
3305   endforeach()
3306   cmake_language(EVAL CODE "
3307     ExternalProject_Add_Step(${name} configure
3308       INDEPENDENT FALSE
3309       COMMAND ${__cmdQuoted}
3310       WORKING_DIRECTORY \${binary_dir}
3311       DEPENDEES patch
3312       DEPENDS \${file_deps}
3313       ${log}
3314       ${uses_terminal}
3315       )"
3316   )
3317 endfunction()
3318
3319
3320 function(_ep_add_build_command name)
3321   ExternalProject_Get_Property(${name} binary_dir)
3322
3323   set(file_deps)
3324   get_property(configure_handled_by_build TARGET ${name}
3325                PROPERTY _EP_CONFIGURE_HANDLED_BY_BUILD)
3326   if(configure_handled_by_build)
3327     # Depend on other external projects (file-level)
3328     _ep_get_file_deps(file_deps ${name})
3329   endif()
3330
3331   get_property(cmd_set TARGET ${name} PROPERTY _EP_BUILD_COMMAND SET)
3332   if(cmd_set)
3333     get_property(cmd TARGET ${name} PROPERTY _EP_BUILD_COMMAND)
3334   else()
3335     _ep_get_build_command(${name} BUILD cmd)
3336   endif()
3337
3338   get_property(log TARGET ${name} PROPERTY _EP_LOG_BUILD)
3339   if(log)
3340     set(log LOG 1)
3341   else()
3342     set(log "")
3343   endif()
3344
3345   get_property(uses_terminal TARGET ${name} PROPERTY
3346     _EP_USES_TERMINAL_BUILD)
3347   if(uses_terminal)
3348     set(uses_terminal USES_TERMINAL 1)
3349   else()
3350     set(uses_terminal "")
3351   endif()
3352
3353   get_property(build_always TARGET ${name} PROPERTY _EP_BUILD_ALWAYS)
3354   if(build_always)
3355     set(always 1)
3356   else()
3357     set(always 0)
3358   endif()
3359
3360   get_property(build_byproducts TARGET ${name} PROPERTY _EP_BUILD_BYPRODUCTS)
3361
3362   set(__cmdQuoted)
3363   foreach(__item IN LISTS cmd)
3364     string(APPEND __cmdQuoted " [==[${__item}]==]")
3365   endforeach()
3366   cmake_language(EVAL CODE "
3367     ExternalProject_Add_Step(${name} build
3368       INDEPENDENT FALSE
3369       COMMAND ${__cmdQuoted}
3370       BYPRODUCTS \${build_byproducts}
3371       WORKING_DIRECTORY \${binary_dir}
3372       DEPENDEES configure
3373       DEPENDS \${file_deps}
3374       ALWAYS \${always}
3375       ${log}
3376       ${uses_terminal}
3377       )"
3378   )
3379 endfunction()
3380
3381
3382 function(_ep_add_install_command name)
3383   ExternalProject_Get_Property(${name} binary_dir)
3384
3385   get_property(cmd_set TARGET ${name} PROPERTY _EP_INSTALL_COMMAND SET)
3386   if(cmd_set)
3387     get_property(cmd TARGET ${name} PROPERTY _EP_INSTALL_COMMAND)
3388   else()
3389     _ep_get_build_command(${name} INSTALL cmd)
3390   endif()
3391
3392   get_property(log TARGET ${name} PROPERTY _EP_LOG_INSTALL)
3393   if(log)
3394     set(log LOG 1)
3395   else()
3396     set(log "")
3397   endif()
3398
3399   get_property(uses_terminal TARGET ${name} PROPERTY
3400     _EP_USES_TERMINAL_INSTALL)
3401   if(uses_terminal)
3402     set(uses_terminal USES_TERMINAL 1)
3403   else()
3404     set(uses_terminal "")
3405   endif()
3406
3407   set(__cmdQuoted)
3408   foreach(__item IN LISTS cmd)
3409     string(APPEND __cmdQuoted " [==[${__item}]==]")
3410   endforeach()
3411   cmake_language(EVAL CODE "
3412     ExternalProject_Add_Step(${name} install
3413       INDEPENDENT FALSE
3414       COMMAND ${__cmdQuoted}
3415       WORKING_DIRECTORY \${binary_dir}
3416       DEPENDEES build
3417       ${log}
3418       ${uses_terminal}
3419       )"
3420   )
3421 endfunction()
3422
3423
3424 function(_ep_add_test_command name)
3425   ExternalProject_Get_Property(${name} binary_dir)
3426
3427   get_property(before TARGET ${name} PROPERTY _EP_TEST_BEFORE_INSTALL)
3428   get_property(after TARGET ${name} PROPERTY _EP_TEST_AFTER_INSTALL)
3429   get_property(exclude TARGET ${name} PROPERTY _EP_TEST_EXCLUDE_FROM_MAIN)
3430   get_property(cmd_set TARGET ${name} PROPERTY _EP_TEST_COMMAND SET)
3431
3432   # Only actually add the test step if one of the test related properties is
3433   # explicitly set. (i.e. the test step is omitted unless requested...)
3434   #
3435   if(cmd_set OR before OR after OR exclude)
3436     if(cmd_set)
3437       get_property(cmd TARGET ${name} PROPERTY _EP_TEST_COMMAND)
3438     else()
3439       _ep_get_build_command(${name} TEST cmd)
3440     endif()
3441
3442     if(before)
3443       set(dependees_args DEPENDEES build)
3444     else()
3445       set(dependees_args DEPENDEES install)
3446     endif()
3447
3448     if(exclude)
3449       set(dependers_args "")
3450       set(exclude_args EXCLUDE_FROM_MAIN 1)
3451     else()
3452       if(before)
3453         set(dependers_args DEPENDERS install)
3454       else()
3455         set(dependers_args "")
3456       endif()
3457       set(exclude_args "")
3458     endif()
3459
3460     get_property(log TARGET ${name} PROPERTY _EP_LOG_TEST)
3461     if(log)
3462       set(log LOG 1)
3463     else()
3464       set(log "")
3465     endif()
3466
3467     get_property(uses_terminal TARGET ${name} PROPERTY
3468       _EP_USES_TERMINAL_TEST)
3469     if(uses_terminal)
3470       set(uses_terminal USES_TERMINAL 1)
3471     else()
3472       set(uses_terminal "")
3473     endif()
3474
3475     set(__cmdQuoted)
3476     foreach(__item IN LISTS cmd)
3477       string(APPEND __cmdQuoted " [==[${__item}]==]")
3478     endforeach()
3479     cmake_language(EVAL CODE "
3480       ExternalProject_Add_Step(${name} test
3481         INDEPENDENT FALSE
3482         COMMAND ${__cmdQuoted}
3483         WORKING_DIRECTORY \${binary_dir}
3484         ${dependees_args}
3485         ${dependers_args}
3486         ${exclude_args}
3487         ${log}
3488         ${uses_terminal}
3489         )"
3490     )
3491   endif()
3492 endfunction()
3493
3494
3495 function(ExternalProject_Add name)
3496   cmake_policy(GET CMP0097 _EP_CMP0097
3497     PARENT_SCOPE # undocumented, do not use outside of CMake
3498     )
3499   cmake_policy(GET CMP0114 cmp0114
3500     PARENT_SCOPE # undocumented, do not use outside of CMake
3501     )
3502   if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12 AND NOT cmp0114 STREQUAL "NEW")
3503     message(AUTHOR_WARNING
3504       "Policy CMP0114 is not set to NEW.  "
3505       "In order to support the Xcode \"new build system\", "
3506       "this project must be updated to set policy CMP0114 to NEW."
3507       "\n"
3508       "Since CMake is generating for the Xcode \"new build system\", "
3509       "ExternalProject_Add will use policy CMP0114's NEW behavior anyway, "
3510       "but the generated build system may not match what the project intends."
3511       )
3512     set(cmp0114 "NEW")
3513   endif()
3514
3515   _ep_get_configuration_subdir_suffix(cfgdir)
3516
3517   # Add a custom target for the external project.
3518   set(cmf_dir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles)
3519   _ep_get_complete_stampfile(${name} complete_stamp_file)
3520
3521   cmake_policy(PUSH)
3522   if(cmp0114 STREQUAL "NEW")
3523     # To implement CMP0114 NEW behavior with Makefile generators,
3524     # we need CMP0113 NEW behavior.
3525     cmake_policy(SET CMP0113 NEW)
3526   endif()
3527   # The "ALL" option to add_custom_target just tells it to not set the
3528   # EXCLUDE_FROM_ALL target property. Later, if the EXCLUDE_FROM_ALL
3529   # argument was passed, we explicitly set it for the target.
3530   add_custom_target(${name} ALL DEPENDS ${complete_stamp_file})
3531   cmake_policy(POP)
3532   set_property(TARGET ${name} PROPERTY _EP_IS_EXTERNAL_PROJECT 1)
3533   set_property(TARGET ${name} PROPERTY LABELS ${name})
3534   set_property(TARGET ${name} PROPERTY FOLDER "ExternalProjectTargets/${name}")
3535
3536   set_property(TARGET ${name} PROPERTY _EP_CMP0114 "${cmp0114}")
3537
3538   set(keywords
3539     #
3540     # Directory options
3541     #
3542     PREFIX
3543     TMP_DIR
3544     STAMP_DIR
3545     LOG_DIR
3546     DOWNLOAD_DIR
3547     SOURCE_DIR
3548     BINARY_DIR
3549     INSTALL_DIR
3550     #
3551     # Download step options
3552     #
3553     DOWNLOAD_COMMAND
3554     #
3555     URL
3556     URL_HASH
3557     URL_MD5
3558     DOWNLOAD_NAME
3559     DOWNLOAD_NO_EXTRACT
3560     DOWNLOAD_NO_PROGRESS
3561     TIMEOUT
3562     INACTIVITY_TIMEOUT
3563     HTTP_USERNAME
3564     HTTP_PASSWORD
3565     HTTP_HEADER
3566     TLS_VERIFY     # Also used for git clone operations
3567     TLS_CAINFO
3568     NETRC
3569     NETRC_FILE
3570     #
3571     GIT_REPOSITORY
3572     GIT_TAG
3573     GIT_REMOTE_NAME
3574     GIT_SUBMODULES
3575     GIT_SUBMODULES_RECURSE
3576     GIT_SHALLOW
3577     GIT_PROGRESS
3578     GIT_CONFIG
3579     GIT_REMOTE_UPDATE_STRATEGY
3580     #
3581     SVN_REPOSITORY
3582     SVN_REVISION
3583     SVN_USERNAME
3584     SVN_PASSWORD
3585     SVN_TRUST_CERT
3586     #
3587     HG_REPOSITORY
3588     HG_TAG
3589     #
3590     CVS_REPOSITORY
3591     CVS_MODULE
3592     CVS_TAG
3593     #
3594     # Update step options
3595     #
3596     UPDATE_COMMAND
3597     UPDATE_DISCONNECTED
3598     #
3599     # Patch step options
3600     #
3601     PATCH_COMMAND
3602     #
3603     # Configure step options
3604     #
3605     CONFIGURE_COMMAND
3606     CMAKE_COMMAND
3607     CMAKE_GENERATOR
3608     CMAKE_GENERATOR_PLATFORM
3609     CMAKE_GENERATOR_TOOLSET
3610     CMAKE_GENERATOR_INSTANCE
3611     CMAKE_ARGS
3612     CMAKE_CACHE_ARGS
3613     CMAKE_CACHE_DEFAULT_ARGS
3614     SOURCE_SUBDIR
3615     CONFIGURE_HANDLED_BY_BUILD
3616     #
3617     # Build step options
3618     #
3619     BUILD_COMMAND
3620     BUILD_IN_SOURCE
3621     BUILD_ALWAYS
3622     BUILD_BYPRODUCTS
3623     #
3624     # Install step options
3625     #
3626     INSTALL_COMMAND
3627     #
3628     # Test step options
3629     #
3630     TEST_COMMAND
3631     TEST_BEFORE_INSTALL
3632     TEST_AFTER_INSTALL
3633     TEST_EXCLUDE_FROM_MAIN
3634     #
3635     # Logging options
3636     #
3637     LOG_DOWNLOAD
3638     LOG_UPDATE
3639     LOG_PATCH
3640     LOG_CONFIGURE
3641     LOG_BUILD
3642     LOG_INSTALL
3643     LOG_TEST
3644     LOG_MERGED_STDOUTERR
3645     LOG_OUTPUT_ON_FAILURE
3646     #
3647     # Terminal access options
3648     #
3649     USES_TERMINAL_DOWNLOAD
3650     USES_TERMINAL_UPDATE
3651     USES_TERMINAL_CONFIGURE
3652     USES_TERMINAL_BUILD
3653     USES_TERMINAL_INSTALL
3654     USES_TERMINAL_TEST
3655     #
3656     # Target options
3657     #
3658     DEPENDS
3659     EXCLUDE_FROM_ALL
3660     STEP_TARGETS
3661     INDEPENDENT_STEP_TARGETS
3662     #
3663     # Miscellaneous options
3664     #
3665     LIST_SEPARATOR
3666   )
3667   _ep_parse_arguments(ExternalProject_Add "${keywords}" ${name} _EP_ "${ARGN}")
3668   _ep_set_directories(${name})
3669   _ep_get_step_stampfile(${name} "done" done_stamp_file)
3670   _ep_get_step_stampfile(${name} "install" install_stamp_file)
3671
3672   # Set the EXCLUDE_FROM_ALL target property if required.
3673   get_property(exclude_from_all TARGET ${name} PROPERTY _EP_EXCLUDE_FROM_ALL)
3674   if(exclude_from_all)
3675     set_property(TARGET ${name} PROPERTY EXCLUDE_FROM_ALL TRUE)
3676   endif()
3677
3678   # The 'complete' step depends on all other steps and creates a
3679   # 'done' mark.  A dependent external project's 'configure' step
3680   # depends on the 'done' mark so that it rebuilds when this project
3681   # rebuilds.  It is important that 'done' is not the output of any
3682   # custom command so that CMake does not propagate build rules to
3683   # other external project targets, which may cause problems during
3684   # parallel builds.  However, the Ninja generator needs to see the entire
3685   # dependency graph, and can cope with custom commands belonging to
3686   # multiple targets, so we add the 'done' mark as an output for Ninja only.
3687   set(complete_outputs ${complete_stamp_file})
3688   if(${CMAKE_GENERATOR} MATCHES "Ninja")
3689     set(complete_outputs ${complete_outputs} ${done_stamp_file})
3690   endif()
3691
3692   add_custom_command(
3693     OUTPUT ${complete_outputs}
3694     COMMENT "Completed '${name}'"
3695     COMMAND ${CMAKE_COMMAND} -E make_directory ${cmf_dir}${cfgdir}
3696     COMMAND ${CMAKE_COMMAND} -E touch ${complete_stamp_file}
3697     COMMAND ${CMAKE_COMMAND} -E touch ${done_stamp_file}
3698     DEPENDS ${install_stamp_file}
3699     VERBATIM
3700     )
3701
3702
3703   # Depend on other external projects (target-level).
3704   get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
3705   foreach(arg IN LISTS deps)
3706     add_dependencies(${name} ${arg})
3707   endforeach()
3708
3709   # Set up custom build steps based on the target properties.
3710   # Each step depends on the previous one.
3711   #
3712   # The target depends on the output of the final step.
3713   # (Already set up above in the DEPENDS of the add_custom_target command.)
3714   #
3715   _ep_add_mkdir_command(${name})
3716   _ep_add_download_command(${name})
3717   _ep_add_update_command(${name})
3718   _ep_add_patch_command(${name})
3719   _ep_add_configure_command(${name})
3720   _ep_add_build_command(${name})
3721   _ep_add_install_command(${name})
3722
3723   # Test is special in that it might depend on build, or it might depend
3724   # on install.
3725   #
3726   _ep_add_test_command(${name})
3727 endfunction()
3728
3729 cmake_policy(POP)