From a5a48166e5b23ef25373c443d8551cdafc58abd3 Mon Sep 17 00:00:00 2001 From: Kai Pastor Date: Mon, 10 Mar 2025 20:16:41 +0100 Subject: [PATCH] [vcpkg] Controlling top-level find_package (#27950) --- scripts/buildsystems/vcpkg.cmake | 36 +++- .../test_ports/unit-test-cmake/portfile.cmake | 167 +----------------- .../unit-test-cmake/test-macros.cmake | 165 +++++++++++++++++ .../portfile.cmake | 157 +++++++++++++++- .../vcpkg_lock_find_package/CMakeLists.txt.in | 10 ++ .../directPackageXConfig.cmake | 1 + ...ansitiveOptionalAbsentPackageXConfig.cmake | 2 + .../transitivePackageXConfig.cmake | 2 + .../vcpkg-ci-cmake-toolchain-file/vcpkg.json | 4 + 9 files changed, 378 insertions(+), 166 deletions(-) create mode 100644 scripts/test_ports/unit-test-cmake/test-macros.cmake create mode 100644 scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/CMakeLists.txt.in create mode 100644 scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/directPackageXConfig.cmake create mode 100644 scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/transitiveOptionalAbsentPackageXConfig.cmake create mode 100644 scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/transitivePackageXConfig.cmake diff --git a/scripts/buildsystems/vcpkg.cmake b/scripts/buildsystems/vcpkg.cmake index 02c462bc73..c14404bf00 100644 --- a/scripts/buildsystems/vcpkg.cmake +++ b/scripts/buildsystems/vcpkg.cmake @@ -784,6 +784,37 @@ macro("${VCPKG_OVERRIDE_FIND_PACKAGE_NAME}" z_vcpkg_find_package_package_name) set(z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_ARGN "${ARGN}") set(z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_backup_vars "") + if(z_vcpkg_find_package_backup_id EQUAL "1") + # This is the top-level find_package call + if("${VCPKG_LOCK_FIND_PACKAGE_${z_vcpkg_find_package_package_name}}") + # Avoid CMake warning when both REQUIRED and CMAKE_REQUIRE_FIND_PACKAGE_ are used + if(NOT "REQUIRED" IN_LIST "z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_ARGN") + list(APPEND "z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_backup_vars" "CMAKE_REQUIRE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}") + if(DEFINED "CMAKE_REQUIRE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}") + set("z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_backup_CMAKE_REQUIRE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}" "${CMAKE_REQUIRE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}}") + endif() + set("CMAKE_REQUIRE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}" 1) + endif() + if(VCPKG_TRACE_FIND_PACKAGE) + message(STATUS " (required by VCPKG_LOCK_FIND_PACKAGE_${z_vcpkg_find_package_package_name}=${VCPKG_LOCK_FIND_PACKAGE_${z_vcpkg_find_package_package_name}})") + endif() + elseif(DEFINED "VCPKG_LOCK_FIND_PACKAGE_${z_vcpkg_find_package_package_name}") + list(APPEND "z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_backup_vars" "CMAKE_DISABLE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}") + if(DEFINED "CMAKE_DISABLE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}") + set("z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_backup_CMAKE_DISABLE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}" "${CMAKE_DISABLE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}}") + endif() + # We don't need to worry about clearing this for transitive users because + # once this top level find_package is disabled, we immediately will return + # not found and not try to visit transitive dependencies in the first place. + set("CMAKE_DISABLE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}" 1) + if(VCPKG_TRACE_FIND_PACKAGE) + message(STATUS " (disabled by VCPKG_LOCK_FIND_PACKAGE_${z_vcpkg_find_package_package_name}=${VCPKG_LOCK_FIND_PACKAGE_${z_vcpkg_find_package_package_name}})") + endif() + elseif(VCPKG_TRACE_FIND_PACKAGE) + message(STATUS " (could be controlled by VCPKG_LOCK_FIND_PACKAGE_${z_vcpkg_find_package_package_name})") + endif() + endif() + # Workaround to set the ROOT_PATH until upstream CMake stops overriding # the ROOT_PATH at apple OS initialization phase. # See https://gitlab.kitware.com/cmake/cmake/merge_requests/3273 @@ -799,7 +830,10 @@ macro("${VCPKG_OVERRIDE_FIND_PACKAGE_NAME}" z_vcpkg_find_package_package_name) string(TOLOWER "${z_vcpkg_find_package_package_name}" z_vcpkg_find_package_lowercase_package_name) set(z_vcpkg_find_package_vcpkg_cmake_wrapper_path "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/${z_vcpkg_find_package_lowercase_package_name}/vcpkg-cmake-wrapper.cmake") - if(EXISTS "${z_vcpkg_find_package_vcpkg_cmake_wrapper_path}") + if(CMAKE_DISABLE_FIND_PACKAGE_${z_vcpkg_find_package_package_name}) + # Skip wrappers, fail if REQUIRED. + _find_package("${z_vcpkg_find_package_package_name}" ${z_vcpkg_find_package_${z_vcpkg_find_package_backup_id}_ARGN}) + elseif(EXISTS "${z_vcpkg_find_package_vcpkg_cmake_wrapper_path}") if(VCPKG_TRACE_FIND_PACKAGE) string(REPEAT " " "${z_vcpkg_find_package_backup_id}" z_vcpkg_find_package_indent) message(STATUS "${z_vcpkg_find_package_indent}using share/${z_vcpkg_find_package_lowercase_package_name}/vcpkg-cmake-wrapper.cmake") diff --git a/scripts/test_ports/unit-test-cmake/portfile.cmake b/scripts/test_ports/unit-test-cmake/portfile.cmake index 615c811688..36a1db33ab 100644 --- a/scripts/test_ports/unit-test-cmake/portfile.cmake +++ b/scripts/test_ports/unit-test-cmake/portfile.cmake @@ -1,168 +1,7 @@ -function(set_fatal_error err) - set(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR "ON" CACHE BOOL "" FORCE) - set(Z_VCPKG_UNIT_TEST_FATAL_ERROR "${err}" CACHE STRING "" FORCE) -endfunction() -function(unset_fatal_error) - set(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR "OFF" CACHE BOOL "" FORCE) -endfunction() -function(set_has_error) - set(Z_VCPKG_UNIT_TEST_HAS_ERROR ON CACHE BOOL "" FORCE) -endfunction() - -macro(message level msg) - if("${level}" STREQUAL "FATAL_ERROR") - set_fatal_error("${msg}") - return() - else() - _message("${level}" "${msg}") # note: this results in incorrect printing, but that's fine - # message(STATUS "\${asdf}") will result in - # message(STATUS "${asdf}"), since that's how macro arguments work. - endif() -endmacro() - -set(Z_VCPKG_UNIT_TEST_HAS_ERROR OFF CACHE BOOL "" FORCE) -unset_fatal_error() - -# in order to allow namespacing -function(unit_test_match namespace value regex) - if("${value}" MATCHES "${regex}") - set("${namespace}_MATCHED" ON PARENT_SCOPE) - if("${CMAKE_MATCH_COUNT}" EQUAL "0") - return() - endif() - - foreach(match RANGE 1 "${CMAKE_MATCH_COUNT}") - set("${namespace}_CMAKE_MATCH_${match}" "${CMAKE_MATCH_${match}}" PARENT_SCOPE) - endforeach() - else() - set("${namespace}_MATCHED" OFF PARENT_SCOPE) - endif() -endfunction() - -function(unit_test_check_variable_unset utcvu_test utcvu_variable) - cmake_language(EVAL CODE "${utcvu_test}") - if(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR) - unset_fatal_error() - set_has_error() - message(SEND_ERROR "${utcvu_test} had an unexpected FATAL_ERROR; - expected: \"${utcvu_value}\"") - message(SEND_ERROR "FATAL_ERROR: ${Z_VCPKG_UNIT_TEST_FATAL_ERROR}") - return() - endif() - - unit_test_match(utcvu "${utcvu_variable}" [[^(ENV|CACHE)\{(.*)\}$]]) - if(utcvu_MATCHED) - message(STATUS "utcvu_variable: ${utcvu_CMAKE_MATCH_2}") - if("${utcvu_CMAKE_MATCH_1}" STREQUAL "ENV") - set(utcvu_actual_value "$ENV{${utcvu_CMAKE_MATCH_2}}") - elseif("${utcvu_CMAKE_MATCH_1}" STREQUAL "CACHE") - set(utcvu_actual_value "$CACHE{${utcvu_CMAKE_MATCH_2}}") - else() - _message(FATAL_ERROR "unexpected value for CMAKE_MATCH_1: ${utcvu_CMAKE_MATCH_1}") - endif() - else() - set(utcvu_actual_value "${${utcvu_variable}}") - endif() - - if(DEFINED "${utcvu_variable}") - message(SEND_ERROR "${utcvu_test} set ${utcvu_variable}; - expected: \"${utcvu_variable}\" unset - actual : \"${utcvu_actual_value}\"") - set_has_error() - return() - endif() -endfunction() - -function(unit_test_check_variable_equal utcve_test utcve_variable utcve_value) - cmake_language(EVAL CODE "${utcve_test}") - if(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR) - unset_fatal_error() - set_has_error() - message(SEND_ERROR "${utcve_test} had an unexpected FATAL_ERROR; - expected: \"${utcve_value}\"") - message(SEND_ERROR "FATAL_ERROR: ${Z_VCPKG_UNIT_TEST_FATAL_ERROR}") - return() - endif() - - if(NOT DEFINED "${utcve_variable}" AND NOT "${utcve_variable}" MATCHES "^ENV\\{") - message(SEND_ERROR "${utcve_test} failed to set ${utcve_variable}; - expected: \"${utcve_value}\"") - set_has_error() - return() - endif() - - unit_test_match(utcve "${utcve_variable}" [[^(ENV|CACHE)\{(.*)\}$]]) - if(utcve_MATCHED) - if("${utcve_CMAKE_MATCH_1}" STREQUAL "ENV") - set(utcve_actual_value "$ENV{${utcve_CMAKE_MATCH_2}}") - elseif("${utcve_CMAKE_MATCH_1}" STREQUAL "CACHE") - set(utcve_actual_value "$CACHE{${utcve_CMAKE_MATCH_2}}") - else() - _message(FATAL_ERROR "unexpected value for CMAKE_MATCH_1: ${utcve_CMAKE_MATCH_1}") - endif() - else() - set(utcve_actual_value "${${utcve_variable}}") - endif() - - if(NOT "${utcve_actual_value}" STREQUAL "${utcve_value}") - message(SEND_ERROR "${utcve_test} resulted in the wrong value for ${utcve_variable}; - expected: \"${utcve_value}\" - actual : \"${utcve_actual_value}\"") - set_has_error() - return() - endif() -endfunction() - -function(unit_test_check_variable_not_equal utcve_test utcve_variable utcve_value) - cmake_language(EVAL CODE "${utcve_test}") - if(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR) - unset_fatal_error() - set_has_error() - message(SEND_ERROR "${utcve_test} had an unexpected FATAL_ERROR; - expected: \"${utcve_value}\"") - message(SEND_ERROR "FATAL_ERROR: ${Z_VCPKG_UNIT_TEST_FATAL_ERROR}") - return() - endif() - - unit_test_match(utcve "${utcve_variable}" [[^(ENV|CACHE)\{(.*)\}$]]) - if(utcve_MATCHED) - if("${utcve_CMAKE_MATCH_1}" STREQUAL "ENV") - set(utcve_actual_value "$ENV{${utcve_CMAKE_MATCH_2}}") - elseif("${utcve_CMAKE_MATCH_1}" STREQUAL "CACHE") - set(utcve_actual_value "$CACHE{${utcve_CMAKE_MATCH_2}}") - else() - _message(FATAL_ERROR "unexpected value for CMAKE_MATCH_1: ${utcve_CMAKE_MATCH_1}") - endif() - else() - set(utcve_actual_value "${${utcve_variable}}") - endif() - - if("${utcve_actual_value}" STREQUAL "${utcve_value}") - message(SEND_ERROR "${utcve_test} failed to change ${utcve_variable}; - unchanged: \"${utcve_value}\"") - set_has_error() - return() - endif() -endfunction() - -function(unit_test_ensure_success utcve_test) - cmake_language(EVAL CODE "${utcve_test}") - if(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR) - set_has_error() - message(SEND_ERROR "${utcve_test} was expected to be successful.") - endif() - unset_fatal_error() -endfunction() -function(unit_test_ensure_fatal_error utcve_test) - cmake_language(EVAL CODE "${utcve_test}") - if(NOT Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR) - set_has_error() - message(SEND_ERROR "${utcve_test} was expected to be a FATAL_ERROR.") - endif() - unset_fatal_error() -endfunction() - set(VCPKG_POLICY_EMPTY_PACKAGE enabled) +file(INSTALL "${CURRENT_PORT_DIR}/test-macros.cmake" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") + +include("${CURRENT_PORT_DIR}/test-macros.cmake") if("minimum-required" IN_LIST FEATURES) include("${CMAKE_CURRENT_LIST_DIR}/test-vcpkg_minimum_required.cmake") diff --git a/scripts/test_ports/unit-test-cmake/test-macros.cmake b/scripts/test_ports/unit-test-cmake/test-macros.cmake new file mode 100644 index 0000000000..bf1c3c9233 --- /dev/null +++ b/scripts/test_ports/unit-test-cmake/test-macros.cmake @@ -0,0 +1,165 @@ +include_guard(GLOBAL) + +function(set_fatal_error err) + set(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR "ON" CACHE BOOL "" FORCE) + set(Z_VCPKG_UNIT_TEST_FATAL_ERROR "${err}" CACHE STRING "" FORCE) +endfunction() +function(unset_fatal_error) + set(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR "OFF" CACHE BOOL "" FORCE) +endfunction() +function(set_has_error) + set(Z_VCPKG_UNIT_TEST_HAS_ERROR ON CACHE BOOL "" FORCE) +endfunction() + +macro(message level msg) + if("${level}" STREQUAL "FATAL_ERROR") + set_fatal_error("${msg}") + return() + else() + _message("${level}" "${msg}") # note: this results in incorrect printing, but that's fine + # message(STATUS "\${asdf}") will result in + # message(STATUS "${asdf}"), since that's how macro arguments work. + endif() +endmacro() + +set(Z_VCPKG_UNIT_TEST_HAS_ERROR OFF CACHE BOOL "" FORCE) +unset_fatal_error() + +# in order to allow namespacing +function(unit_test_match namespace value regex) + if("${value}" MATCHES "${regex}") + set("${namespace}_MATCHED" ON PARENT_SCOPE) + if("${CMAKE_MATCH_COUNT}" EQUAL "0") + return() + endif() + + foreach(match RANGE 1 "${CMAKE_MATCH_COUNT}") + set("${namespace}_CMAKE_MATCH_${match}" "${CMAKE_MATCH_${match}}" PARENT_SCOPE) + endforeach() + else() + set("${namespace}_MATCHED" OFF PARENT_SCOPE) + endif() +endfunction() + +function(unit_test_check_variable_unset utcvu_test utcvu_variable) + cmake_language(EVAL CODE "${utcvu_test}") + if(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR) + unset_fatal_error() + set_has_error() + message(SEND_ERROR "${utcvu_test} had an unexpected FATAL_ERROR; + expected: \"${utcvu_value}\"") + message(SEND_ERROR "FATAL_ERROR: ${Z_VCPKG_UNIT_TEST_FATAL_ERROR}") + return() + endif() + + unit_test_match(utcvu "${utcvu_variable}" [[^(ENV|CACHE)\{(.*)\}$]]) + if(utcvu_MATCHED) + message(STATUS "utcvu_variable: ${utcvu_CMAKE_MATCH_2}") + if("${utcvu_CMAKE_MATCH_1}" STREQUAL "ENV") + set(utcvu_actual_value "$ENV{${utcvu_CMAKE_MATCH_2}}") + elseif("${utcvu_CMAKE_MATCH_1}" STREQUAL "CACHE") + set(utcvu_actual_value "$CACHE{${utcvu_CMAKE_MATCH_2}}") + else() + _message(FATAL_ERROR "unexpected value for CMAKE_MATCH_1: ${utcvu_CMAKE_MATCH_1}") + endif() + else() + set(utcvu_actual_value "${${utcvu_variable}}") + endif() + + if(DEFINED "${utcvu_variable}") + message(SEND_ERROR "${utcvu_test} set ${utcvu_variable}; + expected: \"${utcvu_variable}\" unset + actual : \"${utcvu_actual_value}\"") + set_has_error() + return() + endif() +endfunction() + +function(unit_test_check_variable_equal utcve_test utcve_variable utcve_value) + cmake_language(EVAL CODE "${utcve_test}") + if(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR) + unset_fatal_error() + set_has_error() + message(SEND_ERROR "${utcve_test} had an unexpected FATAL_ERROR; + expected: \"${utcve_value}\"") + message(SEND_ERROR "FATAL_ERROR: ${Z_VCPKG_UNIT_TEST_FATAL_ERROR}") + return() + endif() + + if(NOT DEFINED "${utcve_variable}" AND NOT "${utcve_variable}" MATCHES "^ENV\\{") + message(SEND_ERROR "${utcve_test} failed to set ${utcve_variable}; + expected: \"${utcve_value}\"") + set_has_error() + return() + endif() + + unit_test_match(utcve "${utcve_variable}" [[^(ENV|CACHE)\{(.*)\}$]]) + if(utcve_MATCHED) + if("${utcve_CMAKE_MATCH_1}" STREQUAL "ENV") + set(utcve_actual_value "$ENV{${utcve_CMAKE_MATCH_2}}") + elseif("${utcve_CMAKE_MATCH_1}" STREQUAL "CACHE") + set(utcve_actual_value "$CACHE{${utcve_CMAKE_MATCH_2}}") + else() + _message(FATAL_ERROR "unexpected value for CMAKE_MATCH_1: ${utcve_CMAKE_MATCH_1}") + endif() + else() + set(utcve_actual_value "${${utcve_variable}}") + endif() + + if(NOT "${utcve_actual_value}" STREQUAL "${utcve_value}") + message(SEND_ERROR "${utcve_test} resulted in the wrong value for ${utcve_variable}; + expected: \"${utcve_value}\" + actual : \"${utcve_actual_value}\"") + set_has_error() + return() + endif() +endfunction() + +function(unit_test_check_variable_not_equal utcve_test utcve_variable utcve_value) + cmake_language(EVAL CODE "${utcve_test}") + if(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR) + unset_fatal_error() + set_has_error() + message(SEND_ERROR "${utcve_test} had an unexpected FATAL_ERROR; + expected: \"${utcve_value}\"") + message(SEND_ERROR "FATAL_ERROR: ${Z_VCPKG_UNIT_TEST_FATAL_ERROR}") + return() + endif() + + unit_test_match(utcve "${utcve_variable}" [[^(ENV|CACHE)\{(.*)\}$]]) + if(utcve_MATCHED) + if("${utcve_CMAKE_MATCH_1}" STREQUAL "ENV") + set(utcve_actual_value "$ENV{${utcve_CMAKE_MATCH_2}}") + elseif("${utcve_CMAKE_MATCH_1}" STREQUAL "CACHE") + set(utcve_actual_value "$CACHE{${utcve_CMAKE_MATCH_2}}") + else() + _message(FATAL_ERROR "unexpected value for CMAKE_MATCH_1: ${utcve_CMAKE_MATCH_1}") + endif() + else() + set(utcve_actual_value "${${utcve_variable}}") + endif() + + if("${utcve_actual_value}" STREQUAL "${utcve_value}") + message(SEND_ERROR "${utcve_test} failed to change ${utcve_variable}; + unchanged: \"${utcve_value}\"") + set_has_error() + return() + endif() +endfunction() + +function(unit_test_ensure_success utcve_test) + cmake_language(EVAL CODE "${utcve_test}") + if(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR) + set_has_error() + message(SEND_ERROR "${utcve_test} was expected to be successful.") + endif() + unset_fatal_error() +endfunction() +function(unit_test_ensure_fatal_error utcve_test) + cmake_language(EVAL CODE "${utcve_test}") + if(NOT Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR) + set_has_error() + message(SEND_ERROR "${utcve_test} was expected to be a FATAL_ERROR.") + endif() + unset_fatal_error() +endfunction() diff --git a/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/portfile.cmake b/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/portfile.cmake index 7617e1d895..06e58b130b 100644 --- a/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/portfile.cmake +++ b/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/portfile.cmake @@ -1,7 +1,162 @@ set(VCPKG_POLICY_EMPTY_PACKAGE enabled) +# For simplicity and speed, reusing source and build dirs +# - and the CMake cache - in multiple steps. +set(SOURCE_PATH "${CURRENT_BUILDTREES_DIR}/src/project") +file(REMOVE_RECURSE "${SOURCE_PATH}") + + +message(STATUS "Testing toolchain find_library search path setup") + +file(COPY "${CURRENT_PORT_DIR}/project/" DESTINATION "${SOURCE_PATH}") vcpkg_cmake_configure( - SOURCE_PATH "${CURRENT_PORT_DIR}/project" + SOURCE_PATH "${SOURCE_PATH}" DISABLE_PARALLEL_CONFIGURE # keep separate logs ) vcpkg_cmake_build() + + +message(STATUS "Testing toolchain capability VCPKG_LOCK_FIND_PACKAGE") + +set(VCPKG_BUILD_TYPE release) + +function(write_test_project TEST_CODE) + configure_file("${CURRENT_PORT_DIR}/project/vcpkg_lock_find_package/CMakeLists.txt.in" "${SOURCE_PATH}/CMakeLists.txt" @ONLY) +endfunction() + +include("${CURRENT_HOST_INSTALLED_DIR}/share/unit-test-cmake/test-macros.cmake") + +function(send_error summary) + set_has_error() + string(SHA1 id "${summary}") + string(SUBSTRING "${id}" 0 6 id) + set(log_base "${CURRENT_BUILDTREES_DIR}/test-${TARGET_TRIPLET}-${id}") + set(log_files "") + file(COPY_FILE "${CURRENT_BUILDTREES_DIR}/build-${TARGET_TRIPLET}-rel-out.log" "${log_base}-out.log") + file(COPY_FILE "${CURRENT_BUILDTREES_DIR}/build-${TARGET_TRIPLET}-rel-err.log" "${log_base}-err.log") + message(SEND_ERROR " Test failed:\n${summary}\n See logs for more information:\n ${log_base}-out.log\n ${log_base}-err.log\n") +endfunction() + +macro(unit_test_ensure_cmake_success utecs_test) + write_test_project("${utecs_test}") + cmake_language(EVAL CODE "vcpkg_cmake_build()") + if(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR) + send_error("${utecs_test} was expected to be successful.") + endif() + unset_fatal_error() +endmacro() + +macro(unit_test_ensure_cmake_error utece_test) + write_test_project("${utece_test}") + cmake_language(EVAL CODE "vcpkg_cmake_build()") + if(NOT Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR) + send_error("${utece_test} was expected to be successful.") + endif() + unset_fatal_error() +endmacro() + + +unit_test_ensure_cmake_error([[ + # No VCPKG_LOCK_FIND_PACKAGE + find_package(absentPackageX REQUIRED) +]]) +unit_test_ensure_cmake_success([[ + # No VCPKG_LOCK_FIND_PACKAGE + find_package(directPackageX REQUIRED) + find_package(transitivePackageX REQUIRED) + find_package(transitiveOptionalAbsentPackageX REQUIRED) + find_package(absentPackageX) + if(absentPackageX_FOUND) + message(FATAL_ERROR "absentPackageX_FOUND unexpectedly set to '${absentPackageX_FOUND}'.") + endif() +]]) + + +unit_test_ensure_cmake_success([[ + # Disabling an absent optional package + set(VCPKG_LOCK_FIND_PACKAGE_absentPackageX 0) + find_package(absentPackageX) +]]) + +unit_test_ensure_cmake_error([[ + # Disabling an absent required package + set(VCPKG_LOCK_FIND_PACKAGE_absentPackageX 0) + find_package(absentPackageX REQUIRED) +]]) + +unit_test_ensure_cmake_success([[ + # Disabling an available optional package + set(VCPKG_LOCK_FIND_PACKAGE_directPackageX 0) + find_package(directPackageX) + if(directPackageX_FOUND) + message(FATAL_ERROR "directPackageX_FOUND unexpectedly set to '${directPackageX_FOUND}'.") + endif() +]]) + +unit_test_ensure_cmake_error([[ + # Disabling an available required package + set(VCPKG_LOCK_FIND_PACKAGE_directPackageX 0) + find_package(directPackageX REQUIRED) +]]) + +unit_test_ensure_cmake_success([[ + # Core capability: a smart CMAKE_DISABLE_FIND_PACKAGE_ + # Disabling only the direct package + set(VCPKG_LOCK_FIND_PACKAGE_directPackageX 0) + find_package(directPackageX) # optional + find_package(transitivePackageX REQUIRED) +]]) + +unit_test_ensure_cmake_error([[ + # For reference: CMake default behavior which we want to avoid + set(CMAKE_DISABLE_FIND_PACKAGE_directPackageX 1) + find_package(transitivePackageX REQUIRED) +]]) + + +unit_test_ensure_cmake_error([[ + # Requiring an absent optional package + set(VCPKG_LOCK_FIND_PACKAGE_absentPackageX 1) + find_package(absentPackageX) +]]) + +unit_test_ensure_cmake_error([[ + # Requiring an absent required package + set(VCPKG_LOCK_FIND_PACKAGE_absentPackageX 1) + find_package(absentPackageX REQUIRED) +]]) + +unit_test_ensure_cmake_success([[ + # Requiring an available optional package + set(VCPKG_LOCK_FIND_PACKAGE_directPackageX 1) + find_package(directPackageX) + if(NOT DEFINED directPackageX_FOUND) + message(FATAL_ERROR "directPackageX_FOUND unexpectedly undefined.") + elseif(NOT directPackageX_FOUND) + message(FATAL_ERROR "directPackageX_FOUND unexpectedly set to '${directPackageX_FOUND}'.") + endif() +]]) + +unit_test_ensure_cmake_success([[ + # Requiring an available required package + set(VCPKG_LOCK_FIND_PACKAGE_directPackageX 1) + find_package(directPackageX REQUIRED) + if(NOT DEFINED directPackageX_FOUND) + message(FATAL_ERROR "directPackageX_FOUND unexpectedly undefined.") + elseif(NOT directPackageX_FOUND) + message(FATAL_ERROR "directPackageX_FOUND unexpectedly set to '${directPackageX_FOUND}'.") + endif() +]]) + +unit_test_ensure_cmake_success([[ + # Core capability: a smart CMAKE_REQUIRE_FIND_PACKAGE_ + # Requiring only the direct package + set(VCPKG_LOCK_FIND_PACKAGE_absentPackageX 1) + find_package(transitiveOptionalAbsentPackageX REQUIRED) +]]) + +unit_test_ensure_cmake_error([[ + # For reference: CMake default behavior which we want to avoid + set(CMAKE_REQUIRE_FIND_PACKAGE_absentPackageX 1) + find_package(transitiveOptionalAbsentPackageX REQUIRED) +]]) diff --git a/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/CMakeLists.txt.in b/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/CMakeLists.txt.in new file mode 100644 index 0000000000..c80e1da6be --- /dev/null +++ b/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/CMakeLists.txt.in @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.30) +project(cmake-toolchain-file-test C) + +set(CMAKE_FIND_DEBUG_MODE 1) +set(VCPKG_TRACE_FIND_PACKAGE 1) + +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER) +set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}/vcpkg_lock_find_package") + +@TEST_CODE@ diff --git a/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/directPackageXConfig.cmake b/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/directPackageXConfig.cmake new file mode 100644 index 0000000000..636bc1a8ab --- /dev/null +++ b/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/directPackageXConfig.cmake @@ -0,0 +1 @@ +# intentionally empty diff --git a/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/transitiveOptionalAbsentPackageXConfig.cmake b/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/transitiveOptionalAbsentPackageXConfig.cmake new file mode 100644 index 0000000000..c55e262f83 --- /dev/null +++ b/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/transitiveOptionalAbsentPackageXConfig.cmake @@ -0,0 +1,2 @@ +# Optional dependency! +find_package(absentPackageX) diff --git a/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/transitivePackageXConfig.cmake b/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/transitivePackageXConfig.cmake new file mode 100644 index 0000000000..2a47fac926 --- /dev/null +++ b/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/project/vcpkg_lock_find_package/transitivePackageXConfig.cmake @@ -0,0 +1,2 @@ +include(CMakeFindDependencyMacro) +find_dependency(directPackageX) diff --git a/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/vcpkg.json b/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/vcpkg.json index 0df0d542da..d754f71807 100644 --- a/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/vcpkg.json +++ b/scripts/test_ports/vcpkg-ci-cmake-toolchain-file/vcpkg.json @@ -5,6 +5,10 @@ "homepage": "https://github.com/microsoft/vcpkg", "license": "MIT", "dependencies": [ + { + "name": "unit-test-cmake", + "host": true + }, { "name": "vcpkg-cmake", "host": true