summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CTest/cmCTestResourceSpec.cxx221
-rw-r--r--Source/CTest/cmCTestResourceSpec.h2
-rw-r--r--Source/LexerParser/cmCommandArgumentLexer.cxx22
-rw-r--r--Source/LexerParser/cmCommandArgumentLexer.in.l7
-rw-r--r--Source/cmCommandArgumentParserHelper.cxx38
-rw-r--r--Source/cmCommandArgumentParserHelper.h11
-rw-r--r--Source/cmConditionEvaluator.cxx72
-rw-r--r--Source/cmConditionEvaluator.h6
-rw-r--r--Source/cmExpandedCommandArgument.cxx5
-rw-r--r--Source/cmExpandedCommandArgument.h2
-rw-r--r--Source/cmFileCommand.cxx46
-rw-r--r--Source/cmGeneratorTarget.cxx34
-rw-r--r--Source/cmJSONHelpers.h304
-rw-r--r--Source/cmLocalGenerator.cxx28
-rw-r--r--Source/cmLocalVisualStudio10Generator.cxx7
-rw-r--r--Source/cmLocalVisualStudio10Generator.h9
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx16
-rw-r--r--Source/cmLocalVisualStudio7Generator.h9
-rw-r--r--Source/cmMakefile.cxx2
-rw-r--r--Source/cmQtAutoMocUic.cxx22
-rw-r--r--Source/cmStringAlgorithms.h7
23 files changed, 636 insertions, 237 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 310ffeb..1be424a 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -336,6 +336,7 @@ set(SRCS
cmInstallTargetGenerator.cxx
cmInstallDirectoryGenerator.h
cmInstallDirectoryGenerator.cxx
+ cmJSONHelpers.h
cmLDConfigLDConfigTool.cxx
cmLDConfigLDConfigTool.h
cmLDConfigTool.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 24976ad..835b785 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 18)
-set(CMake_VERSION_PATCH 20200908)
+set(CMake_VERSION_PATCH 20200910)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CTest/cmCTestResourceSpec.cxx b/Source/CTest/cmCTestResourceSpec.cxx
index 21c97de..101dc2c 100644
--- a/Source/CTest/cmCTestResourceSpec.cxx
+++ b/Source/CTest/cmCTestResourceSpec.cxx
@@ -2,19 +2,140 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestResourceSpec.h"
+#include <functional>
#include <map>
#include <string>
#include <utility>
#include <vector>
+#include <cmext/string_view>
+
#include <cm3p/json/reader.h>
#include <cm3p/json/value.h>
#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
-static const cmsys::RegularExpression IdentifierRegex{ "^[a-z_][a-z0-9_]*$" };
-static const cmsys::RegularExpression IdRegex{ "^[a-z0-9_]+$" };
+#include "cmJSONHelpers.h"
+
+namespace {
+const cmsys::RegularExpression IdentifierRegex{ "^[a-z_][a-z0-9_]*$" };
+const cmsys::RegularExpression IdRegex{ "^[a-z0-9_]+$" };
+
+struct Version
+{
+ int Major = 1;
+ int Minor = 0;
+};
+
+struct TopVersion
+{
+ struct Version Version;
+};
+
+auto const VersionFieldHelper =
+ cmJSONIntHelper<cmCTestResourceSpec::ReadFileResult>(
+ cmCTestResourceSpec::ReadFileResult::READ_OK,
+ cmCTestResourceSpec::ReadFileResult::INVALID_VERSION);
+
+auto const VersionHelper =
+ cmJSONRequiredHelper<Version, cmCTestResourceSpec::ReadFileResult>(
+ cmCTestResourceSpec::ReadFileResult::NO_VERSION,
+ cmJSONObjectHelper<Version, cmCTestResourceSpec::ReadFileResult>(
+ cmCTestResourceSpec::ReadFileResult::READ_OK,
+ cmCTestResourceSpec::ReadFileResult::INVALID_VERSION)
+ .Bind("major"_s, &Version::Major, VersionFieldHelper)
+ .Bind("minor"_s, &Version::Minor, VersionFieldHelper));
+
+auto const RootVersionHelper =
+ cmJSONObjectHelper<TopVersion, cmCTestResourceSpec::ReadFileResult>(
+ cmCTestResourceSpec::ReadFileResult::READ_OK,
+ cmCTestResourceSpec::ReadFileResult::INVALID_ROOT)
+ .Bind("version"_s, &TopVersion::Version, VersionHelper, false);
+
+cmCTestResourceSpec::ReadFileResult ResourceIdHelper(std::string& out,
+ const Json::Value* value)
+{
+ auto result = cmJSONStringHelper(
+ cmCTestResourceSpec::ReadFileResult::READ_OK,
+ cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE)(out, value);
+ if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) {
+ return result;
+ }
+ cmsys::RegularExpressionMatch match;
+ if (!IdRegex.find(out.c_str(), match)) {
+ return cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE;
+ }
+ return cmCTestResourceSpec::ReadFileResult::READ_OK;
+}
+
+auto const ResourceHelper =
+ cmJSONObjectHelper<cmCTestResourceSpec::Resource,
+ cmCTestResourceSpec::ReadFileResult>(
+ cmCTestResourceSpec::ReadFileResult::READ_OK,
+ cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE)
+ .Bind("id"_s, &cmCTestResourceSpec::Resource::Id, ResourceIdHelper)
+ .Bind("slots"_s, &cmCTestResourceSpec::Resource::Capacity,
+ cmJSONUIntHelper(
+ cmCTestResourceSpec::ReadFileResult::READ_OK,
+ cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE, 1),
+ false);
+
+auto const ResourceListHelper =
+ cmJSONVectorHelper<cmCTestResourceSpec::Resource,
+ cmCTestResourceSpec::ReadFileResult>(
+ cmCTestResourceSpec::ReadFileResult::READ_OK,
+ cmCTestResourceSpec::ReadFileResult::INVALID_RESOURCE_TYPE,
+ ResourceHelper);
+
+auto const ResourceMapHelper =
+ cmJSONMapFilterHelper<std::vector<cmCTestResourceSpec::Resource>,
+ cmCTestResourceSpec::ReadFileResult>(
+ cmCTestResourceSpec::ReadFileResult::READ_OK,
+ cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC,
+ ResourceListHelper, [](const std::string& key) -> bool {
+ cmsys::RegularExpressionMatch match;
+ return IdentifierRegex.find(key.c_str(), match);
+ });
+
+auto const SocketSetHelper = cmJSONVectorHelper<
+ std::map<std::string, std::vector<cmCTestResourceSpec::Resource>>>(
+ cmCTestResourceSpec::ReadFileResult::READ_OK,
+ cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, ResourceMapHelper);
+
+cmCTestResourceSpec::ReadFileResult SocketHelper(
+ cmCTestResourceSpec::Socket& out, const Json::Value* value)
+{
+ std::vector<
+ std::map<std::string, std::vector<cmCTestResourceSpec::Resource>>>
+ sockets;
+ cmCTestResourceSpec::ReadFileResult result = SocketSetHelper(sockets, value);
+ if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) {
+ return result;
+ }
+ if (sockets.size() > 1) {
+ return cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC;
+ }
+ if (sockets.empty()) {
+ out.Resources.clear();
+ } else {
+ out.Resources = std::move(sockets[0]);
+ }
+ return cmCTestResourceSpec::ReadFileResult::READ_OK;
+}
+
+auto const LocalRequiredHelper =
+ cmJSONRequiredHelper<cmCTestResourceSpec::Socket,
+ cmCTestResourceSpec::ReadFileResult>(
+ cmCTestResourceSpec::ReadFileResult::INVALID_SOCKET_SPEC, SocketHelper);
+
+auto const RootHelper =
+ cmJSONObjectHelper<cmCTestResourceSpec, cmCTestResourceSpec::ReadFileResult>(
+ cmCTestResourceSpec::ReadFileResult::READ_OK,
+ cmCTestResourceSpec::ReadFileResult::INVALID_ROOT)
+ .Bind("local", &cmCTestResourceSpec::LocalSocket, LocalRequiredHelper,
+ false);
+}
cmCTestResourceSpec::ReadFileResult cmCTestResourceSpec::ReadFromJSONFile(
const std::string& filename)
@@ -30,99 +151,17 @@ cmCTestResourceSpec::ReadFileResult cmCTestResourceSpec::ReadFromJSONFile(
return ReadFileResult::JSON_PARSE_ERROR;
}
- if (!root.isObject()) {
- return ReadFileResult::INVALID_ROOT;
- }
-
- int majorVersion = 1;
- int minorVersion = 0;
- if (root.isMember("version")) {
- auto const& version = root["version"];
- if (version.isObject()) {
- if (!version.isMember("major") || !version.isMember("minor")) {
- return ReadFileResult::INVALID_VERSION;
- }
- auto const& major = version["major"];
- auto const& minor = version["minor"];
- if (!major.isInt() || !minor.isInt()) {
- return ReadFileResult::INVALID_VERSION;
- }
- majorVersion = major.asInt();
- minorVersion = minor.asInt();
- } else {
- return ReadFileResult::INVALID_VERSION;
- }
- } else {
- return ReadFileResult::NO_VERSION;
+ TopVersion version;
+ ReadFileResult result;
+ if ((result = RootVersionHelper(version, &root)) !=
+ ReadFileResult::READ_OK) {
+ return result;
}
-
- if (majorVersion != 1 || minorVersion != 0) {
+ if (version.Version.Major != 1 || version.Version.Minor != 0) {
return ReadFileResult::UNSUPPORTED_VERSION;
}
- auto const& local = root["local"];
- if (!local.isArray()) {
- return ReadFileResult::INVALID_SOCKET_SPEC;
- }
- if (local.size() > 1) {
- return ReadFileResult::INVALID_SOCKET_SPEC;
- }
-
- if (local.empty()) {
- this->LocalSocket.Resources.clear();
- return ReadFileResult::READ_OK;
- }
-
- auto const& localSocket = local[0];
- if (!localSocket.isObject()) {
- return ReadFileResult::INVALID_SOCKET_SPEC;
- }
- std::map<std::string, std::vector<cmCTestResourceSpec::Resource>> resources;
- cmsys::RegularExpressionMatch match;
- for (auto const& key : localSocket.getMemberNames()) {
- if (IdentifierRegex.find(key.c_str(), match)) {
- auto const& value = localSocket[key];
- auto& r = resources[key];
- if (value.isArray()) {
- for (auto const& item : value) {
- if (item.isObject()) {
- cmCTestResourceSpec::Resource resource;
-
- if (!item.isMember("id")) {
- return ReadFileResult::INVALID_RESOURCE;
- }
- auto const& id = item["id"];
- if (!id.isString()) {
- return ReadFileResult::INVALID_RESOURCE;
- }
- resource.Id = id.asString();
- if (!IdRegex.find(resource.Id.c_str(), match)) {
- return ReadFileResult::INVALID_RESOURCE;
- }
-
- if (item.isMember("slots")) {
- auto const& capacity = item["slots"];
- if (!capacity.isConvertibleTo(Json::uintValue)) {
- return ReadFileResult::INVALID_RESOURCE;
- }
- resource.Capacity = capacity.asUInt();
- } else {
- resource.Capacity = 1;
- }
-
- r.push_back(resource);
- } else {
- return ReadFileResult::INVALID_RESOURCE;
- }
- }
- } else {
- return ReadFileResult::INVALID_RESOURCE_TYPE;
- }
- }
- }
-
- this->LocalSocket.Resources = std::move(resources);
- return ReadFileResult::READ_OK;
+ return RootHelper(*this, &root);
}
const char* cmCTestResourceSpec::ResultToString(ReadFileResult result)
diff --git a/Source/CTest/cmCTestResourceSpec.h b/Source/CTest/cmCTestResourceSpec.h
index 1aa279b..72628a3 100644
--- a/Source/CTest/cmCTestResourceSpec.h
+++ b/Source/CTest/cmCTestResourceSpec.h
@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
+#include "cmConfigure.h" // IWYU pragma: keep
+
#include <map>
#include <string>
#include <vector>
diff --git a/Source/LexerParser/cmCommandArgumentLexer.cxx b/Source/LexerParser/cmCommandArgumentLexer.cxx
index 5879912..46220ff 100644
--- a/Source/LexerParser/cmCommandArgumentLexer.cxx
+++ b/Source/LexerParser/cmCommandArgumentLexer.cxx
@@ -653,7 +653,7 @@ This file must be translated to C++ and modified to build everywhere.
Run flex >= 2.6 like this:
- flex --nounistd -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
+ flex --nounistd --never-interactive --batch -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
Modify cmCommandArgumentLexer.cxx:
- remove trailing whitespace: sed -i 's/\s*$//' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx
@@ -668,10 +668,7 @@ Modify cmCommandArgumentLexer.cxx:
#include "cmCommandArgumentParserHelper.h"
-/* Replace the lexer input function. */
-#undef YY_INPUT
-#define YY_INPUT(buf, result, max_size) \
- do { result = yyextra->LexInput(buf, max_size); } while (0)
+#define YY_USER_ACTION yyextra->UpdateInputPosition(yyleng);
/* Include the set of tokens from the parser. */
#include "cmCommandArgumentParserTokens.h"
@@ -967,16 +964,12 @@ yy_match:
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 41 );
+ while ( yy_current_state != 29 );
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
yy_find_action:
yy_act = yy_accept[yy_current_state];
- if ( yy_act == 0 )
- { /* have to back up */
- yy_cp = yyg->yy_last_accepting_cpos;
- yy_current_state = yyg->yy_last_accepting_state;
- yy_act = yy_accept[yy_current_state];
- }
YY_DO_BEFORE_ACTION;
@@ -1173,7 +1166,8 @@ case YY_STATE_EOF(NOESCAPES):
else
{
- yy_cp = yyg->yy_c_buf_p;
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
goto yy_find_action;
}
}
@@ -1661,7 +1655,7 @@ static void yy_load_buffer_state (yyscan_t yyscanner)
b->yy_bs_column = 0;
}
- b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+ b->yy_is_interactive = 0;
errno = oerrno;
}
diff --git a/Source/LexerParser/cmCommandArgumentLexer.in.l b/Source/LexerParser/cmCommandArgumentLexer.in.l
index 010d54b..8ad2335 100644
--- a/Source/LexerParser/cmCommandArgumentLexer.in.l
+++ b/Source/LexerParser/cmCommandArgumentLexer.in.l
@@ -7,7 +7,7 @@ This file must be translated to C++ and modified to build everywhere.
Run flex >= 2.6 like this:
- flex --nounistd -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
+ flex --nounistd --never-interactive --batch -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
Modify cmCommandArgumentLexer.cxx:
- remove trailing whitespace: sed -i 's/\s*$//' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx
@@ -22,10 +22,7 @@ Modify cmCommandArgumentLexer.cxx:
#include "cmCommandArgumentParserHelper.h"
-/* Replace the lexer input function. */
-#undef YY_INPUT
-#define YY_INPUT(buf, result, max_size) \
- do { result = yyextra->LexInput(buf, max_size); } while (0)
+#define YY_USER_ACTION yyextra->UpdateInputPosition(yyleng);
/* Include the set of tokens from the parser. */
#include "cmCommandArgumentParserTokens.h"
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index e07f7f1..e3d014e 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -205,23 +205,24 @@ bool cmCommandArgumentParserHelper::HandleEscapeSymbol(
void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes);
-int cmCommandArgumentParserHelper::ParseString(const char* str, int verb)
+int cmCommandArgumentParserHelper::ParseString(std::string const& str,
+ int verb)
{
- if (!str) {
+ if (str.empty()) {
return 0;
}
+ this->InputSize = str.size();
this->Verbose = verb;
- this->InputBuffer = str;
- this->InputBufferPos = 0;
- this->CurrentLine = 0;
this->Result.clear();
yyscan_t yyscanner;
cmCommandArgument_yylex_init(&yyscanner);
+ auto scanBuf = cmCommandArgument_yy_scan_string(str.c_str(), yyscanner);
cmCommandArgument_yyset_extra(this, yyscanner);
cmCommandArgument_SetupEscapes(yyscanner, this->NoEscapeMode);
int res = cmCommandArgument_yyparse(yyscanner);
+ cmCommandArgument_yy_delete_buffer(scanBuf, yyscanner);
cmCommandArgument_yylex_destroy(yyscanner);
if (res != 0) {
return 0;
@@ -241,25 +242,14 @@ void cmCommandArgumentParserHelper::CleanupParser()
this->Variables.clear();
}
-int cmCommandArgumentParserHelper::LexInput(char* buf, int maxlen)
+void cmCommandArgumentParserHelper::Error(const char* str)
{
- if (maxlen < 1) {
- return 0;
+ auto pos = this->InputBufferPos;
+ auto const isEof = (this->InputSize < this->InputBufferPos);
+ if (!isEof) {
+ pos -= this->LastTokenLength;
}
- if (this->InputBufferPos < this->InputBuffer.size()) {
- buf[0] = this->InputBuffer[this->InputBufferPos++];
- if (buf[0] == '\n') {
- this->CurrentLine++;
- }
- return (1);
- }
- buf[0] = '\n';
- return (0);
-}
-void cmCommandArgumentParserHelper::Error(const char* str)
-{
- unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
std::ostringstream ostr;
ostr << str << " (" << pos << ")";
this->SetError(ostr.str());
@@ -286,3 +276,9 @@ void cmCommandArgumentParserHelper::SetError(std::string const& msg)
this->ErrorString = msg;
}
}
+
+void cmCommandArgumentParserHelper::UpdateInputPosition(int const tokenLength)
+{
+ this->InputBufferPos += tokenLength;
+ this->LastTokenLength = tokenLength;
+}
diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h
index 8ff689e..f79ca2c 100644
--- a/Source/cmCommandArgumentParserHelper.h
+++ b/Source/cmCommandArgumentParserHelper.h
@@ -25,7 +25,7 @@ public:
cmCommandArgumentParserHelper& operator=(
cmCommandArgumentParserHelper const&) = delete;
- int ParseString(const char* str, int verb);
+ int ParseString(std::string const& str, int verb);
// For the lexer:
void AllocateParserType(cmCommandArgumentParserHelper::ParserType* pt,
@@ -33,7 +33,6 @@ public:
bool HandleEscapeSymbol(cmCommandArgumentParserHelper::ParserType* pt,
char symbol);
- int LexInput(char* buf, int maxlen);
void Error(const char* str);
// For yacc
@@ -46,6 +45,8 @@ public:
void SetMakefile(const cmMakefile* mf);
+ void UpdateInputPosition(int tokenLength);
+
std::string& GetResult() { return this->Result; }
void SetLineFile(long line, const char* file);
@@ -57,8 +58,9 @@ public:
const char* GetError() { return this->ErrorString.c_str(); }
private:
- std::string::size_type InputBufferPos;
- std::string InputBuffer;
+ std::string::size_type InputBufferPos{ 1 };
+ std::string::size_type LastTokenLength{};
+ std::string::size_type InputSize{};
std::vector<char> OutputBuffer;
void Print(const char* place, const char* str);
@@ -75,7 +77,6 @@ private:
std::string ErrorString;
const char* FileName;
long FileLine;
- int CurrentLine;
int Verbose;
bool EscapeQuotes;
bool NoEscapeMode;
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index 8021b49..7ada8d8 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -4,7 +4,6 @@
#include <cstdio>
#include <cstdlib>
-#include <cstring>
#include <functional>
#include <sstream>
#include <utility>
@@ -135,7 +134,7 @@ bool cmConditionEvaluator::IsTrue(
}
//=========================================================================
-const char* cmConditionEvaluator::GetDefinitionIfUnquoted(
+cmProp cmConditionEvaluator::GetDefinitionIfUnquoted(
cmExpandedCommandArgument const& argument) const
{
if ((this->Policy54Status != cmPolicies::WARN &&
@@ -162,17 +161,17 @@ const char* cmConditionEvaluator::GetDefinitionIfUnquoted(
}
}
- return cmToCStr(def);
+ return def;
}
//=========================================================================
-const char* cmConditionEvaluator::GetVariableOrString(
+cmProp cmConditionEvaluator::GetVariableOrString(
const cmExpandedCommandArgument& argument) const
{
- const char* def = this->GetDefinitionIfUnquoted(argument);
+ cmProp def = this->GetDefinitionIfUnquoted(argument);
if (!def) {
- def = argument.c_str();
+ def = &argument.GetValue();
}
return def;
@@ -232,7 +231,7 @@ bool cmConditionEvaluator::GetBooleanValue(
// Check for numbers.
if (!arg.empty()) {
char* end;
- double d = strtod(arg.c_str(), &end);
+ double d = strtod(arg.GetValue().c_str(), &end);
if (*end == '\0') {
// The whole string is a number. Use C conversion to bool.
return static_cast<bool>(d);
@@ -240,7 +239,7 @@ bool cmConditionEvaluator::GetBooleanValue(
}
// Check definition.
- const char* def = this->GetDefinitionIfUnquoted(arg);
+ cmProp def = this->GetDefinitionIfUnquoted(arg);
return !cmIsOff(def);
}
@@ -257,13 +256,13 @@ bool cmConditionEvaluator::GetBooleanValueOld(
if (arg == "1") {
return true;
}
- const char* def = this->GetDefinitionIfUnquoted(arg);
+ cmProp def = this->GetDefinitionIfUnquoted(arg);
return !cmIsOff(def);
}
// Old GetVariableOrNumber behavior.
- const char* def = this->GetDefinitionIfUnquoted(arg);
- if (!def && atoi(arg.c_str())) {
- def = arg.c_str();
+ cmProp def = this->GetDefinitionIfUnquoted(arg);
+ if (!def && atoi(arg.GetValue().c_str())) {
+ def = &arg.GetValue();
}
return !cmIsOff(def);
}
@@ -435,36 +434,38 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
this->IncrementArguments(newArgs, argP1, argP2);
// does a file exist
if (this->IsKeyword(keyEXISTS, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(cmSystemTools::FileExists(argP1->c_str()),
+ this->HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()),
reducible, arg, newArgs, argP1, argP2);
}
// does a directory with this name exist
if (this->IsKeyword(keyIS_DIRECTORY, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(cmSystemTools::FileIsDirectory(argP1->c_str()),
- reducible, arg, newArgs, argP1, argP2);
+ this->HandlePredicate(
+ cmSystemTools::FileIsDirectory(argP1->GetValue()), reducible, arg,
+ newArgs, argP1, argP2);
}
// does a symlink with this name exist
if (this->IsKeyword(keyIS_SYMLINK, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(cmSystemTools::FileIsSymlink(argP1->c_str()),
+ this->HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()),
reducible, arg, newArgs, argP1, argP2);
}
// is the given path an absolute path ?
if (this->IsKeyword(keyIS_ABSOLUTE, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(cmSystemTools::FileIsFullPath(argP1->c_str()),
+ this->HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()),
reducible, arg, newArgs, argP1, argP2);
}
// does a command exist
if (this->IsKeyword(keyCOMMAND, *arg) && argP1 != newArgs.end()) {
cmState::Command command =
- this->Makefile.GetState()->GetCommand(argP1->c_str());
+ this->Makefile.GetState()->GetCommand(argP1->GetValue());
this->HandlePredicate(command != nullptr, reducible, arg, newArgs,
argP1, argP2);
}
// does a policy exist
if (this->IsKeyword(keyPOLICY, *arg) && argP1 != newArgs.end()) {
cmPolicies::PolicyID pid;
- this->HandlePredicate(cmPolicies::GetPolicyID(argP1->c_str(), pid),
- reducible, arg, newArgs, argP1, argP2);
+ this->HandlePredicate(
+ cmPolicies::GetPolicyID(argP1->GetValue().c_str(), pid), reducible,
+ arg, newArgs, argP1, argP2);
}
// does a target exist
if (this->IsKeyword(keyTARGET, *arg) && argP1 != newArgs.end()) {
@@ -476,7 +477,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
if (this->Policy64Status != cmPolicies::OLD &&
this->Policy64Status != cmPolicies::WARN) {
if (this->IsKeyword(keyTEST, *arg) && argP1 != newArgs.end()) {
- const cmTest* haveTest = this->Makefile.GetTest(argP1->c_str());
+ const cmTest* haveTest = this->Makefile.GetTest(argP1->GetValue());
this->HandlePredicate(haveTest != nullptr, reducible, arg, newArgs,
argP1, argP2);
}
@@ -523,8 +524,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
{
int reducible;
std::string def_buf;
- const char* def;
- const char* def2;
+ cmProp def;
+ cmProp def2;
do {
reducible = 0;
auto arg = newArgs.begin();
@@ -537,14 +538,14 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
IsKeyword(keyMATCHES, *argP1)) {
def = this->GetDefinitionIfUnquoted(*arg);
if (!def) {
- def = arg->c_str();
+ def = &arg->GetValue();
} else if (cmHasLiteralPrefix(arg->GetValue(), "CMAKE_MATCH_")) {
// The string to match is owned by our match result variables.
// Move it to our own buffer before clearing them.
- def_buf = def;
- def = def_buf.c_str();
+ def_buf = *def;
+ def = &def_buf;
}
- const char* rex = argP2->c_str();
+ const std::string& rex = argP2->GetValue();
this->Makefile.ClearMatches();
cmsys::RegularExpression regEntry;
if (!regEntry.compile(rex)) {
@@ -554,7 +555,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
status = MessageType::FATAL_ERROR;
return false;
}
- if (regEntry.find(def)) {
+ if (regEntry.find(*def)) {
this->Makefile.StoreMatches(regEntry);
*arg = cmExpandedCommandArgument("1", true);
} else {
@@ -586,7 +587,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
double lhs;
double rhs;
bool result;
- if (sscanf(def, "%lg", &lhs) != 1 || sscanf(def2, "%lg", &rhs) != 1) {
+ if (sscanf(def->c_str(), "%lg", &lhs) != 1 ||
+ sscanf(def2->c_str(), "%lg", &rhs) != 1) {
result = false;
} else if (*(argP1) == keyLESS) {
result = (lhs < rhs);
@@ -610,7 +612,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
this->IsKeyword(keySTREQUAL, *argP1))) {
def = this->GetVariableOrString(*arg);
def2 = this->GetVariableOrString(*argP2);
- int val = strcmp(def, def2);
+ int val = (*def).compare(*def2);
bool result;
if (*(argP1) == keySTRLESS) {
result = (val < 0);
@@ -647,7 +649,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
} else { // version_equal
op = cmSystemTools::OP_EQUAL;
}
- bool result = cmSystemTools::VersionCompare(op, def, def2);
+ bool result =
+ cmSystemTools::VersionCompare(op, def->c_str(), def2->c_str());
this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
}
@@ -669,12 +672,11 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
bool result = false;
def = this->GetVariableOrString(*arg);
- def2 = cmToCStr(this->Makefile.GetDefinition(argP2->GetValue()));
+ def2 = this->Makefile.GetDefinition(argP2->GetValue());
if (def2) {
- std::vector<std::string> list = cmExpandedList(def2, true);
-
- result = cm::contains(list, def);
+ std::vector<std::string> list = cmExpandedList(*def2, true);
+ result = cm::contains(list, *def);
}
this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h
index a1e3829..a4cedff 100644
--- a/Source/cmConditionEvaluator.h
+++ b/Source/cmConditionEvaluator.h
@@ -12,6 +12,7 @@
#include "cmListFileCache.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
class cmMakefile;
@@ -31,11 +32,10 @@ public:
private:
// Filter the given variable definition based on policy CMP0054.
- const char* GetDefinitionIfUnquoted(
+ cmProp GetDefinitionIfUnquoted(
const cmExpandedCommandArgument& argument) const;
- const char* GetVariableOrString(
- const cmExpandedCommandArgument& argument) const;
+ cmProp GetVariableOrString(const cmExpandedCommandArgument& argument) const;
bool IsKeyword(std::string const& keyword,
cmExpandedCommandArgument& argument) const;
diff --git a/Source/cmExpandedCommandArgument.cxx b/Source/cmExpandedCommandArgument.cxx
index 43f648b..1f14fc4 100644
--- a/Source/cmExpandedCommandArgument.cxx
+++ b/Source/cmExpandedCommandArgument.cxx
@@ -37,8 +37,3 @@ bool cmExpandedCommandArgument::empty() const
{
return this->Value.empty();
}
-
-const char* cmExpandedCommandArgument::c_str() const
-{
- return this->Value.c_str();
-}
diff --git a/Source/cmExpandedCommandArgument.h b/Source/cmExpandedCommandArgument.h
index 50a17a8..1ff6ed1 100644
--- a/Source/cmExpandedCommandArgument.h
+++ b/Source/cmExpandedCommandArgument.h
@@ -28,8 +28,6 @@ public:
bool empty() const;
- const char* c_str() const;
-
private:
std::string Value;
bool Quoted = false;
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index cdb1492..84639a7 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -28,6 +28,7 @@
#include "cmAlgorithms.h"
#include "cmArgumentParser.h"
+#include "cmCMakePath.h"
#include "cmCryptoHash.h"
#include "cmExecutionStatus.h"
#include "cmFSPermissions.h"
@@ -1234,6 +1235,50 @@ bool HandleInstallCommand(std::vector<std::string> const& args,
return installer.Run(args);
}
+bool HandleRealPathCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() < 3) {
+ status.SetError("REAL_PATH requires a path and an output variable");
+ return false;
+ }
+
+ struct Arguments
+ {
+ std::string BaseDirectory;
+ };
+ static auto const parser = cmArgumentParser<Arguments>{}.Bind(
+ "BASE_DIRECTORY"_s, &Arguments::BaseDirectory);
+
+ std::vector<std::string> unparsedArguments;
+ std::vector<std::string> keywordsMissingValue;
+ std::vector<std::string> parsedKeywords;
+ auto arguments =
+ parser.Parse(cmMakeRange(args).advance(3), &unparsedArguments,
+ &keywordsMissingValue, &parsedKeywords);
+
+ if (!unparsedArguments.empty()) {
+ status.SetError("REAL_PATH called with unexpected arguments");
+ return false;
+ }
+ if (!keywordsMissingValue.empty()) {
+ status.SetError("BASE_DIRECTORY requires a value");
+ return false;
+ }
+
+ if (parsedKeywords.empty()) {
+ arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory();
+ }
+
+ cmCMakePath path(args[1]);
+ path = path.Absolute(arguments.BaseDirectory).Normal();
+ auto realPath = cmSystemTools::GetRealPath(path.GenericString());
+
+ status.GetMakefile().AddDefinition(args[2], realPath);
+
+ return true;
+}
+
bool HandleRelativePathCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -3360,6 +3405,7 @@ bool cmFileCommand(std::vector<std::string> const& args,
{ "RPATH_CHECK"_s, HandleRPathCheckCommand },
{ "RPATH_REMOVE"_s, HandleRPathRemoveCommand },
{ "READ_ELF"_s, HandleReadElfCommand },
+ { "REAL_PATH"_s, HandleRealPathCommand },
{ "RELATIVE_PATH"_s, HandleRelativePathCommand },
{ "TO_CMAKE_PATH"_s, HandleCMakePathCommand },
{ "TO_NATIVE_PATH"_s, HandleNativePathCommand },
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index f8568b3..1bb069f 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -6472,21 +6472,16 @@ bool cmGeneratorTarget::ComputeOutputDir(const std::string& config,
// Look for a target property defining the target output directory
// based on the target type.
std::string targetTypeName = this->GetOutputTargetType(artifact);
- const char* propertyName = nullptr;
- std::string propertyNameStr = targetTypeName;
- if (!propertyNameStr.empty()) {
- propertyNameStr += "_OUTPUT_DIRECTORY";
- propertyName = propertyNameStr.c_str();
+ std::string propertyName;
+ if (!targetTypeName.empty()) {
+ propertyName = cmStrCat(targetTypeName, "_OUTPUT_DIRECTORY");
}
// Check for a per-configuration output directory target property.
std::string configUpper = cmSystemTools::UpperCase(conf);
- const char* configProp = nullptr;
- std::string configPropStr = targetTypeName;
- if (!configPropStr.empty()) {
- configPropStr += "_OUTPUT_DIRECTORY_";
- configPropStr += configUpper;
- configProp = configPropStr.c_str();
+ std::string configProp;
+ if (!targetTypeName.empty()) {
+ configProp = cmStrCat(targetTypeName, "_OUTPUT_DIRECTORY_", configUpper);
}
// Select an output directory.
@@ -6547,22 +6542,17 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind,
{
// Look for a target property defining the target output directory
// based on the target type.
- const char* propertyName = nullptr;
- std::string propertyNameStr = kind;
- if (!propertyNameStr.empty()) {
- propertyNameStr += "_OUTPUT_DIRECTORY";
- propertyName = propertyNameStr.c_str();
+ std::string propertyName;
+ if (!kind.empty()) {
+ propertyName = cmStrCat(kind, "_OUTPUT_DIRECTORY");
}
std::string conf = config;
// Check for a per-configuration output directory target property.
std::string configUpper = cmSystemTools::UpperCase(conf);
- const char* configProp = nullptr;
- std::string configPropStr = kind;
- if (!configPropStr.empty()) {
- configPropStr += "_OUTPUT_DIRECTORY_";
- configPropStr += configUpper;
- configProp = configPropStr.c_str();
+ std::string configProp;
+ if (!kind.empty()) {
+ configProp = cmStrCat(kind, "_OUTPUT_DIRECTORY_", configUpper);
}
// Select an output directory.
diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h
new file mode 100644
index 0000000..2da2a03
--- /dev/null
+++ b/Source/cmJSONHelpers.h
@@ -0,0 +1,304 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <algorithm>
+#include <cstddef>
+#include <functional>
+#include <map>
+#include <string>
+#include <vector>
+
+#include <cm/optional>
+#include <cm/string_view>
+
+#include <cm3p/json/value.h>
+
+template <typename T, typename E>
+using cmJSONHelper = std::function<E(T& out, const Json::Value* value)>;
+
+template <typename T, typename E>
+class cmJSONObjectHelper
+{
+public:
+ cmJSONObjectHelper(E&& success, E&& fail, bool allowExtra = true);
+
+ template <typename U, typename M, typename F>
+ cmJSONObjectHelper& Bind(const cm::string_view& name, M U::*member, F func,
+ bool required = true);
+ template <typename M, typename F>
+ cmJSONObjectHelper& Bind(const cm::string_view& name, std::nullptr_t, F func,
+ bool required = true);
+
+ E operator()(T& out, const Json::Value* value) const;
+
+private:
+ // Not a true cmJSONHelper, it just happens to match the signature
+ using MemberFunction = std::function<E(T& out, const Json::Value* value)>;
+ struct Member
+ {
+ cm::string_view Name;
+ MemberFunction Function;
+ bool Required;
+ };
+ std::vector<Member> Members;
+ bool AnyRequired = false;
+ E Success;
+ E Fail;
+ bool AllowExtra;
+
+ cmJSONObjectHelper& BindPrivate(const cm::string_view& name,
+ MemberFunction&& func, bool required);
+};
+
+template <typename T, typename E>
+cmJSONObjectHelper<T, E>::cmJSONObjectHelper(E&& success, E&& fail,
+ bool allowExtra)
+ : Success(std::move(success))
+ , Fail(std::move(fail))
+ , AllowExtra(allowExtra)
+{
+}
+
+template <typename T, typename E>
+template <typename U, typename M, typename F>
+cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind(
+ const cm::string_view& name, M U::*member, F func, bool required)
+{
+ return this->BindPrivate(
+ name,
+ [func, member](T& out, const Json::Value* value) -> E {
+ return func(out.*member, value);
+ },
+ required);
+}
+
+template <typename T, typename E>
+template <typename M, typename F>
+cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind(
+ const cm::string_view& name, std::nullptr_t, F func, bool required)
+{
+ return this->BindPrivate(name,
+ [func](T& /*out*/, const Json::Value* value) -> E {
+ M dummy;
+ return func(dummy, value);
+ },
+ required);
+}
+
+template <typename T, typename E>
+cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::BindPrivate(
+ const cm::string_view& name, MemberFunction&& func, bool required)
+{
+ Member m;
+ m.Name = name;
+ m.Function = std::move(func);
+ m.Required = required;
+ this->Members.push_back(std::move(m));
+ if (required) {
+ this->AnyRequired = true;
+ }
+ return *this;
+}
+
+template <typename T, typename E>
+E cmJSONObjectHelper<T, E>::operator()(T& out, const Json::Value* value) const
+{
+ if (!value && this->AnyRequired) {
+ return this->Fail;
+ }
+ if (value && !value->isObject()) {
+ return this->Fail;
+ }
+ Json::Value::Members extraFields;
+ if (value) {
+ extraFields = value->getMemberNames();
+ }
+
+ for (auto const& m : this->Members) {
+ std::string name(m.Name.data(), m.Name.size());
+ if (value && value->isMember(name)) {
+ E result = m.Function(out, &(*value)[name]);
+ if (result != this->Success) {
+ return result;
+ }
+ extraFields.erase(
+ std::find(extraFields.begin(), extraFields.end(), name));
+ } else if (!m.Required) {
+ E result = m.Function(out, nullptr);
+ if (result != this->Success) {
+ return result;
+ }
+ } else {
+ return this->Fail;
+ }
+ }
+
+ return this->AllowExtra || extraFields.empty() ? this->Success : this->Fail;
+}
+
+template <typename E>
+cmJSONHelper<std::string, E> cmJSONStringHelper(E success, E fail,
+ const std::string& defval = "")
+{
+ return
+ [success, fail, defval](std::string& out, const Json::Value* value) -> E {
+ if (!value) {
+ out = defval;
+ return success;
+ }
+ if (!value->isString()) {
+ return fail;
+ }
+ out = value->asString();
+ return success;
+ };
+}
+
+template <typename E>
+cmJSONHelper<int, E> cmJSONIntHelper(E success, E fail, int defval = 0)
+{
+ return [success, fail, defval](int& out, const Json::Value* value) -> E {
+ if (!value) {
+ out = defval;
+ return success;
+ }
+ if (!value->isInt()) {
+ return fail;
+ }
+ out = value->asInt();
+ return success;
+ };
+}
+
+template <typename E>
+cmJSONHelper<unsigned int, E> cmJSONUIntHelper(E success, E fail,
+ unsigned int defval = 0)
+{
+ return
+ [success, fail, defval](unsigned int& out, const Json::Value* value) -> E {
+ if (!value) {
+ out = defval;
+ return success;
+ }
+ if (!value->isUInt()) {
+ return fail;
+ }
+ out = value->asUInt();
+ return success;
+ };
+}
+
+template <typename E>
+cmJSONHelper<bool, E> cmJSONBoolHelper(E success, E fail, bool defval = false)
+{
+ return [success, fail, defval](bool& out, const Json::Value* value) -> E {
+ if (!value) {
+ out = defval;
+ return success;
+ }
+ if (!value->isBool()) {
+ return fail;
+ }
+ out = value->asBool();
+ return success;
+ };
+}
+
+template <typename T, typename E, typename F, typename Filter>
+cmJSONHelper<std::vector<T>, E> cmJSONVectorFilterHelper(E success, E fail,
+ F func, Filter filter)
+{
+ return [success, fail, func, filter](std::vector<T>& out,
+ const Json::Value* value) -> E {
+ if (!value) {
+ out.clear();
+ return success;
+ }
+ if (!value->isArray()) {
+ return fail;
+ }
+ out.clear();
+ for (auto const& item : *value) {
+ T t;
+ E result = func(t, &item);
+ if (result != success) {
+ return result;
+ }
+ if (!filter(t)) {
+ continue;
+ }
+ out.push_back(t);
+ }
+ return success;
+ };
+}
+
+template <typename T, typename E, typename F>
+cmJSONHelper<std::vector<T>, E> cmJSONVectorHelper(E success, E fail, F func)
+{
+ return cmJSONVectorFilterHelper<T, E, F>(success, fail, func,
+ [](const T&) { return true; });
+}
+
+template <typename T, typename E, typename F, typename Filter>
+cmJSONHelper<std::map<std::string, T>, E> cmJSONMapFilterHelper(E success,
+ E fail, F func,
+ Filter filter)
+{
+ return [success, fail, func, filter](std::map<std::string, T>& out,
+ const Json::Value* value) -> E {
+ if (!value) {
+ out.clear();
+ return success;
+ }
+ if (!value->isObject()) {
+ return fail;
+ }
+ out.clear();
+ for (auto const& key : value->getMemberNames()) {
+ if (!filter(key)) {
+ continue;
+ }
+ T t;
+ E result = func(t, &(*value)[key]);
+ if (result != success) {
+ return result;
+ }
+ out[key] = std::move(t);
+ }
+ return success;
+ };
+}
+
+template <typename T, typename E, typename F>
+cmJSONHelper<std::map<std::string, T>, E> cmJSONMapHelper(E success, E fail,
+ F func)
+{
+ return cmJSONMapFilterHelper<T, E, F>(
+ success, fail, func, [](const std::string&) { return true; });
+}
+
+template <typename T, typename E, typename F>
+cmJSONHelper<cm::optional<T>, E> cmJSONOptionalHelper(E success, F func)
+{
+ return [success, func](cm::optional<T>& out, const Json::Value* value) -> E {
+ if (!value) {
+ out.reset();
+ return success;
+ }
+ out.emplace();
+ return func(*out, value);
+ };
+}
+
+template <typename T, typename E, typename F>
+cmJSONHelper<T, E> cmJSONRequiredHelper(E fail, F func)
+{
+ return [fail, func](T& out, const Json::Value* value) -> E {
+ if (!value) {
+ return fail;
+ }
+ return func(out, value);
+ };
+}
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 0ec0757..47931b0 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -2574,17 +2574,29 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
this->Makefile->GetSafeDefinition(
cmStrCat("CMAKE_", lang, "_FLAGS_", configUpper));
+ bool editAndContinueDebugInfo =
+ langFlags.find("/ZI") != std::string::npos ||
+ langFlags.find("-ZI") != std::string::npos;
+
+ bool enableDebuggingInformation =
+ langFlags.find("/Zi") != std::string::npos ||
+ langFlags.find("-Zi") != std::string::npos;
+
// MSVC 2008 is producing both .pdb and .idb files with /Zi.
- if ((langFlags.find("/ZI") != std::string::npos ||
- langFlags.find("-ZI") != std::string::npos) ||
- (cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
- compilerVersion.c_str(),
- "16.0") &&
- compilerId == "MSVC")) {
+ bool msvc2008OrLess =
+ cmSystemTools::VersionCompare(
+ cmSystemTools::OP_LESS, compilerVersion.c_str(), "16.0") &&
+ compilerId == "MSVC";
+ // but not when used via toolset -Tv90
+ if (this->Makefile->GetSafeDefinition(
+ "CMAKE_VS_PLATFORM_TOOLSET") == "v90") {
+ msvc2008OrLess = false;
+ }
+
+ if (editAndContinueDebugInfo || msvc2008OrLess) {
CopyPchCompilePdb(config, target, *ReuseFrom, reuseTarget,
{ ".pdb", ".idb" });
- } else if ((langFlags.find("/Zi") != std::string::npos ||
- langFlags.find("-Zi") != std::string::npos)) {
+ } else if (enableDebuggingInformation) {
CopyPchCompilePdb(config, target, *ReuseFrom, reuseTarget,
{ ".pdb" });
}
diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx
index 98e9db9..3ed49a0 100644
--- a/Source/cmLocalVisualStudio10Generator.cxx
+++ b/Source/cmLocalVisualStudio10Generator.cxx
@@ -68,13 +68,6 @@ cmLocalVisualStudio10Generator::~cmLocalVisualStudio10Generator()
void cmLocalVisualStudio10Generator::GenerateTarget(cmGeneratorTarget* target)
{
- auto& targetVisited = this->GetSourcesVisited(target);
- auto& deps = this->GlobalGenerator->GetTargetDirectDepends(target);
- for (auto& d : deps) {
- // Take the union of visited source files of custom commands
- auto depVisited = this->GetSourcesVisited(d);
- targetVisited.insert(depVisited.begin(), depVisited.end());
- }
if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
->TargetIsFortranOnly(target)) {
this->cmLocalVisualStudio7Generator::GenerateTarget(target);
diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h
index 631132e..45ee082 100644
--- a/Source/cmLocalVisualStudio10Generator.h
+++ b/Source/cmLocalVisualStudio10Generator.h
@@ -28,19 +28,10 @@ public:
void ReadAndStoreExternalGUID(const std::string& name,
const char* path) override;
- std::set<cmSourceFile const*>& GetSourcesVisited(
- cmGeneratorTarget const* target)
- {
- return SourcesVisited[target];
- };
-
protected:
const char* ReportErrorLabel() const override;
bool CustomCommandUseLocal() const override { return true; }
private:
void GenerateTarget(cmGeneratorTarget* target) override;
-
- std::map<cmGeneratorTarget const*, std::set<cmSourceFile const*>>
- SourcesVisited;
};
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 1ebd5da..7795654 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -86,6 +86,15 @@ void cmLocalVisualStudio7Generator::Generate()
if (!gt->IsInBuildSystem() || gt->GetProperty("EXTERNAL_MSPROJECT")) {
continue;
}
+
+ auto& gtVisited = this->GetSourcesVisited(gt);
+ auto& deps = this->GlobalGenerator->GetTargetDirectDepends(gt);
+ for (auto& d : deps) {
+ // Take the union of visited source files of custom commands
+ auto depVisited = this->GetSourcesVisited(d);
+ gtVisited.insert(depVisited.begin(), depVisited.end());
+ }
+
this->GenerateTarget(gt);
}
@@ -1615,6 +1624,8 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
this->WriteVCProjBeginGroup(fout, name.c_str(), "");
}
+ auto& sourcesVisited = this->GetSourcesVisited(target);
+
// Loop through each source in the source group.
for (const cmSourceFile* sf : sourceFiles) {
std::string source = sf->GetFullPath();
@@ -1638,7 +1649,10 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
// build it, then it will.
fout << "\t\t\t\tRelativePath=\"" << d << "\">\n";
if (cmCustomCommand const* command = sf->GetCustomCommand()) {
- this->WriteCustomRule(fout, configs, source.c_str(), *command, fcinfo);
+ if (sourcesVisited.insert(sf).second) {
+ this->WriteCustomRule(fout, configs, source.c_str(), *command,
+ fcinfo);
+ }
} else if (!fcinfo.FileConfigMap.empty()) {
const char* aCompilerTool = "VCCLCompilerTool";
std::string ppLang = "CXX";
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index 9ccd1a1..6e06c09 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -83,6 +83,12 @@ public:
virtual void ReadAndStoreExternalGUID(const std::string& name,
const char* path);
+ std::set<cmSourceFile const*>& GetSourcesVisited(
+ cmGeneratorTarget const* target)
+ {
+ return this->SourcesVisited[target];
+ };
+
protected:
virtual void GenerateTarget(cmGeneratorTarget* target);
@@ -148,4 +154,7 @@ private:
bool FortranProject;
bool WindowsCEProject;
std::unique_ptr<cmLocalVisualStudio7GeneratorInternals> Internal;
+
+ std::map<cmGeneratorTarget const*, std::set<cmSourceFile const*>>
+ SourcesVisited;
};
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index ebbe3e7..d77c4af 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -2898,7 +2898,7 @@ MessageType cmMakefile::ExpandVariablesInStringOld(
parser.SetNoEscapeMode(noEscapes);
parser.SetReplaceAtSyntax(replaceAt);
parser.SetRemoveEmpty(removeEmpty);
- int res = parser.ParseString(source.c_str(), 0);
+ int res = parser.ParseString(source, 0);
const char* emsg = parser.GetError();
MessageType mtype = MessageType::LOG;
if (res && !emsg[0]) {
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 71c288c..9cb172b 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -192,7 +192,7 @@ public:
{
public:
// -- Parse Cache
- bool ParseCacheChanged = false;
+ std::atomic<bool> ParseCacheChanged = ATOMIC_VAR_INIT(false);
cmFileTime ParseCacheTime;
ParseCacheT ParseCache;
@@ -1777,16 +1777,24 @@ bool cmQtAutoMocUicT::JobProbeDepsMocT::Probe(MappingT const& mapping,
{
// Check dependency timestamps
std::string const sourceDir = SubDirPrefix(sourceFile);
- for (std::string const& dep : mapping.SourceFile->ParseData->Moc.Depends) {
+ auto& dependencies = mapping.SourceFile->ParseData->Moc.Depends;
+ for (auto it = dependencies.begin(); it != dependencies.end(); ++it) {
+ auto& dep = *it;
+
// Find dependency file
auto const depMatch = FindDependency(sourceDir, dep);
if (depMatch.first.empty()) {
- Log().Warning(GenT::MOC,
- cmStrCat(MessagePath(sourceFile), " depends on ",
- MessagePath(dep),
- " but the file does not exist."));
- continue;
+ if (reason != nullptr) {
+ *reason =
+ cmStrCat("Generating ", MessagePath(outputFile), " from ",
+ MessagePath(sourceFile), ", because its dependency ",
+ MessagePath(dep), " vanished.");
+ }
+ dependencies.erase(it);
+ BaseEval().ParseCacheChanged = true;
+ return true;
}
+
// Test if dependency file is older
if (outputFileTime.Older(depMatch.second)) {
if (reason != nullptr) {
diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h
index f3c262b..01e3d94 100644
--- a/Source/cmStringAlgorithms.h
+++ b/Source/cmStringAlgorithms.h
@@ -33,6 +33,13 @@ inline bool cmNonempty(std::string const* str)
return str && !str->empty();
}
+/** Returns length of a literal string. */
+template <size_t N>
+constexpr size_t cmStrLen(const char (&/*str*/)[N])
+{
+ return N - 1;
+}
+
/** Callable string comparison struct. */
struct cmStrCmp
{