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