CMake Nightly Date Stamp
[kiteware-cmake.git] / Source / cmIncludeGuardCommand.cxx
blob2b0e03cecef1f4fdaed59c78b4edbb2f4144bba8
1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmIncludeGuardCommand.h"
5 #include "cmCryptoHash.h"
6 #include "cmExecutionStatus.h"
7 #include "cmMakefile.h"
8 #include "cmStateDirectory.h"
9 #include "cmStateSnapshot.h"
10 #include "cmStringAlgorithms.h"
11 #include "cmValue.h"
12 #include "cmake.h"
14 namespace {
16 enum IncludeGuardScope
18 VARIABLE,
19 DIRECTORY,
20 GLOBAL
23 std::string GetIncludeGuardVariableName(std::string const& filePath)
25 cmCryptoHash hasher(cmCryptoHash::AlgoMD5);
26 return cmStrCat("__INCGUARD_", hasher.HashString(filePath), "__");
29 bool CheckIncludeGuardIsSet(cmMakefile* mf, std::string const& includeGuardVar)
31 if (mf->GetProperty(includeGuardVar)) {
32 return true;
34 cmStateSnapshot dirSnapshot =
35 mf->GetStateSnapshot().GetBuildsystemDirectoryParent();
36 while (dirSnapshot.GetState()) {
37 cmStateDirectory stateDir = dirSnapshot.GetDirectory();
38 if (stateDir.GetProperty(includeGuardVar)) {
39 return true;
41 dirSnapshot = dirSnapshot.GetBuildsystemDirectoryParent();
43 return false;
46 } // anonymous namespace
48 // cmIncludeGuardCommand
49 bool cmIncludeGuardCommand(std::vector<std::string> const& args,
50 cmExecutionStatus& status)
52 if (args.size() > 1) {
53 status.SetError(
54 "given an invalid number of arguments. The command takes at "
55 "most 1 argument.");
56 return false;
59 IncludeGuardScope scope = VARIABLE;
61 if (!args.empty()) {
62 std::string const& arg = args[0];
63 if (arg == "DIRECTORY") {
64 scope = DIRECTORY;
65 } else if (arg == "GLOBAL") {
66 scope = GLOBAL;
67 } else {
68 status.SetError("given an invalid scope: " + arg);
69 return false;
73 std::string includeGuardVar = GetIncludeGuardVariableName(
74 *status.GetMakefile().GetDefinition("CMAKE_CURRENT_LIST_FILE"));
76 cmMakefile* const mf = &status.GetMakefile();
78 switch (scope) {
79 case VARIABLE:
80 if (mf->IsDefinitionSet(includeGuardVar)) {
81 status.SetReturnInvoked();
82 return true;
84 mf->AddDefinitionBool(includeGuardVar, true);
85 break;
86 case DIRECTORY:
87 if (CheckIncludeGuardIsSet(mf, includeGuardVar)) {
88 status.SetReturnInvoked();
89 return true;
91 mf->SetProperty(includeGuardVar, "TRUE");
92 break;
93 case GLOBAL:
94 cmake* const cm = mf->GetCMakeInstance();
95 if (cm->GetProperty(includeGuardVar)) {
96 status.SetReturnInvoked();
97 return true;
99 cm->SetProperty(includeGuardVar, "TRUE");
100 break;
103 return true;