mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-13 01:29:02 -05:00
Merge topic 'feature/include_guard'
c96f43b7include_guard: add tests for the feature80f1221finclude_guard: add doc pages and a release note85b52a04include_guard: add vim syntax highlighting rulesd44bd1c2include_guard: implement new command Acked-by: Kitware Robot <kwrobot@kitware.com> Reviewed-by: Craig Scott <craig.scott@crascit.com> Merge-request: !928
This commit is contained in:
@@ -203,6 +203,9 @@ syn keyword cmakeKWinclude_directories contained
|
||||
syn keyword cmakeKWinclude_external_msproject contained
|
||||
\ GUID MAP_IMPORTED_CONFIG_ PLATFORM TYPE WIX
|
||||
|
||||
syn keyword cmakeKWinclude_guard contained
|
||||
\ DIRECTORY GLOBAL
|
||||
|
||||
syn keyword cmakeKWinstall contained
|
||||
\ ARCHIVE BUNDLE CODE COMPONENT CONFIGURATIONS CVS DESTDIR DESTINATION DIRECTORY DIRECTORY_PERMISSIONS DLL EXCLUDE_FROM_ALL EXPORT EXPORT_ANDROID_MK EXPORT_LINK_INTERFACE_LIBRARIES FILES FILES_MATCHING FILE_PERMISSIONS FRAMEWORK GROUP_EXECUTE GROUP_READ GROUP_WRITE IMPORTED_ INCLUDES INSTALL_PREFIX INTERFACE_INCLUDE_DIRECTORIES LIBRARY MACOSX_BUNDLE MESSAGE_NEVER NAMELINK_ONLY NAMELINK_SKIP NAMESPACE NDK OBJECTS OPTIONAL OWNER_EXECUTE OWNER_READ OWNER_WRITE PATTERN PERMISSIONS POST_INSTALL_SCRIPT PRE_INSTALL_SCRIPT PRIVATE_HEADER PROGRAMS PUBLIC_HEADER REGEX RENAME RESOURCE RUNTIME SCRIPT SETGID SETUID SOVERSION TARGETS TRUE USE_SOURCE_PERMISSIONS VERSION WORLD_EXECUTE WORLD_READ WORLD_WRITE
|
||||
|
||||
@@ -327,7 +330,7 @@ syn keyword cmakeGeneratorExpressions contained
|
||||
syn case ignore
|
||||
|
||||
syn keyword cmakeCommand
|
||||
\ add_compile_options add_custom_command add_custom_target add_definitions add_dependencies add_executable add_library add_subdirectory add_test aux_source_directory break build_command cmake_host_system_information cmake_minimum_required cmake_parse_arguments cmake_policy configure_file continue create_test_sourcelist ctest_build ctest_configure ctest_coverage ctest_empty_binary_directory ctest_memcheck ctest_read_custom_files ctest_run_script ctest_sleep ctest_start ctest_submit ctest_test ctest_update ctest_upload define_property enable_language enable_testing endfunction endmacro execute_process export file find_file find_library find_package find_path find_program fltk_wrap_ui function get_cmake_property get_directory_property get_filename_component get_property get_source_file_property get_target_property get_test_property include include_directories include_external_msproject include_regular_expression install link_directories list load_cache load_command macro mark_as_advanced math message option project qt_wrap_cpp qt_wrap_ui remove_definitions return separate_arguments set set_directory_properties set_property set_source_files_properties set_target_properties set_tests_properties site_name source_group string target_compile_definitions target_compile_features target_compile_options target_include_directories target_link_libraries target_sources try_compile try_run unset variable_watch
|
||||
\ add_compile_options add_custom_command add_custom_target add_definitions add_dependencies add_executable add_library add_subdirectory add_test aux_source_directory break build_command cmake_host_system_information cmake_minimum_required cmake_parse_arguments cmake_policy configure_file continue create_test_sourcelist ctest_build ctest_configure ctest_coverage ctest_empty_binary_directory ctest_memcheck ctest_read_custom_files ctest_run_script ctest_sleep ctest_start ctest_submit ctest_test ctest_update ctest_upload define_property enable_language enable_testing endfunction endmacro execute_process export file find_file find_library find_package find_path find_program fltk_wrap_ui function get_cmake_property get_directory_property get_filename_component get_property get_source_file_property get_target_property get_test_property include include_directories include_external_msproject include_guard include_regular_expression install link_directories list load_cache load_command macro mark_as_advanced math message option project qt_wrap_cpp qt_wrap_ui remove_definitions return separate_arguments set set_directory_properties set_property set_source_files_properties set_target_properties set_tests_properties site_name source_group string target_compile_definitions target_compile_features target_compile_options target_include_directories target_link_libraries target_sources try_compile try_run unset variable_watch
|
||||
\ nextgroup=cmakeArguments
|
||||
|
||||
syn keyword cmakeCommandConditional
|
||||
@@ -420,6 +423,7 @@ hi def link cmakeKWif ModeMsg
|
||||
hi def link cmakeKWinclude ModeMsg
|
||||
hi def link cmakeKWinclude_directories ModeMsg
|
||||
hi def link cmakeKWinclude_external_msproject ModeMsg
|
||||
hi def link cmakeKWinclude_guard ModeMsg
|
||||
hi def link cmakeKWinstall ModeMsg
|
||||
hi def link cmakeKWinstall_files ModeMsg
|
||||
hi def link cmakeKWinstall_programs ModeMsg
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
include_guard
|
||||
-------------
|
||||
|
||||
Provides an include guard for the file currently being processed by CMake.
|
||||
|
||||
::
|
||||
|
||||
include_guard([DIRECTORY|GLOBAL])
|
||||
|
||||
Sets up an include guard for the current CMake file (see the
|
||||
:variable:`CMAKE_CURRENT_LIST_FILE` variable documentation).
|
||||
|
||||
CMake will end its processing of the current file at the location of the
|
||||
:command:`include_guard` command if the current file has already been
|
||||
processed for the applicable scope (see below). This provides functionality
|
||||
similar to the include guards commonly used in source headers or to the
|
||||
``#pragma once`` directive. If the current file has been processed previously
|
||||
for the applicable scope, the effect is as though :command:`return` had been
|
||||
called. Do not call this command from inside a function being defined within
|
||||
the current file.
|
||||
|
||||
An optional argument specifying the scope of the guard may be provided.
|
||||
Possible values for the option are:
|
||||
|
||||
``DIRECTORY``
|
||||
The include guard applies within the current directory and below. The file
|
||||
will only be included once within this directory scope, but may be included
|
||||
again by other files outside of this directory (i.e. a parent directory or
|
||||
another directory not pulled in by :command:`add_subdirectory` or
|
||||
:command:`include` from the current file or its children).
|
||||
|
||||
``GLOBAL``
|
||||
The include guard applies globally to the whole build. The current file
|
||||
will only be included once regardless of the scope.
|
||||
|
||||
If no arguments given, ``include_guard`` has the same scope as a variable,
|
||||
meaning that the include guard effect is isolated by the most recent
|
||||
function scope or current directory if no inner function scopes exist.
|
||||
In this case the command behavior is the same as:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
if(__CURRENT_FILE_VAR__)
|
||||
return()
|
||||
endif()
|
||||
set(__CURRENT_FILE_VAR__ TRUE)
|
||||
@@ -44,6 +44,7 @@ These commands are always available.
|
||||
/command/get_property
|
||||
/command/if
|
||||
/command/include
|
||||
/command/include_guard
|
||||
/command/list
|
||||
/command/macro
|
||||
/command/mark_as_advanced
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
include_guard
|
||||
-------------
|
||||
|
||||
* The :command:`include_guard` command was introduced to allow guarding
|
||||
CMake scripts from being included more than once. The command supports
|
||||
``DIRECTORY`` and ``GLOBAL`` options to adjust the corresponding include guard
|
||||
scope. If no options given, include guard is similar to basic variable-based
|
||||
check.
|
||||
@@ -469,6 +469,8 @@ set(SRCS
|
||||
cmIncludeDirectoryCommand.h
|
||||
cmIncludeExternalMSProjectCommand.cxx
|
||||
cmIncludeExternalMSProjectCommand.h
|
||||
cmIncludeGuardCommand.cxx
|
||||
cmIncludeGuardCommand.h
|
||||
cmIncludeRegularExpressionCommand.cxx
|
||||
cmIncludeRegularExpressionCommand.h
|
||||
cmInstallCommand.cxx
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "cmIfCommand.h"
|
||||
#include "cmIncludeCommand.h"
|
||||
#include "cmIncludeDirectoryCommand.h"
|
||||
#include "cmIncludeGuardCommand.h"
|
||||
#include "cmIncludeRegularExpressionCommand.h"
|
||||
#include "cmInstallCommand.h"
|
||||
#include "cmInstallFilesCommand.h"
|
||||
@@ -132,6 +133,7 @@ void GetScriptingCommands(cmState* state)
|
||||
state->AddBuiltinCommand("get_property", new cmGetPropertyCommand);
|
||||
state->AddBuiltinCommand("if", new cmIfCommand);
|
||||
state->AddBuiltinCommand("include", new cmIncludeCommand);
|
||||
state->AddBuiltinCommand("include_guard", new cmIncludeGuardCommand);
|
||||
state->AddBuiltinCommand("list", new cmListCommand);
|
||||
state->AddBuiltinCommand("macro", new cmMacroCommand);
|
||||
state->AddBuiltinCommand("make_directory", new cmMakeDirectoryCommand);
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmIncludeGuardCommand.h"
|
||||
|
||||
#include "cmExecutionStatus.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmStateDirectory.h"
|
||||
#include "cmStateSnapshot.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmake.h"
|
||||
|
||||
namespace {
|
||||
|
||||
enum IncludeGuardScope
|
||||
{
|
||||
VARIABLE,
|
||||
DIRECTORY,
|
||||
GLOBAL
|
||||
};
|
||||
|
||||
std::string GetIncludeGuardVariableName(std::string const& filePath)
|
||||
{
|
||||
std::string result = "__INCGUARD_";
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
result += cmSystemTools::ComputeStringMD5(filePath);
|
||||
#else
|
||||
result += cmSystemTools::MakeCidentifier(filePath);
|
||||
#endif
|
||||
result += "__";
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CheckIncludeGuardIsSet(cmMakefile* mf, std::string const& includeGuardVar)
|
||||
{
|
||||
if (mf->GetProperty(includeGuardVar)) {
|
||||
return true;
|
||||
}
|
||||
cmStateSnapshot dirSnapshot =
|
||||
mf->GetStateSnapshot().GetBuildsystemDirectoryParent();
|
||||
while (dirSnapshot.GetState()) {
|
||||
cmStateDirectory stateDir = dirSnapshot.GetDirectory();
|
||||
if (stateDir.GetProperty(includeGuardVar)) {
|
||||
return true;
|
||||
}
|
||||
dirSnapshot = dirSnapshot.GetBuildsystemDirectoryParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// cmIncludeGuardCommand
|
||||
bool cmIncludeGuardCommand::InitialPass(std::vector<std::string> const& args,
|
||||
cmExecutionStatus& status)
|
||||
{
|
||||
if (args.size() > 1) {
|
||||
this->SetError(
|
||||
"given an invalid number of arguments. The command takes at "
|
||||
"most 1 argument.");
|
||||
return false;
|
||||
}
|
||||
|
||||
IncludeGuardScope scope = VARIABLE;
|
||||
|
||||
if (!args.empty()) {
|
||||
std::string const& arg = args[0];
|
||||
if (arg == "DIRECTORY") {
|
||||
scope = DIRECTORY;
|
||||
} else if (arg == "GLOBAL") {
|
||||
scope = GLOBAL;
|
||||
} else {
|
||||
this->SetError("given an invalid scope: " + arg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string includeGuardVar = GetIncludeGuardVariableName(
|
||||
this->Makefile->GetDefinition("CMAKE_CURRENT_LIST_FILE"));
|
||||
|
||||
cmMakefile* const mf = this->Makefile;
|
||||
|
||||
switch (scope) {
|
||||
case VARIABLE:
|
||||
if (mf->IsDefinitionSet(includeGuardVar)) {
|
||||
status.SetReturnInvoked();
|
||||
return true;
|
||||
}
|
||||
mf->AddDefinition(includeGuardVar, true);
|
||||
break;
|
||||
case DIRECTORY:
|
||||
if (CheckIncludeGuardIsSet(mf, includeGuardVar)) {
|
||||
status.SetReturnInvoked();
|
||||
return true;
|
||||
}
|
||||
mf->SetProperty(includeGuardVar, "TRUE");
|
||||
break;
|
||||
case GLOBAL:
|
||||
cmake* const cm = mf->GetCMakeInstance();
|
||||
if (cm->GetProperty(includeGuardVar)) {
|
||||
status.SetReturnInvoked();
|
||||
return true;
|
||||
}
|
||||
cm->SetProperty(includeGuardVar, "TRUE");
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#ifndef cmIncludeGuardCommand_h
|
||||
#define cmIncludeGuardCommand_h
|
||||
|
||||
#include "cmConfigure.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cmCommand.h"
|
||||
|
||||
class cmExecutionStatus;
|
||||
|
||||
/** \class cmIncludeGuardCommand
|
||||
* \brief cmIncludeGuardCommand identical to C++ #pragma_once command
|
||||
* Can work in 3 modes: GLOBAL (works on global properties),
|
||||
* DIRECTORY(use directory property), VARIABLE(unnamed overload without
|
||||
* arguments) define an ordinary variable to be used as include guard checker
|
||||
*/
|
||||
class cmIncludeGuardCommand : public cmCommand
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This is a virtual constructor for the command.
|
||||
*/
|
||||
cmCommand* Clone() CM_OVERRIDE { return new cmIncludeGuardCommand; }
|
||||
|
||||
/**
|
||||
* This is called when the command is first encountered in
|
||||
* the CMakeLists.txt file.
|
||||
*/
|
||||
bool InitialPass(std::vector<std::string> const& args,
|
||||
cmExecutionStatus& status) CM_OVERRIDE;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -215,6 +215,7 @@ add_RunCMake_test(get_property)
|
||||
add_RunCMake_test(if)
|
||||
add_RunCMake_test(include)
|
||||
add_RunCMake_test(include_directories)
|
||||
add_RunCMake_test(include_guard)
|
||||
add_RunCMake_test(list)
|
||||
add_RunCMake_test(message)
|
||||
add_RunCMake_test(project -DCMake_TEST_RESOURCES=${CMake_TEST_RESOURCES})
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
cmake_minimum_required(VERSION 3.9)
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
||||
@@ -0,0 +1,19 @@
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/Scripts")
|
||||
|
||||
# Test include_guard with DIRECTORY scope
|
||||
|
||||
# Add subdirectory which includes DirScript three times:
|
||||
# 1. Include at inner function scope
|
||||
# 2. At directory scope
|
||||
# 3. At another subdirectory to check that the guard is checked
|
||||
# against parent directories
|
||||
add_subdirectory(sub_dir_script1)
|
||||
# Add another directory which includes DirScript
|
||||
add_subdirectory(sub_dir_script2)
|
||||
|
||||
# check inclusions count
|
||||
get_property(dir_count GLOBAL PROPERTY DIR_SCRIPT_COUNT)
|
||||
if(NOT dir_count EQUAL 2)
|
||||
message(FATAL_ERROR
|
||||
"Wrong DIR_SCRIPT_COUNT value: ${dir_count}, expected: 2")
|
||||
endif()
|
||||
@@ -0,0 +1,11 @@
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/Scripts")
|
||||
|
||||
# Test GLOBAL include guard
|
||||
add_subdirectory(global_script_dir)
|
||||
include(GlobScript)
|
||||
|
||||
get_property(glob_count GLOBAL PROPERTY GLOB_SCRIPT_COUNT)
|
||||
if(NOT glob_count EQUAL 1)
|
||||
message(FATAL_ERROR
|
||||
"Wrong GLOB_SCRIPT_COUNT value: ${glob_count}, expected: 1")
|
||||
endif()
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
CMake Error at InvalidArgumentsNumber.cmake:1 \(include_guard\):
|
||||
include_guard given an invalid number of arguments. The command takes at
|
||||
most 1 argument.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
@@ -0,0 +1 @@
|
||||
include_guard(ARG1 ARG2)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Error at InvalidScope.cmake:1 \(include_guard\):
|
||||
include_guard given an invalid scope: INVALID
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
@@ -0,0 +1 @@
|
||||
include_guard(INVALID)
|
||||
@@ -0,0 +1,7 @@
|
||||
include(RunCMake)
|
||||
|
||||
run_cmake(VariableScope)
|
||||
run_cmake(DirectoryScope)
|
||||
run_cmake(GlobalScope)
|
||||
run_cmake(InvalidScope)
|
||||
run_cmake(InvalidArgumentsNumber)
|
||||
@@ -0,0 +1,12 @@
|
||||
include_guard(DIRECTORY)
|
||||
|
||||
set(prop_name DIR_SCRIPT_COUNT)
|
||||
get_property(count_is_set GLOBAL PROPERTY ${prop_name} SET)
|
||||
|
||||
if(NOT count_is_set)
|
||||
set_property(GLOBAL PROPERTY ${prop_name} 1)
|
||||
else()
|
||||
get_property(count GLOBAL PROPERTY ${prop_name})
|
||||
math(EXPR count "${count} + 1")
|
||||
set_property(GLOBAL PROPERTY ${prop_name} ${count})
|
||||
endif()
|
||||
@@ -0,0 +1,12 @@
|
||||
include_guard(GLOBAL)
|
||||
|
||||
set(prop_name GLOB_SCRIPT_COUNT)
|
||||
get_property(count_is_set GLOBAL PROPERTY ${prop_name} SET)
|
||||
|
||||
if(NOT count_is_set)
|
||||
set_property(GLOBAL PROPERTY ${prop_name} 1)
|
||||
else()
|
||||
get_property(count GLOBAL PROPERTY ${prop_name})
|
||||
math(EXPR count "${count} + 1")
|
||||
set_property(GLOBAL PROPERTY ${prop_name} ${count})
|
||||
endif()
|
||||
@@ -0,0 +1,12 @@
|
||||
include_guard()
|
||||
|
||||
set(prop_name VAR_SCRIPT_COUNT)
|
||||
get_property(count_is_set GLOBAL PROPERTY ${prop_name} SET)
|
||||
|
||||
if(NOT count_is_set)
|
||||
set_property(GLOBAL PROPERTY ${prop_name} 1)
|
||||
else()
|
||||
get_property(count GLOBAL PROPERTY ${prop_name})
|
||||
math(EXPR count "${count} + 1")
|
||||
set_property(GLOBAL PROPERTY ${prop_name} ${count})
|
||||
endif()
|
||||
@@ -0,0 +1,24 @@
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/Scripts")
|
||||
|
||||
# Test include_guard with VARIABLE scope
|
||||
function(var_include_func)
|
||||
# Include twice in the same scope
|
||||
include(VarScript)
|
||||
include(VarScript)
|
||||
get_property(var_count GLOBAL PROPERTY VAR_SCRIPT_COUNT)
|
||||
if(NOT var_count EQUAL 1)
|
||||
message(FATAL_ERROR
|
||||
"Wrong VAR_SCRIPT_COUNT value: ${var_count}, expected: 1")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
var_include_func()
|
||||
|
||||
# Check again that include_guard has been reset
|
||||
include(VarScript)
|
||||
|
||||
get_property(var_count GLOBAL PROPERTY VAR_SCRIPT_COUNT)
|
||||
if(NOT var_count EQUAL 2)
|
||||
message(FATAL_ERROR
|
||||
"Wrong VAR_SCRIPT_COUNT value: ${var_count}, expected: 2")
|
||||
endif()
|
||||
@@ -0,0 +1 @@
|
||||
include(GlobScript)
|
||||
@@ -0,0 +1,9 @@
|
||||
function(dir_check)
|
||||
include(DirScript)
|
||||
endfunction()
|
||||
|
||||
dir_check()
|
||||
|
||||
include(DirScript)
|
||||
|
||||
add_subdirectory(sub_dir_script3)
|
||||
@@ -0,0 +1 @@
|
||||
include(DirScript)
|
||||
@@ -0,0 +1 @@
|
||||
include(DirScript)
|
||||
Reference in New Issue
Block a user