Skip to content
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

[vcpkg.cmake] guard against inf recursion. #23195

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion ports/zlib/vcpkg-cmake-wrapper.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ if(CMAKE_VERSION VERSION_LESS 3.4)
select_library_configurations(ZLIB)
unset(ZLIB_FOUND)
endif()
_find_package(${ARGS})

z_vcpkg_underlying_find_package(${ARGS})
4 changes: 3 additions & 1 deletion ports/zlib/vcpkg.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"name": "zlib",
"version": "1.2.12",
"port-version": 1,
"description": "A compression library",
"homepage": "https://www.zlib.net/"
"homepage": "https://www.zlib.net/",
"license": "Zlib"
}
98 changes: 84 additions & 14 deletions scripts/buildsystems/vcpkg.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,33 @@ function(z_vcpkg_add_fatal_error ERROR)
endif()
endfunction()

#[===[.md:
# z_vcpkg_get_command_underscores
Get the number of underscores/overrides the given `command` has.
If a `function|command` is overwritten it will be available as `_command`.
To chain these overrides it is required for the next override to override
`_command` instead `command` and so on for further overrides. This function
finds the last of the defined commands and returns the number of `_` needed
to savely chain commands

```cmake
z_vcpkg_get_command_underscores(<command> <out_underscores>)
```

#]===]
function(z_vcpkg_get_command_underscores command underscores_out)
set(underscores "")
while(COMMAND "_${underscores}${command}")
set(underscores "_${underscores}")
endwhile()
set("${underscores_out}" "${underscores}" PARENT_SCOPE)
endfunction()
set(Z_VCPKG_CHAIN_COMMANDS OFF)
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
set(Z_VCPKG_CHAIN_COMMANDS ON)
endif()


set(Z_VCPKG_CMAKE_REQUIRED_MINIMUM_VERSION "3.7.2")
if(CMAKE_VERSION VERSION_LESS Z_VCPKG_CMAKE_REQUIRED_MINIMUM_VERSION)
message(FATAL_ERROR "vcpkg.cmake requires at least CMake ${Z_VCPKG_CMAKE_REQUIRED_MINIMUM_VERSION}.")
Expand Down Expand Up @@ -562,10 +589,19 @@ endif()
cmake_policy(POP)

# Any policies applied to the below macros and functions appear to leak into consumers
set(Z_VCPKG_ADD_EXECUTABLE_US "")
if(Z_VCPKG_CHAIN_COMMANDS)
z_vcpkg_get_command_underscores("add_executable" Z_VCPKG_ADD_EXECUTABLE_US)
endif()
set(Z_VCPKG_ADD_EXECUTABLE "${Z_VCPKG_ADD_EXECUTABLE_US}add_executable" CACHE INTERNAL "")

function(add_executable)
function(${Z_VCPKG_ADD_EXECUTABLE})
z_vcpkg_function_arguments(ARGS)
_add_executable(${ARGS})
if(Z_VCPKG_CHAIN_COMMANDS)
cmake_language(CALL _${Z_VCPKG_ADD_EXECUTABLE} ${ARGS})
else()
_add_executable(${ARGS})
endif()
set(target_name "${ARGV0}")

list(FIND ARGV "IMPORTED" IMPORTED_IDX)
Expand Down Expand Up @@ -601,9 +637,19 @@ function(add_executable)
endif()
endfunction()

function(add_library)
set(Z_VCPKG_ADD_LIBRARY_US "")
if(Z_VCPKG_CHAIN_COMMANDS)
z_vcpkg_get_command_underscores("add_library" Z_VCPKG_ADD_LIBRARY_US)
endif()
set(Z_VCPKG_ADD_LIBRARY "${Z_VCPKG_ADD_LIBRARY_US}add_library" CACHE INTERNAL "")

function(${Z_VCPKG_ADD_LIBRARY})
z_vcpkg_function_arguments(ARGS)
_add_library(${ARGS})
if(Z_VCPKG_CHAIN_COMMANDS)
cmake_language(CALL _${Z_VCPKG_ADD_LIBRARY} ${ARGS})
else()
_add_library(${ARGS})
endif()
set(target_name "${ARGV0}")

list(FIND ARGS "IMPORTED" IMPORTED_IDX)
Expand Down Expand Up @@ -681,9 +727,18 @@ function(x_vcpkg_install_local_dependencies)
endfunction()

if(X_VCPKG_APPLOCAL_DEPS_INSTALL)
function(install)
set(Z_VCPKG_INSTALL_US "")
if(Z_VCPKG_CHAIN_COMMANDS)
z_vcpkg_get_command_underscores("install" Z_VCPKG_INSTALL_US)
endif()
set(Z_VCPKG_INSTALL "${Z_VCPKG_INSTALL_US}install" CACHE INTERNAL "")
function(${Z_VCPKG_INSTALL})
z_vcpkg_function_arguments(ARGS)
_install(${ARGS})
if(Z_VCPKG_CHAIN_COMMANDS)
cmake_language(CALL _${Z_VCPKG_INSTALL} ${ARGS})
else()
_install(${ARGS})
endif()

if(ARGV0 STREQUAL "TARGETS")
# Will contain the list of targets
Expand Down Expand Up @@ -731,10 +786,25 @@ endif()
if(NOT DEFINED VCPKG_OVERRIDE_FIND_PACKAGE_NAME)
set(VCPKG_OVERRIDE_FIND_PACKAGE_NAME find_package)
Neumann-A marked this conversation as resolved.
Show resolved Hide resolved
endif()
set(Z_VCPKG_FIND_PACKAGE_US "")
if(Z_VCPKG_CHAIN_COMMANDS)
z_vcpkg_get_command_underscores("${VCPKG_OVERRIDE_FIND_PACKAGE_NAME}" Z_VCPKG_FIND_PACKAGE_US)
endif()
set(Z_VCPKG_FIND_PACKAGE "${Z_VCPKG_FIND_PACKAGE_US}${VCPKG_OVERRIDE_FIND_PACKAGE_NAME}" CACHE INTERNAL "")

# Helper to be used in vcpkg-cmake-wrapper.cmake instead of _find_package
macro(z_vcpkg_underlying_find_package)
if(Z_VCPKG_CHAIN_COMMANDS)
cmake_language(CALL _${Z_VCPKG_FIND_PACKAGE} ${ARGS})
else()
_find_package(${ARGS})
endif()
endmacro()

# NOTE: this is not a function, which means that arguments _are not_ perfectly forwarded
# this is fine for `find_package`, since there are no usecases for `;` in arguments,
# so perfect forwarding is not important
macro("${VCPKG_OVERRIDE_FIND_PACKAGE_NAME}" z_vcpkg_find_package_package_name)
macro("${Z_VCPKG_FIND_PACKAGE}" z_vcpkg_find_package_package_name)
set(z_vcpkg_find_package_package_name "${z_vcpkg_find_package_package_name}")
set(z_vcpkg_find_package_ARGN "${ARGN}")
set(z_vcpkg_find_package_backup_vars)
Expand Down Expand Up @@ -781,16 +851,16 @@ macro("${VCPKG_OVERRIDE_FIND_PACKAGE_NAME}" z_vcpkg_find_package_package_name)
else()
set(Boost_COMPILER "-vc140")
endif()
_find_package("${z_vcpkg_find_package_package_name}" ${z_vcpkg_find_package_ARGN})
z_vcpkg_underlying_find_package("${z_vcpkg_find_package_package_name}" ${z_vcpkg_find_package_ARGN})
elseif(z_vcpkg_find_package_package_name STREQUAL "ICU" AND EXISTS "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include/unicode/utf.h")
list(FIND z_vcpkg_find_package_ARGN "COMPONENTS" z_vcpkg_find_package_COMPONENTS_IDX)
if(NOT z_vcpkg_find_package_COMPONENTS_IDX EQUAL -1)
_find_package("${z_vcpkg_find_package_package_name}" ${z_vcpkg_find_package_ARGN} COMPONENTS data)
z_vcpkg_underlying_find_package("${z_vcpkg_find_package_package_name}" ${z_vcpkg_find_package_ARGN} COMPONENTS data)
else()
_find_package("${z_vcpkg_find_package_package_name}" ${z_vcpkg_find_package_ARGN})
z_vcpkg_underlying_find_package("${z_vcpkg_find_package_package_name}" ${z_vcpkg_find_package_ARGN})
endif()
elseif(z_vcpkg_find_package_package_name STREQUAL "GSL" AND EXISTS "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include/gsl")
_find_package("${z_vcpkg_find_package_package_name}" ${z_vcpkg_find_package_ARGN})
z_vcpkg_underlying_find_package("${z_vcpkg_find_package_package_name}" ${z_vcpkg_find_package_ARGN})
if(GSL_FOUND AND TARGET GSL::gsl)
set_property( TARGET GSL::gslcblas APPEND PROPERTY IMPORTED_CONFIGURATIONS Release )
set_property( TARGET GSL::gsl APPEND PROPERTY IMPORTED_CONFIGURATIONS Release )
Expand All @@ -802,7 +872,7 @@ macro("${VCPKG_OVERRIDE_FIND_PACKAGE_NAME}" z_vcpkg_find_package_package_name)
endif()
endif()
elseif("${z_vcpkg_find_package_package_name}" STREQUAL "CURL" AND EXISTS "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include/curl")
_find_package("${z_vcpkg_find_package_package_name}" ${z_vcpkg_find_package_ARGN})
z_vcpkg_underlying_find_package("${z_vcpkg_find_package_package_name}" ${z_vcpkg_find_package_ARGN})
if(CURL_FOUND)
if(EXISTS "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/nghttp2.lib")
list(APPEND CURL_LIBRARIES
Expand All @@ -811,9 +881,9 @@ macro("${VCPKG_OVERRIDE_FIND_PACKAGE_NAME}" z_vcpkg_find_package_package_name)
endif()
endif()
elseif("${z_vcpkg_find_package_lowercase_package_name}" STREQUAL "grpc" AND EXISTS "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/grpc")
_find_package(gRPC ${z_vcpkg_find_package_ARGN})
z_vcpkg_underlying_find_package(gRPC ${z_vcpkg_find_package_ARGN})
else()
_find_package("${z_vcpkg_find_package_package_name}" ${z_vcpkg_find_package_ARGN})
z_vcpkg_underlying_find_package("${z_vcpkg_find_package_package_name}" ${z_vcpkg_find_package_ARGN})
endif()

foreach(z_vcpkg_find_package_backup_var IN LISTS z_vcpkg_find_package_backup_vars)
Expand Down
3 changes: 3 additions & 0 deletions scripts/test_ports/inf-recursion-test/portfile.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
set(VCPKG_POLICY_EMPTY_PACKAGE enabled)

vcpkg_cmake_configure(SOURCE_PATH "${CURRENT_PORT_DIR}/project")
20 changes: 20 additions & 0 deletions scripts/test_ports/inf-recursion-test/project/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.18)

# vcpkg can only guard against overrides before the first project() call!
macro(find_package)
_find_package(${ARGV})
endmacro()

function(add_library)
_add_library(${ARGV})
endfunction()

function(add_executable)
_add_executable(${ARGV})
endfunction()

project(inf-recursion-test)

find_package(ZLIB REQUIRED)
add_library(mylib lib.cpp)
add_executable(myexe main.cpp)
1 change: 1 addition & 0 deletions scripts/test_ports/inf-recursion-test/project/lib.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
struct MyClass {};
5 changes: 5 additions & 0 deletions scripts/test_ports/inf-recursion-test/project/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <cstdio>
int main() {
std::puts("Hello World!");
return 0;
}
13 changes: 13 additions & 0 deletions scripts/test_ports/inf-recursion-test/vcpkg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "inf-recursion-test",
"version-date": "2022-02-20",
"description": "Test port to verify if vcpkg.cmake is robust against command recursions",
"license" : "MIT",
"dependencies" : [
{
"name": "vcpkg-cmake",
"host": true
},
"zlib"
]
}
2 changes: 1 addition & 1 deletion versions/baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -7630,7 +7630,7 @@
},
"zlib": {
"baseline": "1.2.12",
"port-version": 0
"port-version": 1
},
"zlib-ng": {
"baseline": "2.0.5",
Expand Down
5 changes: 5 additions & 0 deletions versions/z-/zlib.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
{
"versions": [
{
"git-tree": "8ae60d9b19188369614811dbd5a19d6994055e0f",
"version": "1.2.12",
"port-version": 1
},
{
"git-tree": "9c4edb1fabbd87dd236a200ba55eaf241cd8c8d0",
"version": "1.2.12",
Expand Down