-
Notifications
You must be signed in to change notification settings - Fork 0
Fix standalone setup.cmake version resolution to avoid invalid vX.Y.Z checkout
#21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,22 +9,55 @@ | |
|
|
||
| cmake_minimum_required(VERSION 3.20) | ||
|
|
||
| # Detect cpp-library version from git tags | ||
| # Extract latest semantic version from a list of refs/tags/vX.Y.Z entries | ||
| function(extract_latest_cpp_library_version_from_tags TAG_REFS OUTPUT_VAR) | ||
| string(REGEX MATCHALL "refs/tags/v[0-9]+\\.[0-9]+\\.[0-9]+" TAG_REFS_MATCHES "${TAG_REFS}") | ||
|
|
||
| set(SEMVER_TAGS "") | ||
| foreach(tag_ref IN LISTS TAG_REFS_MATCHES) | ||
| string(REGEX REPLACE "^refs/tags/v" "" semver "${tag_ref}") | ||
| list(APPEND SEMVER_TAGS "${semver}") | ||
| endforeach() | ||
|
|
||
| if(SEMVER_TAGS) | ||
| list(REMOVE_DUPLICATES SEMVER_TAGS) | ||
| list(SORT SEMVER_TAGS COMPARE NATURAL ORDER DESCENDING) | ||
| list(GET SEMVER_TAGS 0 latest_version) | ||
| set(${OUTPUT_VAR} "${latest_version}" PARENT_SCOPE) | ||
| else() | ||
| set(${OUTPUT_VAR} "" PARENT_SCOPE) | ||
| endif() | ||
| endfunction() | ||
|
|
||
| # Detect cpp-library version from local git tags first | ||
| set(CPP_LIBRARY_VERSION "") | ||
| execute_process( | ||
| COMMAND git describe --tags --abbrev=0 | ||
| WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} | ||
| OUTPUT_VARIABLE CPP_LIBRARY_GIT_VERSION | ||
| OUTPUT_STRIP_TRAILING_WHITESPACE | ||
| ERROR_QUIET | ||
| ) | ||
|
|
||
| # Clean version (remove 'v' prefix if present) | ||
| if(CPP_LIBRARY_GIT_VERSION) | ||
| string(REGEX REPLACE "^v" "" CPP_LIBRARY_VERSION "${CPP_LIBRARY_GIT_VERSION}") | ||
| else() | ||
| # Fallback to X.Y.Z placeholder if no git tag found | ||
| set(CPP_LIBRARY_VERSION "X.Y.Z") | ||
| message(WARNING "No git tag found for cpp-library version. Using placeholder 'X.Y.Z'. Check https://github.com/stlab/cpp-library/releases for the latest version.") | ||
| endif() | ||
|
|
||
| # If setup.cmake is downloaded standalone (no local tags), detect from remote tags | ||
| if(NOT CPP_LIBRARY_VERSION) | ||
| execute_process( | ||
| COMMAND git ls-remote --tags --refs https://github.com/stlab/cpp-library.git v[0-9]* | ||
| OUTPUT_VARIABLE CPP_LIBRARY_REMOTE_TAGS | ||
| OUTPUT_STRIP_TRAILING_WHITESPACE | ||
| ERROR_QUIET | ||
| TIMEOUT 10 | ||
| ) | ||
| extract_latest_cpp_library_version_from_tags("${CPP_LIBRARY_REMOTE_TAGS}" CPP_LIBRARY_VERSION) | ||
| endif() | ||
|
|
||
| # Last-resort fallback to main branch so initialization still works | ||
| if(NOT CPP_LIBRARY_VERSION) | ||
| set(CPP_LIBRARY_VERSION "main") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fallback
|
||
| message(WARNING "No git tag found for cpp-library version. Falling back to branch 'main'.") | ||
| endif() | ||
|
|
||
| message(STATUS "cpp-library version: ${CPP_LIBRARY_VERSION}") | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| # SPDX-License-Identifier: BSL-1.0 | ||
| # | ||
| # Integration test for setup.cmake version detection when run standalone | ||
| # | ||
| # Run as: cmake -P tests/setup/test_setup_version_resolution.cmake | ||
|
|
||
| cmake_minimum_required(VERSION 3.20) | ||
|
|
||
| if(DEFINED ENV{TMPDIR} AND NOT "$ENV{TMPDIR}" STREQUAL "") | ||
| set(TEST_BASE_DIR "$ENV{TMPDIR}") | ||
| elseif(DEFINED ENV{TEMP} AND NOT "$ENV{TEMP}" STREQUAL "") | ||
| set(TEST_BASE_DIR "$ENV{TEMP}") | ||
| elseif(DEFINED ENV{TMP} AND NOT "$ENV{TMP}" STREQUAL "") | ||
| set(TEST_BASE_DIR "$ENV{TMP}") | ||
| else() | ||
| set(TEST_BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}") | ||
| endif() | ||
|
|
||
| set(TEST_ROOT_DIR "${TEST_BASE_DIR}/cpp-library-setup-version-test") | ||
| set(TEST_PROJECT_NAME "setup-version-test-lib") | ||
|
|
||
| file(REMOVE_RECURSE "${TEST_ROOT_DIR}") | ||
| file(MAKE_DIRECTORY "${TEST_ROOT_DIR}") | ||
| file(COPY "${CMAKE_CURRENT_LIST_DIR}/../../setup.cmake" DESTINATION "${TEST_ROOT_DIR}") | ||
|
|
||
| execute_process( | ||
| COMMAND | ||
| ${CMAKE_COMMAND} | ||
| -P | ||
| setup.cmake | ||
| -- | ||
| --name=${TEST_PROJECT_NAME} | ||
| --namespace=testns | ||
| --description=test | ||
| --header-only=yes | ||
| --examples=no | ||
| --tests=no | ||
| WORKING_DIRECTORY "${TEST_ROOT_DIR}" | ||
| RESULT_VARIABLE SETUP_RESULT | ||
| OUTPUT_VARIABLE SETUP_OUTPUT | ||
| ERROR_VARIABLE SETUP_ERROR | ||
| ) | ||
|
|
||
| if(NOT SETUP_RESULT EQUAL 0) | ||
| message(FATAL_ERROR "setup.cmake failed with exit code ${SETUP_RESULT}\nstdout:\n${SETUP_OUTPUT}\nstderr:\n${SETUP_ERROR}") | ||
| endif() | ||
|
|
||
| set(GENERATED_CMAKE_LISTS "${TEST_ROOT_DIR}/${TEST_PROJECT_NAME}/CMakeLists.txt") | ||
| if(NOT EXISTS "${GENERATED_CMAKE_LISTS}") | ||
| message(FATAL_ERROR "Generated CMakeLists.txt not found: ${GENERATED_CMAKE_LISTS}") | ||
| endif() | ||
|
|
||
| file(READ "${GENERATED_CMAKE_LISTS}" GENERATED_CONTENT) | ||
|
|
||
| if(GENERATED_CONTENT MATCHES "CPMAddPackage\\(\"gh:stlab/cpp-library@X\\.Y\\.Z\"\\)") | ||
| message(FATAL_ERROR "setup.cmake generated placeholder version X.Y.Z, which should never be emitted.") | ||
| endif() | ||
|
|
||
| if(NOT GENERATED_CONTENT MATCHES "CPMAddPackage\\(\"gh:stlab/cpp-library@([0-9]+\\.[0-9]+\\.[0-9]+|main)\"\\)") | ||
| message(FATAL_ERROR "setup.cmake generated invalid cpp-library version reference in CPMAddPackage.") | ||
| endif() | ||
|
|
||
| message(STATUS "✓ setup.cmake generated a valid cpp-library version reference") | ||
|
|
||
| file(REMOVE_RECURSE "${TEST_ROOT_DIR}") |


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unanchored regex matches pre-release tags as releases
Low Severity
The
MATCHALLregexrefs/tags/v[0-9]+\\.[0-9]+\\.[0-9]+has no end-of-token anchor, so it performs substring matching. A pre-release tag likerefs/tags/v2.0.0-rc1would partially match asrefs/tags/v2.0.0, causing the function to return version2.0.0even if only the-rc1tag exists. CPM would then attempt to check out the nonexistentv2.0.0tag and fail — the same class of problem this PR aims to fix.Reviewed by Cursor Bugbot for commit dcab025. Configure here.