1 # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 # file Copyright.txt or https://cmake.org/licensing for details.
4 #[=======================================================================[.rst:
15 External Project Definition
16 """""""""""""""""""""""""""
18 .. command:: ExternalProject_Add
20 The ``ExternalProject_Add()`` function creates a custom target to drive
21 download, update/patch, configure, build, install and test steps of an
26 ExternalProject_Add(<name> [<option>...])
28 The individual steps within the process can be driven independently if
29 required (e.g. for CDash submission) and extra custom steps can be defined,
30 along with the ability to control the step dependencies. The directory
31 structure used for the management of the external project can also be
32 customized. The function supports a large number of options which can be used
33 to tailor the external project behavior.
35 **Directory Options:**
36 Most of the time, the default directory layout is sufficient. It is largely
37 an implementation detail that the main project usually doesn't need to
38 change. In some circumstances, however, control over the directory layout
39 can be useful or necessary. The directory options are potentially more
40 useful from the point of view that the main build can use the
41 :command:`ExternalProject_Get_Property` command to retrieve their values,
42 thereby allowing the main project to refer to build artifacts of the
46 Root directory for the external project. Unless otherwise noted below,
47 all other directories associated with the external project will be
51 Directory in which to store temporary files.
54 Directory in which to store the timestamps of each step. Log files from
55 individual steps are also created in here unless overridden by LOG_DIR
56 (see *Logging Options* below).
59 Directory in which to store the logs of each step.
61 ``DOWNLOAD_DIR <dir>``
62 Directory in which to store downloaded files before unpacking them. This
63 directory is only used by the URL download method, all other download
64 methods use ``SOURCE_DIR`` directly instead.
67 Source directory into which downloaded contents will be unpacked, or for
68 non-URL download methods, the directory in which the repository should be
69 checked out, cloned, etc. If no download method is specified, this must
70 point to an existing directory where the external project has already
71 been unpacked or cloned/checked out.
74 If a download method is specified, any existing contents of the source
75 directory may be deleted. Only the URL download method checks whether
76 this directory is either missing or empty before initiating the
77 download, stopping with an error if it is not empty. All other
78 download methods silently discard any previous contents of the source
82 Specify the build directory location. This option is ignored if
83 ``BUILD_IN_SOURCE`` is enabled.
86 Installation prefix to be placed in the ``<INSTALL_DIR>`` placeholder.
87 This does not actually configure the external project to install to
88 the given prefix. That must be done by passing appropriate arguments
89 to the external project configuration step, e.g. using ``<INSTALL_DIR>``.
91 If any of the above ``..._DIR`` options are not specified, their defaults
92 are computed as follows. If the ``PREFIX`` option is given or the
93 ``EP_PREFIX`` directory property is set, then an external project is built
94 and installed under the specified prefix::
96 TMP_DIR = <prefix>/tmp
97 STAMP_DIR = <prefix>/src/<name>-stamp
98 DOWNLOAD_DIR = <prefix>/src
99 SOURCE_DIR = <prefix>/src/<name>
100 BINARY_DIR = <prefix>/src/<name>-build
101 INSTALL_DIR = <prefix>
102 LOG_DIR = <STAMP_DIR>
104 Otherwise, if the ``EP_BASE`` directory property is set then components
105 of an external project are stored under the specified base::
107 TMP_DIR = <base>/tmp/<name>
108 STAMP_DIR = <base>/Stamp/<name>
109 DOWNLOAD_DIR = <base>/Download/<name>
110 SOURCE_DIR = <base>/Source/<name>
111 BINARY_DIR = <base>/Build/<name>
112 INSTALL_DIR = <base>/Install/<name>
113 LOG_DIR = <STAMP_DIR>
115 If no ``PREFIX``, ``EP_PREFIX``, or ``EP_BASE`` is specified, then the
116 default is to set ``PREFIX`` to ``<name>-prefix``. Relative paths are
117 interpreted with respect to :variable:`CMAKE_CURRENT_BINARY_DIR` at the
118 point where ``ExternalProject_Add()`` is called.
120 **Download Step Options:**
121 A download method can be omitted if the ``SOURCE_DIR`` option is used to
122 point to an existing non-empty directory. Otherwise, one of the download
123 methods below must be specified (multiple download methods should not be
124 given) or a custom ``DOWNLOAD_COMMAND`` provided.
126 ``DOWNLOAD_COMMAND <cmd>...``
127 Overrides the command used for the download step
128 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
129 supported). If this option is specified, all other download options will
130 be ignored. Providing an empty string for ``<cmd>`` effectively disables
134 ``URL <url1> [<url2>...]``
135 List of paths and/or URL(s) of the external project's source. When more
136 than one URL is given, they are tried in turn until one succeeds. A URL
137 may be an ordinary path in the local file system (in which case it
138 must be the only URL provided) or any downloadable URL supported by the
139 :command:`file(DOWNLOAD)` command. A local filesystem path may refer to
140 either an existing directory or to an archive file, whereas a URL is
141 expected to point to a file which can be treated as an archive. When an
142 archive is used, it will be unpacked automatically unless the
143 ``DOWNLOAD_NO_EXTRACT`` option is set to prevent it. The archive type
144 is determined by inspecting the actual content rather than using logic
145 based on the file extension.
147 ``URL_HASH <algo>=<hashValue>``
148 Hash of the archive file to be downloaded. The argument should be of
149 the form ``<algo>=<hashValue>`` where ``algo`` can be any of the hashing
150 algorithms supported by the :command:`file()` command. Specifying this
151 option is strongly recommended for URL downloads, as it ensures the
152 integrity of the downloaded content. It is also used as a check for a
153 previously downloaded file, allowing connection to the remote location
154 to be avoided altogether if the local directory already has a file from
155 an earlier download that matches the specified hash.
158 Equivalent to ``URL_HASH MD5=<md5>``.
160 ``DOWNLOAD_NAME <fname>``
161 File name to use for the downloaded file. If not given, the end of the
162 URL is used to determine the file name. This option is rarely needed,
163 the default name is generally suitable and is not normally used outside
164 of code internal to the ``ExternalProject`` module.
166 ``DOWNLOAD_NO_EXTRACT <bool>``
167 Allows the extraction part of the download step to be disabled by
168 passing a boolean true value for this option. If this option is not
169 given, the downloaded contents will be unpacked automatically if
170 required. If extraction has been disabled, the full path to the
171 downloaded file is available as ``<DOWNLOADED_FILE>`` in subsequent
172 steps or as the property ``DOWNLOADED_FILE`` with the
173 :command:`ExternalProject_Get_Property` command.
175 ``DOWNLOAD_NO_PROGRESS <bool>``
176 Can be used to disable logging the download progress. If this option is
177 not given, download progress messages will be logged.
179 ``TIMEOUT <seconds>``
180 Maximum time allowed for file download operations.
182 ``HTTP_USERNAME <username>``
183 Username for the download operation if authentication is required.
185 ``HTTP_PASSWORD <password>``
186 Password for the download operation if authentication is required.
188 ``HTTP_HEADER <header1> [<header2>...]``
189 Provides an arbitrary list of HTTP headers for the download operation.
190 This can be useful for accessing content in systems like AWS, etc.
192 ``TLS_VERIFY <bool>``
193 Specifies whether certificate verification should be performed for
194 https URLs. If this option is not provided, the default behavior is
195 determined by the ``CMAKE_TLS_VERIFY`` variable (see
196 :command:`file(DOWNLOAD)`). If that is also not set, certificate
197 verification will not be performed. In situations where ``URL_HASH``
198 cannot be provided, this option can be an alternative verification
201 ``TLS_CAINFO <file>``
202 Specify a custom certificate authority file to use if ``TLS_VERIFY``
203 is enabled. If this option is not specified, the value of the
204 ``CMAKE_TLS_CAINFO`` variable will be used instead (see
205 :command:`file(DOWNLOAD)`)
208 Specify whether the ``.netrc`` file is to be used for operation.
209 If this option is not specified, the value of the ``CMAKE_NETRC``
210 variable will be used instead (see :command:`file(DOWNLOAD)`)
214 The ``.netrc`` file is ignored.
217 The ``.netrc`` file is optional, and information in the URL
218 is preferred. The file will be scanned to find which ever
219 information is not specified in the URL.
221 The ``.netrc`` file is required, and information in the URL
224 ``NETRC_FILE <file>``
225 Specify an alternative ``.netrc`` file to the one in your home directory
226 if the ``NETRC`` level is ``OPTIONAL`` or ``REQUIRED``. If this option
227 is not specified, the value of the ``CMAKE_NETRC_FILE`` variable will
228 be used instead (see :command:`file(DOWNLOAD)`)
231 NOTE: A git version of 1.6.5 or later is required if this download method
234 ``GIT_REPOSITORY <url>``
235 URL of the git repository. Any URL understood by the ``git`` command
239 Git branch name, tag or commit hash. Note that branch names and tags
240 should generally be specified as remote names (i.e. ``origin/myBranch``
241 rather than simply ``myBranch``). This ensures that if the remote end
242 has its tag moved or branch rebased or history rewritten, the local
243 clone will still be updated correctly. In general, however, specifying
244 a commit hash should be preferred for a number of reasons:
246 - If the local clone already has the commit corresponding to the hash,
247 no ``git fetch`` needs to be performed to check for changes each time
248 CMake is re-run. This can result in a significant speed up if many
249 external projects are being used.
250 - Using a specific git hash ensures that the main project's own history
251 is fully traceable to a specific point in the external project's
252 evolution. If a branch or tag name is used instead, then checking out
253 a specific commit of the main project doesn't necessarily pin the
254 whole build to a specific point in the life of the external project.
255 The lack of such deterministic behavior makes the main project lose
256 traceability and repeatability.
258 If ``GIT_SHALLOW`` is enabled then ``GIT_TAG`` works only with
259 branch names and tags. A commit hash is not allowed.
261 ``GIT_REMOTE_NAME <name>``
262 The optional name of the remote. If this option is not specified, it
263 defaults to ``origin``.
265 ``GIT_SUBMODULES <module>...``
266 Specific git submodules that should also be updated. If this option is
267 not provided, all git submodules will be updated. When :policy:`CMP0097`
268 is set to ``NEW`` if this value is set to an empty string then no submodules
269 are initialized or updated.
271 ``GIT_SUBMODULES_RECURSE <bool>``
272 Specify whether git submodules (if any) should update recursively by
273 passing the ``--recursive`` flag to ``git submodule update``.
274 If not specified, the default is on.
276 ``GIT_SHALLOW <bool>``
277 When this option is enabled, the ``git clone`` operation will be given
278 the ``--depth 1`` option. This performs a shallow clone, which avoids
279 downloading the whole history and instead retrieves just the commit
280 denoted by the ``GIT_TAG`` option.
282 ``GIT_PROGRESS <bool>``
283 When enabled, this option instructs the ``git clone`` operation to
284 report its progress by passing it the ``--progress`` option. Without
285 this option, the clone step for large projects may appear to make the
286 build stall, since nothing will be logged until the clone operation
287 finishes. While this option can be used to provide progress to prevent
288 the appearance of the build having stalled, it may also make the build
289 overly noisy if lots of external projects are used.
291 ``GIT_CONFIG <option1> [<option2>...]``
292 Specify a list of config options to pass to ``git clone``. Each option
293 listed will be transformed into its own ``--config <option>`` on the
294 ``git clone`` command line, with each option required to be in the
297 ``GIT_REMOTE_UPDATE_STRATEGY <strategy>``
298 When ``GIT_TAG`` refers to a remote branch, this option can be used to
299 specify how the update step behaves. The ``<strategy>`` must be one of
303 Ignore the local branch and always checkout the branch specified by
307 Try to rebase the current branch to the one specified by ``GIT_TAG``.
308 If there are local uncommitted changes, they will be stashed first
309 and popped again after rebasing. If rebasing or popping stashed
310 changes fail, abort the rebase and halt with an error.
311 When ``GIT_REMOTE_UPDATE_STRATEGY`` is not present, this is the
312 default strategy unless the default has been overridden with
313 ``CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY`` (see below).
316 Same as ``REBASE`` except if the rebase fails, an annotated tag will
317 be created at the original ``HEAD`` position from before the rebase
318 and then checkout ``GIT_TAG`` just like the ``CHECKOUT`` strategy.
319 The message stored on the annotated tag will give information about
320 what was attempted and the tag name will include a timestamp so that
321 each failed run will add a new tag. This strategy ensures no changes
322 will be lost, but updates should always succeed if ``GIT_TAG`` refers
323 to a valid ref unless there are uncommitted changes that cannot be
326 The variable ``CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY`` can be set to
327 override the default strategy. This variable should not be set by a
328 project, it is intended for the user to set. It is primarily intended
329 for use in continuous integration scripts to ensure that when history
330 is rewritten on a remote branch, the build doesn't end up with unintended
331 changes or failed builds resulting from conflicts during rebase operations.
334 ``SVN_REPOSITORY <url>``
335 URL of the Subversion repository.
337 ``SVN_REVISION -r<rev>``
338 Revision to checkout from the Subversion repository.
340 ``SVN_USERNAME <username>``
341 Username for the Subversion checkout and update.
343 ``SVN_PASSWORD <password>``
344 Password for the Subversion checkout and update.
346 ``SVN_TRUST_CERT <bool>``
347 Specifies whether to trust the Subversion server site certificate. If
348 enabled, the ``--trust-server-cert`` option is passed to the ``svn``
349 checkout and update commands.
352 ``HG_REPOSITORY <url>``
353 URL of the mercurial repository.
356 Mercurial branch name, tag or commit id.
359 ``CVS_REPOSITORY <cvsroot>``
360 CVSROOT of the CVS repository.
363 Module to checkout from the CVS repository.
366 Tag to checkout from the CVS repository.
368 **Update/Patch Step Options:**
369 Whenever CMake is re-run, by default the external project's sources will be
370 updated if the download method supports updates (e.g. a git repository
371 would be checked if the ``GIT_TAG`` does not refer to a specific commit).
373 ``UPDATE_COMMAND <cmd>...``
374 Overrides the download method's update step with a custom command.
376 :manual:`generator expressions <cmake-generator-expressions(7)>`.
378 ``UPDATE_DISCONNECTED <bool>``
379 When enabled, this option causes the update step to be skipped. It does
380 not, however, prevent the download step. The update step can still be
381 added as a step target (see :command:`ExternalProject_Add_StepTargets`)
382 and called manually. This is useful if you want to allow developers to
383 build the project when disconnected from the network (the network may
384 still be needed for the download step though).
386 When this option is present, it is generally advisable to make the value
387 a cache variable under the developer's control rather than hard-coding
388 it. If this option is not present, the default value is taken from the
389 ``EP_UPDATE_DISCONNECTED`` directory property. If that is also not
390 defined, updates are performed as normal. The ``EP_UPDATE_DISCONNECTED``
391 directory property is intended as a convenience for controlling the
392 ``UPDATE_DISCONNECTED`` behavior for an entire section of a project's
393 directory hierarchy and may be a more convenient method of giving
394 developers control over whether or not to perform updates (assuming the
395 project also provides a cache variable or some other convenient method
396 for setting the directory property).
398 ``PATCH_COMMAND <cmd>...``
399 Specifies a custom command to patch the sources after an update. By
400 default, no patch command is defined. Note that it can be quite difficult
401 to define an appropriate patch command that performs robustly, especially
402 for download methods such as git where changing the ``GIT_TAG`` will not
403 discard changes from a previous patch, but the patch command will be
404 called again after updating to the new tag.
406 **Configure Step Options:**
407 The configure step is run after the download and update steps. By default,
408 the external project is assumed to be a CMake project, but this can be
409 overridden if required.
411 ``CONFIGURE_COMMAND <cmd>...``
412 The default configure command runs CMake with options based on the main
413 project. For non-CMake external projects, the ``CONFIGURE_COMMAND``
414 option must be used to override this behavior
415 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
416 supported). For projects that require no configure step, specify this
417 option with an empty string as the command to execute.
419 ``CMAKE_COMMAND /.../cmake``
420 Specify an alternative cmake executable for the configure step (use an
421 absolute path). This is generally not recommended, since it is
422 usually desirable to use the same CMake version throughout the whole
423 build. This option is ignored if a custom configure command has been
424 specified with ``CONFIGURE_COMMAND``.
426 ``CMAKE_GENERATOR <gen>``
427 Override the CMake generator used for the configure step. Without this
428 option, the same generator as the main build will be used. This option is
429 ignored if a custom configure command has been specified with the
430 ``CONFIGURE_COMMAND`` option.
432 ``CMAKE_GENERATOR_PLATFORM <platform>``
433 Pass a generator-specific platform name to the CMake command (see
434 :variable:`CMAKE_GENERATOR_PLATFORM`). It is an error to provide this
435 option without the ``CMAKE_GENERATOR`` option.
437 ``CMAKE_GENERATOR_TOOLSET <toolset>``
438 Pass a generator-specific toolset name to the CMake command (see
439 :variable:`CMAKE_GENERATOR_TOOLSET`). It is an error to provide this
440 option without the ``CMAKE_GENERATOR`` option.
442 ``CMAKE_GENERATOR_INSTANCE <instance>``
443 Pass a generator-specific instance selection to the CMake command (see
444 :variable:`CMAKE_GENERATOR_INSTANCE`). It is an error to provide this
445 option without the ``CMAKE_GENERATOR`` option.
447 ``CMAKE_ARGS <arg>...``
448 The specified arguments are passed to the ``cmake`` command line. They
449 can be any argument the ``cmake`` command understands, not just cache
450 values defined by ``-D...`` arguments (see also
451 :manual:`CMake Options <cmake(1)>`). In addition, arguments may use
452 :manual:`generator expressions <cmake-generator-expressions(7)>`.
454 ``CMAKE_CACHE_ARGS <arg>...``
455 This is an alternate way of specifying cache variables where command line
456 length issues may become a problem. The arguments are expected to be in
457 the form ``-Dvar:STRING=value``, which are then transformed into
458 CMake :command:`set` commands with the ``FORCE`` option used. These
459 ``set()`` commands are written to a pre-load script which is then applied
460 using the :manual:`cmake -C <cmake(1)>` command line option. Arguments
461 may use :manual:`generator expressions <cmake-generator-expressions(7)>`.
463 ``CMAKE_CACHE_DEFAULT_ARGS <arg>...``
464 This is the same as the ``CMAKE_CACHE_ARGS`` option except the ``set()``
465 commands do not include the ``FORCE`` keyword. This means the values act
466 as initial defaults only and will not override any variables already set
467 from a previous run. Use this option with care, as it can lead to
468 different behavior depending on whether the build starts from a fresh
469 build directory or re-uses previous build contents.
471 If the CMake generator is the ``Green Hills MULTI`` and not overridden then
472 the original project's settings for the GHS toolset and target system
473 customization cache variables are propagated into the external project.
475 ``SOURCE_SUBDIR <dir>``
476 When no ``CONFIGURE_COMMAND`` option is specified, the configure step
477 assumes the external project has a ``CMakeLists.txt`` file at the top of
478 its source tree (i.e. in ``SOURCE_DIR``). The ``SOURCE_SUBDIR`` option
479 can be used to point to an alternative directory within the source tree
480 to use as the top of the CMake source tree instead. This must be a
481 relative path and it will be interpreted as being relative to
482 ``SOURCE_DIR``. When ``BUILD_IN_SOURCE 1`` is specified, the
483 ``BUILD_COMMAND`` is used to point to an alternative directory within the
486 **Build Step Options:**
487 If the configure step assumed the external project uses CMake as its build
488 system, the build step will also. Otherwise, the build step will assume a
489 Makefile-based build and simply run ``make`` with no arguments as the
490 default build step. This can be overridden with custom build commands if
493 ``BUILD_COMMAND <cmd>...``
494 Overrides the default build command
495 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
496 supported). If this option is not given, the default build command will
497 be chosen to integrate with the main build in the most appropriate way
498 (e.g. using recursive ``make`` for Makefile generators or
499 ``cmake --build`` if the project uses a CMake build). This option can be
500 specified with an empty string as the command to make the build step do
503 ``BUILD_IN_SOURCE <bool>``
504 When this option is enabled, the build will be done directly within the
505 external project's source tree. This should generally be avoided, the use
506 of a separate build directory is usually preferred, but it can be useful
507 when the external project assumes an in-source build. The ``BINARY_DIR``
508 option should not be specified if building in-source.
510 ``BUILD_ALWAYS <bool>``
511 Enabling this option forces the build step to always be run. This can be
512 the easiest way to robustly ensure that the external project's own build
513 dependencies are evaluated rather than relying on the default
514 success timestamp-based method. This option is not normally needed unless
515 developers are expected to modify something the external project's build
516 depends on in a way that is not detectable via the step target
517 dependencies (e.g. ``SOURCE_DIR`` is used without a download method and
518 developers might modify the sources in ``SOURCE_DIR``).
520 ``BUILD_BYPRODUCTS <file>...``
521 Specifies files that will be generated by the build command but which
522 might or might not have their modification time updated by subsequent
523 builds. These ultimately get passed through as ``BYPRODUCTS`` to the
524 build step's own underlying call to :command:`add_custom_command`.
526 **Install Step Options:**
527 If the configure step assumed the external project uses CMake as its build
528 system, the install step will also. Otherwise, the install step will assume
529 a Makefile-based build and simply run ``make install`` as the default build
530 step. This can be overridden with custom install commands if required.
532 ``INSTALL_COMMAND <cmd>...``
533 The external project's own install step is invoked as part of the main
534 project's *build*. It is done after the external project's build step
535 and may be before or after the external project's test step (see the
536 ``TEST_BEFORE_INSTALL`` option below). The external project's install
537 rules are not part of the main project's install rules, so if anything
538 from the external project should be installed as part of the main build,
539 these need to be specified in the main build as additional
540 :command:`install` commands. The default install step builds the
541 ``install`` target of the external project, but this can be overridden
542 with a custom command using this option
543 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
544 supported). Passing an empty string as the ``<cmd>`` makes the install
547 **Test Step Options:**
548 The test step is only defined if at least one of the following ``TEST_...``
549 options are provided.
551 ``TEST_COMMAND <cmd>...``
552 Overrides the default test command
553 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
554 supported). If this option is not given, the default behavior of the test
555 step is to build the external project's own ``test`` target. This option
556 can be specified with ``<cmd>`` as an empty string, which allows the test
557 step to still be defined, but it will do nothing. Do not specify any of
558 the other ``TEST_...`` options if providing an empty string as the test
559 command, but prefer to omit all ``TEST_...`` options altogether if the
560 test step target is not needed.
562 ``TEST_BEFORE_INSTALL <bool>``
563 When this option is enabled, the test step will be executed before the
564 install step. The default behavior is for the test step to run after the
567 ``TEST_AFTER_INSTALL <bool>``
568 This option is mainly useful as a way to indicate that the test step is
569 desired but all default behavior is sufficient. Specifying this option
570 with a boolean true value ensures the test step is defined and that it
571 comes after the install step. If both ``TEST_BEFORE_INSTALL`` and
572 ``TEST_AFTER_INSTALL`` are enabled, the latter is silently ignored.
574 ``TEST_EXCLUDE_FROM_MAIN <bool>``
575 If enabled, the main build's default ALL target will not depend on the
576 test step. This can be a useful way of ensuring the test step is defined
577 but only gets invoked when manually requested.
579 **Output Logging Options:**
580 Each of the following ``LOG_...`` options can be used to wrap the relevant
581 step in a script to capture its output to files. The log files will be
582 created in ``LOG_DIR`` if supplied or otherwise the ``STAMP_DIR``
583 directory with step-specific file names.
585 ``LOG_DOWNLOAD <bool>``
586 When enabled, the output of the download step is logged to files.
588 ``LOG_UPDATE <bool>``
589 When enabled, the output of the update step is logged to files.
592 When enabled, the output of the patch step is logged to files.
594 ``LOG_CONFIGURE <bool>``
595 When enabled, the output of the configure step is logged to files.
598 When enabled, the output of the build step is logged to files.
600 ``LOG_INSTALL <bool>``
601 When enabled, the output of the install step is logged to files.
604 When enabled, the output of the test step is logged to files.
606 ``LOG_MERGED_STDOUTERR <bool>``
607 When enabled, stdout and stderr will be merged for any step whose
608 output is being logged to files.
610 ``LOG_OUTPUT_ON_FAILURE <bool>``
611 This option only has an effect if at least one of the other ``LOG_<step>``
612 options is enabled. If an error occurs for a step which has logging to
613 file enabled, that step's output will be printed to the console if
614 ``LOG_OUTPUT_ON_FAILURE`` is set to true. For cases where a large amount
615 of output is recorded, just the end of that output may be printed to the
618 **Terminal Access Options:**
619 Steps can be given direct access to the terminal in some cases. Giving a
620 step access to the terminal may allow it to receive terminal input if
621 required, such as for authentication details not provided by other options.
622 With the :generator:`Ninja` generator, these options place the steps in the
623 ``console`` :prop_gbl:`job pool <JOB_POOLS>`. Each step can be given access
624 to the terminal individually via the following options:
626 ``USES_TERMINAL_DOWNLOAD <bool>``
627 Give the download step access to the terminal.
629 ``USES_TERMINAL_UPDATE <bool>``
630 Give the update step access to the terminal.
632 ``USES_TERMINAL_CONFIGURE <bool>``
633 Give the configure step access to the terminal.
635 ``USES_TERMINAL_BUILD <bool>``
636 Give the build step access to the terminal.
638 ``USES_TERMINAL_INSTALL <bool>``
639 Give the install step access to the terminal.
641 ``USES_TERMINAL_TEST <bool>``
642 Give the test step access to the terminal.
645 ``DEPENDS <targets>...``
646 Specify other targets on which the external project depends. The other
647 targets will be brought up to date before any of the external project's
648 steps are executed. Because the external project uses additional custom
649 targets internally for each step, the ``DEPENDS`` option is the most
650 convenient way to ensure all of those steps depend on the other targets.
652 :command:`add_dependencies(\<name\> \<targets\>) <add_dependencies>` will
653 not make any of the steps dependent on ``<targets>``.
655 ``EXCLUDE_FROM_ALL <bool>``
656 When enabled, this option excludes the external project from the default
657 ALL target of the main build.
659 ``STEP_TARGETS <step-target>...``
660 Generate custom targets for the specified steps. This is required if the
661 steps need to be triggered manually or if they need to be used as
662 dependencies of other targets. If this option is not specified, the
663 default value is taken from the ``EP_STEP_TARGETS`` directory property.
664 See :command:`ExternalProject_Add_Step` below for further discussion of
665 the effects of this option.
667 ``INDEPENDENT_STEP_TARGETS <step-target>...``
668 Generate custom targets for the specified steps and prevent these targets
669 from having the usual dependencies applied to them. If this option is not
670 specified, the default value is taken from the
671 ``EP_INDEPENDENT_STEP_TARGETS`` directory property. This option is mostly
672 useful for allowing individual steps to be driven independently, such as
673 for a CDash setup where each step should be initiated and reported
674 individually rather than as one whole build. See
675 :command:`ExternalProject_Add_Step` below for further discussion of the
676 effects of this option.
678 **Miscellaneous Options:**
679 ``LIST_SEPARATOR <sep>``
680 For any of the various ``..._COMMAND`` options, replace ``;`` with
681 ``<sep>`` in the specified command lines. This can be useful where list
682 variables may be given in commands where they should end up as
683 space-separated arguments (``<sep>`` would be a single space character
684 string in this case).
687 Any of the other ``..._COMMAND`` options can have additional commands
688 appended to them by following them with as many ``COMMAND ...`` options
690 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
691 supported). For example:
693 .. code-block:: cmake
695 ExternalProject_Add(example
696 ... # Download options, etc.
697 BUILD_COMMAND ${CMAKE_COMMAND} -E echo "Starting $<CONFIG> build"
698 COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --config $<CONFIG>
699 COMMAND ${CMAKE_COMMAND} -E echo "$<CONFIG> build complete"
702 It should also be noted that each build step is created via a call to
703 :command:`ExternalProject_Add_Step`. See that command's documentation for the
704 automatic substitutions that are supported for some options.
706 Obtaining Project Properties
707 """"""""""""""""""""""""""""
709 .. command:: ExternalProject_Get_Property
711 The ``ExternalProject_Get_Property()`` function retrieves external project
714 .. code-block:: cmake
716 ExternalProject_Get_Property(<name> <prop1> [<prop2>...])
718 The function stores property values in variables of the same name. Property
719 names correspond to the keyword argument names of ``ExternalProject_Add()``.
720 For example, the source directory might be retrieved like so:
722 .. code-block:: cmake
724 ExternalProject_Get_property(myExtProj SOURCE_DIR)
725 message("Source dir of myExtProj = ${SOURCE_DIR}")
727 Explicit Step Management
728 """"""""""""""""""""""""
730 The ``ExternalProject_Add()`` function on its own is often sufficient for
731 incorporating an external project into the main build. Certain scenarios
732 require additional work to implement desired behavior, such as adding in a
733 custom step or making steps available as manually triggerable targets. The
734 ``ExternalProject_Add_Step()``, ``ExternalProject_Add_StepTargets()`` and
735 ``ExternalProject_Add_StepDependencies`` functions provide the lower level
736 control needed to implement such step-level capabilities.
738 .. command:: ExternalProject_Add_Step
740 The ``ExternalProject_Add_Step()`` function specifies an additional custom
741 step for an external project defined by an earlier call to
742 :command:`ExternalProject_Add`:
744 .. code-block:: cmake
746 ExternalProject_Add_Step(<name> <step> [<option>...])
748 ``<name>`` is the same as the name passed to the original call to
749 :command:`ExternalProject_Add`. The specified ``<step>`` must not be one of
750 the pre-defined steps (``mkdir``, ``download``, ``update``,
751 ``patch``, ``configure``, ``build``, ``install`` or ``test``). The supported
755 The command line to be executed by this custom step
756 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
757 supported). This option can be repeated multiple times to specify multiple
758 commands to be executed in order.
760 ``COMMENT "<text>..."``
761 Text to be printed when the custom step executes.
763 ``DEPENDEES <step>...``
764 Other steps (custom or pre-defined) on which this step depends.
766 ``DEPENDERS <step>...``
767 Other steps (custom or pre-defined) that depend on this new custom step.
769 ``DEPENDS <file>...``
770 Files on which this custom step depends.
772 ``BYPRODUCTS <file>...``
773 Files that will be generated by this custom step but which might or might
774 not have their modification time updated by subsequent builds. This list of
775 files will ultimately be passed through as the ``BYPRODUCTS`` option to the
776 :command:`add_custom_command` used to implement the custom step internally.
779 When enabled, this option specifies that the custom step should always be
780 run (i.e. that it is always considered out of date).
782 ``EXCLUDE_FROM_MAIN <bool>``
783 When enabled, this option specifies that the external project's main target
784 does not depend on the custom step.
786 ``WORKING_DIRECTORY <dir>``
787 Specifies the working directory to set before running the custom step's
788 command. If this option is not specified, the directory will be the value
789 of the :variable:`CMAKE_CURRENT_BINARY_DIR` at the point where
790 ``ExternalProject_Add_Step()`` was called.
793 If set, this causes the output from the custom step to be captured to files
794 in the external project's ``LOG_DIR`` if supplied or ``STAMP_DIR``.
796 ``USES_TERMINAL <bool>``
797 If enabled, this gives the custom step direct access to the terminal if
800 The command line, comment, working directory and byproducts of every
801 standard and custom step are processed to replace the tokens
802 ``<SOURCE_DIR>``, ``<SOURCE_SUBDIR>``, ``<BINARY_DIR>``, ``<INSTALL_DIR>``
803 ``<TMP_DIR>``, ``<DOWNLOAD_DIR>`` and ``<DOWNLOADED_FILE>`` with their
804 corresponding property values defined in the original call to
805 :command:`ExternalProject_Add`.
807 .. command:: ExternalProject_Add_StepTargets
809 The ``ExternalProject_Add_StepTargets()`` function generates targets for the
810 steps listed. The name of each created target will be of the form
813 .. code-block:: cmake
815 ExternalProject_Add_StepTargets(<name> [NO_DEPENDS] <step1> [<step2>...])
817 Creating a target for a step allows it to be used as a dependency of another
818 target or to be triggered manually. Having targets for specific steps also
819 allows them to be driven independently of each other by specifying targets on
820 build command lines. For example, you may be submitting to a sub-project
821 based dashboard where you want to drive the configure portion of the build,
822 then submit to the dashboard, followed by the build portion, followed
823 by tests. If you invoke a custom target that depends on a step halfway
824 through the step dependency chain, then all the previous steps will also run
825 to ensure everything is up to date.
827 If the ``NO_DEPENDS`` option is specified, the step target will not depend on
828 the dependencies of the external project (i.e. on any dependencies of the
829 ``<name>`` custom target created by :command:`ExternalProject_Add`). This is
830 usually safe for the ``download``, ``update`` and ``patch`` steps, since they
831 do not typically require that the dependencies are updated and built. Using
832 ``NO_DEPENDS`` for any of the other pre-defined steps, however, may break
833 parallel builds. Only use ``NO_DEPENDS`` where it is certain that the named
834 steps genuinely do not have dependencies. For custom steps, consider whether
835 or not the custom commands require the dependencies to be configured, built
838 Internally, :command:`ExternalProject_Add` calls
839 :command:`ExternalProject_Add_Step` to create each step. If any
840 ``STEP_TARGETS`` or ``INDEPENDENT_STEP_TARGETS`` were specified, then
841 ``ExternalProject_Add_StepTargets()`` will also be called after
842 :command:`ExternalProject_Add_Step`. ``INDEPENDENT_STEP_TARGETS`` have the
843 ``NO_DEPENDS`` option set, whereas ``STEP_TARGETS`` do not. Other than that,
844 the two options result in ``ExternalProject_Add_StepTargets()`` being called
845 in the same way. Even if a step is not mentioned in either of those two
846 options, ``ExternalProject_Add_StepTargets()`` can still be called later to
847 manually define a target for the step.
849 The ``STEP_TARGETS`` and ``INDEPENDENT_STEP_TARGETS`` options for
850 :command:`ExternalProject_Add` are generally the easiest way to ensure
851 targets are created for specific steps of interest. For custom steps,
852 ``ExternalProject_Add_StepTargets()`` must be called explicitly if a target
853 should also be created for that custom step. An alternative to these two
854 options is to populate the ``EP_STEP_TARGETS`` and
855 ``EP_INDEPENDENT_STEP_TARGETS`` directory properties. These act as defaults
856 for the step target options and can save having to repeatedly specify the
857 same set of step targets when multiple external projects are being defined.
859 .. command:: ExternalProject_Add_StepDependencies
861 The ``ExternalProject_Add_StepDependencies()`` function can be used to add
862 dependencies to a step. The dependencies added must be targets CMake already
863 knows about (these can be ordinary executable or library targets, custom
864 targets or even step targets of another external project):
866 .. code-block:: cmake
868 ExternalProject_Add_StepDependencies(<name> <step> <target1> [<target2>...])
870 This function takes care to set both target and file level dependencies and
871 will ensure that parallel builds will not break. It should be used instead of
872 :command:`add_dependencies` whenever adding a dependency for some of the step
873 targets generated by the ``ExternalProject`` module.
878 The following example shows how to download and build a hypothetical project
879 called *FooBar* from github:
881 .. code-block:: cmake
883 include(ExternalProject)
884 ExternalProject_Add(foobar
885 GIT_REPOSITORY git@github.com:FooCo/FooBar.git
886 GIT_TAG origin/release/1.2.3
889 For the sake of the example, also define a second hypothetical external project
890 called *SecretSauce*, which is downloaded from a web server. Two URLs are given
891 to take advantage of a faster internal network if available, with a fallback to
892 a slower external server. The project is a typical ``Makefile`` project with no
893 configure step, so some of the default commands are overridden. The build is
894 only required to build the *sauce* target:
896 .. code-block:: cmake
898 find_program(MAKE_EXE NAMES gmake nmake make)
899 ExternalProject_Add(secretsauce
900 URL http://intranet.somecompany.com/artifacts/sauce-2.7.tgz
901 https://www.somecompany.com/downloads/sauce-2.7.zip
902 URL_HASH MD5=d41d8cd98f00b204e9800998ecf8427e
904 BUILD_COMMAND ${MAKE_EXE} sauce
907 Suppose the build step of ``secretsauce`` requires that ``foobar`` must already
908 be built. This could be enforced like so:
910 .. code-block:: cmake
912 ExternalProject_Add_StepDependencies(secretsauce build foobar)
914 Another alternative would be to create a custom target for ``foobar``'s build
915 step and make ``secretsauce`` depend on that rather than the whole ``foobar``
916 project. This would mean ``foobar`` only needs to be built, it doesn't need to
917 run its install or test steps before ``secretsauce`` can be built. The
918 dependency can also be defined along with the ``secretsauce`` project:
920 .. code-block:: cmake
922 ExternalProject_Add_StepTargets(foobar build)
923 ExternalProject_Add(secretsauce
924 URL http://intranet.somecompany.com/artifacts/sauce-2.7.tgz
925 https://www.somecompany.com/downloads/sauce-2.7.zip
926 URL_HASH MD5=d41d8cd98f00b204e9800998ecf8427e
928 BUILD_COMMAND ${MAKE_EXE} sauce
932 Instead of calling :command:`ExternalProject_Add_StepTargets`, the target could
933 be defined along with the ``foobar`` project itself:
935 .. code-block:: cmake
937 ExternalProject_Add(foobar
938 GIT_REPOSITORY git@github.com:FooCo/FooBar.git
939 GIT_TAG origin/release/1.2.3
943 If many external projects should have the same set of step targets, setting a
944 directory property may be more convenient. The ``build`` step target could be
945 created automatically by setting the ``EP_STEP_TARGETS`` directory property
946 before creating the external projects with :command:`ExternalProject_Add`:
948 .. code-block:: cmake
950 set_property(DIRECTORY PROPERTY EP_STEP_TARGETS build)
952 Lastly, suppose that ``secretsauce`` provides a script called ``makedoc`` which
953 can be used to generate its own documentation. Further suppose that the script
954 expects the output directory to be provided as the only parameter and that it
955 should be run from the ``secretsauce`` source directory. A custom step and a
956 custom target to trigger the script can be defined like so:
958 .. code-block:: cmake
960 ExternalProject_Add_Step(secretsauce docs
961 COMMAND <SOURCE_DIR>/makedoc <BINARY_DIR>
962 WORKING_DIRECTORY <SOURCE_DIR>
963 COMMENT "Building secretsauce docs"
965 EXCLUDE_FROM_MAIN TRUE
967 ExternalProject_Add_StepTargets(secretsauce docs)
969 The custom step could then be triggered from the main build like so::
971 cmake --build . --target secretsauce-docs
973 #]=======================================================================]
976 cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
977 cmake_policy(SET CMP0057 NEW) # if() supports IN_LIST
979 # Pre-compute a regex to match documented keywords for each command.
980 math(EXPR _ep_documentation_line_count "${CMAKE_CURRENT_LIST_LINE} - 4")
981 file(STRINGS "${CMAKE_CURRENT_LIST_FILE}" lines
982 LIMIT_COUNT ${_ep_documentation_line_count}
983 REGEX "^\\.\\. command:: [A-Za-z0-9_]+|^ +``[A-Z0-9_]+ [^`]*``$")
984 foreach(line IN LISTS lines)
985 if("${line}" MATCHES "^\\.\\. command:: ([A-Za-z0-9_]+)")
987 string(APPEND _ep_keywords_${_ep_func} ")$")
989 set(_ep_func "${CMAKE_MATCH_1}")
990 #message("function [${_ep_func}]")
991 set(_ep_keywords_${_ep_func} "^(")
993 elseif("${line}" MATCHES "^ +``([A-Z0-9_]+) [^`]*``$")
994 set(_ep_key "${CMAKE_MATCH_1}")
995 # COMMAND should never be included as a keyword,
996 # for ExternalProject_Add(), as it is treated as a
997 # special case by argument parsing as an extension
998 # of a previous ..._COMMAND
999 if("x${_ep_key}x" STREQUAL "xCOMMANDx" AND
1000 "x${_ep_func}x" STREQUAL "xExternalProject_Addx")
1003 #message(" keyword [${_ep_key}]")
1004 string(APPEND _ep_keywords_${_ep_func}
1005 "${_ep_keyword_sep}${_ep_key}")
1006 set(_ep_keyword_sep "|")
1010 string(APPEND _ep_keywords_${_ep_func} ")$")
1013 # Save regex matching supported hash algorithm names.
1014 set(_ep_hash_algos "MD5|SHA1|SHA224|SHA256|SHA384|SHA512|SHA3_224|SHA3_256|SHA3_384|SHA3_512")
1015 set(_ep_hash_regex "^(${_ep_hash_algos})=([0-9A-Fa-f]+)$")
1017 set(_ExternalProject_SELF "${CMAKE_CURRENT_LIST_FILE}")
1018 get_filename_component(_ExternalProject_SELF_DIR "${_ExternalProject_SELF}" PATH)
1020 function(_ep_parse_arguments f name ns args)
1021 # Transfer the arguments to this function into target properties for the
1022 # new custom target we just added so that we can set up all the build steps
1023 # correctly based on target properties.
1025 # We loop through ARGN and consider the namespace starting with an
1026 # upper-case letter followed by at least two more upper-case letters,
1027 # numbers or underscores to be keywords.
1029 if(NOT DEFINED _ExternalProject_SELF)
1030 message(FATAL_ERROR "error: ExternalProject module must be explicitly included before using ${f} function")
1035 foreach(arg IN LISTS args)
1038 if(arg MATCHES "^[A-Z][A-Z0-9_][A-Z0-9_]+$" AND
1039 NOT (("x${arg}x" STREQUAL "x${key}x") AND ("x${key}x" STREQUAL "xCOMMANDx")) AND
1040 NOT arg MATCHES "^(TRUE|FALSE)$")
1041 if(_ep_keywords_${f} AND arg MATCHES "${_ep_keywords_${f}}")
1049 if(NOT arg STREQUAL "")
1050 set_property(TARGET ${name} APPEND PROPERTY ${ns}${key} "${arg}")
1052 get_property(have_key TARGET ${name} PROPERTY ${ns}${key} SET)
1054 get_property(value TARGET ${name} PROPERTY ${ns}${key})
1055 set_property(TARGET ${name} PROPERTY ${ns}${key} "${value};${arg}")
1057 set_property(TARGET ${name} PROPERTY ${ns}${key} "${arg}")
1062 message(AUTHOR_WARNING "value '${arg}' with no previous keyword in ${f}")
1067 get_property(have_key TARGET ${name} PROPERTY ${ns}${key} SET)
1074 define_property(DIRECTORY PROPERTY "EP_BASE" INHERITED
1075 BRIEF_DOCS "Base directory for External Project storage."
1077 "See documentation of the ExternalProject_Add() function in the "
1078 "ExternalProject module."
1081 define_property(DIRECTORY PROPERTY "EP_PREFIX" INHERITED
1082 BRIEF_DOCS "Top prefix for External Project storage."
1084 "See documentation of the ExternalProject_Add() function in the "
1085 "ExternalProject module."
1088 define_property(DIRECTORY PROPERTY "EP_STEP_TARGETS" INHERITED
1090 "List of ExternalProject steps that automatically get corresponding targets"
1092 "These targets will be dependent on the main target dependencies. "
1093 "See documentation of the ExternalProject_Add_StepTargets() function in the "
1094 "ExternalProject module."
1097 define_property(DIRECTORY PROPERTY "EP_INDEPENDENT_STEP_TARGETS" INHERITED
1099 "List of ExternalProject steps that automatically get corresponding targets"
1101 "These targets will not be dependent on the main target dependencies. "
1102 "See documentation of the ExternalProject_Add_StepTargets() function in the "
1103 "ExternalProject module."
1106 define_property(DIRECTORY PROPERTY "EP_UPDATE_DISCONNECTED" INHERITED
1107 BRIEF_DOCS "Never update automatically from the remote repo."
1109 "See documentation of the ExternalProject_Add() function in the "
1110 "ExternalProject module."
1113 function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag git_remote_name init_submodules git_submodules_recurse git_submodules git_shallow git_progress git_config src_name work_dir gitclone_infofile gitclone_stampfile tls_verify)
1114 if(NOT GIT_VERSION_STRING VERSION_LESS 1.8.5)
1115 # Use `git checkout <tree-ish> --` to avoid ambiguity with a local path.
1116 set(git_checkout_explicit-- "--")
1118 # Use `git checkout <branch>` even though this risks ambiguity with a
1119 # local path. Unfortunately we cannot use `git checkout <tree-ish> --`
1120 # because that will not search for remote branch names, a common use case.
1121 set(git_checkout_explicit-- "")
1123 if("${git_tag}" STREQUAL "")
1124 message(FATAL_ERROR "Tag for git checkout should not be empty.")
1127 if(GIT_VERSION_STRING VERSION_LESS 2.20 OR 2.21 VERSION_LESS_EQUAL GIT_VERSION_STRING)
1128 set(git_clone_options "--no-checkout")
1130 set(git_clone_options)
1133 if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.10)
1134 list(APPEND git_clone_options "--depth 1 --no-single-branch")
1136 list(APPEND git_clone_options "--depth 1")
1140 list(APPEND git_clone_options --progress)
1142 foreach(config IN LISTS git_config)
1143 list(APPEND git_clone_options --config \"${config}\")
1145 if(NOT ${git_remote_name} STREQUAL "origin")
1146 list(APPEND git_clone_options --origin \"${git_remote_name}\")
1149 string (REPLACE ";" " " git_clone_options "${git_clone_options}")
1152 # disable cert checking if explicitly told not to do it
1153 if(NOT "x${tls_verify}" STREQUAL "x" AND NOT tls_verify)
1155 -c http.sslVerify=false)
1157 string (REPLACE ";" " " git_options "${git_options}")
1159 file(WRITE ${script_filename}
1161 if(NOT \"${gitclone_infofile}\" IS_NEWER_THAN \"${gitclone_stampfile}\")
1162 message(STATUS \"Avoiding repeated git clone, stamp file is up to date: '${gitclone_stampfile}'\")
1167 COMMAND \${CMAKE_COMMAND} -E rm -rf \"${source_dir}\"
1168 RESULT_VARIABLE error_code
1171 message(FATAL_ERROR \"Failed to remove directory: '${source_dir}'\")
1174 # try the clone 3 times in case there is an odd git clone issue
1176 set(number_of_tries 0)
1177 while(error_code AND number_of_tries LESS 3)
1179 COMMAND \"${git_EXECUTABLE}\" ${git_options} clone ${git_clone_options} \"${git_repository}\" \"${src_name}\"
1180 WORKING_DIRECTORY \"${work_dir}\"
1181 RESULT_VARIABLE error_code
1183 math(EXPR number_of_tries \"\${number_of_tries} + 1\")
1185 if(number_of_tries GREATER 1)
1186 message(STATUS \"Had to git clone more than once:
1187 \${number_of_tries} times.\")
1190 message(FATAL_ERROR \"Failed to clone repository: '${git_repository}'\")
1194 COMMAND \"${git_EXECUTABLE}\" ${git_options} checkout ${git_tag} ${git_checkout_explicit--}
1195 WORKING_DIRECTORY \"${work_dir}/${src_name}\"
1196 RESULT_VARIABLE error_code
1199 message(FATAL_ERROR \"Failed to checkout tag: '${git_tag}'\")
1202 set(init_submodules ${init_submodules})
1205 COMMAND \"${git_EXECUTABLE}\" ${git_options} submodule update ${git_submodules_recurse} --init ${git_submodules}
1206 WORKING_DIRECTORY \"${work_dir}/${src_name}\"
1207 RESULT_VARIABLE error_code
1211 message(FATAL_ERROR \"Failed to update submodules in: '${work_dir}/${src_name}'\")
1214 # Complete success, update the script-last-run stamp file:
1217 COMMAND \${CMAKE_COMMAND} -E copy
1218 \"${gitclone_infofile}\"
1219 \"${gitclone_stampfile}\"
1220 RESULT_VARIABLE error_code
1223 message(FATAL_ERROR \"Failed to copy script-last-run stamp file: '${gitclone_stampfile}'\")
1231 function(_ep_write_hgclone_script script_filename source_dir hg_EXECUTABLE hg_repository hg_tag src_name work_dir hgclone_infofile hgclone_stampfile)
1232 if("${hg_tag}" STREQUAL "")
1233 message(FATAL_ERROR "Tag for hg checkout should not be empty.")
1235 file(WRITE ${script_filename}
1237 if(NOT \"${hgclone_infofile}\" IS_NEWER_THAN \"${hgclone_stampfile}\")
1238 message(STATUS \"Avoiding repeated hg clone, stamp file is up to date: '${hgclone_stampfile}'\")
1243 COMMAND \${CMAKE_COMMAND} -E rm -rf \"${source_dir}\"
1244 RESULT_VARIABLE error_code
1247 message(FATAL_ERROR \"Failed to remove directory: '${source_dir}'\")
1251 COMMAND \"${hg_EXECUTABLE}\" clone -U \"${hg_repository}\" \"${src_name}\"
1252 WORKING_DIRECTORY \"${work_dir}\"
1253 RESULT_VARIABLE error_code
1256 message(FATAL_ERROR \"Failed to clone repository: '${hg_repository}'\")
1260 COMMAND \"${hg_EXECUTABLE}\" update ${hg_tag}
1261 WORKING_DIRECTORY \"${work_dir}/${src_name}\"
1262 RESULT_VARIABLE error_code
1265 message(FATAL_ERROR \"Failed to checkout tag: '${hg_tag}'\")
1268 # Complete success, update the script-last-run stamp file:
1271 COMMAND \${CMAKE_COMMAND} -E copy
1272 \"${hgclone_infofile}\"
1273 \"${hgclone_stampfile}\"
1274 RESULT_VARIABLE error_code
1277 message(FATAL_ERROR \"Failed to copy script-last-run stamp file: '${hgclone_stampfile}'\")
1286 function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_remote_name init_submodules git_submodules_recurse git_submodules git_repository work_dir git_update_strategy)
1287 if("${git_tag}" STREQUAL "")
1288 message(FATAL_ERROR "Tag for git checkout should not be empty.")
1290 if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.6)
1291 set(git_stash_save_options --all --quiet)
1293 set(git_stash_save_options --quiet)
1297 "${_ExternalProject_SELF_DIR}/ExternalProject-gitupdate.cmake.in"
1298 "${script_filename}"
1303 function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout no_progress hash tls_verify tls_cainfo userpwd http_headers netrc netrc_file)
1305 set(TIMEOUT_ARGS TIMEOUT ${timeout})
1306 set(TIMEOUT_MSG "${timeout} seconds")
1308 set(TIMEOUT_ARGS "# no TIMEOUT")
1309 set(TIMEOUT_MSG "none")
1313 set(SHOW_PROGRESS "")
1315 set(SHOW_PROGRESS "SHOW_PROGRESS")
1318 if("${hash}" MATCHES "${_ep_hash_regex}")
1319 set(ALGO "${CMAKE_MATCH_1}")
1320 string(TOLOWER "${CMAKE_MATCH_2}" EXPECT_VALUE)
1323 set(EXPECT_VALUE "")
1326 set(TLS_VERIFY_CODE "")
1327 set(TLS_CAINFO_CODE "")
1329 set(NETRC_FILE_CODE "")
1331 # check for curl globals in the project
1332 if(DEFINED CMAKE_TLS_VERIFY)
1333 set(TLS_VERIFY_CODE "set(CMAKE_TLS_VERIFY ${CMAKE_TLS_VERIFY})")
1335 if(DEFINED CMAKE_TLS_CAINFO)
1336 set(TLS_CAINFO_CODE "set(CMAKE_TLS_CAINFO \"${CMAKE_TLS_CAINFO}\")")
1338 if(DEFINED CMAKE_NETRC)
1339 set(NETRC_CODE "set(CMAKE_NETRC \"${CMAKE_NETRC}\")")
1341 if(DEFINED CMAKE_NETRC_FILE)
1342 set(NETRC_FILE_CODE "set(CMAKE_NETRC_FILE \"${CMAKE_NETRC_FILE}\")")
1345 # now check for curl locals so that the local values
1346 # will override the globals
1348 # check for tls_verify argument
1349 string(LENGTH "${tls_verify}" tls_verify_len)
1350 if(tls_verify_len GREATER 0)
1351 set(TLS_VERIFY_CODE "set(CMAKE_TLS_VERIFY ${tls_verify})")
1353 # check for tls_cainfo argument
1354 string(LENGTH "${tls_cainfo}" tls_cainfo_len)
1355 if(tls_cainfo_len GREATER 0)
1356 set(TLS_CAINFO_CODE "set(CMAKE_TLS_CAINFO \"${tls_cainfo}\")")
1358 # check for netrc argument
1359 string(LENGTH "${netrc}" netrc_len)
1360 if(netrc_len GREATER 0)
1361 set(NETRC_CODE "set(CMAKE_NETRC \"${netrc}\")")
1363 # check for netrc_file argument
1364 string(LENGTH "${netrc_file}" netrc_file_len)
1365 if(netrc_file_len GREATER 0)
1366 set(NETRC_FILE_CODE "set(CMAKE_NETRC_FILE \"${netrc_file}\")")
1369 if(userpwd STREQUAL ":")
1372 set(USERPWD_ARGS USERPWD "${userpwd}")
1375 set(HTTP_HEADERS_ARGS "")
1376 if(NOT http_headers STREQUAL "")
1377 foreach(header ${http_headers})
1380 "HTTPHEADER \"${header}\"\n ${HTTP_HEADERS_ARGS}"
1396 # * HTTP_HEADERS_ARGS
1398 "${_ExternalProject_SELF_DIR}/ExternalProject-download.cmake.in"
1399 "${script_filename}"
1404 function(_ep_write_verifyfile_script script_filename LOCAL hash)
1405 if("${hash}" MATCHES "${_ep_hash_regex}")
1406 set(ALGO "${CMAKE_MATCH_1}")
1407 string(TOLOWER "${CMAKE_MATCH_2}" EXPECT_VALUE)
1410 set(EXPECT_VALUE "")
1418 "${_ExternalProject_SELF_DIR}/ExternalProject-verify.cmake.in"
1419 "${script_filename}"
1425 function(_ep_write_extractfile_script script_filename name filename directory)
1428 if(filename MATCHES "(\\.|=)(7z|tar\\.bz2|tar\\.gz|tar\\.xz|tbz2|tgz|txz|zip)$")
1432 if(filename MATCHES "(\\.|=)tar$")
1436 if(args STREQUAL "")
1437 message(SEND_ERROR "error: do not know how to extract '${filename}' -- known types are .7z, .tar, .tar.bz2, .tar.gz, .tar.xz, .tbz2, .tgz, .txz and .zip")
1441 file(WRITE ${script_filename}
1442 "# Make file names absolute:
1444 get_filename_component(filename \"${filename}\" ABSOLUTE)
1445 get_filename_component(directory \"${directory}\" ABSOLUTE)
1447 message(STATUS \"extracting...
1449 dst='\${directory}'\")
1451 if(NOT EXISTS \"\${filename}\")
1452 message(FATAL_ERROR \"error: file to extract does not exist: '\${filename}'\")
1455 # Prepare a space for extracting:
1458 while(EXISTS \"\${directory}/../ex-${name}\${i}\")
1459 math(EXPR i \"\${i} + 1\")
1461 set(ut_dir \"\${directory}/../ex-${name}\${i}\")
1462 file(MAKE_DIRECTORY \"\${ut_dir}\")
1466 message(STATUS \"extracting... [tar ${args}]\")
1467 execute_process(COMMAND \${CMAKE_COMMAND} -E tar ${args} \${filename}
1468 WORKING_DIRECTORY \${ut_dir}
1472 message(STATUS \"extracting... [error clean up]\")
1473 file(REMOVE_RECURSE \"\${ut_dir}\")
1474 message(FATAL_ERROR \"error: extract of '\${filename}' failed\")
1477 # Analyze what came out of the tar file:
1479 message(STATUS \"extracting... [analysis]\")
1480 file(GLOB contents \"\${ut_dir}/*\")
1481 list(REMOVE_ITEM contents \"\${ut_dir}/.DS_Store\")
1482 list(LENGTH contents n)
1483 if(NOT n EQUAL 1 OR NOT IS_DIRECTORY \"\${contents}\")
1484 set(contents \"\${ut_dir}\")
1487 # Move \"the one\" directory to the final directory:
1489 message(STATUS \"extracting... [rename]\")
1490 file(REMOVE_RECURSE \${directory})
1491 get_filename_component(contents \${contents} ABSOLUTE)
1492 file(RENAME \${contents} \${directory})
1496 message(STATUS \"extracting... [clean up]\")
1497 file(REMOVE_RECURSE \"\${ut_dir}\")
1499 message(STATUS \"extracting... done\")
1506 function(_ep_set_directories name)
1507 get_property(prefix TARGET ${name} PROPERTY _EP_PREFIX)
1509 get_property(prefix DIRECTORY PROPERTY EP_PREFIX)
1511 get_property(base DIRECTORY PROPERTY EP_BASE)
1513 set(prefix "${name}-prefix")
1518 set(tmp_default "${prefix}/tmp")
1519 set(download_default "${prefix}/src")
1520 set(source_default "${prefix}/src/${name}")
1521 set(binary_default "${prefix}/src/${name}-build")
1522 set(stamp_default "${prefix}/src/${name}-stamp")
1523 set(install_default "${prefix}")
1525 set(tmp_default "${base}/tmp/${name}")
1526 set(download_default "${base}/Download/${name}")
1527 set(source_default "${base}/Source/${name}")
1528 set(binary_default "${base}/Build/${name}")
1529 set(stamp_default "${base}/Stamp/${name}")
1530 set(install_default "${base}/Install/${name}")
1532 get_property(build_in_source TARGET ${name} PROPERTY _EP_BUILD_IN_SOURCE)
1534 get_property(have_binary_dir TARGET ${name} PROPERTY _EP_BINARY_DIR SET)
1537 "External project ${name} has both BINARY_DIR and BUILD_IN_SOURCE!")
1540 set(top "${CMAKE_CURRENT_BINARY_DIR}")
1542 # Apply defaults and convert to absolute paths.
1543 set(places stamp download source binary install tmp)
1544 foreach(var ${places})
1545 string(TOUPPER "${var}" VAR)
1546 get_property(${var}_dir TARGET ${name} PROPERTY _EP_${VAR}_DIR)
1548 set(${var}_dir "${${var}_default}")
1550 if(NOT IS_ABSOLUTE "${${var}_dir}")
1551 get_filename_component(${var}_dir "${top}/${${var}_dir}" ABSOLUTE)
1553 set_property(TARGET ${name} PROPERTY _EP_${VAR}_DIR "${${var}_dir}")
1556 # Special case for default log directory based on stamp directory.
1557 get_property(log_dir TARGET ${name} PROPERTY _EP_LOG_DIR)
1559 get_property(log_dir TARGET ${name} PROPERTY _EP_STAMP_DIR)
1561 if(NOT IS_ABSOLUTE "${log_dir}")
1562 get_filename_component(log_dir "${top}/${log_dir}" ABSOLUTE)
1564 set_property(TARGET ${name} PROPERTY _EP_LOG_DIR "${log_dir}")
1566 get_property(source_subdir TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR)
1567 if(NOT source_subdir)
1568 set_property(TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR "")
1569 elseif(IS_ABSOLUTE "${source_subdir}")
1571 "External project ${name} has non-relative SOURCE_SUBDIR!")
1573 # Prefix with a slash so that when appended to the source directory, it
1574 # behaves as expected.
1575 set_property(TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR "/${source_subdir}")
1578 get_property(source_dir TARGET ${name} PROPERTY _EP_SOURCE_DIR)
1580 set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}/${source_subdir}")
1582 set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}")
1586 # Make the directories at CMake configure time *and* add a custom command
1587 # to make them at build time. They need to exist at makefile generation
1588 # time for Borland make and wmake so that CMake may generate makefiles
1589 # with "cd C:\short\paths\with\no\spaces" commands in them.
1591 # Additionally, the add_custom_command is still used in case somebody
1592 # removes one of the necessary directories and tries to rebuild without
1594 foreach(var ${places})
1595 string(TOUPPER "${var}" VAR)
1596 get_property(dir TARGET ${name} PROPERTY _EP_${VAR}_DIR)
1597 file(MAKE_DIRECTORY "${dir}")
1598 if(NOT EXISTS "${dir}")
1599 message(FATAL_ERROR "dir '${dir}' does not exist after file(MAKE_DIRECTORY)")
1605 # IMPORTANT: this MUST be a macro and not a function because of the
1606 # in-place replacements that occur in each ${var}
1608 macro(_ep_replace_location_tags target_name)
1610 foreach(var ${vars})
1612 foreach(dir SOURCE_DIR SOURCE_SUBDIR BINARY_DIR INSTALL_DIR TMP_DIR DOWNLOAD_DIR DOWNLOADED_FILE LOG_DIR)
1613 get_property(val TARGET ${target_name} PROPERTY _EP_${dir})
1614 string(REPLACE "<${dir}>" "${val}" ${var} "${${var}}")
1621 function(_ep_command_line_to_initial_cache var args force)
1622 set(script_initial_cache "")
1623 set(regex "^([^:]+):([^=]+)=(.*)$")
1627 set(forceArg "FORCE")
1629 foreach(line ${args})
1630 if("${line}" MATCHES "^-D(.*)")
1631 set(line "${CMAKE_MATCH_1}")
1632 if(NOT "${setArg}" STREQUAL "")
1633 # This is required to build up lists in variables, or complete an entry
1634 string(APPEND setArg "${accumulator}\" CACHE ${type} \"Initial cache\" ${forceArg})")
1635 string(APPEND script_initial_cache "\n${setArg}")
1639 if("${line}" MATCHES "${regex}")
1640 set(name "${CMAKE_MATCH_1}")
1641 set(type "${CMAKE_MATCH_2}")
1642 set(value "${CMAKE_MATCH_3}")
1643 set(setArg "set(${name} \"${value}")
1645 message(WARNING "Line '${line}' does not match regex. Ignoring.")
1648 # Assume this is a list to append to the last var
1649 string(APPEND accumulator ";${line}")
1652 # Catch the final line of the args
1653 if(NOT "${setArg}" STREQUAL "")
1654 string(APPEND setArg "${accumulator}\" CACHE ${type} \"Initial cache\" ${forceArg})")
1655 string(APPEND script_initial_cache "\n${setArg}")
1657 set(${var} ${script_initial_cache} PARENT_SCOPE)
1661 function(_ep_write_initial_cache target_name script_filename script_initial_cache)
1662 # Write out values into an initial cache, that will be passed to CMake with -C
1663 # Replace location tags.
1664 _ep_replace_location_tags(${target_name} script_initial_cache)
1665 _ep_replace_location_tags(${target_name} script_filename)
1666 # Replace list separators.
1667 get_property(sep TARGET ${target_name} PROPERTY _EP_LIST_SEPARATOR)
1668 if(sep AND script_initial_cache)
1669 string(REPLACE "${sep}" ";" script_initial_cache "${script_initial_cache}")
1671 # Write out the initial cache file to the location specified.
1672 file(GENERATE OUTPUT "${script_filename}" CONTENT "${script_initial_cache}")
1676 function(ExternalProject_Get_Property name)
1677 foreach(var ${ARGN})
1678 string(TOUPPER "${var}" VAR)
1679 get_property(is_set TARGET ${name} PROPERTY _EP_${VAR} SET)
1681 message(FATAL_ERROR "External project \"${name}\" has no ${var}")
1683 get_property(${var} TARGET ${name} PROPERTY _EP_${VAR})
1684 set(${var} "${${var}}" PARENT_SCOPE)
1689 function(_ep_get_configure_command_id name cfg_cmd_id_var)
1690 get_target_property(cmd ${name} _EP_CONFIGURE_COMMAND)
1693 # Explicit empty string means no configure step for this project
1694 set(${cfg_cmd_id_var} "none" PARENT_SCOPE)
1697 # Default is "use cmake":
1698 set(${cfg_cmd_id_var} "cmake" PARENT_SCOPE)
1700 # Otherwise we have to analyze the value:
1701 if(cmd MATCHES "^[^;]*/configure")
1702 set(${cfg_cmd_id_var} "configure" PARENT_SCOPE)
1703 elseif(cmd MATCHES "^[^;]*/cmake" AND NOT cmd MATCHES ";-[PE];")
1704 set(${cfg_cmd_id_var} "cmake" PARENT_SCOPE)
1705 elseif(cmd MATCHES "config")
1706 set(${cfg_cmd_id_var} "configure" PARENT_SCOPE)
1708 set(${cfg_cmd_id_var} "unknown:${cmd}" PARENT_SCOPE)
1715 function(_ep_get_build_command name step cmd_var)
1718 _ep_get_configure_command_id(${name} cfg_cmd_id)
1719 if(cfg_cmd_id STREQUAL "cmake")
1720 # CMake project. Select build command based on generator.
1721 get_target_property(cmake_generator ${name} _EP_CMAKE_GENERATOR)
1722 if("${CMAKE_GENERATOR}" MATCHES "Make" AND
1723 ("${cmake_generator}" MATCHES "Make" OR NOT cmake_generator))
1724 # The project uses the same Makefile generator. Use recursive make.
1726 if(step STREQUAL "INSTALL")
1729 if("x${step}x" STREQUAL "xTESTx")
1733 # Drive the project with "cmake --build".
1734 get_target_property(cmake_command ${name} _EP_CMAKE_COMMAND)
1736 set(cmd "${cmake_command}")
1738 set(cmd "${CMAKE_COMMAND}")
1740 set(args --build ".")
1741 get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
1743 if (CMAKE_CFG_INTDIR AND
1744 NOT CMAKE_CFG_INTDIR STREQUAL "." AND
1745 NOT CMAKE_CFG_INTDIR MATCHES "\\$")
1746 # CMake 3.4 and below used the CMAKE_CFG_INTDIR placeholder value
1747 # provided by multi-configuration generators. Some projects were
1748 # taking advantage of that undocumented implementation detail to
1749 # specify a specific configuration here. They should use
1750 # BUILD_COMMAND to change the default command instead, but for
1751 # compatibility honor the value.
1752 set(config ${CMAKE_CFG_INTDIR})
1753 message(AUTHOR_WARNING "CMAKE_CFG_INTDIR should not be set by project code.\n"
1754 "To get a non-default build command, use the BUILD_COMMAND option.")
1756 set(config $<CONFIG>)
1758 list(APPEND args --config ${config})
1760 if(step STREQUAL "INSTALL")
1761 list(APPEND args --target install)
1763 # But for "TEST" drive the project with corresponding "ctest".
1764 if("x${step}x" STREQUAL "xTESTx")
1765 string(REGEX REPLACE "^(.*/)cmake([^/]*)$" "\\1ctest\\2" cmd "${cmd}")
1768 list(APPEND args -C ${config})
1773 # Non-CMake project. Guess "make" and "make install" and "make test".
1774 if("${CMAKE_GENERATOR}" MATCHES "Makefiles")
1775 # Try to get the parallel arguments
1780 if(step STREQUAL "INSTALL")
1783 if("x${step}x" STREQUAL "xTESTx")
1788 # Use user-specified arguments instead of default arguments, if any.
1789 get_property(have_args TARGET ${name} PROPERTY _EP_${step}_ARGS SET)
1791 get_target_property(args ${name} _EP_${step}_ARGS)
1794 if(NOT "${args}" STREQUAL "")
1795 # args could have empty items, so we must quote it to prevent them
1796 # from being silently removed
1797 list(APPEND cmd "${args}")
1799 set(${cmd_var} "${cmd}" PARENT_SCOPE)
1802 function(_ep_write_log_script name step cmd_var)
1803 ExternalProject_Get_Property(${name} log_dir)
1804 ExternalProject_Get_Property(${name} stamp_dir)
1805 set(command "${${cmd_var}}")
1808 set(code_cygpath_make "")
1809 if(command MATCHES "^\\$\\(MAKE\\)")
1810 # GNU make recognizes the string "$(MAKE)" as recursive make, so
1811 # ensure that it appears directly in the makefile.
1812 string(REGEX REPLACE "^\\$\\(MAKE\\)" "\${make}" command "${command}")
1813 set(make "-Dmake=$(MAKE)")
1815 if(WIN32 AND NOT CYGWIN)
1816 set(code_cygpath_make "
1817 if(\${make} MATCHES \"^/\")
1819 COMMAND cygpath -w \${make}
1820 OUTPUT_VARIABLE cygpath_make
1821 ERROR_VARIABLE cygpath_make
1822 RESULT_VARIABLE cygpath_error
1823 OUTPUT_STRIP_TRAILING_WHITESPACE
1825 if(NOT cygpath_error)
1826 set(make \${cygpath_make})
1834 if("${CMAKE_CFG_INTDIR}" MATCHES "^\\$")
1835 string(REPLACE "${CMAKE_CFG_INTDIR}" "\${config}" command "${command}")
1836 set(config "-Dconfig=${CMAKE_CFG_INTDIR}")
1839 # Wrap multiple 'COMMAND' lines up into a second-level wrapper
1840 # script so all output can be sent to one log file.
1841 if(command MATCHES "(^|;)COMMAND;")
1842 set(code_execute_process "
1843 ${code_cygpath_make}
1844 execute_process(COMMAND \${command} RESULT_VARIABLE result)
1846 set(msg \"Command failed (\${result}):\\n\")
1847 foreach(arg IN LISTS command)
1848 set(msg \"\${msg} '\${arg}'\")
1850 message(FATAL_ERROR \"\${msg}\")
1856 foreach(arg IN LISTS command)
1857 if("x${arg}" STREQUAL "xCOMMAND")
1858 if(NOT "x${cmd}" STREQUAL "x")
1859 string(APPEND code "set(command \"${cmd}\")${code_execute_process}")
1864 string(APPEND cmd "${sep}${arg}")
1868 string(APPEND code "set(command \"${cmd}\")${code_execute_process}")
1869 file(GENERATE OUTPUT "${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake" CONTENT "${code}")
1870 set(command ${CMAKE_COMMAND} "-Dmake=\${make}" "-Dconfig=\${config}" -P ${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake)
1873 # Wrap the command in a script to log output to files.
1874 set(script ${stamp_dir}/${name}-${step}-$<CONFIG>.cmake)
1875 set(logbase ${log_dir}/${name}-${step})
1876 get_property(log_merged TARGET ${name} PROPERTY _EP_LOG_MERGED_STDOUTERR)
1877 get_property(log_output_on_failure TARGET ${name} PROPERTY _EP_LOG_OUTPUT_ON_FAILURE)
1879 set(stdout_log "${logbase}.log")
1880 set(stderr_log "${logbase}.log")
1882 set(stdout_log "${logbase}-out.log")
1883 set(stderr_log "${logbase}-err.log")
1886 cmake_minimum_required(VERSION 3.15)
1887 ${code_cygpath_make}
1888 set(command \"${command}\")
1889 set(log_merged \"${log_merged}\")
1890 set(log_output_on_failure \"${log_output_on_failure}\")
1891 set(stdout_log \"${stdout_log}\")
1892 set(stderr_log \"${stderr_log}\")
1895 RESULT_VARIABLE result
1896 OUTPUT_FILE \"\${stdout_log}\"
1897 ERROR_FILE \"\${stderr_log}\"
1899 macro(read_up_to_max_size log_file output_var)
1900 file(SIZE \${log_file} determined_size)
1902 if (determined_size GREATER max_size)
1903 math(EXPR seek_position \"\${determined_size} - \${max_size}\")
1904 file(READ \${log_file} \${output_var} OFFSET \${seek_position})
1905 set(\${output_var} \"...skipping to end...\\n\${\${output_var}}\")
1907 file(READ \${log_file} \${output_var})
1911 set(msg \"Command failed: \${result}\\n\")
1912 foreach(arg IN LISTS command)
1913 set(msg \"\${msg} '\${arg}'\")
1916 set(msg \"\${msg}\\nSee also\\n \${stderr_log}\")
1918 set(msg \"\${msg}\\nSee also\\n ${logbase}-*.log\")
1920 if (\${log_output_on_failure})
1921 message(SEND_ERROR \"\${msg}\")
1923 read_up_to_max_size(\"\${stderr_log}\" error_log_contents)
1924 message(STATUS \"Log output is:\\n\${error_log_contents}\")
1926 read_up_to_max_size(\"\${stdout_log}\" out_log_contents)
1927 read_up_to_max_size(\"\${stderr_log}\" err_log_contents)
1928 message(STATUS \"stdout output is:\\n\${out_log_contents}\")
1929 message(STATUS \"stderr output is:\\n\${err_log_contents}\")
1931 message(FATAL_ERROR \"Stopping after outputting logs.\")
1933 message(FATAL_ERROR \"\${msg}\")
1936 set(msg \"${name} ${step} command succeeded. See also ${logbase}-*.log\")
1937 message(STATUS \"\${msg}\")
1940 file(GENERATE OUTPUT "${script}" CONTENT "${code}")
1941 set(command ${CMAKE_COMMAND} ${make} ${config} -P ${script})
1942 set(${cmd_var} "${command}" PARENT_SCOPE)
1945 # This module used to use "/${CMAKE_CFG_INTDIR}" directly and produced
1946 # makefiles with "/./" in paths for custom command dependencies. Which
1947 # resulted in problems with parallel make -j invocations.
1949 # This function was added so that the suffix (search below for ${cfgdir}) is
1950 # only set to "/${CMAKE_CFG_INTDIR}" when ${CMAKE_CFG_INTDIR} is not going to
1951 # be "." (multi-configuration build systems like Visual Studio and Xcode...)
1953 function(_ep_get_configuration_subdir_suffix suffix_var)
1955 get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
1957 set(suffix "/${CMAKE_CFG_INTDIR}")
1959 set(${suffix_var} "${suffix}" PARENT_SCOPE)
1963 function(_ep_get_step_stampfile name step stampfile_var)
1964 ExternalProject_Get_Property(${name} stamp_dir)
1966 _ep_get_configuration_subdir_suffix(cfgdir)
1967 set(stampfile "${stamp_dir}${cfgdir}/${name}-${step}")
1969 set(${stampfile_var} "${stampfile}" PARENT_SCOPE)
1973 function(_ep_get_complete_stampfile name stampfile_var)
1974 set(cmf_dir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles)
1975 _ep_get_configuration_subdir_suffix(cfgdir)
1976 set(stampfile "${cmf_dir}${cfgdir}/${name}-complete")
1978 set(${stampfile_var} ${stampfile} PARENT_SCOPE)
1982 function(ExternalProject_Add_StepTargets name)
1984 if(ARGC GREATER 1 AND "${ARGV1}" STREQUAL "NO_DEPENDS")
1986 list(REMOVE_AT steps 0)
1988 foreach(step ${steps})
1989 if(no_deps AND "${step}" MATCHES "^(configure|build|install|test)$")
1990 message(AUTHOR_WARNING "Using NO_DEPENDS for \"${step}\" step might break parallel builds")
1992 _ep_get_step_stampfile(${name} ${step} stamp_file)
1993 add_custom_target(${name}-${step}
1994 DEPENDS ${stamp_file})
1995 set_property(TARGET ${name}-${step} PROPERTY _EP_IS_EXTERNAL_PROJECT_STEP 1)
1996 set_property(TARGET ${name}-${step} PROPERTY LABELS ${name})
1997 set_property(TARGET ${name}-${step} PROPERTY FOLDER "ExternalProjectTargets/${name}")
1999 # Depend on other external projects (target-level).
2001 get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
2002 foreach(arg IN LISTS deps)
2003 add_dependencies(${name}-${step} ${arg})
2010 function(ExternalProject_Add_Step name step)
2011 _ep_get_complete_stampfile(${name} complete_stamp_file)
2012 _ep_get_step_stampfile(${name} ${step} stamp_file)
2014 _ep_parse_arguments(ExternalProject_Add_Step
2015 ${name} _EP_${step}_ "${ARGN}")
2017 get_property(exclude_from_main TARGET ${name} PROPERTY _EP_${step}_EXCLUDE_FROM_MAIN)
2018 if(NOT exclude_from_main)
2019 add_custom_command(APPEND
2020 OUTPUT ${complete_stamp_file}
2021 DEPENDS ${stamp_file}
2025 # Steps depending on this step.
2026 get_property(dependers TARGET ${name} PROPERTY _EP_${step}_DEPENDERS)
2027 foreach(depender IN LISTS dependers)
2028 _ep_get_step_stampfile(${name} ${depender} depender_stamp_file)
2029 add_custom_command(APPEND
2030 OUTPUT ${depender_stamp_file}
2031 DEPENDS ${stamp_file}
2035 # Dependencies on files.
2036 get_property(depends TARGET ${name} PROPERTY _EP_${step}_DEPENDS)
2038 # Byproducts of the step.
2039 get_property(byproducts TARGET ${name} PROPERTY _EP_${step}_BYPRODUCTS)
2041 # Dependencies on steps.
2042 get_property(dependees TARGET ${name} PROPERTY _EP_${step}_DEPENDEES)
2043 foreach(dependee IN LISTS dependees)
2044 _ep_get_step_stampfile(${name} ${dependee} dependee_stamp_file)
2045 list(APPEND depends ${dependee_stamp_file})
2048 # The command to run.
2049 get_property(command TARGET ${name} PROPERTY _EP_${step}_COMMAND)
2051 set(comment "Performing ${step} step for '${name}'")
2053 set(comment "No ${step} step for '${name}'")
2055 get_property(work_dir TARGET ${name} PROPERTY _EP_${step}_WORKING_DIRECTORY)
2057 # Replace list separators.
2058 get_property(sep TARGET ${name} PROPERTY _EP_LIST_SEPARATOR)
2060 string(REPLACE "${sep}" "\\;" command "${command}")
2063 # Replace location tags.
2064 _ep_replace_location_tags(${name} comment command work_dir byproducts)
2067 get_property(comment_set TARGET ${name} PROPERTY _EP_${step}_COMMENT SET)
2069 get_property(comment TARGET ${name} PROPERTY _EP_${step}_COMMENT)
2073 get_property(uses_terminal TARGET ${name} PROPERTY _EP_${step}_USES_TERMINAL)
2075 set(uses_terminal USES_TERMINAL)
2077 set(uses_terminal "")
2081 get_property(always TARGET ${name} PROPERTY _EP_${step}_ALWAYS)
2083 set_property(SOURCE ${stamp_file} PROPERTY SYMBOLIC 1)
2085 # Remove any existing stamp in case the option changed in an existing tree.
2086 get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
2088 foreach(cfg ${CMAKE_CONFIGURATION_TYPES})
2089 string(REPLACE "/${CMAKE_CFG_INTDIR}" "/${cfg}" stamp_file_config "${stamp_file}")
2090 file(REMOVE ${stamp_file_config})
2093 file(REMOVE ${stamp_file})
2096 set(touch ${CMAKE_COMMAND} -E touch ${stamp_file})
2099 # Wrap with log script?
2100 get_property(log TARGET ${name} PROPERTY _EP_${step}_LOG)
2102 _ep_write_log_script(${name} ${step} command)
2105 if("${command}" STREQUAL "")
2106 # Some generators (i.e. Xcode) will not generate a file level target
2107 # if no command is set, and therefore the dependencies on this
2108 # target will be broken.
2109 # The empty command is replaced by an echo command here in order to
2111 set(command ${CMAKE_COMMAND} -E echo_append)
2115 foreach(__item IN LISTS command)
2116 string(APPEND __cmdQuoted " [==[${__item}]==]")
2118 cmake_language(EVAL CODE "
2120 OUTPUT \${stamp_file}
2121 BYPRODUCTS \${byproducts}
2123 COMMAND ${__cmdQuoted}
2126 WORKING_DIRECTORY \${work_dir}
2131 set_property(TARGET ${name} APPEND PROPERTY _EP_STEPS ${step})
2133 # Add custom "step target"?
2134 get_property(step_targets TARGET ${name} PROPERTY _EP_STEP_TARGETS)
2135 if(NOT step_targets)
2136 get_property(step_targets DIRECTORY PROPERTY EP_STEP_TARGETS)
2138 foreach(st ${step_targets})
2139 if("${st}" STREQUAL "${step}")
2140 ExternalProject_Add_StepTargets(${name} ${step})
2145 get_property(independent_step_targets TARGET ${name} PROPERTY _EP_INDEPENDENT_STEP_TARGETS)
2146 if(NOT independent_step_targets)
2147 get_property(independent_step_targets DIRECTORY PROPERTY EP_INDEPENDENT_STEP_TARGETS)
2149 foreach(st ${independent_step_targets})
2150 if("${st}" STREQUAL "${step}")
2151 ExternalProject_Add_StepTargets(${name} NO_DEPENDS ${step})
2158 function(ExternalProject_Add_StepDependencies name step)
2159 set(dependencies ${ARGN})
2161 # Sanity checks on "name" and "step".
2162 if(NOT TARGET ${name})
2163 message(FATAL_ERROR "Cannot find target \"${name}\". Perhaps it has not yet been created using ExternalProject_Add.")
2166 get_property(type TARGET ${name} PROPERTY TYPE)
2167 if(NOT type STREQUAL "UTILITY")
2168 message(FATAL_ERROR "Target \"${name}\" was not generated by ExternalProject_Add.")
2171 get_property(is_ep TARGET ${name} PROPERTY _EP_IS_EXTERNAL_PROJECT)
2173 message(FATAL_ERROR "Target \"${name}\" was not generated by ExternalProject_Add.")
2176 get_property(steps TARGET ${name} PROPERTY _EP_STEPS)
2177 list(FIND steps ${step} is_step)
2179 message(FATAL_ERROR "External project \"${name}\" does not have a step \"${step}\".")
2182 if(TARGET ${name}-${step})
2183 get_property(type TARGET ${name}-${step} PROPERTY TYPE)
2184 if(NOT type STREQUAL "UTILITY")
2185 message(FATAL_ERROR "Target \"${name}-${step}\" was not generated by ExternalProject_Add_StepTargets.")
2187 get_property(is_ep_step TARGET ${name}-${step} PROPERTY _EP_IS_EXTERNAL_PROJECT_STEP)
2189 message(FATAL_ERROR "Target \"${name}-${step}\" was not generated by ExternalProject_Add_StepTargets.")
2193 # Always add file-level dependency, but add target-level dependency
2194 # only if the target exists for that step.
2195 _ep_get_step_stampfile(${name} ${step} stamp_file)
2196 foreach(dep ${dependencies})
2197 add_custom_command(APPEND
2198 OUTPUT ${stamp_file}
2200 if(TARGET ${name}-${step})
2201 foreach(dep ${dependencies})
2202 add_dependencies(${name}-${step} ${dep})
2210 function(_ep_add_mkdir_command name)
2211 ExternalProject_Get_Property(${name}
2212 source_dir binary_dir install_dir stamp_dir download_dir tmp_dir log_dir)
2214 _ep_get_configuration_subdir_suffix(cfgdir)
2216 ExternalProject_Add_Step(${name} mkdir
2217 COMMENT "Creating directories for '${name}'"
2218 COMMAND ${CMAKE_COMMAND} -E make_directory ${source_dir}
2219 COMMAND ${CMAKE_COMMAND} -E make_directory ${binary_dir}
2220 COMMAND ${CMAKE_COMMAND} -E make_directory ${install_dir}
2221 COMMAND ${CMAKE_COMMAND} -E make_directory ${tmp_dir}
2222 COMMAND ${CMAKE_COMMAND} -E make_directory ${stamp_dir}${cfgdir}
2223 COMMAND ${CMAKE_COMMAND} -E make_directory ${download_dir}
2224 COMMAND ${CMAKE_COMMAND} -E make_directory ${log_dir}
2229 function(_ep_is_dir_empty dir empty_var)
2230 file(GLOB gr "${dir}/*")
2231 if("${gr}" STREQUAL "")
2232 set(${empty_var} 1 PARENT_SCOPE)
2234 set(${empty_var} 0 PARENT_SCOPE)
2238 function(_ep_get_git_submodules_recurse git_submodules_recurse)
2239 # Checks for GIT_SUBMODULES_RECURSE property
2240 # Default is ON, which sets git_submodules_recurse output variable to "--recursive"
2241 # Otherwise, the output variable is set to an empty value ""
2242 get_property(git_submodules_recurse_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES_RECURSE SET)
2243 if(NOT git_submodules_recurse_set)
2244 set(recurseFlag "--recursive")
2246 get_property(git_submodules_recurse_value TARGET ${name} PROPERTY _EP_GIT_SUBMODULES_RECURSE)
2247 if(git_submodules_recurse_value)
2248 set(recurseFlag "--recursive")
2253 set(${git_submodules_recurse} "${recurseFlag}" PARENT_SCOPE)
2255 # The git submodule update '--recursive' flag requires git >= v1.6.5
2256 if(recurseFlag AND GIT_VERSION_STRING VERSION_LESS 1.6.5)
2257 message(FATAL_ERROR "error: git version 1.6.5 or later required for --recursive flag with 'git submodule ...': GIT_VERSION_STRING='${GIT_VERSION_STRING}'")
2262 function(_ep_add_download_command name)
2263 ExternalProject_Get_Property(${name} source_dir stamp_dir download_dir tmp_dir)
2265 get_property(cmd_set TARGET ${name} PROPERTY _EP_DOWNLOAD_COMMAND SET)
2266 get_property(cmd TARGET ${name} PROPERTY _EP_DOWNLOAD_COMMAND)
2267 get_property(cvs_repository TARGET ${name} PROPERTY _EP_CVS_REPOSITORY)
2268 get_property(svn_repository TARGET ${name} PROPERTY _EP_SVN_REPOSITORY)
2269 get_property(git_repository TARGET ${name} PROPERTY _EP_GIT_REPOSITORY)
2270 get_property(hg_repository TARGET ${name} PROPERTY _EP_HG_REPOSITORY )
2271 get_property(url TARGET ${name} PROPERTY _EP_URL)
2272 get_property(fname TARGET ${name} PROPERTY _EP_DOWNLOAD_NAME)
2274 # TODO: Perhaps file:// should be copied to download dir before extraction.
2275 string(REGEX REPLACE "file://" "" url "${url}")
2282 set(work_dir ${download_dir})
2283 elseif(cvs_repository)
2284 find_package(CVS QUIET)
2285 if(NOT CVS_EXECUTABLE)
2286 message(FATAL_ERROR "error: could not find cvs for checkout of ${name}")
2289 get_target_property(cvs_module ${name} _EP_CVS_MODULE)
2291 message(FATAL_ERROR "error: no CVS_MODULE")
2294 get_property(cvs_tag TARGET ${name} PROPERTY _EP_CVS_TAG)
2296 set(repository ${cvs_repository})
2297 set(module ${cvs_module})
2300 "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
2301 "${stamp_dir}/${name}-cvsinfo.txt"
2305 get_filename_component(src_name "${source_dir}" NAME)
2306 get_filename_component(work_dir "${source_dir}" PATH)
2307 set(comment "Performing download step (CVS checkout) for '${name}'")
2308 set(cmd ${CVS_EXECUTABLE} -d ${cvs_repository} -q co ${cvs_tag} -d ${src_name} ${cvs_module})
2309 list(APPEND depends ${stamp_dir}/${name}-cvsinfo.txt)
2310 elseif(svn_repository)
2311 find_package(Subversion QUIET)
2312 if(NOT Subversion_SVN_EXECUTABLE)
2313 message(FATAL_ERROR "error: could not find svn for checkout of ${name}")
2316 get_property(svn_revision TARGET ${name} PROPERTY _EP_SVN_REVISION)
2317 get_property(svn_username TARGET ${name} PROPERTY _EP_SVN_USERNAME)
2318 get_property(svn_password TARGET ${name} PROPERTY _EP_SVN_PASSWORD)
2319 get_property(svn_trust_cert TARGET ${name} PROPERTY _EP_SVN_TRUST_CERT)
2321 set(repository "${svn_repository} user=${svn_username} password=${svn_password}")
2323 set(tag ${svn_revision})
2325 "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
2326 "${stamp_dir}/${name}-svninfo.txt"
2330 get_filename_component(src_name "${source_dir}" NAME)
2331 get_filename_component(work_dir "${source_dir}" PATH)
2332 set(comment "Performing download step (SVN checkout) for '${name}'")
2333 set(svn_user_pw_args "")
2334 if(DEFINED svn_username)
2335 set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}")
2337 if(DEFINED svn_password)
2338 set(svn_user_pw_args ${svn_user_pw_args} "--password=${svn_password}")
2341 set(svn_trust_cert_args --trust-server-cert)
2343 set(cmd ${Subversion_SVN_EXECUTABLE} co ${svn_repository} ${svn_revision}
2344 --non-interactive ${svn_trust_cert_args} ${svn_user_pw_args} ${src_name})
2345 list(APPEND depends ${stamp_dir}/${name}-svninfo.txt)
2346 elseif(git_repository)
2347 unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
2348 find_package(Git QUIET)
2349 if(NOT GIT_EXECUTABLE)
2350 message(FATAL_ERROR "error: could not find git for clone of ${name}")
2353 _ep_get_git_submodules_recurse(git_submodules_recurse)
2355 get_property(git_tag TARGET ${name} PROPERTY _EP_GIT_TAG)
2357 set(git_tag "master")
2360 set(git_init_submodules TRUE)
2361 get_property(git_submodules_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES SET)
2362 if(git_submodules_set)
2363 get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES)
2364 if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW")
2365 set(git_init_submodules FALSE)
2369 get_property(git_remote_name TARGET ${name} PROPERTY _EP_GIT_REMOTE_NAME)
2370 if(NOT git_remote_name)
2371 set(git_remote_name "origin")
2374 get_property(tls_verify TARGET ${name} PROPERTY _EP_TLS_VERIFY)
2375 if("x${tls_verify}" STREQUAL "x" AND DEFINED CMAKE_TLS_VERIFY)
2376 set(tls_verify "${CMAKE_TLS_VERIFY}")
2378 get_property(git_shallow TARGET ${name} PROPERTY _EP_GIT_SHALLOW)
2379 get_property(git_progress TARGET ${name} PROPERTY _EP_GIT_PROGRESS)
2380 get_property(git_config TARGET ${name} PROPERTY _EP_GIT_CONFIG)
2382 # For the download step, and the git clone operation, only the repository
2383 # should be recorded in a configured RepositoryInfo file. If the repo
2384 # changes, the clone script should be run again. But if only the tag
2385 # changes, avoid running the clone script again. Let the 'always' running
2386 # update step checkout the new tag.
2388 set(repository ${git_repository})
2390 set(tag ${git_remote_name})
2392 "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
2393 "${stamp_dir}/${name}-gitinfo.txt"
2397 get_filename_component(src_name "${source_dir}" NAME)
2398 get_filename_component(work_dir "${source_dir}" PATH)
2400 # Since git clone doesn't succeed if the non-empty source_dir exists,
2401 # create a cmake script to invoke as download command.
2402 # The script will delete the source directory and then call git clone.
2404 _ep_write_gitclone_script(${tmp_dir}/${name}-gitclone.cmake ${source_dir}
2405 ${GIT_EXECUTABLE} ${git_repository} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules_recurse}" "${git_submodules}" "${git_shallow}" "${git_progress}" "${git_config}" ${src_name} ${work_dir}
2406 ${stamp_dir}/${name}-gitinfo.txt ${stamp_dir}/${name}-gitclone-lastrun.txt "${tls_verify}"
2408 set(comment "Performing download step (git clone) for '${name}'")
2409 set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-gitclone.cmake)
2410 list(APPEND depends ${stamp_dir}/${name}-gitinfo.txt)
2411 elseif(hg_repository)
2412 find_package(Hg QUIET)
2413 if(NOT HG_EXECUTABLE)
2414 message(FATAL_ERROR "error: could not find hg for clone of ${name}")
2417 get_property(hg_tag TARGET ${name} PROPERTY _EP_HG_TAG)
2422 # For the download step, and the hg clone operation, only the repository
2423 # should be recorded in a configured RepositoryInfo file. If the repo
2424 # changes, the clone script should be run again. But if only the tag
2425 # changes, avoid running the clone script again. Let the 'always' running
2426 # update step checkout the new tag.
2428 set(repository ${hg_repository})
2432 "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
2433 "${stamp_dir}/${name}-hginfo.txt"
2437 get_filename_component(src_name "${source_dir}" NAME)
2438 get_filename_component(work_dir "${source_dir}" PATH)
2440 # Since hg clone doesn't succeed if the non-empty source_dir exists,
2441 # create a cmake script to invoke as download command.
2442 # The script will delete the source directory and then call hg clone.
2444 _ep_write_hgclone_script(${tmp_dir}/${name}-hgclone.cmake ${source_dir}
2445 ${HG_EXECUTABLE} ${hg_repository} ${hg_tag} ${src_name} ${work_dir}
2446 ${stamp_dir}/${name}-hginfo.txt ${stamp_dir}/${name}-hgclone-lastrun.txt
2448 set(comment "Performing download step (hg clone) for '${name}'")
2449 set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-hgclone.cmake)
2450 list(APPEND depends ${stamp_dir}/${name}-hginfo.txt)
2452 get_filename_component(work_dir "${source_dir}" PATH)
2453 get_property(hash TARGET ${name} PROPERTY _EP_URL_HASH)
2454 if(hash AND NOT "${hash}" MATCHES "${_ep_hash_regex}")
2455 message(FATAL_ERROR "URL_HASH is set to\n ${hash}\n"
2456 "but must be ALGO=value where ALGO is\n ${_ep_hash_algos}\n"
2457 "and value is a hex string.")
2459 get_property(md5 TARGET ${name} PROPERTY _EP_URL_MD5)
2460 if(md5 AND NOT "MD5=${md5}" MATCHES "${_ep_hash_regex}")
2461 message(FATAL_ERROR "URL_MD5 is set to\n ${md5}\nbut must be a hex string.")
2463 if(md5 AND NOT hash)
2464 set(hash "MD5=${md5}")
2466 set(repository "external project URL")
2467 set(module "${url}")
2470 "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in"
2471 "${stamp_dir}/${name}-urlinfo.txt"
2474 list(APPEND depends ${stamp_dir}/${name}-urlinfo.txt)
2476 list(LENGTH url url_list_length)
2477 if(NOT "${url_list_length}" STREQUAL "1")
2478 foreach(entry ${url})
2479 if(NOT "${entry}" MATCHES "^[a-z]+://")
2480 message(FATAL_ERROR "At least one entry of URL is a path (invalid in a list)")
2483 if("x${fname}" STREQUAL "x")
2484 list(GET url 0 fname)
2488 if(IS_DIRECTORY "${url}")
2489 get_filename_component(abs_dir "${url}" ABSOLUTE)
2490 set(comment "Performing download step (DIR copy) for '${name}'")
2491 set(cmd ${CMAKE_COMMAND} -E rm -rf ${source_dir}
2492 COMMAND ${CMAKE_COMMAND} -E copy_directory ${abs_dir} ${source_dir})
2494 get_property(no_extract TARGET "${name}" PROPERTY _EP_DOWNLOAD_NO_EXTRACT)
2495 if("${url}" MATCHES "^[a-z]+://")
2496 # TODO: Should download and extraction be different steps?
2497 if("x${fname}" STREQUAL "x")
2500 if("${fname}" MATCHES [[([^/\?#]+(\.|=)(7z|tar|tar\.bz2|tar\.gz|tar\.xz|tbz2|tgz|txz|zip))([/?#].*)?$]])
2501 set(fname "${CMAKE_MATCH_1}")
2503 get_filename_component(fname "${fname}" NAME)
2505 # Fall back to a default file name. The actual file name does not
2506 # matter because it is used only internally and our extraction tool
2507 # inspects the file content directly. If it turns out the wrong URL
2508 # was given that will be revealed during the build which is an easier
2509 # place for users to diagnose than an error here anyway.
2510 set(fname "archive.tar")
2512 string(REPLACE ";" "-" fname "${fname}")
2513 set(file ${download_dir}/${fname})
2514 get_property(timeout TARGET ${name} PROPERTY _EP_TIMEOUT)
2515 get_property(no_progress TARGET ${name} PROPERTY _EP_DOWNLOAD_NO_PROGRESS)
2516 get_property(tls_verify TARGET ${name} PROPERTY _EP_TLS_VERIFY)
2517 get_property(tls_cainfo TARGET ${name} PROPERTY _EP_TLS_CAINFO)
2518 get_property(netrc TARGET ${name} PROPERTY _EP_NETRC)
2519 get_property(netrc_file TARGET ${name} PROPERTY _EP_NETRC_FILE)
2520 get_property(http_username TARGET ${name} PROPERTY _EP_HTTP_USERNAME)
2521 get_property(http_password TARGET ${name} PROPERTY _EP_HTTP_PASSWORD)
2522 get_property(http_headers TARGET ${name} PROPERTY _EP_HTTP_HEADER)
2523 set(download_script "${stamp_dir}/download-${name}.cmake")
2524 _ep_write_downloadfile_script("${download_script}" "${url}" "${file}" "${timeout}" "${no_progress}" "${hash}" "${tls_verify}" "${tls_cainfo}" "${http_username}:${http_password}" "${http_headers}" "${netrc}" "${netrc_file}")
2525 set(cmd ${CMAKE_COMMAND} -P "${download_script}"
2528 set(steps "download and verify")
2530 set(steps "download, verify and extract")
2532 set(comment "Performing download step (${steps}) for '${name}'")
2533 file(WRITE "${stamp_dir}/verify-${name}.cmake" "") # already verified by 'download_script'
2539 set(steps "verify and extract")
2541 set(comment "Performing download step (${steps}) for '${name}'")
2542 _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}")
2544 list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake)
2546 _ep_write_extractfile_script("${stamp_dir}/extract-${name}.cmake" "${name}" "${file}" "${source_dir}")
2547 list(APPEND cmd COMMAND ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake)
2549 set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file})
2553 _ep_is_dir_empty("${source_dir}" empty)
2556 "No download info given for '${name}' and its source directory:\n"
2558 "is not an existing non-empty directory. Please specify one of:\n"
2559 " * SOURCE_DIR with an existing non-empty directory\n"
2560 " * DOWNLOAD_COMMAND\n"
2562 " * GIT_REPOSITORY\n"
2563 " * SVN_REPOSITORY\n"
2564 " * HG_REPOSITORY\n"
2565 " * CVS_REPOSITORY and CVS_MODULE"
2570 get_property(log TARGET ${name} PROPERTY _EP_LOG_DOWNLOAD)
2577 get_property(uses_terminal TARGET ${name} PROPERTY
2578 _EP_USES_TERMINAL_DOWNLOAD)
2580 set(uses_terminal USES_TERMINAL 1)
2582 set(uses_terminal "")
2586 foreach(__item IN LISTS cmd)
2587 string(APPEND __cmdQuoted " [==[${__item}]==]")
2589 cmake_language(EVAL CODE "
2590 ExternalProject_Add_Step(\${name} download
2592 COMMAND ${__cmdQuoted}
2593 WORKING_DIRECTORY \${work_dir}
2602 function(_ep_get_update_disconnected var name)
2603 get_property(update_disconnected_set TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED SET)
2604 if(update_disconnected_set)
2605 get_property(update_disconnected TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED)
2607 get_property(update_disconnected DIRECTORY PROPERTY EP_UPDATE_DISCONNECTED)
2609 set(${var} "${update_disconnected}" PARENT_SCOPE)
2612 function(_ep_add_update_command name)
2613 ExternalProject_Get_Property(${name} source_dir tmp_dir)
2615 get_property(cmd_set TARGET ${name} PROPERTY _EP_UPDATE_COMMAND SET)
2616 get_property(cmd TARGET ${name} PROPERTY _EP_UPDATE_COMMAND)
2617 get_property(cvs_repository TARGET ${name} PROPERTY _EP_CVS_REPOSITORY)
2618 get_property(svn_repository TARGET ${name} PROPERTY _EP_SVN_REPOSITORY)
2619 get_property(git_repository TARGET ${name} PROPERTY _EP_GIT_REPOSITORY)
2620 get_property(hg_repository TARGET ${name} PROPERTY _EP_HG_REPOSITORY )
2622 _ep_get_update_disconnected(update_disconnected ${name})
2629 set(work_dir ${source_dir})
2630 if(NOT "x${cmd}" STREQUAL "x")
2633 elseif(cvs_repository)
2634 if(NOT CVS_EXECUTABLE)
2635 message(FATAL_ERROR "error: could not find cvs for update of ${name}")
2637 set(work_dir ${source_dir})
2638 set(comment "Performing update step (CVS update) for '${name}'")
2639 get_property(cvs_tag TARGET ${name} PROPERTY _EP_CVS_TAG)
2640 set(cmd ${CVS_EXECUTABLE} -d ${cvs_repository} -q up -dP ${cvs_tag})
2642 elseif(svn_repository)
2643 if(NOT Subversion_SVN_EXECUTABLE)
2644 message(FATAL_ERROR "error: could not find svn for update of ${name}")
2646 set(work_dir ${source_dir})
2647 set(comment "Performing update step (SVN update) for '${name}'")
2648 get_property(svn_revision TARGET ${name} PROPERTY _EP_SVN_REVISION)
2649 get_property(svn_username TARGET ${name} PROPERTY _EP_SVN_USERNAME)
2650 get_property(svn_password TARGET ${name} PROPERTY _EP_SVN_PASSWORD)
2651 get_property(svn_trust_cert TARGET ${name} PROPERTY _EP_SVN_TRUST_CERT)
2652 set(svn_user_pw_args "")
2653 if(DEFINED svn_username)
2654 set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}")
2656 if(DEFINED svn_password)
2657 set(svn_user_pw_args ${svn_user_pw_args} "--password=${svn_password}")
2660 set(svn_trust_cert_args --trust-server-cert)
2662 set(cmd ${Subversion_SVN_EXECUTABLE} up ${svn_revision}
2663 --non-interactive ${svn_trust_cert_args} ${svn_user_pw_args})
2665 elseif(git_repository)
2666 unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
2667 find_package(Git QUIET)
2668 if(NOT GIT_EXECUTABLE)
2669 message(FATAL_ERROR "error: could not find git for fetch of ${name}")
2671 set(work_dir ${source_dir})
2672 set(comment "Performing update step for '${name}'")
2673 get_property(git_tag TARGET ${name} PROPERTY _EP_GIT_TAG)
2675 set(git_tag "master")
2677 get_property(git_remote_name TARGET ${name} PROPERTY _EP_GIT_REMOTE_NAME)
2678 if(NOT git_remote_name)
2679 set(git_remote_name "origin")
2682 set(git_init_submodules TRUE)
2683 get_property(git_submodules_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES SET)
2684 if(git_submodules_set)
2685 get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES)
2686 if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW")
2687 set(git_init_submodules FALSE)
2691 get_property(git_update_strategy TARGET ${name} PROPERTY _EP_GIT_REMOTE_UPDATE_STRATEGY)
2692 if(NOT git_update_strategy)
2693 set(git_update_strategy "${CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY}")
2695 if(NOT git_update_strategy)
2696 set(git_update_strategy REBASE)
2698 set(strategies CHECKOUT REBASE REBASE_CHECKOUT)
2699 if(NOT git_update_strategy IN_LIST strategies)
2700 message(FATAL_ERROR "'${git_update_strategy}' is not one of the supported strategies: ${strategies}")
2703 _ep_get_git_submodules_recurse(git_submodules_recurse)
2705 _ep_write_gitupdate_script(${tmp_dir}/${name}-gitupdate.cmake
2706 ${GIT_EXECUTABLE} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules_recurse}" "${git_submodules}" ${git_repository} ${work_dir} ${git_update_strategy}
2708 set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-gitupdate.cmake)
2710 elseif(hg_repository)
2711 if(NOT HG_EXECUTABLE)
2712 message(FATAL_ERROR "error: could not find hg for pull of ${name}")
2714 set(work_dir ${source_dir})
2715 set(comment "Performing update step (hg pull) for '${name}'")
2716 get_property(hg_tag TARGET ${name} PROPERTY _EP_HG_TAG)
2720 if("${HG_VERSION_STRING}" STREQUAL "2.1")
2721 message(WARNING "Mercurial 2.1 does not distinguish an empty pull from a failed pull:
2722 http://mercurial.selenic.com/wiki/UpgradeNotes#A2.1.1:_revert_pull_return_code_change.2C_compile_issue_on_OS_X
2723 http://thread.gmane.org/gmane.comp.version-control.mercurial.devel/47656
2724 Update to Mercurial >= 2.1.1.
2727 set(cmd ${HG_EXECUTABLE} pull
2728 COMMAND ${HG_EXECUTABLE} update ${hg_tag}
2733 get_property(log TARGET ${name} PROPERTY _EP_LOG_UPDATE)
2740 get_property(uses_terminal TARGET ${name} PROPERTY
2741 _EP_USES_TERMINAL_UPDATE)
2743 set(uses_terminal USES_TERMINAL 1)
2745 set(uses_terminal "")
2749 foreach(__item IN LISTS cmd)
2750 string(APPEND __cmdQuoted " [==[${__item}]==]")
2752 cmake_language(EVAL CODE "
2753 ExternalProject_Add_Step(${name} update
2755 COMMAND ${__cmdQuoted}
2757 EXCLUDE_FROM_MAIN \${update_disconnected}
2758 WORKING_DIRECTORY \${work_dir}
2768 function(_ep_add_patch_command name)
2769 ExternalProject_Get_Property(${name} source_dir)
2771 get_property(cmd_set TARGET ${name} PROPERTY _EP_PATCH_COMMAND SET)
2772 get_property(cmd TARGET ${name} PROPERTY _EP_PATCH_COMMAND)
2777 set(work_dir ${source_dir})
2780 get_property(log TARGET ${name} PROPERTY _EP_LOG_PATCH)
2787 _ep_get_update_disconnected(update_disconnected ${name})
2788 if(update_disconnected)
2789 set(patch_dep download)
2791 set(patch_dep update)
2795 foreach(__item IN LISTS cmd)
2796 string(APPEND __cmdQuoted " [==[${__item}]==]")
2798 cmake_language(EVAL CODE "
2799 ExternalProject_Add_Step(${name} patch
2800 COMMAND ${__cmdQuoted}
2801 WORKING_DIRECTORY \${work_dir}
2802 DEPENDEES \${patch_dep}
2809 function(_ep_extract_configure_command var name)
2810 get_property(cmd_set TARGET ${name} PROPERTY _EP_CONFIGURE_COMMAND SET)
2812 get_property(cmd TARGET ${name} PROPERTY _EP_CONFIGURE_COMMAND)
2814 get_target_property(cmake_command ${name} _EP_CMAKE_COMMAND)
2816 set(cmd "${cmake_command}")
2818 set(cmd "${CMAKE_COMMAND}")
2821 get_property(cmake_args TARGET ${name} PROPERTY _EP_CMAKE_ARGS)
2822 list(APPEND cmd ${cmake_args})
2824 # If there are any CMAKE_CACHE_ARGS or CMAKE_CACHE_DEFAULT_ARGS,
2825 # write an initial cache and use it
2826 get_property(cmake_cache_args TARGET ${name} PROPERTY _EP_CMAKE_CACHE_ARGS)
2827 get_property(cmake_cache_default_args TARGET ${name} PROPERTY _EP_CMAKE_CACHE_DEFAULT_ARGS)
2829 set(has_cmake_cache_args 0)
2830 if(NOT "${cmake_cache_args}" STREQUAL "")
2831 set(has_cmake_cache_args 1)
2834 set(has_cmake_cache_default_args 0)
2835 if(NOT "${cmake_cache_default_args}" STREQUAL "")
2836 set(has_cmake_cache_default_args 1)
2839 get_target_property(cmake_generator ${name} _EP_CMAKE_GENERATOR)
2840 get_target_property(cmake_generator_instance ${name} _EP_CMAKE_GENERATOR_INSTANCE)
2841 get_target_property(cmake_generator_platform ${name} _EP_CMAKE_GENERATOR_PLATFORM)
2842 get_target_property(cmake_generator_toolset ${name} _EP_CMAKE_GENERATOR_TOOLSET)
2844 list(APPEND cmd "-G${cmake_generator}")
2845 if(cmake_generator_platform)
2846 list(APPEND cmd "-A${cmake_generator_platform}")
2848 if(cmake_generator_toolset)
2849 list(APPEND cmd "-T${cmake_generator_toolset}")
2851 if(cmake_generator_instance)
2852 list(APPEND cmd "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${cmake_generator_instance}")
2855 if(CMAKE_EXTRA_GENERATOR)
2856 list(APPEND cmd "-G${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}")
2858 list(APPEND cmd "-G${CMAKE_GENERATOR}")
2859 if("${CMAKE_GENERATOR}" MATCHES "Green Hills MULTI")
2860 set(has_cmake_cache_default_args 1)
2861 set(cmake_cache_default_args ${cmake_cache_default_args}
2862 "-DGHS_TARGET_PLATFORM:STRING=${GHS_TARGET_PLATFORM}"
2863 "-DGHS_PRIMARY_TARGET:STRING=${GHS_PRIMARY_TARGET}"
2864 "-DGHS_TOOLSET_ROOT:STRING=${GHS_TOOLSET_ROOT}"
2865 "-DGHS_OS_ROOT:STRING=${GHS_OS_ROOT}"
2866 "-DGHS_OS_DIR:STRING=${GHS_OS_DIR}"
2867 "-DGHS_BSP_NAME:STRING=${GHS_BSP_NAME}")
2870 if(cmake_generator_platform)
2871 message(FATAL_ERROR "Option CMAKE_GENERATOR_PLATFORM not allowed without CMAKE_GENERATOR.")
2873 if(CMAKE_GENERATOR_PLATFORM)
2874 list(APPEND cmd "-A${CMAKE_GENERATOR_PLATFORM}")
2876 if(cmake_generator_toolset)
2877 message(FATAL_ERROR "Option CMAKE_GENERATOR_TOOLSET not allowed without CMAKE_GENERATOR.")
2879 if(CMAKE_GENERATOR_TOOLSET)
2880 list(APPEND cmd "-T${CMAKE_GENERATOR_TOOLSET}")
2882 if(cmake_generator_instance)
2883 message(FATAL_ERROR "Option CMAKE_GENERATOR_INSTANCE not allowed without CMAKE_GENERATOR.")
2885 if(CMAKE_GENERATOR_INSTANCE)
2886 list(APPEND cmd "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${CMAKE_GENERATOR_INSTANCE}")
2890 if(has_cmake_cache_args OR has_cmake_cache_default_args)
2891 set(_ep_cache_args_script "<TMP_DIR>/${name}-cache-$<CONFIG>.cmake")
2892 if(has_cmake_cache_args)
2893 _ep_command_line_to_initial_cache(script_initial_cache_force "${cmake_cache_args}" 1)
2895 if(has_cmake_cache_default_args)
2896 _ep_command_line_to_initial_cache(script_initial_cache_default "${cmake_cache_default_args}" 0)
2898 _ep_write_initial_cache(${name} "${_ep_cache_args_script}" "${script_initial_cache_force}${script_initial_cache_default}")
2899 list(APPEND cmd "-C${_ep_cache_args_script}")
2900 _ep_replace_location_tags(${name} _ep_cache_args_script)
2901 set(_ep_cache_args_script
2902 "${_ep_cache_args_script}"
2906 list(APPEND cmd "<SOURCE_DIR><SOURCE_SUBDIR>")
2909 set("${var}" "${cmd}" PARENT_SCOPE)
2912 # TODO: Make sure external projects use the proper compiler
2913 function(_ep_add_configure_command name)
2914 ExternalProject_Get_Property(${name} binary_dir tmp_dir)
2916 # Depend on other external projects (file-level).
2918 get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
2919 foreach(dep IN LISTS deps)
2920 get_property(dep_type TARGET ${dep} PROPERTY TYPE)
2921 if(dep_type STREQUAL "UTILITY")
2922 get_property(is_ep TARGET ${dep} PROPERTY _EP_IS_EXTERNAL_PROJECT)
2924 _ep_get_step_stampfile(${dep} "done" done_stamp_file)
2925 list(APPEND file_deps ${done_stamp_file})
2930 _ep_extract_configure_command(cmd ${name})
2932 # If anything about the configure command changes, (command itself, cmake
2933 # used, cmake args or cmake generator) then re-run the configure step.
2934 # Fixes issue https://gitlab.kitware.com/cmake/cmake/-/issues/10258
2936 if(NOT EXISTS ${tmp_dir}/${name}-cfgcmd.txt.in)
2937 file(WRITE ${tmp_dir}/${name}-cfgcmd.txt.in "cmd='\@cmd\@'\n")
2939 configure_file(${tmp_dir}/${name}-cfgcmd.txt.in ${tmp_dir}/${name}-cfgcmd.txt)
2940 list(APPEND file_deps ${tmp_dir}/${name}-cfgcmd.txt)
2941 list(APPEND file_deps ${_ep_cache_args_script})
2943 get_property(log TARGET ${name} PROPERTY _EP_LOG_CONFIGURE)
2950 get_property(uses_terminal TARGET ${name} PROPERTY
2951 _EP_USES_TERMINAL_CONFIGURE)
2953 set(uses_terminal USES_TERMINAL 1)
2955 set(uses_terminal "")
2959 foreach(__item IN LISTS cmd)
2960 string(APPEND __cmdQuoted " [==[${__item}]==]")
2962 cmake_language(EVAL CODE "
2963 ExternalProject_Add_Step(${name} configure
2964 COMMAND ${__cmdQuoted}
2965 WORKING_DIRECTORY \${binary_dir}
2967 DEPENDS \${file_deps}
2975 function(_ep_add_build_command name)
2976 ExternalProject_Get_Property(${name} binary_dir)
2978 get_property(cmd_set TARGET ${name} PROPERTY _EP_BUILD_COMMAND SET)
2980 get_property(cmd TARGET ${name} PROPERTY _EP_BUILD_COMMAND)
2982 _ep_get_build_command(${name} BUILD cmd)
2985 get_property(log TARGET ${name} PROPERTY _EP_LOG_BUILD)
2992 get_property(uses_terminal TARGET ${name} PROPERTY
2993 _EP_USES_TERMINAL_BUILD)
2995 set(uses_terminal USES_TERMINAL 1)
2997 set(uses_terminal "")
3000 get_property(build_always TARGET ${name} PROPERTY _EP_BUILD_ALWAYS)
3007 get_property(build_byproducts TARGET ${name} PROPERTY _EP_BUILD_BYPRODUCTS)
3010 foreach(__item IN LISTS cmd)
3011 string(APPEND __cmdQuoted " [==[${__item}]==]")
3013 cmake_language(EVAL CODE "
3014 ExternalProject_Add_Step(${name} build
3015 COMMAND ${__cmdQuoted}
3016 BYPRODUCTS \${build_byproducts}
3017 WORKING_DIRECTORY \${binary_dir}
3027 function(_ep_add_install_command name)
3028 ExternalProject_Get_Property(${name} binary_dir)
3030 get_property(cmd_set TARGET ${name} PROPERTY _EP_INSTALL_COMMAND SET)
3032 get_property(cmd TARGET ${name} PROPERTY _EP_INSTALL_COMMAND)
3034 _ep_get_build_command(${name} INSTALL cmd)
3037 get_property(log TARGET ${name} PROPERTY _EP_LOG_INSTALL)
3044 get_property(uses_terminal TARGET ${name} PROPERTY
3045 _EP_USES_TERMINAL_INSTALL)
3047 set(uses_terminal USES_TERMINAL 1)
3049 set(uses_terminal "")
3053 foreach(__item IN LISTS cmd)
3054 string(APPEND __cmdQuoted " [==[${__item}]==]")
3056 cmake_language(EVAL CODE "
3057 ExternalProject_Add_Step(${name} install
3058 COMMAND ${__cmdQuoted}
3059 WORKING_DIRECTORY \${binary_dir}
3068 function(_ep_add_test_command name)
3069 ExternalProject_Get_Property(${name} binary_dir)
3071 get_property(before TARGET ${name} PROPERTY _EP_TEST_BEFORE_INSTALL)
3072 get_property(after TARGET ${name} PROPERTY _EP_TEST_AFTER_INSTALL)
3073 get_property(exclude TARGET ${name} PROPERTY _EP_TEST_EXCLUDE_FROM_MAIN)
3074 get_property(cmd_set TARGET ${name} PROPERTY _EP_TEST_COMMAND SET)
3076 # Only actually add the test step if one of the test related properties is
3077 # explicitly set. (i.e. the test step is omitted unless requested...)
3079 if(cmd_set OR before OR after OR exclude)
3081 get_property(cmd TARGET ${name} PROPERTY _EP_TEST_COMMAND)
3083 _ep_get_build_command(${name} TEST cmd)
3087 set(dependees_args DEPENDEES build)
3089 set(dependees_args DEPENDEES install)
3093 set(dependers_args "")
3094 set(exclude_args EXCLUDE_FROM_MAIN 1)
3097 set(dependers_args DEPENDERS install)
3099 set(dependers_args "")
3101 set(exclude_args "")
3104 get_property(log TARGET ${name} PROPERTY _EP_LOG_TEST)
3111 get_property(uses_terminal TARGET ${name} PROPERTY
3112 _EP_USES_TERMINAL_TEST)
3114 set(uses_terminal USES_TERMINAL 1)
3116 set(uses_terminal "")
3120 foreach(__item IN LISTS cmd)
3121 string(APPEND __cmdQuoted " [==[${__item}]==]")
3123 cmake_language(EVAL CODE "
3124 ExternalProject_Add_Step(${name} test
3125 COMMAND ${__cmdQuoted}
3126 WORKING_DIRECTORY \${binary_dir}
3138 function(ExternalProject_Add name)
3139 cmake_policy(GET CMP0097 _EP_CMP0097
3140 PARENT_SCOPE # undocumented, do not use outside of CMake
3143 _ep_get_configuration_subdir_suffix(cfgdir)
3145 # Add a custom target for the external project.
3146 set(cmf_dir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles)
3147 _ep_get_complete_stampfile(${name} complete_stamp_file)
3149 # The "ALL" option to add_custom_target just tells it to not set the
3150 # EXCLUDE_FROM_ALL target property. Later, if the EXCLUDE_FROM_ALL
3151 # argument was passed, we explicitly set it for the target.
3152 add_custom_target(${name} ALL DEPENDS ${complete_stamp_file})
3153 set_property(TARGET ${name} PROPERTY _EP_IS_EXTERNAL_PROJECT 1)
3154 set_property(TARGET ${name} PROPERTY LABELS ${name})
3155 set_property(TARGET ${name} PROPERTY FOLDER "ExternalProjectTargets/${name}")
3157 _ep_parse_arguments(ExternalProject_Add ${name} _EP_ "${ARGN}")
3158 _ep_set_directories(${name})
3159 _ep_get_step_stampfile(${name} "done" done_stamp_file)
3160 _ep_get_step_stampfile(${name} "install" install_stamp_file)
3162 # Set the EXCLUDE_FROM_ALL target property if required.
3163 get_property(exclude_from_all TARGET ${name} PROPERTY _EP_EXCLUDE_FROM_ALL)
3164 if(exclude_from_all)
3165 set_property(TARGET ${name} PROPERTY EXCLUDE_FROM_ALL TRUE)
3168 # The 'complete' step depends on all other steps and creates a
3169 # 'done' mark. A dependent external project's 'configure' step
3170 # depends on the 'done' mark so that it rebuilds when this project
3171 # rebuilds. It is important that 'done' is not the output of any
3172 # custom command so that CMake does not propagate build rules to
3173 # other external project targets, which may cause problems during
3174 # parallel builds. However, the Ninja generator needs to see the entire
3175 # dependency graph, and can cope with custom commands belonging to
3176 # multiple targets, so we add the 'done' mark as an output for Ninja only.
3177 set(complete_outputs ${complete_stamp_file})
3178 if(${CMAKE_GENERATOR} MATCHES "Ninja")
3179 set(complete_outputs ${complete_outputs} ${done_stamp_file})
3183 OUTPUT ${complete_outputs}
3184 COMMENT "Completed '${name}'"
3185 COMMAND ${CMAKE_COMMAND} -E make_directory ${cmf_dir}${cfgdir}
3186 COMMAND ${CMAKE_COMMAND} -E touch ${complete_stamp_file}
3187 COMMAND ${CMAKE_COMMAND} -E touch ${done_stamp_file}
3188 DEPENDS ${install_stamp_file}
3193 # Depend on other external projects (target-level).
3194 get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
3195 foreach(arg IN LISTS deps)
3196 add_dependencies(${name} ${arg})
3199 # Set up custom build steps based on the target properties.
3200 # Each step depends on the previous one.
3202 # The target depends on the output of the final step.
3203 # (Already set up above in the DEPENDS of the add_custom_target command.)
3205 _ep_add_mkdir_command(${name})
3206 _ep_add_download_command(${name})
3207 _ep_add_update_command(${name})
3208 _ep_add_patch_command(${name})
3209 _ep_add_configure_command(${name})
3210 _ep_add_build_command(${name})
3211 _ep_add_install_command(${name})
3213 # Test is special in that it might depend on build, or it might depend
3216 _ep_add_test_command(${name})