Commit d44bd1c2 authored by Pavel Solodovnikov's avatar Pavel Solodovnikov

include_guard: implement new command

parent 4ba2d2e3
......@@ -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);
......
/* 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;
}
/* 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
......@@ -330,6 +330,7 @@ CMAKE_CXX_SOURCES="\
cmHexFileConverter \
cmIfCommand \
cmIncludeCommand \
cmIncludeGuardCommand \
cmIncludeDirectoryCommand \
cmIncludeRegularExpressionCommand \
cmInstallCommand \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment