shared_internal_commands.cmake 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994
  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_revision "${_EP_SVN_REVISION}")
  782. set(svn_username "${_EP_SVN_USERNAME}")
  783. set(svn_password "${_EP_SVN_PASSWORD}")
  784. set(svn_trust_cert "${_EP_SVN_TRUST_CERT}")
  785. set(uses_terminal "${_EP_USES_TERMINAL_DOWNLOAD}")
  786. # The --trust-server-cert option requires --non-interactive
  787. if(uses_terminal AND NOT svn_trust_cert)
  788. set(svn_interactive_args "")
  789. else()
  790. set(svn_interactive_args "--non-interactive")
  791. endif()
  792. get_filename_component(src_name "${source_dir}" NAME)
  793. get_filename_component(work_dir "${source_dir}" PATH)
  794. set(comment "Performing download step (SVN checkout) for '${name}'")
  795. set(svn_user_pw_args "")
  796. if(DEFINED _EP_SVN_USERNAME)
  797. set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}")
  798. endif()
  799. if(DEFINED _EP_SVN_PASSWORD)
  800. set(svn_user_pw_args ${svn_user_pw_args} "--password=${svn_password}")
  801. endif()
  802. if(svn_trust_cert)
  803. set(svn_trust_cert_args --trust-server-cert)
  804. endif()
  805. set(cmd
  806. ${Subversion_SVN_EXECUTABLE}
  807. co
  808. ${svn_repository}
  809. ${svn_revision}
  810. ${svn_interactive_args}
  811. ${svn_trust_cert_args}
  812. ${svn_user_pw_args}
  813. ${src_name}
  814. )
  815. if(arg_SCRIPT_FILE)
  816. _ep_add_script_commands(
  817. step_script_contents
  818. "${work_dir}"
  819. "${cmd}" # Must be a single quoted argument
  820. )
  821. endif()
  822. elseif(git_repository)
  823. set(method git)
  824. # FetchContent gives us these directly, so don't try to recompute them
  825. if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING)
  826. unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
  827. find_package(Git QUIET)
  828. if(NOT GIT_EXECUTABLE)
  829. message(FATAL_ERROR "error: could not find git for clone of ${name}")
  830. endif()
  831. endif()
  832. _ep_get_git_submodules_recurse(git_submodules_recurse)
  833. set(git_tag "${_EP_GIT_TAG}")
  834. if(NOT git_tag)
  835. set(git_tag "master")
  836. endif()
  837. set(git_init_submodules TRUE)
  838. if(DEFINED _EP_GIT_SUBMODULES)
  839. set(git_submodules "${_EP_GIT_SUBMODULES}")
  840. if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW")
  841. set(git_init_submodules FALSE)
  842. endif()
  843. endif()
  844. set(git_remote_name "${_EP_GIT_REMOTE_NAME}")
  845. if(NOT git_remote_name)
  846. set(git_remote_name "origin")
  847. endif()
  848. _ep_get_tls_version(${name} tls_version)
  849. _ep_get_tls_verify(${name} tls_verify)
  850. set(git_shallow "${_EP_GIT_SHALLOW}")
  851. set(git_progress "${_EP_GIT_PROGRESS}")
  852. set(git_config "${_EP_GIT_CONFIG}")
  853. # If git supports it, make checkouts quiet when checking out a git hash.
  854. # This avoids the very noisy detached head message.
  855. if(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.7)
  856. list(PREPEND git_config advice.detachedHead=false)
  857. endif()
  858. # The command doesn't expose any details, so we need to record additional
  859. # information in the RepositoryInfo.txt file. For the download step, only
  860. # the things specifically affecting the clone operation should be recorded.
  861. # If the repo changes, the clone script should be run again.
  862. # But if only the tag changes, avoid running the clone script again.
  863. # Let the 'always' running update step checkout the new tag.
  864. #
  865. set(extra_repo_info
  866. "repository=${git_repository}
  867. remote=${git_remote_name}
  868. init_submodules=${git_init_submodules}
  869. recurse_submodules=${git_submodules_recurse}
  870. submodules=${git_submodules}
  871. CMP0097=${_EP_CMP0097}
  872. ")
  873. get_filename_component(src_name "${source_dir}" NAME)
  874. get_filename_component(work_dir "${source_dir}" PATH)
  875. # Since git clone doesn't succeed if the non-empty source_dir exists,
  876. # create a cmake script to invoke as download command.
  877. # The script will delete the source directory and then call git clone.
  878. #
  879. set(clone_script ${tmp_dir}/${name}-gitclone.cmake)
  880. _ep_write_gitclone_script(
  881. ${clone_script}
  882. ${source_dir}
  883. ${GIT_EXECUTABLE}
  884. ${git_repository}
  885. ${git_tag}
  886. ${git_remote_name}
  887. ${git_init_submodules}
  888. "${git_submodules_recurse}"
  889. "${git_submodules}"
  890. "${git_shallow}"
  891. "${git_progress}"
  892. "${git_config}"
  893. ${src_name}
  894. ${work_dir}
  895. ${stamp_dir}/${name}-gitinfo.txt
  896. ${stamp_dir}/${name}-gitclone-lastrun.txt
  897. "${tls_version}"
  898. "${tls_verify}"
  899. )
  900. set(comment "Performing download step (git clone) for '${name}'")
  901. set(cmd ${CMAKE_COMMAND}
  902. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  903. -P ${clone_script}
  904. )
  905. if(arg_SCRIPT_FILE)
  906. set(step_script_contents "include(\"${clone_script}\")")
  907. list(APPEND depends ${clone_script})
  908. endif()
  909. elseif(hg_repository)
  910. set(method hg)
  911. find_package(Hg QUIET)
  912. if(NOT HG_EXECUTABLE)
  913. message(FATAL_ERROR "error: could not find hg for clone of ${name}")
  914. endif()
  915. set(hg_tag "${_EP_HG_TAG}")
  916. if(NOT hg_tag)
  917. set(hg_tag "tip")
  918. endif()
  919. # The command doesn't expose any details, so we need to record additional
  920. # information in the RepositoryInfo.txt file. For the download step, only
  921. # the things specifically affecting the clone operation should be recorded.
  922. # If the repo changes, the clone script should be run again.
  923. # But if only the tag changes, avoid running the clone script again.
  924. # Let the 'always' running update step checkout the new tag.
  925. #
  926. set(extra_repo_info "repository=${hg_repository}")
  927. get_filename_component(src_name "${source_dir}" NAME)
  928. get_filename_component(work_dir "${source_dir}" PATH)
  929. # Since hg clone doesn't succeed if the non-empty source_dir exists,
  930. # create a cmake script to invoke as download command.
  931. # The script will delete the source directory and then call hg clone.
  932. #
  933. set(clone_script ${tmp_dir}/${name}-hgclone.cmake)
  934. _ep_write_hgclone_script(
  935. ${clone_script}
  936. ${source_dir}
  937. ${HG_EXECUTABLE}
  938. ${hg_repository}
  939. ${hg_tag}
  940. ${src_name}
  941. ${work_dir}
  942. ${stamp_dir}/${name}-hginfo.txt
  943. ${stamp_dir}/${name}-hgclone-lastrun.txt
  944. )
  945. set(comment "Performing download step (hg clone) for '${name}'")
  946. set(cmd ${CMAKE_COMMAND}
  947. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  948. -P ${clone_script}
  949. )
  950. if(arg_SCRIPT_FILE)
  951. set(step_script_contents "include(\"${clone_script}\")")
  952. list(APPEND depends ${clone_script})
  953. endif()
  954. elseif(url)
  955. set(method url)
  956. get_filename_component(work_dir "${source_dir}" PATH)
  957. set(hash "${_EP_URL_HASH}")
  958. _ep_get_hash_regex(_ep_hash_regex)
  959. if(hash AND NOT "${hash}" MATCHES "${_ep_hash_regex}")
  960. _ep_get_hash_algos(_ep_hash_algos)
  961. list(JOIN _ep_hash_algos "|" _ep_hash_algos)
  962. message(FATAL_ERROR
  963. "URL_HASH is set to\n"
  964. " ${hash}\n"
  965. "but must be ALGO=value where ALGO is\n"
  966. " ${_ep_hash_algos}\n"
  967. "and value is a hex string."
  968. )
  969. endif()
  970. set(md5 "${_EP_URL_MD5}")
  971. if(md5 AND NOT "MD5=${md5}" MATCHES "${_ep_hash_regex}")
  972. message(FATAL_ERROR
  973. "URL_MD5 is set to\n"
  974. " ${md5}\n"
  975. "but must be a hex string."
  976. )
  977. endif()
  978. if(md5 AND NOT hash)
  979. set(hash "MD5=${md5}")
  980. endif()
  981. set(extra_repo_info
  982. "url(s)=${url}
  983. hash=${hash}
  984. ")
  985. list(LENGTH url url_list_length)
  986. if(NOT "${url_list_length}" STREQUAL "1")
  987. foreach(entry IN LISTS url)
  988. if(NOT "${entry}" MATCHES "^[a-z]+://")
  989. message(FATAL_ERROR
  990. "At least one entry of URL is a path (invalid in a list)"
  991. )
  992. endif()
  993. endforeach()
  994. if("x${fname}" STREQUAL "x")
  995. list(GET url 0 fname)
  996. endif()
  997. endif()
  998. if(IS_DIRECTORY "${url}")
  999. get_filename_component(abs_dir "${url}" ABSOLUTE)
  1000. set(comment "Performing download step (DIR copy) for '${name}'")
  1001. set(cmd
  1002. ${CMAKE_COMMAND} -E rm -rf ${source_dir}
  1003. COMMAND ${CMAKE_COMMAND} -E copy_directory ${abs_dir} ${source_dir}
  1004. )
  1005. if(arg_SCRIPT_FILE)
  1006. # While it may be tempting to implement the two operations directly
  1007. # with file(), the behavior is different. file(COPY) preserves input
  1008. # file timestamps, which we don't want. Therefore, still use the same
  1009. # external commands so that we get the same behavior.
  1010. _ep_add_script_commands(
  1011. step_script_contents
  1012. "${work_dir}"
  1013. "${cmd}" # Must be a single quoted argument
  1014. )
  1015. endif()
  1016. else()
  1017. set(no_extract "${_EP_DOWNLOAD_NO_EXTRACT}")
  1018. string(APPEND extra_repo_info "no_extract=${no_extract}\n")
  1019. set(verify_script "${stamp_dir}/verify-${name}.cmake")
  1020. if("${url}" MATCHES "^[a-z]+://")
  1021. # TODO: Should download and extraction be different steps?
  1022. if("x${fname}" STREQUAL "x")
  1023. set(fname "${url}")
  1024. endif()
  1025. set(ext_regex [[7z|tar|tar\.bz2|tar\.gz|tar\.xz|tbz2|tgz|txz|zip]])
  1026. if("${fname}" MATCHES "([^/\\?#]+(\\.|=)(${ext_regex}))([/?#].*)?$")
  1027. set(fname "${CMAKE_MATCH_1}")
  1028. elseif(no_extract)
  1029. get_filename_component(fname "${fname}" NAME)
  1030. else()
  1031. # Fall back to a default file name. The actual file name does not
  1032. # matter because it is used only internally and our extraction tool
  1033. # inspects the file content directly. If it turns out the wrong URL
  1034. # was given that will be revealed during the build which is an easier
  1035. # place for users to diagnose than an error here anyway.
  1036. set(fname "archive.tar")
  1037. endif()
  1038. string(REPLACE ";" "-" fname "${fname}")
  1039. set(file ${download_dir}/${fname})
  1040. set(timeout "${_EP_TIMEOUT}")
  1041. set(inactivity_timeout "${_EP_INACTIVITY_TIMEOUT}")
  1042. set(no_progress "${_EP_DOWNLOAD_NO_PROGRESS}")
  1043. _ep_get_tls_version(${name} tls_version)
  1044. _ep_get_tls_verify(${name} tls_verify)
  1045. _ep_get_tls_cainfo(${name} tls_cainfo)
  1046. _ep_get_netrc(${name} netrc)
  1047. _ep_get_netrc_file(${name} netrc_file)
  1048. set(http_username "${_EP_HTTP_USERNAME}")
  1049. set(http_password "${_EP_HTTP_PASSWORD}")
  1050. set(http_headers "${_EP_HTTP_HEADER}")
  1051. set(download_script "${stamp_dir}/download-${name}.cmake")
  1052. _ep_write_downloadfile_script(
  1053. "${download_script}"
  1054. "${url}"
  1055. "${file}"
  1056. "${timeout}"
  1057. "${inactivity_timeout}"
  1058. "${no_progress}"
  1059. "${hash}"
  1060. "${tls_version}"
  1061. "${tls_verify}"
  1062. "${tls_cainfo}"
  1063. "${http_username}:${http_password}"
  1064. "${http_headers}"
  1065. "${netrc}"
  1066. "${netrc_file}"
  1067. )
  1068. set(cmd
  1069. ${CMAKE_COMMAND}
  1070. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  1071. -P "${download_script}"
  1072. COMMAND
  1073. )
  1074. if(arg_SCRIPT_FILE)
  1075. set(step_script_contents "include(\"${download_script}\")\n")
  1076. endif()
  1077. if (no_extract)
  1078. set(steps "download and verify")
  1079. else ()
  1080. set(steps "download, verify and extract")
  1081. endif ()
  1082. set(comment "Performing download step (${steps}) for '${name}'")
  1083. # already verified by 'download_script'
  1084. file(WRITE "${verify_script}" "")
  1085. # Rather than adding everything to the RepositoryInfo.txt file, it is
  1086. # more robust to just depend on the download script. That way, we will
  1087. # re-download if any aspect of the download changes.
  1088. list(APPEND depends "${download_script}")
  1089. else()
  1090. set(file "${url}")
  1091. if (no_extract)
  1092. set(steps "verify")
  1093. else ()
  1094. set(steps "verify and extract")
  1095. endif ()
  1096. set(comment "Performing download step (${steps}) for '${name}'")
  1097. _ep_write_verifyfile_script(
  1098. "${verify_script}"
  1099. "${file}"
  1100. "${hash}"
  1101. )
  1102. endif()
  1103. list(APPEND cmd ${CMAKE_COMMAND}
  1104. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  1105. -P ${verify_script}
  1106. )
  1107. if(arg_SCRIPT_FILE)
  1108. string(APPEND step_script_contents "include(\"${verify_script}\")\n")
  1109. list(APPEND depends ${verify_script})
  1110. endif()
  1111. set(extract_timestamp "${_EP_DOWNLOAD_EXTRACT_TIMESTAMP}")
  1112. if(no_extract)
  1113. if(DEFINED _EP_DOWNLOAD_EXTRACT_TIMESTAMP)
  1114. message(FATAL_ERROR
  1115. "Cannot specify DOWNLOAD_EXTRACT_TIMESTAMP when using "
  1116. "DOWNLOAD_NO_EXTRACT TRUE"
  1117. )
  1118. endif()
  1119. if(arg_SCRIPT_FILE)
  1120. # There's no target to record the location of the downloaded file.
  1121. # Instead, we copy it to the source directory within the script,
  1122. # which is what FetchContent always does in this situation.
  1123. cmake_path(SET safe_file NORMALIZE "${file}")
  1124. cmake_path(GET safe_file FILENAME filename)
  1125. string(APPEND step_script_contents
  1126. "file(COPY_FILE\n"
  1127. " \"${file}\"\n"
  1128. " \"${source_dir}/${filename}\"\n"
  1129. " ONLY_IF_DIFFERENT\n"
  1130. " INPUT_MAY_BE_RECENT\n"
  1131. ")"
  1132. )
  1133. list(APPEND depends ${source_dir}/${filename})
  1134. else()
  1135. set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file})
  1136. endif()
  1137. else()
  1138. if(NOT DEFINED _EP_DOWNLOAD_EXTRACT_TIMESTAMP)
  1139. # Default depends on policy CMP0135
  1140. if(_EP_CMP0135 STREQUAL "")
  1141. message(AUTHOR_WARNING
  1142. "The DOWNLOAD_EXTRACT_TIMESTAMP option was not given and policy "
  1143. "CMP0135 is not set. The policy's OLD behavior will be used. "
  1144. "When using a URL download, the timestamps of extracted files "
  1145. "should preferably be that of the time of extraction, otherwise "
  1146. "code that depends on the extracted contents might not be "
  1147. "rebuilt if the URL changes. The OLD behavior preserves the "
  1148. "timestamps from the archive instead, but this is usually not "
  1149. "what you want. Update your project to the NEW behavior or "
  1150. "specify the DOWNLOAD_EXTRACT_TIMESTAMP option with a value of "
  1151. "true to avoid this robustness issue."
  1152. )
  1153. set(extract_timestamp TRUE)
  1154. elseif(_EP_CMP0135 STREQUAL "NEW")
  1155. set(extract_timestamp FALSE)
  1156. else()
  1157. set(extract_timestamp TRUE)
  1158. endif()
  1159. endif()
  1160. if(extract_timestamp)
  1161. set(options "")
  1162. else()
  1163. set(options "--touch")
  1164. endif()
  1165. set(extract_script "${stamp_dir}/extract-${name}.cmake")
  1166. _ep_write_extractfile_script(
  1167. "${extract_script}"
  1168. "${name}"
  1169. "${file}"
  1170. "${source_dir}"
  1171. "${options}"
  1172. )
  1173. list(APPEND cmd
  1174. COMMAND ${CMAKE_COMMAND}
  1175. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  1176. -P ${extract_script}
  1177. )
  1178. if(arg_SCRIPT_FILE)
  1179. string(APPEND step_script_contents "include(\"${extract_script}\")\n")
  1180. list(APPEND depends ${extract_script})
  1181. endif()
  1182. endif ()
  1183. endif()
  1184. else()
  1185. set(method source_dir)
  1186. _ep_is_dir_empty("${source_dir}" empty)
  1187. if(${empty})
  1188. message(FATAL_ERROR
  1189. "No download info given for '${name}' and its source directory:\n"
  1190. " ${source_dir}\n"
  1191. "is not an existing non-empty directory. Please specify one of:\n"
  1192. " * SOURCE_DIR with an existing non-empty directory\n"
  1193. " * DOWNLOAD_COMMAND\n"
  1194. " * URL\n"
  1195. " * GIT_REPOSITORY\n"
  1196. " * SVN_REPOSITORY\n"
  1197. " * HG_REPOSITORY\n"
  1198. " * CVS_REPOSITORY and CVS_MODULE"
  1199. )
  1200. endif()
  1201. if(arg_SCRIPT_FILE)
  1202. set(step_script_contents "message(VERBOSE [[Using SOURCE_DIR as is]])")
  1203. endif()
  1204. endif()
  1205. # We use configure_file() to write the repo_info_file so that the file's
  1206. # timestamp is not updated if we don't change the contents
  1207. set(repo_info_file ${stamp_dir}/${name}-${method}info.txt)
  1208. list(APPEND depends ${repo_info_file})
  1209. configure_file(
  1210. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/RepositoryInfo.txt.in"
  1211. "${repo_info_file}"
  1212. @ONLY
  1213. )
  1214. if(arg_SCRIPT_FILE)
  1215. set(step_name download)
  1216. configure_file(
  1217. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stepscript.cmake.in"
  1218. "${arg_SCRIPT_FILE}"
  1219. @ONLY
  1220. )
  1221. set(${arg_DEPENDS_VARIABLE} "${depends}" PARENT_SCOPE)
  1222. return()
  1223. endif()
  1224. # Nothing below this point is applicable when we've been asked to put the
  1225. # download step in a script file (which is the FetchContent case).
  1226. if(_EP_LOG_DOWNLOAD)
  1227. set(log LOG 1)
  1228. else()
  1229. set(log "")
  1230. endif()
  1231. if(_EP_USES_TERMINAL_DOWNLOAD)
  1232. set(uses_terminal USES_TERMINAL 1)
  1233. else()
  1234. set(uses_terminal "")
  1235. endif()
  1236. set(__cmdQuoted)
  1237. foreach(__item IN LISTS cmd)
  1238. string(APPEND __cmdQuoted " [==[${__item}]==]")
  1239. endforeach()
  1240. cmake_language(EVAL CODE "
  1241. ExternalProject_Add_Step(\${name} download
  1242. INDEPENDENT TRUE
  1243. COMMENT \${comment}
  1244. COMMAND ${__cmdQuoted}
  1245. WORKING_DIRECTORY \${work_dir}
  1246. DEPENDS \${depends}
  1247. DEPENDEES mkdir
  1248. ${log}
  1249. ${uses_terminal}
  1250. )"
  1251. )
  1252. endfunction()
  1253. function(_ep_get_update_disconnected var name)
  1254. # Note that the arguments are assumed to have already been parsed and have
  1255. # been translated into variables with the prefix _EP_... by a call to
  1256. # ep_parse_arguments() or ep_parse_arguments_to_vars().
  1257. if(DEFINED _EP_UPDATE_DISCONNECTED)
  1258. set(update_disconnected "${_EP_UPDATE_DISCONNECTED}")
  1259. else()
  1260. get_property(update_disconnected
  1261. DIRECTORY
  1262. PROPERTY EP_UPDATE_DISCONNECTED
  1263. )
  1264. endif()
  1265. set(${var} "${update_disconnected}" PARENT_SCOPE)
  1266. endfunction()
  1267. function(_ep_add_update_command name)
  1268. set(noValueOptions )
  1269. set(singleValueOptions
  1270. SCRIPT_FILE # These should only be used by FetchContent
  1271. DEPEND_VARIABLE #
  1272. )
  1273. set(multiValueOptions )
  1274. cmake_parse_arguments(PARSE_ARGV 1 arg
  1275. "${noValueOptions}" "${singleValueOptions}" "${multiValueOptions}"
  1276. )
  1277. # The various _EP_... variables mentioned here and throughout this function
  1278. # are expected to already have been set by the caller via a call to
  1279. # _ep_parse_arguments() or ep_parse_arguments_to_vars(). Other variables
  1280. # with different names are assigned to for historical reasons only to keep
  1281. # the code more readable and minimize change.
  1282. set(source_dir "${_EP_SOURCE_DIR}")
  1283. set(stamp_dir "${_EP_STAMP_DIR}")
  1284. set(tmp_dir "${_EP_TMP_DIR}")
  1285. set(cmd "${_EP_UPDATE_COMMAND}")
  1286. set(cvs_repository "${_EP_CVS_REPOSITORY}")
  1287. set(svn_repository "${_EP_SVN_REPOSITORY}")
  1288. set(git_repository "${_EP_GIT_REPOSITORY}")
  1289. set(hg_repository "${_EP_HG_REPOSITORY}")
  1290. _ep_get_update_disconnected(update_disconnected ${name})
  1291. set(work_dir)
  1292. set(comment)
  1293. set(always)
  1294. set(file_deps)
  1295. if(DEFINED _EP_UPDATE_COMMAND)
  1296. set(work_dir ${source_dir})
  1297. if(NOT "x${cmd}" STREQUAL "x")
  1298. set(always 1)
  1299. _ep_add_script_commands(
  1300. step_script_contents
  1301. "${work_dir}"
  1302. "${cmd}" # Must be a single quoted argument
  1303. )
  1304. endif()
  1305. elseif(cvs_repository)
  1306. if(NOT CVS_EXECUTABLE)
  1307. message(FATAL_ERROR "error: could not find cvs for update of ${name}")
  1308. endif()
  1309. set(work_dir ${source_dir})
  1310. set(comment "Performing update step (CVS update) for '${name}'")
  1311. set(cvs_tag "${_EP_CVS_TAG}")
  1312. set(cmd ${CVS_EXECUTABLE} -d ${cvs_repository} -q up -dP ${cvs_tag})
  1313. set(always 1)
  1314. if(arg_SCRIPT_FILE)
  1315. _ep_add_script_commands(
  1316. step_script_contents
  1317. "${work_dir}"
  1318. "${cmd}" # Must be a single quoted argument
  1319. )
  1320. endif()
  1321. elseif(svn_repository)
  1322. if(NOT Subversion_SVN_EXECUTABLE)
  1323. message(FATAL_ERROR "error: could not find svn for update of ${name}")
  1324. endif()
  1325. set(work_dir ${source_dir})
  1326. set(comment "Performing update step (SVN update) for '${name}'")
  1327. set(svn_revision "${_EP_SVN_REVISION}")
  1328. set(svn_username "${_EP_SVN_USERNAME}")
  1329. set(svn_password "${_EP_SVN_PASSWORD}")
  1330. set(svn_trust_cert "${_EP_SVN_TRUST_CERT}")
  1331. set(uses_terminal "${_EP_USES_TERMINAL_UPDATE}")
  1332. # The --trust-server-cert option requires --non-interactive
  1333. if(uses_terminal AND NOT svn_trust_cert)
  1334. set(svn_interactive_args "")
  1335. else()
  1336. set(svn_interactive_args "--non-interactive")
  1337. endif()
  1338. set(svn_user_pw_args "")
  1339. if(DEFINED _EP_SVN_USERNAME)
  1340. set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}")
  1341. endif()
  1342. if(DEFINED _EP_SVN_PASSWORD)
  1343. set(svn_user_pw_args ${svn_user_pw_args} "--password=${svn_password}")
  1344. endif()
  1345. if(svn_trust_cert)
  1346. set(svn_trust_cert_args --trust-server-cert)
  1347. endif()
  1348. set(cmd
  1349. ${Subversion_SVN_EXECUTABLE}
  1350. up
  1351. ${svn_revision}
  1352. ${svn_interactive_args}
  1353. ${svn_trust_cert_args}
  1354. ${svn_user_pw_args}
  1355. )
  1356. set(always 1)
  1357. if(arg_SCRIPT_FILE)
  1358. _ep_add_script_commands(
  1359. step_script_contents
  1360. "${work_dir}"
  1361. "${cmd}" # Must be a single quoted argument
  1362. )
  1363. endif()
  1364. elseif(git_repository)
  1365. # FetchContent gives us these directly, so don't try to recompute them
  1366. if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING)
  1367. unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
  1368. find_package(Git QUIET)
  1369. if(NOT GIT_EXECUTABLE)
  1370. message(FATAL_ERROR "error: could not find git for fetch of ${name}")
  1371. endif()
  1372. endif()
  1373. set(work_dir ${source_dir})
  1374. set(comment "Performing update step for '${name}'")
  1375. set(comment_disconnected "Performing disconnected update step for '${name}'")
  1376. set(git_tag "${_EP_GIT_TAG}")
  1377. if(NOT git_tag)
  1378. set(git_tag "master")
  1379. endif()
  1380. set(git_remote_name "${_EP_GIT_REMOTE_NAME}")
  1381. if(NOT git_remote_name)
  1382. set(git_remote_name "origin")
  1383. endif()
  1384. set(git_init_submodules TRUE)
  1385. if(DEFINED _EP_GIT_SUBMODULES)
  1386. set(git_submodules "${_EP_GIT_SUBMODULES}")
  1387. if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW")
  1388. set(git_init_submodules FALSE)
  1389. endif()
  1390. endif()
  1391. set(git_update_strategy "${_EP_GIT_REMOTE_UPDATE_STRATEGY}")
  1392. if(NOT git_update_strategy)
  1393. set(git_update_strategy "${CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY}")
  1394. endif()
  1395. if(NOT git_update_strategy)
  1396. set(git_update_strategy REBASE)
  1397. endif()
  1398. set(strategies CHECKOUT REBASE REBASE_CHECKOUT)
  1399. if(NOT git_update_strategy IN_LIST strategies)
  1400. message(FATAL_ERROR
  1401. "'${git_update_strategy}' is not one of the supported strategies: "
  1402. "${strategies}"
  1403. )
  1404. endif()
  1405. _ep_get_git_submodules_recurse(git_submodules_recurse)
  1406. _ep_get_tls_version(${name} tls_version)
  1407. _ep_get_tls_verify(${name} tls_verify)
  1408. set(update_script "${tmp_dir}/${name}-gitupdate.cmake")
  1409. list(APPEND file_deps ${update_script})
  1410. _ep_write_gitupdate_script(
  1411. "${update_script}"
  1412. "${GIT_EXECUTABLE}"
  1413. "${git_tag}"
  1414. "${git_remote_name}"
  1415. "${git_init_submodules}"
  1416. "${git_submodules_recurse}"
  1417. "${git_submodules}"
  1418. "${git_repository}"
  1419. "${work_dir}"
  1420. "${git_update_strategy}"
  1421. "${tls_version}"
  1422. "${tls_verify}"
  1423. )
  1424. set(cmd ${CMAKE_COMMAND}
  1425. -Dcan_fetch=YES
  1426. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  1427. -P ${update_script}
  1428. )
  1429. set(cmd_disconnected ${CMAKE_COMMAND}
  1430. -Dcan_fetch=NO
  1431. -DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE
  1432. -P ${update_script}
  1433. )
  1434. set(always 1)
  1435. if(arg_SCRIPT_FILE)
  1436. if(update_disconnected)
  1437. set(can_fetch_default NO)
  1438. else()
  1439. set(can_fetch_default YES)
  1440. endif()
  1441. set(step_script_contents "include(\"${update_script}\")")
  1442. endif()
  1443. elseif(hg_repository)
  1444. if(NOT HG_EXECUTABLE)
  1445. message(FATAL_ERROR "error: could not find hg for pull of ${name}")
  1446. endif()
  1447. set(work_dir ${source_dir})
  1448. set(comment "Performing update step (hg pull) for '${name}'")
  1449. set(comment_disconnected "Performing disconnected update step for '${name}'")
  1450. set(hg_tag "${_EP_HG_TAG}")
  1451. if(NOT hg_tag)
  1452. set(hg_tag "tip")
  1453. endif()
  1454. if("${HG_VERSION_STRING}" STREQUAL "2.1")
  1455. set(notesAnchor
  1456. "#A2.1.1:_revert_pull_return_code_change.2C_compile_issue_on_OS_X"
  1457. )
  1458. message(WARNING
  1459. "Mercurial 2.1 does not distinguish an empty pull from a failed pull:
  1460. http://mercurial.selenic.com/wiki/UpgradeNotes${notesAnchor}
  1461. http://thread.gmane.org/gmane.comp.version-control.mercurial.devel/47656
  1462. Update to Mercurial >= 2.1.1.
  1463. ")
  1464. endif()
  1465. set(cmd
  1466. ${HG_EXECUTABLE} pull
  1467. COMMAND ${HG_EXECUTABLE} update ${hg_tag}
  1468. )
  1469. set(cmd_disconnected ${HG_EXECUTABLE} update ${hg_tag})
  1470. set(always 1)
  1471. if(arg_SCRIPT_FILE)
  1472. # These commands are simple, and we know whether updates need to be
  1473. # disconnected or not for this case, so write them directly instead of
  1474. # forming them from "cmd" and "cmd_disconnected".
  1475. if(NOT update_disconnected)
  1476. string(APPEND step_script_contents
  1477. "execute_process(\n"
  1478. " WORKING_DIRECTORY \"${work_dir}\"\n"
  1479. " COMMAND_ERROR_IS_FATAL LAST\n"
  1480. " COMMAND \"${HG_EXECUTABLE}\" pull\n"
  1481. ")"
  1482. )
  1483. endif()
  1484. string(APPEND step_script_contents
  1485. "execute_process(\n"
  1486. " WORKING_DIRECTORY \"${work_dir}\"\n"
  1487. " COMMAND_ERROR_IS_FATAL LAST\n"
  1488. " COMMAND \"${HG_EXECUTABLE}\" update \"${hg_tag}\"\n"
  1489. ")"
  1490. )
  1491. endif()
  1492. endif()
  1493. # We use configure_file() to write the update_info_file so that the file's
  1494. # timestamp is not updated if we don't change the contents
  1495. if(NOT DEFINED cmd_disconnected)
  1496. set(cmd_disconnected "${cmd}")
  1497. endif()
  1498. set(update_info_file ${stamp_dir}/${name}-update-info.txt)
  1499. list(APPEND file_deps ${update_info_file})
  1500. configure_file(
  1501. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/UpdateInfo.txt.in"
  1502. "${update_info_file}"
  1503. @ONLY
  1504. )
  1505. if(arg_SCRIPT_FILE)
  1506. set(step_name update)
  1507. configure_file(
  1508. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stepscript.cmake.in"
  1509. "${arg_SCRIPT_FILE}"
  1510. @ONLY
  1511. )
  1512. set(${arg_DEPENDS_VARIABLE} "${file_deps}" PARENT_SCOPE)
  1513. return()
  1514. endif()
  1515. # Nothing below this point is applicable when we've been asked to put the
  1516. # update step in a script file (which is the FetchContent case).
  1517. if(_EP_LOG_UPDATE)
  1518. set(log LOG 1)
  1519. else()
  1520. set(log "")
  1521. endif()
  1522. if(_EP_USES_TERMINAL_UPDATE)
  1523. set(uses_terminal USES_TERMINAL 1)
  1524. else()
  1525. set(uses_terminal "")
  1526. endif()
  1527. set(__cmdQuoted)
  1528. foreach(__item IN LISTS cmd)
  1529. string(APPEND __cmdQuoted " [==[${__item}]==]")
  1530. endforeach()
  1531. cmake_language(EVAL CODE "
  1532. ExternalProject_Add_Step(${name} update
  1533. INDEPENDENT TRUE
  1534. COMMENT \${comment}
  1535. COMMAND ${__cmdQuoted}
  1536. ALWAYS \${always}
  1537. EXCLUDE_FROM_MAIN \${update_disconnected}
  1538. WORKING_DIRECTORY \${work_dir}
  1539. DEPENDEES download
  1540. DEPENDS \${file_deps}
  1541. ${log}
  1542. ${uses_terminal}
  1543. )"
  1544. )
  1545. if(update_disconnected)
  1546. if(NOT DEFINED comment_disconnected)
  1547. set(comment_disconnected "${comment}")
  1548. endif()
  1549. set(__cmdQuoted)
  1550. foreach(__item IN LISTS cmd_disconnected)
  1551. string(APPEND __cmdQuoted " [==[${__item}]==]")
  1552. endforeach()
  1553. cmake_language(EVAL CODE "
  1554. ExternalProject_Add_Step(${name} update_disconnected
  1555. INDEPENDENT TRUE
  1556. COMMENT \${comment_disconnected}
  1557. COMMAND ${__cmdQuoted}
  1558. WORKING_DIRECTORY \${work_dir}
  1559. DEPENDEES download
  1560. DEPENDS \${file_deps}
  1561. ${log}
  1562. ${uses_terminal}
  1563. )"
  1564. )
  1565. endif()
  1566. endfunction()
  1567. function(_ep_add_patch_command name)
  1568. set(noValueOptions )
  1569. set(singleValueOptions
  1570. SCRIPT_FILE # These should only be used by FetchContent
  1571. )
  1572. set(multiValueOptions )
  1573. cmake_parse_arguments(PARSE_ARGV 1 arg
  1574. "${noValueOptions}" "${singleValueOptions}" "${multiValueOptions}"
  1575. )
  1576. # The various _EP_... variables mentioned here and throughout this function
  1577. # are expected to already have been set by the caller via a call to
  1578. # _ep_parse_arguments() or ep_parse_arguments_to_vars(). Other variables
  1579. # with different names are assigned to for historical reasons only to keep
  1580. # the code more readable and minimize change.
  1581. set(source_dir "${_EP_SOURCE_DIR}")
  1582. set(stamp_dir "${_EP_STAMP_DIR}")
  1583. set(cmd "${_EP_PATCH_COMMAND}")
  1584. set(step_script_contents "")
  1585. set(work_dir)
  1586. if(DEFINED _EP_PATCH_COMMAND)
  1587. set(work_dir ${source_dir})
  1588. if(arg_SCRIPT_FILE)
  1589. _ep_add_script_commands(
  1590. step_script_contents
  1591. "${work_dir}"
  1592. "${cmd}" # Must be a single quoted argument
  1593. )
  1594. endif()
  1595. endif()
  1596. # We use configure_file() to write the patch_info_file so that the file's
  1597. # timestamp is not updated if we don't change the contents
  1598. set(patch_info_file ${stamp_dir}/${name}-patch-info.txt)
  1599. configure_file(
  1600. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/PatchInfo.txt.in"
  1601. "${patch_info_file}"
  1602. @ONLY
  1603. )
  1604. if(arg_SCRIPT_FILE)
  1605. set(step_name patch)
  1606. configure_file(
  1607. "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stepscript.cmake.in"
  1608. "${arg_SCRIPT_FILE}"
  1609. @ONLY
  1610. )
  1611. return()
  1612. endif()
  1613. # Nothing below this point is applicable when we've been asked to put the
  1614. # patch step in a script file (which is the FetchContent case).
  1615. if(_EP_LOG_PATCH)
  1616. set(log LOG 1)
  1617. else()
  1618. set(log "")
  1619. endif()
  1620. if(_EP_USES_TERMINAL_PATCH)
  1621. set(uses_terminal USES_TERMINAL 1)
  1622. else()
  1623. set(uses_terminal "")
  1624. endif()
  1625. _ep_get_update_disconnected(update_disconnected ${name})
  1626. set(__cmdQuoted)
  1627. foreach(__item IN LISTS cmd)
  1628. string(APPEND __cmdQuoted " [==[${__item}]==]")
  1629. endforeach()
  1630. cmake_language(EVAL CODE "
  1631. ExternalProject_Add_Step(${name} patch
  1632. INDEPENDENT TRUE
  1633. COMMAND ${__cmdQuoted}
  1634. WORKING_DIRECTORY \${work_dir}
  1635. EXCLUDE_FROM_MAIN \${update_disconnected}
  1636. DEPENDEES update
  1637. DEPENDS \${patch_info_file}
  1638. ${log}
  1639. ${uses_terminal}
  1640. )"
  1641. )
  1642. if(update_disconnected)
  1643. cmake_language(EVAL CODE "
  1644. ExternalProject_Add_Step(${name} patch_disconnected
  1645. INDEPENDENT TRUE
  1646. COMMAND ${__cmdQuoted}
  1647. WORKING_DIRECTORY \${work_dir}
  1648. DEPENDEES update_disconnected
  1649. DEPENDS \${patch_info_file}
  1650. ${log}
  1651. ${uses_terminal}
  1652. )"
  1653. )
  1654. endif()
  1655. endfunction()
  1656. macro(_ep_get_add_keywords out_var)
  1657. set(${out_var}
  1658. #
  1659. # Directory options
  1660. #
  1661. PREFIX
  1662. TMP_DIR
  1663. STAMP_DIR
  1664. LOG_DIR
  1665. DOWNLOAD_DIR
  1666. SOURCE_DIR
  1667. BINARY_DIR
  1668. INSTALL_DIR
  1669. #
  1670. # Download step options
  1671. #
  1672. DOWNLOAD_COMMAND
  1673. #
  1674. URL
  1675. URL_HASH
  1676. URL_MD5
  1677. DOWNLOAD_NAME
  1678. DOWNLOAD_EXTRACT_TIMESTAMP
  1679. DOWNLOAD_NO_EXTRACT
  1680. DOWNLOAD_NO_PROGRESS
  1681. TIMEOUT
  1682. INACTIVITY_TIMEOUT
  1683. HTTP_USERNAME
  1684. HTTP_PASSWORD
  1685. HTTP_HEADER
  1686. TLS_VERSION # Also used for git clone operations
  1687. TLS_VERIFY # Also used for git clone operations
  1688. TLS_CAINFO
  1689. NETRC
  1690. NETRC_FILE
  1691. #
  1692. GIT_REPOSITORY
  1693. GIT_TAG
  1694. GIT_REMOTE_NAME
  1695. GIT_SUBMODULES
  1696. GIT_SUBMODULES_RECURSE
  1697. GIT_SHALLOW
  1698. GIT_PROGRESS
  1699. GIT_CONFIG
  1700. GIT_REMOTE_UPDATE_STRATEGY
  1701. #
  1702. SVN_REPOSITORY
  1703. SVN_REVISION
  1704. SVN_USERNAME
  1705. SVN_PASSWORD
  1706. SVN_TRUST_CERT
  1707. #
  1708. HG_REPOSITORY
  1709. HG_TAG
  1710. #
  1711. CVS_REPOSITORY
  1712. CVS_MODULE
  1713. CVS_TAG
  1714. #
  1715. # Update step options
  1716. #
  1717. UPDATE_COMMAND
  1718. UPDATE_DISCONNECTED
  1719. #
  1720. # Patch step options
  1721. #
  1722. PATCH_COMMAND
  1723. #
  1724. # Configure step options
  1725. #
  1726. CONFIGURE_COMMAND
  1727. CMAKE_COMMAND
  1728. CMAKE_GENERATOR
  1729. CMAKE_GENERATOR_PLATFORM
  1730. CMAKE_GENERATOR_TOOLSET
  1731. CMAKE_GENERATOR_INSTANCE
  1732. CMAKE_ARGS
  1733. CMAKE_CACHE_ARGS
  1734. CMAKE_CACHE_DEFAULT_ARGS
  1735. SOURCE_SUBDIR
  1736. CONFIGURE_HANDLED_BY_BUILD
  1737. #
  1738. # Build step options
  1739. #
  1740. BUILD_COMMAND
  1741. BUILD_IN_SOURCE
  1742. BUILD_ALWAYS
  1743. BUILD_BYPRODUCTS
  1744. BUILD_JOB_SERVER_AWARE
  1745. #
  1746. # Install step options
  1747. #
  1748. INSTALL_COMMAND
  1749. INSTALL_BYPRODUCTS
  1750. #
  1751. # Test step options
  1752. #
  1753. TEST_COMMAND
  1754. TEST_BEFORE_INSTALL
  1755. TEST_AFTER_INSTALL
  1756. TEST_EXCLUDE_FROM_MAIN
  1757. #
  1758. # Logging options
  1759. #
  1760. LOG_DOWNLOAD
  1761. LOG_UPDATE
  1762. LOG_PATCH
  1763. LOG_CONFIGURE
  1764. LOG_BUILD
  1765. LOG_INSTALL
  1766. LOG_TEST
  1767. LOG_MERGED_STDOUTERR
  1768. LOG_OUTPUT_ON_FAILURE
  1769. #
  1770. # Terminal access options
  1771. #
  1772. USES_TERMINAL_DOWNLOAD
  1773. USES_TERMINAL_UPDATE
  1774. USES_TERMINAL_PATCH
  1775. USES_TERMINAL_CONFIGURE
  1776. USES_TERMINAL_BUILD
  1777. USES_TERMINAL_INSTALL
  1778. USES_TERMINAL_TEST
  1779. #
  1780. # Target options
  1781. #
  1782. DEPENDS
  1783. EXCLUDE_FROM_ALL
  1784. STEP_TARGETS
  1785. INDEPENDENT_STEP_TARGETS
  1786. #
  1787. # Miscellaneous options
  1788. #
  1789. LIST_SEPARATOR
  1790. #
  1791. # Internal options (undocumented)
  1792. #
  1793. EXTERNALPROJECT_INTERNAL_ARGUMENT_SEPARATOR
  1794. )
  1795. endmacro()