From 2579503f450f99166408d25161d950450cda0544 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 6 Jun 2022 12:25:51 -0400 Subject: PrintHelpers: Fix target SOURCES property It's been a long-standing bug in CMakePrintHelpers that the cmake_print_properties() function cannot print the SOURCES property of a requested TARGET, confusing it with a request to print properties of SOURCES. We work around this by parsing the arguments in two stages, so that a SOURCES that comes after the PROPERTIES keyword is handled differently from a SOURCES that comes before it. This adds the restriction that the "mode" keyword (TARGETS SOURCES DIRECTORIES etc...) and its arguments **must** precede the PROPERTIES keyword and its arguments. In other words: 1. Both of these are now valid and will be interpreted correctly, whereas previously only the first was, and the second caused a FATAL_ERROR: cmake_print_properties(SOURCES foo.c PROPERTIES LANGUAGE) cmake_print_properties(TARGETS foo PROPERTIES SOURCES) 2. This, OTOH, which used to be valid, no longer is, and will trigger a FATAL_ERROR: cmake_print_properties(PROPERTIES LANGUAGE SOURCES foo.c) Fixes: #14883 --- Modules/CMakePrintHelpers.cmake | 49 +++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/Modules/CMakePrintHelpers.cmake b/Modules/CMakePrintHelpers.cmake index 8c25a73..0af2d3f 100644 --- a/Modules/CMakePrintHelpers.cmake +++ b/Modules/CMakePrintHelpers.cmake @@ -56,17 +56,34 @@ endfunction() function(cmake_print_properties) set(options ) set(oneValueArgs ) - set(multiValueArgs TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES PROPERTIES ) + set(cpp_multiValueArgs PROPERTIES ) + set(cppmode_multiValueArgs TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES ) - cmake_parse_arguments(CPP "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + string(JOIN " " _mode_names ${cppmode_multiValueArgs}) + set(_missing_mode_message + "Mode keyword missing in cmake_print_properties() call, there must be exactly one of ${_mode_names}") - if(CPP_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "Unknown keywords given to cmake_print_properties(): \"${CPP_UNPARSED_ARGUMENTS}\"") + cmake_parse_arguments( + CPP "${options}" "${oneValueArgs}" "${cpp_multiValueArgs}" ${ARGN}) + + if(NOT CPP_PROPERTIES) + message(FATAL_ERROR + "Required argument PROPERTIES missing in cmake_print_properties() call") return() endif() - if(NOT CPP_PROPERTIES) - message(FATAL_ERROR "Required argument PROPERTIES missing in cmake_print_properties() call") + if(NOT CPP_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "${_missing_mode_message}") + return() + endif() + + cmake_parse_arguments( + CPPMODE "${options}" "${oneValueArgs}" "${cppmode_multiValueArgs}" + ${CPP_UNPARSED_ARGUMENTS}) + + if(CPPMODE_UNPARSED_ARGUMENTS) + message(FATAL_ERROR + "Unknown keywords given to cmake_print_properties(): \"${CPPMODE_UNPARSED_ARGUMENTS}\"") return() endif() @@ -74,32 +91,32 @@ function(cmake_print_properties) set(items) set(keyword) - if(CPP_TARGETS) - set(items ${CPP_TARGETS}) + if(CPPMODE_TARGETS) + set(items ${CPPMODE_TARGETS}) set(mode ${mode} TARGETS) set(keyword TARGET) endif() - if(CPP_SOURCES) - set(items ${CPP_SOURCES}) + if(CPPMODE_SOURCES) + set(items ${CPPMODE_SOURCES}) set(mode ${mode} SOURCES) set(keyword SOURCE) endif() - if(CPP_TESTS) - set(items ${CPP_TESTS}) + if(CPPMODE_TESTS) + set(items ${CPPMODE_TESTS}) set(mode ${mode} TESTS) set(keyword TEST) endif() - if(CPP_DIRECTORIES) - set(items ${CPP_DIRECTORIES}) + if(CPPMODE_DIRECTORIES) + set(items ${CPPMODE_DIRECTORIES}) set(mode ${mode} DIRECTORIES) set(keyword DIRECTORY) endif() - if(CPP_CACHE_ENTRIES) - set(items ${CPP_CACHE_ENTRIES}) + if(CPPMODE_CACHE_ENTRIES) + set(items ${CPPMODE_CACHE_ENTRIES}) set(mode ${mode} CACHE_ENTRIES) # This is a workaround for the fact that passing `CACHE` as an argument to # set() causes a cache variable to be set. -- cgit v0.12 From 5fa70e1738902ea7cdec11f30622705c0d9a2149 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 6 Jun 2022 12:27:09 -0400 Subject: PrintHelpers: Rewrite a few more error messages --- Modules/CMakePrintHelpers.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Modules/CMakePrintHelpers.cmake b/Modules/CMakePrintHelpers.cmake index 0af2d3f..f40b06c 100644 --- a/Modules/CMakePrintHelpers.cmake +++ b/Modules/CMakePrintHelpers.cmake @@ -125,13 +125,14 @@ function(cmake_print_properties) endif() if(NOT mode) - message(FATAL_ERROR "Mode keyword missing in cmake_print_properties() call, must be one of TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES PROPERTIES") + message(FATAL_ERROR "${_missing_mode_message}") return() endif() list(LENGTH mode modeLength) if("${modeLength}" GREATER 1) - message(FATAL_ERROR "Multiple mode keyword used in cmake_print_properties() call, it must be exactly one of TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES PROPERTIES") + message(FATAL_ERROR + "Multiple mode keywords used in cmake_print_properties() call, there must be exactly one of ${_mode_names}.") return() endif() -- cgit v0.12 From d87ed4d88fb3dce4eca55d6cfc512f7769ac1bd8 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 6 Jun 2022 11:37:51 -0400 Subject: PrintHelpers: Fix indentation --- Modules/CMakePrintHelpers.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/CMakePrintHelpers.cmake b/Modules/CMakePrintHelpers.cmake index f40b06c..1a623db 100644 --- a/Modules/CMakePrintHelpers.cmake +++ b/Modules/CMakePrintHelpers.cmake @@ -142,8 +142,8 @@ function(cmake_print_properties) set(itemExists TRUE) if(keyword STREQUAL "TARGET") if(NOT TARGET ${item}) - set(itemExists FALSE) - string(APPEND msg "\n No such TARGET \"${item}\" !\n\n") + set(itemExists FALSE) + string(APPEND msg "\n No such TARGET \"${item}\" !\n\n") endif() endif() -- cgit v0.12 From e52b9e127053fa404d964ee2df1ab3915fc43565 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 6 Jun 2022 11:38:27 -0400 Subject: PrintHelpers: Document argument order restriction --- Modules/CMakePrintHelpers.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Modules/CMakePrintHelpers.cmake b/Modules/CMakePrintHelpers.cmake index 1a623db..6d6355c 100644 --- a/Modules/CMakePrintHelpers.cmake +++ b/Modules/CMakePrintHelpers.cmake @@ -19,7 +19,10 @@ e.g. for debugging. This function prints the values of the properties of the given targets, source files, directories, tests or cache entries. Exactly one of the -scope keywords must be used. Example:: +scope keywords must be used. The scope keyword and its arguments must +come before the ``PROPERTIES`` keyword, in the arguments list. + +Example:: cmake_print_properties(TARGETS foo bar PROPERTIES LOCATION INTERFACE_INCLUDE_DIRECTORIES) -- cgit v0.12 From b7ddfcfe084ac1c2652dab524938f84dc37f6230 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 6 Jun 2022 11:39:59 -0400 Subject: cmake_print_properties(): Update grammar docs --- Modules/CMakePrintHelpers.cmake | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/CMakePrintHelpers.cmake b/Modules/CMakePrintHelpers.cmake index 6d6355c..fb201dc 100644 --- a/Modules/CMakePrintHelpers.cmake +++ b/Modules/CMakePrintHelpers.cmake @@ -10,12 +10,12 @@ e.g. for debugging. :: - cmake_print_properties([TARGETS target1 .. targetN] - [SOURCES source1 .. sourceN] - [DIRECTORIES dir1 .. dirN] - [TESTS test1 .. testN] - [CACHE_ENTRIES entry1 .. entryN] - PROPERTIES prop1 .. propN ) + cmake_print_properties( ...] | + SOURCES [ ...] | + DIRECTORIES [ ...] | + TESTS [ ...] | + CACHE_ENTRIES [ ...] > + PROPERTIES [ ...] ) This function prints the values of the properties of the given targets, source files, directories, tests or cache entries. Exactly one of the -- cgit v0.12 From d8dcfa7776002756efbc30e45be305e425103e31 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 5 Jun 2022 13:18:16 -0400 Subject: Tests: Add tests for CMakePrintHelpers Add three tests in Tests/RunCMake/PrintHelpers, meant to verify basic functionality of the module. Tests are: * Variables: Test the results of a cmake_print_variables() call on two variables set within the test script. * Properties: Test cmake_print_properties() calls on a pair of SOURCES and a pair of TARGETS, printing some basic properties. * PropertiesSources: Specifically verify the results of a cmake_print_properties() call for the SOURCES property of a TARGET. Prior to the fix introduced alongside these tests, it was a known bug that such a request caused a FATAL_ERROR. --- Tests/RunCMake/CMakeLists.txt | 1 + Tests/RunCMake/PrintHelpers/CMakeLists.txt | 3 +++ Tests/RunCMake/PrintHelpers/Properties-stdout.txt | 14 ++++++++++++ Tests/RunCMake/PrintHelpers/Properties.cmake | 26 ++++++++++++++++++++++ .../PrintHelpers/PropertiesSources-stdout.cmake | 8 +++++++ .../RunCMake/PrintHelpers/PropertiesSources.cmake | 19 ++++++++++++++++ Tests/RunCMake/PrintHelpers/RunCMakeTest.cmake | 5 +++++ Tests/RunCMake/PrintHelpers/Variables-stdout.txt | 1 + Tests/RunCMake/PrintHelpers/Variables.cmake | 6 +++++ Tests/RunCMake/PrintHelpers/nothing.c | 6 +++++ Tests/RunCMake/PrintHelpers/nothing.h | 8 +++++++ Tests/RunCMake/PrintHelpers/rot13.c | 15 +++++++++++++ Tests/RunCMake/PrintHelpers/rot13.h | 9 ++++++++ Tests/RunCMake/PrintHelpers/something.c | 7 ++++++ Tests/RunCMake/PrintHelpers/something.h | 8 +++++++ 15 files changed, 136 insertions(+) create mode 100644 Tests/RunCMake/PrintHelpers/CMakeLists.txt create mode 100644 Tests/RunCMake/PrintHelpers/Properties-stdout.txt create mode 100644 Tests/RunCMake/PrintHelpers/Properties.cmake create mode 100644 Tests/RunCMake/PrintHelpers/PropertiesSources-stdout.cmake create mode 100644 Tests/RunCMake/PrintHelpers/PropertiesSources.cmake create mode 100644 Tests/RunCMake/PrintHelpers/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/PrintHelpers/Variables-stdout.txt create mode 100644 Tests/RunCMake/PrintHelpers/Variables.cmake create mode 100644 Tests/RunCMake/PrintHelpers/nothing.c create mode 100644 Tests/RunCMake/PrintHelpers/nothing.h create mode 100644 Tests/RunCMake/PrintHelpers/rot13.c create mode 100644 Tests/RunCMake/PrintHelpers/rot13.h create mode 100644 Tests/RunCMake/PrintHelpers/something.c create mode 100644 Tests/RunCMake/PrintHelpers/something.h diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 3ca01ec..a519dab 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -464,6 +464,7 @@ add_RunCMake_test(load_cache) add_RunCMake_test(math) add_RunCMake_test(message) add_RunCMake_test(option) +add_RunCMake_test(PrintHelpers) add_RunCMake_test(project -DCMake_TEST_RESOURCES=${CMake_TEST_RESOURCES}) add_RunCMake_test(project_injected) add_RunCMake_test(DependencyProviders) diff --git a/Tests/RunCMake/PrintHelpers/CMakeLists.txt b/Tests/RunCMake/PrintHelpers/CMakeLists.txt new file mode 100644 index 0000000..6d4fe63 --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.23) +project(${RunCMake_TEST} C) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/PrintHelpers/Properties-stdout.txt b/Tests/RunCMake/PrintHelpers/Properties-stdout.txt new file mode 100644 index 0000000..c52f7b6 --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/Properties-stdout.txt @@ -0,0 +1,14 @@ +.*Properties for TARGET nothing:.* +.*nothing.LINKER_LANGUAGE = .* +.*nothing.TYPE = \"STATIC_LIBRARY\".* +.*Properties for TARGET something:.* +.*something.LINKER_LANGUAGE = .* +.*something.TYPE = \"EXECUTABLE\".* ++ +.* +.*Properties for SOURCE nothing.c:.* +.*nothing.c.COMPILE_DEFINITIONS = .* +.*nothing.c.LANGUAGE = \"C\".* +.*Properties for SOURCE something.c:.* +.*something.c.COMPILE_DEFINITIONS = \"SOMETHING=1\".* +.*something.c.LANGUAGE = \"C\".* diff --git a/Tests/RunCMake/PrintHelpers/Properties.cmake b/Tests/RunCMake/PrintHelpers/Properties.cmake new file mode 100644 index 0000000..3e8ecd1 --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/Properties.cmake @@ -0,0 +1,26 @@ +enable_language(C) + +set_property(SOURCE nothing.c PROPERTY LANGUAGE C) +set_property(SOURCE something.c PROPERTY + COMPILE_DEFINITIONS SOMETHING=1) + +add_library(nothing STATIC nothing.c nothing.h) + +add_executable(something something.c something.h) +target_link_libraries(something PUBLIC nothing) + +include(CMakePrintHelpers) + +cmake_print_properties( + TARGETS nothing something + PROPERTIES + LINKER_LANGUAGE + TYPE +) + +cmake_print_properties( + SOURCES nothing.c something.c + PROPERTIES + COMPILE_DEFINITIONS + LANGUAGE +) diff --git a/Tests/RunCMake/PrintHelpers/PropertiesSources-stdout.cmake b/Tests/RunCMake/PrintHelpers/PropertiesSources-stdout.cmake new file mode 100644 index 0000000..93b3df0 --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/PropertiesSources-stdout.cmake @@ -0,0 +1,8 @@ +.*Properties for TARGET rot13:.* +.*rot13.SOURCES = \"rot13.c;rot13.h\".* +.*rot13.POSITION_INDEPENDENT_CODE = \"True\".* ++ +.*--.* +.*Properties for SOURCE rot13.c:.* +.*rot13.c.LOCATION = \"[^\"]*/PrintHelpers/rot13.c\".* +.*rot13.c.LANGUAGE = \"C\".* diff --git a/Tests/RunCMake/PrintHelpers/PropertiesSources.cmake b/Tests/RunCMake/PrintHelpers/PropertiesSources.cmake new file mode 100644 index 0000000..f102b94 --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/PropertiesSources.cmake @@ -0,0 +1,19 @@ +set_property(SOURCE rot13.c PROPERTY LANGUAGE C) + +add_library(rot13 SHARED rot13.c rot13.h) + +include(CMakePrintHelpers) + +cmake_print_properties( + TARGETS rot13 + PROPERTIES + SOURCES + POSITION_INDEPENDENT_CODE +) + +cmake_print_properties( + SOURCES rot13.c + PROPERTIES + LOCATION + LANGUAGE +) diff --git a/Tests/RunCMake/PrintHelpers/RunCMakeTest.cmake b/Tests/RunCMake/PrintHelpers/RunCMakeTest.cmake new file mode 100644 index 0000000..5b8ad0c --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/RunCMakeTest.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +run_cmake(Variables) +run_cmake(Properties) +run_cmake(PropertiesSources) diff --git a/Tests/RunCMake/PrintHelpers/Variables-stdout.txt b/Tests/RunCMake/PrintHelpers/Variables-stdout.txt new file mode 100644 index 0000000..ca95c8d --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/Variables-stdout.txt @@ -0,0 +1 @@ +-- source_dir="src" ; binary_dir="build" diff --git a/Tests/RunCMake/PrintHelpers/Variables.cmake b/Tests/RunCMake/PrintHelpers/Variables.cmake new file mode 100644 index 0000000..88f5ad1 --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/Variables.cmake @@ -0,0 +1,6 @@ + +set(source_dir "src") +set(binary_dir "build") + +include(CMakePrintHelpers) +cmake_print_variables(source_dir binary_dir) diff --git a/Tests/RunCMake/PrintHelpers/nothing.c b/Tests/RunCMake/PrintHelpers/nothing.c new file mode 100644 index 0000000..32b7b39 --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/nothing.c @@ -0,0 +1,6 @@ +#include "nothing.h" + +void nothing() +{ + (void*)0; +} diff --git a/Tests/RunCMake/PrintHelpers/nothing.h b/Tests/RunCMake/PrintHelpers/nothing.h new file mode 100644 index 0000000..ae86667 --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/nothing.h @@ -0,0 +1,8 @@ +#ifndef NOTHING_H +#define NOTHING_H + +#include + +void nothing(); + +#endif diff --git a/Tests/RunCMake/PrintHelpers/rot13.c b/Tests/RunCMake/PrintHelpers/rot13.c new file mode 100644 index 0000000..053bebd --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/rot13.c @@ -0,0 +1,15 @@ +#include "rot13.h" + +void rot13(char* in) +{ + char* end = in + strlen(in); + for (char* c = in; c < end; c++) { + if (*c >= 'a' && *c <= 'z') { + *c += (*c < 'n') ? 13 : -13; + continue; + } + if (*c >= 'A' && *c <= 'Z') { + *c += (*c < 'N') ? 13 : -13; + } + } +} diff --git a/Tests/RunCMake/PrintHelpers/rot13.h b/Tests/RunCMake/PrintHelpers/rot13.h new file mode 100644 index 0000000..9afea5f --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/rot13.h @@ -0,0 +1,9 @@ +#ifndef ROT13_H +#define ROT13_H + +#include +#include + +void rot13(char* in); + +#endif diff --git a/Tests/RunCMake/PrintHelpers/something.c b/Tests/RunCMake/PrintHelpers/something.c new file mode 100644 index 0000000..a2bc425 --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/something.c @@ -0,0 +1,7 @@ +#include "something.h" + +int main() +{ + nothing(); + return 0; +} diff --git a/Tests/RunCMake/PrintHelpers/something.h b/Tests/RunCMake/PrintHelpers/something.h new file mode 100644 index 0000000..667ee99 --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/something.h @@ -0,0 +1,8 @@ +#ifndef SOMETHING_H +#define SOMETHING_H + +#include + +#include "nothing.h" + +#endif -- cgit v0.12