Where does the hash before .clean under buildtrees/<package>/src in vcpkg come from

intro

If you inspect the structure of vcpkg in your local file system, you may notice that the source code of the package is located in a directory like this:

tsecer@harry: ls  -d  vcpkg/buildtrees/curl/src/url-8_14_1-c688bafef9.clean                                             vcpkg/buildtrees/curl/src/url-8_14_1-c688bafef9.clean  

The interesting part is what the hash value is, e.g. c688bafef9 in the example above. where does it come from and what is it used for?

inside vcpkg

It's not diffault to track down the source code that generates this hash in vcpkg. And the code is copied here for easy reading:

    # Hash the archive hash along with the patches. Take the first 10 chars of the hash
    file(SHA512 "${arg_ARCHIVE}" patchset_hash)
    foreach(patch IN LISTS arg_PATCHES)
        cmake_path(ABSOLUTE_PATH patch
            BASE_DIRECTORY "${CURRENT_PORT_DIR}"
            OUTPUT_VARIABLE absolute_patch
        )
        if(NOT EXISTS "${absolute_patch}")
            message(FATAL_ERROR "Could not find patch: '${patch}'")
        endif()
        file(SHA512 "${absolute_patch}" current_hash)
        string(APPEND patchset_hash "${current_hash}")
    endforeach()

    string(SHA512 patchset_hash "${patchset_hash}")
    string(SUBSTRING "${patchset_hash}" 0 10 patchset_hash)
    cmake_path(APPEND working_directory "${arg_SOURCE_BASE}-${patchset_hash}"
        OUTPUT_VARIABLE source_path
    )

    if(_VCPKG_EDITABLE AND EXISTS "${source_path}")
        set("${out_source_path}" "${source_path}" PARENT_SCOPE)
        message(STATUS "Using source at ${source_path}")
        return()
    elseif(NOT _VCPKG_EDITABLE)
        cmake_path(APPEND_STRING source_path ".clean")
        if(EXISTS "${source_path}")
            message(STATUS "Cleaning sources at ${source_path}. Use --editable to skip cleaning for the packages you specify.")
            file(REMOVE_RECURSE "${source_path}")
        endif()
    endif()

The logic here is straightforward too: It derives from the SHA512 hash value of the string which is assembled from the archive file and hash values of all patch files.

patch set matters

  • orders

Since the hashes of all patches are constructed in the order defined in the patch set, the final hash will change if the patch sequence is adjusted, even if the file content remains unchanged.

  • content

A new local package will be created for each patch set no matter how tiny the patch set is.

verify

If the order of the patches is modified even without changing the patch files, a new local package will be created:

tsecer@harry: git diff
diff --git a/ports/curl/portfile.cmake b/ports/curl/portfile.cmake
index d884af05e2..0dce90ab42 100644
--- a/ports/curl/portfile.cmake
+++ b/ports/curl/portfile.cmake
@@ -7,8 +7,8 @@ vcpkg_from_github(
     SHA512 ec2fa6c47d52feed943421b00e98370971bcc73b82842a85426ea9e42d36eaab51258a8d00197fdaaf5ec39e19385280fe387765f27e3b3dc1086c46236dc0bf
     HEAD_REF master
     PATCHES
-        dependencies.patch
         pkgconfig-curl-config.patch
+        dependencies.patch
 )

 vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
tsecer@harry: ls buildtrees/curl/src/
url-8_14_1-15947c732c.clean  url-8_14_1-c688bafef9.clean
tsecer@harry:

outro

I guess the hash is primarily used for the patch mechanism in vcpkg and it does resolve the issue neatly.

posted on 2026-05-24 13:22  tsecer  阅读(28)  评论(0)    收藏  举报

导航