[PATCH] ExternalProject: Add EXTRACT_COMMAND option

Pau Garcia i Quiles pgquiles at elpauer.org
Tue Nov 26 09:36:49 EST 2013


Add an EXTRACT_COMMAND option to ExternalProject_Add to specify the
extraction command explicitly.  This is useful when downloading a file
that CMake does not know how to extract, but we do.  Rather than having
to replace the entire DOWNLOAD_COMMAND with a custom version, this
allows us to re-use the builtin download features while plugging in our
own extraction command.

Extend the ExternalProject test to cover custom extraction of a
self-extracting zip file.
---
 Modules/ExternalProject.cmake               |  42 +++++++++++++++++-----------
 Tests/ExternalProject/CMakeLists.txt        |  15 ++++++++++
 Tests/ExternalProject/autoextractingzip.exe | Bin 0 -> 1074 bytes
 3 files changed, 41 insertions(+), 16 deletions(-)
 create mode 100644 Tests/ExternalProject/autoextractingzip.exe

diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 63f1180..4cd7a3c 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -38,6 +38,8 @@
 #    [TLS_VERIFY bool]           # Should certificate for https be checked
 #    [TLS_CAINFO file]           # Path to a certificate authority file
 #    [TIMEOUT seconds]           # Time allowed for file download operations
+#   #--Extract step --------------
+#    [EXTRACT_COMMAND cmd...]    # Custom command to extract downloaded file
 #   #--Update/Patch step----------
 #    [UPDATE_COMMAND cmd...]     # Source work-tree update command
 #    [PATCH_COMMAND cmd...]      # Command to patch downloaded source
@@ -612,22 +614,27 @@ ${script_content}
 endfunction()
 
 
-function(_ep_write_extractfile_script script_filename name filename directory)
+function(_ep_write_extractfile_script script_filename name filename directory excommand)
   set(args "")
 
-  if(filename MATCHES "(\\.|=)(bz2|tar\\.gz|tgz|zip)$")
-    set(args xfz)
-  endif()
+  if(NOT excommand STREQUAL "")
+    set(args "${excommand}")
+  else()
+    if(filename MATCHES "(\\.|=)(bz2|tar\\.gz|tgz|zip)$")
+      set(args "\${CMAKE_COMMAND} -E tar xfz")
+    endif()
 
-  if(filename MATCHES "(\\.|=)tar$")
-    set(args xf)
-  endif()
+    if(filename MATCHES "(\\.|=)tar$")
+      set(args "\${CMAKE_COMMAND} -E tar xf")
+    endif()
 
-  if(args STREQUAL "")
-    message(SEND_ERROR "error: do not know how to extract '${filename}' -- known types are .bz2, .tar, .tar.gz, .tgz and .zip")
-    return()
+    if(args STREQUAL "")
+      message(SEND_ERROR "error: do not know how to extract '${filename}' -- known types are .bz2, .tar, .tar.gz, .tgz and .zip")
+      return()
+    endif()
   endif()
 
+
   file(WRITE ${script_filename}
 "# Make file names absolute:
 #
@@ -653,8 +660,8 @@ file(MAKE_DIRECTORY \"\${ut_dir}\")
 
 # Extract it:
 #
-message(STATUS \"extracting... [tar ${args}]\")
-execute_process(COMMAND \${CMAKE_COMMAND} -E tar ${args} \${filename}
+message(STATUS \"extracting... [${args}]\")
+execute_process(COMMAND ${args} \${filename}
   WORKING_DIRECTORY \${ut_dir}
   RESULT_VARIABLE rv)
 
@@ -664,7 +671,7 @@ if(NOT rv EQUAL 0)
   message(FATAL_ERROR \"error: extract of '\${filename}' failed\")
 endif()
 
-# Analyze what came out of the tar file:
+# Analyze what came out of the file:
 #
 message(STATUS \"extracting... [analysis]\")
 file(GLOB contents \"\${ut_dir}/*\")
@@ -1216,6 +1223,9 @@ function(_ep_add_download_command name)
   get_property(hg_repository  TARGET ${name} PROPERTY _EP_HG_REPOSITORY )
   get_property(url TARGET ${name} PROPERTY _EP_URL)
   get_property(fname TARGET ${name} PROPERTY _EP_DOWNLOAD_NAME)
+  get_property(excmd_set TARGET ${name} PROPERTY _EP_EXTRACT_COMMAND SET)
+  get_property(excmd TARGET ${name} PROPERTY _EP_EXTRACT_COMMAND)
+
 
   # TODO: Perhaps file:// should be copied to download dir before extraction.
   string(REGEX REPLACE "^file://" "" url "${url}")
@@ -1411,11 +1421,11 @@ function(_ep_add_download_command name)
         if("x${fname}" STREQUAL "x")
           string(REGEX MATCH "[^/\\?]*$" fname "${url}")
         endif()
-        if(NOT "${fname}" MATCHES "(\\.|=)(bz2|tar|tgz|tar\\.gz|zip)$")
+        if(NOT excmd_set AND NOT "${fname}" MATCHES "(\\.|=)(bz2|tar|tgz|tar\\.gz|zip)$")
           string(REGEX MATCH "([^/\\?]+(\\.|=)(bz2|tar|tgz|tar\\.gz|zip))/.*$" match_result "${url}")
           set(fname "${CMAKE_MATCH_1}")
         endif()
-        if(NOT "${fname}" MATCHES "(\\.|=)(bz2|tar|tgz|tar\\.gz|zip)$")
+        if(NOT excmd_set AND NOT "${fname}" MATCHES "(\\.|=)(bz2|tar|tgz|tar\\.gz|zip)$")
           message(FATAL_ERROR "Could not extract tarball filename from url:\n  ${url}")
         endif()
         string(REPLACE ";" "-" fname "${fname}")
@@ -1435,7 +1445,7 @@ function(_ep_add_download_command name)
       _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}")
       list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake
         COMMAND)
-      _ep_write_extractfile_script("${stamp_dir}/extract-${name}.cmake" "${name}" "${file}" "${source_dir}")
+      _ep_write_extractfile_script("${stamp_dir}/extract-${name}.cmake" "${name}" "${file}" "${source_dir}" "${excmd}")
       list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake)
     endif()
   else()
diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt
index 602ff0f..65f008e 100644
--- a/Tests/ExternalProject/CMakeLists.txt
+++ b/Tests/ExternalProject/CMakeLists.txt
@@ -250,6 +250,21 @@ ExternalProject_Add(${proj}
 )
 set_property(TARGET ${proj} PROPERTY FOLDER "Local/ZIP")
 
+# Local autoextracting ZIP:
+#
+# (The extract test here is just to verify the EXTRACT_COMMAND does
+#  overrides the downloadable files white list... The configure and build
+#  commands are set to nothing to make the test quicker...)
+#
+set(proj TutorialStep1-LocalExtractCommand)
+ExternalProject_Add(${proj}
+  URL "${CMAKE_CURRENT_SOURCE_DIR}/autoextractingzip.exe"
+  EXTRACT_COMMAND ${CMAKE_COMMAND} -E tar xvf "${CMAKE_CURRENT_SOURCE_DIR}/autoextractingzip.exe"
+  CONFIGURE_COMMAND ""
+  BUILD_COMMAND ""
+  INSTALL_COMMAND ""
+)
+set_property(TARGET ${proj} PROPERTY FOLDER "Local/ExtractCommand")
 
 # CVS-based tests:
 #
diff --git a/Tests/ExternalProject/autoextractingzip.exe b/Tests/ExternalProject/autoextractingzip.exe
new file mode 100644
index 0000000000000000000000000000000000000000..49dac24edff7e6b281bd3ce85cfd1a9f3dbd6107
GIT binary patch
literal 1074
zcmWIWW at Zs#U|`^2SYEWuCj7HufgU3RgESKZ14uNuB(=a$-`O`YJJlz%xTILGq at tvB
zqQC!P1D>Pre~Mgta3Sv0eCF?gWiOVjT_No;XOT|fb%)tJ>WR)B at BN~B4_?@zT6g}u
z{pn4@`X{V&OT?}Gen^=tY<f}{q}x@*cm1aCDYKOMfmI&U4n|*E<SS|2oZ9 at M?a3C?
z1gGszr)C_E*W1VcaP!A4YaVF*_1AkAxKGAusp-}@b|--g3j#a>UW*-!zQOVQz)ik`
z*B(6nP$PCzF|8{1nx2_^aD2Jhgd-A5C&+&KAu!pX;o{HZwV{6MKPTy*YS)_oVfUh6
zdwv`{)!w(}<Q7TU-TB==cT`!ueYf^7lhaDZq@}$J%0IMJJaBT{)LH$5Ez5gBZ%*@}
z#DjA8znVQv?A~xSSNgTv!TXLm_m76!OnGBkax(M8ML~gg0c`qVx|<>%+223xc;LPK
z%sX#`zOe?NgzwF&uRHXC;p+<wUm<w-mXwy{7iA{q=p|QFv<CWSA94`b`+j}J5|$*+
z!0I*I6qd4cn<lIk*WRQyJ4Nwk at 9&G<Kkn~7)^SX1S9 at aGx4o79GwbAqGvcnQI<HMx
zm%$nw(CiYn)zoKqm*ab#P#!NY=9!I7H?mHP?0l at GnS09Mn%Yw%t$DlGPRifCw`<m-
z%OAzAc^u9BspNX>^NJ4~4-YL^6r*5~7V^}yW61)p?|T2^)>fzZGt5)8_?OtzK5unn
zt?=e3%P296%1qxEKc&2vnM`M at llu8``iDbo6?JDX9Ncx==JqX}_~-JME4Ee6-*fcy
ze}l`BHt&1?ZTYw|^PJqnJ9Em)w_McP&U3UUl<9DAX~9Lq?eFwrc6jS#W=hU;=snZa
zW?>^3JwbS<)62O=2V1W*<jd;T$zMBvaBH`@^)4Q+^`)~`u6=#5L*@iOYVgh%Uab`i
z4A!MUEC~<Z5NPl^=jWwmrt4+sW#(PJ9<FiHBh=&EdGFIc`nq1efhY7ePM$fh9p-Vy
zJ5a+<SM%f<Z~ZWj)A~Uinz|?TPx+jA806>ad-{xbEBBH1oouYtzkVP6ZB_M?UDF~#
zy!^o8^OyN|+fCTPEH2Iv;LXS+0?t0zGZoNb48Sx11=z9}x(VpX2BZ~YLIRM2n1Gy!
i(DkE-3qt>XU_ylG#}Y~b-mGjOrOZHh5=aL#gLnWD?Xc(o

literal 0
HcmV?d00001

-- 
1.8.4.rc3


--------------080801080103070902050407--


More information about the cmake-developers mailing list