Bladeren bron

include_guard: implement new command

Pavel Solodovnikov 8 jaren geleden
bovenliggende
commit
d44bd1c25f
5 gewijzigde bestanden met toevoegingen van 150 en 0 verwijderingen
  1. 2 0
      Source/CMakeLists.txt
  2. 2 0
      Source/cmCommands.cxx
  3. 108 0
      Source/cmIncludeGuardCommand.cxx
  4. 37 0
      Source/cmIncludeGuardCommand.h
  5. 1 0
      bootstrap

+ 2 - 0
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

+ 2 - 0
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);

+ 108 - 0
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;
+}

+ 37 - 0
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

+ 1 - 0
bootstrap

@@ -330,6 +330,7 @@ CMAKE_CXX_SOURCES="\
   cmHexFileConverter \
   cmIfCommand \
   cmIncludeCommand \
+  cmIncludeGuardCommand \
   cmIncludeDirectoryCommand \
   cmIncludeRegularExpressionCommand \
   cmInstallCommand \