From d354d37cef65ac34d3b0700b218fe527c965132b Mon Sep 17 00:00:00 2001 From: lc285652 Date: Tue, 28 Jul 2026 19:50:05 +0800 Subject: [PATCH] fix(c-api): stop reporting bogus 0.2.1 version when git tags are missing When 'git describe' cannot produce a vX.Y.Z tag (shallow clones, tarball builds), the C API version headers were silently baked with a plausible-looking 0.2.1, lying about the ABI identity. Following DuckDB's approach: add OVERRIDE_GIT_DESCRIBE cache variable so packagers/CI can inject an explicit version (with format validation, FATAL_ERROR on malformed input), and fall back to an obviously-dummy v0.0.0 with a loud warning, keeping the commit hash for traceability. Fixes #621 --- src/binding/c/CMakeLists.txt | 40 ++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/binding/c/CMakeLists.txt b/src/binding/c/CMakeLists.txt index a23a64373..1074b9ba2 100644 --- a/src/binding/c/CMakeLists.txt +++ b/src/binding/c/CMakeLists.txt @@ -16,8 +16,25 @@ include(${PROJECT_ROOT_DIR}/cmake/bazel.cmake) include(${PROJECT_ROOT_DIR}/cmake/option.cmake) include(GNUInstallDirs) -# Retrieve version from git repository and generate version header -git_version(ZVEC_VERSION ${CMAKE_CURRENT_SOURCE_DIR}) +# Allow packagers/CI to inject an explicit version when git tags are not +# visible (shallow clones, tarball builds, fetch-depth:1 checkouts, ...). +# Same convention as DuckDB's OVERRIDE_GIT_DESCRIBE. +# Expected format: vX.Y.Z, optionally with a describe suffix (e.g. v0.5.1-3-gabc1234) +set(OVERRIDE_GIT_DESCRIBE "" CACHE STRING + "Explicit version string (vX.Y.Z[-N-g]) used instead of 'git describe'") + +if(OVERRIDE_GIT_DESCRIBE) + if(NOT OVERRIDE_GIT_DESCRIBE MATCHES "^v[0-9]+\\.[0-9]+\\.[0-9]+") + message(FATAL_ERROR + "Provided OVERRIDE_GIT_DESCRIBE '${OVERRIDE_GIT_DESCRIBE}' does not match " + "the expected format 'vX.Y.Z' or 'vX.Y.Z-N-g'") + endif() + set(ZVEC_VERSION "${OVERRIDE_GIT_DESCRIBE}") + message(STATUS "Using OVERRIDE_GIT_DESCRIBE as version: ${ZVEC_VERSION}") +else() + # Retrieve version from git repository and generate version header + git_version(ZVEC_VERSION ${CMAKE_CURRENT_SOURCE_DIR}) +endif() # Debug: print version variables message(STATUS "ZVEC_VERSION: ${ZVEC_VERSION}") @@ -30,11 +47,22 @@ if(ZVEC_VERSION MATCHES "^v([0-9]+)\\.([0-9]+)\\.([0-9]+)") set(ZVEC_VERSION_PATCH "${CMAKE_MATCH_3}") set(ZVEC_VERSION_STRING "${ZVEC_VERSION}") else() - # Default version if parsing fails + # git describe failed to produce a 'vX.Y.Z' tag (likely a shallow clone + # without tags). Fall back to an obviously-dummy version instead of a + # plausible-looking one, so consumers never trust a lying ABI identity. + message(WARNING + "Could not derive a 'vX.Y.Z' version from git describe (got '${ZVEC_VERSION}'), " + "likely due to a shallow clone without tags. Continuing with dummy version v0.0.0. " + "Fetch tags (git fetch --tags) or pass -DOVERRIDE_GIT_DESCRIBE=vX.Y.Z for a correct version.") set(ZVEC_VERSION_MAJOR 0) - set(ZVEC_VERSION_MINOR 2) - set(ZVEC_VERSION_PATCH 1) - set(ZVEC_VERSION_STRING "${ZVEC_VERSION_MAJOR}.${ZVEC_VERSION_MINOR}.${ZVEC_VERSION_PATCH}") + set(ZVEC_VERSION_MINOR 0) + set(ZVEC_VERSION_PATCH 0) + if(ZVEC_VERSION) + # Keep the commit identifier (e.g. 'g') for traceability + set(ZVEC_VERSION_STRING "v0.0.0-${ZVEC_VERSION}") + else() + set(ZVEC_VERSION_STRING "v0.0.0") + endif() endif() message(STATUS "Parsed version: ${ZVEC_VERSION_MAJOR}.${ZVEC_VERSION_MINOR}.${ZVEC_VERSION_PATCH} (${ZVEC_VERSION_STRING})")