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