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_config_test] Add function to test the exported cmake configurations #15173

Closed
Closed
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
3b9ff10
[vcpkg_test_cmake_config] Add function to test the exported cmake con…
Dec 17, 2020
0c53ee3
Add code to test
Dec 17, 2020
c25da95
add doc, add release check.
Dec 18, 2020
f6cd789
Merge branch 'master' into dev/jack/vcpkg_test_cmake_config
JackBoosY May 25, 2021
4edfa9a
format doc
May 25, 2021
ec96372
Merge branch 'dev/jack/vcpkg_test_cmake_config' of https://github.com…
May 25, 2021
d645252
convert to port vcpkg-cmake-test
May 27, 2021
28db599
add dependency
May 28, 2021
5e7d1fc
include
May 28, 2021
a06d58a
install
May 28, 2021
d2e91f6
fix TARGET_NAME
May 28, 2021
dc532d6
Allow to use `vcpkg-test.cmake` / `vcpkg.test.cpp` / `vcpkg-test.c` i…
Jun 3, 2021
753884f
Add option HEADERS / FUNCTIONS
Jun 3, 2021
bfb187a
[curl] add cmake test
Jun 3, 2021
805b7f9
Merge branch 'master' into dev/jack/vcpkg_test_cmake_config
JackBoosY Jun 3, 2021
fa4c6f9
add port version
Jun 3, 2021
4b3f8ad
update version record
Jun 4, 2021
2ace8a8
update version record
Jun 7, 2021
c71f7d8
move vcpkg_cmake_config_test -> vcpkg-cmake-config port
strega-nil Jun 7, 2021
abe70cd
Merge branch 'master' of https://github.com/microsoft/vcpkg into dev/…
Oct 19, 2021
9302e28
script audit
Oct 19, 2021
1a7a050
More audits.
Oct 19, 2021
f400a0b
update doc
Oct 19, 2021
235f7cf
bump version
Oct 19, 2021
af29925
version
Oct 19, 2021
c639021
Remove useless record
Oct 19, 2021
8e98f74
update function name
Oct 20, 2021
3bcf01d
version
Oct 20, 2021
4a23b84
Rename options name, fix bug
Oct 27, 2021
9d4885f
version
Oct 27, 2021
4ce2fda
Apply suggestions
Oct 27, 2021
eab5fed
Apply suggestions
Oct 28, 2021
7f3283a
Merge branch 'master' of https://github.com/microsoft/vcpkg into dev/…
Dec 17, 2021
0c9d2c9
Apply suggestions.
Dec 17, 2021
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
1 change: 1 addition & 0 deletions docs/maintainers/portfile-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
### [vcpkg-cmake-config](ports/vcpkg-cmake-config.md)

- [vcpkg\_cmake\_config\_fixup](ports/vcpkg-cmake-config/vcpkg_cmake_config_fixup.md)
- [vcpkg\_cmake\_config\_test](ports/vcpkg-cmake-config/vcpkg_cmake_config_test.md)

### [vcpkg-pkgconfig-get-modules](ports/vcpkg-pkgconfig-get-modules.md)

Expand Down
9 changes: 7 additions & 2 deletions docs/maintainers/ports/vcpkg-cmake-config.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
# vcpkg-cmake-config

`vcpkg-cmake-config` provides `vcpkg_cmake_config_fixup()`,
a function which both:
`vcpkg-cmake-config` provides `vcpkg_cmake_config_fixup()` and `vcpkg_cmake_config_test()`.
The first function:

- Fixes common mistakes in port build systems, like using absolute paths
- Merges the debug and release config files.

This function should almost always be used when a port has `*config.cmake` files,
even when the buildsystem of the project is not CMake.

The latter function tests the generated cmake config files;
in general, any port that generates `*[Cc]onfig.cmake` should call this
function to check whether the generated configuration is correct,
after calling `vcpkg_cmake_config_fixup()`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# vcpkg_cmake_config_test

The latest version of this document lives in the [vcpkg repo](https://github.com/Microsoft/vcpkg/blob/master/docs/maintainers/ports/vcpkg-cmake-config/vcpkg_cmake_config_test.md).

Automatically test the correctness of the configuration file exported by cmake

```cmake
vcpkg_cmake_config_test(
[TARGET_NAME <PORT_NAME>]
[TARGET_VARS <TARGETS>...]
[HEADERS <headername.h>...]
[FUNCTIONS <function1> ...]
)
```

For most ports, `vcpkg_cmake_config_test` should work without passing any options,
`vcpkg_cmake_config_test` will automatically detect the targets declared in the generated
cmake configuration file which are used in `find_package`, and set the targets to `TARGET_NAME`.

`TARGET_VARS` should use the target name in `target_link_libraries` and support namespace.

For more advanced usage, `vcpkg_cmake_config_test` supports the use of reserved c/c++ code for testing.
Please encapsulate the test code as one or more functions and save them to `vcpkg_test.c` or `vcpkg_test.cpp`,
and pass the name of the system header file that needs to be included into the `HEADERS`.

And, please use option `FUNCTIONS` to pass these test function names into `vcpkg_cmake_config_test`.

More, you can implement the test cmake code by yourself to add additional compilation options
or cmake options by writing them into `vcpkg_test.cmake`.

Please note that `vcpkg_test.cmake` / `vcpkg_test.c` / `vcpkg_test.cpp` must be placed in the same directory
as `portfile.cmake`.

## Examples

* [curl](https://github.com/Microsoft/vcpkg/blob/master/ports/curl/portfile.cmake)
* [ptex](https://github.com/Microsoft/vcpkg/blob/master/ports/ptex/portfile.cmake)

## Source
[ports/vcpkg-cmake-config/vcpkg\_cmake\_config\_test.cmake](https://github.com/Microsoft/vcpkg/blob/master/ports/vcpkg-cmake-config/vcpkg_cmake_config_test.cmake)
5 changes: 5 additions & 0 deletions ports/curl/portfile.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,10 @@ if(EXISTS "${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libcurl.pc")
vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libcurl.pc" " -lcurl" " -lcurl-d")
endif()

vcpkg_cmake_config_test(
HEADERS curl/curl.h
FUNCTIONS curl_global_init
)

file(INSTALL "${CURRENT_PORT_DIR}/vcpkg-cmake-wrapper.cmake" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
file(INSTALL "${SOURCE_PATH}/COPYING" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)
1 change: 1 addition & 0 deletions ports/curl/vcpkg.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "curl",
"version": "7.79.1",
"port-version": 1,
"description": "A library for transferring data with URLs",
"homepage": "https://github.com/curl/curl",
"dependencies": [
Expand Down
2 changes: 2 additions & 0 deletions ports/ptex/portfile.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ vcpkg_cmake_install()
vcpkg_cmake_config_fixup(CONFIG_PATH share/cmake/Ptex)
vcpkg_copy_pdbs()

vcpkg_cmake_config_test()

foreach(HEADER PtexHalf.h Ptexture.h)
file(READ "${CURRENT_PACKAGES_DIR}/include/${HEADER}" PTEX_HEADER)
if(VCPKG_LIBRARY_LINKAGE STREQUAL dynamic)
Expand Down
2 changes: 1 addition & 1 deletion ports/ptex/vcpkg.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ptex",
"version": "2.3.2",
"port-version": 3,
"port-version": 4,
"description": "Per-Face Texture Mapping for Production Rendering.",
"homepage": "https://github.com/wdas/ptex",
"supports": "!uwp",
Expand Down
9 changes: 7 additions & 2 deletions ports/vcpkg-cmake-config/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
# vcpkg-cmake-config

`vcpkg-cmake-config` provides `vcpkg_cmake_config_fixup()`,
a function which both:
`vcpkg-cmake-config` provides `vcpkg_cmake_config_fixup()` and `vcpkg_cmake_config_test()`.
The first function:

- Fixes common mistakes in port build systems, like using absolute paths
- Merges the debug and release config files.

This function should almost always be used when a port has `*config.cmake` files,
even when the buildsystem of the project is not CMake.

The latter function tests the generated cmake config files;
in general, any port that generates `*[Cc]onfig.cmake` should call this
function to check whether the generated configuration is correct,
after calling `vcpkg_cmake_config_fixup()`.
1 change: 1 addition & 0 deletions ports/vcpkg-cmake-config/portfile.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ endif()

file(INSTALL
"${CMAKE_CURRENT_LIST_DIR}/vcpkg_cmake_config_fixup.cmake"
"${CMAKE_CURRENT_LIST_DIR}/vcpkg_cmake_config_test.cmake"
"${CMAKE_CURRENT_LIST_DIR}/vcpkg-port-config.cmake"
"${CMAKE_CURRENT_LIST_DIR}/copyright"
DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
Expand Down
1 change: 1 addition & 0 deletions ports/vcpkg-cmake-config/vcpkg-port-config.cmake
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
include("${CMAKE_CURRENT_LIST_DIR}/vcpkg_cmake_config_fixup.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/vcpkg_cmake_config_test.cmake")
2 changes: 1 addition & 1 deletion ports/vcpkg-cmake-config/vcpkg.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"name": "vcpkg-cmake-config",
"version-date": "2021-09-27"
"version-date": "2021-10-19"
}
223 changes: 223 additions & 0 deletions ports/vcpkg-cmake-config/vcpkg_cmake_config_test.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
#[===[.md:
# vcpkg_cmake_config_test

Automatically test the correctness of the configuration file exported by cmake

```cmake
vcpkg_cmake_config_test(
[TARGET_NAME <PORT_NAME>]
[TARGET_VARS <TARGETS>...]
[HEADERS <headername.h>...]
[FUNCTIONS <function1> ...]
)
```

For most ports, `vcpkg_cmake_config_test` should work without passing any options,
`vcpkg_cmake_config_test` will automatically detect the targets declared in the generated
cmake configuration file which are used in `find_package`, and set the targets to `TARGET_NAME`.

`TARGET_VARS` should use the target name in `target_link_libraries` and support namespace.

For more advanced usage, `vcpkg_cmake_config_test` supports the use of reserved c/c++ code for testing.
Please encapsulate the test code as one or more functions and save them to `vcpkg_test.c` or `vcpkg_test.cpp`,
and pass the name of the system header file that needs to be included into the `HEADERS`.

And, please use option `FUNCTIONS` to pass these test function names into `vcpkg_cmake_config_test`.

More, you can implement the test cmake code by yourself to add additional compilation options
or cmake options by writing them into `vcpkg_test.cmake`.

Please note that `vcpkg_test.cmake` / `vcpkg_test.c` / `vcpkg_test.cpp` must be placed in the same directory
as `portfile.cmake`.

## Examples

* [curl](https://github.com/Microsoft/vcpkg/blob/master/ports/curl/portfile.cmake)
* [ptex](https://github.com/Microsoft/vcpkg/blob/master/ports/ptex/portfile.cmake)
#]===]

macro(z_get_cmake_targets)
JackBoosY marked this conversation as resolved.
Show resolved Hide resolved
set(target_names )
set(target_folders )
JackBoosY marked this conversation as resolved.
Show resolved Hide resolved

file(GLOB_RECURSE cmake_files "${CURRENT_PACKAGES_DIR}/*/*.cmake")
foreach(cmake_file IN ITEMS cmake_files)
JackBoosY marked this conversation as resolved.
Show resolved Hide resolved
get_filename_component(target_folder ${cmake_file} DIRECTORY)
get_filename_component(target_folder ${target_folder} NAME)
vcpkg_list(APPEND target_folders "${target_folder}")
file(READ "${cmake_file}" CMAKE_CONTENT)
string(REGEX MATCH "add_library.([^\ ]+)\ " target_name "${CMAKE_CONTENT}")
JackBoosY marked this conversation as resolved.
Show resolved Hide resolved
string(REPLACE "add_library(" "" target_name "${target_name}")
string(REPLACE " " "" target_name "${target_name}")
if (NOT target_name)
continue()
JackBoosY marked this conversation as resolved.
Show resolved Hide resolved
endif()
list(APPEND target_names ${target_name})
debug_message("target_name: ${target_name}")
endforeach()
unset(target_name)
vcpkg_list(REMOVE_DUPLICATES target_names)
vcpkg_list(REMOVE_DUPLICATES target_folders)

list(LENGTH target_names target_size)
list(LENGTH target_folders folder_size)

if (target_size EQUAL 0 OR folder_size EQUAL 0)
return()
endif()

if (NOT folder_size EQUAL 1 AND NOT arg_TARGET_NAME)
message(FATAL_ERROR "More than one folder contains cmake configuration files, please set \"target_name\" to select the certain target name")
endif()

#set(target_names ${target_names} PARENT_SCOPE)
#set(target_folder ${target_folders} PARENT_SCOPE)
endmacro()

macro(z_write_sample_code current_target)
JackBoosY marked this conversation as resolved.
Show resolved Hide resolved
set(test_dir "${CURRENT_BUILDTREES_DIR}/test_cmake")
file(REMOVE_RECURSE "${test_dir}")
file(MAKE_DIRECTORY "${test_dir}")

# c/cxx test file
if (EXISTS "${CURRENT_PORT_DIR}/vcpkg_test.c")
set(test_source cmake_test.c)
configure_file("${CURRENT_PORT_DIR}/vcpkg_test.c" "${test_dir}/cmake_test.c" COPYONLY)
elseif (EXISTS "${CURRENT_PORT_DIR}/vcpkg_test.cpp")
set(test_source cmake_test.cpp)
configure_file("${CURRENT_PORT_DIR}/vcpkg_test.c" "${test_dir}/cmake_test.cpp" COPYONLY)
else()
set(src_content
[[
#include <stdio.h>
@extern_header_checks@
@extern_symbol_checks_base@
int main(void)
{@extern_symbol_check_symbol@}
]]
)

file(WRITE "${test_dir}/cmake_test.cpp.in" "${src_content}")
configure_file("${test_dir}/cmake_test.cpp.in" "${test_dir}/cmake_test.cpp" @ONLY)
set(test_source cmake_test.cpp)
endif()

# CMakeLists.txt
if (EXISTS "${CURRENT_PORT_DIR}/vcpkg_test.cmake")
configure_file("${CURRENT_PORT_DIR}/vcpkg_test.cmake" "${test_dir}/CMakeLists.txt" COPYONLY)
else()
set(CMAKE_LISTS_CONTENT
[[
cmake_minimum_required (VERSION 3.19)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tests with all CMake 3.19 features enabled. This works, but it doesn't help verify that the port works with previous versions of CMake. It is okay for now.

project (cmake_test)

find_package(@target_folder@ CONFIG REQUIRED)
JackBoosY marked this conversation as resolved.
Show resolved Hide resolved

add_executable(cmake_test @test_source@)

target_link_libraries(cmake_test PRIVATE @current_target@)
]]
)

set(current_target ${current_target})
file(WRITE "${test_dir}/CMakeLists.txt.in" "${CMAKE_LISTS_CONTENT}")
configure_file("${test_dir}/CMakeLists.txt.in" "${test_dir}/CMakeLists.txt" @ONLY)
endif()
endmacro()

macro(z_build_with_toolchain)
JackBoosY marked this conversation as resolved.
Show resolved Hide resolved
foreach(build_type IN ITEMS "Debug" "Release")
set(config_cmd ${CMAKE_COMMAND} -G Ninja
-DCMAKE_BUILD_TYPE=${build_type}
-DCMAKE_PREFIX_PATH="${CURRENT_PACKAGES_DIR}/share/${target_folder}"
-DCMAKE_SOURCE_DIR="${test_dir}"
-DCMAKE_BINARY_DIR="${test_dir}"
JackBoosY marked this conversation as resolved.
Show resolved Hide resolved
-DCMAKE_TOOLCHAIN_FILE="${VCPKG_ROOT_DIR}/scripts/buildsystems/vcpkg.cmake"
-DVCPKG_TARGET_TRIPLET=${TARGET_TRIPLET}
)
set(build_cmd "${CMAKE_COMMAND} --build . --config ${build_type} -- -v")

execute_process(
COMMAND "${config_cmd}"
WORKING_DIRECTORY "${test_dir}"
RESULT_VARIABLE error_code
OUTPUT_FILE "${CURRENT_BUILDTREES_DIR}/config-test-cmake-out.log"
ERROR_FILE "${CURRENT_BUILDTREES_DIR}/config-test-cmake-err.log"
)

if (error_code)
message(FATAL_ERROR
"Test cmake configuration failed, please check cmake configuration file!"
"See log: ${CURRENT_BUILDTREES_DIR}/config-test-cmake-err.log"
)
endif()

execute_process(
COMMAND "${build_cmd}"
WORKING_DIRECTORY "${test_dir}"
RESULT_VARIABLE error_code
OUTPUT_FILE "${CURRENT_BUILDTREES_DIR}/build-test-cmake-out.log"
ERROR_FILE "${CURRENT_BUILDTREES_DIR}/build-test-cmake-err.log"
)

if (error_code)
message(FATAL_ERROR
"Test cmake configuration failed, please check cmake configuration file!"
"See log: ${CURRENT_BUILDTREES_DIR}/config-test-cmake-err.log"
)
endif()
endforeach()
endmacro()

function(vcpkg_cmake_config_test)
if (NOT _VCPKG_EDITABLE)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is the right indicator for controlling the test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect this test to run in edit mode or CI mode to reduce user build time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the argument about build time, But edit mode is somewhat exceptional in my personal use, and it is propably inactive during CI.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope the ci command will pass a special VCPKG_ variable to cmake to enable this function.
But for now I think it can be enabled in edit mode first.

# Skip cmake test
return()
endif()

cmake_parse_arguments(PARSE_ARGV 0 arg "" "TARGET_NAME" "TARGET_VARS;HEADERS;FUNCTIONS")
# First, we should get the cmake targets automanticlly
if ((arg_TARGET_NAME AND NOT arg_TARGET_VARS) OR (NOT arg_TARGET_NAME AND arg_TARGET_VARS))
message(FATAL_ERROR "TARGET_NAME and TARGET_VARS must be declared at same time!")
endif()

if (NOT arg_TARGET_NAME)
z_get_cmake_targets()
endif()

if (arg_TARGET_NAME)
set(target_folder "${arg_TARGET_NAME}")
set(target_names ${arg_TARGET_VARS})
elseif (NOT target_folder OR NOT target_names)
# Skip cmake test because the cmake configuration is not exported
message(STATUS "Could not find the cmake configuration file, skip test the cmake configuration.")
JackBoosY marked this conversation as resolved.
Show resolved Hide resolved
return()
endif()


set(extern_header_checks )
set(extern_symbol_checks_base )
set(extern_symbol_check_symbol )
JackBoosY marked this conversation as resolved.
Show resolved Hide resolved
if (arg_HEADERS)
foreach(header IN LISTS arg_HEADERS)
string(APPEND extern_header_checks ${extern_header_checks} "#include <${header}>\n")
JackBoosY marked this conversation as resolved.
Show resolved Hide resolved
endforeach()
endif()

if (arg_FUNCTIONS)
set(extern_symbol_checks_base "typedef int (*symbol_func)(void);\n\n")
foreach(symbol ${arg_FUNCTIONS})
set(extern_symbol_check_symbol "symbol_func func = (symbol_func)&${symbol};\nreturn func();\n")
endforeach()
endif()

foreach(target_name IN LISTS target_names)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the loop which is actually limiting us to the single cmake package case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, but it doesn't matter, this function will only be enabled in the official triplet which doesn't include the single configuration triplet yet.

# Write a sample CMakeLists.txt and source file
z_write_sample_code(${target_name})
# Build
z_build_with_toolchain()
endforeach()
unset(extern_symbol_check_symbol)
unset(extern_symbol_checks_base)
unset(extern_header_checks)
JackBoosY marked this conversation as resolved.
Show resolved Hide resolved
endfunction()
6 changes: 3 additions & 3 deletions versions/baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -1678,7 +1678,7 @@
},
"curl": {
"baseline": "7.79.1",
"port-version": 0
"port-version": 1
},
"curlpp": {
"baseline": "2018-06-15",
Expand Down Expand Up @@ -5334,7 +5334,7 @@
},
"ptex": {
"baseline": "2.3.2",
"port-version": 3
"port-version": 4
},
"pthread": {
"baseline": "3.0.0",
Expand Down Expand Up @@ -6949,7 +6949,7 @@
"port-version": 0
},
"vcpkg-cmake-config": {
"baseline": "2021-09-27",
"baseline": "2021-10-19",
"port-version": 0
},
"vcpkg-gfortran": {
Expand Down
Loading