mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-16 14:08:35 +08:00
@@ -42,6 +42,15 @@ is equivalent to
|
||||
|
||||
message(STATUS "Hello World!")
|
||||
|
||||
.. note::
|
||||
To ensure consistency of the code, the following commands are not allowed:
|
||||
|
||||
* ``if`` / ``elseif`` / ``else`` / ``endif``
|
||||
* ``while`` / ``endwhile``
|
||||
* ``foreach`` / ``endforeach``
|
||||
* ``function`` / ``endfunction``
|
||||
* ``macro`` / ``endmacro``
|
||||
|
||||
Evaluating Code
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
|
@@ -3,15 +3,32 @@
|
||||
#include "cmCMakeLanguageCommand.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <cm/string_view>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmExecutionStatus.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmRange.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
namespace {
|
||||
std::array<cm::static_string_view, 12> InvalidCommands{
|
||||
{ // clang-format off
|
||||
"function"_s, "endfunction"_s,
|
||||
"macro"_s, "endmacro"_s,
|
||||
"if"_s, "elseif"_s, "else"_s, "endif"_s,
|
||||
"while"_s, "endwhile"_s,
|
||||
"foreach"_s, "endforeach"_s
|
||||
} // clang-format on
|
||||
};
|
||||
}
|
||||
|
||||
bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
|
||||
cmExecutionStatus& status)
|
||||
@@ -64,6 +81,15 @@ bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
|
||||
startArg = 1;
|
||||
}
|
||||
|
||||
// ensure specified command is valid
|
||||
// start/end flow control commands are not allowed
|
||||
auto cmd = cmSystemTools::LowerCase(callCommand);
|
||||
if (std::find(InvalidCommands.cbegin(), InvalidCommands.cend(), cmd) !=
|
||||
InvalidCommands.cend()) {
|
||||
status.SetError(cmStrCat("invalid command specified: "_s, callCommand));
|
||||
return false;
|
||||
}
|
||||
|
||||
cmListFileFunction func;
|
||||
func.Name = callCommand;
|
||||
func.Line = context.Line;
|
||||
|
2
Tests/RunCMake/cmake_language/CallInvalidCommand.cmake
Normal file
2
Tests/RunCMake/cmake_language/CallInvalidCommand.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
cmake_language(CALL ${COMMAND})
|
4
Tests/RunCMake/cmake_language/CheckIncludeGuard.cmake
Normal file
4
Tests/RunCMake/cmake_language/CheckIncludeGuard.cmake
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
cmake_language (CALL "include_guard")
|
||||
|
||||
set (GUARD_VALUE 1)
|
19
Tests/RunCMake/cmake_language/CheckProject/CMakeLists.txt
Normal file
19
Tests/RunCMake/cmake_language/CheckProject/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
cmake_language (CALL cmake_minimum_required VERSION 3.17...3.18)
|
||||
|
||||
cmake_language (CALL project CheckProject VERSION 1.2.3 LANGUAGES C)
|
||||
|
||||
if (NOT PROJECT_NAME STREQUAL "CheckProject")
|
||||
message (SEND_ERROR "error on project() usage.")
|
||||
endif()
|
||||
|
||||
if (NOT CheckProject_VERSION VERSION_EQUAL "1.2.3")
|
||||
message (SEND_ERROR "error on project() usage.")
|
||||
endif()
|
||||
|
||||
get_property (languages GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||
if (NOT "C" IN_LIST languages)
|
||||
message (SEND_ERROR "error on project() usage.")
|
||||
endif()
|
||||
|
||||
add_library (lib SHARED lib.c)
|
0
Tests/RunCMake/cmake_language/CheckProject/lib.c
Normal file
0
Tests/RunCMake/cmake_language/CheckProject/lib.c
Normal file
@@ -2,6 +2,8 @@ include(RunCMake)
|
||||
|
||||
run_cmake(no_parameters)
|
||||
run_cmake(unknown_meta_operation)
|
||||
run_cmake(call_invalid_command)
|
||||
run_cmake(call_valid_command)
|
||||
run_cmake(call_double_evaluation)
|
||||
run_cmake(call_expanded_command)
|
||||
run_cmake(call_expanded_command_and_arguments)
|
||||
|
14
Tests/RunCMake/cmake_language/call_invalid_command.cmake
Normal file
14
Tests/RunCMake/cmake_language/call_invalid_command.cmake
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
foreach (command IN ITEMS "function" "ENDFUNCTION"
|
||||
"macro" "endMACRO"
|
||||
"if" "elseif" "else" "endif"
|
||||
"while" "endwhile"
|
||||
"foreach" "endforeach")
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -DCOMMAND=${command}
|
||||
-P "${CMAKE_CURRENT_SOURCE_DIR}/CallInvalidCommand.cmake"
|
||||
OUTPUT_QUIET ERROR_QUIET
|
||||
RESULT_VARIABLE result)
|
||||
if (NOT result)
|
||||
message (SEND_ERROR "cmake_language(CALL ${command}) unexpectedly successfull.")
|
||||
endif()
|
||||
endforeach()
|
99
Tests/RunCMake/cmake_language/call_valid_command.cmake
Normal file
99
Tests/RunCMake/cmake_language/call_valid_command.cmake
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
## check continue() usage
|
||||
set (VALUE 0)
|
||||
foreach (i RANGE 1 4)
|
||||
set (VALUE "${i}")
|
||||
cmake_language (CALL "continue")
|
||||
set (VALUE "0")
|
||||
endforeach()
|
||||
if (NOT VALUE EQUAL "4")
|
||||
message (SEND_ERROR "error on continue() usage.")
|
||||
endif()
|
||||
|
||||
|
||||
## check break() usage
|
||||
set (VALUE 0)
|
||||
foreach (i RANGE 1 4)
|
||||
set (VALUE "${i}")
|
||||
cmake_language (CALL "break")
|
||||
set (VALUE 0)
|
||||
endforeach()
|
||||
if (NOT VALUE EQUAL "1")
|
||||
message (SEND_ERROR "error on break() usage.")
|
||||
endif()
|
||||
|
||||
|
||||
## check return() usage in macro
|
||||
macro (call_return_in_macro)
|
||||
cmake_language (CALL "return")
|
||||
set (VALUE 1)
|
||||
endmacro()
|
||||
function (wrapper)
|
||||
call_return_in_macro()
|
||||
set (VALUE 1 PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
set (VALUE 0)
|
||||
wrapper()
|
||||
if (NOT VALUE EQUAL "0")
|
||||
message (SEND_ERROR "error on return() usage in macro.")
|
||||
endif()
|
||||
|
||||
set (VALUE 0)
|
||||
cmake_language (CALL "wrapper")
|
||||
if (NOT VALUE EQUAL "0")
|
||||
message (SEND_ERROR "error on return() usage in macro.")
|
||||
endif()
|
||||
|
||||
function (wrapper2)
|
||||
cmake_language (CALL "call_return_in_macro")
|
||||
set (VALUE 1 PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
set (VALUE 0)
|
||||
wrapper2()
|
||||
if (NOT VALUE EQUAL "0")
|
||||
message (SEND_ERROR "error on return() usage in macro.")
|
||||
endif()
|
||||
|
||||
set (VALUE 0)
|
||||
cmake_language (CALL "wrapper2")
|
||||
if (NOT VALUE EQUAL "0")
|
||||
message (SEND_ERROR "error on return() usage in macro.")
|
||||
endif()
|
||||
|
||||
## check return() usage in function
|
||||
function (call_return_in_function)
|
||||
cmake_language (CALL "return")
|
||||
set (VALUE 1 PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
set (VALUE 0)
|
||||
call_return_in_function()
|
||||
if (NOT VALUE EQUAL "0")
|
||||
message (SEND_ERROR "error on return() usage in function.")
|
||||
endif()
|
||||
|
||||
set (VALUE 0)
|
||||
cmake_language (CALL "call_return_in_function")
|
||||
if (NOT VALUE EQUAL "0")
|
||||
message (SEND_ERROR "error on return() usage in function.")
|
||||
endif()
|
||||
|
||||
|
||||
## check usage of include_guard()
|
||||
set (GUARD_VALUE 0)
|
||||
include ("${CMAKE_CURRENT_SOURCE_DIR}/CheckIncludeGuard.cmake")
|
||||
if (NOT GUARD_VALUE EQUAL "1")
|
||||
message (SEND_ERROR "error on include_guard() on first include.")
|
||||
endif()
|
||||
|
||||
set (GUARD_VALUE 0)
|
||||
include ("${CMAKE_CURRENT_SOURCE_DIR}/CheckIncludeGuard.cmake")
|
||||
if (NOT GUARD_VALUE EQUAL "0")
|
||||
message (SEND_ERROR "error on include_guard() on second include.")
|
||||
endif()
|
||||
|
||||
|
||||
## check usage of cmake_minimum_required() and project()
|
||||
add_subdirectory (CheckProject)
|
Reference in New Issue
Block a user