Skip to content

[BUG] Patch commands fail trying to re-apply the same patch twice #618

Open
@Jazzinghen

Description

@Jazzinghen

Due to a dependency with improper CMakeLists.txt I tried to use the PATCHES field, however the second time I run the configuration CMake fails during FetchContent_MakeAvailable for that package with this output:

[cmake] -- CPM: Adding package sqlite_protobuf@0 (082596c282cab90f50b6d6dee5f9be22fd503dbe)
[cmake] [ 11%] Performing update step for 'sqlite_protobuf-populate'
[cmake] -- Already at requested ref: 082596c282cab90f50b6d6dee5f9be22fd503dbe
[cmake] [ 22%] Performing patch step for 'sqlite_protobuf-populate'
[cmake] patching file CMakeLists.txt
[cmake] Reversed (or previously applied) patch detected!  Assume -R? [n] 
[cmake] Apply anyway? [n] 
[cmake] Skipping patch.
[cmake] 1 out of 1 hunk ignored -- saving rejects to file CMakeLists.txt.rej
[cmake] patching file src/CMakeLists.txt
[cmake] Reversed (or previously applied) patch detected!  Assume -R? [n] 
[cmake] Apply anyway? [n] 
[cmake] Skipping patch.
[cmake] 2 out of 2 hunks ignored -- saving rejects to file src/CMakeLists.txt.rej
[cmake] make[2]: *** [CMakeFiles/sqlite_protobuf-populate.dir/build.make:118: sqlite_protobuf-populate-prefix/src/sqlite_protobuf-populate-stamp/sqlite_protobuf-populate-patch] Error 1
[cmake] make[1]: *** [CMakeFiles/Makefile2:87: CMakeFiles/sqlite_protobuf-populate.dir/all] Error 2
[cmake] make: *** [Makefile:91: all] Error 2
[cmake] 
[cmake] CMake Error at /usr/share/cmake/Modules/FetchContent.cmake:1918 (message):
[cmake]   Build step for sqlite_protobuf failed: 2
[cmake] Call Stack (most recent call first):
[cmake]   /usr/share/cmake/Modules/FetchContent.cmake:1609 (__FetchContent_populateSubbuild)
[cmake]   /usr/share/cmake/Modules/FetchContent.cmake:2145:EVAL:2 (__FetchContent_doPopulation)
[cmake]   /usr/share/cmake/Modules/FetchContent.cmake:2145 (cmake_language)
[cmake]   /usr/share/cmake/Modules/FetchContent.cmake:2384 (__FetchContent_Populate)
[cmake]   build/cmake/CPM_0.40.2.cmake:1114 (FetchContent_MakeAvailable)
[cmake]   build/cmake/CPM_0.40.2.cmake:895 (cpm_fetch_package)
[cmake]   src/wrapper/CMakeLists.txt:3 (cpmaddpackage)
[cmake] 
[cmake] 
[cmake] -- Configuring incomplete, errors occurred!

This is the relevant piece of my CMakeLists.txt:

cpmaddpackage(
  NAME
  sqlite_protobuf
  GITHUB_REPOSITORY
  rgov/sqlite_protobuf
  GIT_TAG
  082596c282cab90f50b6d6dee5f9be22fd503dbe
  PATCHES
  "${PROJECT_SOURCE_DIR}/cmake/sqlite_protobuf_fix.patch")

Activity

soulfresh

soulfresh commented on Nov 26, 2024

@soulfresh

I'm seeing the same issue. If I choose "no" at the patch reverse step, the build fails because the patch fails to apply. If I choose "yes", then the patch is reversed and the library is no longer patched the way I need. It might be good to set a cache variable tracking each patch that has been applied and then skipping that patch on subsequent passes.

soulfresh

soulfresh commented on Nov 26, 2024

@soulfresh

For anyone else who finds this, here's my workaround:

if (NOT TRACKTION_ENGINE_PATCHED) 
  set(TRACKTION_ENGINE_PATCHED TRUE CACHE INTERNAL "Whether to apply patches to Tracktion Engine")
  CPMAddPackage(
    NAME TracktionEngine
    GITHUB_REPOSITORY Tracktion/tracktion_engine
    VERSION 3.0
    SOURCE_DIR ${DEPS_DIR}/tracktion_engine
    # Prevent Tracktion Engine from compiling its examples.
    PATCHES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/tracktion_engine.patch"
  )
else()
  CPMAddPackage(
    NAME TracktionEngine
    GITHUB_REPOSITORY Tracktion/tracktion_engine
    VERSION 3.0
    SOURCE_DIR ${DEPS_DIR}/tracktion_engine
  )
endif()
apirogov

apirogov commented on Nov 27, 2024

@apirogov

Have the same issue. Hope this gets fixed soon!

apirogov

apirogov commented on Nov 28, 2024

@apirogov

The workaround works only when no CPM caching is used. Otherwise probably it needs to do something more reliable, like checking whether it was just freshly downloaded or not.

soulfresh

soulfresh commented on Nov 29, 2024

@soulfresh

Hmmm...it seems to work for me with CPM caching on (unless I'm misunderstanding what CPM caching does). In my project, I've set set(CPM_SOURCE_CACHE "${CMAKE_CURRENT_SOURCE_DIR}/deps"). On the first run, it downloads the package, applies my patch and sets my custom CMake cache variable. On subsequent runs, CPM doesn't re-download the package or apply the patch and my app builds as expected. Its possible for my custom CMake cache variable to get out of sync with the file system if the dependency cache is deleted but that CMake variable is not removed. I use a clean script to ensure both get removed.

My work around is definitely less than ideal but should work; though I may be misunderstanding something.

rokups

rokups commented on Mar 30, 2025

@rokups
Contributor

Could something like this be considered for a fix?

diff --git a/CMake/Modules/CPM.cmake b/CMake/Modules/CPM.cmake
index e3b1bfbda3..7ee7e5798a 100644
--- a/CMake/Modules/CPM.cmake
+++ b/CMake/Modules/CPM.cmake
@@ -765,8 +765,6 @@ function(CPMAddPackage)
     set(CPM_FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/_deps)
   endif()
 
-  cpm_add_patches(${CPM_ARGS_PATCHES})
-
   if(DEFINED CPM_ARGS_DOWNLOAD_COMMAND)
     list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND})
   elseif(DEFINED CPM_ARGS_SOURCE_DIR)
@@ -819,14 +817,9 @@ function(CPMAddPackage)
       )
       cpm_get_fetch_properties("${CPM_ARGS_NAME}")
 
-      if(DEFINED CPM_ARGS_GIT_TAG AND NOT (PATCH_COMMAND IN_LIST CPM_ARGS_UNPARSED_ARGUMENTS))
-        # warn if cache has been changed since checkout
-        cpm_check_git_working_dir_is_clean(${download_directory} ${CPM_ARGS_GIT_TAG} IS_CLEAN)
-        if(NOT ${IS_CLEAN})
-          message(
-            WARNING "${CPM_INDENT} Cache for ${CPM_ARGS_NAME} (${download_directory}) is dirty"
-          )
-        endif()
+      # Only apply patches if the source directory doesn't exist, meaning it's a fresh checkout
+      if(NOT EXISTS "${${CPM_ARGS_NAME}_SOURCE_DIR}")
+        cpm_add_patches(${CPM_ARGS_PATCHES})
       endif()
 
       cpm_add_subdirectory(
aaeberharter

aaeberharter commented on Apr 30, 2025

@aaeberharter

The following does NOT work reliably, instead the fix by @BohdanBuinich should be used.

I changed some code in CPM which fixes this issue for me. The main idea is checking first if the patch is reversible which (hopefully) is only the case if the patch had been applied previously. Command is taken from here: https://stackoverflow.com/questions/48167884/check-if-git-apply-was-already-applied

I also use git apply instead of the legacy (?) patch CLI

function(cpm_add_patches)
    (...)
    # Convert to absolute path for use with patch file command.
    get_filename_component(PATCH_FILE "${PATCH_FILE}" ABSOLUTE)

    execute_process(COMMAND "${GIT_EXECUTABLE}" "apply" "--reverse" "--check" "-p1" "${PATCH_FILE}"
        RESULT_VARIABLE apply_reverse
    )

    if (NOT apply_reverse EQUAL 0) # if a reverse patch would NOT be succesful
        # The first patch entry must be preceded by "PATCH_COMMAND" while the following items are
        # preceded by "&&".
        if(first_item)
          set(first_item False)
          list(APPEND temp_list "PATCH_COMMAND")
        else()
          list(APPEND temp_list "&&")
        endif()
        # Add the patch command to the list
        list(APPEND temp_list "${GIT_EXECUTABLE}" "apply" "-p1" "${PATCH_FILE}")
    endif()
    (...)
carlocorradini

carlocorradini commented on May 8, 2025

@carlocorradini
Contributor

Any update? 😥

added a commit that references this issue on Jun 3, 2025
5060d97
added a commit that references this issue on Jun 16, 2025
3c3ebf1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @Jazzinghen@apirogov@soulfresh@aaeberharter@rokups

      Issue actions

        [BUG] Patch commands fail trying to re-apply the same patch twice · Issue #618 · cpm-cmake/CPM.cmake