1 # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 # file Copyright.txt or https://cmake.org/licensing for details.
6 #[=======================================================================[.rst:
14 External Project Definition
15 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
17 .. command:: ExternalProject_Add
19 The ``ExternalProject_Add()`` function creates a custom target to drive
20 download, update/patch, configure, build, install and test steps of an
25 ExternalProject_Add(<name> [<option>...])
27 The individual steps within the process can be driven independently if
28 required (e.g. for CDash submission) and extra custom steps can be defined,
29 along with the ability to control the step dependencies. The directory
30 structure used for the management of the external project can also be
31 customized. The function supports a large number of options which can be used
32 to tailor the external project behavior.
37 Most of the time, the default directory layout is sufficient. It is largely
38 an implementation detail that the main project usually doesn't need to
39 change. In some circumstances, however, control over the directory layout
40 can be useful or necessary. The directory options are potentially more
41 useful from the point of view that the main build can use the
42 :command:`ExternalProject_Get_Property` command to retrieve their values,
43 thereby allowing the main project to refer to build artifacts of the
47 Root directory for the external project. Unless otherwise noted below,
48 all other directories associated with the external project will be
52 Directory in which to store temporary files.
55 Directory in which to store the timestamps of each step. Log files from
56 individual steps are also created in here unless overridden by LOG_DIR
57 (see *Logging Options* below).
60 .. versionadded:: 3.14
62 Directory in which to store the logs of each step.
64 ``DOWNLOAD_DIR <dir>``
65 Directory in which to store downloaded files before unpacking them. This
66 directory is only used by the URL download method, all other download
67 methods use ``SOURCE_DIR`` directly instead.
70 Source directory into which downloaded contents will be unpacked, or for
71 non-URL download methods, the directory in which the repository should be
72 checked out, cloned, etc. If no download method is specified, this must
73 point to an existing directory where the external project has already
74 been unpacked or cloned/checked out.
77 If a download method is specified, any existing contents of the source
78 directory may be deleted. Only the URL download method checks whether
79 this directory is either missing or empty before initiating the
80 download, stopping with an error if it is not empty. All other
81 download methods silently discard any previous contents of the source
85 Specify the build directory location. This option is ignored if
86 ``BUILD_IN_SOURCE`` is enabled.
89 Installation prefix to be placed in the ``<INSTALL_DIR>`` placeholder.
90 This does not actually configure the external project to install to
91 the given prefix. That must be done by passing appropriate arguments
92 to the external project configuration step, e.g. using ``<INSTALL_DIR>``.
94 If any of the above ``..._DIR`` options are not specified, their defaults
95 are computed as follows. If the ``PREFIX`` option is given or the
96 ``EP_PREFIX`` directory property is set, then an external project is built
97 and installed under the specified prefix::
99 TMP_DIR = <prefix>/tmp
100 STAMP_DIR = <prefix>/src/<name>-stamp
101 DOWNLOAD_DIR = <prefix>/src
102 SOURCE_DIR = <prefix>/src/<name>
103 BINARY_DIR = <prefix>/src/<name>-build
104 INSTALL_DIR = <prefix>
105 LOG_DIR = <STAMP_DIR>
107 Otherwise, if the ``EP_BASE`` directory property is set then components
108 of an external project are stored under the specified base::
110 TMP_DIR = <base>/tmp/<name>
111 STAMP_DIR = <base>/Stamp/<name>
112 DOWNLOAD_DIR = <base>/Download/<name>
113 SOURCE_DIR = <base>/Source/<name>
114 BINARY_DIR = <base>/Build/<name>
115 INSTALL_DIR = <base>/Install/<name>
116 LOG_DIR = <STAMP_DIR>
118 If no ``PREFIX``, ``EP_PREFIX``, or ``EP_BASE`` is specified, then the
119 default is to set ``PREFIX`` to ``<name>-prefix``. Relative paths are
120 interpreted with respect to :variable:`CMAKE_CURRENT_BINARY_DIR` at the
121 point where ``ExternalProject_Add()`` is called.
123 Download Step Options
124 """""""""""""""""""""
126 A download method can be omitted if the ``SOURCE_DIR`` option is used to
127 point to an existing non-empty directory. Otherwise, one of the download
128 methods below must be specified (multiple download methods should not be
129 given) or a custom ``DOWNLOAD_COMMAND`` provided.
131 ``DOWNLOAD_COMMAND <cmd>...``
132 Overrides the command used for the download step
133 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
134 supported). If this option is specified, all other download options will
135 be ignored. Providing an empty string for ``<cmd>`` effectively disables
141 ``URL <url1> [<url2>...]``
142 List of paths and/or URL(s) of the external project's source. When more
143 than one URL is given, they are tried in turn until one succeeds. A URL
144 may be an ordinary path in the local file system (in which case it
145 must be the only URL provided) or any downloadable URL supported by the
146 :command:`file(DOWNLOAD)` command. A local filesystem path may refer to
147 either an existing directory or to an archive file, whereas a URL is
148 expected to point to a file which can be treated as an archive. When an
149 archive is used, it will be unpacked automatically unless the
150 ``DOWNLOAD_NO_EXTRACT`` option is set to prevent it. The archive type
151 is determined by inspecting the actual content rather than using logic
152 based on the file extension.
154 .. versionchanged:: 3.7
155 Multiple URLs are allowed.
157 ``URL_HASH <algo>=<hashValue>``
158 Hash of the archive file to be downloaded. The argument should be of
159 the form ``<algo>=<hashValue>`` where ``algo`` can be any of the hashing
160 algorithms supported by the :command:`file()` command. Specifying this
161 option is strongly recommended for URL downloads, as it ensures the
162 integrity of the downloaded content. It is also used as a check for a
163 previously downloaded file, allowing connection to the remote location
164 to be avoided altogether if the local directory already has a file from
165 an earlier download that matches the specified hash.
168 Equivalent to ``URL_HASH MD5=<md5>``.
170 ``DOWNLOAD_NAME <fname>``
171 File name to use for the downloaded file. If not given, the end of the
172 URL is used to determine the file name. This option is rarely needed,
173 the default name is generally suitable and is not normally used outside
174 of code internal to the ``ExternalProject`` module.
176 ``DOWNLOAD_EXTRACT_TIMESTAMP <bool>``
177 .. versionadded:: 3.24
179 When specified with a true value, the timestamps of the extracted
180 files will match those in the archive. When false, the timestamps of
181 the extracted files will reflect the time at which the extraction
182 was performed. If the download URL changes, timestamps based off
183 those in the archive can result in dependent targets not being rebuilt
184 when they potentially should have been. Therefore, unless the file
185 timestamps are significant to the project in some way, use a false
186 value for this option. If ``DOWNLOAD_EXTRACT_TIMESTAMP`` is not given,
187 the default is false. See policy :policy:`CMP0135`.
189 ``DOWNLOAD_NO_EXTRACT <bool>``
190 .. versionadded:: 3.6
192 Allows the extraction part of the download step to be disabled by
193 passing a boolean true value for this option. If this option is not
194 given, the downloaded contents will be unpacked automatically if
195 required. If extraction has been disabled, the full path to the
196 downloaded file is available as ``<DOWNLOADED_FILE>`` in subsequent
197 steps or as the property ``DOWNLOADED_FILE`` with the
198 :command:`ExternalProject_Get_Property` command.
200 ``DOWNLOAD_NO_PROGRESS <bool>``
201 Can be used to disable logging the download progress. If this option is
202 not given, download progress messages will be logged.
204 ``TIMEOUT <seconds>``
205 Maximum time allowed for file download operations.
207 ``INACTIVITY_TIMEOUT <seconds>``
208 .. versionadded:: 3.19
210 Terminate the operation after a period of inactivity.
212 ``HTTP_USERNAME <username>``
213 .. versionadded:: 3.7
215 Username for the download operation if authentication is required.
217 ``HTTP_PASSWORD <password>``
218 .. versionadded:: 3.7
220 Password for the download operation if authentication is required.
222 ``HTTP_HEADER <header1> [<header2>...]``
223 .. versionadded:: 3.7
225 Provides an arbitrary list of HTTP headers for the download operation.
226 This can be useful for accessing content in systems like AWS, etc.
228 ``TLS_VERSION <min>``
229 .. versionadded:: 3.30
231 Specify minimum TLS version for ``https://`` URLs. If this option is
232 not provided, the value of the :variable:`CMAKE_TLS_VERSION` variable
233 or the :envvar:`CMAKE_TLS_VERSION` environment variable will be used
234 instead (see :command:`file(DOWNLOAD)`).
236 This option also applies to ``git clone`` invocations, although the
237 default behavior is different. If none of the ``TLS_VERSION`` option,
238 :variable:`CMAKE_TLS_VERSION` variable, or :envvar:`CMAKE_TLS_VERSION`
239 environment variable is specified, the behavior will be determined by
240 git's default or a ``http.sslVersion`` git config option the user may
241 have set at a global level.
243 ``TLS_VERIFY <bool>``
244 Specifies whether certificate verification should be performed for
245 ``https://`` URLs. If this option is not provided, the value of the
246 :variable:`CMAKE_TLS_VERIFY` variable or the :envvar:`CMAKE_TLS_VERIFY`
247 environment variable will be used instead (see :command:`file(DOWNLOAD)`).
248 If neither of those is set, certificate verification will not be performed.
249 In situations where ``URL_HASH`` cannot be provided, this option can
250 be an alternative verification measure.
252 This option also applies to ``git clone`` invocations, although the
253 default behavior is different. If none of the ``TLS_VERIFY`` option,
254 :variable:`CMAKE_TLS_VERIFY` variable, or :envvar:`CMAKE_TLS_VERIFY`
255 environment variable is specified, the behavior will be determined by
256 git's default (true) or a ``http.sslVerify`` git config option the
257 user may have set at a global level.
259 .. versionchanged:: 3.6
261 Previously this option did not apply to ``git clone`` invocations.
263 .. versionchanged:: 3.30
265 Previously the :envvar:`CMAKE_TLS_VERIFY` environment variable
268 ``TLS_CAINFO <file>``
269 Specify a custom certificate authority file to use if ``TLS_VERIFY``
270 is enabled. If this option is not specified, the value of the
271 :variable:`CMAKE_TLS_CAINFO` variable will be used instead (see
272 :command:`file(DOWNLOAD)`)
275 .. versionadded:: 3.11
277 Specify whether the ``.netrc`` file is to be used for operation.
278 If this option is not specified, the value of the
279 :variable:`CMAKE_NETRC` variable will be used instead
280 (see :command:`file(DOWNLOAD)`). Valid levels are:
283 The ``.netrc`` file is ignored.
286 The ``.netrc`` file is optional, and information in the URL
287 is preferred. The file will be scanned to find which ever
288 information is not specified in the URL.
290 The ``.netrc`` file is required, and information in the URL
293 ``NETRC_FILE <file>``
294 .. versionadded:: 3.11
296 Specify an alternative ``.netrc`` file to the one in your home directory
297 if the ``NETRC`` level is ``OPTIONAL`` or ``REQUIRED``. If this option
298 is not specified, the value of the :variable:`CMAKE_NETRC_FILE` variable
299 will be used instead (see :command:`file(DOWNLOAD)`)
301 .. versionadded:: 3.1
302 Added support for `tbz2`, `.tar.xz`, `.txz`, and `.7z` extensions.
307 NOTE: A git version of 1.6.5 or later is required if this download method
310 ``GIT_REPOSITORY <url>``
311 URL of the git repository. Any URL understood by the ``git`` command
314 .. versionchanged:: 3.27
315 A relative URL will be resolved based on the parent project's
316 remote, subject to :policy:`CMP0150`. See the policy documentation
317 for how the remote is selected, including conditions where the
318 remote selection can fail. Local filesystem remotes should
319 always use absolute paths.
322 Git branch name, tag or commit hash. Note that branch names and tags
323 should generally be specified as remote names (i.e. ``origin/myBranch``
324 rather than simply ``myBranch``). This ensures that if the remote end
325 has its tag moved or branch rebased or history rewritten, the local
326 clone will still be updated correctly. In general, however, specifying
327 a commit hash should be preferred for a number of reasons:
329 - If the local clone already has the commit corresponding to the hash,
330 no ``git fetch`` needs to be performed to check for changes each time
331 CMake is re-run. This can result in a significant speed up if many
332 external projects are being used.
333 - Using a specific git hash ensures that the main project's own history
334 is fully traceable to a specific point in the external project's
335 evolution. If a branch or tag name is used instead, then checking out
336 a specific commit of the main project doesn't necessarily pin the
337 whole build to a specific point in the life of the external project.
338 The lack of such deterministic behavior makes the main project lose
339 traceability and repeatability.
341 If ``GIT_SHALLOW`` is enabled then ``GIT_TAG`` works only with
342 branch names and tags. A commit hash is not allowed.
344 Note that if not provided, ``GIT_TAG`` defaults to ``master``, not the
345 default Git branch name.
347 ``GIT_REMOTE_NAME <name>``
348 The optional name of the remote. If this option is not specified, it
349 defaults to ``origin``.
351 ``GIT_SUBMODULES <module>...``
352 Specific git submodules that should also be updated. If this option is
353 not provided, all git submodules will be updated.
355 .. versionchanged:: 3.16
356 When :policy:`CMP0097` is set to ``NEW``, if this value is set
357 to an empty string then no submodules are initialized or updated.
359 ``GIT_SUBMODULES_RECURSE <bool>``
360 .. versionadded:: 3.17
362 Specify whether git submodules (if any) should update recursively by
363 passing the ``--recursive`` flag to ``git submodule update``.
364 If not specified, the default is on.
366 ``GIT_SHALLOW <bool>``
367 .. versionadded:: 3.6
369 When this option is enabled, the ``git clone`` operation will be given
370 the ``--depth 1`` option. This performs a shallow clone, which avoids
371 downloading the whole history and instead retrieves just the commit
372 denoted by the ``GIT_TAG`` option.
374 ``GIT_PROGRESS <bool>``
375 .. versionadded:: 3.8
377 When enabled, this option instructs the ``git clone`` operation to
378 report its progress by passing it the ``--progress`` option. Without
379 this option, the clone step for large projects may appear to make the
380 build stall, since nothing will be logged until the clone operation
381 finishes. While this option can be used to provide progress to prevent
382 the appearance of the build having stalled, it may also make the build
383 overly noisy if lots of external projects are used.
385 ``GIT_CONFIG <option1> [<option2>...]``
386 .. versionadded:: 3.8
388 Specify a list of config options to pass to ``git clone``. Each option
389 listed will be transformed into its own ``--config <option>`` on the
390 ``git clone`` command line, with each option required to be in the
393 ``GIT_REMOTE_UPDATE_STRATEGY <strategy>``
394 .. versionadded:: 3.18
396 When ``GIT_TAG`` refers to a remote branch, this option can be used to
397 specify how the update step behaves. The ``<strategy>`` must be one of
401 Ignore the local branch and always checkout the branch specified by
405 Try to rebase the current branch to the one specified by ``GIT_TAG``.
406 If there are local uncommitted changes, they will be stashed first
407 and popped again after rebasing. If rebasing or popping stashed
408 changes fail, abort the rebase and halt with an error.
409 When ``GIT_REMOTE_UPDATE_STRATEGY`` is not present, this is the
410 default strategy unless the default has been overridden with
411 ``CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY`` (see below).
412 Note that if the branch specified in ``GIT_TAG`` is different to
413 the upstream branch currently being tracked, it is not safe to
414 perform a rebase. In that situation, ``REBASE`` will silently be
415 treated as ``CHECKOUT`` instead.
418 Same as ``REBASE`` except if the rebase fails, an annotated tag will
419 be created at the original ``HEAD`` position from before the rebase
420 and then checkout ``GIT_TAG`` just like the ``CHECKOUT`` strategy.
421 The message stored on the annotated tag will give information about
422 what was attempted and the tag name will include a timestamp so that
423 each failed run will add a new tag. This strategy ensures no changes
424 will be lost, but updates should always succeed if ``GIT_TAG`` refers
425 to a valid ref unless there are uncommitted changes that cannot be
428 The variable ``CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY`` can be set to
429 override the default strategy. This variable should not be set by a
430 project, it is intended for the user to set. It is primarily intended
431 for use in continuous integration scripts to ensure that when history
432 is rewritten on a remote branch, the build doesn't end up with
433 unintended changes or failed builds resulting from conflicts during
439 ``SVN_REPOSITORY <url>``
440 URL of the Subversion repository.
442 ``SVN_REVISION -r<rev>``
443 Revision to checkout from the Subversion repository.
445 ``SVN_USERNAME <username>``
446 Username for the Subversion checkout and update.
448 ``SVN_PASSWORD <password>``
449 Password for the Subversion checkout and update.
451 ``SVN_TRUST_CERT <bool>``
452 Specifies whether to trust the Subversion server site certificate. If
453 enabled, the ``--trust-server-cert`` option is passed to the ``svn``
454 checkout and update commands.
459 ``HG_REPOSITORY <url>``
460 URL of the mercurial repository.
463 Mercurial branch name, tag or commit id.
468 ``CVS_REPOSITORY <cvsroot>``
469 CVSROOT of the CVS repository.
472 Module to checkout from the CVS repository.
475 Tag to checkout from the CVS repository.
480 Whenever CMake is re-run, by default the external project's sources will be
481 updated if the download method supports updates (e.g. a git repository
482 would be checked if the ``GIT_TAG`` does not refer to a specific commit).
484 ``UPDATE_COMMAND <cmd>...``
485 Overrides the download method's update step with a custom command.
487 :manual:`generator expressions <cmake-generator-expressions(7)>`.
489 ``UPDATE_DISCONNECTED <bool>``
490 .. versionadded:: 3.2
492 When enabled, this option causes the update step to be skipped (but see
493 below for changed behavior where this is not the case). It does not
494 prevent the download step. The update step can still be
495 added as a step target (see :command:`ExternalProject_Add_StepTargets`)
496 and called manually. This is useful if you want to allow developers to
497 build the project when disconnected from the network (the network may
498 still be needed for the download step though).
500 .. versionchanged:: 3.27
502 When ``UPDATE_DISCONNECTED`` is true, the update step will be executed
503 if any details about the update or download step are changed.
504 Furthermore, if using the git download/update method, the update
505 logic will be modified to skip attempts to contact the remote.
506 If the ``GIT_TAG`` mentions a ref that is not known locally, the
507 update step will halt with a fatal error.
509 When this option is present, it is generally advisable to make the value
510 a cache variable under the developer's control rather than hard-coding
511 it. If this option is not present, the default value is taken from the
512 ``EP_UPDATE_DISCONNECTED`` directory property. If that is also not
513 defined, updates are performed as normal. The ``EP_UPDATE_DISCONNECTED``
514 directory property is intended as a convenience for controlling the
515 ``UPDATE_DISCONNECTED`` behavior for an entire section of a project's
516 directory hierarchy and may be a more convenient method of giving
517 developers control over whether or not to perform updates (assuming the
518 project also provides a cache variable or some other convenient method
519 for setting the directory property).
521 This may cause a step target to be created automatically for the
522 ``download`` step. See policy :policy:`CMP0114`.
527 ``PATCH_COMMAND <cmd>...``
528 Specifies a custom command to patch the sources after an update. By
529 default, no patch command is defined. Note that it can be quite difficult
530 to define an appropriate patch command that performs robustly, especially
531 for download methods such as git where changing the ``GIT_TAG`` will not
532 discard changes from a previous patch, but the patch command will be
533 called again after updating to the new tag.
535 Configure Step Options
536 """"""""""""""""""""""
538 The configure step is run after the download and update steps. By default,
539 the external project is assumed to be a CMake project, but this can be
540 overridden if required.
542 ``CONFIGURE_COMMAND <cmd>...``
543 The default configure command runs CMake with a few options based on
544 the main project. The options added are typically only those needed to
545 use the same generator as the main project, but the ``CMAKE_GENERATOR``
546 option can be given to override this. The project is responsible for
547 adding any toolchain details, flags or other settings it wants to
548 reuse from the main project or otherwise specify (see ``CMAKE_ARGS``,
549 ``CMAKE_CACHE_ARGS`` and ``CMAKE_CACHE_DEFAULT_ARGS`` below).
551 For non-CMake external projects, the ``CONFIGURE_COMMAND`` option must
552 be used to override the default configure command
553 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
554 supported). For projects that require no configure step, specify this
555 option with an empty string as the command to execute.
557 ``CMAKE_COMMAND /.../cmake``
558 Specify an alternative cmake executable for the configure step (use an
559 absolute path). This is generally not recommended, since it is
560 usually desirable to use the same CMake version throughout the whole
561 build. This option is ignored if a custom configure command has been
562 specified with ``CONFIGURE_COMMAND``.
564 ``CMAKE_GENERATOR <gen>``
565 Override the CMake generator used for the configure step. Without this
566 option, the same generator as the main build will be used. This option is
567 ignored if a custom configure command has been specified with the
568 ``CONFIGURE_COMMAND`` option.
570 ``CMAKE_GENERATOR_PLATFORM <platform>``
571 .. versionadded:: 3.1
573 Pass a generator-specific platform name to the CMake command (see
574 :variable:`CMAKE_GENERATOR_PLATFORM`). It is an error to provide this
575 option without the ``CMAKE_GENERATOR`` option.
577 ``CMAKE_GENERATOR_TOOLSET <toolset>``
578 Pass a generator-specific toolset name to the CMake command (see
579 :variable:`CMAKE_GENERATOR_TOOLSET`). It is an error to provide this
580 option without the ``CMAKE_GENERATOR`` option.
582 ``CMAKE_GENERATOR_INSTANCE <instance>``
583 .. versionadded:: 3.11
585 Pass a generator-specific instance selection to the CMake command (see
586 :variable:`CMAKE_GENERATOR_INSTANCE`). It is an error to provide this
587 option without the ``CMAKE_GENERATOR`` option.
589 ``CMAKE_ARGS <arg>...``
590 The specified arguments are passed to the :program:`cmake` command line.
591 They can be any argument the :program:`cmake` command understands, not just
592 cache values defined by ``-D...`` arguments (see also
593 :manual:`CMake Options <cmake(1)>`).
595 .. versionadded:: 3.3
597 :manual:`generator expressions <cmake-generator-expressions(7)>`.
599 ``CMAKE_CACHE_ARGS <arg>...``
600 This is an alternate way of specifying cache variables where command line
601 length issues may become a problem. The arguments are expected to be in
602 the form ``-Dvar:STRING=value``, which are then transformed into
603 CMake :command:`set` commands with the ``FORCE`` option used. These
604 ``set()`` commands are written to a pre-load script which is then applied
605 using the :manual:`cmake -C <cmake(1)>` command line option.
607 .. versionadded:: 3.3
609 :manual:`generator expressions <cmake-generator-expressions(7)>`.
611 ``CMAKE_CACHE_DEFAULT_ARGS <arg>...``
612 .. versionadded:: 3.2
614 This is the same as the ``CMAKE_CACHE_ARGS`` option except the ``set()``
615 commands do not include the ``FORCE`` keyword. This means the values act
616 as initial defaults only and will not override any variables already set
617 from a previous run. Use this option with care, as it can lead to
618 different behavior depending on whether the build starts from a fresh
619 build directory or reuses previous build contents.
621 .. versionadded:: 3.15
622 If the CMake generator is the ``Green Hills MULTI`` and not overridden,
623 the original project's settings for the GHS toolset and target system
624 customization cache variables are propagated into the external project.
626 ``SOURCE_SUBDIR <dir>``
627 .. versionadded:: 3.7
629 When no ``CONFIGURE_COMMAND`` option is specified, the configure step
630 assumes the external project has a ``CMakeLists.txt`` file at the top of
631 its source tree (i.e. in ``SOURCE_DIR``). The ``SOURCE_SUBDIR`` option
632 can be used to point to an alternative directory within the source tree
633 to use as the top of the CMake source tree instead. This must be a
634 relative path and it will be interpreted as being relative to
637 .. versionadded:: 3.14
638 When ``BUILD_IN_SOURCE`` option is enabled, the ``BUILD_COMMAND``
639 is used to point to an alternative directory within the source tree.
641 ``CONFIGURE_HANDLED_BY_BUILD <bool>``
642 .. versionadded:: 3.20
644 Enabling this option relaxes the dependencies of the configure step on
645 other external projects to order-only. This means the configure step will
646 be executed after its external project dependencies are built but it will
647 not be marked dirty when one of its external project dependencies is
648 rebuilt. This option can be enabled when the build step is smart enough
649 to figure out if the configure step needs to be rerun. CMake and Meson are
650 examples of build systems whose build step is smart enough to know if the
651 configure step needs to be rerun.
656 If the configure step assumed the external project uses CMake as its build
657 system, the build step will also. Otherwise, the build step will assume a
658 Makefile-based build and simply run ``make`` with no arguments as the
659 default build step. This can be overridden with custom build commands if
662 If both the main project and the external project use make as their build
663 tool, the build step of the external project is invoked as a recursive
664 make using ``$(MAKE)``. This will communicate some build tool settings
665 from the main project to the external project. If either the main project
666 or external project is not using make, no build tool settings will be
667 passed to the external project other than those established by the
668 configure step (i.e. running ``ninja -v`` in the main project will not
669 pass ``-v`` to the external project's build step, even if it also uses
670 ``ninja`` as its build tool).
672 ``BUILD_COMMAND <cmd>...``
673 Overrides the default build command
674 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
675 supported). If this option is not given, the default build command will
676 be chosen to integrate with the main build in the most appropriate way
677 (e.g. using recursive ``make`` for Makefile generators or
678 :option:`cmake --build` if the project uses a CMake build). This option
679 can be specified with an empty string as the command to make the build
682 ``BUILD_IN_SOURCE <bool>``
683 When this option is enabled, the build will be done directly within the
684 external project's source tree. This should generally be avoided, the use
685 of a separate build directory is usually preferred, but it can be useful
686 when the external project assumes an in-source build. The ``BINARY_DIR``
687 option should not be specified if building in-source.
689 ``BUILD_ALWAYS <bool>``
690 Enabling this option forces the build step to always be run. This can be
691 the easiest way to robustly ensure that the external project's own build
692 dependencies are evaluated rather than relying on the default
693 success timestamp-based method. This option is not normally needed unless
694 developers are expected to modify something the external project's build
695 depends on in a way that is not detectable via the step target
696 dependencies (e.g. ``SOURCE_DIR`` is used without a download method and
697 developers might modify the sources in ``SOURCE_DIR``).
699 ``BUILD_BYPRODUCTS <file>...``
700 .. versionadded:: 3.2
702 Specifies files that will be generated by the build command but which
703 might or might not have their modification time updated by subsequent
704 builds. This may also be required to explicitly declare dependencies
705 when using the :generator:`Ninja` generator.
706 These ultimately get passed through as ``BYPRODUCTS`` to the
707 build step's own underlying call to :command:`add_custom_command`, which
708 has additional documentation.
710 ``BUILD_JOB_SERVER_AWARE <bool>``
711 .. versionadded:: 3.28
713 Specifies that the build step is aware of the GNU Make job server.
714 See the :command:`add_custom_command` documentation of its
715 ``JOB_SERVER_AWARE`` option for details. This option is relevant
716 only when an explicit ``BUILD_COMMAND`` is specified.
721 If the configure step assumed the external project uses CMake as its build
722 system, the install step will also. Otherwise, the install step will assume
723 a Makefile-based build and simply run ``make install`` as the default build
724 step. This can be overridden with custom install commands if required.
726 ``INSTALL_COMMAND <cmd>...``
727 The external project's own install step is invoked as part of the main
728 project's *build*. It is done after the external project's build step
729 and may be before or after the external project's test step (see the
730 ``TEST_BEFORE_INSTALL`` option below). The external project's install
731 rules are not part of the main project's install rules, so if anything
732 from the external project should be installed as part of the main build,
733 these need to be specified in the main build as additional
734 :command:`install` commands. The default install step builds the
735 ``install`` target of the external project, but this can be overridden
736 with a custom command using this option
737 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
738 supported). Passing an empty string as the ``<cmd>`` makes the install
741 ``INSTALL_BYPRODUCTS <file>...``
742 .. versionadded:: 3.26
744 Specifies files that will be generated by the install command but which
745 might or might not have their modification time updated by subsequent
746 installs. This may also be required to explicitly declare dependencies
747 when using the :generator:`Ninja` generator.
748 These ultimately get passed through as ``BYPRODUCTS`` to the
749 install step's own underlying call to :command:`add_custom_command`, which
750 has additional documentation.
752 ``INSTALL_JOB_SERVER_AWARE <bool>``
753 .. versionadded:: 4.0
755 Specifies that the install step is aware of the GNU Make job server.
756 See the :command:`add_custom_command` documentation of its
757 ``JOB_SERVER_AWARE`` option for details. This option is relevant
758 only when an explicit ``INSTALL_COMMAND`` is specified.
761 If the :envvar:`CMAKE_INSTALL_MODE` environment variable is set when the
762 main project is built, it will only have an effect if the following
765 * The main project's configure step assumed the external project uses
766 CMake as its build system.
767 * The external project's install command actually runs. Note that due
768 to the way ``ExternalProject`` may use timestamps internally, if
769 nothing the install step depends on needs to be re-executed, the
770 install command might also not need to run.
772 Note also that ``ExternalProject`` does not check whether the
773 :envvar:`CMAKE_INSTALL_MODE` environment variable changes from one run
779 The test step is only defined if at least one of the following ``TEST_...``
780 options are provided.
782 ``TEST_COMMAND <cmd>...``
783 Overrides the default test command
784 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
785 supported). If this option is not given, the default behavior of the test
786 step is to build the external project's own ``test`` target. This option
787 can be specified with ``<cmd>`` as an empty string, which allows the test
788 step to still be defined, but it will do nothing. Do not specify any of
789 the other ``TEST_...`` options if providing an empty string as the test
790 command, but prefer to omit all ``TEST_...`` options altogether if the
791 test step target is not needed.
793 ``TEST_BEFORE_INSTALL <bool>``
794 When this option is enabled, the test step will be executed before the
795 install step. The default behavior is for the test step to run after the
798 ``TEST_AFTER_INSTALL <bool>``
799 This option is mainly useful as a way to indicate that the test step is
800 desired but all default behavior is sufficient. Specifying this option
801 with a boolean true value ensures the test step is defined and that it
802 comes after the install step. If both ``TEST_BEFORE_INSTALL`` and
803 ``TEST_AFTER_INSTALL`` are enabled, the latter is silently ignored.
805 ``TEST_EXCLUDE_FROM_MAIN <bool>``
806 .. versionadded:: 3.2
808 If enabled, the main build's default ALL target will not depend on the
809 test step. This can be a useful way of ensuring the test step is defined
810 but only gets invoked when manually requested.
811 This may cause a step target to be created automatically for either
812 the ``install`` or ``build`` step. See policy :policy:`CMP0114`.
814 Output Logging Options
815 """"""""""""""""""""""
817 Each of the following ``LOG_...`` options can be used to wrap the relevant
818 step in a script to capture its output to files. The log files will be
819 created in ``LOG_DIR`` if supplied or otherwise the ``STAMP_DIR``
820 directory with step-specific file names.
822 ``LOG_DOWNLOAD <bool>``
823 When enabled, the output of the download step is logged to files.
825 ``LOG_UPDATE <bool>``
826 When enabled, the output of the update step is logged to files.
829 .. versionadded:: 3.14
831 When enabled, the output of the patch step is logged to files.
833 ``LOG_CONFIGURE <bool>``
834 When enabled, the output of the configure step is logged to files.
837 When enabled, the output of the build step is logged to files.
839 ``LOG_INSTALL <bool>``
840 When enabled, the output of the install step is logged to files.
843 When enabled, the output of the test step is logged to files.
845 ``LOG_MERGED_STDOUTERR <bool>``
846 .. versionadded:: 3.14
848 When enabled, stdout and stderr will be merged for any step whose
849 output is being logged to files.
851 ``LOG_OUTPUT_ON_FAILURE <bool>``
852 .. versionadded:: 3.14
854 This option only has an effect if at least one of the other ``LOG_<step>``
855 options is enabled. If an error occurs for a step which has logging to
856 file enabled, that step's output will be printed to the console if
857 ``LOG_OUTPUT_ON_FAILURE`` is set to true. For cases where a large amount
858 of output is recorded, just the end of that output may be printed to the
861 Terminal Access Options
862 """""""""""""""""""""""
864 .. versionadded:: 3.4
866 Steps can be given direct access to the terminal in some cases. Giving a
867 step access to the terminal may allow it to receive terminal input if
868 required, such as for authentication details not provided by other options.
869 With the :generator:`Ninja` generator, these options place the steps in the
870 ``console`` :prop_gbl:`job pool <JOB_POOLS>`. Each step can be given access
871 to the terminal individually via the following options:
873 ``USES_TERMINAL_DOWNLOAD <bool>``
874 Give the download step access to the terminal.
876 ``USES_TERMINAL_UPDATE <bool>``
877 Give the update step access to the terminal.
879 ``USES_TERMINAL_PATCH <bool>``
880 .. versionadded:: 3.23
882 Give the patch step access to the terminal.
884 ``USES_TERMINAL_CONFIGURE <bool>``
885 Give the configure step access to the terminal.
887 ``USES_TERMINAL_BUILD <bool>``
888 Give the build step access to the terminal.
890 ``USES_TERMINAL_INSTALL <bool>``
891 Give the install step access to the terminal.
893 ``USES_TERMINAL_TEST <bool>``
894 Give the test step access to the terminal.
899 ``DEPENDS <targets>...``
900 Specify other targets on which the external project depends. The other
901 targets will be brought up to date before any of the external project's
902 steps are executed. Because the external project uses additional custom
903 targets internally for each step, the ``DEPENDS`` option is the most
904 convenient way to ensure all of those steps depend on the other targets.
906 :command:`add_dependencies(\<name\> \<targets\>) <add_dependencies>` will
907 not make any of the steps dependent on ``<targets>``.
909 ``EXCLUDE_FROM_ALL <bool>``
910 When enabled, this option excludes the external project from the default
911 ALL target of the main build.
913 ``STEP_TARGETS <step-target>...``
914 Generate custom targets for the specified steps. This is required if the
915 steps need to be triggered manually or if they need to be used as
916 dependencies of other targets. If this option is not specified, the
917 default value is taken from the ``EP_STEP_TARGETS`` directory property.
918 See :command:`ExternalProject_Add_StepTargets` below for further
919 discussion of the effects of this option.
921 ``INDEPENDENT_STEP_TARGETS <step-target>...``
923 This is allowed only if policy :policy:`CMP0114` is not set to ``NEW``.
925 Generates custom targets for the specified steps and prevent these targets
926 from having the usual dependencies applied to them. If this option is not
927 specified, the default value is taken from the
928 ``EP_INDEPENDENT_STEP_TARGETS`` directory property. This option is mostly
929 useful for allowing individual steps to be driven independently, such as
930 for a CDash setup where each step should be initiated and reported
931 individually rather than as one whole build. See
932 :command:`ExternalProject_Add_StepTargets` below for further discussion
933 of the effects of this option.
935 Miscellaneous Options
936 """""""""""""""""""""
938 ``LIST_SEPARATOR <sep>``
939 For any of the various ``..._COMMAND`` options, and ``CMAKE_ARGS``,
940 ``ExternalProject`` will replace ``<sep>`` with ``;`` in the specified
941 command lines. This can be used to ensure a command has a literal ``;`` in it
942 where direct usage would otherwise be interpreted as argument separators to
943 CMake APIs instead. Note that the separator should be chosen to avoid being
944 confused for non-list-separator usages of the sequence. For example, using
945 ``LIST_SEPARATOR`` allows for passing list values to CMake cache variables on
948 .. code-block:: cmake
950 ExternalProject_Add(example
951 ... # Download options, etc.
953 CMAKE_ARGS "-DCMAKE_PREFIX_PATH:STRING=${first_prefix},${second_prefix}"
957 Any of the other ``..._COMMAND`` options can have additional commands
958 appended to them by following them with as many ``COMMAND ...`` options
960 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
961 supported). For example:
963 .. code-block:: cmake
965 ExternalProject_Add(example
966 ... # Download options, etc.
967 BUILD_COMMAND ${CMAKE_COMMAND} -E echo "Starting $<CONFIG> build"
968 COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --config $<CONFIG>
969 COMMAND ${CMAKE_COMMAND} -E echo "$<CONFIG> build complete"
972 It should also be noted that each build step is created via a call to
973 :command:`ExternalProject_Add_Step`. See that command's documentation for the
974 automatic substitutions that are supported for some options.
976 Obtaining Project Properties
977 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
979 .. command:: ExternalProject_Get_Property
981 The ``ExternalProject_Get_Property()`` function retrieves external project
984 .. code-block:: cmake
986 ExternalProject_Get_Property(<name> <prop1> [<prop2>...])
988 The function stores property values in variables of the same name. Property
989 names correspond to the keyword argument names of ``ExternalProject_Add()``.
990 For example, the source directory might be retrieved like so:
992 .. code-block:: cmake
994 ExternalProject_Get_property(myExtProj SOURCE_DIR)
995 message("Source dir of myExtProj = ${SOURCE_DIR}")
997 Explicit Step Management
998 ^^^^^^^^^^^^^^^^^^^^^^^^
1000 The ``ExternalProject_Add()`` function on its own is often sufficient for
1001 incorporating an external project into the main build. Certain scenarios
1002 require additional work to implement desired behavior, such as adding in a
1003 custom step or making steps available as manually triggerable targets. The
1004 ``ExternalProject_Add_Step()``, ``ExternalProject_Add_StepTargets()`` and
1005 ``ExternalProject_Add_StepDependencies`` functions provide the lower level
1006 control needed to implement such step-level capabilities.
1008 .. command:: ExternalProject_Add_Step
1010 The ``ExternalProject_Add_Step()`` function specifies an additional custom
1011 step for an external project defined by an earlier call to
1012 :command:`ExternalProject_Add`:
1014 .. code-block:: cmake
1016 ExternalProject_Add_Step(<name> <step> [<option>...])
1018 ``<name>`` is the same as the name passed to the original call to
1019 :command:`ExternalProject_Add`. The specified ``<step>`` must not be one of
1020 the pre-defined steps (``mkdir``, ``download``, ``update``,
1021 ``patch``, ``configure``, ``build``, ``install`` or ``test``). The supported
1024 ``COMMAND <cmd>...``
1025 The command line to be executed by this custom step
1026 (:manual:`generator expressions <cmake-generator-expressions(7)>` are
1027 supported). This option can be repeated multiple times to specify multiple
1028 commands to be executed in order.
1030 ``COMMENT "<text>..."``
1031 Text to be printed when the custom step executes.
1033 ``DEPENDEES <step>...``
1034 Other steps (custom or pre-defined) on which this step depends.
1036 ``DEPENDERS <step>...``
1037 Other steps (custom or pre-defined) that depend on this new custom step.
1039 ``DEPENDS <file>...``
1040 Files on which this custom step depends.
1042 ``INDEPENDENT <bool>``
1043 .. versionadded:: 3.19
1045 Specifies whether this step is independent of the external dependencies
1046 specified by the :command:`ExternalProject_Add`'s ``DEPENDS`` option.
1047 The default is ``FALSE``. Steps marked as independent may depend only
1048 on other steps marked independent. See policy :policy:`CMP0114`.
1050 Note that this use of the term "independent" refers only to independence
1051 from external targets specified by the ``DEPENDS`` option and is
1052 orthogonal to a step's dependencies on other steps.
1054 If a step target is created for an independent step by the
1055 :command:`ExternalProject_Add` ``STEP_TARGETS`` option or by the
1056 :command:`ExternalProject_Add_StepTargets` function, it will not depend
1057 on the external targets, but may depend on targets for other steps.
1059 ``BYPRODUCTS <file>...``
1060 .. versionadded:: 3.2
1062 Files that will be generated by this custom step but which might or might
1063 not have their modification time updated by subsequent builds.
1064 This may also be required to explicitly declare dependencies
1065 when using the :generator:`Ninja` generator. This list of
1066 files will ultimately be passed through as the ``BYPRODUCTS`` option to the
1067 :command:`add_custom_command` used to implement the custom step internally,
1068 which has additional documentation.
1071 When enabled, this option specifies that the custom step should always be
1072 run (i.e. that it is always considered out of date).
1074 ``JOB_SERVER_AWARE <bool>``
1075 .. versionadded:: 3.28
1077 Specifies that the custom step is aware of the GNU Make job server.
1078 See the :command:`add_custom_command` documentation of its
1079 ``JOB_SERVER_AWARE`` option for details.
1081 ``EXCLUDE_FROM_MAIN <bool>``
1082 When enabled, this option specifies that the external project's main target
1083 does not depend on the custom step.
1084 This may cause step targets to be created automatically for the steps on
1085 which this step depends. See policy :policy:`CMP0114`.
1087 ``WORKING_DIRECTORY <dir>``
1088 Specifies the working directory to set before running the custom step's
1089 command. If this option is not specified, the directory will be the value
1090 of the :variable:`CMAKE_CURRENT_BINARY_DIR` at the point where
1091 ``ExternalProject_Add_Step()`` was called.
1094 If set, this causes the output from the custom step to be captured to files
1095 in the external project's ``LOG_DIR`` if supplied or ``STAMP_DIR``.
1097 ``USES_TERMINAL <bool>``
1098 If enabled, this gives the custom step direct access to the terminal if
1101 The command line, comment, working directory and byproducts of every
1102 standard and custom step are processed to replace the tokens
1103 ``<SOURCE_DIR>``, ``<SOURCE_SUBDIR>``, ``<BINARY_DIR>``, ``<INSTALL_DIR>``
1104 ``<TMP_DIR>``, ``<DOWNLOAD_DIR>`` and ``<DOWNLOADED_FILE>`` with their
1105 corresponding property values defined in the original call to
1106 :command:`ExternalProject_Add`.
1108 .. versionadded:: 3.3
1109 Token replacement is extended to byproducts.
1111 .. versionadded:: 3.11
1112 The ``<DOWNLOAD_DIR>`` substitution token.
1114 .. command:: ExternalProject_Add_StepTargets
1116 The ``ExternalProject_Add_StepTargets()`` function generates targets for the
1117 steps listed. The name of each created target will be of the form
1120 .. code-block:: cmake
1122 ExternalProject_Add_StepTargets(<name> <step1> [<step2>...])
1124 Creating a target for a step allows it to be used as a dependency of another
1125 target or to be triggered manually. Having targets for specific steps also
1126 allows them to be driven independently of each other by specifying targets on
1127 build command lines. For example, you may be submitting to a sub-project
1128 based dashboard where you want to drive the configure portion of the build,
1129 then submit to the dashboard, followed by the build portion, followed
1130 by tests. If you invoke a custom target that depends on a step halfway
1131 through the step dependency chain, then all the previous steps will also run
1132 to ensure everything is up to date.
1134 Internally, :command:`ExternalProject_Add` calls
1135 :command:`ExternalProject_Add_Step` to create each step. If any
1136 ``STEP_TARGETS`` were specified, then ``ExternalProject_Add_StepTargets()``
1137 will also be called after :command:`ExternalProject_Add_Step`. Even if a
1138 step is not mentioned in the ``STEP_TARGETS`` option,
1139 ``ExternalProject_Add_StepTargets()`` can still be called later to manually
1140 define a target for the step.
1142 The ``STEP_TARGETS`` option for :command:`ExternalProject_Add` is generally
1143 the easiest way to ensure targets are created for specific steps of interest.
1144 For custom steps, ``ExternalProject_Add_StepTargets()`` must be called
1145 explicitly if a target should also be created for that custom step.
1146 An alternative to these two options is to populate the ``EP_STEP_TARGETS``
1147 directory property. It acts as a default for the step target options and
1148 can save having to repeatedly specify the same set of step targets when
1149 multiple external projects are being defined.
1151 .. versionadded:: 3.19
1152 If :policy:`CMP0114` is set to ``NEW``, step targets are fully responsible
1153 for holding the custom commands implementing their steps. The primary
1154 target created by ``ExternalProject_Add`` depends on the step targets, and
1155 the step targets depend on each other. The target-level dependencies match
1156 the file-level dependencies used by the custom commands for each step.
1157 The targets for steps created with :command:`ExternalProject_Add_Step`'s
1158 ``INDEPENDENT`` option do not depend on the external targets specified
1159 by :command:`ExternalProject_Add`'s ``DEPENDS`` option. The predefined
1160 steps ``mkdir``, ``download``, ``update``, and ``patch`` are independent.
1162 If :policy:`CMP0114` is not ``NEW``, the following deprecated behavior
1165 * A deprecated ``NO_DEPENDS`` option may be specified immediately after the
1166 ``<name>`` and before the first step.
1167 If the ``NO_DEPENDS`` option is specified, the step target will not depend
1168 on the dependencies of the external project (i.e. on any dependencies of the
1169 ``<name>`` custom target created by :command:`ExternalProject_Add`). This is
1170 usually safe for the ``download``, ``update`` and ``patch`` steps, since
1171 they do not typically require that the dependencies are updated and built.
1172 Using ``NO_DEPENDS`` for any of the other pre-defined steps, however, may
1173 break parallel builds. Only use ``NO_DEPENDS`` where it is certain that the
1174 named steps genuinely do not have dependencies. For custom steps, consider
1175 whether or not the custom commands require the dependencies to be
1176 configured, built and installed.
1178 * The ``INDEPENDENT_STEP_TARGETS`` option for :command:`ExternalProject_Add`,
1179 or the ``EP_INDEPENDENT_STEP_TARGETS`` directory property, tells the
1180 function to call ``ExternalProject_Add_StepTargets()`` internally
1181 using the ``NO_DEPENDS`` option for the specified steps.
1183 .. command:: ExternalProject_Add_StepDependencies
1185 .. versionadded:: 3.2
1187 The ``ExternalProject_Add_StepDependencies()`` function can be used to add
1188 dependencies to a step. The dependencies added must be targets CMake already
1189 knows about (these can be ordinary executable or library targets, custom
1190 targets or even step targets of another external project):
1192 .. code-block:: cmake
1194 ExternalProject_Add_StepDependencies(<name> <step> <target1> [<target2>...])
1196 This function takes care to set both target and file level dependencies and
1197 will ensure that parallel builds will not break. It should be used instead of
1198 :command:`add_dependencies` whenever adding a dependency for some of the step
1199 targets generated by the ``ExternalProject`` module.
1204 The following example shows how to download and build a hypothetical project
1205 called *FooBar* from github:
1207 .. code-block:: cmake
1209 include(ExternalProject)
1210 ExternalProject_Add(foobar
1211 GIT_REPOSITORY git@github.com:FooCo/FooBar.git
1212 GIT_TAG origin/release/1.2.3
1215 For the sake of the example, also define a second hypothetical external project
1216 called *SecretSauce*, which is downloaded from a web server. Two URLs are given
1217 to take advantage of a faster internal network if available, with a fallback to
1218 a slower external server. The project is a typical ``Makefile`` project with no
1219 configure step, so some of the default commands are overridden. The build is
1220 only required to build the *sauce* target:
1222 .. code-block:: cmake
1224 find_program(MAKE_EXE NAMES gmake nmake make)
1225 ExternalProject_Add(secretsauce
1226 URL http://intranet.somecompany.com/artifacts/sauce-2.7.tgz
1227 https://www.somecompany.com/downloads/sauce-2.7.zip
1228 URL_HASH MD5=d41d8cd98f00b204e9800998ecf8427e
1229 CONFIGURE_COMMAND ""
1230 BUILD_COMMAND ${MAKE_EXE} sauce
1233 Suppose the build step of ``secretsauce`` requires that ``foobar`` must already
1234 be built. This could be enforced like so:
1236 .. code-block:: cmake
1238 ExternalProject_Add_StepDependencies(secretsauce build foobar)
1240 Another alternative would be to create a custom target for ``foobar``'s build
1241 step and make ``secretsauce`` depend on that rather than the whole ``foobar``
1242 project. This would mean ``foobar`` only needs to be built, it doesn't need to
1243 run its install or test steps before ``secretsauce`` can be built. The
1244 dependency can also be defined along with the ``secretsauce`` project:
1246 .. code-block:: cmake
1248 ExternalProject_Add_StepTargets(foobar build)
1249 ExternalProject_Add(secretsauce
1250 URL http://intranet.somecompany.com/artifacts/sauce-2.7.tgz
1251 https://www.somecompany.com/downloads/sauce-2.7.zip
1252 URL_HASH MD5=d41d8cd98f00b204e9800998ecf8427e
1253 CONFIGURE_COMMAND ""
1254 BUILD_COMMAND ${MAKE_EXE} sauce
1255 DEPENDS foobar-build
1258 Instead of calling :command:`ExternalProject_Add_StepTargets`, the target could
1259 be defined along with the ``foobar`` project itself:
1261 .. code-block:: cmake
1263 ExternalProject_Add(foobar
1264 GIT_REPOSITORY git@github.com:FooCo/FooBar.git
1265 GIT_TAG origin/release/1.2.3
1269 If many external projects should have the same set of step targets, setting a
1270 directory property may be more convenient. The ``build`` step target could be
1271 created automatically by setting the ``EP_STEP_TARGETS`` directory property
1272 before creating the external projects with :command:`ExternalProject_Add`:
1274 .. code-block:: cmake
1276 set_property(DIRECTORY PROPERTY EP_STEP_TARGETS build)
1278 Lastly, suppose that ``secretsauce`` provides a script called ``makedoc`` which
1279 can be used to generate its own documentation. Further suppose that the script
1280 expects the output directory to be provided as the only parameter and that it
1281 should be run from the ``secretsauce`` source directory. A custom step and a
1282 custom target to trigger the script can be defined like so:
1284 .. code-block:: cmake
1286 ExternalProject_Add_Step(secretsauce docs
1287 COMMAND <SOURCE_DIR>/makedoc <BINARY_DIR>
1288 WORKING_DIRECTORY <SOURCE_DIR>
1289 COMMENT "Building secretsauce docs"
1291 EXCLUDE_FROM_MAIN TRUE
1293 ExternalProject_Add_StepTargets(secretsauce docs)
1295 The custom step could then be triggered from the main build like so::
1297 cmake --build . --target secretsauce-docs
1299 #]=======================================================================]
1301 include(${CMAKE_CURRENT_LIST_DIR}/ExternalProject/shared_internal_commands.cmake)
1303 define_property(DIRECTORY PROPERTY "EP_BASE" INHERITED)
1304 define_property(DIRECTORY PROPERTY "EP_PREFIX" INHERITED)
1305 define_property(DIRECTORY PROPERTY "EP_STEP_TARGETS" INHERITED)
1306 define_property(DIRECTORY PROPERTY "EP_INDEPENDENT_STEP_TARGETS" INHERITED)
1307 define_property(DIRECTORY PROPERTY "EP_UPDATE_DISCONNECTED" INHERITED)
1309 # file(TO_CMAKE_PATH) will interpret a platform-specific character as a path
1310 # separator, and if its input contains that character, it will treat the input
1311 # as a list. Sometimes we have a string that we know is always a single path,
1312 # but it may contain the separator character. To prevent it being treated as a
1313 # list of paths, this function masks the separator character while calling
1314 # file(TO_CMAKE_PATH).
1315 function(_ep_to_single_cmake_path out_var input)
1317 set(unsafe_char ";")
1319 set(unsafe_char ":")
1322 string(REPLACE "${unsafe_char}" "__EP_MARKER__" safe_input "${input}")
1323 file(TO_CMAKE_PATH "${safe_input}" converted_input)
1324 string(REPLACE "__EP_MARKER__" "${unsafe_char}" output "${converted_input}")
1326 set(${out_var} "${output}" PARENT_SCOPE)
1329 function(_ep_set_directories name)
1330 get_property(prefix TARGET ${name} PROPERTY _EP_PREFIX)
1332 get_property(prefix DIRECTORY PROPERTY EP_PREFIX)
1334 get_property(base DIRECTORY PROPERTY EP_BASE)
1336 set(prefix "${name}-prefix")
1341 _ep_to_single_cmake_path(prefix "${prefix}")
1342 set(tmp_default "${prefix}/tmp")
1343 set(download_default "${prefix}/src")
1344 set(source_default "${prefix}/src/${name}")
1345 set(binary_default "${prefix}/src/${name}-build")
1346 set(stamp_default "${prefix}/src/${name}-stamp")
1347 set(install_default "${prefix}")
1349 _ep_to_single_cmake_path(base "${base}")
1350 set(tmp_default "${base}/tmp/${name}")
1351 set(download_default "${base}/Download/${name}")
1352 set(source_default "${base}/Source/${name}")
1353 set(binary_default "${base}/Build/${name}")
1354 set(stamp_default "${base}/Stamp/${name}")
1355 set(install_default "${base}/Install/${name}")
1357 get_property(build_in_source TARGET ${name} PROPERTY _EP_BUILD_IN_SOURCE)
1359 get_property(have_binary_dir TARGET ${name} PROPERTY _EP_BINARY_DIR SET)
1362 "External project ${name} has both BINARY_DIR and BUILD_IN_SOURCE!"
1366 set(top "${CMAKE_CURRENT_BINARY_DIR}")
1368 # Apply defaults and convert to absolute paths.
1369 set(places stamp download source binary install tmp)
1370 foreach(var IN LISTS places)
1371 string(TOUPPER "${var}" VAR)
1372 get_property(${var}_dir TARGET ${name} PROPERTY _EP_${VAR}_DIR)
1374 set(${var}_dir "${${var}_default}")
1376 if(NOT IS_ABSOLUTE "${${var}_dir}")
1377 get_filename_component(${var}_dir "${top}/${${var}_dir}" ABSOLUTE)
1379 _ep_to_single_cmake_path(${var}_dir "${${var}_dir}")
1380 set_property(TARGET ${name} PROPERTY _EP_${VAR}_DIR "${${var}_dir}")
1381 set(_EP_${VAR}_DIR "${${var}_dir}" PARENT_SCOPE)
1384 # Special case for default log directory based on stamp directory.
1385 get_property(log_dir TARGET ${name} PROPERTY _EP_LOG_DIR)
1387 get_property(log_dir TARGET ${name} PROPERTY _EP_STAMP_DIR)
1389 if(NOT IS_ABSOLUTE "${log_dir}")
1390 get_filename_component(log_dir "${top}/${log_dir}" ABSOLUTE)
1392 _ep_to_single_cmake_path(log_dir "${log_dir}")
1393 set_property(TARGET ${name} PROPERTY _EP_LOG_DIR "${log_dir}")
1394 set(_EP_LOG_DIR "${log_dir}" PARENT_SCOPE)
1396 get_property(source_subdir TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR)
1397 if(NOT source_subdir)
1398 set_property(TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR "")
1399 set(_EP_SOURCE_SUBDIR "" PARENT_SCOPE)
1400 elseif(IS_ABSOLUTE "${source_subdir}")
1402 "External project ${name} has non-relative SOURCE_SUBDIR!"
1405 # Prefix with a slash so that when appended to the source directory, it
1406 # behaves as expected.
1407 _ep_to_single_cmake_path(source_subdir "${source_subdir}")
1408 set_property(TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR "/${source_subdir}")
1409 set(_EP_SOURCE_SUBDIR "/${source_subdir}" PARENT_SCOPE)
1412 get_property(source_dir TARGET ${name} PROPERTY _EP_SOURCE_DIR)
1414 set_property(TARGET ${name} PROPERTY
1415 _EP_BINARY_DIR "${source_dir}/${source_subdir}"
1417 set(_EP_BINARY_DIR "${source_dir}/${source_subdir}" PARENT_SCOPE)
1419 set_property(TARGET ${name} PROPERTY
1420 _EP_BINARY_DIR "${source_dir}"
1422 set(_EP_BINARY_DIR "${source_dir}" PARENT_SCOPE)
1426 # This script will be used both here and by the mkdir step. We create the
1427 # directories now at configure time and ensure they exist again at build
1428 # time (since somebody might remove one of the required directories and try
1429 # to rebuild without re-running cmake). They need to exist now at makefile
1430 # generation time for Borland make and wmake so that CMake may generate
1431 # makefiles with "cd C:\short\paths\with\no\spaces" commands in them.
1432 set(script_filename "${tmp_dir}/${name}-mkdirs.cmake")
1434 ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/mkdirs.cmake.in
1438 unset(cfgdir) # do not leak into mkdirs.cmake script
1439 include(${script_filename})
1443 # IMPORTANT: this MUST be a macro and not a function because of the
1444 # in-place replacements that occur in each ${var}
1446 macro(_ep_replace_location_tags target_name)
1448 foreach(var IN LISTS vars)
1450 foreach(dir IN ITEMS
1460 get_property(val TARGET ${target_name} PROPERTY _EP_${dir})
1461 string(REPLACE "<${dir}>" "${val}" ${var} "${${var}}")
1468 function(_ep_command_line_to_initial_cache
1473 set(script_initial_cache "")
1474 set(regex "^([^:]+):([^=]+)=(.*)$")
1478 set(forceArg "FORCE")
1480 foreach(line IN LISTS args)
1481 if("${line}" MATCHES "^-D(.*)")
1482 set(line "${CMAKE_MATCH_1}")
1483 if(NOT "${setArg}" STREQUAL "")
1484 # This is required to build up lists in variables, or complete an entry
1485 string(APPEND setArg
1486 "${accumulator}\" CACHE ${type} \"Initial cache\" ${forceArg})"
1488 string(APPEND script_initial_cache "\n${setArg}")
1492 if("${line}" MATCHES "${regex}")
1493 set(name "${CMAKE_MATCH_1}")
1494 set(type "${CMAKE_MATCH_2}")
1495 set(value "${CMAKE_MATCH_3}")
1496 set(setArg "set(${name} \"${value}")
1498 message(WARNING "Line '${line}' does not match regex. Ignoring.")
1501 # Assume this is a list to append to the last var
1502 string(APPEND accumulator ";${line}")
1505 # Catch the final line of the args
1506 if(NOT "${setArg}" STREQUAL "")
1507 string(APPEND setArg
1508 "${accumulator}\" CACHE ${type} \"Initial cache\" ${forceArg})"
1510 string(APPEND script_initial_cache "\n${setArg}")
1512 set(${var} ${script_initial_cache} PARENT_SCOPE)
1516 function(_ep_write_initial_cache
1519 script_initial_cache
1521 # Write out values into an initial cache, that will be passed to CMake with -C
1522 # Replace location tags.
1523 _ep_replace_location_tags(${target_name} script_initial_cache)
1524 _ep_replace_location_tags(${target_name} script_filename)
1525 # Replace list separators.
1526 get_property(sep TARGET ${target_name} PROPERTY _EP_LIST_SEPARATOR)
1527 if(sep AND script_initial_cache)
1528 string(REPLACE "${sep}" ";" script_initial_cache "${script_initial_cache}")
1530 # Write out the initial cache file to the location specified.
1531 file(GENERATE OUTPUT "${script_filename}" CONTENT "${script_initial_cache}")
1535 function(ExternalProject_Get_Property name)
1536 foreach(var IN LISTS ARGN)
1537 string(TOUPPER "${var}" VAR)
1538 get_property(is_set TARGET ${name} PROPERTY _EP_${VAR} SET)
1540 message(FATAL_ERROR "External project \"${name}\" has no ${var}")
1542 get_property(${var} TARGET ${name} PROPERTY _EP_${VAR})
1543 set(${var} "${${var}}" PARENT_SCOPE)
1548 function(_ep_get_configure_command_id
1552 get_target_property(cmd ${name} _EP_CONFIGURE_COMMAND)
1555 # Explicit empty string means no configure step for this project
1556 set(${cfg_cmd_id_var} "none" PARENT_SCOPE)
1559 # Default is "use cmake":
1560 set(${cfg_cmd_id_var} "cmake" PARENT_SCOPE)
1562 # Otherwise we have to analyze the value:
1563 if(cmd MATCHES "^[^;]*/configure")
1564 set(${cfg_cmd_id_var} "configure" PARENT_SCOPE)
1565 elseif(cmd MATCHES "^[^;]*/cmake" AND NOT cmd MATCHES ";-[PE];")
1566 set(${cfg_cmd_id_var} "cmake" PARENT_SCOPE)
1567 elseif(cmd MATCHES "config")
1568 set(${cfg_cmd_id_var} "configure" PARENT_SCOPE)
1570 set(${cfg_cmd_id_var} "unknown:${cmd}" PARENT_SCOPE)
1577 function(_ep_get_build_command
1584 _ep_get_configure_command_id(${name} cfg_cmd_id)
1585 if(cfg_cmd_id STREQUAL "cmake")
1586 # Adding a CMake project as an External Project. Select command based on generator
1587 get_property(cmake_generator TARGET ${name} PROPERTY _EP_CMAKE_GENERATOR)
1588 # cmake_generator is the CMake generator of the ExternalProject target being added
1589 # CMAKE_GENERATOR is the CMake generator of the Current Project
1590 if("${CMAKE_GENERATOR}" MATCHES "Make" AND
1591 ("${cmake_generator}" MATCHES "Make" OR NOT cmake_generator))
1592 # The project uses the same Makefile generator. Use recursive make.
1594 if(step STREQUAL "INSTALL")
1597 if("x${step}x" STREQUAL "xTESTx")
1601 # Drive the project with "cmake --build".
1602 if(NOT cmake_generator)
1603 # If there is no CMake Generator defined on the ExternalProject,
1604 # use the same Generator as the current project
1605 set(cmake_generator "${CMAKE_GENERATOR}")
1607 get_target_property(cmake_command ${name} _EP_CMAKE_COMMAND)
1609 set(cmd "${cmake_command}")
1611 set(cmd "${CMAKE_COMMAND}")
1613 set(args --build ".")
1614 get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
1616 if (CMAKE_CFG_INTDIR AND
1617 NOT CMAKE_CFG_INTDIR STREQUAL "." AND
1618 NOT CMAKE_CFG_INTDIR MATCHES "\\$")
1619 # CMake 3.4 and below used the CMAKE_CFG_INTDIR placeholder value
1620 # provided by multi-configuration generators. Some projects were
1621 # taking advantage of that undocumented implementation detail to
1622 # specify a specific configuration here. They should use
1623 # BUILD_COMMAND to change the default command instead, but for
1624 # compatibility honor the value.
1625 set(config ${CMAKE_CFG_INTDIR})
1626 message(AUTHOR_WARNING
1627 "CMAKE_CFG_INTDIR should not be set by project code.\n"
1628 "To get a non-default build command, use the BUILD_COMMAND option."
1631 set(config $<CONFIG>)
1633 list(APPEND args --config ${config})
1635 if(step STREQUAL "INSTALL")
1636 if("${cmake_generator}" MATCHES "Green Hills MULTI")
1637 list(APPEND args --target INSTALL)
1639 list(APPEND args --target install)
1642 # But for "TEST" drive the project with corresponding "ctest".
1643 if("x${step}x" STREQUAL "xTESTx")
1644 string(REGEX REPLACE "^(.*/)cmake([^/]*)$" "\\1ctest\\2" cmd "${cmd}")
1647 list(APPEND args -C ${config})
1652 # Non-CMake project. Guess "make" and "make install" and "make test".
1653 if("${CMAKE_GENERATOR}" MATCHES "Makefiles")
1654 # Try to get the parallel arguments
1659 if(step STREQUAL "INSTALL")
1662 if("x${step}x" STREQUAL "xTESTx")
1667 # Use user-specified arguments instead of default arguments, if any.
1668 get_property(have_args TARGET ${name} PROPERTY _EP_${step}_ARGS SET)
1670 get_target_property(args ${name} _EP_${step}_ARGS)
1673 if(NOT "${args}" STREQUAL "")
1674 # args could have empty items, so we must quote it to prevent them
1675 # from being silently removed
1676 list(APPEND cmd "${args}")
1678 set(${cmd_var} "${cmd}" PARENT_SCOPE)
1682 function(_ep_write_log_script
1687 ExternalProject_Get_Property(${name} log_dir)
1688 ExternalProject_Get_Property(${name} stamp_dir)
1689 set(command "${${cmd_var}}")
1692 set(code_cygpath_make "")
1693 if(command MATCHES "^\\$\\(MAKE\\)")
1694 # GNU make recognizes the string "$(MAKE)" as recursive make, so
1695 # ensure that it appears directly in the makefile.
1696 string(REGEX REPLACE "^\\$\\(MAKE\\)" "\${make}" command "${command}")
1697 set(make "-Dmake=$(MAKE)")
1699 if(WIN32 AND NOT CYGWIN)
1700 set(code_cygpath_make "
1701 if(\${make} MATCHES \"^/\")
1703 COMMAND cygpath -w \${make}
1704 OUTPUT_VARIABLE cygpath_make
1705 ERROR_VARIABLE cygpath_make
1706 RESULT_VARIABLE cygpath_error
1707 OUTPUT_STRIP_TRAILING_WHITESPACE
1709 if(NOT cygpath_error)
1710 set(make \${cygpath_make})
1718 if("${CMAKE_CFG_INTDIR}" MATCHES "^\\$")
1719 string(REPLACE "${CMAKE_CFG_INTDIR}" "\${config}" command "${command}")
1720 set(config "-Dconfig=${CMAKE_CFG_INTDIR}")
1723 # Wrap multiple 'COMMAND' lines up into a second-level wrapper
1724 # script so all output can be sent to one log file.
1725 if(command MATCHES "(^|;)COMMAND;")
1726 set(code_execute_process "
1727 ${code_cygpath_make}
1728 execute_process(COMMAND \${command} RESULT_VARIABLE result)
1730 set(msg \"Command failed (\${result}):\\n\")
1731 foreach(arg IN LISTS command)
1732 set(msg \"\${msg} '\${arg}'\")
1734 message(FATAL_ERROR \"\${msg}\")
1740 foreach(arg IN LISTS command)
1741 if("x${arg}" STREQUAL "xCOMMAND")
1742 if(NOT "x${cmd}" STREQUAL "x")
1743 string(APPEND code "set(command \"${cmd}\")${code_execute_process}")
1748 string(APPEND cmd "${sep}${arg}")
1752 string(APPEND code "set(command \"${cmd}\")${code_execute_process}")
1754 OUTPUT "${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake"
1760 "-Dconfig=\${config}"
1761 -P ${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake
1765 # Wrap the command in a script to log output to files.
1766 set(script ${stamp_dir}/${name}-${step}-$<CONFIG>.cmake)
1767 set(logbase ${log_dir}/${name}-${step})
1768 get_property(log_merged
1770 PROPERTY _EP_LOG_MERGED_STDOUTERR
1772 get_property(log_output_on_failure
1774 PROPERTY _EP_LOG_OUTPUT_ON_FAILURE
1777 set(stdout_log "${logbase}.log")
1778 set(stderr_log "${logbase}.log")
1780 set(stdout_log "${logbase}-out.log")
1781 set(stderr_log "${logbase}-err.log")
1784 cmake_minimum_required(VERSION \${CMAKE_VERSION}) # this file comes with cmake
1785 ${code_cygpath_make}
1786 set(command \"${command}\")
1787 set(log_merged \"${log_merged}\")
1788 set(log_output_on_failure \"${log_output_on_failure}\")
1789 set(stdout_log \"${stdout_log}\")
1790 set(stderr_log \"${stderr_log}\")
1793 RESULT_VARIABLE result
1794 OUTPUT_FILE \"\${stdout_log}\"
1795 ERROR_FILE \"\${stderr_log}\"
1797 macro(read_up_to_max_size log_file output_var)
1798 file(SIZE \${log_file} determined_size)
1800 if (determined_size GREATER max_size)
1801 math(EXPR seek_position \"\${determined_size} - \${max_size}\")
1802 file(READ \${log_file} \${output_var} OFFSET \${seek_position})
1803 set(\${output_var} \"...skipping to end...\\n\${\${output_var}}\")
1805 file(READ \${log_file} \${output_var})
1809 set(msg \"Command failed: \${result}\\n\")
1810 foreach(arg IN LISTS command)
1811 set(msg \"\${msg} '\${arg}'\")
1814 set(msg \"\${msg}\\nSee also\\n \${stderr_log}\")
1816 set(msg \"\${msg}\\nSee also\\n ${logbase}-*.log\")
1818 if (\${log_output_on_failure})
1819 message(SEND_ERROR \"\${msg}\")
1821 read_up_to_max_size(\"\${stderr_log}\" error_log_contents)
1822 message(STATUS \"Log output is:\\n\${error_log_contents}\")
1824 read_up_to_max_size(\"\${stdout_log}\" out_log_contents)
1825 read_up_to_max_size(\"\${stderr_log}\" err_log_contents)
1826 message(STATUS \"stdout output is:\\n\${out_log_contents}\")
1827 message(STATUS \"stderr output is:\\n\${err_log_contents}\")
1829 message(FATAL_ERROR \"Stopping after outputting logs.\")
1831 message(FATAL_ERROR \"\${msg}\")
1834 if(NOT \"${CMAKE_GENERATOR}\" MATCHES \"Ninja\")
1835 set(msg \"${name} ${step} command succeeded. See also ${logbase}-*.log\")
1836 message(STATUS \"\${msg}\")
1840 file(GENERATE OUTPUT "${script}" CONTENT "${code}")
1841 set(command ${CMAKE_COMMAND} ${make} ${config} -P ${script})
1842 set(${cmd_var} "${command}" PARENT_SCOPE)
1846 # On multi-config generators, provide a placeholder for a per-config subdir.
1847 # On single-config generators, this is empty.
1848 function(_ep_get_configuration_subdir_genex suffix_var)
1850 get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
1852 if(CMAKE_GENERATOR STREQUAL "Xcode")
1853 # The Xcode generator does not support per-config sources,
1854 # so use the underlying build system's placeholder instead.
1855 # FIXME(#23652): We have no test for the use case requiring
1856 # CMAKE_CFG_INTDIR for XCODE_EMIT_EFFECTIVE_PLATFORM_NAME,
1857 # but $<CONFIG> does not work.
1858 set(suffix "/${CMAKE_CFG_INTDIR}")
1860 set(suffix "/$<CONFIG>")
1863 set(${suffix_var} "${suffix}" PARENT_SCOPE)
1867 function(_ep_get_step_stampfile
1872 ExternalProject_Get_Property(${name} stamp_dir)
1874 _ep_get_configuration_subdir_genex(cfgdir)
1875 set(stampfile "${stamp_dir}${cfgdir}/${name}-${step}")
1877 set(${stampfile_var} "${stampfile}" PARENT_SCOPE)
1881 function(_ep_get_complete_stampfile
1885 set(cmf_dir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles)
1886 _ep_get_configuration_subdir_genex(cfgdir)
1887 set(stampfile "${cmf_dir}${cfgdir}/${name}-complete")
1889 set(${stampfile_var} ${stampfile} PARENT_SCOPE)
1893 function(_ep_step_add_target
1898 if(TARGET ${name}-${step})
1901 get_property(cmp0114 TARGET ${name} PROPERTY _EP_CMP0114)
1902 _ep_get_step_stampfile(${name} ${step} stamp_file)
1904 if(cmp0114 STREQUAL "NEW")
1905 # To implement CMP0114 NEW behavior with Makefile generators,
1906 # we need CMP0113 NEW behavior.
1907 cmake_policy(SET CMP0113 NEW)
1909 add_custom_target(${name}-${step} DEPENDS ${stamp_file})
1911 set_target_properties(${name}-${step} PROPERTIES
1912 _EP_IS_EXTERNAL_PROJECT_STEP 1
1914 FOLDER "ExternalProjectTargets/${name}"
1917 if(cmp0114 STREQUAL "NEW")
1918 # Add target-level dependencies for the step.
1919 get_property(exclude_from_main
1921 PROPERTY _EP_${step}_EXCLUDE_FROM_MAIN
1923 if(NOT exclude_from_main)
1924 add_dependencies(${name} ${name}-${step})
1926 _ep_step_add_target_dependencies(${name} ${step} ${step})
1927 _ep_step_add_target_dependents(${name} ${step} ${step})
1929 get_property(independent TARGET ${name} PROPERTY _EP_${step}_INDEPENDENT)
1931 if(no_deps AND "${step}" MATCHES "^(configure|build|install|test)$")
1932 message(AUTHOR_WARNING
1933 "Using NO_DEPENDS for \"${step}\" step might break parallel builds"
1936 set(independent ${no_deps})
1939 # Depend on other external projects (target-level).
1941 get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
1942 foreach(arg IN LISTS deps)
1943 add_dependencies(${name}-${step} ${arg})
1949 function(_ep_step_add_target_dependencies
1954 get_property(dependees
1956 PROPERTY _EP_${node}_INTERNAL_DEPENDEES
1958 list(REMOVE_DUPLICATES dependees)
1959 foreach(dependee IN LISTS dependees)
1960 get_property(exclude_from_main
1962 PROPERTY _EP_${step}_EXCLUDE_FROM_MAIN
1964 get_property(dependee_dependers
1966 PROPERTY _EP_${dependee}_INTERNAL_DEPENDERS
1968 if(exclude_from_main OR dependee_dependers MATCHES ";")
1969 # The step on which our step target depends itself has
1970 # dependents in multiple targes. It needs a step target too
1971 # so that there is a unique place for its custom command.
1972 _ep_step_add_target("${name}" "${dependee}" "FALSE")
1975 if(TARGET ${name}-${dependee})
1976 add_dependencies(${name}-${step} ${name}-${dependee})
1978 _ep_step_add_target_dependencies(${name} ${step} ${dependee})
1984 function(_ep_step_add_target_dependents
1989 get_property(dependers
1991 PROPERTY _EP_${node}_INTERNAL_DEPENDERS
1993 list(REMOVE_DUPLICATES dependers)
1994 foreach(depender IN LISTS dependers)
1995 if(TARGET ${name}-${depender})
1996 add_dependencies(${name}-${depender} ${name}-${step})
1998 _ep_step_add_target_dependents(${name} ${step} ${depender})
2004 function(ExternalProject_Add_StepTargets name)
2005 get_property(cmp0114 TARGET ${name} PROPERTY _EP_CMP0114)
2007 if(ARGC GREATER 1 AND "${ARGV1}" STREQUAL "NO_DEPENDS")
2009 list(REMOVE_AT steps 0)
2013 if(cmp0114 STREQUAL "NEW")
2016 "The 'NO_DEPENDS' option is no longer allowed. "
2017 "It has been superseded by the per-step 'INDEPENDENT' option. "
2018 "See policy CMP0114."
2021 elseif(cmp0114 STREQUAL "")
2022 cmake_policy(GET_WARNING CMP0114 _cmp0114_warning)
2023 string(APPEND _cmp0114_warning "\n"
2024 "ExternalProject target '${name}' would depend on the targets for "
2025 "step(s) '${steps}' under policy CMP0114, but this is being left out "
2026 "for compatibility since the policy is not set."
2029 string(APPEND _cmp0114_warning " "
2030 "Also, the NO_DEPENDS option is deprecated in favor of policy CMP0114."
2033 message(AUTHOR_WARNING "${_cmp0114_warning}")
2035 foreach(step IN LISTS steps)
2036 _ep_step_add_target("${name}" "${step}" "${no_deps}")
2041 # While this function is referenced in shared_internal_commands.cmake in a few
2042 # places, all of those code paths will only be reached by calling one of the
2043 # functions defined in this file. Keep it here, since it is part of the public
2044 # interface of ExternalProject.
2045 function(ExternalProject_Add_Step name step)
2046 get_property(cmp0114 TARGET ${name} PROPERTY _EP_CMP0114)
2047 _ep_get_complete_stampfile(${name} complete_stamp_file)
2048 _ep_get_step_stampfile(${name} ${step} stamp_file)
2065 _ep_parse_arguments(
2066 ExternalProject_Add_Step
2073 get_property(independent
2075 PROPERTY _EP_${step}_INDEPENDENT
2077 if(independent STREQUAL "")
2078 set(independent FALSE)
2079 set_property(TARGET ${name} PROPERTY
2080 _EP_${step}_INDEPENDENT "${independent}"
2084 get_property(exclude_from_main
2086 PROPERTY _EP_${step}_EXCLUDE_FROM_MAIN
2088 if(NOT exclude_from_main)
2089 add_custom_command(APPEND
2090 OUTPUT ${complete_stamp_file}
2091 DEPENDS ${stamp_file}
2095 # Steps depending on this step.
2096 get_property(dependers TARGET ${name} PROPERTY _EP_${step}_DEPENDERS)
2097 set_property(TARGET ${name} APPEND PROPERTY
2098 _EP_${step}_INTERNAL_DEPENDERS ${dependers}
2100 foreach(depender IN LISTS dependers)
2101 set_property(TARGET ${name} APPEND PROPERTY
2102 _EP_${depender}_INTERNAL_DEPENDEES ${step}
2104 _ep_get_step_stampfile(${name} ${depender} depender_stamp_file)
2105 add_custom_command(APPEND
2106 OUTPUT ${depender_stamp_file}
2107 DEPENDS ${stamp_file}
2109 if(cmp0114 STREQUAL "NEW" AND NOT independent)
2110 get_property(dep_independent
2112 PROPERTY _EP_${depender}_INDEPENDENT
2116 "ExternalProject '${name}' step '${depender}' is marked INDEPENDENT "
2117 "but depends on step '${step}' that is not marked INDEPENDENT."
2123 # Dependencies on files.
2124 get_property(depends TARGET ${name} PROPERTY _EP_${step}_DEPENDS)
2126 # Byproducts of the step.
2127 get_property(byproducts TARGET ${name} PROPERTY _EP_${step}_BYPRODUCTS)
2129 # Dependencies on steps.
2130 get_property(dependees TARGET ${name} PROPERTY _EP_${step}_DEPENDEES)
2131 set_property(TARGET ${name} APPEND PROPERTY
2132 _EP_${step}_INTERNAL_DEPENDEES ${dependees}
2134 foreach(dependee IN LISTS dependees)
2135 set_property(TARGET ${name} APPEND PROPERTY
2136 _EP_${dependee}_INTERNAL_DEPENDERS ${step}
2138 _ep_get_step_stampfile(${name} ${dependee} dependee_stamp_file)
2139 list(APPEND depends ${dependee_stamp_file})
2140 if(cmp0114 STREQUAL "NEW" AND independent)
2141 get_property(dep_independent
2143 PROPERTY _EP_${dependee}_INDEPENDENT
2145 if(NOT dep_independent)
2147 "ExternalProject '${name}' step '${step}' is marked INDEPENDENT "
2148 "but depends on step '${dependee}' that is not marked INDEPENDENT."
2154 # The command to run.
2155 get_property(command TARGET ${name} PROPERTY _EP_${step}_COMMAND)
2157 set(comment "Performing ${step} step for '${name}'")
2159 set(comment "No ${step} step for '${name}'")
2161 get_property(work_dir
2163 PROPERTY _EP_${step}_WORKING_DIRECTORY
2166 # Replace list separators.
2169 PROPERTY _EP_LIST_SEPARATOR
2172 string(REPLACE "${sep}" "\\;" command "${command}")
2175 # Replace location tags.
2176 _ep_replace_location_tags(
2184 if(NOT "x${work_dir}" STREQUAL "x")
2185 set(maybe_WORKING_DIRECTORY "WORKING_DIRECTORY [==[${work_dir}]==]")
2187 set(maybe_WORKING_DIRECTORY "")
2191 get_property(comment_set
2193 PROPERTY _EP_${step}_COMMENT
2197 get_property(comment
2199 PROPERTY _EP_${step}_COMMENT
2204 get_property(uses_terminal
2206 PROPERTY _EP_${step}_USES_TERMINAL
2209 set(maybe_USES_TERMINAL USES_TERMINAL)
2211 set(maybe_USES_TERMINAL "")
2217 PROPERTY _EP_${step}_ALWAYS
2220 set(maybe_COMMAND_touch "")
2221 # Mark stamp files for all configs as SYMBOLIC since we do not create them.
2222 # Remove any existing stamp in case the option changed in an existing tree.
2223 get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
2225 _ep_get_configuration_subdir_genex(cfgdir)
2226 foreach(cfg IN LISTS CMAKE_CONFIGURATION_TYPES)
2227 string(REPLACE "${cfgdir}" "/${cfg}"
2228 stamp_file_config "${stamp_file}"
2230 set_property(SOURCE ${stamp_file_config} PROPERTY SYMBOLIC 1)
2231 file(REMOVE ${stamp_file_config})
2233 if(CMAKE_GENERATOR STREQUAL "Xcode")
2234 # See Xcode case in _ep_get_configuration_subdir_genex.
2235 set_property(SOURCE ${stamp_file} PROPERTY SYMBOLIC 1)
2238 set_property(SOURCE ${stamp_file} PROPERTY SYMBOLIC 1)
2239 file(REMOVE ${stamp_file})
2242 set(maybe_COMMAND_touch "COMMAND \${CMAKE_COMMAND} -E touch \${stamp_file}")
2245 get_property(job_server_aware
2247 PROPERTY _EP_${step}_JOB_SERVER_AWARE
2249 if(job_server_aware)
2250 set(maybe_JOB_SERVER_AWARE "JOB_SERVER_AWARE 1")
2252 set(maybe_JOB_SERVER_AWARE "")
2255 # Wrap with log script?
2256 get_property(log TARGET ${name} PROPERTY _EP_${step}_LOG)
2258 _ep_write_log_script(${name} ${step} command)
2261 if("${command}" STREQUAL "")
2262 # Some generators (i.e. Xcode) will not generate a file level target
2263 # if no command is set, and therefore the dependencies on this
2264 # target will be broken.
2265 # The empty command is replaced by an echo command here in order to
2267 set(command ${CMAKE_COMMAND} -E echo_append)
2271 foreach(__item IN LISTS command)
2272 string(APPEND __cmdQuoted " [==[${__item}]==]")
2274 cmake_language(EVAL CODE "
2276 OUTPUT \${stamp_file}
2277 BYPRODUCTS \${byproducts}
2278 COMMENT [===[${comment}]===]
2279 COMMAND ${__cmdQuoted}
2282 ${maybe_COMMAND_touch}
2283 ${maybe_JOB_SERVER_AWARE}
2284 ${maybe_WORKING_DIRECTORY}
2285 ${maybe_USES_TERMINAL}
2288 set_property(TARGET ${name} APPEND PROPERTY _EP_STEPS ${step})
2290 # Add custom "step target"?
2291 get_property(step_targets
2293 PROPERTY _EP_STEP_TARGETS
2295 if(NOT step_targets)
2296 get_property(step_targets
2298 PROPERTY EP_STEP_TARGETS
2301 foreach(st IN LISTS step_targets)
2302 if("${st}" STREQUAL "${step}")
2303 _ep_step_add_target("${name}" "${step}" "FALSE")
2308 get_property(independent_step_targets
2309 TARGET ${name} PROPERTY
2310 _EP_INDEPENDENT_STEP_TARGETS
2312 if(NOT independent_step_targets)
2313 get_property(independent_step_targets
2315 PROPERTY EP_INDEPENDENT_STEP_TARGETS
2318 if(cmp0114 STREQUAL "NEW")
2319 if(independent_step_targets)
2321 "ExternalProject '${name}' option 'INDEPENDENT_STEP_TARGETS' is set to"
2322 "\n ${independent_step_targets}\n"
2323 "but the option is no longer allowed. "
2324 "It has been superseded by the per-step 'INDEPENDENT' option. "
2325 "See policy CMP0114."
2329 if(independent_step_targets AND cmp0114 STREQUAL "")
2332 PROPERTY _EP_CMP0114_WARNED_INDEPENDENT_STEP_TARGETS
2335 set_property(TARGET ${name} PROPERTY
2336 _EP_CMP0114_WARNED_INDEPENDENT_STEP_TARGETS 1
2338 cmake_policy(GET_WARNING CMP0114 _cmp0114_warning)
2339 string(APPEND _cmp0114_warning
2341 "ExternalProject '${name}' option INDEPENDENT_STEP_TARGETS is set to"
2342 "\n ${independent_step_targets}\n"
2343 "but the option is deprecated in favor of policy CMP0114."
2345 message(AUTHOR_WARNING "${_cmp0114_warning}")
2348 foreach(st IN LISTS independent_step_targets)
2349 if("${st}" STREQUAL "${step}")
2350 _ep_step_add_target("${name}" "${step}" "TRUE")
2358 function(ExternalProject_Add_StepDependencies name step)
2359 set(dependencies ${ARGN})
2361 # Sanity checks on "name" and "step".
2362 if(NOT TARGET ${name})
2364 "Cannot find target \"${name}\". Perhaps it has not yet been created "
2365 "using ExternalProject_Add."
2369 get_property(type TARGET ${name} PROPERTY TYPE)
2370 if(NOT type STREQUAL "UTILITY")
2372 "Target \"${name}\" was not generated by ExternalProject_Add."
2376 get_property(is_ep TARGET ${name} PROPERTY _EP_IS_EXTERNAL_PROJECT)
2379 "Target \"${name}\" was not generated by ExternalProject_Add."
2383 get_property(steps TARGET ${name} PROPERTY _EP_STEPS)
2384 list(FIND steps ${step} is_step)
2387 "External project \"${name}\" does not have a step \"${step}\"."
2391 if(TARGET ${name}-${step})
2392 get_property(type TARGET ${name}-${step} PROPERTY TYPE)
2393 if(NOT type STREQUAL "UTILITY")
2395 "Target \"${name}-${step}\" was not generated by "
2396 "ExternalProject_Add_StepTargets."
2399 get_property(is_ep_step
2400 TARGET ${name}-${step}
2401 PROPERTY _EP_IS_EXTERNAL_PROJECT_STEP
2405 "Target \"${name}-${step}\" was not generated by "
2406 "ExternalProject_Add_StepTargets."
2411 # Always add file-level dependency, but add target-level dependency
2412 # only if the target exists for that step.
2413 _ep_get_step_stampfile(${name} ${step} stamp_file)
2414 foreach(dep IN LISTS dependencies)
2415 add_custom_command(APPEND
2416 OUTPUT ${stamp_file}
2420 if(TARGET ${name}-${step})
2421 add_dependencies(${name}-${step} ${dependencies})
2427 function(_ep_add_mkdir_command name)
2428 ExternalProject_Get_Property(${name} tmp_dir)
2429 set(script_filename "${tmp_dir}/${name}-mkdirs.cmake")
2430 _ep_get_configuration_subdir_genex(cfgdir)
2432 ExternalProject_Add_Step(${name} mkdir
2434 COMMENT "Creating directories for '${name}'"
2435 COMMAND ${CMAKE_COMMAND} -Dcfgdir=${cfgdir} -P ${script_filename}
2440 function(_ep_get_file_deps var name)
2445 PROPERTY _EP_DEPENDS
2447 foreach(dep IN LISTS deps)
2448 get_property(dep_type
2452 if(dep_type STREQUAL "UTILITY")
2455 PROPERTY _EP_IS_EXTERNAL_PROJECT
2458 _ep_get_step_stampfile(${dep} "done" done_stamp_file)
2459 list(APPEND file_deps ${done_stamp_file})
2464 set("${var}" "${file_deps}" PARENT_SCOPE)
2468 function(_ep_extract_configure_command var name)
2469 get_property(cmd_set
2471 PROPERTY _EP_CONFIGURE_COMMAND
2477 PROPERTY _EP_CONFIGURE_COMMAND
2480 get_target_property(cmake_command ${name} _EP_CMAKE_COMMAND)
2482 set(cmd "${cmake_command}")
2484 set(cmd "${CMAKE_COMMAND}")
2487 get_property(cmake_args
2489 PROPERTY _EP_CMAKE_ARGS
2491 list(APPEND cmd ${cmake_args})
2493 # If there are any CMAKE_CACHE_ARGS or CMAKE_CACHE_DEFAULT_ARGS,
2494 # write an initial cache and use it
2495 get_property(cmake_cache_args
2497 PROPERTY _EP_CMAKE_CACHE_ARGS
2499 get_property(cmake_cache_default_args
2501 PROPERTY _EP_CMAKE_CACHE_DEFAULT_ARGS
2504 set(has_cmake_cache_args 0)
2505 if(NOT "${cmake_cache_args}" STREQUAL "")
2506 set(has_cmake_cache_args 1)
2509 set(has_cmake_cache_default_args 0)
2510 if(NOT "${cmake_cache_default_args}" STREQUAL "")
2511 set(has_cmake_cache_default_args 1)
2514 get_target_property(cmake_generator ${name}
2517 get_target_property(cmake_generator_instance ${name}
2518 _EP_CMAKE_GENERATOR_INSTANCE
2520 get_target_property(cmake_generator_platform ${name}
2521 _EP_CMAKE_GENERATOR_PLATFORM
2523 get_target_property(cmake_generator_toolset ${name}
2524 _EP_CMAKE_GENERATOR_TOOLSET
2527 list(APPEND cmd "-G${cmake_generator}")
2528 if(cmake_generator_platform)
2529 list(APPEND cmd "-A${cmake_generator_platform}")
2531 if(cmake_generator_toolset)
2532 list(APPEND cmd "-T${cmake_generator_toolset}")
2534 if(cmake_generator_instance)
2536 "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${cmake_generator_instance}"
2540 if(CMAKE_EXTRA_GENERATOR)
2541 list(APPEND cmd "-G${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}")
2543 list(APPEND cmd "-G${CMAKE_GENERATOR}")
2544 # GreenHills needs to know about the compiler and toolset.
2545 # Be sure to update the similar section in
2546 # FetchContent.cmake:__FetchContent_directPopulate()
2547 if("${CMAKE_GENERATOR}" MATCHES "Green Hills MULTI")
2548 set(has_cmake_cache_default_args 1)
2549 list(APPEND cmake_cache_default_args
2550 "-DGHS_TARGET_PLATFORM:STRING=${GHS_TARGET_PLATFORM}"
2551 "-DGHS_PRIMARY_TARGET:STRING=${GHS_PRIMARY_TARGET}"
2552 "-DGHS_TOOLSET_ROOT:STRING=${GHS_TOOLSET_ROOT}"
2553 "-DGHS_OS_ROOT:STRING=${GHS_OS_ROOT}"
2554 "-DGHS_OS_DIR:STRING=${GHS_OS_DIR}"
2555 "-DGHS_BSP_NAME:STRING=${GHS_BSP_NAME}"
2559 if(cmake_generator_platform)
2561 "Option CMAKE_GENERATOR_PLATFORM not allowed without "
2565 if(CMAKE_GENERATOR_PLATFORM)
2566 list(APPEND cmd "-A${CMAKE_GENERATOR_PLATFORM}")
2568 if(cmake_generator_toolset)
2570 "Option CMAKE_GENERATOR_TOOLSET not allowed without CMAKE_GENERATOR."
2573 if(CMAKE_GENERATOR_TOOLSET)
2574 list(APPEND cmd "-T${CMAKE_GENERATOR_TOOLSET}")
2576 if(cmake_generator_instance)
2578 "Option CMAKE_GENERATOR_INSTANCE not allowed without CMAKE_GENERATOR."
2581 if(CMAKE_GENERATOR_INSTANCE)
2583 "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${CMAKE_GENERATOR_INSTANCE}"
2588 if(has_cmake_cache_args OR has_cmake_cache_default_args)
2589 set(_ep_cache_args_script "<TMP_DIR>/${name}-cache-$<CONFIG>.cmake")
2590 if(has_cmake_cache_args)
2591 _ep_command_line_to_initial_cache(
2592 script_initial_cache_force
2593 "${cmake_cache_args}"
2597 if(has_cmake_cache_default_args)
2598 _ep_command_line_to_initial_cache(
2599 script_initial_cache_default
2600 "${cmake_cache_default_args}"
2604 _ep_write_initial_cache(
2606 "${_ep_cache_args_script}"
2607 "${script_initial_cache_force}${script_initial_cache_default}"
2609 list(APPEND cmd "-C${_ep_cache_args_script}")
2610 _ep_replace_location_tags(${name} _ep_cache_args_script)
2611 set(_ep_cache_args_script
2612 "${_ep_cache_args_script}"
2617 list(APPEND cmd -S "<SOURCE_DIR><SOURCE_SUBDIR>" -B "<BINARY_DIR>")
2620 set("${var}" "${cmd}" PARENT_SCOPE)
2624 # TODO: Make sure external projects use the proper compiler
2625 function(_ep_add_configure_command name)
2626 ExternalProject_Get_Property(${name} binary_dir tmp_dir)
2629 get_property(configure_handled_by_build
2631 PROPERTY _EP_CONFIGURE_HANDLED_BY_BUILD
2633 if(NOT configure_handled_by_build)
2634 # Depend on other external projects (file-level)
2635 _ep_get_file_deps(file_deps ${name})
2638 _ep_extract_configure_command(cmd ${name})
2640 # If anything about the configure command changes, (command itself, cmake
2641 # used, cmake args or cmake generator) then re-run the configure step.
2642 # Fixes issue https://gitlab.kitware.com/cmake/cmake/-/issues/10258
2645 ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/cfgcmd.txt.in
2646 ${tmp_dir}/${name}-cfgcmd.txt
2649 list(APPEND file_deps ${tmp_dir}/${name}-cfgcmd.txt)
2650 list(APPEND file_deps ${_ep_cache_args_script})
2652 _ep_get_update_disconnected(update_disconnected ${name})
2653 if(update_disconnected)
2654 set(dependees patch_disconnected)
2656 set(dependees patch)
2661 PROPERTY _EP_LOG_CONFIGURE
2669 get_property(uses_terminal
2671 PROPERTY _EP_USES_TERMINAL_CONFIGURE
2674 set(uses_terminal USES_TERMINAL 1)
2676 set(uses_terminal "")
2680 foreach(__item IN LISTS cmd)
2681 string(APPEND __cmdQuoted " [==[${__item}]==]")
2683 cmake_language(EVAL CODE "
2684 ExternalProject_Add_Step(${name} configure
2686 COMMAND ${__cmdQuoted}
2687 WORKING_DIRECTORY \${binary_dir}
2688 DEPENDEES \${dependees}
2689 DEPENDS \${file_deps}
2697 function(_ep_add_build_command name)
2698 ExternalProject_Get_Property(${name} binary_dir)
2701 get_property(configure_handled_by_build
2703 PROPERTY _EP_CONFIGURE_HANDLED_BY_BUILD
2705 if(configure_handled_by_build)
2706 # Depend on other external projects (file-level)
2707 _ep_get_file_deps(file_deps ${name})
2710 get_property(cmd_set
2712 PROPERTY _EP_BUILD_COMMAND
2718 PROPERTY _EP_BUILD_COMMAND
2721 _ep_get_build_command(${name} BUILD cmd)
2726 PROPERTY _EP_LOG_BUILD
2734 get_property(uses_terminal
2736 PROPERTY _EP_USES_TERMINAL_BUILD
2739 set(uses_terminal USES_TERMINAL 1)
2741 set(uses_terminal "")
2744 get_property(build_always
2746 PROPERTY _EP_BUILD_ALWAYS
2754 get_property(build_byproducts
2756 PROPERTY _EP_BUILD_BYPRODUCTS
2759 get_property(build_job_server_aware
2761 PROPERTY _EP_BUILD_JOB_SERVER_AWARE
2763 if(build_job_server_aware)
2764 set(maybe_JOB_SERVER_AWARE "JOB_SERVER_AWARE 1")
2766 set(maybe_JOB_SERVER_AWARE "")
2771 foreach(__item IN LISTS cmd)
2772 string(APPEND __cmdQuoted " [==[${__item}]==]")
2774 cmake_language(EVAL CODE "
2775 ExternalProject_Add_Step(${name} build
2777 COMMAND ${__cmdQuoted}
2778 BYPRODUCTS \${build_byproducts}
2779 WORKING_DIRECTORY \${binary_dir}
2781 DEPENDS \${file_deps}
2783 ${maybe_JOB_SERVER_AWARE}
2791 function(_ep_add_install_command name)
2792 ExternalProject_Get_Property(${name} binary_dir)
2794 get_property(cmd_set
2796 PROPERTY _EP_INSTALL_COMMAND
2802 PROPERTY _EP_INSTALL_COMMAND
2805 _ep_get_build_command(${name} INSTALL cmd)
2810 PROPERTY _EP_LOG_INSTALL
2818 get_property(uses_terminal
2820 PROPERTY _EP_USES_TERMINAL_INSTALL
2823 set(uses_terminal USES_TERMINAL 1)
2825 set(uses_terminal "")
2828 # With BUILD_ALWAYS+BUILD_BYPRODUCTS, Ninja restats the
2829 # build step outputs and may not consider this step to
2830 # be out-of-date. Explicitly mark it out-of-date too.
2831 get_property(build_always
2833 PROPERTY _EP_BUILD_ALWAYS
2841 get_property(install_byproducts
2843 PROPERTY _EP_INSTALL_BYPRODUCTS
2846 get_property(install_job_server_aware
2848 PROPERTY _EP_INSTALL_JOB_SERVER_AWARE
2850 if(install_job_server_aware)
2851 set(maybe_JOB_SERVER_AWARE "JOB_SERVER_AWARE 1")
2853 set(maybe_JOB_SERVER_AWARE "")
2857 foreach(__item IN LISTS cmd)
2858 string(APPEND __cmdQuoted " [==[${__item}]==]")
2860 cmake_language(EVAL CODE "
2861 ExternalProject_Add_Step(${name} install
2863 COMMAND ${__cmdQuoted}
2864 BYPRODUCTS \${install_byproducts}
2865 WORKING_DIRECTORY \${binary_dir}
2868 ${maybe_JOB_SERVER_AWARE}
2876 function(_ep_add_test_command name)
2877 ExternalProject_Get_Property(${name} binary_dir)
2879 get_property(before TARGET ${name} PROPERTY _EP_TEST_BEFORE_INSTALL)
2880 get_property(after TARGET ${name} PROPERTY _EP_TEST_AFTER_INSTALL)
2881 get_property(exclude TARGET ${name} PROPERTY _EP_TEST_EXCLUDE_FROM_MAIN)
2882 get_property(cmd_set TARGET ${name} PROPERTY _EP_TEST_COMMAND SET)
2884 # Only actually add the test step if one of the test related properties is
2885 # explicitly set. (i.e. the test step is omitted unless requested...)
2887 if(cmd_set OR before OR after OR exclude)
2891 PROPERTY _EP_TEST_COMMAND
2894 _ep_get_build_command(${name} TEST cmd)
2898 set(dependees_args DEPENDEES build)
2900 set(dependees_args DEPENDEES install)
2904 set(dependers_args "")
2905 set(exclude_args EXCLUDE_FROM_MAIN 1)
2908 set(dependers_args DEPENDERS install)
2910 set(dependers_args "")
2912 set(exclude_args "")
2917 PROPERTY _EP_LOG_TEST
2925 get_property(uses_terminal
2927 PROPERTY _EP_USES_TERMINAL_TEST
2930 set(uses_terminal USES_TERMINAL 1)
2932 set(uses_terminal "")
2936 foreach(__item IN LISTS cmd)
2937 string(APPEND __cmdQuoted " [==[${__item}]==]")
2939 cmake_language(EVAL CODE "
2940 ExternalProject_Add_Step(${name} test
2942 COMMAND ${__cmdQuoted}
2943 WORKING_DIRECTORY \${binary_dir}
2955 function(ExternalProject_Add name)
2956 cmake_policy(GET CMP0097 _EP_CMP0097
2957 PARENT_SCOPE # undocumented, do not use outside of CMake
2959 cmake_policy(GET CMP0114 cmp0114
2960 PARENT_SCOPE # undocumented, do not use outside of CMake
2962 if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12 AND
2963 NOT cmp0114 STREQUAL "NEW")
2964 message(AUTHOR_WARNING
2965 "Policy CMP0114 is not set to NEW. "
2966 "In order to support the Xcode \"new build system\", "
2967 "this project must be updated to set policy CMP0114 to NEW."
2969 "Since CMake is generating for the Xcode \"new build system\", "
2970 "ExternalProject_Add will use policy CMP0114's NEW behavior anyway, "
2971 "but the generated build system may not match what the project intends."
2975 cmake_policy(GET CMP0135 _EP_CMP0135
2976 PARENT_SCOPE # undocumented, do not use outside of CMake
2979 _ep_get_configuration_subdir_genex(cfgdir)
2981 # Add a custom target for the external project.
2982 set(cmf_dir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles)
2983 _ep_get_complete_stampfile(${name} complete_stamp_file)
2986 if(cmp0114 STREQUAL "NEW")
2987 # To implement CMP0114 NEW behavior with Makefile generators,
2988 # we need CMP0113 NEW behavior.
2989 cmake_policy(SET CMP0113 NEW)
2991 # The "ALL" option to add_custom_target just tells it to not set the
2992 # EXCLUDE_FROM_ALL target property. Later, if the EXCLUDE_FROM_ALL
2993 # argument was passed, we explicitly set it for the target.
2994 add_custom_target(${name} ALL DEPENDS ${complete_stamp_file})
2996 set_target_properties(${name} PROPERTIES
2997 _EP_IS_EXTERNAL_PROJECT 1
2999 FOLDER "ExternalProjectTargets/${name}"
3000 _EP_CMP0114 "${cmp0114}"
3003 _ep_get_add_keywords(keywords)
3004 _ep_parse_arguments(
3011 _ep_set_directories(${name})
3012 _ep_get_step_stampfile(${name} "done" done_stamp_file)
3013 _ep_get_step_stampfile(${name} "install" install_stamp_file)
3015 # Set the EXCLUDE_FROM_ALL target property if required.
3016 get_property(exclude_from_all
3018 PROPERTY _EP_EXCLUDE_FROM_ALL
3020 if(exclude_from_all)
3021 set_property(TARGET ${name} PROPERTY EXCLUDE_FROM_ALL TRUE)
3024 get_property(repo TARGET ${name} PROPERTY _EP_GIT_REPOSITORY)
3025 if(NOT repo STREQUAL "")
3026 cmake_policy(GET CMP0150 cmp0150
3027 PARENT_SCOPE # undocumented, do not use outside of CMake
3029 get_property(source_dir TARGET ${name} PROPERTY _EP_SOURCE_DIR)
3030 get_filename_component(work_dir "${source_dir}" PATH)
3031 _ep_resolve_git_remote(resolved_git_repository "${repo}" "${cmp0150}" "${work_dir}")
3032 set_property(TARGET ${name} PROPERTY _EP_GIT_REPOSITORY ${resolved_git_repository})
3033 set(_EP_GIT_REPOSITORY "${resolved_git_repository}")
3036 # The 'complete' step depends on all other steps and creates a
3037 # 'done' mark. A dependent external project's 'configure' step
3038 # depends on the 'done' mark so that it rebuilds when this project
3039 # rebuilds. It is important that 'done' is not the output of any
3040 # custom command so that CMake does not propagate build rules to
3041 # other external project targets, which may cause problems during
3042 # parallel builds. However, the Ninja generator needs to see the entire
3043 # dependency graph, and can cope with custom commands belonging to
3044 # multiple targets, so we add the 'done' mark as an output for Ninja only.
3045 set(complete_outputs ${complete_stamp_file})
3046 if(${CMAKE_GENERATOR} MATCHES "Ninja")
3047 set(complete_outputs ${complete_outputs} ${done_stamp_file})
3051 OUTPUT ${complete_outputs}
3052 COMMENT "Completed '${name}'"
3053 COMMAND ${CMAKE_COMMAND} -E make_directory ${cmf_dir}${cfgdir}
3054 COMMAND ${CMAKE_COMMAND} -E touch ${complete_stamp_file}
3055 COMMAND ${CMAKE_COMMAND} -E touch ${done_stamp_file}
3056 DEPENDS ${install_stamp_file}
3060 # Depend on other external projects (target-level).
3063 PROPERTY _EP_DEPENDS
3065 foreach(arg IN LISTS deps)
3066 add_dependencies(${name} ${arg})
3069 # Set up custom build steps based on the target properties.
3070 # Each step depends on the previous one.
3072 # The target depends on the output of the final step.
3073 # (Already set up above in the DEPENDS of the add_custom_target command.)
3075 _ep_add_mkdir_command(${name})
3076 _ep_add_download_command(${name})
3077 _ep_add_update_command(${name})
3078 _ep_add_patch_command(${name})
3079 _ep_add_configure_command(${name})
3080 _ep_add_build_command(${name})
3081 _ep_add_install_command(${name})
3083 # Test is special in that it might depend on build, or it might depend
3086 _ep_add_test_command(${name})