shared_internal_commands.cmake 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977
  1. cmake_policy(VERSION 3.25)
  2. # Determine the remote URL of the project containing the working_directory.
  3. # This will leave output_variable unset if the URL can't be determined.
  4. function(_ep_get_git_remote_url output_variable working_directory)
  5. set("${output_variable}" "" PARENT_SCOPE)
  6. find_package(Git QUIET REQUIRED)
  7. execute_process(
  8. COMMAND ${GIT_EXECUTABLE} symbolic-ref --short HEAD
  9. WORKING_DIRECTORY "${working_directory}"
  10. OUTPUT_VARIABLE git_symbolic_ref
  11. OUTPUT_STRIP_TRAILING_WHITESPACE
  12. ERROR_QUIET
  13. )
  14. if(NOT git_symbolic_ref STREQUAL "")
  15. # We are potentially on a branch. See if that branch is associated with
  16. # an upstream remote (might be just a local one or not a branch at all).
  17. execute_process(
  18. COMMAND ${GIT_EXECUTABLE} config branch.${git_symbolic_ref}.remote
  19. WORKING_DIRECTORY "${working_directory}"
  20. OUTPUT_VARIABLE git_remote_name
  21. OUTPUT_STRIP_TRAILING_WHITESPACE
  22. ERROR_QUIET
  23. )
  24. endif()
  25. if(NOT git_remote_name)
  26. # Can't select a remote based on a branch. If there's only one remote,
  27. # or we have multiple remotes but one is called "origin", choose that.
  28. execute_process(
  29. COMMAND ${GIT_EXECUTABLE} remote
  30. WORKING_DIRECTORY "${working_directory}"
  31. OUTPUT_VARIABLE git_remote_list
  32. OUTPUT_STRIP_TRAILING_WHITESPACE
  33. ERROR_QUIET
  34. )
  35. string(REPLACE "\n" ";" git_remote_list "${git_remote_list}")
  36. list(LENGTH git_remote_list git_remote_list_length)
  37. if(git_remote_list_length EQUAL 0)
  38. message(FATAL_ERROR "Git remote not found in parent project.")
  39. elseif(git_remote_list_length EQUAL 1)
  40. list(GET git_remote_list 0 git_remote_name)
  41. else()
  42. set(base_warning_msg "Multiple git remotes found for parent project")
  43. if("origin" IN_LIST git_remote_list)
  44. message(WARNING "${base_warning_msg}, defaulting to origin.")
  45. set(git_remote_name "origin")
  46. else()
  47. message(FATAL_ERROR "${base_warning_msg}, none of which are origin.")
  48. endif()
  49. endif()
  50. endif()
  51. if(GIT_VERSION VERSION_LESS 1.7.5)
  52. set(_git_remote_url_cmd_args config remote.${git_remote_name}.url)
  53. elseif(GIT_VERSION VERSION_LESS 2.7)
  54. set(_git_remote_url_cmd_args ls-remote --get-url ${git_remote_name})
  55. else()
  56. set(_git_remote_url_cmd_args remote get-url ${git_remote_name})
  57. endif()
  58. execute_process(
  59. COMMAND ${GIT_EXECUTABLE} ${_git_remote_url_cmd_args}
  60. WORKING_DIRECTORY "${working_directory}"
  61. OUTPUT_VARIABLE git_remote_url
  62. OUTPUT_STRIP_TRAILING_WHITESPACE
  63. COMMAND_ERROR_IS_FATAL LAST
  64. ENCODING UTF-8 # Needed to handle non-ascii characters in local paths
  65. )
  66. set("${output_variable}" "${git_remote_url}" PARENT_SCOPE)
  67. endfunction()
  68. function(_ep_is_relative_git_remote output_variable remote_url)
  69. if(remote_url MATCHES "^\\.\\./")
  70. set("${output_variable}" TRUE PARENT_SCOPE)
  71. else()
  72. set("${output_variable}" FALSE PARENT_SCOPE)
  73. endif()
  74. endfunction()
  75. # Return an absolute remote URL given an existing remote URL and relative path.
  76. # The output_variable will be set to an empty string if an absolute URL
  77. # could not be computed (no error message is output).
  78. function(_ep_resolve_relative_git_remote
  79. output_variable
  80. parent_remote_url
  81. relative_remote_url
  82. )
  83. set("${output_variable}" "" PARENT_SCOPE)
  84. if(parent_remote_url STREQUAL "")
  85. return()
  86. endif()
  87. string(REGEX MATCH
  88. "^(([A-Za-z0-9][A-Za-z0-9+.-]*)://)?(([^/@]+)@)?(\\[[A-Za-z0-9:]+\\]|[^/:]+)?([/:]/?)(.+(\\.git)?/?)$"
  89. git_remote_url_components
  90. "${parent_remote_url}"
  91. )
  92. set(protocol "${CMAKE_MATCH_1}")
  93. set(auth "${CMAKE_MATCH_3}")
  94. set(host "${CMAKE_MATCH_5}")
  95. set(separator "${CMAKE_MATCH_6}")
  96. set(path "${CMAKE_MATCH_7}")
  97. string(REPLACE "/" ";" remote_path_components "${path}")
  98. string(REPLACE "/" ";" relative_path_components "${relative_remote_url}")
  99. foreach(relative_path_component IN LISTS relative_path_components)
  100. if(NOT relative_path_component STREQUAL "..")
  101. break()
  102. endif()
  103. list(LENGTH remote_path_components remote_path_component_count)
  104. if(remote_path_component_count LESS 1)
  105. return()
  106. endif()
  107. list(POP_BACK remote_path_components)
  108. list(POP_FRONT relative_path_components)
  109. endforeach()
  110. list(APPEND final_path_components ${remote_path_components} ${relative_path_components})
  111. list(JOIN final_path_components "/" path)
  112. set("${output_variable}" "${protocol}${auth}${host}${separator}${path}" PARENT_SCOPE)
  113. endfunction()
  114. # The output_variable will be set to the original git_repository if it
  115. # could not be resolved (no error message is output). The original value is
  116. # also returned if it doesn't need to be resolved.
  117. function(_ep_resolve_git_remote
  118. output_variable
  119. git_repository
  120. cmp0150
  121. cmp0150_old_base_dir
  122. )
  123. if(git_repository STREQUAL "")
  124. set("${output_variable}" "" PARENT_SCOPE)
  125. return()
  126. endif()
  127. _ep_is_relative_git_remote(_git_repository_is_relative "${git_repository}")
  128. if(NOT _git_repository_is_relative)
  129. set("${output_variable}" "${git_repository}" PARENT_SCOPE)
  130. return()
  131. endif()
  132. if(cmp0150 STREQUAL "NEW")
  133. _ep_get_git_remote_url(_parent_git_remote_url "${CMAKE_CURRENT_SOURCE_DIR}")
  134. _ep_resolve_relative_git_remote(_resolved_git_remote_url "${_parent_git_remote_url}" "${git_repository}")
  135. if(_resolved_git_remote_url STREQUAL "")
  136. message(FATAL_ERROR
  137. "Failed to resolve relative git remote URL:\n"
  138. " Relative URL: ${git_repository}\n"
  139. " Parent URL: ${_parent_git_remote_url}"
  140. )
  141. endif()
  142. set("${output_variable}" "${_resolved_git_remote_url}" PARENT_SCOPE)
  143. return()
  144. elseif(cmp0150 STREQUAL "")
  145. cmake_policy(GET_WARNING CMP0150 _cmp0150_warning)
  146. message(AUTHOR_WARNING
  147. "${_cmp0150_warning}\n"
  148. "A relative GIT_REPOSITORY path was detected. "
  149. "This will be interpreted as a local path to where the project is being cloned. "
  150. "Set GIT_REPOSITORY to an absolute path or set policy CMP0150 to NEW to avoid "
  151. "this warning."
  152. )
  153. endif()
  154. set("${output_variable}" "${cmp0150_old_base_dir}/${git_repository}" PARENT_SCOPE)
  155. endfunction()
  156. macro(_ep_get_hash_algos out_var)
  157. set(${out_var}
  158. MD5
  159. SHA1
  160. SHA224
  161. SHA256
  162. SHA384
  163. SHA512
  164. SHA3_224
  165. SHA3_256
  166. SHA3_384
  167. SHA3_512
  168. )
  169. endmacro()
  170. macro(_ep_get_hash_regex out_var)
  171. _ep_get_hash_algos(${out_var})
  172. list(JOIN ${out_var} "|" ${out_var})
  173. set(${out_var} "^(${${out_var}})=([0-9A-Fa-f]+)$")
  174. endmacro()
  175. function(_ep_parse_arguments_to_vars
  176. f
  177. keywords
  178. name
  179. ns
  180. args
  181. )
  182. # Transfer the arguments into variables in the calling scope.
  183. # Because some keywords can be repeated, we can't use cmake_parse_arguments().
  184. # Instead, we loop through the args and consider the namespace starting with
  185. # an upper-case letter followed by at least two more upper-case letters,
  186. # numbers or underscores to be keywords.
  187. foreach(key IN LISTS keywords)
  188. unset(${ns}${key})
  189. endforeach()
  190. set(key)
  191. foreach(arg IN LISTS args)
  192. set(is_value 1)
  193. if(arg MATCHES "^[A-Z][A-Z0-9_][A-Z0-9_]+$" AND
  194. NOT (("x${arg}x" STREQUAL "x${key}x") AND
  195. ("x${key}x" STREQUAL "xCOMMANDx")) AND
  196. NOT arg MATCHES "^(TRUE|FALSE|YES)$")
  197. if(arg IN_LIST keywords)
  198. set(is_value 0)
  199. endif()
  200. endif()
  201. if(is_value)
  202. if(key)
  203. # Value
  204. list(APPEND ${ns}${key} "${arg}")
  205. else()
  206. # Missing Keyword
  207. message(AUTHOR_WARNING
  208. "value '${arg}' with no previous keyword in ${f}"
  209. )
  210. endif()
  211. else()
  212. set(key "${arg}")
  213. endif()
  214. endforeach()
  215. foreach(key IN LISTS keywords)
  216. if(DEFINED ${ns}${key})
  217. set(${ns}${key} "${${ns}${key}}" PARENT_SCOPE)
  218. else()
  219. unset(${ns}${key} PARENT_SCOPE)
  220. endif()
  221. endforeach()
  222. endfunction()
  223. # NOTE: This cannot be a macro because that will evaluate anything that looks
  224. # like a CMake variable in any of the args.
  225. function(_ep_parse_arguments
  226. f
  227. keywords
  228. name
  229. ns
  230. args
  231. )
  232. _ep_parse_arguments_to_vars(
  233. "${f}"
  234. "${keywords}"
  235. ${name}
  236. ${ns}
  237. "${args}"
  238. )
  239. foreach(key IN LISTS keywords)
  240. if(DEFINED ${ns}${key})
  241. set(${ns}${key} "${${ns}${key}}" PARENT_SCOPE)
  242. else()
  243. unset(${ns}${key} PARENT_SCOPE)
  244. endif()
  245. endforeach()
  246. # Transfer the arguments to the target as target properties. These are
  247. # read by the various steps, potentially from different scopes.
  248. foreach(key IN LISTS keywords)
  249. if(DEFINED ${ns}${key})
  250. set_property(TARGET ${name} PROPERTY ${ns}${key} "${${ns}${key}}")
  251. endif()
  252. endforeach()
  253. endfunction()
  254. function(_ep_get_tls_version name tls_version_var)
  255. # Note that the arguments are assumed to have already been parsed and have
  256. # been translated into variables with the prefix _EP_... by a call to
  257. # ep_parse_arguments() or ep_parse_arguments_to_vars().
  258. set(tls_version_regex "^1\\.[0-3]$")
  259. set(tls_version "${_EP_TLS_VERSION}")
  260. if(NOT "x${tls_version}" STREQUAL "x")
  261. if(NOT tls_version MATCHES "${tls_version_regex}")
  262. message(FATAL_ERROR "TLS_VERSION '${tls_version}' not known")
  263. endif()
  264. elseif(NOT "x${CMAKE_TLS_VERSION}" STREQUAL "x")
  265. set(tls_version "${CMAKE_TLS_VERSION}")
  266. if(NOT tls_version MATCHES "${tls_version_regex}")
  267. message(FATAL_ERROR "CMAKE_TLS_VERSION '${tls_version}' not known")
  268. endif()
  269. elseif(NOT "x$ENV{CMAKE_TLS_VERSION}" STREQUAL "x")
  270. set(tls_version "$ENV{CMAKE_TLS_VERSION}")
  271. if(NOT tls_version MATCHES "${tls_version_regex}")
  272. message(FATAL_ERROR "ENV{CMAKE_TLS_VERSION} '${tls_version}' not known")
  273. endif()
  274. endif()
  275. set("${tls_version_var}" "${tls_version}" PARENT_SCOPE)
  276. endfunction()
  277. function(_ep_get_tls_verify name tls_verify_var)
  278. # Note that the arguments are assumed to have already been parsed and have
  279. # been translated into variables with the prefix _EP_... by a call to
  280. # ep_parse_arguments() or ep_parse_arguments_to_vars().
  281. set(tls_verify "${_EP_TLS_VERIFY}")
  282. if("x${tls_verify}" STREQUAL "x")
  283. if(NOT "x${CMAKE_TLS_VERIFY}" STREQUAL "x")
  284. set(tls_verify "${CMAKE_TLS_VERIFY}")
  285. elseif(NOT "x$ENV{CMAKE_TLS_VERIFY}" STREQUAL "x")
  286. set(tls_verify "$ENV{CMAKE_TLS_VERIFY}")
  287. endif()
  288. endif()
  289. set("${tls_verify_var}" "${tls_verify}" PARENT_SCOPE)
  290. endfunction()
  291. function(_ep_get_tls_cainfo name tls_cainfo_var)
  292. # Note that the arguments are assumed to have already been parsed and have
  293. # been translated into variables with the prefix _EP_... by a call to
  294. # ep_parse_arguments() or ep_parse_arguments_to_vars().
  295. set(tls_cainfo "${_EP_TLS_CAINFO}")
  296. if("x${tls_cainfo}" STREQUAL "x" AND DEFINED CMAKE_TLS_CAINFO)
  297. set(tls_cainfo "${CMAKE_TLS_CAINFO}")
  298. endif()
  299. set("${tls_cainfo_var}" "${tls_cainfo}" PARENT_SCOPE)
  300. endfunction()
  301. function(_ep_get_netrc name netrc_var)
  302. # Note that the arguments are assumed to have already been parsed and have
  303. # been translated into variables with the prefix _EP_... by a call to
  304. # ep_parse_arguments() or ep_parse_arguments_to_vars().
  305. set(netrc "${_EP_NETRC}")
  306. if("x${netrc}" STREQUAL "x" AND DEFINED CMAKE_NETRC)
  307. set(netrc "${CMAKE_NETRC}")
  308. endif()
  309. set("${netrc_var}" "${netrc}" PARENT_SCOPE)
  310. endfunction()
  311. function(_ep_get_netrc_file name netrc_file_var)
  312. # Note that the arguments are assumed to have already been parsed and have
  313. # been translated into variables with the prefix _EP_... by a call to
  314. # ep_parse_arguments() or ep_parse_arguments_to_vars().
  315. set(netrc_file "${_EP_NETRC_FILE}")
  316. if("x${netrc_file}" STREQUAL "x" AND DEFINED CMAKE_NETRC_FILE)
  317. set(netrc_file "${CMAKE_NETRC_FILE}")
  318. endif()
  319. set("${netrc_file_var}" "${netrc_file}" PARENT_SCOPE)
  320. endfunction()
  321. function(_ep_write_gitclone_script
  322. script_filename
  323. source_dir
  324. git_EXECUTABLE
  325. git_repository
  326. git_tag
  327. git_remote_name
  328. init_submodules
  329. git_submodules_recurse
  330. git_submodules
  331. git_shallow
  332. git_progress
  333. git_config
  334. src_name
  335. work_dir
  336. gitclone_infofile
  337. gitclone_stampfile
  338. tls_version
  339. tls_verify
  340. )
  341. if(NOT GIT_VERSION_STRING VERSION_LESS 1.8.5)
  342. # Use `git checkout <tree-ish> --` to avoid ambiguity with a local path.
  343. set(git_checkout_explicit-- "--")
  344. else()
  345. # Use `git checkout <branch>` even though this risks ambiguity with a
  346. # local path. Unfortunately we cannot use `git checkout <tree-ish> --`
  347. # because that will not search for remote branch names, a common use case.
  348. set(git_checkout_explicit-- "")
  349. endif()
  350. if("${git_tag}" STREQUAL "")
  351. message(FATAL_ERROR "Tag for git checkout should not be empty.")
  352. endif()
  353. if(GIT_VERSION_STRING VERSION_LESS 2.20 OR
  354. 2.21 VERSION_LESS_EQUAL GIT_VERSION_STRING)
  355. set(git_clone_options "--no-checkout")
  356. else()
  357. set(git_clone_options)
  358. endif()
  359. if(git_shallow)
  360. if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.10)
  361. list(APPEND git_clone_options "--depth 1 --no-single-branch")
  362. else()
  363. list(APPEND git_clone_options "--depth 1")
  364. endif()
  365. endif()
  366. if(git_progress)
  367. list(APPEND git_clone_options --progress)
  368. endif()
  369. foreach(config IN LISTS git_config)
  370. list(APPEND git_clone_options --config \"${config}\")
  371. endforeach()
  372. if(NOT ${git_remote_name} STREQUAL "origin")
  373. list(APPEND git_clone_options --origin \"${git_remote_name}\")
  374. endif()
  375. # The clone config option is sticky, it will apply to all subsequent git
  376. # update operations. The submodules config option is not sticky, because
  377. # git doesn't provide any way to do that. Thus, we will have to pass the
  378. # same config option in the update step too for submodules, but not for
  379. # the main git repo.
  380. set(git_submodules_config_options "")
  381. if(NOT "x${tls_version}" STREQUAL "x")
  382. list(APPEND git_clone_options -c http.sslVersion=tlsv${tls_version})
  383. list(APPEND git_submodules_config_options -c http.sslVersion=tlsv${tls_version})
  384. endif()
  385. if(NOT "x${tls_verify}" STREQUAL "x")
  386. if(tls_verify)
  387. # Default git behavior is "true", but the user might have changed the
  388. # global default to "false". Since TLS_VERIFY was given, ensure we honor
  389. # the specified setting regardless of what the global default might be.
  390. list(APPEND git_clone_options -c http.sslVerify=true)
  391. list(APPEND git_submodules_config_options -c http.sslVerify=true)
  392. else()
  393. list(APPEND git_clone_options -c http.sslVerify=false)
  394. list(APPEND git_submodules_config_options -c http.sslVerify=false)
  395. endif()
  396. endif()
  397. string (REPLACE ";" " " git_clone_options "${git_clone_options}")
  398. configure_file(
  399. ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/gitclone.cmake.in
  400. ${script_filename}
  401. @ONLY
  402. )
  403. endfunction()
  404. function(_ep_write_hgclone_script
  405. script_filename
  406. source_dir
  407. hg_EXECUTABLE
  408. hg_repository
  409. hg_tag
  410. src_name
  411. work_dir
  412. hgclone_infofile
  413. hgclone_stampfile
  414. )
  415. if("${hg_tag}" STREQUAL "")
  416. message(FATAL_ERROR "Tag for hg checkout should not be empty.")
  417. endif()
  418. configure_file(
  419. ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/hgclone.cmake.in
  420. ${script_filename}
  421. @ONLY
  422. )
  423. endfunction()
  424. function(_ep_write_gitupdate_script
  425. script_filename
  426. git_EXECUTABLE
  427. git_tag
  428. git_remote_name
  429. init_submodules
  430. git_submodules_recurse
  431. git_submodules
  432. git_repository
  433. work_dir
  434. git_update_strategy
  435. tls_version
  436. tls_verify
  437. )
  438. if("${git_tag}" STREQUAL "")
  439. message(FATAL_ERROR "Tag for git checkout should not be empty.")
  440. endif()
  441. set(git_stash_save_options --quiet)
  442. if(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.7)
  443. # This avoids stashing files covered by .gitignore
  444. list(APPEND git_stash_save_options --include-untracked)
  445. elseif(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.6)
  446. # Untracked files, but also ignored files, so potentially slower
  447. list(APPEND git_stash_save_options --all)
  448. endif()
  449. # The submodules config option is not sticky, git doesn't provide any way
  450. # to do that. We have to pass this config option for the update step too.
  451. # We don't need to set it for the non-submodule update because it gets
  452. # recorded as part of the clone operation in a sticky manner.
  453. set(git_submodules_config_options "")
  454. if(NOT "x${tls_version}" STREQUAL "x")
  455. list(APPEND git_submodules_config_options -c http.sslVersion=tlsv${tls_version})
  456. endif()
  457. if(NOT "x${tls_verify}" STREQUAL "x")
  458. if(tls_verify)
  459. # Default git behavior is "true", but the user might have changed the
  460. # global default to "false". Since TLS_VERIFY was given, ensure we honor
  461. # the specified setting regardless of what the global default might be.
  462. list(APPEND git_submodules_config_options -c http.sslVerify=true)
  463. else()
  464. list(APPEND git_submodules_config_options -c http.sslVerify=false)
  465. endif()
  466. endif()
  467. configure_file(
  468. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/gitupdate.cmake.in"
  469. "${script_filename}"
  470. @ONLY
  471. )
  472. endfunction()
  473. function(_ep_write_downloadfile_script
  474. script_filename
  475. REMOTE
  476. LOCAL
  477. timeout
  478. inactivity_timeout
  479. no_progress
  480. hash
  481. tls_version
  482. tls_verify
  483. tls_cainfo
  484. userpwd
  485. http_headers
  486. netrc
  487. netrc_file
  488. )
  489. if("x${REMOTE}" STREQUAL "x")
  490. message(FATAL_ERROR "REMOTE can't be empty")
  491. endif()
  492. if("x${LOCAL}" STREQUAL "x")
  493. message(FATAL_ERROR "LOCAL can't be empty")
  494. endif()
  495. # REMOTE could contain special characters that parse as separate arguments.
  496. # Things like parentheses are legitimate characters in a URL, but would be
  497. # seen as the start of a new unquoted argument by the cmake language parser.
  498. # Avoid those special cases by preparing quoted strings for direct inclusion
  499. # in the foreach() call that iterates over the set of URLs in REMOTE.
  500. set(REMOTE "[====[${REMOTE}]====]")
  501. string(REPLACE ";" "]====] [====[" REMOTE "${REMOTE}")
  502. if(timeout)
  503. set(TIMEOUT_ARGS TIMEOUT ${timeout})
  504. set(TIMEOUT_MSG "${timeout} seconds")
  505. else()
  506. set(TIMEOUT_ARGS "# no TIMEOUT")
  507. set(TIMEOUT_MSG "none")
  508. endif()
  509. if(inactivity_timeout)
  510. set(INACTIVITY_TIMEOUT_ARGS INACTIVITY_TIMEOUT ${inactivity_timeout})
  511. set(INACTIVITY_TIMEOUT_MSG "${inactivity_timeout} seconds")
  512. else()
  513. set(INACTIVITY_TIMEOUT_ARGS "# no INACTIVITY_TIMEOUT")
  514. set(INACTIVITY_TIMEOUT_MSG "none")
  515. endif()
  516. if(no_progress)
  517. set(SHOW_PROGRESS "")
  518. else()
  519. set(SHOW_PROGRESS "SHOW_PROGRESS")
  520. endif()
  521. _ep_get_hash_regex(_ep_hash_regex)
  522. if("${hash}" MATCHES "${_ep_hash_regex}")
  523. set(ALGO "${CMAKE_MATCH_1}")
  524. string(TOLOWER "${CMAKE_MATCH_2}" EXPECT_VALUE)
  525. else()
  526. set(ALGO "")
  527. set(EXPECT_VALUE "")
  528. endif()
  529. set(TLS_VERSION_CODE "")
  530. if(NOT "x${tls_version}" STREQUAL "x")
  531. set(TLS_VERSION_CODE "set(CMAKE_TLS_VERSION \"${tls_version}\")")
  532. endif()
  533. set(TLS_VERIFY_CODE "")
  534. if(NOT "x${tls_verify}" STREQUAL "x")
  535. set(TLS_VERIFY_CODE "set(CMAKE_TLS_VERIFY \"${tls_verify}\")")
  536. endif()
  537. set(TLS_CAINFO_CODE "")
  538. if(NOT "x${tls_cainfo}" STREQUAL "x")
  539. set(TLS_CAINFO_CODE "set(CMAKE_TLS_CAINFO \"${tls_cainfo}\")")
  540. endif()
  541. set(NETRC_CODE "")
  542. if(NOT "x${netrc}" STREQUAL "x")
  543. set(NETRC_CODE "set(CMAKE_NETRC \"${netrc}\")")
  544. endif()
  545. set(NETRC_FILE_CODE "")
  546. if(NOT "x${netrc_file}" STREQUAL "x")
  547. set(NETRC_FILE_CODE "set(CMAKE_NETRC_FILE \"${netrc_file}\")")
  548. endif()
  549. if(userpwd STREQUAL ":")
  550. set(USERPWD_ARGS)
  551. else()
  552. set(USERPWD_ARGS USERPWD "${userpwd}")
  553. endif()
  554. set(HTTP_HEADERS_ARGS "")
  555. if(NOT http_headers STREQUAL "")
  556. foreach(header IN LISTS http_headers)
  557. string(PREPEND HTTP_HEADERS_ARGS
  558. "HTTPHEADER \"${header}\"\n "
  559. )
  560. endforeach()
  561. endif()
  562. # Used variables:
  563. # * TLS_VERSION_CODE
  564. # * TLS_VERIFY_CODE
  565. # * TLS_CAINFO_CODE
  566. # * ALGO
  567. # * EXPECT_VALUE
  568. # * REMOTE
  569. # * LOCAL
  570. # * SHOW_PROGRESS
  571. # * TIMEOUT_ARGS
  572. # * TIMEOUT_MSG
  573. # * USERPWD_ARGS
  574. # * HTTP_HEADERS_ARGS
  575. configure_file(
  576. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/download.cmake.in"
  577. "${script_filename}"
  578. @ONLY
  579. )
  580. endfunction()
  581. function(_ep_write_verifyfile_script
  582. script_filename
  583. LOCAL
  584. hash
  585. )
  586. _ep_get_hash_regex(_ep_hash_regex)
  587. if("${hash}" MATCHES "${_ep_hash_regex}")
  588. set(ALGO "${CMAKE_MATCH_1}")
  589. string(TOLOWER "${CMAKE_MATCH_2}" EXPECT_VALUE)
  590. else()
  591. set(ALGO "")
  592. set(EXPECT_VALUE "")
  593. endif()
  594. # Used variables:
  595. # * ALGO
  596. # * EXPECT_VALUE
  597. # * LOCAL
  598. configure_file(
  599. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/verify.cmake.in"
  600. "${script_filename}"
  601. @ONLY
  602. )
  603. endfunction()
  604. function(_ep_write_extractfile_script
  605. script_filename
  606. name
  607. filename
  608. directory
  609. options
  610. )
  611. set(args "")
  612. if(filename MATCHES
  613. "(\\.|=)(7z|tar\\.bz2|tar\\.gz|tar\\.xz|tbz2|tgz|txz|zip)$")
  614. set(args xfz)
  615. endif()
  616. if(filename MATCHES "(\\.|=)tar$")
  617. set(args xf)
  618. endif()
  619. if(args STREQUAL "")
  620. message(FATAL_ERROR
  621. "Do not know how to extract '${filename}' -- known types are: "
  622. ".7z, .tar, .tar.bz2, .tar.gz, .tar.xz, .tbz2, .tgz, .txz and .zip"
  623. )
  624. endif()
  625. configure_file(
  626. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/extractfile.cmake.in"
  627. "${script_filename}"
  628. @ONLY
  629. )
  630. endfunction()
  631. function(_ep_is_dir_empty dir empty_var)
  632. file(GLOB gr "${dir}/*")
  633. if("${gr}" STREQUAL "")
  634. set(${empty_var} 1 PARENT_SCOPE)
  635. else()
  636. set(${empty_var} 0 PARENT_SCOPE)
  637. endif()
  638. endfunction()
  639. function(_ep_get_git_submodules_recurse git_submodules_recurse)
  640. # Checks for GIT_SUBMODULES_RECURSE argument. Default is ON, which sets
  641. # git_submodules_recurse output variable to "--recursive". Otherwise, the
  642. # output variable is set to an empty value "".
  643. # Note that the arguments are assumed to have already been parsed and have
  644. # been translated into variables with the prefix _EP_... by a call to
  645. # ep_parse_arguments() or ep_parse_arguments_to_vars().
  646. if(NOT DEFINED _EP_GIT_SUBMODULES_RECURSE)
  647. set(recurseFlag "--recursive")
  648. else()
  649. if(_EP_GIT_SUBMODULES_RECURSE)
  650. set(recurseFlag "--recursive")
  651. else()
  652. set(recurseFlag "")
  653. endif()
  654. endif()
  655. set(${git_submodules_recurse} "${recurseFlag}" PARENT_SCOPE)
  656. # The git submodule update '--recursive' flag requires git >= v1.6.5
  657. if(recurseFlag AND GIT_VERSION_STRING VERSION_LESS 1.6.5)
  658. message(FATAL_ERROR
  659. "git version 1.6.5 or later required for --recursive flag with "
  660. "'git submodule ...': GIT_VERSION_STRING='${GIT_VERSION_STRING}'"
  661. )
  662. endif()
  663. endfunction()
  664. function(_ep_add_script_commands script_var work_dir cmd)
  665. # We only support a subset of what ep_replace_location_tags() handles
  666. set(location_tags
  667. SOURCE_DIR
  668. SOURCE_SUBDIR
  669. BINARY_DIR
  670. TMP_DIR
  671. DOWNLOAD_DIR
  672. DOWNLOADED_FILE
  673. )
  674. # There can be multiple COMMANDs, but we have to split those up to
  675. # one command per call to execute_process()
  676. string(CONCAT execute_process_cmd
  677. "execute_process(\n"
  678. " WORKING_DIRECTORY \"${work_dir}\"\n"
  679. " COMMAND_ERROR_IS_FATAL LAST\n"
  680. )
  681. cmake_language(GET_MESSAGE_LOG_LEVEL active_log_level)
  682. if(active_log_level MATCHES "VERBOSE|DEBUG|TRACE")
  683. string(APPEND execute_process_cmd " COMMAND_ECHO STDOUT\n")
  684. endif()
  685. string(APPEND execute_process_cmd " COMMAND ")
  686. string(APPEND ${script_var} "${execute_process_cmd}")
  687. foreach(cmd_arg IN LISTS cmd)
  688. if(cmd_arg STREQUAL "COMMAND")
  689. string(APPEND ${script_var} "\n)\n${execute_process_cmd}")
  690. else()
  691. if(_EP_LIST_SEPARATOR)
  692. string(REPLACE "${_EP_LIST_SEPARATOR}" "\\;" cmd_arg "${cmd_arg}")
  693. endif()
  694. foreach(dir IN LISTS location_tags)
  695. string(REPLACE "<${dir}>" "${_EP_${dir}}" cmd_arg "${cmd_arg}")
  696. endforeach()
  697. string(APPEND ${script_var} " [====[${cmd_arg}]====]")
  698. endif()
  699. endforeach()
  700. string(APPEND ${script_var} "\n)")
  701. set(${script_var} "${${script_var}}" PARENT_SCOPE)
  702. endfunction()
  703. function(_ep_add_download_command name)
  704. set(noValueOptions )
  705. set(singleValueOptions
  706. SCRIPT_FILE # These should only be used by FetchContent
  707. DEPENDS_VARIABLE #
  708. )
  709. set(multiValueOptions )
  710. cmake_parse_arguments(PARSE_ARGV 1 arg
  711. "${noValueOptions}" "${singleValueOptions}" "${multiValueOptions}"
  712. )
  713. # The various _EP_... variables mentioned here and throughout this function
  714. # are expected to already have been set by the caller via a call to
  715. # _ep_parse_arguments() or ep_parse_arguments_to_vars(). Other variables
  716. # with different names are assigned to for historical reasons only to keep
  717. # the code more readable and minimize change.
  718. set(source_dir "${_EP_SOURCE_DIR}")
  719. set(stamp_dir "${_EP_STAMP_DIR}")
  720. set(download_dir "${_EP_DOWNLOAD_DIR}")
  721. set(tmp_dir "${_EP_TMP_DIR}")
  722. set(cmd "${_EP_DOWNLOAD_COMMAND}")
  723. set(cvs_repository "${_EP_CVS_REPOSITORY}")
  724. set(svn_repository "${_EP_SVN_REPOSITORY}")
  725. set(git_repository "${_EP_GIT_REPOSITORY}")
  726. set(hg_repository "${_EP_HG_REPOSITORY}")
  727. set(url "${_EP_URL}")
  728. set(fname "${_EP_DOWNLOAD_NAME}")
  729. # TODO: Perhaps file:// should be copied to download dir before extraction.
  730. string(REGEX REPLACE "file://" "" url "${url}")
  731. set(step_script_contents)
  732. set(depends)
  733. set(comment)
  734. set(work_dir)
  735. set(extra_repo_info)
  736. if(DEFINED _EP_DOWNLOAD_COMMAND)
  737. set(work_dir ${download_dir})
  738. set(method custom)
  739. if(NOT "x${cmd}" STREQUAL "x" AND arg_SCRIPT_FILE)
  740. _ep_add_script_commands(
  741. step_script_contents
  742. "${work_dir}"
  743. "${cmd}" # Must be a single quoted argument
  744. )
  745. endif()
  746. elseif(cvs_repository)
  747. set(method cvs)
  748. find_package(CVS QUIET)
  749. if(NOT CVS_EXECUTABLE)
  750. message(FATAL_ERROR "error: could not find cvs for checkout of ${name}")
  751. endif()
  752. set(cvs_module "${_EP_CVS_MODULE}")
  753. if(NOT cvs_module)
  754. message(FATAL_ERROR "error: no CVS_MODULE")
  755. endif()
  756. set(cvs_tag "${_EP_CVS_TAG}")
  757. get_filename_component(src_name "${source_dir}" NAME)
  758. get_filename_component(work_dir "${source_dir}" PATH)
  759. set(comment "Performing download step (CVS checkout) for '${name}'")
  760. set(cmd
  761. ${CVS_EXECUTABLE}
  762. -d ${cvs_repository}
  763. -q
  764. co ${cvs_tag}
  765. -d ${src_name}
  766. ${cvs_module}
  767. )
  768. if(arg_SCRIPT_FILE)
  769. _ep_add_script_commands(
  770. step_script_contents
  771. "${work_dir}"
  772. "${cmd}" # Must be a single quoted argument
  773. )
  774. endif()
  775. elseif(svn_repository)
  776. set(method svn)
  777. find_package(Subversion QUIET)
  778. if(NOT Subversion_SVN_EXECUTABLE)
  779. message(FATAL_ERROR "error: could not find svn for checkout of ${name}")
  780. endif()
  781. set(svn_trust_cert "${_EP_SVN_TRUST_CERT}")
  782. set(uses_terminal "${_EP_USES_TERMINAL_DOWNLOAD}")
  783. get_filename_component(src_name "${source_dir}" NAME)
  784. get_filename_component(work_dir "${source_dir}" PATH)
  785. set(comment "Performing download step (SVN checkout) for '${name}'")
  786. set(cmd
  787. ${Subversion_SVN_EXECUTABLE}
  788. co
  789. ${svn_repository}
  790. ${_EP_SVN_REVISION}
  791. )
  792. # The --trust-server-cert option requires --non-interactive
  793. if(svn_trust_cert OR NOT uses_terminal)
  794. list(APPEND cmd "--non-interactive")
  795. endif()
  796. if(svn_trust_cert)
  797. list(APPEND cmd "--trust-server-cert")
  798. endif()
  799. if(DEFINED _EP_SVN_USERNAME)
  800. list(APPEND cmd "--username=${_EP_SVN_USERNAME}")
  801. endif()
  802. if(DEFINED _EP_SVN_PASSWORD)
  803. list(APPEND cmd "--password=${_EP_SVN_PASSWORD}")
  804. endif()
  805. list(APPEND cmd ${src_name})
  806. if(arg_SCRIPT_FILE)
  807. _ep_add_script_commands(
  808. step_script_contents
  809. "${work_dir}"
  810. "${cmd}" # Must be a single quoted argument
  811. )
  812. endif()
  813. elseif(git_repository)
  814. set(method git)
  815. # FetchContent gives us these directly, so don't try to recompute them
  816. if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING)
  817. unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
  818. find_package(Git QUIET)
  819. if(NOT GIT_EXECUTABLE)
  820. message(FATAL_ERROR "error: could not find git for clone of ${name}")
  821. endif()
  822. endif()
  823. _ep_get_git_submodules_recurse(git_submodules_recurse)
  824. set(git_tag "${_EP_GIT_TAG}")
  825. if(NOT git_tag)
  826. set(git_tag "master")
  827. endif()
  828. set(git_init_submodules TRUE)
  829. if(DEFINED _EP_GIT_SUBMODULES)
  830. set(git_submodules "${_EP_GIT_SUBMODULES}")
  831. if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW")
  832. set(git_init_submodules FALSE)
  833. endif()
  834. endif()
  835. set(git_remote_name "${_EP_GIT_REMOTE_NAME}")
  836. if(NOT git_remote_name)
  837. set(git_remote_name "origin")
  838. endif()
  839. _ep_get_tls_version(${name} tls_version)
  840. _ep_get_tls_verify(${name} tls_verify)
  841. set(git_shallow "${_EP_GIT_SHALLOW}")
  842. set(git_progress "${_EP_GIT_PROGRESS}")
  843. set(git_config "${_EP_GIT_CONFIG}")
  844. # If git supports it, make checkouts quiet when checking out a git hash.
  845. # This avoids the very noisy detached head message.
  846. if(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.7)
  847. list(PREPEND git_config advice.detachedHead=false)
  848. endif()
  849. # The command doesn't expose any details, so we need to record additional
  850. # information in the RepositoryInfo.txt file. For the download step, only
  851. # the things specifically affecting the clone operation should be recorded.
  852. # If the repo changes, the clone script should be run again.
  853. # But if only the tag changes, avoid running the clone script again.
  854. # Let the 'always' running update step checkout the new tag.
  855. #
  856. set(extra_repo_info
  857. "repository=${git_repository}
  858. remote=${git_remote_name}
  859. init_submodules=${git_init_submodules}
  860. recurse_submodules=${git_submodules_recurse}
  861. submodules=${git_submodules}
  862. CMP0097=${_EP_CMP0097}
  863. ")
  864. get_filename_component(src_name "${source_dir}" NAME)
  865. get_filename_component(work_dir "${source_dir}" PATH)
  866. # Since git clone doesn't succeed if the non-empty source_dir exists,
  867. # create a cmake script to invoke as download command.
  868. # The script will delete the source directory and then call git clone.
  869. #
  870. set(clone_script ${tmp_dir}/${name}-gitclone.cmake)
  871. _ep_write_gitclone_script(
  872. ${clone_script}
  873. ${source_dir}
  874. ${GIT_EXECUTABLE}
  875. ${git_repository}
  876. ${git_tag}
  877. ${git_remote_name}
  878. ${git_init_submodules}
  879. "${git_submodules_recurse}"
  880. "${git_submodules}"
  881. "${git_shallow}"
  882. "${git_progress}"
  883. "${git_config}"
  884. ${src_name}
  885. ${work_dir}
  886. ${stamp_dir}/${name}-gitinfo.txt
  887. ${stamp_dir}/${name}-gitclone-lastrun.txt
  888. "${tls_version}"
  889. "${tls_verify}"
  890. )
  891. set(comment "Performing download step (git clone) for '${name}'")
  892. set(cmd ${CMAKE_COMMAND}
  893. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  894. -P ${clone_script}
  895. )
  896. if(arg_SCRIPT_FILE)
  897. set(step_script_contents "include(\"${clone_script}\")")
  898. list(APPEND depends ${clone_script})
  899. endif()
  900. elseif(hg_repository)
  901. set(method hg)
  902. find_package(Hg QUIET)
  903. if(NOT HG_EXECUTABLE)
  904. message(FATAL_ERROR "error: could not find hg for clone of ${name}")
  905. endif()
  906. set(hg_tag "${_EP_HG_TAG}")
  907. if(NOT hg_tag)
  908. set(hg_tag "tip")
  909. endif()
  910. # The command doesn't expose any details, so we need to record additional
  911. # information in the RepositoryInfo.txt file. For the download step, only
  912. # the things specifically affecting the clone operation should be recorded.
  913. # If the repo changes, the clone script should be run again.
  914. # But if only the tag changes, avoid running the clone script again.
  915. # Let the 'always' running update step checkout the new tag.
  916. #
  917. set(extra_repo_info "repository=${hg_repository}")
  918. get_filename_component(src_name "${source_dir}" NAME)
  919. get_filename_component(work_dir "${source_dir}" PATH)
  920. # Since hg clone doesn't succeed if the non-empty source_dir exists,
  921. # create a cmake script to invoke as download command.
  922. # The script will delete the source directory and then call hg clone.
  923. #
  924. set(clone_script ${tmp_dir}/${name}-hgclone.cmake)
  925. _ep_write_hgclone_script(
  926. ${clone_script}
  927. ${source_dir}
  928. ${HG_EXECUTABLE}
  929. ${hg_repository}
  930. ${hg_tag}
  931. ${src_name}
  932. ${work_dir}
  933. ${stamp_dir}/${name}-hginfo.txt
  934. ${stamp_dir}/${name}-hgclone-lastrun.txt
  935. )
  936. set(comment "Performing download step (hg clone) for '${name}'")
  937. set(cmd ${CMAKE_COMMAND}
  938. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  939. -P ${clone_script}
  940. )
  941. if(arg_SCRIPT_FILE)
  942. set(step_script_contents "include(\"${clone_script}\")")
  943. list(APPEND depends ${clone_script})
  944. endif()
  945. elseif(url)
  946. set(method url)
  947. get_filename_component(work_dir "${source_dir}" PATH)
  948. set(hash "${_EP_URL_HASH}")
  949. _ep_get_hash_regex(_ep_hash_regex)
  950. if(hash AND NOT "${hash}" MATCHES "${_ep_hash_regex}")
  951. _ep_get_hash_algos(_ep_hash_algos)
  952. list(JOIN _ep_hash_algos "|" _ep_hash_algos)
  953. message(FATAL_ERROR
  954. "URL_HASH is set to\n"
  955. " ${hash}\n"
  956. "but must be ALGO=value where ALGO is\n"
  957. " ${_ep_hash_algos}\n"
  958. "and value is a hex string."
  959. )
  960. endif()
  961. set(md5 "${_EP_URL_MD5}")
  962. if(md5 AND NOT "MD5=${md5}" MATCHES "${_ep_hash_regex}")
  963. message(FATAL_ERROR
  964. "URL_MD5 is set to\n"
  965. " ${md5}\n"
  966. "but must be a hex string."
  967. )
  968. endif()
  969. if(md5 AND NOT hash)
  970. set(hash "MD5=${md5}")
  971. endif()
  972. set(extra_repo_info
  973. "url(s)=${url}
  974. hash=${hash}
  975. ")
  976. list(LENGTH url url_list_length)
  977. if(NOT "${url_list_length}" STREQUAL "1")
  978. foreach(entry IN LISTS url)
  979. if(NOT "${entry}" MATCHES "^[a-z]+://")
  980. message(FATAL_ERROR
  981. "At least one entry of URL is a path (invalid in a list)"
  982. )
  983. endif()
  984. endforeach()
  985. if("x${fname}" STREQUAL "x")
  986. list(GET url 0 fname)
  987. endif()
  988. endif()
  989. if(IS_DIRECTORY "${url}")
  990. get_filename_component(abs_dir "${url}" ABSOLUTE)
  991. set(comment "Performing download step (DIR copy) for '${name}'")
  992. set(cmd
  993. ${CMAKE_COMMAND} -E rm -rf ${source_dir}
  994. COMMAND ${CMAKE_COMMAND} -E copy_directory ${abs_dir} ${source_dir}
  995. )
  996. if(arg_SCRIPT_FILE)
  997. # While it may be tempting to implement the two operations directly
  998. # with file(), the behavior is different. file(COPY) preserves input
  999. # file timestamps, which we don't want. Therefore, still use the same
  1000. # external commands so that we get the same behavior.
  1001. _ep_add_script_commands(
  1002. step_script_contents
  1003. "${work_dir}"
  1004. "${cmd}" # Must be a single quoted argument
  1005. )
  1006. endif()
  1007. else()
  1008. set(no_extract "${_EP_DOWNLOAD_NO_EXTRACT}")
  1009. string(APPEND extra_repo_info "no_extract=${no_extract}\n")
  1010. set(verify_script "${stamp_dir}/verify-${name}.cmake")
  1011. if("${url}" MATCHES "^[a-z]+://")
  1012. # TODO: Should download and extraction be different steps?
  1013. if("x${fname}" STREQUAL "x")
  1014. set(fname "${url}")
  1015. endif()
  1016. set(ext_regex [[7z|tar|tar\.bz2|tar\.gz|tar\.xz|tbz2|tgz|txz|zip]])
  1017. if("${fname}" MATCHES "([^/\\?#]+(\\.|=)(${ext_regex}))([/?#].*)?$")
  1018. set(fname "${CMAKE_MATCH_1}")
  1019. elseif(no_extract)
  1020. get_filename_component(fname "${fname}" NAME)
  1021. else()
  1022. # Fall back to a default file name. The actual file name does not
  1023. # matter because it is used only internally and our extraction tool
  1024. # inspects the file content directly. If it turns out the wrong URL
  1025. # was given that will be revealed during the build which is an easier
  1026. # place for users to diagnose than an error here anyway.
  1027. set(fname "archive.tar")
  1028. endif()
  1029. string(REPLACE ";" "-" fname "${fname}")
  1030. set(file ${download_dir}/${fname})
  1031. set(timeout "${_EP_TIMEOUT}")
  1032. set(inactivity_timeout "${_EP_INACTIVITY_TIMEOUT}")
  1033. set(no_progress "${_EP_DOWNLOAD_NO_PROGRESS}")
  1034. _ep_get_tls_version(${name} tls_version)
  1035. _ep_get_tls_verify(${name} tls_verify)
  1036. _ep_get_tls_cainfo(${name} tls_cainfo)
  1037. _ep_get_netrc(${name} netrc)
  1038. _ep_get_netrc_file(${name} netrc_file)
  1039. set(http_username "${_EP_HTTP_USERNAME}")
  1040. set(http_password "${_EP_HTTP_PASSWORD}")
  1041. set(http_headers "${_EP_HTTP_HEADER}")
  1042. set(download_script "${stamp_dir}/download-${name}.cmake")
  1043. _ep_write_downloadfile_script(
  1044. "${download_script}"
  1045. "${url}"
  1046. "${file}"
  1047. "${timeout}"
  1048. "${inactivity_timeout}"
  1049. "${no_progress}"
  1050. "${hash}"
  1051. "${tls_version}"
  1052. "${tls_verify}"
  1053. "${tls_cainfo}"
  1054. "${http_username}:${http_password}"
  1055. "${http_headers}"
  1056. "${netrc}"
  1057. "${netrc_file}"
  1058. )
  1059. set(cmd
  1060. ${CMAKE_COMMAND}
  1061. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  1062. -P "${download_script}"
  1063. COMMAND
  1064. )
  1065. if(arg_SCRIPT_FILE)
  1066. set(step_script_contents "include(\"${download_script}\")\n")
  1067. endif()
  1068. if (no_extract)
  1069. set(steps "download and verify")
  1070. else ()
  1071. set(steps "download, verify and extract")
  1072. endif ()
  1073. set(comment "Performing download step (${steps}) for '${name}'")
  1074. # already verified by 'download_script'
  1075. file(WRITE "${verify_script}" "")
  1076. # Rather than adding everything to the RepositoryInfo.txt file, it is
  1077. # more robust to just depend on the download script. That way, we will
  1078. # re-download if any aspect of the download changes.
  1079. list(APPEND depends "${download_script}")
  1080. else()
  1081. set(file "${url}")
  1082. if (no_extract)
  1083. set(steps "verify")
  1084. else ()
  1085. set(steps "verify and extract")
  1086. endif ()
  1087. set(comment "Performing download step (${steps}) for '${name}'")
  1088. _ep_write_verifyfile_script(
  1089. "${verify_script}"
  1090. "${file}"
  1091. "${hash}"
  1092. )
  1093. endif()
  1094. list(APPEND cmd ${CMAKE_COMMAND}
  1095. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  1096. -P ${verify_script}
  1097. )
  1098. if(arg_SCRIPT_FILE)
  1099. string(APPEND step_script_contents "include(\"${verify_script}\")\n")
  1100. list(APPEND depends ${verify_script})
  1101. endif()
  1102. set(extract_timestamp "${_EP_DOWNLOAD_EXTRACT_TIMESTAMP}")
  1103. if(no_extract)
  1104. if(DEFINED _EP_DOWNLOAD_EXTRACT_TIMESTAMP)
  1105. message(FATAL_ERROR
  1106. "Cannot specify DOWNLOAD_EXTRACT_TIMESTAMP when using "
  1107. "DOWNLOAD_NO_EXTRACT TRUE"
  1108. )
  1109. endif()
  1110. if(arg_SCRIPT_FILE)
  1111. # There's no target to record the location of the downloaded file.
  1112. # Instead, we copy it to the source directory within the script,
  1113. # which is what FetchContent always does in this situation.
  1114. cmake_path(SET safe_file NORMALIZE "${file}")
  1115. cmake_path(GET safe_file FILENAME filename)
  1116. string(APPEND step_script_contents
  1117. "file(COPY_FILE\n"
  1118. " \"${file}\"\n"
  1119. " \"${source_dir}/${filename}\"\n"
  1120. " ONLY_IF_DIFFERENT\n"
  1121. " INPUT_MAY_BE_RECENT\n"
  1122. ")"
  1123. )
  1124. list(APPEND depends ${source_dir}/${filename})
  1125. else()
  1126. set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file})
  1127. endif()
  1128. else()
  1129. if(NOT DEFINED _EP_DOWNLOAD_EXTRACT_TIMESTAMP)
  1130. # Default depends on policy CMP0135
  1131. if(_EP_CMP0135 STREQUAL "")
  1132. message(AUTHOR_WARNING
  1133. "The DOWNLOAD_EXTRACT_TIMESTAMP option was not given and policy "
  1134. "CMP0135 is not set. The policy's OLD behavior will be used. "
  1135. "When using a URL download, the timestamps of extracted files "
  1136. "should preferably be that of the time of extraction, otherwise "
  1137. "code that depends on the extracted contents might not be "
  1138. "rebuilt if the URL changes. The OLD behavior preserves the "
  1139. "timestamps from the archive instead, but this is usually not "
  1140. "what you want. Update your project to the NEW behavior or "
  1141. "specify the DOWNLOAD_EXTRACT_TIMESTAMP option with a value of "
  1142. "true to avoid this robustness issue."
  1143. )
  1144. set(extract_timestamp TRUE)
  1145. elseif(_EP_CMP0135 STREQUAL "NEW")
  1146. set(extract_timestamp FALSE)
  1147. else()
  1148. set(extract_timestamp TRUE)
  1149. endif()
  1150. endif()
  1151. if(extract_timestamp)
  1152. set(options "")
  1153. else()
  1154. set(options "--touch")
  1155. endif()
  1156. set(extract_script "${stamp_dir}/extract-${name}.cmake")
  1157. _ep_write_extractfile_script(
  1158. "${extract_script}"
  1159. "${name}"
  1160. "${file}"
  1161. "${source_dir}"
  1162. "${options}"
  1163. )
  1164. list(APPEND cmd
  1165. COMMAND ${CMAKE_COMMAND}
  1166. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  1167. -P ${extract_script}
  1168. )
  1169. if(arg_SCRIPT_FILE)
  1170. string(APPEND step_script_contents "include(\"${extract_script}\")\n")
  1171. list(APPEND depends ${extract_script})
  1172. endif()
  1173. endif ()
  1174. endif()
  1175. else()
  1176. set(method source_dir)
  1177. _ep_is_dir_empty("${source_dir}" empty)
  1178. if(${empty})
  1179. message(FATAL_ERROR
  1180. "No download info given for '${name}' and its source directory:\n"
  1181. " ${source_dir}\n"
  1182. "is not an existing non-empty directory. Please specify one of:\n"
  1183. " * SOURCE_DIR with an existing non-empty directory\n"
  1184. " * DOWNLOAD_COMMAND\n"
  1185. " * URL\n"
  1186. " * GIT_REPOSITORY\n"
  1187. " * SVN_REPOSITORY\n"
  1188. " * HG_REPOSITORY\n"
  1189. " * CVS_REPOSITORY and CVS_MODULE"
  1190. )
  1191. endif()
  1192. if(arg_SCRIPT_FILE)
  1193. set(step_script_contents "message(VERBOSE [[Using SOURCE_DIR as is]])")
  1194. endif()
  1195. endif()
  1196. # We use configure_file() to write the repo_info_file so that the file's
  1197. # timestamp is not updated if we don't change the contents
  1198. set(repo_info_file ${stamp_dir}/${name}-${method}info.txt)
  1199. list(APPEND depends ${repo_info_file})
  1200. configure_file(
  1201. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/RepositoryInfo.txt.in"
  1202. "${repo_info_file}"
  1203. @ONLY
  1204. )
  1205. if(arg_SCRIPT_FILE)
  1206. set(step_name download)
  1207. configure_file(
  1208. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stepscript.cmake.in"
  1209. "${arg_SCRIPT_FILE}"
  1210. @ONLY
  1211. )
  1212. set(${arg_DEPENDS_VARIABLE} "${depends}" PARENT_SCOPE)
  1213. return()
  1214. endif()
  1215. # Nothing below this point is applicable when we've been asked to put the
  1216. # download step in a script file (which is the FetchContent case).
  1217. if(_EP_LOG_DOWNLOAD)
  1218. set(log LOG 1)
  1219. else()
  1220. set(log "")
  1221. endif()
  1222. if(_EP_USES_TERMINAL_DOWNLOAD)
  1223. set(uses_terminal USES_TERMINAL 1)
  1224. else()
  1225. set(uses_terminal "")
  1226. endif()
  1227. set(__cmdQuoted)
  1228. foreach(__item IN LISTS cmd)
  1229. string(APPEND __cmdQuoted " [==[${__item}]==]")
  1230. endforeach()
  1231. cmake_language(EVAL CODE "
  1232. ExternalProject_Add_Step(\${name} download
  1233. INDEPENDENT TRUE
  1234. COMMENT \${comment}
  1235. COMMAND ${__cmdQuoted}
  1236. WORKING_DIRECTORY \${work_dir}
  1237. DEPENDS \${depends}
  1238. DEPENDEES mkdir
  1239. ${log}
  1240. ${uses_terminal}
  1241. )"
  1242. )
  1243. endfunction()
  1244. function(_ep_get_update_disconnected var name)
  1245. # Note that the arguments are assumed to have already been parsed and have
  1246. # been translated into variables with the prefix _EP_... by a call to
  1247. # ep_parse_arguments() or ep_parse_arguments_to_vars().
  1248. if(DEFINED _EP_UPDATE_DISCONNECTED)
  1249. set(update_disconnected "${_EP_UPDATE_DISCONNECTED}")
  1250. else()
  1251. get_property(update_disconnected
  1252. DIRECTORY
  1253. PROPERTY EP_UPDATE_DISCONNECTED
  1254. )
  1255. endif()
  1256. set(${var} "${update_disconnected}" PARENT_SCOPE)
  1257. endfunction()
  1258. function(_ep_add_update_command name)
  1259. set(noValueOptions )
  1260. set(singleValueOptions
  1261. SCRIPT_FILE # These should only be used by FetchContent
  1262. DEPEND_VARIABLE #
  1263. )
  1264. set(multiValueOptions )
  1265. cmake_parse_arguments(PARSE_ARGV 1 arg
  1266. "${noValueOptions}" "${singleValueOptions}" "${multiValueOptions}"
  1267. )
  1268. # The various _EP_... variables mentioned here and throughout this function
  1269. # are expected to already have been set by the caller via a call to
  1270. # _ep_parse_arguments() or ep_parse_arguments_to_vars(). Other variables
  1271. # with different names are assigned to for historical reasons only to keep
  1272. # the code more readable and minimize change.
  1273. set(source_dir "${_EP_SOURCE_DIR}")
  1274. set(stamp_dir "${_EP_STAMP_DIR}")
  1275. set(tmp_dir "${_EP_TMP_DIR}")
  1276. set(cmd "${_EP_UPDATE_COMMAND}")
  1277. set(cvs_repository "${_EP_CVS_REPOSITORY}")
  1278. set(svn_repository "${_EP_SVN_REPOSITORY}")
  1279. set(git_repository "${_EP_GIT_REPOSITORY}")
  1280. set(hg_repository "${_EP_HG_REPOSITORY}")
  1281. _ep_get_update_disconnected(update_disconnected ${name})
  1282. set(work_dir)
  1283. set(comment)
  1284. set(always)
  1285. set(file_deps)
  1286. if(DEFINED _EP_UPDATE_COMMAND)
  1287. set(work_dir ${source_dir})
  1288. if(NOT "x${cmd}" STREQUAL "x")
  1289. set(always 1)
  1290. _ep_add_script_commands(
  1291. step_script_contents
  1292. "${work_dir}"
  1293. "${cmd}" # Must be a single quoted argument
  1294. )
  1295. endif()
  1296. elseif(cvs_repository)
  1297. if(NOT CVS_EXECUTABLE)
  1298. message(FATAL_ERROR "error: could not find cvs for update of ${name}")
  1299. endif()
  1300. set(work_dir ${source_dir})
  1301. set(comment "Performing update step (CVS update) for '${name}'")
  1302. set(cvs_tag "${_EP_CVS_TAG}")
  1303. set(cmd ${CVS_EXECUTABLE} -d ${cvs_repository} -q up -dP ${cvs_tag})
  1304. set(always 1)
  1305. if(arg_SCRIPT_FILE)
  1306. _ep_add_script_commands(
  1307. step_script_contents
  1308. "${work_dir}"
  1309. "${cmd}" # Must be a single quoted argument
  1310. )
  1311. endif()
  1312. elseif(svn_repository)
  1313. if(NOT Subversion_SVN_EXECUTABLE)
  1314. message(FATAL_ERROR "error: could not find svn for update of ${name}")
  1315. endif()
  1316. set(work_dir ${source_dir})
  1317. set(comment "Performing update step (SVN update) for '${name}'")
  1318. set(svn_trust_cert "${_EP_SVN_TRUST_CERT}")
  1319. set(uses_terminal "${_EP_USES_TERMINAL_UPDATE}")
  1320. set(cmd
  1321. ${Subversion_SVN_EXECUTABLE}
  1322. up
  1323. ${_EP_SVN_REVISION}
  1324. )
  1325. # The --trust-server-cert option requires --non-interactive
  1326. if(svn_trust_cert OR NOT uses_terminal)
  1327. list(APPEND cmd "--non-interactive")
  1328. endif()
  1329. if(svn_trust_cert)
  1330. list(APPEND cmd --trust-server-cert)
  1331. endif()
  1332. if(DEFINED _EP_SVN_USERNAME)
  1333. list(APPEND cmd "--username=${_EP_SVN_USERNAME}")
  1334. endif()
  1335. if(DEFINED _EP_SVN_PASSWORD)
  1336. list(APPEND cmd "--password=${_EP_SVN_PASSWORD}")
  1337. endif()
  1338. set(always 1)
  1339. if(arg_SCRIPT_FILE)
  1340. _ep_add_script_commands(
  1341. step_script_contents
  1342. "${work_dir}"
  1343. "${cmd}" # Must be a single quoted argument
  1344. )
  1345. endif()
  1346. elseif(git_repository)
  1347. # FetchContent gives us these directly, so don't try to recompute them
  1348. if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING)
  1349. unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
  1350. find_package(Git QUIET)
  1351. if(NOT GIT_EXECUTABLE)
  1352. message(FATAL_ERROR "error: could not find git for fetch of ${name}")
  1353. endif()
  1354. endif()
  1355. set(work_dir ${source_dir})
  1356. set(comment "Performing update step for '${name}'")
  1357. set(comment_disconnected "Performing disconnected update step for '${name}'")
  1358. set(git_tag "${_EP_GIT_TAG}")
  1359. if(NOT git_tag)
  1360. set(git_tag "master")
  1361. endif()
  1362. set(git_remote_name "${_EP_GIT_REMOTE_NAME}")
  1363. if(NOT git_remote_name)
  1364. set(git_remote_name "origin")
  1365. endif()
  1366. set(git_init_submodules TRUE)
  1367. if(DEFINED _EP_GIT_SUBMODULES)
  1368. set(git_submodules "${_EP_GIT_SUBMODULES}")
  1369. if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW")
  1370. set(git_init_submodules FALSE)
  1371. endif()
  1372. endif()
  1373. set(git_update_strategy "${_EP_GIT_REMOTE_UPDATE_STRATEGY}")
  1374. if(NOT git_update_strategy)
  1375. set(git_update_strategy "${CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY}")
  1376. endif()
  1377. if(NOT git_update_strategy)
  1378. set(git_update_strategy REBASE)
  1379. endif()
  1380. set(strategies CHECKOUT REBASE REBASE_CHECKOUT)
  1381. if(NOT git_update_strategy IN_LIST strategies)
  1382. message(FATAL_ERROR
  1383. "'${git_update_strategy}' is not one of the supported strategies: "
  1384. "${strategies}"
  1385. )
  1386. endif()
  1387. _ep_get_git_submodules_recurse(git_submodules_recurse)
  1388. _ep_get_tls_version(${name} tls_version)
  1389. _ep_get_tls_verify(${name} tls_verify)
  1390. set(update_script "${tmp_dir}/${name}-gitupdate.cmake")
  1391. list(APPEND file_deps ${update_script})
  1392. _ep_write_gitupdate_script(
  1393. "${update_script}"
  1394. "${GIT_EXECUTABLE}"
  1395. "${git_tag}"
  1396. "${git_remote_name}"
  1397. "${git_init_submodules}"
  1398. "${git_submodules_recurse}"
  1399. "${git_submodules}"
  1400. "${git_repository}"
  1401. "${work_dir}"
  1402. "${git_update_strategy}"
  1403. "${tls_version}"
  1404. "${tls_verify}"
  1405. )
  1406. set(cmd ${CMAKE_COMMAND}
  1407. -Dcan_fetch=YES
  1408. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  1409. -P ${update_script}
  1410. )
  1411. set(cmd_disconnected ${CMAKE_COMMAND}
  1412. -Dcan_fetch=NO
  1413. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  1414. -P ${update_script}
  1415. )
  1416. set(always 1)
  1417. if(arg_SCRIPT_FILE)
  1418. if(update_disconnected)
  1419. set(can_fetch_default NO)
  1420. else()
  1421. set(can_fetch_default YES)
  1422. endif()
  1423. set(step_script_contents "include(\"${update_script}\")")
  1424. endif()
  1425. elseif(hg_repository)
  1426. if(NOT HG_EXECUTABLE)
  1427. message(FATAL_ERROR "error: could not find hg for pull of ${name}")
  1428. endif()
  1429. set(work_dir ${source_dir})
  1430. set(comment "Performing update step (hg pull) for '${name}'")
  1431. set(comment_disconnected "Performing disconnected update step for '${name}'")
  1432. set(hg_tag "${_EP_HG_TAG}")
  1433. if(NOT hg_tag)
  1434. set(hg_tag "tip")
  1435. endif()
  1436. if("${HG_VERSION_STRING}" STREQUAL "2.1")
  1437. set(notesAnchor
  1438. "#A2.1.1:_revert_pull_return_code_change.2C_compile_issue_on_OS_X"
  1439. )
  1440. message(WARNING
  1441. "Mercurial 2.1 does not distinguish an empty pull from a failed pull:
  1442. http://mercurial.selenic.com/wiki/UpgradeNotes${notesAnchor}
  1443. http://thread.gmane.org/gmane.comp.version-control.mercurial.devel/47656
  1444. Update to Mercurial >= 2.1.1.
  1445. ")
  1446. endif()
  1447. set(cmd
  1448. ${HG_EXECUTABLE} pull
  1449. COMMAND ${HG_EXECUTABLE} update ${hg_tag}
  1450. )
  1451. set(cmd_disconnected ${HG_EXECUTABLE} update ${hg_tag})
  1452. set(always 1)
  1453. if(arg_SCRIPT_FILE)
  1454. # These commands are simple, and we know whether updates need to be
  1455. # disconnected or not for this case, so write them directly instead of
  1456. # forming them from "cmd" and "cmd_disconnected".
  1457. if(NOT update_disconnected)
  1458. string(APPEND step_script_contents
  1459. "execute_process(\n"
  1460. " WORKING_DIRECTORY \"${work_dir}\"\n"
  1461. " COMMAND_ERROR_IS_FATAL LAST\n"
  1462. " COMMAND \"${HG_EXECUTABLE}\" pull\n"
  1463. ")"
  1464. )
  1465. endif()
  1466. string(APPEND step_script_contents
  1467. "execute_process(\n"
  1468. " WORKING_DIRECTORY \"${work_dir}\"\n"
  1469. " COMMAND_ERROR_IS_FATAL LAST\n"
  1470. " COMMAND \"${HG_EXECUTABLE}\" update \"${hg_tag}\"\n"
  1471. ")"
  1472. )
  1473. endif()
  1474. endif()
  1475. # We use configure_file() to write the update_info_file so that the file's
  1476. # timestamp is not updated if we don't change the contents
  1477. if(NOT DEFINED cmd_disconnected)
  1478. set(cmd_disconnected "${cmd}")
  1479. endif()
  1480. set(update_info_file ${stamp_dir}/${name}-update-info.txt)
  1481. list(APPEND file_deps ${update_info_file})
  1482. configure_file(
  1483. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/UpdateInfo.txt.in"
  1484. "${update_info_file}"
  1485. @ONLY
  1486. )
  1487. if(arg_SCRIPT_FILE)
  1488. set(step_name update)
  1489. configure_file(
  1490. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stepscript.cmake.in"
  1491. "${arg_SCRIPT_FILE}"
  1492. @ONLY
  1493. )
  1494. set(${arg_DEPENDS_VARIABLE} "${file_deps}" PARENT_SCOPE)
  1495. return()
  1496. endif()
  1497. # Nothing below this point is applicable when we've been asked to put the
  1498. # update step in a script file (which is the FetchContent case).
  1499. if(_EP_LOG_UPDATE)
  1500. set(log LOG 1)
  1501. else()
  1502. set(log "")
  1503. endif()
  1504. if(_EP_USES_TERMINAL_UPDATE)
  1505. set(uses_terminal USES_TERMINAL 1)
  1506. else()
  1507. set(uses_terminal "")
  1508. endif()
  1509. set(__cmdQuoted)
  1510. foreach(__item IN LISTS cmd)
  1511. string(APPEND __cmdQuoted " [==[${__item}]==]")
  1512. endforeach()
  1513. cmake_language(EVAL CODE "
  1514. ExternalProject_Add_Step(${name} update
  1515. INDEPENDENT TRUE
  1516. COMMENT \${comment}
  1517. COMMAND ${__cmdQuoted}
  1518. ALWAYS \${always}
  1519. EXCLUDE_FROM_MAIN \${update_disconnected}
  1520. WORKING_DIRECTORY \${work_dir}
  1521. DEPENDEES download
  1522. DEPENDS \${file_deps}
  1523. ${log}
  1524. ${uses_terminal}
  1525. )"
  1526. )
  1527. if(update_disconnected)
  1528. if(NOT DEFINED comment_disconnected)
  1529. set(comment_disconnected "${comment}")
  1530. endif()
  1531. set(__cmdQuoted)
  1532. foreach(__item IN LISTS cmd_disconnected)
  1533. string(APPEND __cmdQuoted " [==[${__item}]==]")
  1534. endforeach()
  1535. cmake_language(EVAL CODE "
  1536. ExternalProject_Add_Step(${name} update_disconnected
  1537. INDEPENDENT TRUE
  1538. COMMENT \${comment_disconnected}
  1539. COMMAND ${__cmdQuoted}
  1540. WORKING_DIRECTORY \${work_dir}
  1541. DEPENDEES download
  1542. DEPENDS \${file_deps}
  1543. ${log}
  1544. ${uses_terminal}
  1545. )"
  1546. )
  1547. endif()
  1548. endfunction()
  1549. function(_ep_add_patch_command name)
  1550. set(noValueOptions )
  1551. set(singleValueOptions
  1552. SCRIPT_FILE # These should only be used by FetchContent
  1553. )
  1554. set(multiValueOptions )
  1555. cmake_parse_arguments(PARSE_ARGV 1 arg
  1556. "${noValueOptions}" "${singleValueOptions}" "${multiValueOptions}"
  1557. )
  1558. # The various _EP_... variables mentioned here and throughout this function
  1559. # are expected to already have been set by the caller via a call to
  1560. # _ep_parse_arguments() or ep_parse_arguments_to_vars(). Other variables
  1561. # with different names are assigned to for historical reasons only to keep
  1562. # the code more readable and minimize change.
  1563. set(source_dir "${_EP_SOURCE_DIR}")
  1564. set(stamp_dir "${_EP_STAMP_DIR}")
  1565. set(cmd "${_EP_PATCH_COMMAND}")
  1566. set(step_script_contents "")
  1567. set(work_dir)
  1568. if(DEFINED _EP_PATCH_COMMAND)
  1569. set(work_dir ${source_dir})
  1570. if(arg_SCRIPT_FILE)
  1571. _ep_add_script_commands(
  1572. step_script_contents
  1573. "${work_dir}"
  1574. "${cmd}" # Must be a single quoted argument
  1575. )
  1576. endif()
  1577. endif()
  1578. # We use configure_file() to write the patch_info_file so that the file's
  1579. # timestamp is not updated if we don't change the contents
  1580. set(patch_info_file ${stamp_dir}/${name}-patch-info.txt)
  1581. configure_file(
  1582. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/PatchInfo.txt.in"
  1583. "${patch_info_file}"
  1584. @ONLY
  1585. )
  1586. if(arg_SCRIPT_FILE)
  1587. set(step_name patch)
  1588. configure_file(
  1589. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stepscript.cmake.in"
  1590. "${arg_SCRIPT_FILE}"
  1591. @ONLY
  1592. )
  1593. return()
  1594. endif()
  1595. # Nothing below this point is applicable when we've been asked to put the
  1596. # patch step in a script file (which is the FetchContent case).
  1597. if(_EP_LOG_PATCH)
  1598. set(log LOG 1)
  1599. else()
  1600. set(log "")
  1601. endif()
  1602. if(_EP_USES_TERMINAL_PATCH)
  1603. set(uses_terminal USES_TERMINAL 1)
  1604. else()
  1605. set(uses_terminal "")
  1606. endif()
  1607. _ep_get_update_disconnected(update_disconnected ${name})
  1608. set(__cmdQuoted)
  1609. foreach(__item IN LISTS cmd)
  1610. string(APPEND __cmdQuoted " [==[${__item}]==]")
  1611. endforeach()
  1612. cmake_language(EVAL CODE "
  1613. ExternalProject_Add_Step(${name} patch
  1614. INDEPENDENT TRUE
  1615. COMMAND ${__cmdQuoted}
  1616. WORKING_DIRECTORY \${work_dir}
  1617. EXCLUDE_FROM_MAIN \${update_disconnected}
  1618. DEPENDEES update
  1619. DEPENDS \${patch_info_file}
  1620. ${log}
  1621. ${uses_terminal}
  1622. )"
  1623. )
  1624. if(update_disconnected)
  1625. cmake_language(EVAL CODE "
  1626. ExternalProject_Add_Step(${name} patch_disconnected
  1627. INDEPENDENT TRUE
  1628. COMMAND ${__cmdQuoted}
  1629. WORKING_DIRECTORY \${work_dir}
  1630. DEPENDEES update_disconnected
  1631. DEPENDS \${patch_info_file}
  1632. ${log}
  1633. ${uses_terminal}
  1634. )"
  1635. )
  1636. endif()
  1637. endfunction()
  1638. macro(_ep_get_add_keywords out_var)
  1639. set(${out_var}
  1640. #
  1641. # Directory options
  1642. #
  1643. PREFIX
  1644. TMP_DIR
  1645. STAMP_DIR
  1646. LOG_DIR
  1647. DOWNLOAD_DIR
  1648. SOURCE_DIR
  1649. BINARY_DIR
  1650. INSTALL_DIR
  1651. #
  1652. # Download step options
  1653. #
  1654. DOWNLOAD_COMMAND
  1655. #
  1656. URL
  1657. URL_HASH
  1658. URL_MD5
  1659. DOWNLOAD_NAME
  1660. DOWNLOAD_EXTRACT_TIMESTAMP
  1661. DOWNLOAD_NO_EXTRACT
  1662. DOWNLOAD_NO_PROGRESS
  1663. TIMEOUT
  1664. INACTIVITY_TIMEOUT
  1665. HTTP_USERNAME
  1666. HTTP_PASSWORD
  1667. HTTP_HEADER
  1668. TLS_VERSION # Also used for git clone operations
  1669. TLS_VERIFY # Also used for git clone operations
  1670. TLS_CAINFO
  1671. NETRC
  1672. NETRC_FILE
  1673. #
  1674. GIT_REPOSITORY
  1675. GIT_TAG
  1676. GIT_REMOTE_NAME
  1677. GIT_SUBMODULES
  1678. GIT_SUBMODULES_RECURSE
  1679. GIT_SHALLOW
  1680. GIT_PROGRESS
  1681. GIT_CONFIG
  1682. GIT_REMOTE_UPDATE_STRATEGY
  1683. #
  1684. SVN_REPOSITORY
  1685. SVN_REVISION
  1686. SVN_USERNAME
  1687. SVN_PASSWORD
  1688. SVN_TRUST_CERT
  1689. #
  1690. HG_REPOSITORY
  1691. HG_TAG
  1692. #
  1693. CVS_REPOSITORY
  1694. CVS_MODULE
  1695. CVS_TAG
  1696. #
  1697. # Update step options
  1698. #
  1699. UPDATE_COMMAND
  1700. UPDATE_DISCONNECTED
  1701. #
  1702. # Patch step options
  1703. #
  1704. PATCH_COMMAND
  1705. #
  1706. # Configure step options
  1707. #
  1708. CONFIGURE_COMMAND
  1709. CMAKE_COMMAND
  1710. CMAKE_GENERATOR
  1711. CMAKE_GENERATOR_PLATFORM
  1712. CMAKE_GENERATOR_TOOLSET
  1713. CMAKE_GENERATOR_INSTANCE
  1714. CMAKE_ARGS
  1715. CMAKE_CACHE_ARGS
  1716. CMAKE_CACHE_DEFAULT_ARGS
  1717. SOURCE_SUBDIR
  1718. CONFIGURE_HANDLED_BY_BUILD
  1719. #
  1720. # Build step options
  1721. #
  1722. BUILD_COMMAND
  1723. BUILD_IN_SOURCE
  1724. BUILD_ALWAYS
  1725. BUILD_BYPRODUCTS
  1726. BUILD_JOB_SERVER_AWARE
  1727. #
  1728. # Install step options
  1729. #
  1730. INSTALL_COMMAND
  1731. INSTALL_BYPRODUCTS
  1732. #
  1733. # Test step options
  1734. #
  1735. TEST_COMMAND
  1736. TEST_BEFORE_INSTALL
  1737. TEST_AFTER_INSTALL
  1738. TEST_EXCLUDE_FROM_MAIN
  1739. #
  1740. # Logging options
  1741. #
  1742. LOG_DOWNLOAD
  1743. LOG_UPDATE
  1744. LOG_PATCH
  1745. LOG_CONFIGURE
  1746. LOG_BUILD
  1747. LOG_INSTALL
  1748. LOG_TEST
  1749. LOG_MERGED_STDOUTERR
  1750. LOG_OUTPUT_ON_FAILURE
  1751. #
  1752. # Terminal access options
  1753. #
  1754. USES_TERMINAL_DOWNLOAD
  1755. USES_TERMINAL_UPDATE
  1756. USES_TERMINAL_PATCH
  1757. USES_TERMINAL_CONFIGURE
  1758. USES_TERMINAL_BUILD
  1759. USES_TERMINAL_INSTALL
  1760. USES_TERMINAL_TEST
  1761. #
  1762. # Target options
  1763. #
  1764. DEPENDS
  1765. EXCLUDE_FROM_ALL
  1766. STEP_TARGETS
  1767. INDEPENDENT_STEP_TARGETS
  1768. #
  1769. # Miscellaneous options
  1770. #
  1771. LIST_SEPARATOR
  1772. #
  1773. # Internal options (undocumented)
  1774. #
  1775. EXTERNALPROJECT_INTERNAL_ARGUMENT_SEPARATOR
  1776. )
  1777. endmacro()