From 753999d4db842a73727f7efb68ce1b6406b5913b Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Thu, 10 Aug 2023 10:02:36 -0400 Subject: set_property(TEST): Add DIRECTORY option --- Help/command/set_property.rst | 14 +++- Help/release/dev/test-properties-directory.rst | 6 ++ Source/cmSetPropertyCommand.cxx | 86 ++++++++++++++++++++-- Source/cmSetPropertyCommand.h | 12 +++ Tests/RunCMake/set_property/RunCMakeTest.cmake | 6 ++ .../RunCMake/set_property/TEST-invalid-result.txt | 1 + .../RunCMake/set_property/TEST-invalid-stderr.txt | 11 +++ Tests/RunCMake/set_property/TEST-invalid.cmake | 4 + .../set_property/TEST-subdir1/CMakeLists.txt | 3 + .../set_property/TEST-subdir2/CMakeLists.txt | 1 + Tests/RunCMake/set_property/TEST.cmake | 9 +++ 11 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 Help/release/dev/test-properties-directory.rst create mode 100644 Tests/RunCMake/set_property/TEST-invalid-result.txt create mode 100644 Tests/RunCMake/set_property/TEST-invalid-stderr.txt create mode 100644 Tests/RunCMake/set_property/TEST-invalid.cmake create mode 100644 Tests/RunCMake/set_property/TEST-subdir1/CMakeLists.txt create mode 100644 Tests/RunCMake/set_property/TEST-subdir2/CMakeLists.txt create mode 100644 Tests/RunCMake/set_property/TEST.cmake diff --git a/Help/command/set_property.rst b/Help/command/set_property.rst index fc43974..f14b63d 100644 --- a/Help/command/set_property.rst +++ b/Help/command/set_property.rst @@ -12,7 +12,8 @@ Set a named property in a given scope. [DIRECTORY ...] [TARGET_DIRECTORY ...] | INSTALL [ ...] | - TEST [ ...] | + TEST [ ...] + [DIRECTORY ] | CACHE [ ...] > [APPEND] [APPEND_STRING] PROPERTY [ ...]) @@ -91,6 +92,17 @@ It must be one of the following: :manual:`generator expressions ` for tests created by the :command:`add_test(NAME)` signature. + .. versionadded:: 3.28 + + Visibility can be set in other directory scopes using the following sub-option: + + ``DIRECTORY `` + The test property will be set in the ```` directory's scope. CMake must + already know about this directory, either by having added it through a call + to :command:`add_subdirectory` or it being the top level source directory. + Relative paths are treated as relative to the current source directory. + ```` may reference a binary directory. + ``CACHE`` Scope must name zero or more existing cache entries. diff --git a/Help/release/dev/test-properties-directory.rst b/Help/release/dev/test-properties-directory.rst new file mode 100644 index 0000000..7331ac3 --- /dev/null +++ b/Help/release/dev/test-properties-directory.rst @@ -0,0 +1,6 @@ +test-properties-directory +------------------------- + +* The ``TEST`` mode of the :command:`set_property` command gained a + ``DIRECTORY`` sub-option, which allows you to set properties on tests in + other directories. diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index de1e3b0..f9afed8 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -58,7 +58,8 @@ bool HandleSource(cmSourceFile* sf, const std::string& propertyName, bool HandleTestMode(cmExecutionStatus& status, std::set& names, const std::string& propertyName, const std::string& propertyValue, bool appendAsString, - bool appendMode, bool remove); + bool appendMode, bool remove, + cmMakefile* test_directory_makefile); bool HandleTest(cmTest* test, const std::string& propertyName, const std::string& propertyValue, bool appendAsString, bool appendMode, bool remove); @@ -184,6 +185,60 @@ bool HandleAndValidateSourceFileDirectoryScopes( return scope_options_valid; } +bool HandleTestDirectoryScopes(cmExecutionStatus& status, + std::string& test_directory, + cmMakefile*& directory_makefile) +{ + cmMakefile* current_dir_mf = &status.GetMakefile(); + if (!test_directory.empty()) { + const std::string absolute_dir_path = cmSystemTools::CollapseFullPath( + test_directory, current_dir_mf->GetCurrentSourceDirectory()); + cmMakefile* dir_mf = + status.GetMakefile().GetGlobalGenerator()->FindMakefile( + absolute_dir_path); + if (!dir_mf) { + status.SetError( + cmStrCat("given non-existent DIRECTORY ", test_directory)); + return false; + } + directory_makefile = dir_mf; + } else { + directory_makefile = current_dir_mf; + } + return true; +} + +bool HandleTestDirectoryScopeValidation(cmExecutionStatus& status, + bool test_directory_option_enabled, + std::string& test_directory) +{ + // Validate source file directory scopes. + if (test_directory_option_enabled && test_directory.empty()) { + std::string errors = "called with incorrect number of arguments " + "no value provided to the DIRECTORY option"; + status.SetError(errors); + return false; + } + return true; +} + +bool HandleAndValidateTestDirectoryScopes(cmExecutionStatus& status, + bool test_directory_option_enabled, + std::string& test_directory, + cmMakefile*& test_directory_makefile) +{ + bool scope_options_valid = + SetPropertyCommand::HandleTestDirectoryScopeValidation( + status, test_directory_option_enabled, test_directory); + if (!scope_options_valid) { + return false; + } + + scope_options_valid = SetPropertyCommand::HandleTestDirectoryScopes( + status, test_directory, test_directory_makefile); + return scope_options_valid; +} + std::string MakeSourceFilePathAbsoluteIfNeeded( cmExecutionStatus& status, const std::string& source_file_path, const bool needed) @@ -352,6 +407,9 @@ bool cmSetPropertyCommand(std::vector const& args, bool source_file_directory_option_enabled = false; bool source_file_target_option_enabled = false; + std::string test_directory; + bool test_directory_option_enabled = false; + // Parse the rest of the arguments up to the values. enum Doing { @@ -360,7 +418,8 @@ bool cmSetPropertyCommand(std::vector const& args, DoingProperty, DoingValues, DoingSourceDirectory, - DoingSourceTargetDirectory + DoingSourceTargetDirectory, + DoingTestDirectory, }; Doing doing = DoingNames; const char* sep = ""; @@ -385,12 +444,19 @@ bool cmSetPropertyCommand(std::vector const& args, scope == cmProperty::SOURCE_FILE && arg == "TARGET_DIRECTORY") { doing = DoingSourceTargetDirectory; source_file_target_option_enabled = true; + } else if (doing != DoingProperty && doing != DoingValues && + scope == cmProperty::TEST && arg == "DIRECTORY") { + doing = DoingTestDirectory; + test_directory_option_enabled = true; } else if (doing == DoingNames) { names.insert(arg); } else if (doing == DoingSourceDirectory) { source_file_directories.push_back(arg); } else if (doing == DoingSourceTargetDirectory) { source_file_target_directories.push_back(arg); + } else if (doing == DoingTestDirectory) { + test_directory = arg; + doing = DoingNone; } else if (doing == DoingProperty) { propertyName = arg; doing = DoingValues; @@ -412,12 +478,17 @@ bool cmSetPropertyCommand(std::vector const& args, } std::vector source_file_directory_makefiles; - bool file_scopes_handled = + bool source_file_scopes_handled = SetPropertyCommand::HandleAndValidateSourceFileDirectoryScopes( status, source_file_directory_option_enabled, source_file_target_option_enabled, source_file_directories, source_file_target_directories, source_file_directory_makefiles); - if (!file_scopes_handled) { + cmMakefile* test_directory_makefile; + bool test_scopes_handled = + SetPropertyCommand::HandleAndValidateTestDirectoryScopes( + status, test_directory_option_enabled, test_directory, + test_directory_makefile); + if (!(source_file_scopes_handled && test_scopes_handled)) { return false; } bool source_file_paths_should_be_absolute = @@ -441,7 +512,8 @@ bool cmSetPropertyCommand(std::vector const& args, source_file_paths_should_be_absolute); case cmProperty::TEST: return HandleTestMode(status, names, propertyName, propertyValue, - appendAsString, appendMode, remove); + appendAsString, appendMode, remove, + test_directory_makefile); case cmProperty::CACHE: return HandleCacheMode(status, names, propertyName, propertyValue, appendAsString, appendMode, remove); @@ -642,14 +714,14 @@ bool HandleSource(cmSourceFile* sf, const std::string& propertyName, bool HandleTestMode(cmExecutionStatus& status, std::set& names, const std::string& propertyName, const std::string& propertyValue, bool appendAsString, - bool appendMode, bool remove) + bool appendMode, bool remove, cmMakefile* test_makefile) { // Look for tests with all names given. std::set::iterator next; for (auto ni = names.begin(); ni != names.end(); ni = next) { next = ni; ++next; - if (cmTest* test = status.GetMakefile().GetTest(*ni)) { + if (cmTest* test = test_makefile->GetTest(*ni)) { if (HandleTest(test, propertyName, propertyValue, appendAsString, appendMode, remove)) { names.erase(ni); diff --git a/Source/cmSetPropertyCommand.h b/Source/cmSetPropertyCommand.h index 05c4873..4d9480d 100644 --- a/Source/cmSetPropertyCommand.h +++ b/Source/cmSetPropertyCommand.h @@ -33,6 +33,18 @@ bool HandleAndValidateSourceFileDirectoryScopes( std::vector& source_target_directories, std::vector& source_file_directory_makefiles); +bool HandleTestDirectoryScopes(cmExecutionStatus& status, + std::string& test_directory, + cmMakefile*& directory_makefile); + +bool HandleTestDirectoryScopeValidation(cmExecutionStatus& status, + bool test_directory_option_enabled, + std::string& test_directory); + +bool HandleAndValidateTestDirectoryScopes( + cmExecutionStatus& status, bool test_directory_option_encountered, + std::string& test_directory, cmMakefile*& test_directory_makefile); + std::string MakeSourceFilePathAbsoluteIfNeeded( cmExecutionStatus& status, const std::string& source_file_path, bool needed); void MakeSourceFilePathsAbsoluteIfNeeded( diff --git a/Tests/RunCMake/set_property/RunCMakeTest.cmake b/Tests/RunCMake/set_property/RunCMakeTest.cmake index 692c6b9..1a5498d 100644 --- a/Tests/RunCMake/set_property/RunCMakeTest.cmake +++ b/Tests/RunCMake/set_property/RunCMakeTest.cmake @@ -10,6 +10,12 @@ run_cmake(LINK_DIRECTORIES) run_cmake(LINK_LIBRARIES) run_cmake(SOURCES) run_cmake(SOURCE_FILE) +run_cmake(TEST-invalid) run_cmake(TYPE) run_cmake(USER_PROP) run_cmake(USER_PROP_INHERITED) + +set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/TEST-build") +run_cmake(TEST) +set(RunCMake_TEST_NO_CLEAN 1) +run_cmake_command(TEST-test ${CMAKE_CTEST_COMMAND} -C Debug) diff --git a/Tests/RunCMake/set_property/TEST-invalid-result.txt b/Tests/RunCMake/set_property/TEST-invalid-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/set_property/TEST-invalid-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/set_property/TEST-invalid-stderr.txt b/Tests/RunCMake/set_property/TEST-invalid-stderr.txt new file mode 100644 index 0000000..c0a40d6 --- /dev/null +++ b/Tests/RunCMake/set_property/TEST-invalid-stderr.txt @@ -0,0 +1,11 @@ +^CMake Error at TEST-invalid\.cmake:[0-9]+ \(set_property\): + set_property called with incorrect number of arguments no value provided to + the DIRECTORY option +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) + + +CMake Error at TEST-invalid\.cmake:[0-9]+ \(set_property\): + set_property given non-existent DIRECTORY nonexistent +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/set_property/TEST-invalid.cmake b/Tests/RunCMake/set_property/TEST-invalid.cmake new file mode 100644 index 0000000..6828c96 --- /dev/null +++ b/Tests/RunCMake/set_property/TEST-invalid.cmake @@ -0,0 +1,4 @@ +enable_testing() + +set_property(TEST t DIRECTORY PROPERTY PASS_REGULAR_EXPRESSION "Invalid") +set_property(TEST t DIRECTORY nonexistent PROPERTY PASS_REGULAR_EXPRESSION "Invalid") diff --git a/Tests/RunCMake/set_property/TEST-subdir1/CMakeLists.txt b/Tests/RunCMake/set_property/TEST-subdir1/CMakeLists.txt new file mode 100644 index 0000000..b1fad66 --- /dev/null +++ b/Tests/RunCMake/set_property/TEST-subdir1/CMakeLists.txt @@ -0,0 +1,3 @@ +add_test(NAME t COMMAND ${CMAKE_COMMAND} -E echo "Subdirectory") +add_test(NAME t2 COMMAND ${CMAKE_COMMAND} -E echo "Subdirectory") +add_test(NAME t3 COMMAND ${CMAKE_COMMAND} -E echo "Subdirectory") diff --git a/Tests/RunCMake/set_property/TEST-subdir2/CMakeLists.txt b/Tests/RunCMake/set_property/TEST-subdir2/CMakeLists.txt new file mode 100644 index 0000000..8621b00 --- /dev/null +++ b/Tests/RunCMake/set_property/TEST-subdir2/CMakeLists.txt @@ -0,0 +1 @@ +set_property(TEST t3 DIRECTORY ../TEST-subdir1 PROPERTY PASS_REGULAR_EXPRESSION "Subdirectory") diff --git a/Tests/RunCMake/set_property/TEST.cmake b/Tests/RunCMake/set_property/TEST.cmake new file mode 100644 index 0000000..7ef5aa3 --- /dev/null +++ b/Tests/RunCMake/set_property/TEST.cmake @@ -0,0 +1,9 @@ +enable_testing() + +add_test(NAME t COMMAND ${CMAKE_COMMAND} -E echo "Top directory") +add_subdirectory(TEST-subdir1) +add_subdirectory(TEST-subdir2) + +set_property(TEST t PROPERTY PASS_REGULAR_EXPRESSION "Top directory") +set_property(TEST t DIRECTORY TEST-subdir1 PROPERTY PASS_REGULAR_EXPRESSION "Subdirectory") +set_property(TEST t2 DIRECTORY "${CMAKE_BINARY_DIR}/TEST-subdir1" PROPERTY PASS_REGULAR_EXPRESSION "Subdirectory") -- cgit v0.12