aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authornicole mazzuca <83086508+strega-nil-ms@users.noreply.github.com>2021-07-20 12:24:58 -0500
committerGitHub <noreply@github.com>2021-07-20 10:24:58 -0700
commit0e1dc121856eef84bf1852134e548bf9898dabac (patch)
tree4bbae150d61121c81c33a2f4b7b92063e4db3060 /scripts
parentb67fab9861239e33b722b9a44f5c96dec6ca807e (diff)
downloadvcpkg-0e1dc121856eef84bf1852134e548bf9898dabac.tar.gz
vcpkg-0e1dc121856eef84bf1852134e548bf9898dabac.zip
[rollup] Rollup PR 2021-07-16 (#19001)
* [rollup:2021-07-16 1/7] PR #18201 (@JackBoosY) [vcpkg-cmake] Add check for unused cmake variables * [rollup:2021-07-16 2/7] PR #18397 (@strega-nil) [vcpkg_list] add new function * [rollup:2021-07-16 3/7] PR #18782 (@strega-nil) [scripts-audit] vcpkg_build_ninja * [rollup:2021-07-16 4/7] PR #18784 (@strega-nil) [scripts-audit] vcpkg_minimum_required * [rollup:2021-07-16 5/7] PR #18785 (@strega-nil) [scripts-audit] vcpkg_replace_string * [rollup:2021-07-16 6/7] PR #18786 (@strega-nil) [scripts-audit] windows scripts * [rollup:2021-07-16 7/7] PR #18945 (@strega-nil) [many ports] remove deprecated vcpkg_check_features call [1/5] Co-authored-by: nicole mazzuca <mazzucan@outlook.com> Co-authored-by: PhoebeHui <20694052+PhoebeHui@users.noreply.github.com>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/buildsystems/vcpkg.cmake7
-rw-r--r--scripts/cmake/vcpkg_build_ninja.cmake33
-rw-r--r--scripts/cmake/vcpkg_configure_cmake.cmake64
-rw-r--r--scripts/cmake/vcpkg_get_program_files_platform_bitness.cmake13
-rw-r--r--scripts/cmake/vcpkg_get_windows_sdk.cmake10
-rw-r--r--scripts/cmake/vcpkg_internal_get_cmake_vars.cmake1
-rw-r--r--scripts/cmake/vcpkg_list.cmake257
-rw-r--r--scripts/cmake/vcpkg_minimum_required.cmake20
-rw-r--r--scripts/cmake/vcpkg_replace_string.cmake11
-rw-r--r--scripts/cmake/z_vcpkg_function_arguments.cmake16
-rw-r--r--scripts/ports.cmake1
-rw-r--r--scripts/test_ports/unit-test-cmake/portfile.cmake73
-rw-r--r--scripts/test_ports/unit-test-cmake/test-vcpkg_list.cmake813
-rw-r--r--scripts/test_ports/unit-test-cmake/test-z_vcpkg_function_arguments.cmake63
-rw-r--r--scripts/test_ports/unit-test-cmake/vcpkg.json18
15 files changed, 1352 insertions, 48 deletions
diff --git a/scripts/buildsystems/vcpkg.cmake b/scripts/buildsystems/vcpkg.cmake
index 8ab287852..ff0873457 100644
--- a/scripts/buildsystems/vcpkg.cmake
+++ b/scripts/buildsystems/vcpkg.cmake
@@ -153,7 +153,7 @@ macro(z_vcpkg_function_arguments OUT_VAR)
message(FATAL_ERROR "z_vcpkg_function_arguments: invalid arguments (${ARGV})")
endif()
- set("${OUT_VAR}")
+ set("${OUT_VAR}" "")
# this allows us to get the value of the enclosing function's ARGC
set(z_vcpkg_function_arguments_ARGC_NAME "ARGC")
@@ -164,8 +164,11 @@ macro(z_vcpkg_function_arguments OUT_VAR)
if(NOT z_vcpkg_function_arguments_LAST_ARG LESS z_vcpkg_function_arguments_FIRST_ARG)
foreach(z_vcpkg_function_arguments_N RANGE "${z_vcpkg_function_arguments_FIRST_ARG}" "${z_vcpkg_function_arguments_LAST_ARG}")
string(REPLACE ";" "\\;" z_vcpkg_function_arguments_ESCAPED_ARG "${ARGV${z_vcpkg_function_arguments_N}}")
- list(APPEND "${OUT_VAR}" "${z_vcpkg_function_arguments_ESCAPED_ARG}")
+ # adds an extra `;` on the first time through
+ set("${OUT_VAR}" "${${OUT_VAR}};${z_vcpkg_function_arguments_ESCAPED_ARG}")
endforeach()
+ # remove leading `;`
+ string(SUBSTRING "${${OUT_VAR}}" 1 -1 "${OUT_VAR}")
endif()
endmacro()
diff --git a/scripts/cmake/vcpkg_build_ninja.cmake b/scripts/cmake/vcpkg_build_ninja.cmake
index 2c9276e63..5a0a1755f 100644
--- a/scripts/cmake/vcpkg_build_ninja.cmake
+++ b/scripts/cmake/vcpkg_build_ninja.cmake
@@ -15,26 +15,33 @@ vcpkg_build_ninja(
Only build the specified targets.
#]===]
+function(z_vcpkg_build_ninja_build config targets)
+ message(STATUS "Building (${config})...")
+ vcpkg_execute_build_process(
+ COMMAND "${NINJA}" -C "${CURRENT_BUILDTREES_DIR}/${config}" ${targets}
+ WORKING_DIRECTORY "${SOURCE_PATH}"
+ LOGNAME "build-${config}"
+ )
+endfunction()
+
+
function(vcpkg_build_ninja)
- # parse parameters such that semicolons in options arguments to COMMAND don't get erased
- cmake_parse_arguments(PARSE_ARGV 0 _vbn "" "" "TARGETS")
+ cmake_parse_arguments(PARSE_ARGV 0 arg "" "" "TARGETS")
- vcpkg_find_acquire_program(NINJA)
+ if(DEFINED arg_UNPARSED_ARGUMENTS)
+ message(WARNING "${CMAKE_CURRENT_FUNCTION} was passed extra arguments: ${arg_UNPARSED_ARGUMENTS}")
+ endif()
+ if(NOT DEFINED arg_TARGETS)
+ set(arg_TARGETS "")
+ endif()
- function(build CONFIG)
- message(STATUS "Building (${CONFIG})...")
- vcpkg_execute_build_process(
- COMMAND "${NINJA}" -C "${CURRENT_BUILDTREES_DIR}/${CONFIG}" ${_vbn_TARGETS}
- WORKING_DIRECTORY "${SOURCE_PATH}"
- LOGNAME build-${CONFIG}
- )
- endfunction()
+ vcpkg_find_acquire_program(NINJA)
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
- build(${TARGET_TRIPLET}-dbg)
+ z_vcpkg_build_ninja_build("${TARGET_TRIPLET}-dbg" "${arg_TARGETS}")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
- build(${TARGET_TRIPLET}-rel)
+ z_vcpkg_build_ninja_build("${TARGET_TRIPLET}-rel" "${arg_TARGETS}")
endif()
endfunction()
diff --git a/scripts/cmake/vcpkg_configure_cmake.cmake b/scripts/cmake/vcpkg_configure_cmake.cmake
index 1eb50e852..bce3f6af5 100644
--- a/scripts/cmake/vcpkg_configure_cmake.cmake
+++ b/scripts/cmake/vcpkg_configure_cmake.cmake
@@ -15,6 +15,7 @@ vcpkg_configure_cmake(
[OPTIONS <-DUSE_THIS_IN_ALL_BUILDS=1>...]
[OPTIONS_RELEASE <-DOPTIMIZE=1>...]
[OPTIONS_DEBUG <-DDEBUGGABLE=1>...]
+ [MAYBE_UNUSED_VARIABLES <option-name>...]
)
```
@@ -53,6 +54,9 @@ Additional options passed to CMake during the Release configuration. These are i
### OPTIONS_DEBUG
Additional options passed to CMake during the Debug configuration. These are in addition to `OPTIONS`.
+### MAYBE_UNUSED_VARIABLES
+Any CMake variables which are explicitly passed in, but which may not be used on all platforms.
+
### LOGNAME
Name of the log to write the output of the configure call to.
@@ -73,9 +77,9 @@ function(vcpkg_configure_cmake)
endif()
cmake_parse_arguments(PARSE_ARGV 0 arg
- "PREFER_NINJA;DISABLE_PARALLEL_CONFIGURE;NO_CHARSET_FLAG"
+ "PREFER_NINJA;DISABLE_PARALLEL_CONFIGURE;NO_CHARSET_FLAG;Z_VCPKG_IGNORE_UNUSED_VARIABLES"
"SOURCE_PATH;GENERATOR;LOGNAME"
- "OPTIONS;OPTIONS_DEBUG;OPTIONS_RELEASE"
+ "OPTIONS;OPTIONS_DEBUG;OPTIONS_RELEASE;MAYBE_UNUSED_VARIABLES"
)
if(NOT VCPKG_PLATFORM_TOOLSET)
@@ -87,6 +91,18 @@ function(vcpkg_configure_cmake)
set(arg_LOGNAME config-${TARGET_TRIPLET})
endif()
+ set(manually_specified_variables "")
+ if(NOT arg_Z_VCPKG_IGNORE_UNUSED_VARIABLES)
+ foreach(option IN LISTS arg_OPTIONS arg_OPTIONS_RELEASE arg_OPTIONS_DEBUG)
+ if(option MATCHES "^-D([^:=]*)[:=]")
+ list(APPEND manually_specified_variables "${CMAKE_MATCH_1}")
+ endif()
+ endforeach()
+ list(REMOVE_DUPLICATES manually_specified_variables)
+ list(REMOVE_ITEM manually_specified_variables ${arg_MAYBE_UNUSED_VARIABLES})
+ debug_message("manually specified variables: ${manually_specified_variables}")
+ endif()
+
if(CMAKE_HOST_WIN32)
if(DEFINED ENV{PROCESSOR_ARCHITEW6432})
set(arg_HOST_ARCHITECTURE $ENV{PROCESSOR_ARCHITEW6432})
@@ -326,6 +342,10 @@ function(vcpkg_configure_cmake)
WORKING_DIRECTORY ${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/vcpkg-parallel-configure
LOGNAME ${arg_LOGNAME}
)
+
+ list(APPEND config_logs
+ "${CURRENT_BUILDTREES_DIR}/${arg_LOGNAME}-out.log"
+ "${CURRENT_BUILDTREES_DIR}/${arg_LOGNAME}-err.log")
else()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
message(STATUS "Configuring ${TARGET_TRIPLET}-dbg")
@@ -335,6 +355,9 @@ function(vcpkg_configure_cmake)
WORKING_DIRECTORY ${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg
LOGNAME ${arg_LOGNAME}-dbg
)
+ list(APPEND config_logs
+ "${CURRENT_BUILDTREES_DIR}/${arg_LOGNAME}-dbg-out.log"
+ "${CURRENT_BUILDTREES_DIR}/${arg_LOGNAME}-dbg-err.log")
endif()
if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
@@ -345,7 +368,44 @@ function(vcpkg_configure_cmake)
WORKING_DIRECTORY ${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel
LOGNAME ${arg_LOGNAME}-rel
)
+ list(APPEND config_logs
+ "${CURRENT_BUILDTREES_DIR}/${arg_LOGNAME}-rel-out.log"
+ "${CURRENT_BUILDTREES_DIR}/${arg_LOGNAME}-rel-err.log")
+ endif()
+ endif()
+
+ # Check unused variables
+ set(all_unused_variables)
+ foreach(config_log IN LISTS config_logs)
+ if (NOT EXISTS "${config_log}")
+ continue()
+ endif()
+ file(READ "${config_log}" log_contents)
+ debug_message("Reading configure log ${config_log}...")
+ if(NOT log_contents MATCHES "Manually-specified variables were not used by the project:\n\n(( [^\n]*\n)*)")
+ continue()
endif()
+ string(STRIP "${CMAKE_MATCH_1}" unused_variables) # remove leading ` ` and trailing `\n`
+ string(REPLACE "\n " ";" unused_variables "${unused_variables}")
+ debug_message("unused variables: ${unused_variables}")
+
+ foreach(unused_variable IN LISTS unused_variables)
+ if(unused_variable IN_LIST manually_specified_variables)
+ debug_message("manually specified unused variable: ${unused_variable}")
+ list(APPEND all_unused_variables "${unused_variable}")
+ else()
+ debug_message("unused variable (not manually specified): ${unused_variable}")
+ endif()
+ endforeach()
+ endforeach()
+
+ if(DEFINED all_unused_variables)
+ list(REMOVE_DUPLICATES all_unused_variables)
+ list(JOIN all_unused_variables "\n " all_unused_variables)
+ message(WARNING "The following variables are not used in CMakeLists.txt:
+ ${all_unused_variables}
+Please recheck them and remove the unnecessary options from the `vcpkg_configure_cmake` call.
+If these options should still be passed for whatever reason, please use the `MAYBE_UNUSED_VARIABLES` argument.")
endif()
set(Z_VCPKG_CMAKE_GENERATOR "${GENERATOR}" PARENT_SCOPE)
diff --git a/scripts/cmake/vcpkg_get_program_files_platform_bitness.cmake b/scripts/cmake/vcpkg_get_program_files_platform_bitness.cmake
index 7e3a5af52..b40b24c42 100644
--- a/scripts/cmake/vcpkg_get_program_files_platform_bitness.cmake
+++ b/scripts/cmake/vcpkg_get_program_files_platform_bitness.cmake
@@ -11,13 +11,10 @@ vcpkg_get_program_files_platform_bitness(<variable>)
```
#]===]
-function(vcpkg_get_program_files_platform_bitness ret)
-
- set(ret_temp $ENV{ProgramW6432})
- if (NOT DEFINED ret_temp)
- set(ret_temp $ENV{PROGRAMFILES})
+function(vcpkg_get_program_files_platform_bitness out_var)
+ if(DEFINED ENV{ProgramW6432})
+ set("${out_var}" "$ENV{ProgramW6432}" PARENT_SCOPE)
+ else()
+ set("${out_var}" "$ENV{PROGRAMFILES}" PARENT_SCOPE)
endif()
-
- set(${ret} ${ret_temp} PARENT_SCOPE)
-
endfunction()
diff --git a/scripts/cmake/vcpkg_get_windows_sdk.cmake b/scripts/cmake/vcpkg_get_windows_sdk.cmake
index f16d4f53e..0a80d4c76 100644
--- a/scripts/cmake/vcpkg_get_windows_sdk.cmake
+++ b/scripts/cmake/vcpkg_get_windows_sdk.cmake
@@ -9,8 +9,10 @@ vcpkg_get_windows_sdk(<variable>)
```
#]===]
-function(vcpkg_get_windows_sdk ret)
- set(WINDOWS_SDK $ENV{WindowsSDKVersion})
- string(REPLACE "\\" "" WINDOWS_SDK "${WINDOWS_SDK}")
- set(${ret} ${WINDOWS_SDK} PARENT_SCOPE)
+function(vcpkg_get_windows_sdk out_var)
+ if("$ENV{WindowsSDKVersion}" MATCHES [[^([0-9.]*)\\?$]])
+ set("${out_var}" "${CMAKE_MATCH_1}" PARENT_SCOPE)
+ else()
+ message(FATAL_ERROR "Unexpected format for ENV{WindowsSDKVersion} ($ENV{WindowsSDKVersion})")
+ endif()
endfunction()
diff --git a/scripts/cmake/vcpkg_internal_get_cmake_vars.cmake b/scripts/cmake/vcpkg_internal_get_cmake_vars.cmake
index 6c705ae8f..030d74120 100644
--- a/scripts/cmake/vcpkg_internal_get_cmake_vars.cmake
+++ b/scripts/cmake/vcpkg_internal_get_cmake_vars.cmake
@@ -53,6 +53,7 @@ function(vcpkg_internal_get_cmake_vars)
OPTIONS_RELEASE "-DVCPKG_OUTPUT_FILE:PATH=${CURRENT_BUILDTREES_DIR}/cmake-vars-${TARGET_TRIPLET}-rel.cmake.log"
PREFER_NINJA
LOGNAME get-cmake-vars-${TARGET_TRIPLET}
+ Z_VCPKG_IGNORE_UNUSED_VARIABLES
)
set(_include_string)
diff --git a/scripts/cmake/vcpkg_list.cmake b/scripts/cmake/vcpkg_list.cmake
new file mode 100644
index 000000000..74523dc62
--- /dev/null
+++ b/scripts/cmake/vcpkg_list.cmake
@@ -0,0 +1,257 @@
+#[===[.md:
+# vcpkg_list
+
+A replacement for CMake's `list()` function, which correctly handles elements
+with internal semicolons (in other words, escaped semicolons).
+Use `vcpkg_list()` instead of `list()` whenever possible.
+
+```cmake
+vcpkg_list(SET <out-var> [<element>...])
+vcpkg_list(<COMMAND> <list-var> [<other-arguments>...])
+```
+
+In addition to all of the commands from `list()`, `vcpkg_list` adds
+a `vcpkg_list(SET)` command.
+This command takes its arguments, escapes them, and then concatenates
+them into a list; this should be used instead of `set()` for setting any
+list variable.
+
+Otherwise, the `vcpkg_list()` function is the same as the built-in
+`list()` function, with the following restrictions:
+
+- `GET`, `REMOVE_ITEM`, and `REMOVE_AT` support only one index/value
+- `POP_BACK` and `POP_FRONT` do not support getting the value into
+ another out variable. Use C++ style `GET` then `POP_(BACK|FRONT)`.
+- `FILTER` and `TRANSFORM` are unsupported.
+
+See the [CMake documentation for `list()`](https://cmake.org/cmake/help/latest/command/list.html)
+for more information.
+
+## Notes: Some Weirdnesses
+
+The most major weirdness is due to `""` pulling double-duty as "list of zero elements",
+and "list of one element, which is empty". `vcpkg_list` always uses the former understanding.
+This can cause weird behavior, for example:
+
+```cmake
+set(lst "")
+vcpkg_list(APPEND lst "" "")
+# lst = ";"
+```
+
+This is because you're appending two elements to the empty list.
+One very weird behavior that comes out of this would be:
+
+```cmake
+set(lst "")
+vcpkg_list(APPEND lst "")
+# lst = ""
+```
+
+since `""` is the empty list, we append the empty element and end up with a list
+of one element, which is empty. This does not happen for non-empty lists;
+for example:
+
+```cmake
+set(lst "a")
+vcpkg_list(APPEND lst "")
+# lst = "a;"
+```
+
+only the empty list has this odd behavior.
+
+## Examples
+
+### Creating a list
+
+```cmake
+vcpkg_list(SET foo_param)
+if(DEFINED arg_FOO)
+ vcpkg_list(SET foo_param FOO "${arg_FOO}")
+endif()
+```
+
+### Appending to a list
+
+```cmake
+set(OPTIONS -DFOO=BAR)
+if(VCPKG_TARGET_IS_WINDOWS)
+ vcpkg_list(APPEND OPTIONS "-DOS=WINDOWS;FOO")
+endif()
+```
+
+### Popping the end off a list
+
+```cmake
+if(NOT list STREQUAL "")
+ vcpkg_list(GET list end -1)
+ vcpkg_list(POP_BACK list)
+endif()
+```
+#]===]
+
+macro(z_vcpkg_list_escape_once_more lst)
+ string(REPLACE [[\;]] [[\\;]] "${lst}" "${${lst}}")
+endmacro()
+
+function(vcpkg_list)
+ # NOTE: as this function replaces an existing CMake command,
+ # it does not use cmake_parse_arguments
+
+ # vcpkg_list(<operation> <list_var> ...)
+ # A0 A1
+
+ if(ARGC LESS "2")
+ message(FATAL_ERROR "vcpkg_list requires at least two arguments.")
+ endif()
+
+ if(ARGV1 MATCHES "^ARGV([0-9]*)$|^ARG[CN]$|^CMAKE_CURRENT_FUNCTION")
+ message(FATAL_ERROR "vcpkg_list does not support the list_var being ${ARGV1}.
+ Please use a different variable name.")
+ endif()
+
+ set(list "${${ARGV1}}")
+ set(operation "${ARGV0}")
+ set(list_var "${ARGV1}")
+
+ if(operation STREQUAL "SET")
+ z_vcpkg_function_arguments(args 2)
+ set("${list_var}" "${args}" PARENT_SCOPE)
+ return()
+ endif()
+
+ # Normal reading functions
+ if(operation STREQUAL "LENGTH")
+ # vcpkg_list(LENGTH <list-var> <out-var>)
+ # A0 A1 A2
+ if(NOT ARGC EQUAL "3")
+ message(FATAL_ERROR "vcpkg_list sub-command ${operation} requires two arguments.")
+ endif()
+ list(LENGTH list out)
+ set("${ARGV2}" "${out}" PARENT_SCOPE)
+ return()
+ endif()
+ if(operation MATCHES "^(GET|JOIN|FIND)$")
+ # vcpkg_list(<operation> <list-var> <arg> <out-var>)
+ # A0 A1 A2 A3
+ if(NOT ARGC EQUAL "4")
+ message(FATAL_ERROR "vcpkg_list sub-command ${operation} requires three arguments.")
+ endif()
+ if(operation STREQUAL "GET")
+ list(LENGTH list length)
+ if(length EQUAL "0")
+ message(FATAL_ERROR "vcpkg_list GET given empty list")
+ elseif(ARGV2 GREATER_EQUAL length OR ARGV2 LESS "-${length}")
+ message(FATAL_ERROR "vcpkg_list index: ${ARGV2} is not in range")
+ endif()
+ endif()
+ list("${operation}" list "${ARGV2}" out)
+ set("${ARGV3}" "${out}" PARENT_SCOPE)
+ return()
+ endif()
+ if(operation STREQUAL "SUBLIST")
+ # vcpkg_list(SUBLIST <list-var> <begin> <length> <out-var>)
+ # A0 A1 A2 A3 A4
+ if(NOT ARGC EQUAL "5")
+ message(FATAL_ERROR "vcpkg_list sub-command SUBLIST requires four arguments.")
+ endif()
+ list(LENGTH list length)
+ if(ARGV2 LESS "0" OR (ARGV2 GREATER_EQUAL length AND NOT ARGV2 EQUAL "0"))
+ message(FATAL_ERROR "vcpkg_list begin index: ${ARGV2} is out of range")
+ endif()
+ z_vcpkg_list_escape_once_more(list)
+ list(SUBLIST list "${ARGV2}" "${ARGV3}" out)
+ set("${ARGV4}" "${out}" PARENT_SCOPE)
+ return()
+ endif()
+
+ # modification functions
+
+ if(operation MATCHES "^(APPEND|PREPEND)$")
+ # vcpkg_list(<operation> <list> [<element>...])
+ # A0 A1 A2...
+
+ # if ARGC <= 2, then we don't have to do anything
+ if(ARGC GREATER 2)
+ z_vcpkg_function_arguments(args 2)
+ if(list STREQUAL "")
+ set("${list_var}" "${args}" PARENT_SCOPE)
+ elseif(operation STREQUAL "APPEND")
+ set("${list_var}" "${list};${args}" PARENT_SCOPE)
+ else()
+ set("${list_var}" "${args};${list}" PARENT_SCOPE)
+ endif()
+ endif()
+ return()
+ endif()
+ if(operation STREQUAL "INSERT")
+ # vcpkg_list(INSERT <list> <index> [<element>...])
+ # A0 A1 A2 A3...
+
+ list(LENGTH list length)
+ if(ARGV2 LESS "-{$length}" OR ARGV2 GREATER length)
+ message(FATAL_ERROR "vcpkg_list index: ${ARGV2} out of range")
+ endif()
+ if(ARGC GREATER 3)
+ # list(LENGTH) is one of the few subcommands that's fine
+ list(LENGTH list length)
+ if(ARGV2 LESS "0")
+ math(EXPR ARGV2 "${length} + ${ARGV2}")
+ endif()
+ if(ARGV2 LESS "0" OR ARGV2 GREATER length)
+ message(FATAL_ERROR "list index: ${ARGV2} out of range (-${length}, ${length})")
+ endif()
+
+ z_vcpkg_function_arguments(args 3)
+ if(list STREQUAL "")
+ set("${list_var}" "${args}" PARENT_SCOPE)
+ elseif(ARGV2 EQUAL "0")
+ set("${list_var}" "${args};${list}" PARENT_SCOPE)
+ elseif(ARGV2 EQUAL length)
+ set("${list_var}" "${list};${args}" PARENT_SCOPE)
+ else()
+ vcpkg_list(SUBLIST list 0 "${ARGV2}" list_start)
+ vcpkg_list(SUBLIST list "${ARGV2}" -1 list_end)
+ set("${list_var}" "${list_start};${args};${list_end}" PARENT_SCOPE)
+ endif()
+ elseif(ARGC LESS 3)
+ message(FATAL_ERROR "vcpkg_list sub-command INSERT requires at least two arguments.")
+ endif()
+ return()
+ endif()
+
+ if(operation MATCHES "^(POP_BACK|POP_FRONT|REVERSE|REMOVE_DUPLICATES)$")
+ # vcpkg_list(<operation> <list>)
+ # A0 A1
+ if(NOT ARGC EQUAL 2)
+ message(FATAL_ERROR "vcpkg_list sub-command ${operation} requires one argument.")
+ endif()
+ z_vcpkg_list_escape_once_more(list)
+ list("${operation}" list)
+ set("${list_var}" "${list}" PARENT_SCOPE)
+ return()
+ endif()
+
+ if(operation MATCHES "^(REMOVE_AT|REMOVE_ITEM)$")
+ # vcpkg_list(<operation> <list> <index-or-item>)
+ # A0 A1 A2
+ if(NOT ARGC EQUAL 3)
+ message(FATAL_ERROR "vcpkg_list sub-command ${operation} requires two arguments.")
+ endif()
+ if(operation STREQUAL "REMOVE_AT")
+ list(LENGTH list length)
+ if(ARGV2 GREATER_EQUAL length OR ARGV2 LESS "-${length}")
+ message(FATAL_ERROR "vcpkg_list index: ${ARGV2} out of range")
+ endif()
+ endif()
+
+ z_vcpkg_list_escape_once_more(list)
+ string(REPLACE [[;]] [[\;]] ARGV2 "${ARGV2}")
+
+ list("${operation}" list "${ARGV2}")
+ set("${list_var}" "${list}" PARENT_SCOPE)
+ return()
+ endif()
+
+ message(FATAL_ERROR "vcpkg_list sub-command ${operation} is not yet implemented.")
+endfunction()
diff --git a/scripts/cmake/vcpkg_minimum_required.cmake b/scripts/cmake/vcpkg_minimum_required.cmake
index 202935b89..44777875e 100644
--- a/scripts/cmake/vcpkg_minimum_required.cmake
+++ b/scripts/cmake/vcpkg_minimum_required.cmake
@@ -14,7 +14,7 @@ The date-version to check against.
#]===]
function(vcpkg_minimum_required)
- cmake_parse_arguments(PARSE_ARGV 0 _vcpkg "" "VERSION" "")
+ cmake_parse_arguments(PARSE_ARGV 0 arg "" "VERSION" "")
if (NOT DEFINED VCPKG_BASE_VERSION)
message(FATAL_ERROR
"Your vcpkg executable is outdated and is not compatible with the current CMake scripts. "
@@ -22,27 +22,27 @@ function(vcpkg_minimum_required)
)
endif()
- set(_vcpkg_date_regex "^[12][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9]$")
- if (NOT VCPKG_BASE_VERSION MATCHES "${_vcpkg_date_regex}")
+ set(vcpkg_date_regex "^[12][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9]$")
+ if (NOT VCPKG_BASE_VERSION MATCHES "${vcpkg_date_regex}")
message(FATAL_ERROR
- "vcpkg internal failure; \${VCPKG_BASE_VERSION} (${VCPKG_BASE_VERSION}) was not a valid date."
+ "vcpkg internal failure; VCPKG_BASE_VERSION (${VCPKG_BASE_VERSION}) was not a valid date."
)
endif()
- if (NOT _vcpkg_VERSION MATCHES "${_vcpkg_date_regex}")
+ if (NOT arg_VERSION MATCHES "${vcpkg_date_regex}")
message(FATAL_ERROR
"VERSION parameter to vcpkg_minimum_required was not a valid date. "
- "Comparing with vcpkg tool version ${_vcpkg_matched_base_version}"
+ "Comparing with vcpkg tool version ${VCPKG_BASE_VERSION}"
)
endif()
- string(REPLACE "-" "." _VCPKG_BASE_VERSION_as_dotted "${VCPKG_BASE_VERSION}")
- string(REPLACE "-" "." _vcpkg_VERSION_as_dotted "${_vcpkg_VERSION}")
+ string(REPLACE "-" "." VCPKG_BASE_VERSION_as_dotted "${VCPKG_BASE_VERSION}")
+ string(REPLACE "-" "." arg_VERSION_as_dotted "${arg_VERSION}")
- if (_VCPKG_BASE_VERSION_as_dotted VERSION_LESS _vcpkg_VERSION_as_dotted)
+ if (VCPKG_BASE_VERSION_as_dotted VERSION_LESS vcpkg_VERSION_as_dotted)
message(FATAL_ERROR
"Your vcpkg executable is from ${VCPKG_BASE_VERSION} which is older than required by the caller "
- "of vcpkg_minimum_required (${_vcpkg_VERSION}). "
+ "of vcpkg_minimum_required(VERSION ${arg_VERSION}). "
"Please re-acquire vcpkg by running bootstrap-vcpkg."
)
endif()
diff --git a/scripts/cmake/vcpkg_replace_string.cmake b/scripts/cmake/vcpkg_replace_string.cmake
index d24b8677e..1f8b37b65 100644
--- a/scripts/cmake/vcpkg_replace_string.cmake
+++ b/scripts/cmake/vcpkg_replace_string.cmake
@@ -4,13 +4,12 @@
Replace a string in a file.
```cmake
-vcpkg_replace_string(filename match_string replace_string)
+vcpkg_replace_string(<filename> <match> <replace>)
```
-
#]===]
-function(vcpkg_replace_string filename match_string replace_string)
- file(READ ${filename} _contents)
- string(REPLACE "${match_string}" "${replace_string}" _contents "${_contents}")
- file(WRITE ${filename} "${_contents}")
+function(vcpkg_replace_string filename match replace)
+ file(READ "${filename}" contents)
+ string(REPLACE "${match}" "${replace}" contents "${contents}")
+ file(WRITE "${filename}" "${contents}")
endfunction()
diff --git a/scripts/cmake/z_vcpkg_function_arguments.cmake b/scripts/cmake/z_vcpkg_function_arguments.cmake
index 2c5b694ed..043c86191 100644
--- a/scripts/cmake/z_vcpkg_function_arguments.cmake
+++ b/scripts/cmake/z_vcpkg_function_arguments.cmake
@@ -32,22 +32,32 @@ macro(z_vcpkg_function_arguments OUT_VAR)
set(z_vcpkg_function_arguments_FIRST_ARG 0)
elseif("${ARGC}" EQUAL 2)
set(z_vcpkg_function_arguments_FIRST_ARG "${ARGV1}")
+
+ if(NOT z_vcpkg_function_arguments_FIRST_ARG GREATER_EQUAL "0" AND NOT z_vcpkg_function_arguments_FIRST_ARG LESS "0")
+ message(FATAL_ERROR "z_vcpkg_function_arguments: index (${z_vcpkg_function_arguments_FIRST_ARG}) is not a number")
+ elseif(z_vcpkg_function_arguments_FIRST_ARG LESS "0" OR z_vcpkg_function_arguments_FIRST_ARG GREATER ARGC)
+ message(FATAL_ERROR "z_vcpkg_function_arguments: index (${z_vcpkg_function_arguments_FIRST_ARG}) out of range")
+ endif()
else()
# vcpkg bug
message(FATAL_ERROR "z_vcpkg_function_arguments: invalid arguments (${ARGV})")
endif()
- set("${OUT_VAR}")
+ set("${OUT_VAR}" "")
# this allows us to get the value of the enclosing function's ARGC
set(z_vcpkg_function_arguments_ARGC_NAME "ARGC")
set(z_vcpkg_function_arguments_ARGC "${${z_vcpkg_function_arguments_ARGC_NAME}}")
math(EXPR z_vcpkg_function_arguments_LAST_ARG "${z_vcpkg_function_arguments_ARGC} - 1")
- if(z_vcpkg_function_arguments_LAST_ARG GREATER_EQUAL z_vcpkg_function_arguments_FIRST_ARG)
+ # GREATER_EQUAL added in CMake 3.7
+ if(NOT z_vcpkg_function_arguments_LAST_ARG LESS z_vcpkg_function_arguments_FIRST_ARG)
foreach(z_vcpkg_function_arguments_N RANGE "${z_vcpkg_function_arguments_FIRST_ARG}" "${z_vcpkg_function_arguments_LAST_ARG}")
string(REPLACE ";" "\\;" z_vcpkg_function_arguments_ESCAPED_ARG "${ARGV${z_vcpkg_function_arguments_N}}")
- list(APPEND "${OUT_VAR}" "${z_vcpkg_function_arguments_ESCAPED_ARG}")
+ # adds an extra ";" on the front
+ set("${OUT_VAR}" "${${OUT_VAR}};${z_vcpkg_function_arguments_ESCAPED_ARG}")
endforeach()
+ # and then removes that extra semicolon
+ string(SUBSTRING "${${OUT_VAR}}" 1 -1 "${OUT_VAR}")
endif()
endmacro()
diff --git a/scripts/ports.cmake b/scripts/ports.cmake
index ce6fc557b..98a6e2352 100644
--- a/scripts/ports.cmake
+++ b/scripts/ports.cmake
@@ -130,6 +130,7 @@ if(CMD MATCHES "^BUILD$")
include("${SCRIPTS}/cmake/vcpkg_install_nmake.cmake")
include("${SCRIPTS}/cmake/vcpkg_install_qmake.cmake")
include("${SCRIPTS}/cmake/vcpkg_internal_get_cmake_vars.cmake")
+ include("${SCRIPTS}/cmake/vcpkg_list.cmake")
include("${SCRIPTS}/cmake/vcpkg_replace_string.cmake")
include("${SCRIPTS}/cmake/vcpkg_test_cmake.cmake")
diff --git a/scripts/test_ports/unit-test-cmake/portfile.cmake b/scripts/test_ports/unit-test-cmake/portfile.cmake
new file mode 100644
index 000000000..638b15974
--- /dev/null
+++ b/scripts/test_ports/unit-test-cmake/portfile.cmake
@@ -0,0 +1,73 @@
+function(set_fatal_error)
+ if(ARGC EQUAL 0)
+ set(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR "OFF" CACHE BOOL "" FORCE)
+ else()
+ set(Z_VCPKG_UNIT_TEST_HAS_FATAL_ERROR "ON" CACHE BOOL "" FORCE)
+ set(Z_VCPKG_UNIT_TEST_FATAL_ERROR "${ARGV0}" CACHE STRING "" FORCE)
+ endif()
+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)
+set_fatal_error()
+
+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)
+ set_fatal_error()
+ set_has_error()
+ message(STATUS "${utcve_test} had an unexpected FATAL_ERROR;
+ expected: \"${utcve_value}\"")
+ message(STATUS "FATAL_ERROR: ${Z_VCPKG_UNIT_TEST_FATAL_ERROR}")
+ return()
+ endif()
+
+ if(NOT DEFINED "${utcve_variable}")
+ message(STATUS "${utcve_test} failed to set ${utcve_variable};
+ expected: \"${utcve_value}\"")
+ set_has_error()
+ return()
+ endif()
+ if(NOT "${${utcve_variable}}" STREQUAL "${utcve_value}")
+ message(STATUS "${utcve_test} resulted in the wrong value for ${utcve_variable};
+ expected: \"${utcve_value}\"
+ actual : \"${${utcve_variable}}\"")
+ set_has_error()
+ return()
+ endif()
+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(STATUS "${utcve_test} was expected to be a FATAL_ERROR.")
+ endif()
+ set_fatal_error()
+endfunction()
+
+set(VCPKG_POLICY_EMPTY_PACKAGE enabled)
+
+if("list" IN_LIST FEATURES)
+ include("${CMAKE_CURRENT_LIST_DIR}/test-vcpkg_list.cmake")
+endif()
+if("function-arguments" IN_LIST FEATURES)
+ include("${CMAKE_CURRENT_LIST_DIR}/test-z_vcpkg_function_arguments.cmake")
+endif()
+
+if(Z_VCPKG_UNIT_TEST_HAS_ERROR)
+ _message(FATAL_ERROR "At least one test failed")
+endif()
diff --git a/scripts/test_ports/unit-test-cmake/test-vcpkg_list.cmake b/scripts/test_ports/unit-test-cmake/test-vcpkg_list.cmake
new file mode 100644
index 000000000..c0f3ac8c0
--- /dev/null
+++ b/scripts/test_ports/unit-test-cmake/test-vcpkg_list.cmake
@@ -0,0 +1,813 @@
+# vcpkg_list(SET <list> <elements>...)
+unit_test_check_variable_equal(
+ [[vcpkg_list(SET lst)]]
+ lst ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(SET lst "")]]
+ lst ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(SET lst "" "")]]
+ lst ";"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(SET lst a)]]
+ lst "a"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(SET lst a b)]]
+ lst "a;b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(SET lst "a;b")]]
+ lst [[a\;b]]
+)
+unit_test_check_variable_equal(
+ [=[vcpkg_list(SET lst "a;b" "c" [[d\;e]])]=]
+ lst [[a\;b;c;d\\;e]]
+)
+
+# vcpkg_list(LENGTH <list> <out-var>)
+set(lst [[]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(LENGTH lst out)]]
+ out 0
+)
+set(lst [[;]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(LENGTH lst out)]]
+ out 2
+)
+set(lst [[a]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(LENGTH lst out)]]
+ out 1
+)
+set(lst [[a;b]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(LENGTH lst out)]]
+ out 2
+)
+set(lst [[a\\;b]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(LENGTH lst out)]]
+ out 1
+)
+set(lst [[a\;b;c\\;d]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(LENGTH lst out)]]
+ out 2
+)
+
+# vcpkg_list(GET <list> <element-index> <out-var>)
+set(lst "")
+unit_test_ensure_fatal_error([[vcpkg_list(GET lst 0 out)]])
+
+set(lst "a")
+unit_test_check_variable_equal(
+ [[vcpkg_list(GET lst 0 out)]]
+ out "a"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(GET lst -1 out)]]
+ out "a"
+)
+unit_test_ensure_fatal_error([[vcpkg_list(GET lst 2 out)]])
+unit_test_ensure_fatal_error([[vcpkg_list(GET lst -2 out)]])
+
+set(lst ";b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(GET lst 0 out)]]
+ out ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(GET lst -1 out)]]
+ out "b"
+)
+
+set(lst "a;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(GET lst 0 out)]]
+ out "a"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(GET lst -1 out)]]
+ out "b"
+)
+
+set(lst [[a\;b;c]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(GET lst 0 out)]]
+ out "a;b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(GET lst -1 out)]]
+ out "c"
+)
+
+set(lst [[a;b\;c;d\\;e]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(GET lst 1 out)]]
+ out "b;c"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(GET lst -1 out)]]
+ out [[d\;e]]
+)
+
+# vcpkg_list(JOIN <list> <glue> <out-var>)
+set(lst "")
+unit_test_check_variable_equal(
+ [[vcpkg_list(JOIN lst "-" out)]]
+ out ""
+)
+
+set(lst "a")
+unit_test_check_variable_equal(
+ [[vcpkg_list(JOIN lst "-" out)]]
+ out "a"
+)
+
+set(lst ";")
+unit_test_check_variable_equal(
+ [[vcpkg_list(JOIN lst "-" out)]]
+ out "-"
+)
+
+set(lst [[a;b]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(JOIN lst "-" out)]]
+ out [[a-b]]
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(JOIN lst "+" out)]]
+ out [[a+b]]
+)
+
+set(lst [[a;b\;c\\;d]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(JOIN lst "-" out)]]
+ out [[a-b;c\;d]]
+)
+
+# vcpkg_list(SUBLIST <list> <begin> <length> <out-var>)
+set(lst "")
+unit_test_check_variable_equal(
+ [[vcpkg_list(SUBLIST lst 0 0 out)]]
+ out ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(SUBLIST lst 0 1 out)]]
+ out ""
+)
+unit_test_ensure_fatal_error([[vcpkg_list(SUBLIST lst 1 0 out)]])
+
+set(lst "a")
+unit_test_check_variable_equal(
+ [[vcpkg_list(SUBLIST lst 0 0 out)]]
+ out ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(SUBLIST lst 0 1 out)]]
+ out "a"
+)
+unit_test_ensure_fatal_error([[vcpkg_list(SUBLIST lst 2 0 out)]])
+unit_test_ensure_fatal_error([[vcpkg_list(SUBLIST lst 2 1 out)]])
+
+set(lst ";;")
+unit_test_check_variable_equal(
+ [[vcpkg_list(SUBLIST lst 0 0 out)]]
+ out ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(SUBLIST lst 0 1 out)]]
+ out ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(SUBLIST lst 0 2 out)]]
+ out ";"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(SUBLIST lst 0 3 out)]]
+ out ";;"
+)
+
+set(lst "a;b;c;d")
+unit_test_check_variable_equal(
+ [[vcpkg_list(SUBLIST lst 1 2 out)]]
+ out "b;c"
+)
+
+set(lst [[a\;b;c\;d;e]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(SUBLIST lst 1 2 out)]]
+ out [[c\;d;e]]
+)
+
+set(lst [[a\;b;c\\;d;e;f;g;h]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(SUBLIST lst 1 -1 out)]]
+ out [[c\\;d;e;f;g;h]]
+)
+
+# vcpkg_list(FIND <list> <value> <out-var>)
+set(lst "")
+unit_test_check_variable_equal(
+ [[vcpkg_list(FIND lst "a" out)]]
+ out -1
+)
+
+set(lst "b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(FIND lst "a" out)]]
+ out -1
+)
+
+set(lst "a;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(FIND lst "a" out)]]
+ out 0
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(FIND lst b out)]]
+ out 1
+)
+
+set(lst ";b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(FIND lst "" out)]]
+ out 0
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(FIND lst b out)]]
+ out 1
+)
+
+set(lst [[a\;b;c]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(FIND lst "a;b" out)]]
+ out 0
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(FIND lst c out)]]
+ out 1
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(FIND lst a out)]]
+ out -1
+)
+
+set(lst [[a\\;b;c]])
+unit_test_check_variable_equal(
+ [=[vcpkg_list(FIND lst [[a\;b]] out)]=]
+ out 0
+)
+
+# vcpkg_list(APPEND <list> [<element>...])
+set(lst "")
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst)]]
+ lst [[]]
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst "")]]
+ lst ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst "" "")]]
+ lst ";"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst a)]]
+ lst "a"
+)
+
+set(lst ";")
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst)]]
+ lst ";"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst "")]]
+ lst ";;"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst b)]]
+ lst ";;b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst "b;c" d)]]
+ lst [[;;b\;c;d]]
+)
+
+set(lst "a")
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst)]]
+ lst "a"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst "")]]
+ lst "a;"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst b)]]
+ lst "a;b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst "b;c" d)]]
+ lst [[a;b\;c;d]]
+)
+
+set(lst "a;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst)]]
+ lst "a;b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst "")]]
+ lst "a;b;"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst c)]]
+ lst "a;b;c"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(APPEND lst "c;d" e)]]
+ lst [[a;b;c\;d;e]]
+)
+unit_test_check_variable_equal(
+ [=[vcpkg_list(APPEND lst [[c\;d]])]=]
+ lst [[a;b;c\\;d]]
+)
+
+# vcpkg_list(PREPEND <list> [<element>...])
+set(lst "")
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst)]]
+ lst ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst "")]]
+ lst ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst "" "")]]
+ lst ";"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst a)]]
+ lst "a"
+)
+
+set(lst ";")
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst)]]
+ lst ";"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst "")]]
+ lst ";;"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst b)]]
+ lst "b;;"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst "b;c" d)]]
+ lst [[b\;c;d;;]]
+)
+
+set(lst "a")
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst)]]
+ lst "a"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst "")]]
+ lst ";a"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst b)]]
+ lst "b;a"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst "b;c" d)]]
+ lst [[b\;c;d;a]]
+)
+
+set(lst "a;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst)]]
+ lst "a;b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst "")]]
+ lst ";a;b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst c)]]
+ lst "c;a;b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(PREPEND lst "c;d" e)]]
+ lst [[c\;d;e;a;b]]
+)
+unit_test_check_variable_equal(
+ [=[vcpkg_list(PREPEND lst [[c\;d]])]=]
+ lst [[c\\;d;a;b]]
+)
+
+# list(INSERT <list> <index> [<element>...])
+set(lst "")
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst 0)]]
+ lst ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst 0 "")]]
+ lst ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst 0 "" "")]]
+ lst ";"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst 0 "a")]]
+ lst "a"
+)
+unit_test_ensure_fatal_error([[vcpkg_list(INSERT lst 1 "")]])
+unit_test_ensure_fatal_error([[vcpkg_list(INSERT lst -1 "")]])
+
+set(lst ";")
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst 0)]]
+ lst ";"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst 1)]]
+ lst ";"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst 1 "")]]
+ lst ";;"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst 0 b)]]
+ lst "b;;"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst 1 b)]]
+ lst ";b;"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst 2 b)]]
+ lst ";;b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst -1 "b;c" d)]]
+ lst [[;b\;c;d;]]
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst -2 "b;c" d)]]
+ lst [[b\;c;d;;]]
+)
+unit_test_ensure_fatal_error([[vcpkg_list(INSERT lst 3 "")]])
+unit_test_ensure_fatal_error([[vcpkg_list(INSERT lst -3 "")]])
+
+set(lst "a;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst -1 c)]]
+ lst "a;c;b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst 1 c)]]
+ lst "a;c;b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst 2 c)]]
+ lst "a;b;c"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst -2 c)]]
+ lst "c;a;b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(INSERT lst 1 "c;d")]]
+ lst [[a;c\;d;b]]
+)
+unit_test_check_variable_equal(
+ [=[vcpkg_list(INSERT lst 1 [[c\;d]] e)]=]
+ lst [[a;c\\;d;e;b]]
+)
+
+# vcpkg_list(POP_BACK <list>)
+set(lst "")
+unit_test_check_variable_equal(
+ [[vcpkg_list(POP_BACK lst)]]
+ lst ""
+)
+
+set(lst ";")
+unit_test_check_variable_equal(
+ [[vcpkg_list(POP_BACK lst)]]
+ lst ""
+)
+
+set(lst "a;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(POP_BACK lst)]]
+ lst "a"
+)
+
+set(lst "a;;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(POP_BACK lst)]]
+ lst "a;"
+)
+
+set(lst [[a\;b]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(POP_BACK lst)]]
+ lst ""
+)
+
+set(lst [[c;a\;b;c]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(POP_BACK lst)]]
+ lst [[c;a\;b]]
+)
+
+# vcpkg_list(POP_FRONT <list>)
+set(lst "")
+unit_test_check_variable_equal(
+ [[vcpkg_list(POP_BACK lst)]]
+ lst ""
+)
+
+set(lst ";")
+unit_test_check_variable_equal(
+ [[vcpkg_list(POP_FRONT lst)]]
+ lst ""
+)
+
+set(lst "a;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(POP_FRONT lst)]]
+ lst "b"
+)
+
+set(lst "a;;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(POP_FRONT lst)]]
+ lst ";b"
+)
+
+set(lst [[a\;b]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(POP_FRONT lst)]]
+ lst ""
+)
+
+set(lst [[c;a\;b;c]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(POP_FRONT lst)]]
+ lst [[a\;b;c]]
+)
+
+# vcpkg_list(REMOVE_DUPLICATES <list>)
+set(lst ";")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_DUPLICATES lst)]]
+ lst ""
+)
+
+set(lst "a;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_DUPLICATES lst)]]
+ lst "a;b"
+)
+
+set(lst "a;a;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_DUPLICATES lst)]]
+ lst "a;b"
+)
+
+set(lst "a;b;a")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_DUPLICATES lst)]]
+ lst "a;b"
+)
+
+set(lst "c;a;b;a;c")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_DUPLICATES lst)]]
+ lst "c;a;b"
+)
+
+set(lst "a;;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_DUPLICATES lst)]]
+ lst "a;;b"
+)
+
+set(lst [[a\;b;a\;b]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_DUPLICATES lst)]]
+ lst [[a\;b]]
+)
+
+set(lst [[c;a\;b;c]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_DUPLICATES lst)]]
+ lst [[c;a\;b]]
+)
+
+# vcpkg_list(REVERSE <list>)
+set(lst "")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REVERSE lst)]]
+ lst ""
+)
+set(lst ";")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REVERSE lst)]]
+ lst ";"
+)
+set(lst "a;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REVERSE lst)]]
+ lst "b;a"
+)
+set(lst "a;b;c;d;e;f;g")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REVERSE lst)]]
+ lst "g;f;e;d;c;b;a"
+)
+
+set(lst [[a\;b;a\;b\\;c]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(REVERSE lst)]]
+ lst [[a\;b\\;c;a\;b]]
+)
+set(lst [[c;a\;b]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(REVERSE lst)]]
+ lst [[a\;b;c]]
+)
+
+# vcpkg_list(REMOVE_ITEM <list> <value>)
+set(lst "")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_ITEM lst "a")]]
+ lst ""
+)
+
+set(lst ";")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_ITEM lst "")]]
+ lst ""
+)
+
+set(lst "a;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_ITEM lst a)]]
+ lst "b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_ITEM lst b)]]
+ lst "a"
+)
+
+set(lst "a;a;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_ITEM lst a)]]
+ lst "b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_ITEM lst b)]]
+ lst "a;a"
+)
+
+set(lst "a;b;c;a;d")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_ITEM lst b)]]
+ lst "a;c;a;d"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_ITEM lst a)]]
+ lst "b;c;d"
+)
+
+set(lst "a;;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_ITEM lst "")]]
+ lst "a;b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_ITEM lst a)]]
+ lst ";b"
+)
+
+set(lst [[e;a\;b;c\;d]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_ITEM lst "a;b")]]
+ lst [[e;c\;d]]
+)
+
+set(lst [[c;a\;b;c]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_ITEM lst "c")]]
+ lst [[a\;b]]
+)
+
+set(lst [[c;a\\;b;c]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_ITEM lst "a\\;b")]]
+ lst [[c;c]]
+)
+
+# vcpkg_list(REMOVE_AT <list> <index>)
+set(lst "")
+unit_test_ensure_fatal_error([[vcpkg_list(REMOVE_AT lst 0)]])
+
+set(lst ";")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst 0)]]
+ lst ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst 1)]]
+ lst ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst -1)]]
+ lst ""
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst -2)]]
+ lst ""
+)
+unit_test_ensure_fatal_error([[vcpkg_list(REMOVE_AT lst 2)]])
+unit_test_ensure_fatal_error([[vcpkg_list(REMOVE_AT lst -3)]])
+
+set(lst "a;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst 0)]]
+ lst "b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst 1)]]
+ lst "a"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst -1)]]
+ lst "a"
+)
+
+set(lst "a;;b")
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst 0)]]
+ lst ";b"
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst 1)]]
+ lst "a;b"
+)
+
+set(lst [[e;a\;b;c\;d]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst 0)]]
+ lst [[a\;b;c\;d]]
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst 1)]]
+ lst [[e;c\;d]]
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst -1)]]
+ lst [[e;a\;b]]
+)
+
+set(lst [[c;a\\;b;c\;d;e]])
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst 0)]]
+ lst [[a\\;b;c\;d;e]]
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst 1)]]
+ lst [[c;c\;d;e]]
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst 2)]]
+ lst [[c;a\\;b;e]]
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst 3)]]
+ lst [[c;a\\;b;c\;d]]
+)
+unit_test_check_variable_equal(
+ [[vcpkg_list(REMOVE_AT lst -1)]]
+ lst [[c;a\\;b;c\;d]]
+)
diff --git a/scripts/test_ports/unit-test-cmake/test-z_vcpkg_function_arguments.cmake b/scripts/test_ports/unit-test-cmake/test-z_vcpkg_function_arguments.cmake
new file mode 100644
index 000000000..e88eb683f
--- /dev/null
+++ b/scripts/test_ports/unit-test-cmake/test-z_vcpkg_function_arguments.cmake
@@ -0,0 +1,63 @@
+# these both set `args` in the top level
+function(check_function_args start)
+ z_vcpkg_function_arguments(out "${start}")
+ set(args "${out}" PARENT_SCOPE)
+endfunction()
+function(check_all_function_args)
+ z_vcpkg_function_arguments(out)
+ set(args "${out}" PARENT_SCOPE)
+endfunction()
+
+unit_test_ensure_fatal_error([[check_function_args(-1)]])
+unit_test_ensure_fatal_error([[check_function_args(3)]])
+unit_test_ensure_fatal_error([[check_function_args(notanumber)]])
+unit_test_check_variable_equal(
+ [[check_all_function_args()]]
+ args ""
+)
+unit_test_check_variable_equal(
+ [[check_all_function_args("")]]
+ args ""
+)
+unit_test_check_variable_equal(
+ [[check_all_function_args("" "")]]
+ args ";"
+)
+unit_test_check_variable_equal(
+ [[check_all_function_args("" "" "" "")]]
+ args ";;;"
+)
+
+unit_test_check_variable_equal(
+ [[check_all_function_args(a b c)]]
+ args "a;b;c"
+)
+unit_test_check_variable_equal(
+ [[check_function_args(2 a b c)]]
+ args "b;c"
+)
+unit_test_check_variable_equal(
+ [[check_function_args(3 a b c)]]
+ args "c"
+)
+
+unit_test_check_variable_equal(
+ [=[check_all_function_args("a;b" [[c\;d]] e)]=]
+ args [[a\;b;c\\;d;e]]
+)
+unit_test_check_variable_equal(
+ [=[check_all_function_args("a;b" [[c\;d]] [[e\\;f]])]=]
+ args [[a\;b;c\\;d;e\\\;f]]
+)
+unit_test_check_variable_equal(
+ [=[check_function_args(2 "a;b" [[c\;d]] e)]=]
+ args [[c\\;d;e]]
+)
+unit_test_check_variable_equal(
+ [=[check_function_args(3 "a;b" [[c\;d]] e)]=]
+ args "e"
+)
+unit_test_check_variable_equal(
+ [=[check_function_args(4 "a;b" [[c\;d]] e)]=]
+ args ""
+)
diff --git a/scripts/test_ports/unit-test-cmake/vcpkg.json b/scripts/test_ports/unit-test-cmake/vcpkg.json
new file mode 100644
index 000000000..5079f9e73
--- /dev/null
+++ b/scripts/test_ports/unit-test-cmake/vcpkg.json
@@ -0,0 +1,18 @@
+{
+ "name": "unit-test-cmake",
+ "version-string": "0",
+ "description": "Ensures that the CMake scripts are unit tested.",
+ "supports": "x64",
+ "default-features": [
+ "function-arguments",
+ "list"
+ ],
+ "features": {
+ "function-arguments": {
+ "description": "Test the z_vcpkg_function_arguments function"
+ },
+ "list": {
+ "description": "Test the vcpkg_list function"
+ }
+ }
+}