summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/cmCommands.cxx2
-rw-r--r--Source/cmIncludeGuardCommand.cxx108
-rw-r--r--Source/cmIncludeGuardCommand.h37
-rwxr-xr-xbootstrap1
5 files changed, 150 insertions, 0 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 1878b8a..660d632 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -469,6 +469,8 @@ set(SRCS
cmIncludeDirectoryCommand.h
cmIncludeExternalMSProjectCommand.cxx
cmIncludeExternalMSProjectCommand.h
+ cmIncludeGuardCommand.cxx
+ cmIncludeGuardCommand.h
cmIncludeRegularExpressionCommand.cxx
cmIncludeRegularExpressionCommand.h
cmInstallCommand.cxx
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index e1d8ef1..485dd50 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.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);
diff --git a/Source/cmIncludeGuardCommand.cxx b/Source/cmIncludeGuardCommand.cxx
new file mode 100644
index 0000000..505b07c
--- /dev/null
+++ b/Source/cmIncludeGuardCommand.cxx
@@ -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;
+}
diff --git a/Source/cmIncludeGuardCommand.h b/Source/cmIncludeGuardCommand.h
new file mode 100644
index 0000000..140c04f
--- /dev/null
+++ b/Source/cmIncludeGuardCommand.h
@@ -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
diff --git a/bootstrap b/bootstrap
index ba2a5f3..83e67c5 100755
--- a/bootstrap
+++ b/bootstrap
@@ -330,6 +330,7 @@ CMAKE_CXX_SOURCES="\
cmHexFileConverter \
cmIfCommand \
cmIncludeCommand \
+ cmIncludeGuardCommand \
cmIncludeDirectoryCommand \
cmIncludeRegularExpressionCommand \
cmInstallCommand \