diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a80a311..93424be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,9 @@ jobs: - name: Run provider merging tests run: cmake -P tests/install/test_provider_merge.cmake + - name: Run setup.cmake version resolution test + run: cmake -P tests/setup/test_setup_version_resolution.cmake + integration-tests: name: Integration Tests runs-on: ubuntu-latest @@ -152,4 +155,3 @@ jobs: test -f templates/Doxyfile.in test -f templates/custom.css echo "✓ All template files present" - diff --git a/setup.cmake b/setup.cmake index f61cce4..74ef206 100644 --- a/setup.cmake +++ b/setup.cmake @@ -9,7 +9,28 @@ 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} @@ -17,14 +38,26 @@ execute_process( 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") + message(WARNING "No git tag found for cpp-library version. Falling back to branch 'main'.") endif() message(STATUS "cpp-library version: ${CPP_LIBRARY_VERSION}") diff --git a/tests/setup/test_setup_version_resolution.cmake b/tests/setup/test_setup_version_resolution.cmake new file mode 100644 index 0000000..89304c4 --- /dev/null +++ b/tests/setup/test_setup_version_resolution.cmake @@ -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}")