# - Create custom targets to build projects in external trees
# The 'ExternalProject_Add' function creates a custom target to drive
# download, update/patch, configure, build, install and test steps of an
# external project:
# ExternalProject_Add(<name> # Name for custom target
# [DEPENDS projects...] # Targets on which the project depends
# [PREFIX dir] # Root dir for entire project
# [LIST_SEPARATOR sep] # Sep to be replaced by ; in cmd lines
# [TMP_DIR dir] # Directory to store temporary files
# [STAMP_DIR dir] # Directory to store step timestamps
# #--Download step--------------
# [DOWNLOAD_NAME fname] # File name to store (if not end of URL)
# [DOWNLOAD_DIR dir] # Directory to store downloaded files
# [DOWNLOAD_COMMAND cmd...] # Command to download source tree
# [CVS_REPOSITORY cvsroot] # CVSROOT of CVS repository
# [CVS_MODULE mod] # Module to checkout from CVS repo
# [CVS_TAG tag] # Tag to checkout from CVS repo
# [SVN_REPOSITORY url] # URL of Subversion repo
# [SVN_REVISION rev] # Revision to checkout from Subversion repo
# [SVN_USERNAME john ] # Username for Subversion checkout and update
# [SVN_PASSWORD doe ] # Password for Subversion checkout and update
# [SVN_TRUST_CERT 1 ] # Trust the Subversion server site certificate
# [GIT_REPOSITORY url] # URL of git repo
# [GIT_TAG tag] # Git branch name, commit id or tag
# [HG_REPOSITORY url] # URL of mercurial repo
# [HG_TAG tag] # Mercurial branch name, commit id or tag
# [URL /.../src.tgz] # Full path or URL of source
# [URL_HASH ALGO=value] # Hash of file at URL
# [URL_MD5 md5] # Equivalent to URL_HASH MD5=md5
# [TLS_VERIFY bool] # Should certificate for https be checked
# [TLS_CAINFO file] # Path to a certificate authority file
# [TIMEOUT seconds] # Time allowed for file download operations
# #--Update/Patch step----------
# [UPDATE_COMMAND cmd...] # Source work-tree update command
# [PATCH_COMMAND cmd...] # Command to patch downloaded source
# #--Configure step-------------
# [SOURCE_DIR dir] # Source dir to be used for build
# [CONFIGURE_COMMAND cmd...] # Build tree configuration command
# [CMAKE_COMMAND /.../cmake] # Specify alternative cmake executable
# [CMAKE_GENERATOR gen] # Specify generator for native build
# [CMAKE_GENERATOR_TOOLSET t] # Generator-specific toolset name
# [CMAKE_ARGS args...] # Arguments to CMake command line
# [CMAKE_CACHE_ARGS args...] # Initial cache arguments, of the form -Dvar:string=on
# #--Build step-----------------
# [BINARY_DIR dir] # Specify build dir location
# [BUILD_COMMAND cmd...] # Command to drive the native build
# [BUILD_IN_SOURCE 1] # Use source dir for build dir
# #--Install step---------------
# [INSTALL_DIR dir] # Installation prefix
# [INSTALL_COMMAND cmd...] # Command to drive install after build
# #--Test step------------------
# [TEST_BEFORE_INSTALL 1] # Add test step executed before install step
# [TEST_AFTER_INSTALL 1] # Add test step executed after install step
# [TEST_COMMAND cmd...] # Command to drive test
# #--Output logging-------------
# [LOG_DOWNLOAD 1] # Wrap download in script to log output
# [LOG_UPDATE 1] # Wrap update in script to log output
# [LOG_CONFIGURE 1] # Wrap configure in script to log output
# [LOG_BUILD 1] # Wrap build in script to log output
# [LOG_TEST 1] # Wrap test in script to log output
# [LOG_INSTALL 1] # Wrap install in script to log output
# #--Custom targets-------------
# [STEP_TARGETS st1 st2 ...] # Generate custom targets for these steps
# )
# The *_DIR options specify directories for the project, with default
# directories computed as follows.
# If the PREFIX option is given to ExternalProject_Add() or the EP_PREFIX
# directory property is set, then an external project is built and installed
# under the specified prefix:
# TMP_DIR = <prefix>/tmp
# STAMP_DIR = <prefix>/src/<name>-stamp
# DOWNLOAD_DIR = <prefix>/src
# SOURCE_DIR = <prefix>/src/<name>
# BINARY_DIR = <prefix>/src/<name>-build
# INSTALL_DIR = <prefix>
# Otherwise, if the EP_BASE directory property is set then components
# of an external project are stored under the specified base:
# TMP_DIR = <base>/tmp/<name>
# STAMP_DIR = <base>/Stamp/<name>
# DOWNLOAD_DIR = <base>/Download/<name>
# SOURCE_DIR = <base>/Source/<name>
# BINARY_DIR = <base>/Build/<name>
# INSTALL_DIR = <base>/Install/<name>
# If no PREFIX, EP_PREFIX, or EP_BASE is specified then the default
# is to set PREFIX to "<name>-prefix".
# Relative paths are interpreted with respect to the build directory
# corresponding to the source directory in which ExternalProject_Add is
# invoked.
#
# If SOURCE_DIR is explicitly set to an existing directory the project
# will be built from it.
# Otherwise a download step must be specified using one of the
# DOWNLOAD_COMMAND, CVS_*, SVN_*, or URL options.
# The URL option may refer locally to a directory or source tarball,
# or refer to a remote tarball (e.g. http://.../src.tgz).
#
# The 'ExternalProject_Add_Step' function adds a custom step to an external
# project:
# ExternalProject_Add_Step(<name> <step> # Names of project and custom step
# [COMMAND cmd...] # Command line invoked by this step
# [COMMENT "text..."] # Text printed when step executes
# [DEPENDEES steps...] # Steps on which this step depends
# [DEPENDERS steps...] # Steps that depend on this step
# [DEPENDS files...] # Files on which this step depends
# [ALWAYS 1] # No stamp file, step always runs
# [WORKING_DIRECTORY dir] # Working directory for command
# [LOG 1] # Wrap step in script to log output
# )
# The command line, comment, and working directory of every standard
# and custom step is processed to replace tokens
# <SOURCE_DIR>,
# <BINARY_DIR>,
# <INSTALL_DIR>,
# and <TMP_DIR>
# with corresponding property values.
#
# The 'ExternalProject_Get_Property' function retrieves external project
# target properties:
# ExternalProject_Get_Property(<name> [prop1 [prop2 [...]]])
# It stores property values in variables of the same name.
# Property names correspond to the keyword argument names of
# 'ExternalProject_Add'.
#
# The 'ExternalProject_Add_StepTargets' function generates custom targets for
# the steps listed:
# ExternalProject_Add_StepTargets(<name> [step1 [step2 [...]]])
#
# If STEP_TARGETS is set then ExternalProject_Add_StepTargets is automatically
# called at the end of matching calls to ExternalProject_Add_Step. Pass
# STEP_TARGETS explicitly to individual ExternalProject_Add calls, or
# implicitly to all ExternalProject_Add calls by setting the directory property
# EP_STEP_TARGETS.
#
# If STEP_TARGETS is not set, clients may still manually call
# ExternalProject_Add_StepTargets after calling ExternalProject_Add or
# ExternalProject_Add_Step.
#
# This functionality is provided to make it easy to drive the steps
# independently of each other by specifying targets on build command lines.
# For example, you may be submitting to a sub-project based dashboard, where
# you want to drive the configure portion of the build, then submit to the
# dashboard, followed by the build portion, followed by tests. If you invoke
# a custom target that depends on a step halfway through the step dependency
# chain, then all the previous steps will also run to ensure everything is
# up to date.
#
# For example, to drive configure, build and test steps independently for each
# ExternalProject_Add call in your project, write the following line prior to
# any ExternalProject_Add calls in your CMakeLists file:
#
# set_property(DIRECTORY PROPERTY EP_STEP_TARGETS configure build test)
#=============================================================================
# Copyright 2008-2012 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# Pre-compute a regex to match documented keywords for each command.
math ( EXPR _ep_documentation_line_count "${CMAKE_CURRENT_LIST_LINE} - 16" )
file ( STRINGS "${CMAKE_CURRENT_LIST_FILE}" lines
L I M I T _ C O U N T $ { _ e p _ d o c u m e n t a t i o n _ l i n e _ c o u n t }
R E G E X " ^ # ( \\[[A-Z0-9_]+ [^]]*\\] +#.*$|[A-Za-z0-9_]+\\()")
foreach ( line IN LISTS lines )
if ( "${line}" MATCHES "^# [A-Za-z0-9_]+\\(" )
if ( _ep_func )
set ( _ep_keywords_ ${ _ep_func } "${_ep_keywords_${_ep_func}})$" )
endif ( )
string ( REGEX REPLACE "^# ([A-Za-z0-9_]+)\\(.*" "\\1" _ep_func "${line}" )
#message("function [${_ep_func}]")
set ( _ep_keywords_ ${ _ep_func } "^(" )
set ( _ep_keyword_sep )
else ( )
string ( REGEX REPLACE "^# \\[([A-Z0-9_]+) .*" "\\1" _ep_key "${line}" )
#message(" keyword [${_ep_key}]")
set ( _ep_keywords_ ${ _ep_func }
" $ { _ e p _ k e y w o r d s _ $ { _ e p _ f u n c } } $ { _ e p _ k e y w o r d _ s e p } $ { _ e p _ k e y } " )
set ( _ep_keyword_sep "|" )
endif ( )
endforeach ( )
if ( _ep_func )
set ( _ep_keywords_ ${ _ep_func } "${_ep_keywords_${_ep_func}})$" )
endif ( )
# Save regex matching supported hash algorithm names.
set ( _ep_hash_algos "MD5|SHA1|SHA224|SHA256|SHA384|SHA512" )
set ( _ep_hash_regex "^(${_ep_hash_algos})=([0-9A-Fa-f]+)$" )
function ( _ep_parse_arguments f name ns args )
# Transfer the arguments to this function into target properties for the
# new custom target we just added so that we can set up all the build steps
# correctly based on target properties.
#
# We loop through ARGN and consider the namespace starting with an
# upper-case letter followed by at least two more upper-case letters,
# numbers or underscores to be keywords.
set ( key )
foreach ( arg IN LISTS args )
set ( is_value 1 )
if ( arg MATCHES "^[A-Z][A-Z0-9_][A-Z0-9_]+$" AND
NOT ( ( arg STREQUAL "${key}" ) AND ( key STREQUAL "COMMAND" ) ) A N D
N O T a r g M A T C H E S " ^ ( T R U E | F A L S E ) $ " )
if ( _ep_keywords_ ${ f } AND arg MATCHES "${_ep_keywords_${f}}" )
set ( is_value 0 )
endif ( )
endif ( )
if ( is_value )
if ( key )
# Value
if ( NOT arg STREQUAL "" )
set_property ( TARGET ${ name } APPEND PROPERTY ${ ns } ${ key } "${arg}" )
else ( )
get_property ( have_key TARGET ${ name } PROPERTY ${ ns } ${ key } SET )
if ( have_key )
get_property ( value TARGET ${ name } PROPERTY ${ ns } ${ key } )
set_property ( TARGET ${ name } PROPERTY ${ ns } ${ key } "${value};${arg}" )
else ( )
set_property ( TARGET ${ name } PROPERTY ${ ns } ${ key } "${arg}" )
endif ( )
endif ( )
else ( )
# Missing Keyword
message ( AUTHOR_WARNING "value '${arg}' with no previous keyword in ${f}" )
endif ( )
else ( )
set ( key "${arg}" )
endif ( )
endforeach ( )
endfunction ( )
define_property ( DIRECTORY PROPERTY "EP_BASE" INHERITED
B R I E F _ D O C S " B a s e d i r e c t o r y f o r E x t e r n a l P r o j e c t s t o r a g e . "
F U L L _ D O C S
" S e e d o c u m e n t a t i o n o f t h e ExternalProject_Add ( ) f u n c t i o n i n t h e "
" E x t e r n a l P r o j e c t m o d u l e . "
)
define_property ( DIRECTORY PROPERTY "EP_PREFIX" INHERITED
B R I E F _ D O C S " T o p p r e f i x f o r E x t e r n a l P r o j e c t s t o r a g e . "
F U L L _ D O C S
" S e e d o c u m e n t a t i o n o f t h e ExternalProject_Add ( ) f u n c t i o n i n t h e "
" E x t e r n a l P r o j e c t m o d u l e . "
)
define_property ( DIRECTORY PROPERTY "EP_STEP_TARGETS" INHERITED
B R I E F _ D O C S
" L i s t o f E x t e r n a l P r o j e c t s t e p s t h a t a u t o m a t i c a l l y g e t c o r r e s p o n d i n g t a r g e t s "
F U L L _ D O C S
" S e e d o c u m e n t a t i o n o f t h e ExternalProject_Add_StepTargets ( ) f u n c t i o n i n t h e "
" E x t e r n a l P r o j e c t m o d u l e . "
)
function ( _ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag src_name work_dir gitclone_infofile gitclone_stampfile )
file ( WRITE ${ script_filename }
" if ( \"${git_tag}\" STREQUAL \"\")
message ( FATAL_ERROR \"Tag for git checkout should not be empty.\ " )
endif ( )
set ( run 0 )
if ( \"${gitclone_infofile}\" IS_NEWER_THAN \"${gitclone_stampfile}\")
set ( run 1 )
endif ( )
if ( NOT run )
message ( STATUS \"Avoiding repeated git clone, stamp file is up to date: ' ${ gitclone_stampfile } '\ " )
return ( )
endif ( )
execute_process (
C O M M A N D \ $ { C M A K E _ C O M M A N D } - E r e m o v e _ d i r e c t o r y \ " $ { s o u r c e _ d i r } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
)
if ( error_code )
message ( FATAL_ERROR \"Failed to remove directory: ' ${ source_dir } '\ " )
endif ( )
# try the clone 3 times incase there is an odd git clone issue
set ( error_code 1 )
set ( number_of_tries 0 )
while ( error_code AND number_of_tries LESS 3 )
execute_process (
C O M M A N D \ " $ { g i t _ E X E C U T A B L E } \ " c l o n e \ " $ { g i t _ r e p o s i t o r y } \ " \ " $ { s r c _ n a m e } \ "
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
)
math ( EXPR number_of_tries \"\${number_of_tries} + 1\ " )
endwhile ( )
if ( number_of_tries GREATER 1 )
message ( STATUS \"Had to git clone more than once:
\ $ { n u m b e r _ o f _ t r i e s } t i m e s . \ " )
endif ( )
if ( error_code )
message ( FATAL_ERROR \"Failed to clone repository: ' ${ git_repository } '\ " )
endif ( )
execute_process (
C O M M A N D \ " $ { g i t _ E X E C U T A B L E } \ " c h e c k o u t $ { g i t _ t a g }
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } / $ { s r c _ n a m e } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
)
if ( error_code )
message ( FATAL_ERROR \"Failed to checkout tag: ' ${ git_tag } '\ " )
endif ( )
execute_process (
C O M M A N D \ " $ { g i t _ E X E C U T A B L E } \ " s u b m o d u l e i n i t
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } / $ { s r c _ n a m e } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
)
if ( error_code )
message ( FATAL_ERROR \"Failed to init submodules in: ' ${ work_dir } / ${ src_name } '\ " )
endif ( )
execute_process (
C O M M A N D \ " $ { g i t _ E X E C U T A B L E } \ " s u b m o d u l e u p d a t e - - r e c u r s i v e
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } / $ { s r c _ n a m e } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
)
if ( error_code )
message ( FATAL_ERROR \"Failed to update submodules in: ' ${ work_dir } / ${ src_name } '\ " )
endif ( )
# Complete success, update the script-last-run stamp file:
#
execute_process (
C O M M A N D \ $ { C M A K E _ C O M M A N D } - E c o p y
\ " $ { g i t c l o n e _ i n f o f i l e } \ "
\ " $ { g i t c l o n e _ s t a m p f i l e } \ "
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } / $ { s r c _ n a m e } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
)
if ( error_code )
message ( FATAL_ERROR \"Failed to copy script-last-run stamp file: ' ${ gitclone_stampfile } '\ " )
endif ( )
"
)
endfunction ( )
function ( _ep_write_hgclone_script script_filename source_dir hg_EXECUTABLE hg_repository hg_tag src_name work_dir hgclone_infofile hgclone_stampfile )
file ( WRITE ${ script_filename }
" if ( \"${hg_tag}\" STREQUAL \"\")
message ( FATAL_ERROR \"Tag for hg checkout should not be empty.\ " )
endif ( )
set ( run 0 )
if ( \"${hgclone_infofile}\" IS_NEWER_THAN \"${hgclone_stampfile}\")
set ( run 1 )
endif ( )
if ( NOT run )
message ( STATUS \"Avoiding repeated hg clone, stamp file is up to date: ' ${ hgclone_stampfile } '\ " )
return ( )
endif ( )
execute_process (
C O M M A N D \ $ { C M A K E _ C O M M A N D } - E r e m o v e _ d i r e c t o r y \ " $ { s o u r c e _ d i r } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
)
if ( error_code )
message ( FATAL_ERROR \"Failed to remove directory: ' ${ source_dir } '\ " )
endif ( )
execute_process (
C O M M A N D \ " $ { h g _ E X E C U T A B L E } \ " c l o n e \ " $ { h g _ r e p o s i t o r y } \ " \ " $ { s r c _ n a m e } \ "
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
)
if ( error_code )
message ( FATAL_ERROR \"Failed to clone repository: ' ${ hg_repository } '\ " )
endif ( )
execute_process (
C O M M A N D \ " $ { h g _ E X E C U T A B L E } \ " u p d a t e $ { h g _ t a g }
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } / $ { s r c _ n a m e } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
)
if ( error_code )
message ( FATAL_ERROR \"Failed to checkout tag: ' ${ hg_tag } '\ " )
endif ( )
# Complete success, update the script-last-run stamp file:
#
execute_process (
C O M M A N D \ $ { C M A K E _ C O M M A N D } - E c o p y
\ " $ { h g c l o n e _ i n f o f i l e } \ "
\ " $ { h g c l o n e _ s t a m p f i l e } \ "
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } / $ { s r c _ n a m e } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
)
if ( error_code )
message ( FATAL_ERROR \"Failed to copy script-last-run stamp file: ' ${ hgclone_stampfile } '\ " )
endif ( )
"
)
endfunction ( )
function ( _ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_repository work_dir )
file ( WRITE ${ script_filename }
" if ( \"${git_tag}\" STREQUAL \"\")
message ( FATAL_ERROR \"Tag for git checkout should not be empty.\ " )
endif ( )
execute_process (
C O M M A N D \ " $ { g i t _ E X E C U T A B L E } \ " r e v - l i s t - - m a x - c o u n t = 1 H E A D
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
O U T P U T _ V A R I A B L E h e a d _ s h a
)
if ( error_code )
message ( FATAL_ERROR \"Failed to get the hash for HEAD\ " )
endif ( )
execute_process (
C O M M A N D \ " $ { g i t _ E X E C U T A B L E } \ " s h o w - r e f $ { g i t _ t a g }
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } \ "
O U T P U T _ V A R I A B L E s h o w _ r e f _ o u t p u t
)
# If a remote ref is asked for, which can possibly move around,
# we must always do a fetch and checkout.
if ( \"\${show_ref_output}\" MATCHES \"remotes\")
set ( is_remote_ref 1 )
else ( )
set ( is_remote_ref 0 )
endif ( )
# This will fail if the tag does not exist (it probably has not been fetched
# yet).
execute_process (
C O M M A N D \ " $ { g i t _ E X E C U T A B L E } \ " r e v - l i s t - - m a x - c o u n t = 1 $ { g i t _ t a g }
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
O U T P U T _ V A R I A B L E t a g _ s h a
)
# Is the hash checkout out that we want?
if ( error_code OR is_remote_ref OR NOT ( \"\${tag_sha}\" STREQUAL \"\${head_sha}\"))
execute_process (
C O M M A N D \ " $ { g i t _ E X E C U T A B L E } \ " f e t c h
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
)
if ( error_code )
message ( FATAL_ERROR \"Failed to fetch repository ' ${ git_repository } '\ " )
endif ( )
execute_process (
C O M M A N D \ " $ { g i t _ E X E C U T A B L E } \ " c h e c k o u t $ { g i t _ t a g }
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
)
if ( error_code )
message ( FATAL_ERROR \"Failed to checkout tag: ' ${ git_tag } '\ " )
endif ( )
execute_process (
C O M M A N D \ " $ { g i t _ E X E C U T A B L E } \ " s u b m o d u l e u p d a t e - - r e c u r s i v e
W O R K I N G _ D I R E C T O R Y \ " $ { w o r k _ d i r } / $ { s r c _ n a m e } \ "
R E S U L T _ V A R I A B L E e r r o r _ c o d e
)
if ( error_code )
message ( FATAL_ERROR \"Failed to update submodules in: ' ${ work_dir } / ${ src_name } '\ " )
endif ( )
endif ( )
"
)
endfunction ( _ep_write_gitupdate_script )
function ( _ep_write_downloadfile_script script_filename remote local timeout hash tls_verify tls_cainfo )
if ( timeout )
set ( timeout_args TIMEOUT ${ timeout } )
set ( timeout_msg "${timeout} seconds" )
else ( )
set ( timeout_args "# no TIMEOUT" )
set ( timeout_msg "none" )
endif ( )
if ( "${hash}" MATCHES "${_ep_hash_regex}" )
set ( hash_args EXPECTED_HASH ${ CMAKE_MATCH_1 } = ${ CMAKE_MATCH_2 } )
else ( )
set ( hash_args "# no EXPECTED_HASH" )
endif ( )
# check for curl globals in the project
if ( DEFINED CMAKE_TLS_VERIFY )
set ( tls_verify "set(CMAKE_TLS_VERIFY ${CMAKE_TLS_VERIFY})" )
endif ( )
if ( DEFINED CMAKE_TLS_CAINFO )
set ( tls_cainfo "set(CMAKE_TLS_CAINFO \" ${ CMAKE_TLS_CAINFO } \")")
endif ( )
# now check for curl locals so that the local values
# will override the globals
# check for tls_verify argument
string ( LENGTH "${tls_verify}" tls_verify_len )
if ( tls_verify_len GREATER 0 )
set ( tls_verify "set(CMAKE_TLS_VERIFY ${tls_verify})" )
endif ( )
# check for tls_cainfo argument
string ( LENGTH "${tls_cainfo}" tls_cainfo_len )
if ( tls_cainfo_len GREATER 0 )
set ( tls_cainfo "set(CMAKE_TLS_CAINFO \" ${ tls_cainfo } \")")
endif ( )
file ( WRITE ${ script_filename }
" message ( STATUS \"downloading...
s r c = ' $ { r e m o t e } '
d s t = ' $ { l o c a l } '
t i m e o u t = ' $ { t i m e o u t _ m s g } ' \ " )
$ { t l s _ v e r i f y }
$ { t l s _ c a i n f o }
file ( DOWNLOAD
\ " $ { r e m o t e } \ "
\ " $ { l o c a l } \ "
S H O W _ P R O G R E S S
$ { h a s h _ a r g s }
$ { t i m e o u t _ a r g s }
S T A T U S s t a t u s
L O G l o g )
list ( GET status 0 status_code )
list ( GET status 1 status_string )
if ( NOT status_code EQUAL 0 )
message ( FATAL_ERROR \"error: downloading ' ${ remote } ' failed
s t a t u s _ c o d e : \ $ { s t a t u s _ c o d e }
s t a t u s _ s t r i n g : \ $ { s t a t u s _ s t r i n g }
l o g : \ $ { l o g }
\ " )
endif ( )
message ( STATUS \"downloading... done\ " )
"
)
endfunction ( )
function ( _ep_write_verifyfile_script script_filename local hash )
if ( "${hash}" MATCHES "${_ep_hash_regex}" )
set ( algo "${CMAKE_MATCH_1}" )
string ( TOLOWER "${CMAKE_MATCH_2}" expect_value )
set ( script_content "set(expect_value \" ${ expect_value } \")
file ( ${ algo } \"\${file}\" actual_value )
if ( \"\${actual_value}\" STREQUAL \"\${expect_value}\")
message ( STATUS \"verifying file... done\ " )
else ( )
message ( FATAL_ERROR \"error: ${ algo } hash of
\ $ { f i l e }
d o e s n o t m a t c h e x p e c t e d v a l u e
e x p e c t e d : \ $ { e x p e c t _ v a l u e }
a c t u a l : \ $ { a c t u a l _ v a l u e }
\ " )
endif ( ) " )
else ( )
set ( script_content "message(STATUS \" verifying file... warning: did not verify file - no URL_HASH specified?\ ")" )
endif ( )
file ( WRITE ${ script_filename } "set(file \" ${ local } \")
message ( STATUS \"verifying file...
f i l e = ' \ $ { f i l e } ' \ " )
$ { s c r i p t _ c o n t e n t }
" )
endfunction ( )
function ( _ep_write_extractfile_script script_filename name filename directory )
set ( args "" )
if ( filename MATCHES "(\\.|=)(bz2|tar\\.gz|tgz|zip)$" )
set ( args xfz )
endif ( )
if ( filename MATCHES "(\\.|=)tar$" )
set ( args xf )
endif ( )
if ( args STREQUAL "" )
message ( SEND_ERROR "error: do not know how to extract '${filename}' -- known types are .bz2, .tar, .tar.gz, .tgz and .zip" )
return ( )
endif ( )
file ( WRITE ${ script_filename }
" # Make file names absolute:
#
get_filename_component ( filename \"${filename}\" ABSOLUTE )
get_filename_component ( directory \"${directory}\" ABSOLUTE )
message ( STATUS \"extracting...
s r c = ' \ $ { f i l e n a m e } '
d s t = ' \ $ { d i r e c t o r y } ' \ " )
if ( NOT EXISTS \"\${filename}\")
message ( FATAL_ERROR \"error: file to extract does not exist: '\ ${ filename } '\ " )
endif ( )
# Prepare a space for extracting:
#
set ( i 1234 )
while ( EXISTS \"\${directory}/../ex-${name}\${i}\")
math ( EXPR i \"\${i} + 1\ " )
endwhile ( )
set ( ut_dir \"\${directory}/../ex-${name}\${i}\")
file ( MAKE_DIRECTORY \"\${ut_dir}\")
# Extract it:
#
message ( STATUS \"extracting... [tar ${ args } ]\ " )
execute_process ( COMMAND \${CMAKE_COMMAND} -E tar ${ args } \${filename}
W O R K I N G _ D I R E C T O R Y \ $ { u t _ d i r }
R E S U L T _ V A R I A B L E r v )
if ( NOT rv EQUAL 0 )
message ( STATUS \"extracting... [error clean up]\ " )
file ( REMOVE_RECURSE \"\${ut_dir}\")
message ( FATAL_ERROR \"error: extract of '\ ${ filename } ' failed\ " )
endif ( )
# Analyze what came out of the tar file:
#
message ( STATUS \"extracting... [analysis]\ " )
file ( GLOB contents \"\${ut_dir}/*\")
list ( LENGTH contents n )
if ( NOT n EQUAL 1 OR NOT IS_DIRECTORY \"\${contents}\")
set ( contents \"\${ut_dir}\")
endif ( )
# Move \"the one\" directory to the final directory:
#
message ( STATUS \"extracting... [rename]\ " )
file ( REMOVE_RECURSE \${directory})
get_filename_component ( contents \${contents} ABSOLUTE )
file ( RENAME \${contents} \${directory})
# Clean up:
#
message ( STATUS \"extracting... [clean up]\ " )
file ( REMOVE_RECURSE \"\${ut_dir}\")
message ( STATUS \"extracting... done\ " )
"
)
endfunction ( )
function ( _ep_set_directories name )
get_property ( prefix TARGET ${ name } PROPERTY _EP_PREFIX )
if ( NOT prefix )
get_property ( prefix DIRECTORY PROPERTY EP_PREFIX )
if ( NOT prefix )
get_property ( base DIRECTORY PROPERTY EP_BASE )
if ( NOT base )
set ( prefix "${name}-prefix" )
endif ( )
endif ( )
endif ( )
if ( prefix )
set ( tmp_default "${prefix}/tmp" )
set ( download_default "${prefix}/src" )
set ( source_default "${prefix}/src/${name}" )
set ( binary_default "${prefix}/src/${name}-build" )
set ( stamp_default "${prefix}/src/${name}-stamp" )
set ( install_default "${prefix}" )
else ( )
set ( tmp_default "${base}/tmp/${name}" )
set ( download_default "${base}/Download/${name}" )
set ( source_default "${base}/Source/${name}" )
set ( binary_default "${base}/Build/${name}" )
set ( stamp_default "${base}/Stamp/${name}" )
set ( install_default "${base}/Install/${name}" )
endif ( )
get_property ( build_in_source TARGET ${ name } PROPERTY _EP_BUILD_IN_SOURCE )
if ( build_in_source )
get_property ( have_binary_dir TARGET ${ name } PROPERTY _EP_BINARY_DIR SET )
if ( have_binary_dir )
message ( FATAL_ERROR
" E x t e r n a l p r o j e c t $ { n a m e } h a s b o t h B I N A R Y _ D I R a n d B U I L D _ I N _ S O U R C E ! " )
endif ( )
endif ( )
set ( top "${CMAKE_CURRENT_BINARY_DIR}" )
set ( places stamp download source binary install tmp )
foreach ( var ${ places } )
string ( TOUPPER "${var}" VAR )
get_property ( ${ var } _dir TARGET ${ name } PROPERTY _EP_ ${ VAR } _DIR )
if ( NOT ${ var } _dir )
set ( ${ var } _dir "${${var}_default}" )
endif ( )
if ( NOT IS_ABSOLUTE "${${var}_dir}" )
get_filename_component ( ${ var } _dir "${top}/${${var}_dir}" ABSOLUTE )
endif ( )
set_property ( TARGET ${ name } PROPERTY _EP_ ${ VAR } _DIR "${${var}_dir}" )
endforeach ( )
if ( build_in_source )
get_property ( source_dir TARGET ${ name } PROPERTY _EP_SOURCE_DIR )
set_property ( TARGET ${ name } PROPERTY _EP_BINARY_DIR "${source_dir}" )
endif ( )
# Make the directories at CMake configure time *and* add a custom command
# to make them at build time. They need to exist at makefile generation
# time for Borland make and wmake so that CMake may generate makefiles
# with "cd C:\short\paths\with\no\spaces" commands in them.
#
# Additionally, the add_custom_command is still used in case somebody
# removes one of the necessary directories and tries to rebuild without
# re-running cmake.
foreach ( var ${ places } )
string ( TOUPPER "${var}" VAR )
get_property ( dir TARGET ${ name } PROPERTY _EP_ ${ VAR } _DIR )
file ( MAKE_DIRECTORY "${dir}" )
if ( NOT EXISTS "${dir}" )
message ( FATAL_ERROR "dir '${dir}' does not exist after file(MAKE_DIRECTORY)" )
endif ( )
endforeach ( )
endfunction ( )
# IMPORTANT: this MUST be a macro and not a function because of the
# in-place replacements that occur in each ${var}
#
macro ( _ep_replace_location_tags target_name )
set ( vars ${ ARGN } )
foreach ( var ${ vars } )
if ( ${ var } )
foreach ( dir SOURCE_DIR BINARY_DIR INSTALL_DIR TMP_DIR )
get_property ( val TARGET ${ target_name } PROPERTY _EP_ ${ dir } )
string ( REPLACE "<${dir}>" "${val}" ${ var } "${${var}}" )
endforeach ( )
endif ( )
endforeach ( )
endmacro ( )
function ( _ep_write_initial_cache target_name script_filename args )
# Write out values into an initial cache, that will be passed to CMake with -C
set ( script_initial_cache "" )
set ( regex "^([^:]+):([^=]+)=(.*)$" )
set ( setArg "" )
foreach ( line ${ args } )
if ( "${line}" MATCHES "^-D" )
if ( setArg )
# This is required to build up lists in variables, or complete an entry
set ( setArg "${setArg}${accumulator}\" CACHE ${ type } \"Initial cache\ " FORCE)" )
set ( script_initial_cache "${script_initial_cache}\n${setArg}" )
set ( accumulator "" )
set ( setArg "" )
endif ( )
string ( REGEX REPLACE "^-D" "" line ${ line } )
if ( "${line}" MATCHES "${regex}" )
string ( REGEX MATCH "${regex}" match "${line}" )
set ( name "${CMAKE_MATCH_1}" )
set ( type "${CMAKE_MATCH_2}" )
set ( value "${CMAKE_MATCH_3}" )
set ( setArg "set(${name} \" ${ value } " )
else ( )
message ( WARNING "Line '${line}' does not match regex. Ignoring." )
endif ( )
else ( )
# Assume this is a list to append to the last var
set ( accumulator "${accumulator};${line}" )
endif ( )
endforeach ( )
# Catch the final line of the args
if ( setArg )
set ( setArg "${setArg}${accumulator}\" CACHE ${ type } \"Initial cache\ " FORCE)" )
set ( script_initial_cache "${script_initial_cache}\n${setArg}" )
endif ( )
# Replace location tags.
_ep_replace_location_tags ( ${ target_name } script_initial_cache )
# Write out the initial cache file to the location specified.
if ( NOT EXISTS "${script_filename}.in" )
file ( WRITE "${script_filename}.in" "\@script_initial_cache\@\n" )
endif ( )
configure_file ( "${script_filename}.in" "${script_filename}" )
endfunction ( )
function ( ExternalProject_Get_Property name )
foreach ( var ${ ARGN } )
string ( TOUPPER "${var}" VAR )
get_property ( ${ var } TARGET ${ name } PROPERTY _EP_ ${ VAR } )
if ( NOT ${ var } )
message ( FATAL_ERROR "External project \" ${ name } \" has no ${ var } " )
endif ( )
set ( ${ var } "${${var}}" PARENT_SCOPE )
endforeach ( )
endfunction ( )
function ( _ep_get_configure_command_id name cfg_cmd_id_var )
get_target_property ( cmd ${ name } _EP_CONFIGURE_COMMAND )
if ( cmd STREQUAL "" )
# Explicit empty string means no configure step for this project
set ( ${ cfg_cmd_id_var } "none" PARENT_SCOPE )
else ( )
if ( NOT cmd )
# Default is "use cmake":
set ( ${ cfg_cmd_id_var } "cmake" PARENT_SCOPE )
else ( )
# Otherwise we have to analyze the value:
if ( cmd MATCHES "^[^;]*/configure" )
set ( ${ cfg_cmd_id_var } "configure" PARENT_SCOPE )
elseif ( cmd MATCHES "^[^;]*/cmake" AND NOT cmd MATCHES ";-[PE];" )
set ( ${ cfg_cmd_id_var } "cmake" PARENT_SCOPE )
elseif ( cmd MATCHES "config" )
set ( ${ cfg_cmd_id_var } "configure" PARENT_SCOPE )
else ( )
set ( ${ cfg_cmd_id_var } "unknown:${cmd}" PARENT_SCOPE )
endif ( )
endif ( )
endif ( )
endfunction ( )
function ( _ep_get_build_command name step cmd_var )
set ( cmd "${${cmd_var}}" )
if ( NOT cmd )
set ( args )
_ep_get_configure_command_id ( ${ name } cfg_cmd_id )
if ( cfg_cmd_id STREQUAL "cmake" )
# CMake project. Select build command based on generator.
get_target_property ( cmake_generator ${ name } _EP_CMAKE_GENERATOR )
if ( "${CMAKE_GENERATOR}" MATCHES "Make" AND
( " $ { c m a k e _ g e n e r a t o r } " M A T C H E S " M a k e " O R N O T c m a k e _ g e n e r a t o r ) )
# The project uses the same Makefile generator. Use recursive make.
set ( cmd "$(MAKE)" )
if ( step STREQUAL "INSTALL" )
set ( args install )
endif ( )
if ( step STREQUAL "TEST" )
set ( args test )
endif ( )
else ( )
# Drive the project with "cmake --build".
get_target_property ( cmake_command ${ name } _EP_CMAKE_COMMAND )
if ( cmake_command )
set ( cmd "${cmake_command}" )
else ( )
set ( cmd "${CMAKE_COMMAND}" )
endif ( )
set ( args --build ${ binary_dir } --config ${ CMAKE_CFG_INTDIR } )
if ( step STREQUAL "INSTALL" )
list ( APPEND args --target install )
endif ( )
# But for "TEST" drive the project with corresponding "ctest".
if ( step STREQUAL "TEST" )
string ( REGEX REPLACE "^(.*/)cmake([^/]*)$" "\\1ctest\\2" cmd "${cmd}" )
set ( args "" )
endif ( )
endif ( )
else ( )
# Non-CMake project. Guess "make" and "make install" and "make test".
if ( "${CMAKE_GENERATOR}" MATCHES "Makefiles" )
# Try to get the parallel arguments
set ( cmd "$(MAKE)" )
else ( )
set ( cmd "make" )
endif ( )
if ( step STREQUAL "INSTALL" )
set ( args install )
endif ( )
if ( step STREQUAL "TEST" )
set ( args test )
endif ( )
endif ( )
# Use user-specified arguments instead of default arguments, if any.
get_property ( have_args TARGET ${ name } PROPERTY _EP_ ${ step } _ARGS SET )
if ( have_args )
get_target_property ( args ${ name } _EP_ ${ step } _ARGS )
endif ( )
list ( APPEND cmd ${ args } )
endif ( )
set ( ${ cmd_var } "${cmd}" PARENT_SCOPE )
endfunction ( )
function ( _ep_write_log_script name step cmd_var )
ExternalProject_Get_Property ( ${ name } stamp_dir )
set ( command "${${cmd_var}}" )
set ( make "" )
set ( code_cygpath_make "" )
if ( "${command}" MATCHES "^\\$\\(MAKE\\)" )
# GNU make recognizes the string "$(MAKE)" as recursive make, so
# ensure that it appears directly in the makefile.
string ( REGEX REPLACE "^\\$\\(MAKE\\)" "\${make}" command "${command}" )
set ( make "-Dmake=$(MAKE)" )
if ( WIN32 AND NOT CYGWIN )
set ( code_cygpath_make "
if ( \${make} MATCHES \"^/\")
execute_process (
C O M M A N D c y g p a t h - w \ $ { m a k e }
O U T P U T _ V A R I A B L E c y g p a t h _ m a k e
E R R O R _ V A R I A B L E c y g p a t h _ m a k e
R E S U L T _ V A R I A B L E c y g p a t h _ e r r o r
O U T P U T _ S T R I P _ T R A I L I N G _ W H I T E S P A C E
)
if ( NOT cygpath_error )
set ( make \${cygpath_make})
endif ( )
endif ( )
" )
endif ( )
endif ( )
set ( config "" )
if ( "${CMAKE_CFG_INTDIR}" MATCHES "^\\$" )
string ( REPLACE "${CMAKE_CFG_INTDIR}" "\${config}" command "${command}" )
set ( config "-Dconfig=${CMAKE_CFG_INTDIR}" )
endif ( )
# Wrap multiple 'COMMAND' lines up into a second-level wrapper
# script so all output can be sent to one log file.
if ( "${command}" MATCHES ";COMMAND;" )
set ( code_execute_process "
$ { c o d e _ c y g p a t h _ m a k e }
execute_process ( COMMAND \${command} RESULT_VARIABLE result )
if ( result )
set ( msg \"Command failed ( \${result}):\\n\")
foreach ( arg IN LISTS command )
set ( msg \"\${msg} '\ ${ arg } '\ " )
endforeach ( )
message ( FATAL_ERROR \"\${msg}\")
endif ( )
" )
set ( code "" )
set ( cmd "" )
set ( sep "" )
foreach ( arg IN LISTS command )
if ( "x${arg}" STREQUAL "xCOMMAND" )
set ( code "${code}set(command \" ${ cmd } \")${code_execute_process}")
set ( cmd "" )
set ( sep "" )
else ( )
set ( cmd "${cmd}${sep}${arg}" )
set ( sep ";" )
endif ( )
endforeach ( )
set ( code "set(ENV{VS_UNICODE_OUTPUT} \" \")\n${code}set(command \"${cmd}\")${code_execute_process}")
file ( WRITE ${ stamp_dir } / ${ name } - ${ step } -impl.cmake "${code}" )
set ( command ${ CMAKE_COMMAND } "-Dmake=\${make}" "-Dconfig=\${config}" -P ${ stamp_dir } / ${ name } - ${ step } -impl.cmake )
endif ( )
# Wrap the command in a script to log output to files.
set ( script ${ stamp_dir } / ${ name } - ${ step } .cmake )
set ( logbase ${ stamp_dir } / ${ name } - ${ step } )
file ( WRITE ${ script } "
$ { c o d e _ c y g p a t h _ m a k e }
set ( ENV{VS_UNICODE_OUTPUT} \"\")
set ( command \"${command}\")
execute_process (
C O M M A N D \ $ { c o m m a n d }
R E S U L T _ V A R I A B L E r e s u l t
O U T P U T _ F I L E \ " $ { l o g b a s e } - o u t . l o g \ "
E R R O R _ F I L E \ " $ { l o g b a s e } - e r r . l o g \ "
)
if ( result )
set ( msg \"Command failed: \${result}\\n\")
foreach ( arg IN LISTS command )
set ( msg \"\${msg} '\ ${ arg } '\ " )
endforeach ( )
set ( msg \"\${msg}\\nSee also\\n ${ logbase } -*.log\\n\ " )
message ( FATAL_ERROR \"\${msg}\")
else ( )
set ( msg \"${name} ${ step } command succeeded. See also ${ logbase } -*.log\\n\ " )
message ( STATUS \"\${msg}\")
endif ( )
" )
set ( command ${ CMAKE_COMMAND } ${ make } ${ config } -P ${ script } )
set ( ${ cmd_var } "${command}" PARENT_SCOPE )
endfunction ( )
# This module used to use "/${CMAKE_CFG_INTDIR}" directly and produced
# makefiles with "/./" in paths for custom command dependencies. Which
# resulted in problems with parallel make -j invocations.
#
# This function was added so that the suffix (search below for ${cfgdir}) is
# only set to "/${CMAKE_CFG_INTDIR}" when ${CMAKE_CFG_INTDIR} is not going to
# be "." (multi-configuration build systems like Visual Studio and Xcode...)
#
function ( _ep_get_configuration_subdir_suffix suffix_var )
set ( suffix "" )
if ( CMAKE_CONFIGURATION_TYPES )
set ( suffix "/${CMAKE_CFG_INTDIR}" )
endif ( )
set ( ${ suffix_var } "${suffix}" PARENT_SCOPE )
endfunction ( )
function ( _ep_get_step_stampfile name step stampfile_var )
ExternalProject_Get_Property ( ${ name } stamp_dir )
_ep_get_configuration_subdir_suffix ( cfgdir )
set ( stampfile "${stamp_dir}${cfgdir}/${name}-${step}" )
set ( ${ stampfile_var } "${stampfile}" PARENT_SCOPE )
endfunction ( )
function ( ExternalProject_Add_StepTargets name )
set ( steps ${ ARGN } )
foreach ( step ${ steps } )
_ep_get_step_stampfile ( ${ name } ${ step } stamp_file )
add_custom_target ( ${ name } - ${ step }
D E P E N D S $ { s t a m p _ f i l e } )
# Depend on other external projects (target-level).
get_property ( deps TARGET ${ name } PROPERTY _EP_DEPENDS )
foreach ( arg IN LISTS deps )
add_dependencies ( ${ name } - ${ step } ${ arg } )
endforeach ( )
endforeach ( )
endfunction ( )
function ( ExternalProject_Add_Step name step )
set ( cmf_dir ${ CMAKE_CURRENT_BINARY_DIR } /CMakeFiles )
_ep_get_configuration_subdir_suffix ( cfgdir )
set ( complete_stamp_file "${cmf_dir}${cfgdir}/${name}-complete" )
_ep_get_step_stampfile ( ${ name } ${ step } stamp_file )
add_custom_command ( APPEND
O U T P U T $ { c o m p l e t e _ s t a m p _ f i l e }
D E P E N D S $ { s t a m p _ f i l e }
)
_ep_parse_arguments ( ExternalProject_Add_Step
$ { n a m e } _ E P _ $ { s t e p } _ " $ { A R G N } " )
# Steps depending on this step.
get_property ( dependers TARGET ${ name } PROPERTY _EP_ ${ step } _DEPENDERS )
foreach ( depender IN LISTS dependers )
_ep_get_step_stampfile ( ${ name } ${ depender } depender_stamp_file )
add_custom_command ( APPEND
O U T P U T $ { d e p e n d e r _ s t a m p _ f i l e }
D E P E N D S $ { s t a m p _ f i l e }
)
endforeach ( )
# Dependencies on files.
get_property ( depends TARGET ${ name } PROPERTY _EP_ ${ step } _DEPENDS )
# Dependencies on steps.
get_property ( dependees TARGET ${ name } PROPERTY _EP_ ${ step } _DEPENDEES )
foreach ( dependee IN LISTS dependees )
_ep_get_step_stampfile ( ${ name } ${ dependee } dependee_stamp_file )
list ( APPEND depends ${ dependee_stamp_file } )
endforeach ( )
# The command to run.
get_property ( command TARGET ${ name } PROPERTY _EP_ ${ step } _COMMAND )
if ( command )
set ( comment "Performing ${step} step for '${name}'" )
else ( )
set ( comment "No ${step} step for '${name}'" )
endif ( )
get_property ( work_dir TARGET ${ name } PROPERTY _EP_ ${ step } _WORKING_DIRECTORY )
# Replace list separators.
get_property ( sep TARGET ${ name } PROPERTY _EP_LIST_SEPARATOR )
if ( sep AND command )
string ( REPLACE "${sep}" "\\;" command "${command}" )
endif ( )
# Replace location tags.
_ep_replace_location_tags ( ${ name } comment command work_dir )
# Custom comment?
get_property ( comment_set TARGET ${ name } PROPERTY _EP_ ${ step } _COMMENT SET )
if ( comment_set )
get_property ( comment TARGET ${ name } PROPERTY _EP_ ${ step } _COMMENT )
endif ( )
# Run every time?
get_property ( always TARGET ${ name } PROPERTY _EP_ ${ step } _ALWAYS )
if ( always )
set_property ( SOURCE ${ stamp_file } PROPERTY SYMBOLIC 1 )
set ( touch )
else ( )
set ( touch ${ CMAKE_COMMAND } -E touch ${ stamp_file } )
endif ( )
# Wrap with log script?
get_property ( log TARGET ${ name } PROPERTY _EP_ ${ step } _LOG )
if ( command AND log )
_ep_write_log_script ( ${ name } ${ step } command )
endif ( )
add_custom_command (
O U T P U T $ { s t a m p _ f i l e }
C O M M E N T $ { c o m m e n t }
C O M M A N D $ { c o m m a n d }
C O M M A N D $ { t o u c h }
D E P E N D S $ { d e p e n d s }
W O R K I N G _ D I R E C T O R Y $ { w o r k _ d i r }
V E R B A T I M
)
# Add custom "step target"?
get_property ( step_targets TARGET ${ name } PROPERTY _EP_STEP_TARGETS )
if ( NOT step_targets )
get_property ( step_targets DIRECTORY PROPERTY EP_STEP_TARGETS )
endif ( )
foreach ( st ${ step_targets } )
if ( "${st}" STREQUAL "${step}" )
ExternalProject_Add_StepTargets ( ${ name } ${ step } )
break ( )
endif ( )
endforeach ( )
endfunction ( )
function ( _ep_add_mkdir_command name )
ExternalProject_Get_Property ( ${ name }
s o u r c e _ d i r b i n a r y _ d i r i n s t a l l _ d i r s t a m p _ d i r d o w n l o a d _ d i r t m p _ d i r )
_ep_get_configuration_subdir_suffix ( cfgdir )
ExternalProject_Add_Step ( ${ name } mkdir
C O M M E N T " C r e a t i n g d i r e c t o r i e s f o r ' $ { n a m e } ' "
C O M M A N D $ { C M A K E _ C O M M A N D } - E m a k e _ d i r e c t o r y $ { s o u r c e _ d i r }
C O M M A N D $ { C M A K E _ C O M M A N D } - E m a k e _ d i r e c t o r y $ { b i n a r y _ d i r }
C O M M A N D $ { C M A K E _ C O M M A N D } - E m a k e _ d i r e c t o r y $ { i n s t a l l _ d i r }
C O M M A N D $ { C M A K E _ C O M M A N D } - E m a k e _ d i r e c t o r y $ { t m p _ d i r }
C O M M A N D $ { C M A K E _ C O M M A N D } - E m a k e _ d i r e c t o r y $ { s t a m p _ d i r } $ { c f g d i r }
C O M M A N D $ { C M A K E _ C O M M A N D } - E m a k e _ d i r e c t o r y $ { d o w n l o a d _ d i r }
)
endfunction ( )
function ( _ep_get_git_version git_EXECUTABLE git_version_var )
if ( git_EXECUTABLE )
execute_process (
C O M M A N D " $ { g i t _ E X E C U T A B L E } " - - v e r s i o n
O U T P U T _ V A R I A B L E o v
E R R O R _ V A R I A B L E e v
O U T P U T _ S T R I P _ T R A I L I N G _ W H I T E S P A C E
)
string ( REGEX REPLACE "^git version (.+)$" "\\1" version "${ov}" )
set ( ${ git_version_var } "${version}" PARENT_SCOPE )
endif ( )
endfunction ( )
function ( _ep_is_dir_empty dir empty_var )
file ( GLOB gr "${dir}/*" )
if ( "${gr}" STREQUAL "" )
set ( ${ empty_var } 1 PARENT_SCOPE )
else ( )
set ( ${ empty_var } 0 PARENT_SCOPE )
endif ( )
endfunction ( )
function ( _ep_add_download_command name )
ExternalProject_Get_Property ( ${ name } source_dir stamp_dir download_dir tmp_dir )
get_property ( cmd_set TARGET ${ name } PROPERTY _EP_DOWNLOAD_COMMAND SET )
get_property ( cmd TARGET ${ name } PROPERTY _EP_DOWNLOAD_COMMAND )
get_property ( cvs_repository TARGET ${ name } PROPERTY _EP_CVS_REPOSITORY )
get_property ( svn_repository TARGET ${ name } PROPERTY _EP_SVN_REPOSITORY )
get_property ( git_repository TARGET ${ name } PROPERTY _EP_GIT_REPOSITORY )
get_property ( hg_repository TARGET ${ name } PROPERTY _EP_HG_REPOSITORY )
get_property ( url TARGET ${ name } PROPERTY _EP_URL )
get_property ( fname TARGET ${ name } PROPERTY _EP_DOWNLOAD_NAME )
# TODO: Perhaps file:// should be copied to download dir before extraction.
string ( REGEX REPLACE "^file://" "" url "${url}" )
set ( depends )
set ( comment )
set ( work_dir )
if ( cmd_set )
set ( work_dir ${ download_dir } )
elseif ( cvs_repository )
find_package ( CVS )
if ( NOT CVS_EXECUTABLE )
message ( FATAL_ERROR "error: could not find cvs for checkout of ${name}" )
endif ( )
get_target_property ( cvs_module ${ name } _EP_CVS_MODULE )
if ( NOT cvs_module )
message ( FATAL_ERROR "error: no CVS_MODULE" )
endif ( )
get_property ( cvs_tag TARGET ${ name } PROPERTY _EP_CVS_TAG )
set ( repository ${ cvs_repository } )
set ( module ${ cvs_module } )
set ( tag ${ cvs_tag } )
configure_file (
" $ { C M A K E _ R O O T } / M o d u l e s / R e p o s i t o r y I n f o . t x t . i n "
" $ { s t a m p _ d i r } / $ { n a m e } - c v s i n f o . t x t "
@ O N L Y
)
get_filename_component ( src_name "${source_dir}" NAME )
get_filename_component ( work_dir "${source_dir}" PATH )
set ( comment "Performing download step (CVS checkout) for '${name}'" )
set ( cmd ${ CVS_EXECUTABLE } -d ${ cvs_repository } -q co ${ cvs_tag } -d ${ src_name } ${ cvs_module } )
list ( APPEND depends ${ stamp_dir } / ${ name } -cvsinfo.txt )
elseif ( svn_repository )
find_package ( Subversion )
if ( NOT Subversion_SVN_EXECUTABLE )
message ( FATAL_ERROR "error: could not find svn for checkout of ${name}" )
endif ( )
get_property ( svn_revision TARGET ${ name } PROPERTY _EP_SVN_REVISION )
get_property ( svn_username TARGET ${ name } PROPERTY _EP_SVN_USERNAME )
get_property ( svn_password TARGET ${ name } PROPERTY _EP_SVN_PASSWORD )
get_property ( svn_trust_cert TARGET ${ name } PROPERTY _EP_SVN_TRUST_CERT )
set ( repository "${svn_repository} user=${svn_username} password=${svn_password}" )
set ( module )
set ( tag ${ svn_revision } )
configure_file (
" $ { C M A K E _ R O O T } / M o d u l e s / R e p o s i t o r y I n f o . t x t . i n "
" $ { s t a m p _ d i r } / $ { n a m e } - s v n i n f o . t x t "
@ O N L Y
)
get_filename_component ( src_name "${source_dir}" NAME )
get_filename_component ( work_dir "${source_dir}" PATH )
set ( comment "Performing download step (SVN checkout) for '${name}'" )
set ( svn_user_pw_args "" )
if ( svn_username )
set ( svn_user_pw_args ${ svn_user_pw_args } "--username=${svn_username}" )
endif ( )
if ( svn_password )
set ( svn_user_pw_args ${ svn_user_pw_args } "--password=${svn_password}" )
endif ( )
if ( svn_trust_cert )
set ( svn_trust_cert_args --trust-server-cert )
endif ( )
set ( cmd ${ Subversion_SVN_EXECUTABLE } co ${ svn_repository } ${ svn_revision }
- - n o n - i n t e r a c t i v e $ { s v n _ t r u s t _ c e r t _ a r g s } $ { s v n _ u s e r _ p w _ a r g s } $ { s r c _ n a m e } )
list ( APPEND depends ${ stamp_dir } / ${ name } -svninfo.txt )
elseif ( git_repository )
find_package ( Git )
if ( NOT GIT_EXECUTABLE )
message ( FATAL_ERROR "error: could not find git for clone of ${name}" )
endif ( )
# The git submodule update '--recursive' flag requires git >= v1.6.5
#
_ep_get_git_version ( "${GIT_EXECUTABLE}" git_version )
if ( git_version VERSION_LESS 1.6.5 )
message ( FATAL_ERROR "error: git version 1.6.5 or later required for 'git submodule update --recursive': git_version='${git_version}'" )
endif ( )
get_property ( git_tag TARGET ${ name } PROPERTY _EP_GIT_TAG )
if ( NOT git_tag )
set ( git_tag "master" )
endif ( )
# For the download step, and the git clone operation, only the repository
# should be recorded in a configured RepositoryInfo file. If the repo
# changes, the clone script should be run again. But if only the tag
# changes, avoid running the clone script again. Let the 'always' running
# update step checkout the new tag.
#
set ( repository ${ git_repository } )
set ( module )
set ( tag )
configure_file (
" $ { C M A K E _ R O O T } / M o d u l e s / R e p o s i t o r y I n f o . t x t . i n "
" $ { s t a m p _ d i r } / $ { n a m e } - g i t i n f o . t x t "
@ O N L Y
)
get_filename_component ( src_name "${source_dir}" NAME )
get_filename_component ( work_dir "${source_dir}" PATH )
# Since git clone doesn't succeed if the non-empty source_dir exists,
# create a cmake script to invoke as download command.
# The script will delete the source directory and then call git clone.
#
_ep_write_gitclone_script ( ${ tmp_dir } / ${ name } -gitclone.cmake ${ source_dir }
$ { G I T _ E X E C U T A B L E } $ { g i t _ r e p o s i t o r y } $ { g i t _ t a g } $ { s r c _ n a m e } $ { w o r k _ d i r }
$ { s t a m p _ d i r } / $ { n a m e } - g i t i n f o . t x t $ { s t a m p _ d i r } / $ { n a m e } - g i t c l o n e - l a s t r u n . t x t
)
set ( comment "Performing download step (git clone) for '${name}'" )
set ( cmd ${ CMAKE_COMMAND } -P ${ tmp_dir } / ${ name } -gitclone.cmake )
list ( APPEND depends ${ stamp_dir } / ${ name } -gitinfo.txt )
elseif ( hg_repository )
find_package ( Hg )
if ( NOT HG_EXECUTABLE )
message ( FATAL_ERROR "error: could not find hg for clone of ${name}" )
endif ( )
get_property ( hg_tag TARGET ${ name } PROPERTY _EP_HG_TAG )
if ( NOT hg_tag )
set ( hg_tag "tip" )
endif ( )
# For the download step, and the hg clone operation, only the repository
# should be recorded in a configured RepositoryInfo file. If the repo
# changes, the clone script should be run again. But if only the tag
# changes, avoid running the clone script again. Let the 'always' running
# update step checkout the new tag.
#
set ( repository ${ hg_repository } )
set ( module )
set ( tag )
configure_file (
" $ { C M A K E _ R O O T } / M o d u l e s / R e p o s i t o r y I n f o . t x t . i n "
" $ { s t a m p _ d i r } / $ { n a m e } - h g i n f o . t x t "
@ O N L Y
)
get_filename_component ( src_name "${source_dir}" NAME )
get_filename_component ( work_dir "${source_dir}" PATH )
# Since hg clone doesn't succeed if the non-empty source_dir exists,
# create a cmake script to invoke as download command.
# The script will delete the source directory and then call hg clone.
#
_ep_write_hgclone_script ( ${ tmp_dir } / ${ name } -hgclone.cmake ${ source_dir }
$ { H G _ E X E C U T A B L E } $ { h g _ r e p o s i t o r y } $ { h g _ t a g } $ { s r c _ n a m e } $ { w o r k _ d i r }
$ { s t a m p _ d i r } / $ { n a m e } - h g i n f o . t x t $ { s t a m p _ d i r } / $ { n a m e } - h g c l o n e - l a s t r u n . t x t
)
set ( comment "Performing download step (hg clone) for '${name}'" )
set ( cmd ${ CMAKE_COMMAND } -P ${ tmp_dir } / ${ name } -hgclone.cmake )
list ( APPEND depends ${ stamp_dir } / ${ name } -hginfo.txt )
elseif ( url )
get_filename_component ( work_dir "${source_dir}" PATH )
get_property ( hash TARGET ${ name } PROPERTY _EP_URL_HASH )
if ( hash AND NOT "${hash}" MATCHES "${_ep_hash_regex}" )
message ( FATAL_ERROR "URL_HASH is set to\n ${hash}\n"
" b u t m u s t b e A L G O = v a l u e w h e r e A L G O i s \ n $ { _ e p _ h a s h _ a l g o s } \ n "
" a n d v a l u e i s a h e x s t r i n g . " )
endif ( )
get_property ( md5 TARGET ${ name } PROPERTY _EP_URL_MD5 )
if ( md5 AND NOT "MD5=${md5}" MATCHES "${_ep_hash_regex}" )
message ( FATAL_ERROR "URL_MD5 is set to\n ${md5}\nbut must be a hex string." )
endif ( )
if ( md5 AND NOT hash )
set ( hash "MD5=${md5}" )
endif ( )
set ( repository "external project URL" )
set ( module "${url}" )
set ( tag "${hash}" )
configure_file (
" $ { C M A K E _ R O O T } / M o d u l e s / R e p o s i t o r y I n f o . t x t . i n "
" $ { s t a m p _ d i r } / $ { n a m e } - u r l i n f o . t x t "
@ O N L Y
)
list ( APPEND depends ${ stamp_dir } / ${ name } -urlinfo.txt )
if ( IS_DIRECTORY "${url}" )
get_filename_component ( abs_dir "${url}" ABSOLUTE )
set ( comment "Performing download step (DIR copy) for '${name}'" )
set ( cmd ${ CMAKE_COMMAND } -E remove_directory ${ source_dir }
C O M M A N D $ { C M A K E _ C O M M A N D } - E c o p y _ d i r e c t o r y $ { a b s _ d i r } $ { s o u r c e _ d i r } )
else ( )
if ( "${url}" MATCHES "^[a-z]+://" )
# TODO: Should download and extraction be different steps?
if ( "x${fname}" STREQUAL "x" )
string ( REGEX MATCH "[^/\\?]*$" fname "${url}" )
endif ( )
if ( NOT "${fname}" MATCHES "(\\.|=)(bz2|tar|tgz|tar\\.gz|zip)$" )
string ( REGEX MATCH "([^/\\?]+(\\.|=)(bz2|tar|tgz|tar\\.gz|zip))/.*$" match_result "${url}" )
set ( fname "${CMAKE_MATCH_1}" )
endif ( )
if ( NOT "${fname}" MATCHES "(\\.|=)(bz2|tar|tgz|tar\\.gz|zip)$" )
message ( FATAL_ERROR "Could not extract tarball filename from url:\n ${url}" )
endif ( )
string ( REPLACE ";" "-" fname "${fname}" )
set ( file ${ download_dir } / ${ fname } )
get_property ( timeout TARGET ${ name } PROPERTY _EP_TIMEOUT )
get_property ( tls_verify TARGET ${ name } PROPERTY _EP_TLS_VERIFY )
get_property ( tls_cainfo TARGET ${ name } PROPERTY _EP_TLS_CAINFO )
_ep_write_downloadfile_script ( "${stamp_dir}/download-${name}.cmake"
" $ { u r l } " " $ { f i l e } " " $ { t i m e o u t } " " $ { h a s h } " " $ { t l s _ v e r i f y } " " $ { t l s _ c a i n f o } " )
set ( cmd ${ CMAKE_COMMAND } -P ${ stamp_dir } /download- ${ name } .cmake
C O M M A N D )
set ( comment "Performing download step (download, verify and extract) for '${name}'" )
else ( )
set ( file "${url}" )
set ( comment "Performing download step (verify and extract) for '${name}'" )
endif ( )
_ep_write_verifyfile_script ( "${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}" )
list ( APPEND cmd ${ CMAKE_COMMAND } -P ${ stamp_dir } /verify- ${ name } .cmake
C O M M A N D )
_ep_write_extractfile_script ( "${stamp_dir}/extract-${name}.cmake" "${name}" "${file}" "${source_dir}" )
list ( APPEND cmd ${ CMAKE_COMMAND } -P ${ stamp_dir } /extract- ${ name } .cmake )
endif ( )
else ( )
_ep_is_dir_empty ( "${source_dir}" empty )
if ( ${ empty } )
message ( SEND_ERROR "error: no download info for '${name}' -- please specify existing/non-empty SOURCE_DIR or one of URL, CVS_REPOSITORY and CVS_MODULE, SVN_REPOSITORY, GIT_REPOSITORY, HG_REPOSITORY or DOWNLOAD_COMMAND" )
endif ( )
endif ( )
get_property ( log TARGET ${ name } PROPERTY _EP_LOG_DOWNLOAD )
if ( log )
set ( log LOG 1 )
else ( )
set ( log "" )
endif ( )
ExternalProject_Add_Step ( ${ name } download
C O M M E N T $ { c o m m e n t }
C O M M A N D $ { c m d }
W O R K I N G _ D I R E C T O R Y $ { w o r k _ d i r }
D E P E N D S $ { d e p e n d s }
D E P E N D E E S m k d i r
$ { l o g }
)
endfunction ( )
function ( _ep_add_update_command name )
ExternalProject_Get_Property ( ${ name } source_dir tmp_dir )
get_property ( cmd_set TARGET ${ name } PROPERTY _EP_UPDATE_COMMAND SET )
get_property ( cmd TARGET ${ name } PROPERTY _EP_UPDATE_COMMAND )
get_property ( cvs_repository TARGET ${ name } PROPERTY _EP_CVS_REPOSITORY )
get_property ( svn_repository TARGET ${ name } PROPERTY _EP_SVN_REPOSITORY )
get_property ( git_repository TARGET ${ name } PROPERTY _EP_GIT_REPOSITORY )
get_property ( hg_repository TARGET ${ name } PROPERTY _EP_HG_REPOSITORY )
set ( work_dir )
set ( comment )
set ( always )
if ( cmd_set )
set ( work_dir ${ source_dir } )
elseif ( cvs_repository )
if ( NOT CVS_EXECUTABLE )
message ( FATAL_ERROR "error: could not find cvs for update of ${name}" )
endif ( )
set ( work_dir ${ source_dir } )
set ( comment "Performing update step (CVS update) for '${name}'" )
get_property ( cvs_tag TARGET ${ name } PROPERTY _EP_CVS_TAG )
set ( cmd ${ CVS_EXECUTABLE } -d ${ cvs_repository } -q up -dP ${ cvs_tag } )
set ( always 1 )
elseif ( svn_repository )
if ( NOT Subversion_SVN_EXECUTABLE )
message ( FATAL_ERROR "error: could not find svn for update of ${name}" )
endif ( )
set ( work_dir ${ source_dir } )
set ( comment "Performing update step (SVN update) for '${name}'" )
get_property ( svn_revision TARGET ${ name } PROPERTY _EP_SVN_REVISION )
get_property ( svn_username TARGET ${ name } PROPERTY _EP_SVN_USERNAME )
get_property ( svn_password TARGET ${ name } PROPERTY _EP_SVN_PASSWORD )
get_property ( svn_trust_cert TARGET ${ name } PROPERTY _EP_SVN_TRUST_CERT )
set ( svn_user_pw_args "" )
if ( svn_username )
set ( svn_user_pw_args ${ svn_user_pw_args } "--username=${svn_username}" )
endif ( )
if ( svn_password )
set ( svn_user_pw_args ${ svn_user_pw_args } "--password=${svn_password}" )
endif ( )
if ( svn_trust_cert )
set ( svn_trust_cert_args --trust-server-cert )
endif ( )
set ( cmd ${ Subversion_SVN_EXECUTABLE } up ${ svn_revision }
- - n o n - i n t e r a c t i v e $ { s v n _ t r u s t _ c e r t _ a r g s } $ { s v n _ u s e r _ p w _ a r g s } )
set ( always 1 )
elseif ( git_repository )
if ( NOT GIT_EXECUTABLE )
message ( FATAL_ERROR "error: could not find git for fetch of ${name}" )
endif ( )
set ( work_dir ${ source_dir } )
set ( comment "Performing update step for '${name}'" )
get_property ( git_tag TARGET ${ name } PROPERTY _EP_GIT_TAG )
if ( NOT git_tag )
set ( git_tag "master" )
endif ( )
_ep_write_gitupdate_script ( ${ tmp_dir } / ${ name } -gitupdate.cmake
$ { G I T _ E X E C U T A B L E } $ { g i t _ t a g } $ { g i t _ r e p o s i t o r y } $ { w o r k _ d i r }
)
set ( cmd ${ CMAKE_COMMAND } -P ${ tmp_dir } / ${ name } -gitupdate.cmake )
set ( always 1 )
elseif ( hg_repository )
if ( NOT HG_EXECUTABLE )
message ( FATAL_ERROR "error: could not find hg for pull of ${name}" )
endif ( )
set ( work_dir ${ source_dir } )
set ( comment "Performing update step (hg pull) for '${name}'" )
get_property ( hg_tag TARGET ${ name } PROPERTY _EP_HG_TAG )
if ( NOT hg_tag )
set ( hg_tag "tip" )
endif ( )
if ( "${HG_VERSION_STRING}" STREQUAL "2.1" )
message ( WARNING " Mercurial 2.1 does not distinguish an empty pull from a failed pull:
h t t p : / / m e r c u r i a l . s e l e n i c . c o m / w i k i / U p g r a d e N o t e s #A2.1.1:_revert_pull_return_code_change.2C_compile_issue_on_OS_X
h t t p : / / t h r e a d . g m a n e . o r g / g m a n e . c o m p . v e r s i o n - c o n t r o l . m e r c u r i a l . d e v e l / 4 7 6 5 6
U p d a t e t o M e r c u r i a l > = 2 . 1 . 1 .
" )
endif ( )
set ( cmd ${ HG_EXECUTABLE } pull
C O M M A N D $ { H G _ E X E C U T A B L E } u p d a t e $ { h g _ t a g }
)
set ( always 1 )
endif ( )
get_property ( log TARGET ${ name } PROPERTY _EP_LOG_UPDATE )
if ( log )
set ( log LOG 1 )
else ( )
set ( log "" )
endif ( )
ExternalProject_Add_Step ( ${ name } update
C O M M E N T $ { c o m m e n t }
C O M M A N D $ { c m d }
A L W A Y S $ { a l w a y s }
W O R K I N G _ D I R E C T O R Y $ { w o r k _ d i r }
D E P E N D E E S d o w n l o a d
$ { l o g }
)
endfunction ( )
function ( _ep_add_patch_command name )
ExternalProject_Get_Property ( ${ name } source_dir )
get_property ( cmd_set TARGET ${ name } PROPERTY _EP_PATCH_COMMAND SET )
get_property ( cmd TARGET ${ name } PROPERTY _EP_PATCH_COMMAND )
set ( work_dir )
if ( cmd_set )
set ( work_dir ${ source_dir } )
endif ( )
ExternalProject_Add_Step ( ${ name } patch
C O M M A N D $ { c m d }
W O R K I N G _ D I R E C T O R Y $ { w o r k _ d i r }
D E P E N D E E S d o w n l o a d
)
endfunction ( )
# TODO: Make sure external projects use the proper compiler
function ( _ep_add_configure_command name )
ExternalProject_Get_Property ( ${ name } source_dir binary_dir tmp_dir )
# Depend on other external projects (file-level).
set ( file_deps )
get_property ( deps TARGET ${ name } PROPERTY _EP_DEPENDS )
foreach ( dep IN LISTS deps )
get_property ( is_ep TARGET ${ dep } PROPERTY _EP_IS_EXTERNAL_PROJECT )
if ( is_ep )
_ep_get_step_stampfile ( ${ dep } "done" done_stamp_file )
list ( APPEND file_deps ${ done_stamp_file } )
endif ( )
endforeach ( )
get_property ( cmd_set TARGET ${ name } PROPERTY _EP_CONFIGURE_COMMAND SET )
if ( cmd_set )
get_property ( cmd TARGET ${ name } PROPERTY _EP_CONFIGURE_COMMAND )
else ( )
get_target_property ( cmake_command ${ name } _EP_CMAKE_COMMAND )
if ( cmake_command )
set ( cmd "${cmake_command}" )
else ( )
set ( cmd "${CMAKE_COMMAND}" )
endif ( )
get_property ( cmake_args TARGET ${ name } PROPERTY _EP_CMAKE_ARGS )
list ( APPEND cmd ${ cmake_args } )
# If there are any CMAKE_CACHE_ARGS, write an initial cache and use it
get_property ( cmake_cache_args TARGET ${ name } PROPERTY _EP_CMAKE_CACHE_ARGS )
if ( cmake_cache_args )
set ( _ep_cache_args_script "${tmp_dir}/${name}-cache.cmake" )
_ep_write_initial_cache ( ${ name } "${_ep_cache_args_script}" "${cmake_cache_args}" )
list ( APPEND cmd "-C${_ep_cache_args_script}" )
endif ( )
get_target_property ( cmake_generator ${ name } _EP_CMAKE_GENERATOR )
get_target_property ( cmake_generator_toolset ${ name } _EP_CMAKE_GENERATOR_TOOLSET )
if ( cmake_generator )
list ( APPEND cmd "-G${cmake_generator}" )
if ( cmake_generator_toolset )
list ( APPEND cmd "-T${cmake_generator_toolset}" )
endif ( )
else ( )
if ( CMAKE_EXTRA_GENERATOR )
list ( APPEND cmd "-G${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}" )
else ( )
list ( APPEND cmd "-G${CMAKE_GENERATOR}" )
endif ( )
if ( cmake_generator_toolset )
message ( FATAL_ERROR "Option CMAKE_GENERATOR_TOOLSET not allowed without CMAKE_GENERATOR." )
endif ( )
if ( CMAKE_GENERATOR_TOOLSET )
list ( APPEND cmd "-T${CMAKE_GENERATOR_TOOLSET}" )
endif ( )
endif ( )
list ( APPEND cmd "${source_dir}" )
endif ( )
# If anything about the configure command changes, (command itself, cmake
# used, cmake args or cmake generator) then re-run the configure step.
# Fixes issue http://public.kitware.com/Bug/view.php?id=10258
#
if ( NOT EXISTS ${ tmp_dir } / ${ name } -cfgcmd.txt.in )
file ( WRITE ${ tmp_dir } / ${ name } -cfgcmd.txt.in "cmd='\@cmd\@'\n" )
endif ( )
configure_file ( ${ tmp_dir } / ${ name } -cfgcmd.txt.in ${ tmp_dir } / ${ name } -cfgcmd.txt )
list ( APPEND file_deps ${ tmp_dir } / ${ name } -cfgcmd.txt )
list ( APPEND file_deps ${ _ep_cache_args_script } )
get_property ( log TARGET ${ name } PROPERTY _EP_LOG_CONFIGURE )
if ( log )
set ( log LOG 1 )
else ( )
set ( log "" )
endif ( )
ExternalProject_Add_Step ( ${ name } configure
C O M M A N D $ { c m d }
W O R K I N G _ D I R E C T O R Y $ { b i n a r y _ d i r }
D E P E N D E E S u p d a t e p a t c h
D E P E N D S $ { f i l e _ d e p s }
$ { l o g }
)
endfunction ( )
function ( _ep_add_build_command name )
ExternalProject_Get_Property ( ${ name } binary_dir )
get_property ( cmd_set TARGET ${ name } PROPERTY _EP_BUILD_COMMAND SET )
if ( cmd_set )
get_property ( cmd TARGET ${ name } PROPERTY _EP_BUILD_COMMAND )
else ( )
_ep_get_build_command ( ${ name } BUILD cmd )
endif ( )
get_property ( log TARGET ${ name } PROPERTY _EP_LOG_BUILD )
if ( log )
set ( log LOG 1 )
else ( )
set ( log "" )
endif ( )
ExternalProject_Add_Step ( ${ name } build
C O M M A N D $ { c m d }
W O R K I N G _ D I R E C T O R Y $ { b i n a r y _ d i r }
D E P E N D E E S c o n f i g u r e
$ { l o g }
)
endfunction ( )
function ( _ep_add_install_command name )
ExternalProject_Get_Property ( ${ name } binary_dir )
get_property ( cmd_set TARGET ${ name } PROPERTY _EP_INSTALL_COMMAND SET )
if ( cmd_set )
get_property ( cmd TARGET ${ name } PROPERTY _EP_INSTALL_COMMAND )
else ( )
_ep_get_build_command ( ${ name } INSTALL cmd )
endif ( )
get_property ( log TARGET ${ name } PROPERTY _EP_LOG_INSTALL )
if ( log )
set ( log LOG 1 )
else ( )
set ( log "" )
endif ( )
ExternalProject_Add_Step ( ${ name } install
C O M M A N D $ { c m d }
W O R K I N G _ D I R E C T O R Y $ { b i n a r y _ d i r }
D E P E N D E E S b u i l d
$ { l o g }
)
endfunction ( )
function ( _ep_add_test_command name )
ExternalProject_Get_Property ( ${ name } binary_dir )
get_property ( before TARGET ${ name } PROPERTY _EP_TEST_BEFORE_INSTALL )
get_property ( after TARGET ${ name } PROPERTY _EP_TEST_AFTER_INSTALL )
get_property ( cmd_set TARGET ${ name } PROPERTY _EP_TEST_COMMAND SET )
# Only actually add the test step if one of the test related properties is
# explicitly set. (i.e. the test step is omitted unless requested...)
#
if ( cmd_set OR before OR after )
if ( cmd_set )
get_property ( cmd TARGET ${ name } PROPERTY _EP_TEST_COMMAND )
else ( )
_ep_get_build_command ( ${ name } TEST cmd )
endif ( )
if ( before )
set ( dep_args DEPENDEES build DEPENDERS install )
else ( )
set ( dep_args DEPENDEES install )
endif ( )
get_property ( log TARGET ${ name } PROPERTY _EP_LOG_TEST )
if ( log )
set ( log LOG 1 )
else ( )
set ( log "" )
endif ( )
ExternalProject_Add_Step ( ${ name } test
C O M M A N D $ { c m d }
W O R K I N G _ D I R E C T O R Y $ { b i n a r y _ d i r }
$ { d e p _ a r g s }
$ { l o g }
)
endif ( )
endfunction ( )
function ( ExternalProject_Add name )
_ep_get_configuration_subdir_suffix ( cfgdir )
# Add a custom target for the external project.
set ( cmf_dir ${ CMAKE_CURRENT_BINARY_DIR } /CMakeFiles )
set ( complete_stamp_file "${cmf_dir}${cfgdir}/${name}-complete" )
add_custom_target ( ${ name } ALL DEPENDS ${ complete_stamp_file } )
set_property ( TARGET ${ name } PROPERTY _EP_IS_EXTERNAL_PROJECT 1 )
_ep_parse_arguments ( ExternalProject_Add ${ name } _EP_ "${ARGN}" )
_ep_set_directories ( ${ name } )
_ep_get_step_stampfile ( ${ name } "done" done_stamp_file )
_ep_get_step_stampfile ( ${ name } "install" install_stamp_file )
# The 'complete' step depends on all other steps and creates a
# 'done' mark. A dependent external project's 'configure' step
# depends on the 'done' mark so that it rebuilds when this project
# rebuilds. It is important that 'done' is not the output of any
# custom command so that CMake does not propagate build rules to
# other external project targets, which may cause problems during
# parallel builds. However, the Ninja generator needs to see the entire
# dependency graph, and can cope with custom commands belonging to
# multiple targets, so we add the 'done' mark as an output for Ninja only.
set ( complete_outputs ${ complete_stamp_file } )
if ( ${ CMAKE_GENERATOR } MATCHES "Ninja" )
set ( complete_outputs ${ complete_outputs } ${ done_stamp_file } )
endif ( )
add_custom_command (
O U T P U T $ { c o m p l e t e _ o u t p u t s }
C O M M E N T " C o m p l e t e d ' $ { n a m e } ' "
C O M M A N D $ { C M A K E _ C O M M A N D } - E m a k e _ d i r e c t o r y $ { c m f _ d i r } $ { c f g d i r }
C O M M A N D $ { C M A K E _ C O M M A N D } - E t o u c h $ { c o m p l e t e _ s t a m p _ f i l e }
C O M M A N D $ { C M A K E _ C O M M A N D } - E t o u c h $ { d o n e _ s t a m p _ f i l e }
D E P E N D S $ { i n s t a l l _ s t a m p _ f i l e }
V E R B A T I M
)
# Depend on other external projects (target-level).
get_property ( deps TARGET ${ name } PROPERTY _EP_DEPENDS )
foreach ( arg IN LISTS deps )
add_dependencies ( ${ name } ${ arg } )
endforeach ( )
# Set up custom build steps based on the target properties.
# Each step depends on the previous one.
#
# The target depends on the output of the final step.
# (Already set up above in the DEPENDS of the add_custom_target command.)
#
_ep_add_mkdir_command ( ${ name } )
_ep_add_download_command ( ${ name } )
_ep_add_update_command ( ${ name } )
_ep_add_patch_command ( ${ name } )
_ep_add_configure_command ( ${ name } )
_ep_add_build_command ( ${ name } )
_ep_add_install_command ( ${ name } )
# Test is special in that it might depend on build, or it might depend
# on install.
#
_ep_add_test_command ( ${ name } )
endfunction ( )