summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CTest/cmCTestRunTest.cxx34
-rw-r--r--Source/CTest/cmCTestRunTest.h2
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx6
-rw-r--r--Source/CTest/cmCTestTestHandler.h1
-rw-r--r--Source/CursesDialog/cmCursesLongMessageForm.cxx2
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.cxx4
-rw-r--r--Source/cmExportFileGenerator.cxx10
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx2
-rw-r--r--Source/cmFileCommand.cxx13
-rw-r--r--Source/cmGeneratorTarget.cxx93
-rw-r--r--Source/cmGeneratorTarget.h37
-rw-r--r--Source/cmGetPropertyCommand.cxx61
-rw-r--r--Source/cmGetSourceFilePropertyCommand.cxx52
-rw-r--r--Source/cmGlobalGenerator.cxx6
-rw-r--r--Source/cmGlobalGenerator.h2
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx1
-rw-r--r--Source/cmMakefile.cxx12
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx2
-rw-r--r--Source/cmPropertyDefinition.cxx39
-rw-r--r--Source/cmPropertyDefinition.h36
-rw-r--r--Source/cmPropertyDefinitionMap.cxx35
-rw-r--r--Source/cmPropertyDefinitionMap.h30
-rw-r--r--Source/cmSetPropertyCommand.cxx197
-rw-r--r--Source/cmSetPropertyCommand.h29
-rw-r--r--Source/cmSetSourceFilesPropertiesCommand.cxx113
-rw-r--r--Source/cmState.cxx30
-rw-r--r--Source/cmState.h8
-rw-r--r--Source/cmTarget.cxx4
-rw-r--r--Source/cmTarget.h8
-rw-r--r--Source/cmTestGenerator.cxx14
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx213
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h11
-rw-r--r--Source/cmXCodeScheme.cxx3
-rw-r--r--Source/kwsys/Directory.cxx35
-rw-r--r--Source/kwsys/Directory.hxx.in5
-rw-r--r--Source/kwsys/Glob.cxx14
-rw-r--r--Source/kwsys/Glob.hxx.in1
-rw-r--r--Source/kwsys/testDirectory.cxx37
40 files changed, 810 insertions, 396 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index ec473d2..6d585ee 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -383,8 +383,6 @@ set(SRCS
cmProperty.h
cmPropertyDefinition.cxx
cmPropertyDefinition.h
- cmPropertyDefinitionMap.cxx
- cmPropertyDefinitionMap.h
cmPropertyMap.cxx
cmPropertyMap.h
cmQtAutoGen.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index b820d73..f283497 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 17)
-set(CMake_VERSION_PATCH 20200515)
+set(CMake_VERSION_PATCH 20200521)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 7674d7a..ba7d47e 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -429,6 +429,7 @@ void cmCTestRunTest::StartFailure(std::string const& output,
this->TestResult.Path = this->TestProperties->Directory;
this->TestResult.Output = output;
this->TestResult.FullCommandLine.clear();
+ this->TestResult.Environment.clear();
}
std::string cmCTestRunTest::GetTestPrefix(size_t completed, size_t total) const
@@ -500,6 +501,7 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total)
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
this->TestResult.Output = "Disabled";
this->TestResult.FullCommandLine.clear();
+ this->TestResult.Environment.clear();
return false;
}
@@ -519,6 +521,7 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total)
cmCTestLog(this->CTest, HANDLER_OUTPUT, msg << std::endl);
this->TestResult.Output = msg;
this->TestResult.FullCommandLine.clear();
+ this->TestResult.Environment.clear();
this->TestResult.CompletionStatus = "Fixture dependency failed";
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
return false;
@@ -539,6 +542,7 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total)
cmCTestLog(this->CTest, ERROR_MESSAGE, msg << std::endl);
this->TestResult.Output = msg;
this->TestResult.FullCommandLine.clear();
+ this->TestResult.Environment.clear();
this->TestResult.CompletionStatus = "Missing Configuration";
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
return false;
@@ -554,6 +558,7 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total)
"Unable to find required file: " << file << std::endl);
this->TestResult.Output = "Unable to find required file: " + file;
this->TestResult.FullCommandLine.clear();
+ this->TestResult.Environment.clear();
this->TestResult.CompletionStatus = "Required Files Missing";
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
return false;
@@ -569,6 +574,7 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total)
"Unable to find executable: " << args[1] << std::endl);
this->TestResult.Output = "Unable to find executable: " + args[1];
this->TestResult.FullCommandLine.clear();
+ this->TestResult.Environment.clear();
this->TestResult.CompletionStatus = "Unable to find executable";
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
return false;
@@ -713,25 +719,43 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
cmSystemTools::SaveRestoreEnvironment sre;
#endif
+ std::ostringstream envMeasurement;
if (environment && !environment->empty()) {
cmSystemTools::AppendEnv(*environment);
+ for (auto const& var : *environment) {
+ envMeasurement << var << std::endl;
+ }
}
if (this->UseAllocatedResources) {
- this->SetupResourcesEnvironment();
+ std::vector<std::string> envLog;
+ this->SetupResourcesEnvironment(&envLog);
+ for (auto const& var : envLog) {
+ envMeasurement << var << std::endl;
+ }
} else {
cmSystemTools::UnsetEnv("CTEST_RESOURCE_GROUP_COUNT");
+ // Signify that this variable is being actively unset
+ envMeasurement << "#CTEST_RESOURCE_GROUP_COUNT=" << std::endl;
}
+ this->TestResult.Environment = envMeasurement.str();
+ // Remove last newline
+ this->TestResult.Environment.erase(this->TestResult.Environment.length() -
+ 1);
+
return this->TestProcess->StartProcess(this->MultiTestHandler.Loop,
affinity);
}
-void cmCTestRunTest::SetupResourcesEnvironment()
+void cmCTestRunTest::SetupResourcesEnvironment(std::vector<std::string>* log)
{
std::string processCount = "CTEST_RESOURCE_GROUP_COUNT=";
processCount += std::to_string(this->AllocatedResources.size());
cmSystemTools::PutEnv(processCount);
+ if (log) {
+ log->push_back(processCount);
+ }
std::size_t i = 0;
for (auto const& process : this->AllocatedResources) {
@@ -757,8 +781,14 @@ void cmCTestRunTest::SetupResourcesEnvironment()
var += "id:" + it2.Id + ",slots:" + std::to_string(it2.Slots);
}
cmSystemTools::PutEnv(var);
+ if (log) {
+ log->push_back(var);
+ }
}
cmSystemTools::PutEnv(resourceList);
+ if (log) {
+ log->push_back(resourceList);
+ }
++i;
}
}
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index b1d188a..d831247 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -119,7 +119,7 @@ private:
// Run post processing of the process output for MemCheck
void MemCheckPostProcess();
- void SetupResourcesEnvironment();
+ void SetupResourcesEnvironment(std::vector<std::string>* log = nullptr);
// Returns "completed/total Test #Index: "
std::string GetTestPrefix(size_t completed, size_t total) const;
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 8fc5cd6..d0dbaae 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -1432,6 +1432,12 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
xml.Attribute("name", "Command Line");
xml.Element("Value", result.FullCommandLine);
xml.EndElement(); // NamedMeasurement
+
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "text/string");
+ xml.Attribute("name", "Environment");
+ xml.Element("Value", result.Environment);
+ xml.EndElement(); // NamedMeasurement
for (auto const& measure : result.Properties->Measurements) {
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 55cecb6..0d88c30 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -169,6 +169,7 @@ public:
std::string Path;
std::string Reason;
std::string FullCommandLine;
+ std::string Environment;
cmDuration ExecutionTime;
std::int64_t ReturnValue;
int Status;
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx
index 664ba2f..591c546 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.cxx
+++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx
@@ -68,7 +68,7 @@ void cmCursesLongMessageForm::UpdateStatusBar()
bar[i] = ' ';
}
int width;
- if (x < cmCursesMainForm::MAX_WIDTH) {
+ if (x >= 0 && x < cmCursesMainForm::MAX_WIDTH) {
width = x;
} else {
width = cmCursesMainForm::MAX_WIDTH - 1;
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx
index 0ee1259..3641cb2 100644
--- a/Source/cmExportBuildAndroidMKGenerator.cxx
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -47,7 +47,9 @@ void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
os << "LOCAL_MODULE := ";
os << targetName << "\n";
os << "LOCAL_SRC_FILES := ";
- std::string path = cmSystemTools::ConvertToOutputPath(target->GetFullPath());
+ std::string const noConfig; // FIXME: What config to use here?
+ std::string path =
+ cmSystemTools::ConvertToOutputPath(target->GetFullPath(noConfig));
os << path << "\n";
}
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 28037c6..ed0689a 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -923,12 +923,14 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os)
/* clang-format on */
// Isolate the file policy level.
- // We use 2.6 here instead of the current version because newer
- // versions of CMake should be able to export files imported by 2.6
- // until the import format changes.
+ // Support CMake versions as far back as 2.6 but also support using NEW
+ // policy settings for up to CMake 3.17 (this upper limit may be reviewed
+ // and increased from time to time). This reduces the opportunity for CMake
+ // warnings when an older export file is later used with newer CMake
+ // versions.
/* clang-format off */
os << "cmake_policy(PUSH)\n"
- << "cmake_policy(VERSION 2.6)\n";
+ << "cmake_policy(VERSION 2.6...3.17)\n";
/* clang-format on */
}
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index 6212667..46056c1 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -71,7 +71,7 @@ std::string cmExportTryCompileFileGenerator::FindTargets(
cmTarget dummyHead("try_compile_dummy_exe", cmStateEnums::EXECUTABLE,
cmTarget::VisibilityNormal, tgt->Target->GetMakefile(),
- true);
+ cmTarget::PerConfig::Yes);
cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator());
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index f3d49c3..268c5d1 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -677,12 +677,12 @@ bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse,
}
}
+ cmake* cm = status.GetMakefile().GetCMakeInstance();
std::vector<std::string> files;
bool configureDepends = false;
bool warnConfigureLate = false;
bool warnFollowedSymlinks = false;
- const cmake::WorkingMode workingMode =
- status.GetMakefile().GetCMakeInstance()->GetWorkingMode();
+ const cmake::WorkingMode workingMode = cm->GetWorkingMode();
while (i != args.end()) {
if (*i == "LIST_DIRECTORIES") {
++i; // skip LIST_DIRECTORIES
@@ -770,12 +770,17 @@ bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse,
MessageType::AUTHOR_WARNING,
"Cyclic recursion detected while globbing for '" + *i + "':\n" +
globMessage.content);
- } else {
+ } else if (globMessage.type == cmsys::Glob::error) {
status.GetMakefile().IssueMessage(
MessageType::FATAL_ERROR,
"Error has occurred while globbing for '" + *i + "' - " +
globMessage.content);
shouldExit = true;
+ } else if (cm->GetDebugOutput() || cm->GetTrace()) {
+ status.GetMakefile().IssueMessage(
+ MessageType::LOG,
+ cmStrCat("Globbing for\n ", *i, "\nEncountered an error:\n ",
+ globMessage.content));
}
}
if (shouldExit) {
@@ -795,7 +800,7 @@ bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse,
std::sort(foundFiles.begin(), foundFiles.end());
foundFiles.erase(std::unique(foundFiles.begin(), foundFiles.end()),
foundFiles.end());
- status.GetMakefile().GetCMakeInstance()->AddGlobCacheEntry(
+ cm->AddGlobCacheEntry(
recurse, (recurse ? g.GetRecurseListDirs() : g.GetListDirs()),
(recurse ? g.GetRecurseThroughSymlinks() : false),
(g.GetRelative() ? g.GetRelative() : ""), expr, foundFiles, variable,
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index a44126c..2f9da1c 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -693,6 +693,7 @@ const char* cmGeneratorTarget::GetFileSuffixInternal(
void cmGeneratorTarget::ClearSourcesCache()
{
+ this->AllConfigSources.clear();
this->KindedSourcesMap.clear();
this->LinkImplementationLanguageIsContextDependent = true;
this->Objects.clear();
@@ -975,51 +976,12 @@ void cmGeneratorTarget::GetExternalObjects(
IMPLEMENT_VISIT(SourceKindExternalObject);
}
-void cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& headers,
- const std::string& config) const
-{
- KindedSources const& kinded = this->GetKindedSources(config);
- headers = kinded.ExpectedResxHeaders;
-}
-
-void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile const*>& data,
- const std::string& config) const
-{
- IMPLEMENT_VISIT(SourceKindResx);
-}
-
-void cmGeneratorTarget::GetAppManifest(std::vector<cmSourceFile const*>& data,
- const std::string& config) const
-{
- IMPLEMENT_VISIT(SourceKindAppManifest);
-}
-
void cmGeneratorTarget::GetManifests(std::vector<cmSourceFile const*>& data,
const std::string& config) const
{
IMPLEMENT_VISIT(SourceKindManifest);
}
-void cmGeneratorTarget::GetCertificates(std::vector<cmSourceFile const*>& data,
- const std::string& config) const
-{
- IMPLEMENT_VISIT(SourceKindCertificate);
-}
-
-void cmGeneratorTarget::GetExpectedXamlHeaders(std::set<std::string>& headers,
- const std::string& config) const
-{
- KindedSources const& kinded = this->GetKindedSources(config);
- headers = kinded.ExpectedXamlHeaders;
-}
-
-void cmGeneratorTarget::GetExpectedXamlSources(std::set<std::string>& srcs,
- const std::string& config) const
-{
- KindedSources const& kinded = this->GetKindedSources(config);
- srcs = kinded.ExpectedXamlSources;
-}
-
std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
{
if (!this->UtilityItemsDone) {
@@ -1039,12 +1001,6 @@ std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
return this->UtilityItems;
}
-void cmGeneratorTarget::GetXamlSources(std::vector<cmSourceFile const*>& data,
- const std::string& config) const
-{
- IMPLEMENT_VISIT(SourceKindXaml);
-}
-
const std::string& cmGeneratorTarget::GetLocation(
const std::string& config) const
{
@@ -1096,7 +1052,8 @@ const std::string& cmGeneratorTarget::GetLocationForBuild() const
}
// Now handle the deprecated build-time configuration location.
- location = this->GetDirectory();
+ std::string const noConfig;
+ location = this->GetDirectory(noConfig);
const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
if (cfgid && strcmp(cfgid, ".") != 0) {
location += "/";
@@ -1726,14 +1683,6 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
}
} else if (ext == "resx") {
kind = SourceKindResx;
- // Build and save the name of the corresponding .h file
- // This relationship will be used later when building the project files.
- // Both names would have been auto generated from Visual Studio
- // where the user supplied the file name and Visual Studio
- // appended the suffix.
- std::string resx = sf->ResolveFullPath();
- std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h";
- files.ExpectedResxHeaders.insert(hFileName);
} else if (ext == "appxmanifest") {
kind = SourceKindAppManifest;
} else if (ext == "manifest") {
@@ -1742,16 +1691,6 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
kind = SourceKindCertificate;
} else if (ext == "xaml") {
kind = SourceKindXaml;
- // Build and save the name of the corresponding .h and .cpp file
- // This relationship will be used later when building the project files.
- // Both names would have been auto generated from Visual Studio
- // where the user supplied the file name and Visual Studio
- // appended the suffix.
- std::string xaml = sf->ResolveFullPath();
- std::string hFileName = xaml + ".h";
- std::string cppFileName = xaml + ".cpp";
- files.ExpectedXamlHeaders.insert(hFileName);
- files.ExpectedXamlSources.insert(cppFileName);
} else if (header_regex.find(sf->ResolveFullPath())) {
kind = SourceKindHeader;
} else {
@@ -1809,6 +1748,18 @@ void cmGeneratorTarget::ComputeAllConfigSources() const
}
}
+std::vector<cmGeneratorTarget::AllConfigSource>
+cmGeneratorTarget::GetAllConfigSources(SourceKind kind) const
+{
+ std::vector<AllConfigSource> result;
+ for (AllConfigSource const& source : this->GetAllConfigSources()) {
+ if (source.Kind == kind) {
+ result.push_back(source);
+ }
+ }
+ return result;
+}
+
std::set<std::string> cmGeneratorTarget::GetAllConfigCompileLanguages() const
{
std::set<std::string> languages;
@@ -3179,6 +3130,20 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
flags += "]";
}
+ } else if (compiler == "Clang") {
+ for (CudaArchitecture& architecture : architectures) {
+ flags += " --cuda-gpu-arch=sm_" + architecture.name;
+
+ if (!architecture.real) {
+ Makefile->IssueMessage(
+ MessageType::WARNING,
+ "Clang doesn't support disabling CUDA real code generation.");
+ }
+
+ if (!architecture.virtual_) {
+ flags += " --no-cuda-include-ptx=sm_" + architecture.name;
+ }
+ }
}
}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index ff03914..c8732bc 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -117,9 +117,6 @@ public:
struct KindedSources
{
std::vector<SourceAndKind> Sources;
- std::set<std::string> ExpectedResxHeaders;
- std::set<std::string> ExpectedXamlHeaders;
- std::set<std::string> ExpectedXamlSources;
bool Initialized = false;
};
@@ -137,6 +134,9 @@ public:
per-source configurations assigned. */
std::vector<AllConfigSource> const& GetAllConfigSources() const;
+ /** Get all sources needed for all configurations with given kind. */
+ std::vector<AllConfigSource> GetAllConfigSources(SourceKind kind) const;
+
/** Get all languages used to compile sources in any configuration.
This excludes the languages of objects from object libraries. */
std::set<std::string> GetAllConfigCompileLanguages() const;
@@ -151,8 +151,6 @@ public:
void GetModuleDefinitionSources(std::vector<cmSourceFile const*>&,
const std::string& config) const;
- void GetResxSources(std::vector<cmSourceFile const*>&,
- const std::string& config) const;
void GetExternalObjects(std::vector<cmSourceFile const*>&,
const std::string& config) const;
void GetHeaderSources(std::vector<cmSourceFile const*>&,
@@ -161,20 +159,8 @@ public:
const std::string& config) const;
void GetCustomCommands(std::vector<cmSourceFile const*>&,
const std::string& config) const;
- void GetExpectedResxHeaders(std::set<std::string>&,
- const std::string& config) const;
- void GetAppManifest(std::vector<cmSourceFile const*>&,
- const std::string& config) const;
void GetManifests(std::vector<cmSourceFile const*>&,
const std::string& config) const;
- void GetCertificates(std::vector<cmSourceFile const*>&,
- const std::string& config) const;
- void GetXamlSources(std::vector<cmSourceFile const*>&,
- const std::string& config) const;
- void GetExpectedXamlHeaders(std::set<std::string>&,
- const std::string& config) const;
- void GetExpectedXamlSources(std::set<std::string>&,
- const std::string& config) const;
std::set<cmLinkItem> const& GetUtilityItems() const;
@@ -245,7 +231,7 @@ public:
/** Get the full path to the target according to the settings in its
makefile and the configuration type. */
std::string GetFullPath(
- const std::string& config = "",
+ const std::string& config,
cmStateEnums::ArtifactType artifact = cmStateEnums::RuntimeBinaryArtifact,
bool realname = false) const;
std::string NormalGetFullPath(const std::string& config,
@@ -283,7 +269,7 @@ public:
/** Get the full name of the target according to the settings in its
makefile. */
- std::string GetFullName(const std::string& config = "",
+ std::string GetFullName(const std::string& config,
cmStateEnums::ArtifactType artifact =
cmStateEnums::RuntimeBinaryArtifact) const;
@@ -326,8 +312,7 @@ public:
std::string GetSOName(const std::string& config) const;
void GetFullNameComponents(std::string& prefix, std::string& base,
- std::string& suffix,
- const std::string& config = "",
+ std::string& suffix, const std::string& config,
cmStateEnums::ArtifactType artifact =
cmStateEnums::RuntimeBinaryArtifact) const;
@@ -540,7 +525,7 @@ public:
configuration name is given then the generator will add its
subdirectory for that configuration. Otherwise just the canonical
output directory is given. */
- std::string GetDirectory(const std::string& config = "",
+ std::string GetDirectory(const std::string& config,
cmStateEnums::ArtifactType artifact =
cmStateEnums::RuntimeBinaryArtifact) const;
@@ -548,7 +533,7 @@ public:
If the configuration name is given then the generator will add its
subdirectory for that configuration. Otherwise just the canonical
compiler pdb output directory is given. */
- std::string GetCompilePDBDirectory(const std::string& config = "") const;
+ std::string GetCompilePDBDirectory(const std::string& config) const;
/** Get sources that must be built before the given source. */
std::vector<cmSourceFile*> const* GetSourceDepends(
@@ -577,7 +562,7 @@ public:
std::string GetPDBOutputName(const std::string& config) const;
/** Get the name of the pdb file for the target. */
- std::string GetPDBName(const std::string& config = "") const;
+ std::string GetPDBName(const std::string& config) const;
/** Whether this library has soname enabled and platform supports it. */
bool HasSOName(const std::string& config) const;
@@ -595,10 +580,10 @@ public:
bool IsNullImpliedByLinkLibraries(const std::string& p) const;
/** Get the name of the compiler pdb file for the target. */
- std::string GetCompilePDBName(const std::string& config = "") const;
+ std::string GetCompilePDBName(const std::string& config) const;
/** Get the path for the MSVC /Fd option for this target. */
- std::string GetCompilePDBPath(const std::string& config = "") const;
+ std::string GetCompilePDBPath(const std::string& config) const;
// Get the target base name.
std::string GetOutputName(const std::string& config,
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index c3ac672..851f426 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -11,6 +11,7 @@
#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmPropertyDefinition.h"
+#include "cmSetPropertyCommand.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
@@ -48,7 +49,9 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
const std::string& propertyName);
bool HandleSourceMode(cmExecutionStatus& status, const std::string& name,
OutType infoType, const std::string& variable,
- const std::string& propertyName);
+ const std::string& propertyName,
+ cmMakefile& directory_makefile,
+ bool source_file_paths_should_be_absolute);
bool HandleTestMode(cmExecutionStatus& status, const std::string& name,
OutType infoType, const std::string& variable,
const std::string& propertyName);
@@ -78,6 +81,11 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args,
std::string name;
std::string propertyName;
+ std::vector<std::string> source_file_directories;
+ std::vector<std::string> source_file_target_directories;
+ bool source_file_directory_option_enabled = false;
+ bool source_file_target_option_enabled = false;
+
// Get the scope from which to get the property.
cmProperty::ScopeType scope;
if (args[1] == "GLOBAL") {
@@ -111,7 +119,9 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args,
DoingNone,
DoingName,
DoingProperty,
- DoingType
+ DoingType,
+ DoingSourceDirectory,
+ DoingSourceTargetDirectory
};
Doing doing = DoingName;
for (unsigned int i = 2; i < args.size(); ++i) {
@@ -132,6 +142,20 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args,
} else if (doing == DoingName) {
doing = DoingNone;
name = args[i];
+ } else if (doing == DoingNone && scope == cmProperty::SOURCE_FILE &&
+ args[i] == "DIRECTORY") {
+ doing = DoingSourceDirectory;
+ source_file_directory_option_enabled = true;
+ } else if (doing == DoingNone && scope == cmProperty::SOURCE_FILE &&
+ args[i] == "TARGET_DIRECTORY") {
+ doing = DoingSourceTargetDirectory;
+ source_file_target_option_enabled = true;
+ } else if (doing == DoingSourceDirectory) {
+ source_file_directories.push_back(args[i]);
+ doing = DoingNone;
+ } else if (doing == DoingSourceTargetDirectory) {
+ source_file_target_directories.push_back(args[i]);
+ doing = DoingNone;
} else if (doing == DoingProperty) {
doing = DoingNone;
propertyName = args[i];
@@ -147,6 +171,16 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args,
return false;
}
+ std::vector<cmMakefile*> source_file_directory_makefiles;
+ bool file_scopes_handled =
+ SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes(
+ status, source_file_directory_option_enabled,
+ source_file_target_option_enabled, source_file_directories,
+ source_file_target_directories, source_file_directory_makefiles);
+ if (!file_scopes_handled) {
+ return false;
+ }
+
// Compute requested output.
if (infoType == OutBriefDoc) {
// Lookup brief documentation.
@@ -180,6 +214,11 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args,
}
} else {
// Dispatch property getting.
+ cmMakefile& directory_scope_mf = *(source_file_directory_makefiles[0]);
+ bool source_file_paths_should_be_absolute =
+ source_file_directory_option_enabled ||
+ source_file_target_option_enabled;
+
switch (scope) {
case cmProperty::GLOBAL:
return HandleGlobalMode(status, name, infoType, variable,
@@ -191,8 +230,9 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args,
return HandleTargetMode(status, name, infoType, variable,
propertyName);
case cmProperty::SOURCE_FILE:
- return HandleSourceMode(status, name, infoType, variable,
- propertyName);
+ return HandleSourceMode(status, name, infoType, variable, propertyName,
+ directory_scope_mf,
+ source_file_paths_should_be_absolute);
case cmProperty::TEST:
return HandleTestMode(status, name, infoType, variable, propertyName);
case cmProperty::VARIABLE:
@@ -331,7 +371,9 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
bool HandleSourceMode(cmExecutionStatus& status, const std::string& name,
OutType infoType, const std::string& variable,
- const std::string& propertyName)
+ const std::string& propertyName,
+ cmMakefile& directory_makefile,
+ const bool source_file_paths_should_be_absolute)
{
if (name.empty()) {
status.SetError("not given name for SOURCE scope.");
@@ -339,12 +381,17 @@ bool HandleSourceMode(cmExecutionStatus& status, const std::string& name,
}
// Get the source file.
- if (cmSourceFile* sf = status.GetMakefile().GetOrCreateSource(name)) {
+ const std::string source_file_absolute_path =
+ SetPropertyCommand::MakeSourceFilePathAbsoluteIfNeeded(
+ status, name, source_file_paths_should_be_absolute);
+ if (cmSourceFile* sf =
+ directory_makefile.GetOrCreateSource(source_file_absolute_path)) {
return StoreResult(infoType, status.GetMakefile(), variable,
sf->GetPropertyForUser(propertyName));
}
status.SetError(
- cmStrCat("given SOURCE name that could not be found or created: ", name));
+ cmStrCat("given SOURCE name that could not be found or created: ",
+ source_file_absolute_path));
return false;
}
diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx
index eefdc6c..5395bc8 100644
--- a/Source/cmGetSourceFilePropertyCommand.cxx
+++ b/Source/cmGetSourceFilePropertyCommand.cxx
@@ -4,35 +4,71 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmSetPropertyCommand.h"
#include "cmSourceFile.h"
bool cmGetSourceFilePropertyCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- if (args.size() != 3) {
+ std::vector<std::string>::size_type args_size = args.size();
+ if (args_size != 3 && args_size != 5) {
status.SetError("called with incorrect number of arguments");
return false;
}
+
+ std::vector<std::string> source_file_directories;
+ std::vector<std::string> source_file_target_directories;
+ bool source_file_directory_option_enabled = false;
+ bool source_file_target_option_enabled = false;
+
+ int property_arg_index = 2;
+ if (args[2] == "DIRECTORY" && args_size == 5) {
+ property_arg_index = 4;
+ source_file_directory_option_enabled = true;
+ source_file_directories.push_back(args[3]);
+ } else if (args[2] == "TARGET_DIRECTORY" && args_size == 5) {
+ property_arg_index = 4;
+ source_file_target_option_enabled = true;
+ source_file_target_directories.push_back(args[3]);
+ }
+
+ std::vector<cmMakefile*> source_file_directory_makefiles;
+ bool file_scopes_handled =
+ SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes(
+ status, source_file_directory_option_enabled,
+ source_file_target_option_enabled, source_file_directories,
+ source_file_target_directories, source_file_directory_makefiles);
+ if (!file_scopes_handled) {
+ return false;
+ }
+
std::string const& var = args[0];
- std::string const& file = args[1];
- cmMakefile& mf = status.GetMakefile();
+ bool source_file_paths_should_be_absolute =
+ source_file_directory_option_enabled || source_file_target_option_enabled;
+ std::string const file =
+ SetPropertyCommand::MakeSourceFilePathAbsoluteIfNeeded(
+ status, args[1], source_file_paths_should_be_absolute);
+ cmMakefile& mf = *source_file_directory_makefiles[0];
cmSourceFile* sf = mf.GetSource(file);
// for the location we must create a source file first
- if (!sf && args[2] == "LOCATION") {
+ if (!sf && args[property_arg_index] == "LOCATION") {
sf = mf.CreateSource(file);
}
+
if (sf) {
const char* prop = nullptr;
- if (!args[2].empty()) {
- prop = sf->GetPropertyForUser(args[2]);
+ if (!args[property_arg_index].empty()) {
+ prop = sf->GetPropertyForUser(args[property_arg_index]);
}
if (prop) {
- mf.AddDefinition(var, prop);
+ // Set the value on the original Makefile scope, not the scope of the
+ // requested directory.
+ status.GetMakefile().AddDefinition(var, prop);
return true;
}
}
- mf.AddDefinition(var, "NOTFOUND");
+ status.GetMakefile().AddDefinition(var, "NOTFOUND");
return true;
}
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 6370ed2..0b7ba04 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -320,7 +320,7 @@ bool cmGlobalGenerator::CheckTargetsForMissingSources() const
} else {
for (std::string const& config : configs) {
target->GetSourceFiles(srcs, config);
- if (srcs.empty()) {
+ if (!srcs.empty()) {
break;
}
}
@@ -2535,7 +2535,7 @@ void cmGlobalGenerator::AddGlobalTarget_EditCache(
}
GlobalTargetInfo gti;
gti.Name = editCacheTargetName;
- gti.PerConfig = false;
+ gti.PerConfig = cmTarget::PerConfig::No;
cmCustomCommandLine singleLine;
// Use generator preference for the edit_cache rule if it is defined.
@@ -2571,7 +2571,7 @@ void cmGlobalGenerator::AddGlobalTarget_RebuildCache(
gti.Name = rebuildCacheTargetName;
gti.Message = "Running CMake to regenerate build system...";
gti.UsesTerminal = true;
- gti.PerConfig = false;
+ gti.PerConfig = cmTarget::PerConfig::No;
cmCustomCommandLine singleLine;
singleLine.push_back(cmSystemTools::GetCMakeCommand());
singleLine.push_back("--regenerate-during-build");
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index dcd5a66..57c7808 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -553,7 +553,7 @@ protected:
std::vector<std::string> Depends;
std::string WorkingDir;
bool UsesTerminal = false;
- bool PerConfig = true;
+ cmTarget::PerConfig PerConfig = cmTarget::PerConfig::Yes;
bool StdPipesUTF8 = false;
};
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 28bd1ca..0932d06 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -112,6 +112,7 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout)
{
char utf8bom[] = { char(0xEF), char(0xBB), char(0xBF) };
fout.write(utf8bom, 3);
+ fout << '\n';
switch (this->Version) {
case cmGlobalVisualStudioGenerator::VS9:
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 6f05d45..154da50 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -2081,11 +2081,11 @@ cmTarget* cmMakefile::AddExecutable(const std::string& exeName,
cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type,
const std::string& name)
{
- auto it =
- this->Targets
- .emplace(name,
- cmTarget(name, type, cmTarget::VisibilityNormal, this, true))
- .first;
+ auto it = this->Targets
+ .emplace(name,
+ cmTarget(name, type, cmTarget::VisibilityNormal, this,
+ cmTarget::PerConfig::Yes))
+ .first;
this->OrderedTargets.push_back(&it->second);
this->GetGlobalGenerator()->IndexTarget(&it->second);
this->GetStateSnapshot().GetDirectory().AddNormalTargetName(name);
@@ -4261,7 +4261,7 @@ cmTarget* cmMakefile::AddImportedTarget(const std::string& name,
new cmTarget(name, type,
global ? cmTarget::VisibilityImportedGlobally
: cmTarget::VisibilityImported,
- this, true));
+ this, cmTarget::PerConfig::Yes));
// Add to the set of available imported targets.
this->ImportedTargets[name] = target.get();
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index db069ed..f87eba7 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -1024,7 +1024,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
std::string prefix;
std::string base;
std::string suffix;
- gt->GetFullNameComponents(prefix, base, suffix);
+ gt->GetFullNameComponents(prefix, base, suffix, config);
std::string dbg_suffix = ".dbg";
// TODO: Where to document?
if (mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX")) {
diff --git a/Source/cmPropertyDefinition.cxx b/Source/cmPropertyDefinition.cxx
index c8efaf6..1796bb8 100644
--- a/Source/cmPropertyDefinition.cxx
+++ b/Source/cmPropertyDefinition.cxx
@@ -2,17 +2,38 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmPropertyDefinition.h"
-#include <utility>
+#include <tuple>
-cmPropertyDefinition::cmPropertyDefinition(std::string name,
- cmProperty::ScopeType scope,
- std::string shortDescription,
+cmPropertyDefinition::cmPropertyDefinition(std::string shortDescription,
std::string fullDescription,
- bool chain)
- : Name(std::move(name))
- , ShortDescription(std::move(shortDescription))
+ bool chained)
+ : ShortDescription(std::move(shortDescription))
, FullDescription(std::move(fullDescription))
- , Scope(scope)
- , Chained(chain)
+ , Chained(chained)
{
}
+
+void cmPropertyDefinitionMap::DefineProperty(
+ const std::string& name, cmProperty::ScopeType scope,
+ const std::string& ShortDescription, const std::string& FullDescription,
+ bool chain)
+{
+ auto it = this->Map_.find(key_type(name, scope));
+ if (it == this->Map_.end()) {
+ // try_emplace() since C++17
+ this->Map_.emplace(
+ std::piecewise_construct, std::forward_as_tuple(name, scope),
+ std::forward_as_tuple(ShortDescription, FullDescription, chain));
+ }
+}
+
+cmPropertyDefinition const* cmPropertyDefinitionMap::GetPropertyDefinition(
+ const std::string& name, cmProperty::ScopeType scope) const
+{
+ auto it = this->Map_.find(key_type(name, scope));
+ if (it != this->Map_.end()) {
+ return &it->second;
+ }
+
+ return nullptr;
+}
diff --git a/Source/cmPropertyDefinition.h b/Source/cmPropertyDefinition.h
index d2e4467..f83bc4f 100644
--- a/Source/cmPropertyDefinition.h
+++ b/Source/cmPropertyDefinition.h
@@ -5,7 +5,9 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <map>
#include <string>
+#include <utility>
#include "cmProperty.h"
@@ -13,25 +15,19 @@
* \brief Property meta-information
*
* This class contains the following meta-information about property:
- * - Name;
* - Various documentation strings;
- * - The scope of the property;
* - If the property is chained.
*/
class cmPropertyDefinition
{
public:
/// Constructor
- cmPropertyDefinition(std::string name, cmProperty::ScopeType scope,
- std::string ShortDescription,
- std::string FullDescription, bool chained = false);
+ cmPropertyDefinition(std::string shortDescription,
+ std::string fullDescription, bool chained);
/// Is the property chained?
bool IsChained() const { return this->Chained; }
- /// Get the scope
- cmProperty::ScopeType GetScope() const { return this->Scope; }
-
/// Get the documentation (short version)
const std::string& GetShortDescription() const
{
@@ -44,12 +40,30 @@ public:
return this->FullDescription;
}
-protected:
- std::string Name;
+private:
std::string ShortDescription;
std::string FullDescription;
- cmProperty::ScopeType Scope;
bool Chained;
};
+/** \class cmPropertyDefinitionMap
+ * \brief Map property name and scope to their definition
+ */
+class cmPropertyDefinitionMap
+{
+public:
+ // define the property
+ void DefineProperty(const std::string& name, cmProperty::ScopeType scope,
+ const std::string& ShortDescription,
+ const std::string& FullDescription, bool chain);
+
+ // get the property definition if present, otherwise nullptr
+ cmPropertyDefinition const* GetPropertyDefinition(
+ const std::string& name, cmProperty::ScopeType scope) const;
+
+private:
+ using key_type = std::pair<std::string, cmProperty::ScopeType>;
+ std::map<key_type, cmPropertyDefinition> Map_;
+};
+
#endif
diff --git a/Source/cmPropertyDefinitionMap.cxx b/Source/cmPropertyDefinitionMap.cxx
deleted file mode 100644
index 614d5a4..0000000
--- a/Source/cmPropertyDefinitionMap.cxx
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmPropertyDefinitionMap.h"
-
-#include <tuple>
-#include <utility>
-
-void cmPropertyDefinitionMap::DefineProperty(
- const std::string& name, cmProperty::ScopeType scope,
- const std::string& ShortDescription, const std::string& FullDescription,
- bool chain)
-{
- auto it = this->find(name);
- if (it == this->end()) {
- // try_emplace() since C++17
- this->emplace(std::piecewise_construct, std::forward_as_tuple(name),
- std::forward_as_tuple(name, scope, ShortDescription,
- FullDescription, chain));
- }
-}
-
-bool cmPropertyDefinitionMap::IsPropertyDefined(const std::string& name) const
-{
- return this->find(name) != this->end();
-}
-
-bool cmPropertyDefinitionMap::IsPropertyChained(const std::string& name) const
-{
- auto it = this->find(name);
- if (it == this->end()) {
- return false;
- }
-
- return it->second.IsChained();
-}
diff --git a/Source/cmPropertyDefinitionMap.h b/Source/cmPropertyDefinitionMap.h
deleted file mode 100644
index 2ae6efb..0000000
--- a/Source/cmPropertyDefinitionMap.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmPropertyDefinitionMap_h
-#define cmPropertyDefinitionMap_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <map>
-#include <string>
-
-#include "cmProperty.h"
-#include "cmPropertyDefinition.h"
-
-class cmPropertyDefinitionMap
- : public std::map<std::string, cmPropertyDefinition>
-{
-public:
- // define the property
- void DefineProperty(const std::string& name, cmProperty::ScopeType scope,
- const std::string& ShortDescription,
- const std::string& FullDescription, bool chain);
-
- // has a named property been defined
- bool IsPropertyDefined(const std::string& name) const;
-
- // is a named property set to chain
- bool IsPropertyChained(const std::string& name) const;
-};
-
-#endif
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index 4dbbbd7..07cb7c9 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -43,7 +43,9 @@ bool HandleSourceMode(cmExecutionStatus& status,
const std::set<std::string>& names,
const std::string& propertyName,
const std::string& propertyValue, bool appendAsString,
- bool appendMode, bool remove);
+ bool appendMode, bool remove,
+ const std::vector<cmMakefile*>& directory_makefiles,
+ bool source_file_paths_should_be_absolute);
bool HandleSource(cmSourceFile* sf, const std::string& propertyName,
const std::string& propertyValue, bool appendAsString,
bool appendMode, bool remove);
@@ -74,6 +76,131 @@ bool HandleInstall(cmInstalledFile* file, cmMakefile& makefile,
bool appendMode, bool remove);
}
+namespace SetPropertyCommand {
+bool HandleSourceFileDirectoryScopes(
+ cmExecutionStatus& status, std::vector<std::string>& source_file_directories,
+ std::vector<std::string>& source_file_target_directories,
+ std::vector<cmMakefile*>& directory_makefiles)
+{
+ cmMakefile* current_dir_mf = &status.GetMakefile();
+ if (!source_file_directories.empty()) {
+ for (const std::string& dir_path : source_file_directories) {
+ const std::string absolute_dir_path = cmSystemTools::CollapseFullPath(
+ dir_path, current_dir_mf->GetCurrentSourceDirectory());
+ cmMakefile* dir_mf =
+ status.GetMakefile().GetGlobalGenerator()->FindMakefile(
+ absolute_dir_path);
+ if (!dir_mf) {
+ status.SetError(cmStrCat("given non-existent DIRECTORY ", dir_path));
+ return false;
+ }
+ directory_makefiles.push_back(dir_mf);
+ }
+ } else if (!source_file_target_directories.empty()) {
+ for (const std::string& target_name : source_file_target_directories) {
+ cmTarget* target = current_dir_mf->FindTargetToUse(target_name);
+ if (!target) {
+ status.SetError(cmStrCat(
+ "given non-existent target for DIRECTORY_TARGET ", target_name));
+ return false;
+ }
+ cmProp target_source_dir = target->GetProperty("SOURCE_DIR");
+ cmMakefile* target_dir_mf =
+ status.GetMakefile().GetGlobalGenerator()->FindMakefile(
+ *target_source_dir);
+ directory_makefiles.push_back(target_dir_mf);
+ }
+ } else {
+ directory_makefiles.push_back(current_dir_mf);
+ }
+ return true;
+}
+
+bool HandleSourceFileDirectoryScopeValidation(
+ cmExecutionStatus& status, bool source_file_directory_option_enabled,
+ bool source_file_target_option_enabled,
+ std::vector<std::string>& source_file_directories,
+ std::vector<std::string>& source_file_target_directories)
+{
+ // Validate source file directory scopes.
+ if (source_file_directory_option_enabled &&
+ source_file_directories.empty()) {
+ std::string errors = "called with incorrect number of arguments "
+ "no value provided to the DIRECTORY option";
+ status.SetError(errors);
+ return false;
+ }
+ if (source_file_target_option_enabled &&
+ source_file_target_directories.empty()) {
+ std::string errors = "called with incorrect number of arguments "
+ "no value provided to the TARGET_DIRECTORY option";
+ status.SetError(errors);
+ return false;
+ }
+ return true;
+}
+
+bool HandleAndValidateSourceFileDirectortoryScopes(
+ cmExecutionStatus& status, bool source_file_directory_option_enabled,
+ bool source_file_target_option_enabled,
+ std::vector<std::string>& source_file_directories,
+ std::vector<std::string>& source_file_target_directories,
+ std::vector<cmMakefile*>& source_file_directory_makefiles)
+{
+ bool scope_options_valid =
+ SetPropertyCommand::HandleSourceFileDirectoryScopeValidation(
+ status, source_file_directory_option_enabled,
+ source_file_target_option_enabled, source_file_directories,
+ source_file_target_directories);
+ if (!scope_options_valid) {
+ return false;
+ }
+
+ scope_options_valid = SetPropertyCommand::HandleSourceFileDirectoryScopes(
+ status, source_file_directories, source_file_target_directories,
+ source_file_directory_makefiles);
+ return scope_options_valid;
+}
+
+std::string MakeSourceFilePathAbsoluteIfNeeded(
+ cmExecutionStatus& status, const std::string& source_file_path,
+ const bool needed)
+{
+ if (!needed) {
+ return source_file_path;
+ }
+ const std::string absolute_file_path = cmSystemTools::CollapseFullPath(
+ source_file_path, status.GetMakefile().GetCurrentSourceDirectory());
+ return absolute_file_path;
+}
+
+void MakeSourceFilePathsAbsoluteIfNeeded(
+ cmExecutionStatus& status,
+ std::vector<std::string>& source_files_absolute_paths,
+ std::vector<std::string>::const_iterator files_it_begin,
+ std::vector<std::string>::const_iterator files_it_end, const bool needed)
+{
+
+ // Make the file paths absolute, so that relative source file paths are
+ // picked up relative to the command calling site, regardless of the
+ // directory scope.
+ std::vector<std::string>::difference_type num_files =
+ files_it_end - files_it_begin;
+ source_files_absolute_paths.reserve(num_files);
+
+ if (!needed) {
+ source_files_absolute_paths.assign(files_it_begin, files_it_end);
+ return;
+ }
+
+ for (; files_it_begin != files_it_end; ++files_it_begin) {
+ const std::string absolute_file_path =
+ MakeSourceFilePathAbsoluteIfNeeded(status, *files_it_begin, true);
+ source_files_absolute_paths.push_back(absolute_file_path);
+ }
+}
+}
+
bool cmSetPropertyCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -114,13 +241,20 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args,
std::string propertyName;
std::string propertyValue;
+ std::vector<std::string> source_file_directories;
+ std::vector<std::string> source_file_target_directories;
+ bool source_file_directory_option_enabled = false;
+ bool source_file_target_option_enabled = false;
+
// Parse the rest of the arguments up to the values.
enum Doing
{
DoingNone,
DoingNames,
DoingProperty,
- DoingValues
+ DoingValues,
+ DoingSourceDirectory,
+ DoingSourceTargetDirectory
};
Doing doing = DoingNames;
const char* sep = "";
@@ -137,8 +271,20 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args,
appendMode = true;
remove = false;
appendAsString = true;
+ } else if (doing == DoingNames && scope == cmProperty::SOURCE_FILE &&
+ arg == "DIRECTORY") {
+ doing = DoingSourceDirectory;
+ source_file_directory_option_enabled = true;
+ } else if (doing == DoingNames && scope == cmProperty::SOURCE_FILE &&
+ arg == "TARGET_DIRECTORY") {
+ doing = DoingSourceTargetDirectory;
+ source_file_target_option_enabled = true;
} else if (doing == DoingNames) {
names.insert(arg);
+ } else if (doing == DoingSourceDirectory) {
+ source_file_directories.push_back(arg);
+ } else if (doing == DoingSourceTargetDirectory) {
+ source_file_target_directories.push_back(arg);
} else if (doing == DoingProperty) {
propertyName = arg;
doing = DoingValues;
@@ -159,6 +305,18 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args,
return false;
}
+ std::vector<cmMakefile*> source_file_directory_makefiles;
+ bool file_scopes_handled =
+ SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes(
+ status, source_file_directory_option_enabled,
+ source_file_target_option_enabled, source_file_directories,
+ source_file_target_directories, source_file_directory_makefiles);
+ if (!file_scopes_handled) {
+ return false;
+ }
+ bool source_file_paths_should_be_absolute =
+ source_file_directory_option_enabled || source_file_target_option_enabled;
+
// Dispatch property setting.
switch (scope) {
case cmProperty::GLOBAL:
@@ -172,7 +330,9 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args,
appendAsString, appendMode, remove);
case cmProperty::SOURCE_FILE:
return HandleSourceMode(status, names, propertyName, propertyValue,
- appendAsString, appendMode, remove);
+ appendAsString, appendMode, remove,
+ source_file_directory_makefiles,
+ source_file_paths_should_be_absolute);
case cmProperty::TEST:
return HandleTestMode(status, names, propertyName, propertyValue,
appendAsString, appendMode, remove);
@@ -315,21 +475,32 @@ bool HandleSourceMode(cmExecutionStatus& status,
const std::set<std::string>& names,
const std::string& propertyName,
const std::string& propertyValue, bool appendAsString,
- bool appendMode, bool remove)
+ bool appendMode, bool remove,
+ const std::vector<cmMakefile*>& directory_makefiles,
+ const bool source_file_paths_should_be_absolute)
{
- for (std::string const& name : names) {
- // Get the source file.
- if (cmSourceFile* sf = status.GetMakefile().GetOrCreateSource(name)) {
- if (!HandleSource(sf, propertyName, propertyValue, appendAsString,
- appendMode, remove)) {
+ std::vector<std::string> files_absolute;
+ std::vector<std::string> unique_files(names.begin(), names.end());
+ SetPropertyCommand::MakeSourceFilePathsAbsoluteIfNeeded(
+ status, files_absolute, unique_files.begin(), unique_files.end(),
+ source_file_paths_should_be_absolute);
+
+ for (const auto mf : directory_makefiles) {
+ for (std::string const& name : files_absolute) {
+ // Get the source file.
+ if (cmSourceFile* sf = mf->GetOrCreateSource(name)) {
+ if (!HandleSource(sf, propertyName, propertyValue, appendAsString,
+ appendMode, remove)) {
+ return false;
+ }
+ } else {
+ status.SetError(cmStrCat(
+ "given SOURCE name that could not be found or created: ", name));
return false;
}
- } else {
- status.SetError(cmStrCat(
- "given SOURCE name that could not be found or created: ", name));
- return false;
}
}
+
return true;
}
diff --git a/Source/cmSetPropertyCommand.h b/Source/cmSetPropertyCommand.h
index ec36f84..af566a3 100644
--- a/Source/cmSetPropertyCommand.h
+++ b/Source/cmSetPropertyCommand.h
@@ -8,9 +8,38 @@
#include <string>
#include <vector>
+class cmMakefile;
class cmExecutionStatus;
bool cmSetPropertyCommand(std::vector<std::string> const& args,
cmExecutionStatus& status);
+namespace SetPropertyCommand {
+bool HandleSourceFileDirectoryScopes(
+ cmExecutionStatus& status, std::vector<std::string>& source_file_directories,
+ std::vector<std::string>& source_file_target_directories,
+ std::vector<cmMakefile*>& directory_makefiles);
+
+bool HandleSourceFileDirectoryScopeValidation(
+ cmExecutionStatus& status, bool source_file_directory_option_enabled,
+ bool source_file_target_option_enabled,
+ std::vector<std::string>& source_file_directories,
+ std::vector<std::string>& source_file_target_directories);
+
+bool HandleAndValidateSourceFileDirectortoryScopes(
+ cmExecutionStatus& status, bool source_directories_option_encountered,
+ bool source_target_directories_option_encountered,
+ std::vector<std::string>& source_directories,
+ std::vector<std::string>& source_target_directories,
+ std::vector<cmMakefile*>& source_file_directory_makefiles);
+
+std::string MakeSourceFilePathAbsoluteIfNeeded(
+ cmExecutionStatus& status, const std::string& source_file_path, bool needed);
+void MakeSourceFilePathsAbsoluteIfNeeded(
+ cmExecutionStatus& status,
+ std::vector<std::string>& source_files_absolute_paths,
+ std::vector<std::string>::const_iterator files_it_begin,
+ std::vector<std::string>::const_iterator files_it_end, bool needed);
+}
+
#endif
diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx
index 7a53a1d..3135a06 100644
--- a/Source/cmSetSourceFilesPropertiesCommand.cxx
+++ b/Source/cmSetSourceFilesPropertiesCommand.cxx
@@ -10,9 +10,16 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmSetPropertyCommand.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
+static bool RunCommandForScope(
+ cmMakefile* mf, std::vector<std::string>::const_iterator file_begin,
+ std::vector<std::string>::const_iterator file_end,
+ std::vector<std::string>::const_iterator prop_begin,
+ std::vector<std::string>::const_iterator prop_end, std::string& errors);
+
bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -23,16 +30,86 @@ bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args,
// break the arguments into source file names and properties
// old style allows for specifier before PROPERTIES keyword
- static const cm::string_view propNames[] = {
- "ABSTRACT", "GENERATED", "WRAP_EXCLUDE",
- "COMPILE_FLAGS", "OBJECT_DEPENDS", "PROPERTIES"
+ static const cm::string_view prop_names[] = {
+ "ABSTRACT", "GENERATED", "WRAP_EXCLUDE", "COMPILE_FLAGS",
+ "OBJECT_DEPENDS", "PROPERTIES", "DIRECTORY", "TARGET_DIRECTORY"
};
- auto propsBegin = std::find_first_of(
- args.begin(), args.end(), std::begin(propNames), std::end(propNames));
+ auto isNotAPropertyKeyword =
+ [](const std::vector<std::string>::const_iterator& arg_it) {
+ return std::all_of(
+ std::begin(prop_names), std::end(prop_names),
+ [&arg_it](cm::string_view prop_name) { return *arg_it != prop_name; });
+ };
+
+ auto options_begin = std::find_first_of(
+ args.begin(), args.end(), std::begin(prop_names), std::end(prop_names));
+ auto options_it = options_begin;
+
+ // Handle directory options.
+ std::vector<std::string> source_file_directories;
+ std::vector<std::string> source_file_target_directories;
+ bool source_file_directory_option_enabled = false;
+ bool source_file_target_option_enabled = false;
+ std::vector<cmMakefile*> source_file_directory_makefiles;
+
+ if (options_it != args.end() && *options_it == "DIRECTORY") {
+ source_file_directory_option_enabled = true;
+ ++options_it;
+ while (options_it != args.end() && isNotAPropertyKeyword(options_it)) {
+ source_file_directories.push_back(*options_it);
+ ++options_it;
+ }
+ } else if (options_it != args.end() && *options_it == "TARGET_DIRECTORY") {
+ source_file_target_option_enabled = true;
+ ++options_it;
+ while (options_it != args.end() && isNotAPropertyKeyword(options_it)) {
+ source_file_target_directories.push_back(*options_it);
+ ++options_it;
+ }
+ }
+ const auto props_begin = options_it;
+
+ bool file_scopes_handled =
+ SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes(
+ status, source_file_directory_option_enabled,
+ source_file_target_option_enabled, source_file_directories,
+ source_file_target_directories, source_file_directory_makefiles);
+ if (!file_scopes_handled) {
+ return false;
+ }
+
+ std::vector<std::string> files;
+ bool source_file_paths_should_be_absolute =
+ source_file_directory_option_enabled || source_file_target_option_enabled;
+ SetPropertyCommand::MakeSourceFilePathsAbsoluteIfNeeded(
+ status, files, args.begin(), options_begin,
+ source_file_paths_should_be_absolute);
+
+ // Now call the worker function for each directory scope represented by a
+ // cmMakefile instance.
+ std::string errors;
+ for (const auto mf : source_file_directory_makefiles) {
+ bool ret = RunCommandForScope(mf, files.begin(), files.end(), props_begin,
+ args.end(), errors);
+ if (!ret) {
+ status.SetError(errors);
+ return ret;
+ }
+ }
+
+ return true;
+}
+
+static bool RunCommandForScope(
+ cmMakefile* mf, std::vector<std::string>::const_iterator file_begin,
+ std::vector<std::string>::const_iterator file_end,
+ std::vector<std::string>::const_iterator prop_begin,
+ std::vector<std::string>::const_iterator prop_end, std::string& errors)
+{
std::vector<std::string> propertyPairs;
// build the property pairs
- for (auto j = propsBegin; j != args.end(); ++j) {
+ for (auto j = prop_begin; j != prop_end; ++j) {
// consume old style options
if (*j == "ABSTRACT" || *j == "GENERATED" || *j == "WRAP_EXCLUDE") {
propertyPairs.emplace_back(*j);
@@ -40,26 +117,26 @@ bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args,
} else if (*j == "COMPILE_FLAGS") {
propertyPairs.emplace_back("COMPILE_FLAGS");
++j;
- if (j == args.end()) {
- status.SetError("called with incorrect number of arguments "
- "COMPILE_FLAGS with no flags");
+ if (j == prop_end) {
+ errors = "called with incorrect number of arguments "
+ "COMPILE_FLAGS with no flags";
return false;
}
propertyPairs.push_back(*j);
} else if (*j == "OBJECT_DEPENDS") {
propertyPairs.emplace_back("OBJECT_DEPENDS");
++j;
- if (j == args.end()) {
- status.SetError("called with incorrect number of arguments "
- "OBJECT_DEPENDS with no dependencies");
+ if (j == prop_end) {
+ errors = "called with incorrect number of arguments "
+ "OBJECT_DEPENDS with no dependencies";
return false;
}
propertyPairs.push_back(*j);
} else if (*j == "PROPERTIES") {
// PROPERTIES is followed by new style prop value pairs
- cmStringRange newStyleProps{ j + 1, args.end() };
+ cmStringRange newStyleProps{ j + 1, prop_end };
if (newStyleProps.size() % 2 != 0) {
- status.SetError("called with incorrect number of arguments.");
+ errors = "called with incorrect number of arguments.";
return false;
}
// set newStyleProps as is.
@@ -67,16 +144,16 @@ bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args,
// break out of the loop.
break;
} else {
- status.SetError("called with illegal arguments, maybe missing a "
- "PROPERTIES specifier?");
+ errors = "called with illegal arguments, maybe missing a "
+ "PROPERTIES specifier?";
return false;
}
}
// loop over all the files
- for (const std::string& sfname : cmStringRange{ args.begin(), propsBegin }) {
+ for (const std::string& sfname : cmStringRange{ file_begin, file_end }) {
// get the source file
- if (cmSourceFile* sf = status.GetMakefile().GetOrCreateSource(sfname)) {
+ if (cmSourceFile* sf = mf->GetOrCreateSource(sfname)) {
// loop through the props and set them
for (auto k = propertyPairs.begin(); k != propertyPairs.end(); k += 2) {
sf->SetProperty(*k, (k + 1)->c_str());
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index df013f4..18d8537 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -265,7 +265,7 @@ void cmState::RemoveCacheEntryProperty(std::string const& key,
cmStateSnapshot cmState::Reset()
{
this->GlobalProperties.Clear();
- this->PropertyDefinitions.clear();
+ this->PropertyDefinitions = {};
this->GlobVerificationManager->Reset();
cmStateDetail::PositionType pos = this->SnapshotData.Truncate();
@@ -331,39 +331,23 @@ void cmState::DefineProperty(const std::string& name,
const std::string& ShortDescription,
const std::string& FullDescription, bool chained)
{
- this->PropertyDefinitions[scope].DefineProperty(
- name, scope, ShortDescription, FullDescription, chained);
+ this->PropertyDefinitions.DefineProperty(name, scope, ShortDescription,
+ FullDescription, chained);
}
cmPropertyDefinition const* cmState::GetPropertyDefinition(
const std::string& name, cmProperty::ScopeType scope) const
{
- if (this->IsPropertyDefined(name, scope)) {
- cmPropertyDefinitionMap const& defs =
- this->PropertyDefinitions.find(scope)->second;
- return &defs.find(name)->second;
- }
- return nullptr;
-}
-
-bool cmState::IsPropertyDefined(const std::string& name,
- cmProperty::ScopeType scope) const
-{
- auto it = this->PropertyDefinitions.find(scope);
- if (it == this->PropertyDefinitions.end()) {
- return false;
- }
- return it->second.IsPropertyDefined(name);
+ return this->PropertyDefinitions.GetPropertyDefinition(name, scope);
}
bool cmState::IsPropertyChained(const std::string& name,
cmProperty::ScopeType scope) const
{
- auto it = this->PropertyDefinitions.find(scope);
- if (it == this->PropertyDefinitions.end()) {
- return false;
+ if (auto def = this->GetPropertyDefinition(name, scope)) {
+ return def->IsChained();
}
- return it->second.IsPropertyChained(name);
+ return false;
}
void cmState::SetLanguageEnabled(std::string const& l)
diff --git a/Source/cmState.h b/Source/cmState.h
index e966935..f2bd32a 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -17,7 +17,7 @@
#include "cmListFileCache.h"
#include "cmPolicies.h"
#include "cmProperty.h"
-#include "cmPropertyDefinitionMap.h"
+#include "cmPropertyDefinition.h"
#include "cmPropertyMap.h"
#include "cmStatePrivate.h"
#include "cmStateTypes.h"
@@ -25,7 +25,6 @@
class cmCacheManager;
class cmCommand;
class cmGlobVerificationManager;
-class cmPropertyDefinition;
class cmStateSnapshot;
class cmMessenger;
class cmExecutionStatus;
@@ -131,9 +130,6 @@ public:
cmPropertyDefinition const* GetPropertyDefinition(
const std::string& name, cmProperty::ScopeType scope) const;
- // Is a property defined?
- bool IsPropertyDefined(const std::string& name,
- cmProperty::ScopeType scope) const;
bool IsPropertyChained(const std::string& name,
cmProperty::ScopeType scope) const;
@@ -225,7 +221,7 @@ private:
const std::string& variable,
cmListFileBacktrace const& bt);
- std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> PropertyDefinitions;
+ cmPropertyDefinitionMap PropertyDefinitions;
std::vector<std::string> EnabledLanguages;
std::map<std::string, Command> BuiltinCommands;
std::map<std::string, Command> ScriptedCommands;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index d43fbe5..e165f4c 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -215,7 +215,7 @@ public:
};
cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
- Visibility vis, cmMakefile* mf, bool perConfig)
+ Visibility vis, cmMakefile* mf, PerConfig perConfig)
: impl(cm::make_unique<cmTargetInternals>())
{
assert(mf);
@@ -231,7 +231,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
(vis == VisibilityImported || vis == VisibilityImportedGlobally);
impl->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
impl->BuildInterfaceIncludesAppended = false;
- impl->PerConfig = perConfig;
+ impl->PerConfig = (perConfig == PerConfig::Yes);
// Check whether this is a DLL platform.
impl->IsDLLPlatform =
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 8fecd41..6bd47f7 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -45,8 +45,14 @@ public:
VisibilityImportedGlobally
};
+ enum class PerConfig
+ {
+ Yes,
+ No
+ };
+
cmTarget(std::string const& name, cmStateEnums::TargetType type,
- Visibility vis, cmMakefile* mf, bool perConfig);
+ Visibility vis, cmMakefile* mf, PerConfig perConfig);
cmTarget(cmTarget const&) = delete;
cmTarget(cmTarget&&) noexcept;
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index 025a7b3..4e41993 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -76,7 +76,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
cmGeneratorExpression ge(this->Test->GetBacktrace());
// Start the test command.
- os << indent << "add_test(" << this->Test->GetName() << " ";
+ os << indent << "add_test(\"" << this->Test->GetName() << "\" ";
// Evaluate command line arguments
std::vector<std::string> argv =
@@ -126,8 +126,8 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
os << ")\n";
// Output properties for the test.
- os << indent << "set_tests_properties(" << this->Test->GetName()
- << " PROPERTIES ";
+ os << indent << "set_tests_properties(\"" << this->Test->GetName()
+ << "\" PROPERTIES ";
for (auto const& i : this->Test->GetProperties().GetList()) {
os << " " << i.first << " "
<< cmOutputConverter::EscapeForCMake(
@@ -139,7 +139,8 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, Indent indent)
{
- os << indent << "add_test(" << this->Test->GetName() << " NOT_AVAILABLE)\n";
+ os << indent << "add_test(\"" << this->Test->GetName()
+ << "\" NOT_AVAILABLE)\n";
}
bool cmTestGenerator::NeedsScriptNoConfig() const
@@ -159,9 +160,8 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent)
std::string exe = command[0];
cmSystemTools::ConvertToUnixSlashes(exe);
- fout << indent;
- fout << "add_test(";
- fout << this->Test->GetName() << " \"" << exe << "\"";
+ fout << indent << "add_test(\"" << this->Test->GetName() << "\" \"" << exe
+ << "\"";
for (std::string const& arg : cmMakeRange(command).advance(1)) {
// Just double-quote all arguments so they are re-parsed
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 93c09fe..97f7093 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -248,6 +248,7 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
this->InSourceBuild = (this->Makefile->GetCurrentSourceDirectory() ==
this->Makefile->GetCurrentBinaryDirectory());
+ this->ClassifyAllConfigSources();
}
cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
@@ -921,13 +922,11 @@ void cmVisualStudio10TargetGenerator::WriteDotNetDocumentationFile(Elem& e0)
void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
{
- std::vector<cmSourceFile const*> resxObjs;
- this->GeneratorTarget->GetResxSources(resxObjs, "");
- if (!resxObjs.empty()) {
+ if (!this->ResxObjs.empty()) {
Elem e1(e0, "ItemGroup");
std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
ConvertToWindowsSlash(srcDir);
- for (cmSourceFile const* oi : resxObjs) {
+ for (cmSourceFile const* oi : this->ResxObjs) {
std::string obj = oi->GetFullPath();
ConvertToWindowsSlash(obj);
bool useRelativePath = false;
@@ -1016,11 +1015,9 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0)
{
- std::vector<cmSourceFile const*> xamlObjs;
- this->GeneratorTarget->GetXamlSources(xamlObjs, "");
- if (!xamlObjs.empty()) {
+ if (!this->XamlObjs.empty()) {
Elem e1(e0, "ItemGroup");
- for (cmSourceFile const* oi : xamlObjs) {
+ for (cmSourceFile const* oi : this->XamlObjs) {
std::string obj = oi->GetFullPath();
std::string xamlType;
cmProp xamlTypeProperty = oi->GetProperty("VS_XAML_TYPE");
@@ -1329,21 +1326,27 @@ void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
void cmVisualStudio10TargetGenerator::WriteCustomCommands(Elem& e0)
{
this->CSharpCustomCommandNames.clear();
- std::vector<cmSourceFile const*> customCommands;
- this->GeneratorTarget->GetCustomCommands(customCommands, "");
- for (cmSourceFile const* si : customCommands) {
- this->WriteCustomCommand(e0, si);
+
+ cmSourceFile const* srcCMakeLists =
+ this->LocalGenerator->CreateVCProjBuildRule();
+
+ for (cmGeneratorTarget::AllConfigSource const& si :
+ this->GeneratorTarget->GetAllConfigSources()) {
+ if (si.Source == srcCMakeLists) {
+ // Skip explicit reference to CMakeLists.txt source.
+ continue;
+ }
+ this->WriteCustomCommand(e0, si.Source);
}
// Add CMakeLists.txt file with rule to re-run CMake for user convenience.
if (this->GeneratorTarget->GetType() != cmStateEnums::GLOBAL_TARGET &&
this->GeneratorTarget->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
- if (cmSourceFile const* sf =
- this->LocalGenerator->CreateVCProjBuildRule()) {
+ if (srcCMakeLists) {
// Write directly rather than through WriteCustomCommand because
// we do not want the de-duplication and it has no dependencies.
- if (cmCustomCommand const* command = sf->GetCustomCommand()) {
- this->WriteCustomRule(e0, sf, *command);
+ if (cmCustomCommand const* command = srcCMakeLists->GetCustomCommand()) {
+ this->WriteCustomRule(e0, srcCMakeLists, *command);
}
}
}
@@ -1624,11 +1627,9 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
}
}
- std::vector<cmSourceFile const*> resxObjs;
- this->GeneratorTarget->GetResxSources(resxObjs, "");
- if (!resxObjs.empty()) {
+ if (!this->ResxObjs.empty()) {
Elem e1(e0, "ItemGroup");
- for (cmSourceFile const* oi : resxObjs) {
+ for (cmSourceFile const* oi : this->ResxObjs) {
std::string obj = oi->GetFullPath();
ConvertToWindowsSlash(obj);
Elem e2(e1, "EmbeddedResource");
@@ -1656,7 +1657,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
}
}
- if (!resxObjs.empty() || !this->AddedFiles.empty()) {
+ if (!this->ResxObjs.empty() || !this->AddedFiles.empty()) {
std::string guidName = "SG_Filter_Resource Files";
std::string guid = this->GlobalGenerator->GetGUID(guidName);
Elem e2(e1, "Filter");
@@ -2209,10 +2210,10 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
}
} break;
case cmGeneratorTarget::SourceKindResx:
- // Handled elsewhere.
+ this->ResxObjs.push_back(si.Source);
break;
case cmGeneratorTarget::SourceKindXaml:
- // Handled elsewhere.
+ this->XamlObjs.push_back(si.Source);
break;
}
@@ -2317,21 +2318,13 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
cmGeneratorExpression::Find(*cincludes) != std::string::npos;
includes += *cincludes;
}
- std::string lang =
- this->GlobalGenerator->GetLanguageFromExtension(sf.GetExtension().c_str());
- std::string sourceLang = this->LocalGenerator->GetSourceFileLanguage(sf);
- const std::string& linkLanguage =
- this->GeneratorTarget->GetLinkerLanguage("");
- bool needForceLang = false;
- // source file does not match its extension language
- if (lang != sourceLang) {
- needForceLang = true;
- lang = sourceLang;
- }
- // if the source file does not match the linker language
- // then force c or c++
+
+ // Force language if the file extension does not match.
+ std::string lang = this->LocalGenerator->GetSourceFileLanguage(sf);
const char* compileAs = 0;
- if (needForceLang || (linkLanguage != lang)) {
+ if (lang !=
+ this->GlobalGenerator->GetLanguageFromExtension(
+ sf.GetExtension().c_str())) {
if (lang == "CXX") {
// force a C++ file type
compileAs = "CompileAsCpp";
@@ -2340,6 +2333,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
compileAs = "CompileAsC";
}
}
+
bool noWinRT = this->TargetCompileAsWinRT && lang == "C";
// for the first time we need a new line if there is something
// produced here.
@@ -2736,13 +2730,6 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
langForClCompile, configName);
}
- // set the correct language
- if (linkLanguage == "C") {
- clOptions.AddFlag("CompileAs", "CompileAsC");
- }
- if (linkLanguage == "CXX") {
- clOptions.AddFlag("CompileAs", "CompileAsCpp");
- }
// Put the IPO enabled configurations into a set.
if (this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName)) {
@@ -3493,12 +3480,12 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
// its location as the root source directory.
std::string rootDir = this->LocalGenerator->GetCurrentSourceDirectory();
{
- std::vector<cmSourceFile const*> extraSources;
- this->GeneratorTarget->GetExtraSources(extraSources, "");
- for (cmSourceFile const* si : extraSources) {
- if ("androidmanifest.xml" ==
- cmSystemTools::LowerCase(si->GetLocation().GetName())) {
- rootDir = si->GetLocation().GetDirectory();
+ for (cmGeneratorTarget::AllConfigSource const& source :
+ this->GeneratorTarget->GetAllConfigSources()) {
+ if (source.Kind == cmGeneratorTarget::SourceKindExtra &&
+ "androidmanifest.xml" ==
+ cmSystemTools::LowerCase(source.Source->GetLocation().GetName())) {
+ rootDir = source.Source->GetLocation().GetDirectory();
break;
}
}
@@ -4133,7 +4120,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
}
// Don't reference targets that don't produce any output.
- if (dt->GetManagedType("") == cmGeneratorTarget::ManagedType::Undefined) {
+ if (dt->GetManagedType(this->Configurations[0]) ==
+ cmGeneratorTarget::ManagedType::Undefined) {
e2.Element("ReferenceOutputAssembly", "false");
e2.Element("CopyToOutputDirectory", "Never");
}
@@ -4234,12 +4222,13 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile(
this->GlobalGenerator->TargetsWindowsPhone()) &&
(cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType())) {
std::string pfxFile;
- std::vector<cmSourceFile const*> certificates;
- this->GeneratorTarget->GetCertificates(certificates, "");
- for (cmSourceFile const* si : certificates) {
- pfxFile = this->ConvertPath(si->GetFullPath(), false);
- ConvertToWindowsSlash(pfxFile);
- break;
+ for (cmGeneratorTarget::AllConfigSource const& source :
+ this->GeneratorTarget->GetAllConfigSources()) {
+ if (source.Kind == cmGeneratorTarget::SourceKindCertificate) {
+ pfxFile = this->ConvertPath(source.Source->GetFullPath(), false);
+ ConvertToWindowsSlash(pfxFile);
+ break;
+ }
}
if (this->IsMissingFiles &&
@@ -4285,28 +4274,61 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile(
}
}
+void cmVisualStudio10TargetGenerator::ClassifyAllConfigSources()
+{
+ for (cmGeneratorTarget::AllConfigSource const& source :
+ this->GeneratorTarget->GetAllConfigSources()) {
+ this->ClassifyAllConfigSource(source);
+ }
+}
+
+void cmVisualStudio10TargetGenerator::ClassifyAllConfigSource(
+ cmGeneratorTarget::AllConfigSource const& acs)
+{
+ switch (acs.Kind) {
+ case cmGeneratorTarget::SourceKindResx: {
+ // Build and save the name of the corresponding .h file
+ // This relationship will be used later when building the project files.
+ // Both names would have been auto generated from Visual Studio
+ // where the user supplied the file name and Visual Studio
+ // appended the suffix.
+ std::string resx = acs.Source->ResolveFullPath();
+ std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h";
+ this->ExpectedResxHeaders.insert(hFileName);
+ } break;
+ case cmGeneratorTarget::SourceKindXaml: {
+ // Build and save the name of the corresponding .h and .cpp file
+ // This relationship will be used later when building the project files.
+ // Both names would have been auto generated from Visual Studio
+ // where the user supplied the file name and Visual Studio
+ // appended the suffix.
+ std::string xaml = acs.Source->ResolveFullPath();
+ std::string hFileName = xaml + ".h";
+ std::string cppFileName = xaml + ".cpp";
+ this->ExpectedXamlHeaders.insert(hFileName);
+ this->ExpectedXamlSources.insert(cppFileName);
+ } break;
+ default:
+ break;
+ }
+}
+
bool cmVisualStudio10TargetGenerator::IsResxHeader(
const std::string& headerFile)
{
- std::set<std::string> expectedResxHeaders;
- this->GeneratorTarget->GetExpectedResxHeaders(expectedResxHeaders, "");
- return expectedResxHeaders.count(headerFile) > 0;
+ return this->ExpectedResxHeaders.count(headerFile) > 0;
}
bool cmVisualStudio10TargetGenerator::IsXamlHeader(
const std::string& headerFile)
{
- std::set<std::string> expectedXamlHeaders;
- this->GeneratorTarget->GetExpectedXamlHeaders(expectedXamlHeaders, "");
- return expectedXamlHeaders.count(headerFile) > 0;
+ return this->ExpectedXamlHeaders.count(headerFile) > 0;
}
bool cmVisualStudio10TargetGenerator::IsXamlSource(
const std::string& sourceFile)
{
- std::set<std::string> expectedXamlSources;
- this->GeneratorTarget->GetExpectedXamlSources(expectedXamlSources, "");
- return expectedXamlSources.count(sourceFile) > 0;
+ return this->ExpectedXamlSources.count(sourceFile) > 0;
}
void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1)
@@ -4387,39 +4409,38 @@ void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles()
// For Windows and Windows Phone executables, we will assume that if a
// manifest is not present that we need to add all the necessary files
if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
- std::vector<cmSourceFile const*> manifestSources;
- this->GeneratorTarget->GetAppManifest(manifestSources, "");
- {
- std::string const& v = this->GlobalGenerator->GetSystemVersion();
- if (this->GlobalGenerator->TargetsWindowsPhone()) {
- if (v == "8.0") {
- // Look through the sources for WMAppManifest.xml
- std::vector<cmSourceFile const*> extraSources;
- this->GeneratorTarget->GetExtraSources(extraSources, "");
- bool foundManifest = false;
- for (cmSourceFile const* si : extraSources) {
- // Need to do a lowercase comparison on the filename
- if ("wmappmanifest.xml" ==
- cmSystemTools::LowerCase(si->GetLocation().GetName())) {
- foundManifest = true;
- break;
- }
- }
- if (!foundManifest) {
- this->IsMissingFiles = true;
- }
- } else if (v == "8.1") {
- if (manifestSources.empty()) {
- this->IsMissingFiles = true;
+ std::vector<cmGeneratorTarget::AllConfigSource> manifestSources =
+ this->GeneratorTarget->GetAllConfigSources(
+ cmGeneratorTarget::SourceKindAppManifest);
+ std::string const& v = this->GlobalGenerator->GetSystemVersion();
+ if (this->GlobalGenerator->TargetsWindowsPhone()) {
+ if (v == "8.0") {
+ // Look through the sources for WMAppManifest.xml
+ bool foundManifest = false;
+ for (cmGeneratorTarget::AllConfigSource const& source :
+ this->GeneratorTarget->GetAllConfigSources()) {
+ if (source.Kind == cmGeneratorTarget::SourceKindExtra &&
+ "wmappmanifest.xml" ==
+ cmSystemTools::LowerCase(
+ source.Source->GetLocation().GetName())) {
+ foundManifest = true;
+ break;
}
}
- } else if (this->GlobalGenerator->TargetsWindowsStore()) {
+ if (!foundManifest) {
+ this->IsMissingFiles = true;
+ }
+ } else if (v == "8.1") {
if (manifestSources.empty()) {
- if (v == "8.0") {
- this->IsMissingFiles = true;
- } else if (v == "8.1" || cmHasLiteralPrefix(v, "10.0")) {
- this->IsMissingFiles = true;
- }
+ this->IsMissingFiles = true;
+ }
+ }
+ } else if (this->GlobalGenerator->TargetsWindowsStore()) {
+ if (manifestSources.empty()) {
+ if (v == "8.0") {
+ this->IsMissingFiles = true;
+ } else if (v == "8.1" || cmHasLiteralPrefix(v, "10.0")) {
+ this->IsMissingFiles = true;
}
}
}
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index e3782f4..7c71de3 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -13,10 +13,11 @@
#include <unordered_map>
#include <vector>
+#include "cmGeneratorTarget.h"
+
class cmComputeLinkInformation;
class cmCustomCommand;
class cmGeneratedFileStream;
-class cmGeneratorTarget;
class cmGlobalVisualStudio10Generator;
class cmLocalVisualStudio10Generator;
class cmMakefile;
@@ -238,6 +239,14 @@ private:
using ToolSourceMap = std::map<std::string, ToolSources>;
ToolSourceMap Tools;
+ std::set<std::string> ExpectedResxHeaders;
+ std::set<std::string> ExpectedXamlHeaders;
+ std::set<std::string> ExpectedXamlSources;
+ std::vector<cmSourceFile const*> ResxObjs;
+ std::vector<cmSourceFile const*> XamlObjs;
+ void ClassifyAllConfigSources();
+ void ClassifyAllConfigSource(cmGeneratorTarget::AllConfigSource const& acs);
+
using ConfigToSettings =
std::unordered_map<std::string,
std::unordered_map<std::string, std::string>>;
diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx
index 9ac1457..f4c2f2d 100644
--- a/Source/cmXCodeScheme.cxx
+++ b/Source/cmXCodeScheme.cxx
@@ -396,7 +396,8 @@ void cmXCodeScheme::WriteBuildableReference(cmXMLWriter& xout,
xout.BreakAttributes();
xout.Attribute("BuildableIdentifier", "primary");
xout.Attribute("BlueprintIdentifier", xcObj->GetId());
- xout.Attribute("BuildableName", xcObj->GetTarget()->GetFullName());
+ std::string const noConfig; // FIXME: What config to use here?
+ xout.Attribute("BuildableName", xcObj->GetTarget()->GetFullName(noConfig));
xout.Attribute("BlueprintName", xcObj->GetTarget()->GetName());
xout.Attribute("ReferencedContainer", "container:" + container);
xout.EndElement();
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index d640948..be9158e 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -103,7 +103,7 @@ void Directory::Clear()
namespace KWSYS_NAMESPACE {
-bool Directory::Load(const std::string& name)
+bool Directory::Load(const std::string& name, std::string* errorMessage)
{
this->Clear();
# if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
@@ -146,7 +146,8 @@ bool Directory::Load(const std::string& name)
return _findclose(srchHandle) != -1;
}
-unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name)
+unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
+ std::string* errorMessage)
{
# if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
// Older Visual C++ and Embarcadero compilers.
@@ -192,6 +193,8 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name)
# include <sys/types.h>
# include <dirent.h>
+# include <errno.h>
+# include <string.h>
// PGI with glibc has trouble with dirent and large file support:
// http://www.pgroup.com/userforum/viewtopic.php?
@@ -209,29 +212,46 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name)
namespace KWSYS_NAMESPACE {
-bool Directory::Load(const std::string& name)
+bool Directory::Load(const std::string& name, std::string* errorMessage)
{
this->Clear();
+ errno = 0;
DIR* dir = opendir(name.c_str());
if (!dir) {
+ if (errorMessage != nullptr) {
+ *errorMessage = std::string(strerror(errno));
+ }
return false;
}
+ errno = 0;
for (kwsys_dirent* d = readdir(dir); d; d = readdir(dir)) {
this->Internal->Files.emplace_back(d->d_name);
}
+ if (errno != 0) {
+ if (errorMessage != nullptr) {
+ *errorMessage = std::string(strerror(errno));
+ }
+ return false;
+ }
+
this->Internal->Path = name;
closedir(dir);
return true;
}
-unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name)
+unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
+ std::string* errorMessage)
{
+ errno = 0;
DIR* dir = opendir(name.c_str());
if (!dir) {
+ if (errorMessage != nullptr) {
+ *errorMessage = std::string(strerror(errno));
+ }
return 0;
}
@@ -239,6 +259,13 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name)
for (kwsys_dirent* d = readdir(dir); d; d = readdir(dir)) {
count++;
}
+ if (errno != 0) {
+ if (errorMessage != nullptr) {
+ *errorMessage = std::string(strerror(errno));
+ }
+ return false;
+ }
+
closedir(dir);
return count;
}
diff --git a/Source/kwsys/Directory.hxx.in b/Source/kwsys/Directory.hxx.in
index 9b0f4c3..7bc9db0 100644
--- a/Source/kwsys/Directory.hxx.in
+++ b/Source/kwsys/Directory.hxx.in
@@ -35,7 +35,7 @@ public:
* in that directory. 0 is returned if the directory can not be
* opened, 1 if it is opened.
*/
- bool Load(const std::string&);
+ bool Load(const std::string&, std::string* errorMessage = nullptr);
/**
* Return the number of files in the current directory.
@@ -46,7 +46,8 @@ public:
* Return the number of files in the specified directory.
* A higher performance static method.
*/
- static unsigned long GetNumberOfFilesInDirectory(const std::string&);
+ static unsigned long GetNumberOfFilesInDirectory(
+ const std::string&, std::string* errorMessage = nullptr);
/**
* Return the file at the given index, the indexing is 0 based
diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx
index fad6ee1..5452f73 100644
--- a/Source/kwsys/Glob.cxx
+++ b/Source/kwsys/Glob.cxx
@@ -182,7 +182,15 @@ bool Glob::RecurseDirectory(std::string::size_type start,
const std::string& dir, GlobMessages* messages)
{
kwsys::Directory d;
- if (!d.Load(dir)) {
+ std::string errorMessage;
+ if (!d.Load(dir, &errorMessage)) {
+ if (messages) {
+ if (!errorMessage.empty()) {
+ messages->push_back(Message(Glob::warning,
+ "Error listing directory '" + dir +
+ "'! Reason: '" + errorMessage + "'"));
+ }
+ }
return true;
}
unsigned long cc;
@@ -278,7 +286,9 @@ void Glob::ProcessDirectory(std::string::size_type start,
// std::cout << "ProcessDirectory: " << dir << std::endl;
bool last = (start == this->Internals->Expressions.size() - 1);
if (last && this->Recurse) {
- this->RecurseDirectory(start, dir, messages);
+ if (kwsys::SystemTools::FileIsDirectory(dir)) {
+ this->RecurseDirectory(start, dir, messages);
+ }
return;
}
diff --git a/Source/kwsys/Glob.hxx.in b/Source/kwsys/Glob.hxx.in
index 170766f..b5a34d5 100644
--- a/Source/kwsys/Glob.hxx.in
+++ b/Source/kwsys/Glob.hxx.in
@@ -28,6 +28,7 @@ public:
enum MessageType
{
error,
+ warning,
cyclicRecursion
};
diff --git a/Source/kwsys/testDirectory.cxx b/Source/kwsys/testDirectory.cxx
index b1ab0c8..eb3ca32 100644
--- a/Source/kwsys/testDirectory.cxx
+++ b/Source/kwsys/testDirectory.cxx
@@ -57,7 +57,11 @@ int _doLongPathTest()
Directory testdir;
// Set res to failure if the directory doesn't load
- res += !testdir.Load(testdirpath);
+ std::string errorMessage = "";
+ res += !testdir.Load(testdirpath, &errorMessage);
+ if (errorMessage != "") {
+ std::cerr << "Failed to list directory: " << errorMessage << std::endl;
+ }
// Increment res failure if the directory appears empty
res += testdir.GetNumberOfFiles() == 0;
// Increment res failures if the path has changed from
@@ -73,6 +77,34 @@ int _doLongPathTest()
return res;
}
+int _nonExistentDirectoryTest()
+{
+ using namespace kwsys;
+ int res = 0;
+ std::string testdirpath(TEST_SYSTEMTOOLS_BINARY_DIR
+ "/directory_testing/doesnt_exist/");
+ std::string errorMessage;
+ Directory testdir;
+
+ errorMessage = "foo";
+ // Increment res failure if directory lists
+ res += testdir.Load(testdirpath, &errorMessage);
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ // Increment res failure if errorMessage is unmodified
+ res += (errorMessage == "foo");
+#endif
+
+ errorMessage = "foo";
+ // Increment res failure if directory has files
+ res += (testdir.GetNumberOfFilesInDirectory(testdirpath, &errorMessage) > 0);
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ // Increment res failure if errorMessage is unmodified
+ res += (errorMessage == "foo");
+#endif
+
+ return res;
+}
+
int _copyDirectoryTest()
{
using namespace kwsys;
@@ -106,5 +138,6 @@ int _copyDirectoryTest()
int testDirectory(int, char* [])
{
- return _doLongPathTest() + _copyDirectoryTest();
+ return _doLongPathTest() + _nonExistentDirectoryTest() +
+ _copyDirectoryTest();
}