PATCH_COMMAND with ExternalProject works but with FetchContent an error is triggered

I’ve got a PATCH_COMMAND which fails with FetchContent but works
with ExternalProject. The only difference (I can see at least) is
that I change FetchContent_Declare to ExternalProject_Add and
remove FetchContent_MakeAvailable() with adding a dependency to
my target. From the docs it seems that the PATCH_COMMAND option
should be the same. Any ideas what might go wrong?

This is the error I get:

-- The C compiler identification is GNU 15.1.1
-- The CXX compiler identification is GNU 15.1.1
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Cloning into 'glad'...
HEAD is now at 47c20c1 setup: Bumped version: 2.0.3.
error: unknown option `ignore-space-change'
usage: git restore [<options>] [--source=<branch>] <file>...

    -s, --[no-]source <tree-ish>
                          which tree-ish to checkout from
    -S, --[no-]staged     restore the index
    -W, --[no-]worktree   restore the working tree (default)
    --[no-]ignore-unmerged
                          ignore unmerged entries
    --[no-]overlay        use overlay mode
    -q, --[no-]quiet      suppress progress reporting
    --[no-]recurse-submodules[=<checkout>]
                          control recursive updating of submodules
    --[no-]progress       force progress reporting
    -m, --[no-]merge      perform a 3-way merge with the new branch
    --[no-]conflict <style>
                          conflict style (merge, diff3, or zdiff3)
    -2, --ours            checkout our version for unmerged files
    -3, --theirs          checkout their version for unmerged files
    -p, --[no-]patch      select hunks interactively
    --[no-]ignore-skip-worktree-bits
                          do not limit pathspecs to sparse entries only
    --[no-]pathspec-from-file <file>
                          read pathspec from file
    --[no-]pathspec-file-nul
                          with --pathspec-from-file, pathspec elements are separated with NUL character

CMake Error at build.release/CMakeFiles/fc-tmp/glad/patch.cmake:7 (execute_process):
  execute_process last command failed
Call Stack (most recent call first):
  /usr/share/cmake/Modules/FetchContent.cmake:1753 (include)
  /usr/share/cmake/Modules/FetchContent.cmake:1716 (__FetchContent_doStepDirect)
  /usr/share/cmake/Modules/FetchContent.cmake:1607 (__FetchContent_populateDirect)
  /usr/share/cmake/Modules/FetchContent.cmake:2145:EVAL:2 (__FetchContent_doPopulation)
  /usr/share/cmake/Modules/FetchContent.cmake:2145 (cmake_language)
  /usr/share/cmake/Modules/FetchContent.cmake:2384 (__FetchContent_Populate)
  CMakeLists.txt:76 (FetchContent_MakeAvailable)
set(glad_prefix ${CMAKE_CURRENT_BINARY_DIR}/glad)
set(glad_patch ${CMAKE_CURRENT_LIST_DIR}/glad.patch)

include(ExternalProject)
include(FetchContent)

FetchContent_Declare(
#ExternalProject_Add(
  glad
  GIT_REPOSITORY https://github.com/Dav1dde/glad.git
  GIT_TAG v2.0.3
  DOWNLOAD_EXTRACT_TIMESTAMP FALSE
  PATCH_COMMAND
    git restore <SOURCE_DIR>/cmake/CMakeLists.txt &&
    git apply --ignore-space-change --ignore-whitespace ${glad_patch}
  SOURCE_DIR ${glad_prefix}
)

You’re assuming a unix shell is used, and CMake does not guarantee that. Can you try the following to see if it works for you:

FetchContent_Declare(
  glad
  GIT_REPOSITORY https://github.com/Dav1dde/glad.git
  GIT_TAG v2.0.3
  DOWNLOAD_EXTRACT_TIMESTAMP FALSE
  PATCH_COMMAND git restore <SOURCE_DIR>/cmake/CMakeLists.txt
  COMMAND git apply --ignore-space-change --ignore-whitespace ${glad_patch}
  SOURCE_DIR ${glad_prefix}
)

If you don’t want to split the commands like that, you should put the commands in a script file and run that as your PATCH_COMMAND. Don’t use shell redirection, pipes, etc. directly in PATCH_COMMAND.

1 Like

Oh, I just re-read the error message more closely. The --ignore-space-change option isn’t recognised by your version of git. I don’t know how ExternalProject_Add() is not causing an error as well. Maybe it is erroring, but that error is somehow slipping through unnoticed. You could also check whether ExternalProject and FetchContent are both invoking the same git executable. I don’t know how they could be different, but just putting it out there as something to check.

EDIT: Ignore this, I think I was right the first time. The error is saying an option you gave for the second command was not recognised by the first. That seems to confirm the && isn’t doing what you expected. See my previous comment for the likely fix.

Thanks for your replies Craig!

For now I’m doing this test on Linux indeed. I don’t think the issue is related using && to combine commands, that should be fine as far as I know. The thing is, ExternalProject_Add with exactly the same command works, but FetchContent does not. Yeah I thought about my git not supporting –ignore-space-change, but that’s also not the case.

I’ve worked around it with a better solution for this particular dependency, however I’m still curious why FetchContent behaves differently when it comes to PATCH_COMMAND.

While FetchContent uses a lot of ExternalProject’s internal implementation (and in older versions it uses ExternalProject directly), there can still be subtle differences in how some aspects are parsed, etc. I do think the && is your problem, the error message confirms that the whole thing is seen as one command by the system, not two separate commands.