1

I tried to download only part of repository as it is written here: https://stackoverflow.com/a/28039894/7042963, but I wanna do this in CMakeLists.txt by using ExternalProject_Add DOWNLOAD_COMMAND.

However, there are some problems. I cannot write content to file sparse-checkout. File exists, but it is empty. This is my CMakeLists.txt file:

include(ExternalProject)

message("CMAKE_CURRENT_BINARY_DIR is set to ${CMAKE_CURRENT_BINARY_DIR}")

ExternalProject_Add(glm
  DOWNLOAD_COMMAND git init
    COMMAND git remote add origin https://github.com/g-truc/glm
    COMMAND git config core.sparsecheckout true
    COMMAND touch .git/info/sparse-checkout
    COMMAND pwd
    COMMAND echo "glm/*" >> .git/info/sparse-checkout
    COMMAND git pull --depth=1 origin master
  PREFIX "${CMAKE_CURRENT_BINARY_DIR}"
  # Disable configure, build and install steps
  CONFIGURE_COMMAND ""
  BUILD_COMMAND ""
  INSTALL_COMMAND ""
  LOG_DOWNLOAD ON
)

# Specify include dir
set(GLM_INCLUDE_DIRS ${PREFIX}/src PARENT_SCOPE)

Log from this commands execution:

Initialized empty Git repository in /path/to/project/build/modules/glm/src/.git/
/path/to/project/build/modules/glm/src
glm/* >> .git/info/sparse-checkout

When I look at log, I think that echo simply print next part of this command to output and this is problem.

I tried also replace echo command with this :

COMMAND FILE(WRITE .git/info/sparse-checkout "glm/*")

And it is error log from this:

CMake Error at glm-stamp/glm-download--impl.cmake:59 (message):
  Command failed (No such file or directory):

   'FILE' '(' 'WRITE' '.git/info/sparse-checkout' 'glm/*' ')'

Do you know what is the reason of this problem?

Community
  • 1
  • 1
BartekPL
  • 2,290
  • 1
  • 17
  • 34

2 Answers2

2

>> is an element of shell syntax. I don't think it's specified whether CMake executes the commands via a shell or directly. And if it executes them via a shell, whether it recognizes >> as something that should be passed verbatim and not quoted.

To have this work independent of the above "whether"s, you'll need a command which writes directly to the file. You could e.g. write a short CMake script for that purpose and execute it via ${CMAKE_COMMAND} -P.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • I have warning: `Argument not separated from preceding token by whitespace.` And nothing is written to file. I checked that cmake parse it to: `set(command "sh;-c;echo "glm/*" >> .git/info/sparse-checkout")`. So it's not working :( – BartekPL Mar 20 '17 at 10:38
  • 1
    `CMake has no reason to execute commands in DOWNLOAD_COMMAND via a shell, it just executes them directly.` - Not quite true. Content of *DOWNLOAD_COMMAND* option is passed to `add_custom_command`, and it executes commands in the shell (particularly, with "Unix Makefiles" generator). With `add_custom_command` *simple redirection* works. I guess the problem is exactly with appending (`>>`): probably, CMake doesn't recognize it as a *shell operator*, and encloses into double quotes. – Tsyvarev Mar 20 '17 at 10:44
  • @Tsyvarev If that's the case, I will remove the answer (I know next to nothing about EP internals). If you can provide a better answer, please do. – Angew is no longer proud of SO Mar 20 '17 at 10:45
  • No, your answer is mainly OK. While redirection in *COMMAND* is used sometimes, it is not recommended as non-portable and generator-specific. – Tsyvarev Mar 20 '17 at 10:48
  • @Tsyvarev Do you have any idea how to use here FILE(WRITE ...) with success? – BartekPL Mar 20 '17 at 10:52
  • 2
    @BartekPL Wrap it in a script executed via `${CMAKE_COMMAND}`. You can even generate that script on the fly with `file(WRITE)` executed before the external project call, if you really want to. – Angew is no longer proud of SO Mar 20 '17 at 10:55
1

You may use this script for automate checkout of the directory:

git_sparse_checkout.cmake:

execute_process(COMMAND git init)
execute_process(COMMAND git remote add origin ${GIT_REPO})
execute_process(COMMAND git config core.sparsecheckout true)
set(sparse_directories ${GIT_REPO_DIR}/*)
FILE(APPEND .git/info/sparse-checkout ${sparse_directories})
execute_process(COMMAND git pull --depth=1 origin master)

Usage:

ExternalProject_Add(
    DOWNLOAD_COMMAND ${CMAKE_COMMAND} -DGIT_REPO=https://github.com/g-truc/glm -DGIT_REPO_DIR=glm -P git_sparse_checkout.cmake
    ... # Other parameters for ExternalProject_Add
)
BartekPL
  • 2,290
  • 1
  • 17
  • 34
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • Ok, It works, but you should change line `FILE(GLOB sparce_directories "${GIT_REPO_DIR}/*" RELATIVE .)` to `set(sparse_directories ${GIT_REPO_DIR}/*)` and `-DREPO_DIR=glm` to `-DGIT_REPO_DIR=glm`. Thanks a lot! – BartekPL Mar 20 '17 at 12:00
  • You still don't fix everything I wrote in comment above :) I edit it myself, but my edit need review :P. – BartekPL Mar 20 '17 at 12:11
  • Oh, you need "glm/*" **directly** in the file. I though it should be expanded before. – Tsyvarev Mar 20 '17 at 12:32