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/CMakeVersionCompute.cmake7
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.cxx16
-rw-r--r--Source/CPack/cmCPackGenerator.cxx8
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx22
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx22
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx16
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx47
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.h2
-rw-r--r--Source/CTest/cmCTestRunTest.cxx54
-rw-r--r--Source/CTest/cmCTestRunTest.h5
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx2
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx19
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx11
-rw-r--r--Source/CTest/cmCTestTestHandler.h2
-rw-r--r--Source/CTest/cmProcess.cxx18
-rw-r--r--Source/CTest/cmProcess.h2
-rw-r--r--Source/cmAffinity.cxx62
-rw-r--r--Source/cmAffinity.h12
-rw-r--r--Source/cmCTest.h2
-rw-r--r--Source/cmCacheManager.cxx16
-rw-r--r--Source/cmComputeLinkInformation.cxx3
-rw-r--r--Source/cmComputeTargetDepends.cxx6
-rw-r--r--Source/cmDepends.cxx7
-rw-r--r--Source/cmDepends.h6
-rw-r--r--Source/cmExportBuildFileGenerator.cxx4
-rw-r--r--Source/cmFileCommand.cxx146
-rw-r--r--Source/cmFileTimeComparison.h4
-rw-r--r--Source/cmGeneratorTarget.cxx77
-rw-r--r--Source/cmGlobalGenerator.cxx14
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx4
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx38
-rw-r--r--Source/cmInstallCommand.cxx5
-rw-r--r--Source/cmMakefile.cxx12
-rw-r--r--Source/cmOutputConverter.cxx10
-rw-r--r--Source/cmPolicies.h6
-rw-r--r--Source/cmProjectCommand.cxx49
-rw-r--r--Source/cmQtAutoGenerator.cxx29
-rw-r--r--Source/cmTarget.cxx59
-rw-r--r--Source/cmTarget.h3
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx15
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx474
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h4
-rw-r--r--Source/cmWorkingDirectory.cxx16
-rw-r--r--Source/cmWorkingDirectory.h17
-rw-r--r--Source/cmake.cxx11
-rw-r--r--Source/kwsys/CMakeLists.txt4
-rw-r--r--Source/kwsys/SystemInformation.cxx6
-rw-r--r--Source/kwsys/SystemTools.cxx30
-rw-r--r--Source/kwsys/SystemTools.hxx.in1
51 files changed, 825 insertions, 584 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index a0010a2..e547356 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -131,6 +131,8 @@ set(SRCS
LexerParser/cmListFileLexer.c
LexerParser/cmListFileLexer.in.l
+ cmAffinity.cxx
+ cmAffinity.h
cmArchiveWrite.cxx
cmBase32.cxx
cmCacheManager.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 256f75c..a9bf8e6 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 11)
-set(CMake_VERSION_PATCH 20180304)
+set(CMake_VERSION_PATCH 20180312)
#set(CMake_VERSION_RC 1)
diff --git a/Source/CMakeVersionCompute.cmake b/Source/CMakeVersionCompute.cmake
index 79264ed..72a5800 100644
--- a/Source/CMakeVersionCompute.cmake
+++ b/Source/CMakeVersionCompute.cmake
@@ -32,7 +32,12 @@ endif()
# components in the RC file are 16-bit integers so we may have to
# split the patch component.
if(CMake_VERSION_PATCH MATCHES "^([0-9]+)([0-9][0-9][0-9][0-9])$")
- set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMAKE_MATCH_1},${CMAKE_MATCH_2})
+ set(CMake_RCVERSION_YEAR "${CMAKE_MATCH_1}")
+ set(CMake_RCVERSION_MONTH_DAY "${CMAKE_MATCH_2}")
+ string(REGEX REPLACE "^0+" "" CMake_RCVERSION_MONTH_DAY "${CMake_RCVERSION_MONTH_DAY}")
+ set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_RCVERSION_YEAR},${CMake_RCVERSION_MONTH_DAY})
+ unset(CMake_RCVERSION_MONTH_DAY)
+ unset(CMake_RCVERSION_YEAR)
else()
set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_VERSION_PATCH})
endif()
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index 9ff547a..00fbdab 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -9,6 +9,7 @@
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
+#include <cstring>
#include <ostream>
#include <utility>
#include <vector>
@@ -51,6 +52,7 @@ int cmCPackArchiveGenerator::InitializeInternal()
this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1");
return this->Superclass::InitializeInternal();
}
+
int cmCPackArchiveGenerator::addOneComponentToArchive(
cmArchiveWrite& archive, cmCPackComponent* component)
{
@@ -61,6 +63,13 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
localToplevel += "/" + component->Name;
// Change to local toplevel
cmWorkingDirectory workdir(localToplevel);
+ if (workdir.Failed()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed to change working directory to "
+ << localToplevel << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ return 0;
+ }
std::string filePrefix;
if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
filePrefix = this->GetOption("CPACK_PACKAGE_FILE_NAME");
@@ -237,6 +246,13 @@ int cmCPackArchiveGenerator::PackageFiles()
// CASE 3 : NON COMPONENT package.
DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0], archive);
cmWorkingDirectory workdir(toplevel);
+ if (workdir.Failed()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed to change working directory to "
+ << toplevel << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ return 0;
+ }
for (std::string const& file : files) {
// Get the relative path to the file
std::string rp = cmSystemTools::RelativePath(toplevel, file);
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index d838b30..d41a9e5 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -6,6 +6,7 @@
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include <cstring>
#include <memory> // IWYU pragma: keep
#include <utility>
@@ -404,6 +405,13 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Change dir to: " << goToDir
<< std::endl);
cmWorkingDirectory workdir(goToDir);
+ if (workdir.Failed()) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR, "Failed to change working directory to "
+ << goToDir << " : " << std::strerror(workdir.GetLastResult())
+ << std::endl);
+ return 0;
+ }
for (auto const& symlinked : symlinkedFiles) {
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Will create a symlink: "
<< symlinked.second << "--> " << symlinked.first
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index 2e1ea4c..b2c68e7 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -11,6 +11,7 @@
#include "cmsys/Process.h"
#include <chrono>
+#include <cstring>
#include <ratio>
#include <stdlib.h>
@@ -196,6 +197,16 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
cmSystemTools::MakeDirectory(this->BinaryDir);
}
cmWorkingDirectory workdir(this->BinaryDir);
+ if (workdir.Failed()) {
+ auto msg = "Failed to change working directory to " + this->BinaryDir +
+ " : " + std::strerror(workdir.GetLastResult()) + "\n";
+ if (outstring) {
+ *outstring = msg;
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, msg);
+ }
+ return 1;
+ }
if (this->BuildNoCMake) {
// Make the generator available for the Build call below.
@@ -307,7 +318,16 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
// run the test from the this->BuildRunDir if set
if (!this->BuildRunDir.empty()) {
out << "Run test in directory: " << this->BuildRunDir << "\n";
- cmSystemTools::ChangeDirectory(this->BuildRunDir);
+ if (!workdir.SetDirectory(this->BuildRunDir)) {
+ out << "Failed to change working directory : "
+ << std::strerror(workdir.GetLastResult()) << "\n";
+ if (outstring) {
+ *outstring = out.str();
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, out.str());
+ }
+ return 1;
+ }
}
out << "Running test command: \"" << fullPath << "\"";
for (std::string const& testCommandArg : this->TestCommandArgs) {
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 9c66e73..6cf0ac2 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -23,6 +23,7 @@
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
#include <chrono>
+#include <cstring>
#include <iomanip>
#include <iterator>
#include <sstream>
@@ -975,7 +976,12 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
std::string tempDir = testingDir + "/CoverageInfo";
- cmSystemTools::MakeDirectory(tempDir);
+ if (!cmSystemTools::MakeDirectory(tempDir)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to make directory: " << tempDir << std::endl);
+ cont->Error++;
+ return 0;
+ }
cmWorkingDirectory workdir(tempDir);
int gcovStyle = 0;
@@ -1376,6 +1382,14 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
this->Quiet);
std::string fileDir = cmSystemTools::GetFilenamePath(f);
cmWorkingDirectory workdir(fileDir);
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to change working directory to "
+ << fileDir << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ cont->Error++;
+ continue;
+ }
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Current coverage dir: " << fileDir << std::endl,
@@ -1600,6 +1614,12 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
gl.RecurseThroughSymlinksOff();
std::string buildDir = this->CTest->GetCTestConfiguration("BuildDirectory");
cmWorkingDirectory workdir(buildDir);
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to change working directory to " << buildDir
+ << std::endl);
+ return false;
+ }
// Run profmerge to merge all *.dyn files into dpi files
if (!cmSystemTools::RunSingleCommand("profmerge")) {
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index 5a7baf5..1fff2fa 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -9,6 +9,7 @@
#include "cmWorkingDirectory.h"
#include "cmake.h"
+#include <cstring>
#include <sstream>
#include <stdlib.h>
@@ -218,6 +219,21 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
}
cmWorkingDirectory workdir(
this->CTest->GetCTestConfiguration("BuildDirectory"));
+ if (workdir.Failed()) {
+ this->SetError("failed to change directory to " +
+ this->CTest->GetCTestConfiguration("BuildDirectory") +
+ " : " + std::strerror(workdir.GetLastResult()));
+ if (capureCMakeError) {
+ this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
+ "-1");
+ cmCTestLog(this->CTest, ERROR_MESSAGE, this->GetName()
+ << " " << this->GetError() << "\n");
+ // return success because failure is recorded in CAPTURE_CMAKE_ERROR
+ return true;
+ }
+ return false;
+ }
+
int res = handler->ProcessHandler();
if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) {
std::ostringstream str;
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 50c2d86..14b5caa 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestMultiProcessHandler.h"
+#include "cmAffinity.h"
#include "cmCTest.h"
#include "cmCTestRunTest.h"
#include "cmCTestScriptHandler.h"
@@ -19,6 +20,7 @@
#include <algorithm>
#include <chrono>
+#include <cstring>
#include <iomanip>
#include <list>
#include <math.h>
@@ -53,6 +55,8 @@ cmCTestMultiProcessHandler::cmCTestMultiProcessHandler()
this->TestLoad = 0;
this->Completed = 0;
this->RunningCount = 0;
+ this->ProcessorsAvailable = cmAffinity::GetProcessorsAvailable();
+ this->HaveAffinity = this->ProcessorsAvailable.size();
this->StopTimePassed = false;
this->HasCycles = false;
this->SerialTestRunning = false;
@@ -127,6 +131,21 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
return false;
}
+ if (this->HaveAffinity && this->Properties[test]->WantAffinity) {
+ size_t needProcessors = this->GetProcessorsUsed(test);
+ if (needProcessors > this->ProcessorsAvailable.size()) {
+ return false;
+ }
+ std::vector<size_t> affinity;
+ affinity.reserve(needProcessors);
+ for (size_t i = 0; i < needProcessors; ++i) {
+ auto p = this->ProcessorsAvailable.begin();
+ affinity.push_back(*p);
+ this->ProcessorsAvailable.erase(p);
+ }
+ this->Properties[test]->Affinity = std::move(affinity);
+ }
+
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"test " << test << "\n", this->Quiet);
this->TestRunningMap[test] = true; // mark the test as running
@@ -151,13 +170,19 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
}
}
- cmWorkingDirectory workdir(this->Properties[test]->Directory);
-
- // Lock the resources we'll be using
+ // Always lock the resources we'll be using, even if we fail to set the
+ // working directory because FinishTestProcess() will try to unlock them
this->LockResources(test);
- if (testRun->StartTest(this->Total)) {
- return true;
+ cmWorkingDirectory workdir(this->Properties[test]->Directory);
+ if (workdir.Failed()) {
+ testRun->StartFailure("Failed to change working directory to " +
+ this->Properties[test]->Directory + " : " +
+ std::strerror(workdir.GetLastResult()));
+ } else {
+ if (testRun->StartTest(this->Total)) {
+ return true;
+ }
}
this->FinishTestProcess(testRun, false);
@@ -200,6 +225,11 @@ inline size_t cmCTestMultiProcessHandler::GetProcessorsUsed(int test)
if (processors > this->ParallelLevel) {
processors = this->ParallelLevel;
}
+ // Cap tests that want affinity to the maximum affinity available.
+ if (this->HaveAffinity && processors > this->HaveAffinity &&
+ this->Properties[test]->WantAffinity) {
+ processors = this->HaveAffinity;
+ }
return processors;
}
@@ -398,6 +428,11 @@ void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner,
this->UnlockResources(test);
this->RunningCount -= GetProcessorsUsed(test);
+ for (auto p : properties->Affinity) {
+ this->ProcessorsAvailable.insert(p);
+ }
+ properties->Affinity.clear();
+
delete runner;
if (started) {
this->StartNextTests();
@@ -666,6 +701,8 @@ void cmCTestMultiProcessHandler::PrintTestList()
count++;
cmCTestTestHandler::cmCTestTestProperties& p = *it.second;
+ // Don't worry if this fails, we are only showing the test list, not
+ // running the tests
cmWorkingDirectory workdir(p.Directory);
cmCTestRunTest testRun(*this);
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index 7837ff9..19e1a35 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -119,6 +119,8 @@ protected:
// Number of tests that are complete
size_t Completed;
size_t RunningCount;
+ std::set<size_t> ProcessorsAvailable;
+ size_t HaveAffinity;
bool StopTimePassed;
// list of test properties (indices concurrent to the test map)
PropertiesMap Properties;
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 30ad38c..8d8ebaa 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -14,6 +14,7 @@
#include "cmsys/RegularExpression.hxx"
#include <chrono>
#include <cmAlgorithms.h>
+#include <cstring>
#include <iomanip>
#include <ratio>
#include <sstream>
@@ -248,11 +249,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
*this->TestHandler->LogFile << "Test time = " << buf << std::endl;
}
- // Set the working directory to the tests directory to process Dart files.
- {
- cmWorkingDirectory workdir(this->TestProperties->Directory);
- this->DartProcessing();
- }
+ this->DartProcessing();
// if this is doing MemCheck then all the output needs to be put into
// Output since that is what is parsed by cmCTestMemCheckHandler
@@ -338,6 +335,13 @@ bool cmCTestRunTest::StartAgain()
this->RunAgain = false; // reset
// change to tests directory
cmWorkingDirectory workdir(this->TestProperties->Directory);
+ if (workdir.Failed()) {
+ this->StartFailure("Failed to change working directory to " +
+ this->TestProperties->Directory + " : " +
+ std::strerror(workdir.GetLastResult()));
+ return true;
+ }
+
this->StartTest(this->TotalNumberOfTests);
return true;
}
@@ -386,6 +390,37 @@ void cmCTestRunTest::MemCheckPostProcess()
handler->PostProcessTest(this->TestResult, this->Index);
}
+void cmCTestRunTest::StartFailure(std::string const& output)
+{
+ // Still need to log the Start message so the test summary records our
+ // attempt to start this test
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::setw(2 * getNumWidth(this->TotalNumberOfTests) + 8)
+ << "Start "
+ << std::setw(getNumWidth(this->TestHandler->GetMaxIndex()))
+ << this->TestProperties->Index << ": "
+ << this->TestProperties->Name << std::endl);
+
+ this->ProcessOutput.clear();
+ if (!output.empty()) {
+ *this->TestHandler->LogFile << output << std::endl;
+ cmCTestLog(this->CTest, ERROR_MESSAGE, output << std::endl);
+ }
+
+ this->TestResult.Properties = this->TestProperties;
+ this->TestResult.ExecutionTime = cmDuration::zero();
+ this->TestResult.CompressOutput = false;
+ this->TestResult.ReturnValue = -1;
+ this->TestResult.CompletionStatus = "Failed to start";
+ this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
+ this->TestResult.TestCount = this->TestProperties->Index;
+ this->TestResult.Name = this->TestProperties->Name;
+ this->TestResult.Path = this->TestProperties->Directory;
+ this->TestResult.Output = output;
+ this->TestResult.FullCommandLine.clear();
+ this->TestProcess = cm::make_unique<cmProcess>(*this);
+}
+
// Starts the execution of a test. Returns once it has started
bool cmCTestRunTest::StartTest(size_t total)
{
@@ -515,7 +550,8 @@ bool cmCTestRunTest::StartTest(size_t total)
}
return this->ForkProcess(timeout, this->TestProperties->ExplicitTimeout,
- &this->TestProperties->Environment);
+ &this->TestProperties->Environment,
+ &this->TestProperties->Affinity);
}
void cmCTestRunTest::ComputeArguments()
@@ -591,7 +627,8 @@ void cmCTestRunTest::DartProcessing()
}
bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
- std::vector<std::string>* environment)
+ std::vector<std::string>* environment,
+ std::vector<size_t>* affinity)
{
this->TestProcess = cm::make_unique<cmProcess>(*this);
this->TestProcess->SetId(this->Index);
@@ -637,7 +674,8 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
cmSystemTools::AppendEnv(*environment);
}
- return this->TestProcess->StartProcess(this->MultiTestHandler.Loop);
+ return this->TestProcess->StartProcess(this->MultiTestHandler.Loop,
+ affinity);
}
void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index 4d57357..3b1d674 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -74,6 +74,8 @@ public:
bool StartAgain();
+ void StartFailure(std::string const& output);
+
cmCTest* GetCTest() const { return this->CTest; }
void FinalizeTest();
@@ -83,7 +85,8 @@ private:
void DartProcessing();
void ExeNotFound(std::string exe);
bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
- std::vector<std::string>* environment);
+ std::vector<std::string>* environment,
+ std::vector<size_t>* affinity);
void WriteLogOutputTop(size_t completed, size_t total);
// Run post processing of the process output for MemCheck
void MemCheckPostProcess();
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index e0bffd4..5fff730 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -527,7 +527,7 @@ int cmCTestScriptHandler::RunConfigurationScript(
return result;
}
- // only run the curent script if we should
+ // only run the current script if we should
if (this->Makefile && this->Makefile->IsOn("CTEST_RUN_CURRENT_SCRIPT") &&
this->ShouldRunCurrentScript) {
return this->RunCurrentScript();
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 08d05c8..3bab81e 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -7,6 +7,7 @@
#include "cm_jsoncpp_value.h"
#include "cmsys/Process.h"
#include <chrono>
+#include <cstring>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
@@ -1532,6 +1533,15 @@ int cmCTestSubmitHandler::ProcessHandler()
// change to the build directory so that we can uses a relative path
// on windows since scp doesn't support "c:" a drive in the path
cmWorkingDirectory workdir(buildDirectory);
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Failed to change directory to "
+ << buildDirectory << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ ofs << " Failed to change directory to " << buildDirectory << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl;
+ return -1;
+ }
if (!this->SubmitUsingSCP(this->CTest->GetCTestConfiguration("ScpCommand"),
"Testing/" + this->CTest->GetCurrentTag(), files,
@@ -1551,6 +1561,15 @@ int cmCTestSubmitHandler::ProcessHandler()
// change to the build directory so that we can uses a relative path
// on windows since scp doesn't support "c:" a drive in the path
cmWorkingDirectory workdir(buildDirectory);
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Failed to change directory to "
+ << buildDirectory << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ ofs << " Failed to change directory to " << buildDirectory << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl;
+ return -1;
+ }
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
" Change directory: " << buildDirectory << std::endl,
this->Quiet);
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 84d8926..cbaf984 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -6,6 +6,7 @@
#include <cmsys/Base64.h>
#include <cmsys/Directory.hxx>
#include <cmsys/RegularExpression.hxx>
+#include <cstring>
#include <functional>
#include <iomanip>
#include <iterator>
@@ -14,7 +15,6 @@
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <time.h>
#include "cmAlgorithms.h"
@@ -85,6 +85,11 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args,
bool readit = false;
{
cmWorkingDirectory workdir(fname);
+ if (workdir.Failed()) {
+ this->SetError("Failed to change directory to " + fname + " : " +
+ std::strerror(workdir.GetLastResult()));
+ return false;
+ }
const char* testFilename;
if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
// does the CTestTestfile.cmake exist ?
@@ -2165,6 +2170,9 @@ bool cmCTestTestHandler::SetTestsProperties(
rt.Processors = 1;
}
}
+ if (key == "PROCESSOR_AFFINITY") {
+ rt.WantAffinity = cmSystemTools::IsOn(val.c_str());
+ }
if (key == "SKIP_RETURN_CODE") {
rt.SkipReturnCode = atoi(val.c_str());
if (rt.SkipReturnCode < 0 || rt.SkipReturnCode > 255) {
@@ -2336,6 +2344,7 @@ bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args)
test.ExplicitTimeout = false;
test.Cost = 0;
test.Processors = 1;
+ test.WantAffinity = false;
test.SkipReturnCode = -1;
test.PreviousRuns = 0;
if (this->UseIncludeRegExpFlag &&
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index f4978b6..d2694a1 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -130,6 +130,8 @@ public:
int Index;
// Requested number of process slots
int Processors;
+ bool WantAffinity;
+ std::vector<size_t> Affinity;
// return code of test which will mark test as "not run"
int SkipReturnCode;
std::vector<std::string> Environment;
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index 09ed0a9..5c9b169 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -83,7 +83,7 @@ void cmProcess::SetCommandArguments(std::vector<std::string> const& args)
this->Arguments = args;
}
-bool cmProcess::StartProcess(uv_loop_t& loop)
+bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity)
{
this->ProcessState = cmProcess::State::Error;
if (this->Command.empty()) {
@@ -138,6 +138,22 @@ bool cmProcess::StartProcess(uv_loop_t& loop)
options.stdio_count = 3; // in, out and err
options.exit_cb = &cmProcess::OnExitCB;
options.stdio = stdio;
+#if !defined(CMAKE_USE_SYSTEM_LIBUV)
+ std::vector<char> cpumask;
+ if (affinity && !affinity->empty()) {
+ cpumask.resize(static_cast<size_t>(uv_cpumask_size()), 0);
+ for (auto p : *affinity) {
+ cpumask[p] = 1;
+ }
+ options.cpumask = cpumask.data();
+ options.cpumask_size = cpumask.size();
+ } else {
+ options.cpumask = nullptr;
+ options.cpumask_size = 0;
+ }
+#else
+ static_cast<void>(affinity);
+#endif
status =
uv_read_start(pipe_reader, &cmProcess::OnAllocateCB, &cmProcess::OnReadCB);
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index 20e24b9..b2d87fa 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -36,7 +36,7 @@ public:
void ChangeTimeout(cmDuration t);
void ResetStartTime();
// Return true if the process starts
- bool StartProcess(uv_loop_t& loop);
+ bool StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity);
enum class State
{
diff --git a/Source/cmAffinity.cxx b/Source/cmAffinity.cxx
new file mode 100644
index 0000000..bdf1f42
--- /dev/null
+++ b/Source/cmAffinity.cxx
@@ -0,0 +1,62 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAffinity.h"
+
+#include "cm_uv.h"
+
+#ifndef CMAKE_USE_SYSTEM_LIBUV
+#ifdef _WIN32
+#define CM_HAVE_CPU_AFFINITY
+#include <windows.h>
+#elif defined(__linux__) || defined(__FreeBSD__)
+#define CM_HAVE_CPU_AFFINITY
+#include <pthread.h>
+#include <sched.h>
+#if defined(__FreeBSD__)
+#include <pthread_np.h>
+#include <sys/cpuset.h>
+#include <sys/param.h>
+#endif
+#if defined(__linux__)
+typedef cpu_set_t cm_cpuset_t;
+#else
+typedef cpuset_t cm_cpuset_t;
+#endif
+#endif
+#endif
+
+namespace cmAffinity {
+
+std::set<size_t> GetProcessorsAvailable()
+{
+ std::set<size_t> processorsAvailable;
+#ifdef CM_HAVE_CPU_AFFINITY
+ int cpumask_size = uv_cpumask_size();
+ if (cpumask_size > 0) {
+#ifdef _WIN32
+ DWORD_PTR procmask;
+ DWORD_PTR sysmask;
+ if (GetProcessAffinityMask(GetCurrentProcess(), &procmask, &sysmask) !=
+ 0) {
+ for (int i = 0; i < cpumask_size; ++i) {
+ if (procmask & (((DWORD_PTR)1) << i)) {
+ processorsAvailable.insert(i);
+ }
+ }
+ }
+#else
+ cm_cpuset_t cpuset;
+ CPU_ZERO(&cpuset); // NOLINT(clang-tidy)
+ if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset), &cpuset) == 0) {
+ for (int i = 0; i < cpumask_size; ++i) {
+ if (CPU_ISSET(i, &cpuset)) {
+ processorsAvailable.insert(i);
+ }
+ }
+ }
+#endif
+ }
+#endif
+ return processorsAvailable;
+}
+}
diff --git a/Source/cmAffinity.h b/Source/cmAffinity.h
new file mode 100644
index 0000000..3775bae
--- /dev/null
+++ b/Source/cmAffinity.h
@@ -0,0 +1,12 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cstddef>
+#include <set>
+
+namespace cmAffinity {
+
+std::set<size_t> GetProcessorsAvailable();
+}
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 673a40e..b2f4f25 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -347,7 +347,7 @@ public:
const std::string& cmake_var,
bool suppress = false);
- /** Make string safe to be send as an URL */
+ /** Make string safe to be sent as a URL */
static std::string MakeURLSafe(const std::string&);
/** Decode a URL to the original string. */
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index fab2445..85ac985 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -160,14 +160,14 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
currentcwd += "/CMakeCache.txt";
oldcwd += "/CMakeCache.txt";
if (!cmSystemTools::SameFile(oldcwd, currentcwd)) {
- std::string message =
- std::string("The current CMakeCache.txt directory ") + currentcwd +
- std::string(" is different than the directory ") +
- std::string(this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR")) +
- std::string(" where CMakeCache.txt was created. This may result "
- "in binaries being created in the wrong place. If you "
- "are not sure, reedit the CMakeCache.txt");
- cmSystemTools::Error(message.c_str());
+ std::ostringstream message;
+ message << "The current CMakeCache.txt directory " << currentcwd
+ << " is different than the directory "
+ << this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR")
+ << " where CMakeCache.txt was created. This may result "
+ "in binaries being created in the wrong place. If you "
+ "are not sure, reedit the CMakeCache.txt";
+ cmSystemTools::Error(message.str().c_str());
}
}
return true;
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 8a5a6de..e00450f 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -611,6 +611,9 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
if (!libName.empty()) {
this->AddItem(libName, nullptr);
}
+ } else if (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ // Ignore object library!
+ // Its object-files should already have been extracted for linking.
} else {
// Decide whether to use an import library.
bool implib =
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index 18767a3..efdd3a5 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -211,11 +211,11 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
if (depender->GetType() != cmStateEnums::EXECUTABLE &&
depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
depender->GetType() != cmStateEnums::SHARED_LIBRARY &&
- depender->GetType() != cmStateEnums::MODULE_LIBRARY) {
+ depender->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ depender->GetType() != cmStateEnums::OBJECT_LIBRARY) {
this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
cmake::FATAL_ERROR,
- "Only executables and non-OBJECT libraries may "
- "reference target objects.",
+ "Only executables and libraries may reference target objects.",
depender->GetBacktrace());
return;
}
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index cdab671..4716e14 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -7,7 +7,6 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
-#include "cmWorkingDirectory.h"
#include "cmsys/FStream.hxx"
#include <sstream>
@@ -15,8 +14,7 @@
#include <utility>
cmDepends::cmDepends(cmLocalGenerator* lg, const char* targetDir)
- : CompileDirectory()
- , LocalGenerator(lg)
+ : LocalGenerator(lg)
, Verbose(false)
, FileComparison(nullptr)
, TargetDirectory(targetDir)
@@ -73,9 +71,6 @@ bool cmDepends::Finalize(std::ostream& /*unused*/, std::ostream& /*unused*/)
bool cmDepends::Check(const char* makeFile, const char* internalFile,
std::map<std::string, DependencyVector>& validDeps)
{
- // Dependency checks must be done in proper working directory.
- cmWorkingDirectory workdir(this->CompileDirectory);
-
// Check whether dependencies must be regenerated.
bool okay = true;
cmsys::ifstream fin(internalFile);
diff --git a/Source/cmDepends.h b/Source/cmDepends.h
index a4fee3c..4b9e05a 100644
--- a/Source/cmDepends.h
+++ b/Source/cmDepends.h
@@ -31,9 +31,6 @@ public:
path from the build directory to the target file. */
cmDepends(cmLocalGenerator* lg = nullptr, const char* targetDir = "");
- /** at what level will the compile be done from */
- void SetCompileDirectory(const char* dir) { this->CompileDirectory = dir; }
-
/** Set the local generator for the directory in which we are
scanning dependencies. This is not a full local generator; it
has been setup to do relative path conversions for the current
@@ -95,9 +92,6 @@ protected:
virtual bool Finalize(std::ostream& makeDepends,
std::ostream& internalDepends);
- // The directory in which the build rule for the target file is executed.
- std::string CompileDirectory;
-
// The local generator.
cmLocalGenerator* LocalGenerator;
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index a276d01..f0ae47b 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -159,7 +159,9 @@ cmStateEnums::TargetType cmExportBuildFileGenerator::GetExportTargetType(
{
cmStateEnums::TargetType targetType = target->GetType();
// An object library exports as an interface library if we cannot
- // tell clients where to find the objects.
+ // tell clients where to find the objects. This is sufficient
+ // to support transitive usage requirements on other targets that
+ // use the object library.
if (targetType == cmStateEnums::OBJECT_LIBRARY &&
!this->LG->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) {
targetType = cmStateEnums::INTERFACE_LIBRARY;
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 8492c17..90b943b 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -757,9 +757,9 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
}
}
- std::string output;
- bool first = true;
- for (; i != args.end(); ++i) {
+ std::vector<std::string> files;
+ bool warnFollowedSymlinks = false;
+ while (i != args.end()) {
if (*i == "LIST_DIRECTORIES") {
++i;
if (i != args.end()) {
@@ -777,103 +777,105 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
this->SetError("LIST_DIRECTORIES missing bool value.");
return false;
}
- continue;
- }
-
- if (recurse && (*i == "FOLLOW_SYMLINKS")) {
+ ++i;
+ if (i == args.end()) {
+ this->SetError("GLOB requires a glob expression after the bool.");
+ return false;
+ }
+ } else if (*i == "FOLLOW_SYMLINKS") {
+ if (!recurse) {
+ this->SetError("FOLLOW_SYMLINKS is not a valid parameter for GLOB.");
+ return false;
+ }
explicitFollowSymlinks = true;
g.RecurseThroughSymlinksOn();
++i;
if (i == args.end()) {
this->SetError(
- "GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS");
+ "GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS.");
return false;
}
- }
-
- if (*i == "RELATIVE") {
+ } else if (*i == "RELATIVE") {
++i; // skip RELATIVE
if (i == args.end()) {
- this->SetError("GLOB requires a directory after the RELATIVE tag");
+ this->SetError("GLOB requires a directory after the RELATIVE tag.");
return false;
}
g.SetRelative(i->c_str());
++i;
if (i == args.end()) {
- this->SetError("GLOB requires a glob expression after the directory");
+ this->SetError("GLOB requires a glob expression after the directory.");
return false;
}
- }
-
- cmsys::Glob::GlobMessages globMessages;
- if (!cmsys::SystemTools::FileIsFullPath(*i)) {
- std::string expr = this->Makefile->GetCurrentSourceDirectory();
- // Handle script mode
- if (!expr.empty()) {
- expr += "/" + *i;
- g.FindFiles(expr, &globMessages);
- } else {
- g.FindFiles(*i, &globMessages);
- }
} else {
- g.FindFiles(*i, &globMessages);
- }
-
- if (!globMessages.empty()) {
- bool shouldExit = false;
- for (cmsys::Glob::Message const& globMessage : globMessages) {
- if (globMessage.type == cmsys::Glob::cyclicRecursion) {
- this->Makefile->IssueMessage(
- cmake::AUTHOR_WARNING,
- "Cyclic recursion detected while globbing for '" + *i + "':\n" +
- globMessage.content);
+ std::string expr = *i;
+ if (!cmsys::SystemTools::FileIsFullPath(*i)) {
+ expr = this->Makefile->GetCurrentSourceDirectory();
+ // Handle script mode
+ if (!expr.empty()) {
+ expr += "/" + *i;
} else {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, "Error has occurred while globbing for '" +
- *i + "' - " + globMessage.content);
- shouldExit = true;
+ expr = *i;
}
}
- if (shouldExit) {
- return false;
+
+ cmsys::Glob::GlobMessages globMessages;
+ g.FindFiles(expr, &globMessages);
+
+ if (!globMessages.empty()) {
+ bool shouldExit = false;
+ for (cmsys::Glob::Message const& globMessage : globMessages) {
+ if (globMessage.type == cmsys::Glob::cyclicRecursion) {
+ this->Makefile->IssueMessage(
+ cmake::AUTHOR_WARNING,
+ "Cyclic recursion detected while globbing for '" + *i + "':\n" +
+ globMessage.content);
+ } else {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR, "Error has occurred while globbing for '" +
+ *i + "' - " + globMessage.content);
+ shouldExit = true;
+ }
+ }
+ if (shouldExit) {
+ return false;
+ }
}
- }
- std::vector<std::string>::size_type cc;
- std::vector<std::string>& files = g.GetFiles();
- std::sort(files.begin(), files.end());
- for (cc = 0; cc < files.size(); cc++) {
- if (!first) {
- output += ";";
+ if (recurse && !explicitFollowSymlinks &&
+ g.GetFollowedSymlinkCount() != 0) {
+ warnFollowedSymlinks = true;
}
- output += files[cc];
- first = false;
+
+ std::vector<std::string>& foundFiles = g.GetFiles();
+ files.insert(files.end(), foundFiles.begin(), foundFiles.end());
+ ++i;
}
}
- if (recurse && !explicitFollowSymlinks) {
- switch (status) {
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::NEW:
- // Correct behavior, yay!
- break;
- case cmPolicies::OLD:
- // Probably not really the expected behavior, but the author explicitly
- // asked for the old behavior... no warning.
- case cmPolicies::WARN:
- // Possibly unexpected old behavior *and* we actually traversed
- // symlinks without being explicitly asked to: warn the author.
- if (g.GetFollowedSymlinkCount() != 0) {
- this->Makefile->IssueMessage(
- cmake::AUTHOR_WARNING,
- cmPolicies::GetPolicyWarning(cmPolicies::CMP0009));
- }
- break;
- }
+ switch (status) {
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Correct behavior, yay!
+ break;
+ case cmPolicies::OLD:
+ // Probably not really the expected behavior, but the author explicitly
+ // asked for the old behavior... no warning.
+ case cmPolicies::WARN:
+ // Possibly unexpected old behavior *and* we actually traversed
+ // symlinks without being explicitly asked to: warn the author.
+ if (warnFollowedSymlinks) {
+ this->Makefile->IssueMessage(
+ cmake::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0009));
+ }
+ break;
}
- this->Makefile->AddDefinition(variable, output.c_str());
+ std::sort(files.begin(), files.end());
+ files.erase(std::unique(files.begin(), files.end()), files.end());
+ this->Makefile->AddDefinition(variable, cmJoin(files, ";").c_str());
return true;
}
diff --git a/Source/cmFileTimeComparison.h b/Source/cmFileTimeComparison.h
index b1f8ed6..114989b 100644
--- a/Source/cmFileTimeComparison.h
+++ b/Source/cmFileTimeComparison.h
@@ -8,9 +8,9 @@
class cmFileTimeComparisonInternal;
/** \class cmFileTimeComparison
- * \brief Helper class for performing globbing searches.
+ * \brief Helper class for comparing file modification times.
*
- * Finds all files that match a given globbing expression.
+ * Compare file modification times or test if file modification times differ.
*/
class cmFileTimeComparison
{
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index e9b6daf..b9e2978 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -132,8 +132,8 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
this->SourceEntries, true);
this->DLLPlatform =
- (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
+ strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
+ "") != 0;
this->PolicyMap = t->PolicyMap;
}
@@ -240,13 +240,16 @@ const char* cmGeneratorTarget::GetOutputTargetType(
case cmStateEnums::MODULE_LIBRARY:
switch (artifact) {
case cmStateEnums::RuntimeBinaryArtifact:
- // Module import libraries are treated as archive targets.
+ // Module libraries are always treated as library targets.
return "LIBRARY";
case cmStateEnums::ImportLibraryArtifact:
- // Module libraries are always treated as library targets.
+ // Module import libraries are treated as archive targets.
return "ARCHIVE";
}
break;
+ case cmStateEnums::OBJECT_LIBRARY:
+ // Object libraries are always treated as object targets.
+ return "OBJECT";
case cmStateEnums::EXECUTABLE:
switch (artifact) {
case cmStateEnums::RuntimeBinaryArtifact:
@@ -806,6 +809,26 @@ static void AddInterfaceEntries(
}
}
+static void AddObjectEntries(
+ cmGeneratorTarget const* thisTarget, std::string const& config,
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries)
+{
+ if (cmLinkImplementationLibraries const* impl =
+ thisTarget->GetLinkImplementationLibraries(config)) {
+ for (cmLinkImplItem const& lib : impl->Libraries) {
+ if (lib.Target &&
+ lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ std::string genex = "$<TARGET_OBJECTS:" + lib + ">";
+ cmGeneratorExpression ge(lib.Backtrace);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
+ cge->SetEvaluateForBuildsystem(true);
+ entries.push_back(
+ new cmGeneratorTarget::TargetPropertyEntry(std::move(cge), lib));
+ }
+ }
+ }
+}
+
static bool processSources(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
@@ -846,13 +869,10 @@ static bool processSources(
std::ostringstream err;
if (!targetName.empty()) {
err << "Target \"" << targetName
- << "\" contains relative "
- "path in its INTERFACE_SOURCES:\n"
- " \""
+ << "\" contains relative path in its INTERFACE_SOURCES:\n \""
<< src << "\"";
} else {
- err << "Found relative path while evaluating sources of "
- "\""
+ err << "Found relative path while evaluating sources of \""
<< tgt->GetName() << "\":\n \"" << src << "\"\n";
}
tgt->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, err.str());
@@ -929,23 +949,32 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
processSources(this, this->SourceEntries, files, uniqueSrcs, &dagChecker,
config, debugSources);
+ // Collect INTERFACE_SOURCES of all direct link-dependencies.
std::vector<cmGeneratorTarget::TargetPropertyEntry*>
linkInterfaceSourcesEntries;
-
AddInterfaceEntries(this, config, "INTERFACE_SOURCES",
linkInterfaceSourcesEntries);
-
std::vector<std::string>::size_type numFilesBefore = files.size();
bool contextDependentInterfaceSources =
processSources(this, linkInterfaceSourcesEntries, files, uniqueSrcs,
&dagChecker, config, debugSources);
+ // Collect TARGET_OBJECTS of direct object link-dependencies.
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkObjectsEntries;
+ AddObjectEntries(this, config, linkObjectsEntries);
+ std::vector<std::string>::size_type numFilesBefore2 = files.size();
+ bool contextDependentObjects =
+ processSources(this, linkObjectsEntries, files, uniqueSrcs, &dagChecker,
+ config, debugSources);
+
if (!contextDependentDirectSources &&
- !(contextDependentInterfaceSources && numFilesBefore < files.size())) {
+ !(contextDependentInterfaceSources && numFilesBefore < files.size()) &&
+ !(contextDependentObjects && numFilesBefore2 < files.size())) {
this->LinkImplementationLanguageIsContextDependent = false;
}
cmDeleteAll(linkInterfaceSourcesEntries);
+ cmDeleteAll(linkObjectsEntries);
}
void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
@@ -1051,9 +1080,6 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
kind = SourceKindHeader;
} else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
kind = SourceKindExternalObject;
- if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- badObjLib.push_back(sf);
- }
} else if (!sf->GetLanguage().empty()) {
kind = SourceKindObjectSource;
} else if (ext == "def") {
@@ -1671,6 +1697,7 @@ bool cmGeneratorTarget::HaveWellDefinedOutputFiles() const
return this->GetType() == cmStateEnums::STATIC_LIBRARY ||
this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
this->GetType() == cmStateEnums::EXECUTABLE;
}
@@ -1999,8 +2026,13 @@ void cmGeneratorTarget::ComputeModuleDefinitionInfo(
info.WindowsExportAllSymbols =
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS");
+#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
info.DefFileGenerated =
info.WindowsExportAllSymbols || info.Sources.size() > 1;
+#else
+ // Our __create_def helper is only available on Windows.
+ info.DefFileGenerated = false;
+#endif
if (info.DefFileGenerated) {
info.DefFile = this->ObjectDirectory /* has slash */ + "exports.def";
} else if (!info.Sources.empty()) {
@@ -5323,20 +5355,6 @@ cmGeneratorTarget* cmGeneratorTarget::FindTargetToLink(
tgt = nullptr;
}
- if (tgt && tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::ostringstream e;
- e << "Target \"" << this->GetName() << "\" links to "
- "OBJECT library \""
- << tgt->GetName()
- << "\" but this is not "
- "allowed. "
- "One may link only to STATIC or SHARED libraries, or to executables "
- "with the ENABLE_EXPORTS property set.";
- cmake* cm = this->LocalGenerator->GetCMakeInstance();
- cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
- tgt = nullptr;
- }
-
return tgt;
}
@@ -5400,6 +5418,7 @@ bool cmGeneratorTarget::IsLinkable() const
this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY ||
this->GetType() == cmStateEnums::UNKNOWN_LIBRARY ||
+ this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
this->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
this->IsExecutableWithExports());
}
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index c805b98..f9eb90f 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -6,11 +6,11 @@
#include "cmsys/FStream.hxx"
#include <algorithm>
#include <assert.h>
+#include <cstring>
#include <iterator>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
@@ -1806,6 +1806,8 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
cmSystemTools::OutputOption outputflag,
std::vector<std::string> const& nativeOptions)
{
+ bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
+
/**
* Run an executable command and put the stdout in output.
*/
@@ -1813,9 +1815,17 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
output += "Change Dir: ";
output += bindir;
output += "\n";
+ if (workdir.Failed()) {
+ cmSystemTools::SetRunCommandHideConsole(hideconsole);
+ cmSystemTools::Error("Failed to change directory: ",
+ std::strerror(workdir.GetLastResult()));
+ output += "Failed to change directory: ";
+ output += std::strerror(workdir.GetLastResult());
+ output += "\n";
+ return 1;
+ }
int retVal;
- bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
cmSystemTools::SetRunCommandHideConsole(true);
std::string outputBuffer;
std::string* outputPtr = &outputBuffer;
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 43032fb..c92df55 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -241,6 +241,10 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
lg->WriteMakeRule(makefileStream, "The main recursive preinstall target",
"preinstall", depends, no_commands, true);
+ // Write an empty clean:
+ lg->WriteMakeRule(makefileStream, "The main recursive clean target", "clean",
+ depends, no_commands, true);
+
// Write out the "special" stuff
lg->WriteSpecialTargetsTop(makefileStream);
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 0d5dad2..7fdf896 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -466,7 +466,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
if (regenerate && (isTopLevel || !generateTopLevelProjectOnly)) {
this->CreateReRunCMakeFile(root, gens);
std::string file =
- this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile.c_str());
+ this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile);
cmSystemTools::ReplaceString(file, "\\ ", " ");
cmTarget* check = mf->AddUtilityCommand(
CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmMakefile::TargetOrigin::Generator,
@@ -553,7 +553,7 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
for (const auto& lfile : lfiles) {
makefileStream << "TARGETS += $(subst $(space),$(spaceplus),$(wildcard "
- << this->ConvertToRelativeForMake(lfile.c_str()) << "))\n";
+ << this->ConvertToRelativeForMake(lfile) << "))\n";
}
std::string checkCache = root->GetBinaryDirectory();
@@ -562,11 +562,11 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
checkCache += "cmake.check_cache";
makefileStream << "\n"
- << this->ConvertToRelativeForMake(checkCache.c_str())
+ << this->ConvertToRelativeForMake(checkCache)
<< ": $(TARGETS)\n";
makefileStream << "\t"
<< this->ConvertToRelativeForMake(
- cmSystemTools::GetCMakeCommand().c_str())
+ cmSystemTools::GetCMakeCommand())
<< " -H"
<< this->ConvertToRelativeForMake(root->GetSourceDirectory())
<< " -B"
@@ -1571,12 +1571,11 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase(
}
std::string cdir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
- cdir = this->ConvertToRelativeForMake(cdir.c_str());
+ cdir = this->ConvertToRelativeForMake(cdir);
std::string makecmd = "make -C ";
makecmd += cdir;
makecmd += " -f ";
- makecmd +=
- this->ConvertToRelativeForMake((makefile + "$CONFIGURATION").c_str());
+ makecmd += this->ConvertToRelativeForMake((makefile + "$CONFIGURATION"));
makecmd += " all";
buildphase->AddAttribute("shellScript", this->CreateString(makecmd));
buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0"));
@@ -1611,8 +1610,7 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
const std::vector<std::string>& outputs = ccg.GetOutputs();
if (!outputs.empty()) {
for (auto const& output : outputs) {
- makefileStream << "\\\n\t"
- << this->ConvertToRelativeForMake(output.c_str());
+ makefileStream << "\\\n\t" << this->ConvertToRelativeForMake(output);
}
} else {
std::ostringstream str;
@@ -1633,8 +1631,7 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
// There is at least one output, start the rule for it
const char* sep = "";
for (auto const& output : outputs) {
- makefileStream << sep
- << this->ConvertToRelativeForMake(output.c_str());
+ makefileStream << sep << this->ConvertToRelativeForMake(output);
sep = " ";
}
makefileStream << ": ";
@@ -1646,8 +1643,7 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
std::string dep;
if (this->CurrentLocalGenerator->GetRealDependency(d, configName,
dep)) {
- makefileStream << "\\\n"
- << this->ConvertToRelativeForMake(dep.c_str());
+ makefileStream << "\\\n" << this->ConvertToRelativeForMake(dep);
}
}
makefileStream << "\n";
@@ -1664,12 +1660,12 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
// Build the command line in a single string.
std::string cmd2 = ccg.GetCommand(c);
cmSystemTools::ReplaceString(cmd2, "/./", "/");
- cmd2 = this->ConvertToRelativeForMake(cmd2.c_str());
+ cmd2 = this->ConvertToRelativeForMake(cmd2);
std::string cmd;
std::string wd = ccg.GetWorkingDirectory();
if (!wd.empty()) {
cmd += "cd ";
- cmd += this->ConvertToRelativeForMake(wd.c_str());
+ cmd += this->ConvertToRelativeForMake(wd);
cmd += " && ";
}
cmd += cmd2;
@@ -3190,7 +3186,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
std::string tfull = gt->GetFullPath(configName);
- std::string trel = this->ConvertToRelativeForMake(tfull.c_str());
+ std::string trel = this->ConvertToRelativeForMake(tfull);
// Add this target to the post-build phases of its dependencies.
std::map<std::string, cmXCodeObject::StringVec>::const_iterator y =
@@ -3218,7 +3214,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
target->GetDependLibraries().find(configName);
if (x != target->GetDependLibraries().end()) {
for (auto const& deplib : x->second) {
- std::string file = this->ConvertToRelativeForMake(deplib.c_str());
+ std::string file = this->ConvertToRelativeForMake(deplib);
makefileStream << "\\\n\t" << file;
dummyRules.insert(file);
}
@@ -3233,7 +3229,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
d += objLibName;
d += ".a";
- std::string dependency = this->ConvertToRelativeForMake(d.c_str());
+ std::string dependency = this->ConvertToRelativeForMake(d);
makefileStream << "\\\n\t" << dependency;
dummyRules.insert(dependency);
}
@@ -3241,8 +3237,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
// Write the action to remove the target if it is out of date.
makefileStream << "\n";
makefileStream << "\t/bin/rm -f "
- << this->ConvertToRelativeForMake(tfull.c_str())
- << "\n";
+ << this->ConvertToRelativeForMake(tfull) << "\n";
// if building for more than one architecture
// then remove those executables as well
if (this->Architectures.size() > 1) {
@@ -3254,8 +3249,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
universalFile += "/";
universalFile += gt->GetFullName(configName);
makefileStream << "\t/bin/rm -f "
- << this->ConvertToRelativeForMake(
- universalFile.c_str())
+ << this->ConvertToRelativeForMake(universalFile)
<< "\n";
}
}
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 008a5e0..b5291a1 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -5,6 +5,7 @@
#include "cmsys/Glob.hxx"
#include <sstream>
#include <stddef.h>
+#include <string.h>
#include <utility>
#include "cmAlgorithms.h"
@@ -334,8 +335,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// Check whether this is a DLL platform.
bool dll_platform =
- (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
+ strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
+ "") != 0;
for (std::string const& tgt : targetList.GetVector()) {
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 47d75af..9e53579 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -6,12 +6,12 @@
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
#include <assert.h>
+#include <cstring>
#include <ctype.h>
#include <iterator>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <stdlib.h>
-#include <string.h>
#include <utility>
#include "cmAlgorithms.h"
@@ -1867,7 +1867,7 @@ cmTarget* cmMakefile::AddLibrary(const std::string& lname,
// Clear its dependencies. Otherwise, dependencies might persist
// over changes in CMakeLists.txt, making the information stale and
// hence useless.
- target->ClearDependencyInformation(*this, lname);
+ target->ClearDependencyInformation(*this);
if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
@@ -3250,6 +3250,14 @@ int cmMakefile::TryCompile(const std::string& srcdir,
// change to the tests directory and run cmake
// use the cmake object instead of calling cmake
cmWorkingDirectory workdir(bindir);
+ if (workdir.Failed()) {
+ this->IssueMessage(cmake::FATAL_ERROR,
+ "Failed to set working directory to " + bindir + " : " +
+ std::strerror(workdir.GetLastResult()));
+ cmSystemTools::SetFatalErrorOccured();
+ this->IsSourceFileTryCompile = false;
+ return 1;
+ }
// make sure the same generator is used
// use this program as the cmake to be run, it should not
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index 6519dd9..fd42c53 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -342,13 +342,12 @@ use the caret character itself (^), use two in a row (^^).
*/
/* Some helpers to identify character classes */
-namespace {
-inline int Shell__CharIsWhitespace(char c)
+static int Shell__CharIsWhitespace(char c)
{
return ((c == ' ') || (c == '\t'));
}
-inline int Shell__CharNeedsQuotesOnUnix(char c)
+static int Shell__CharNeedsQuotesOnUnix(char c)
{
return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') ||
(c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') ||
@@ -356,17 +355,16 @@ inline int Shell__CharNeedsQuotesOnUnix(char c)
(c == '\\'));
}
-inline int Shell__CharNeedsQuotesOnWindows(char c)
+static int Shell__CharNeedsQuotesOnWindows(char c)
{
return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') ||
(c == '>') || (c == '|') || (c == '^'));
}
-inline int Shell__CharIsMakeVariableName(char c)
+static int Shell__CharIsMakeVariableName(char c)
{
return c && (c == '_' || isalpha((static_cast<int>(c))));
}
-}
int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
{
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index c39f927..a784f98 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -214,6 +214,9 @@ class cmMakefile;
3, 10, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0072, \
"FindOpenGL prefers GLVND by default when available.", 3, 11, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0073, \
+ "Do not produce legacy _LIB_DEPENDS cache entries.", 3, 12, 0, \
cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
@@ -238,7 +241,8 @@ class cmMakefile;
F(CMP0063) \
F(CMP0065) \
F(CMP0068) \
- F(CMP0069)
+ F(CMP0069) \
+ F(CMP0073)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index dfa1858..67c971f 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -3,9 +3,11 @@
#include "cmProjectCommand.h"
#include "cmsys/RegularExpression.hxx"
+#include <functional>
#include <sstream>
#include <stdio.h>
+#include "cmAlgorithms.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
@@ -69,6 +71,10 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
std::string version;
std::string description;
std::vector<std::string> languages;
+ std::function<void()> missedValueReporter;
+ auto resetReporter = [&missedValueReporter]() {
+ missedValueReporter = std::function<void()>();
+ };
enum Doing
{
DoingDescription,
@@ -85,7 +91,18 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
return true;
}
haveLanguages = true;
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
doing = DoingLanguages;
+ if (!languages.empty()) {
+ std::string msg =
+ "the following parameters must be specified after LANGUAGES "
+ "keyword: ";
+ msg += cmJoin(languages, ", ");
+ msg += '.';
+ this->Makefile->IssueMessage(cmake::WARNING, msg);
+ }
} else if (args[i] == "VERSION") {
if (haveVersion) {
this->Makefile->IssueMessage(cmake::FATAL_ERROR,
@@ -94,7 +111,17 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
return true;
}
haveVersion = true;
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
doing = DoingVersion;
+ missedValueReporter = [this, &resetReporter]() {
+ this->Makefile->IssueMessage(
+ cmake::WARNING,
+ "VERSION keyword not followed by a value or was followed by a "
+ "value that expanded to nothing.");
+ resetReporter();
+ };
} else if (args[i] == "DESCRIPTION") {
if (haveDescription) {
this->Makefile->IssueMessage(
@@ -103,23 +130,41 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
return true;
}
haveDescription = true;
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
doing = DoingDescription;
+ missedValueReporter = [this, &resetReporter]() {
+ this->Makefile->IssueMessage(
+ cmake::WARNING,
+ "DESCRIPTION keyword not followed by a value or was followed "
+ "by a value that expanded to nothing.");
+ resetReporter();
+ };
} else if (doing == DoingVersion) {
doing = DoingLanguages;
version = args[i];
+ resetReporter();
} else if (doing == DoingDescription) {
doing = DoingLanguages;
description = args[i];
+ resetReporter();
} else // doing == DoingLanguages
{
languages.push_back(args[i]);
}
}
- if (haveVersion && !haveLanguages && !languages.empty()) {
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
+
+ if ((haveVersion || haveDescription) && !haveLanguages &&
+ !languages.empty()) {
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
- "project with VERSION must use LANGUAGES before language names.");
+ "project with VERSION or DESCRIPTION must use LANGUAGES before "
+ "language names.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index 5b2b6d0..1939bd4 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -190,25 +190,32 @@ bool cmQtAutoGenerator::FileSystem::FileRead(std::string& content,
bool success = false;
{
std::lock_guard<std::mutex> lock(Mutex_);
- if (cmSystemTools::FileExists(filename)) {
+ if (cmSystemTools::FileExists(filename, true)) {
std::size_t const length = cmSystemTools::FileLength(filename);
cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
if (ifs) {
- content.resize(length);
- ifs.read(&content.front(), content.size());
- if (ifs) {
- success = true;
+ if (length > 0) {
+ content.resize(length);
+ ifs.read(&content.front(), content.size());
+ if (ifs) {
+ success = true;
+ } else {
+ content.clear();
+ if (error != nullptr) {
+ error->append("Reading from the file failed.");
+ }
+ }
} else {
+ // Readable but empty file
content.clear();
- if (error != nullptr) {
- error->append("Reading from the file failed.");
- }
+ success = true;
}
} else if (error != nullptr) {
error->append("Opening the file for reading failed.");
}
} else if (error != nullptr) {
- error->append("The file does not exist.");
+ error->append(
+ "The file does not exist, is not readable or is a directory.");
}
}
return success;
@@ -539,8 +546,8 @@ void cmQtAutoGenerator::ReadOnlyProcessT::UVExit(uv_process_t* handle,
void cmQtAutoGenerator::ReadOnlyProcessT::UVTryFinish()
{
// There still might be data in the pipes after the process has finished.
- // Therefore check if the process is finished AND all pipes are closed before
- // signaling the worker thread to continue.
+ // Therefore check if the process is finished AND all pipes are closed
+ // before signaling the worker thread to continue.
if (UVProcess_.get() == nullptr) {
if (UVPipeOut_.uv_pipe() == nullptr) {
if (UVPipeErr_.uv_pipe() == nullptr) {
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 734ac93..6137223 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -114,15 +114,12 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>(
}
if (!noMessage) {
e << "Target \"" << tgt->GetName()
- << "\" contains "
- "$<TARGET_OBJECTS> generator expression in its sources "
- "list. "
- "This content was not previously part of the SOURCES "
- "property "
- "when that property was read at configure time. Code "
- "reading "
- "that property needs to be adapted to ignore the generator "
- "expression using the string(GENEX_STRIP) command.";
+ << "\" contains $<TARGET_OBJECTS> generator expression in its "
+ "sources list. This content was not previously part of the "
+ "SOURCES property when that property was read at configure "
+ "time. Code reading that property needs to be adapted to "
+ "ignore the generator expression using the string(GENEX_STRIP) "
+ "command.";
messenger->IssueMessage(messageType, e.str(), context);
}
if (addContent) {
@@ -189,18 +186,10 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
this->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
this->BuildInterfaceIncludesAppended = false;
- // only add dependency information for library targets
- if (this->TargetTypeValue >= cmStateEnums::STATIC_LIBRARY &&
- this->TargetTypeValue <= cmStateEnums::MODULE_LIBRARY) {
- this->RecordDependencies = true;
- } else {
- this->RecordDependencies = false;
- }
-
// Check whether this is a DLL platform.
this->DLLPlatform =
- (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
+ strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
+ "") != 0;
// Check whether we are targeting an Android platform.
this->IsAndroid =
@@ -638,27 +627,11 @@ const std::vector<std::string>& cmTarget::GetLinkDirectories() const
return this->LinkDirectories;
}
-void cmTarget::ClearDependencyInformation(cmMakefile& mf,
- const std::string& target)
+void cmTarget::ClearDependencyInformation(cmMakefile& mf)
{
- // Clear the dependencies. The cache variable must exist iff we are
- // recording dependency information for this target.
- std::string depname = target;
+ std::string depname = this->GetName();
depname += "_LIB_DEPENDS";
- if (this->RecordDependencies) {
- mf.AddCacheDefinition(depname, "", "Dependencies for target",
- cmStateEnums::STATIC);
- } else {
- if (mf.GetDefinition(depname)) {
- std::string message = "Target ";
- message += target;
- message += " has dependency information when it shouldn't.\n";
- message += "Your cache is probably stale. Please remove the entry\n ";
- message += depname;
- message += "\nfrom the cache.";
- cmSystemTools::Error(message.c_str());
- }
- }
+ mf.RemoveCacheDefinition(depname);
}
std::string cmTarget::GetDebugGeneratorExpressions(
@@ -742,7 +715,8 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
}
if (cmGeneratorExpression::Find(lib) != std::string::npos ||
- (tgt && tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) ||
+ (tgt && (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) ||
(this->Name == lib)) {
return;
}
@@ -754,7 +728,7 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
this->OriginalLinkLibraries.emplace_back(lib, llt);
}
- // Add the explicit dependency information for this target. This is
+ // Add the explicit dependency information for libraries. This is
// simply a set of libraries separated by ";". There should always
// be a trailing ";". These library names are not canonical, in that
// they may be "-framework x", "-ly", "/path/libz.a", etc.
@@ -762,7 +736,10 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
// may be purposefully duplicated to handle recursive dependencies,
// and we removing one instance will break the link line. Duplicates
// will be appropriately eliminated at emit time.
- if (this->RecordDependencies) {
+ if (this->TargetTypeValue >= cmStateEnums::STATIC_LIBRARY &&
+ this->TargetTypeValue <= cmStateEnums::MODULE_LIBRARY &&
+ (this->GetPolicyStatusCMP0073() == cmPolicies::OLD ||
+ this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) {
std::string targetEntry = this->Name;
targetEntry += "_LIB_DEPENDS";
std::string dependencies;
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 56f3e3a..62c4e22 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -137,7 +137,7 @@ public:
/**
* Clear the dependency information recorded for this target, if any.
*/
- void ClearDependencyInformation(cmMakefile& mf, const std::string& target);
+ void ClearDependencyInformation(cmMakefile& mf);
void AddLinkLibrary(cmMakefile& mf, const std::string& lib,
cmTargetLinkLibraryType llt);
@@ -310,7 +310,6 @@ private:
cmTargetInternalPointer Internal;
cmStateEnums::TargetType TargetTypeValue;
bool HaveInstallRule;
- bool RecordDependencies;
bool DLLPlatform;
bool IsAndroid;
bool IsImportedTarget;
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index 9e4575a..699fff8 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -94,16 +94,6 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
return true;
}
- // OBJECT libraries are not allowed on the LHS of the command.
- if (this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::ostringstream e;
- e << "Object library target \"" << args[0] << "\" "
- << "may not link to anything.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
-
// Having a UTILITY library on the LHS is a bug.
if (this->Target->GetType() == cmStateEnums::UTILITY) {
std::ostringstream e;
@@ -401,14 +391,15 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
if (tgt && (tgt->GetType() != cmStateEnums::STATIC_LIBRARY) &&
(tgt->GetType() != cmStateEnums::SHARED_LIBRARY) &&
(tgt->GetType() != cmStateEnums::UNKNOWN_LIBRARY) &&
+ (tgt->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
(tgt->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
!tgt->IsExecutableWithExports()) {
std::ostringstream e;
e << "Target \"" << lib << "\" of type "
<< cmState::GetTargetTypeName(tgt->GetType())
<< " may not be linked into another target. One may link only to "
- "INTERFACE, STATIC or SHARED libraries, or to executables with the "
- "ENABLE_EXPORTS property set.";
+ "INTERFACE, OBJECT, STATIC or SHARED libraries, or to executables "
+ "with the ENABLE_EXPORTS property set.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index ed4a201..0fd8043 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -18,6 +18,22 @@
#include <iterator>
#include <memory> // IWYU pragma: keep
+inline void cmVisualStudio10TargetGenerator::WriteElem(const char* tag,
+ const char* val,
+ int indentLevel)
+{
+ this->WriteString("<", indentLevel);
+ (*this->BuildFileStream) << tag << ">" << val << "</" << tag << ">\n";
+}
+
+inline void cmVisualStudio10TargetGenerator::WriteElem(const char* tag,
+ std::string const& val,
+ int indentLevel)
+{
+ this->WriteString("<", indentLevel);
+ (*this->BuildFileStream) << tag << ">" << val << "</" << tag << ">\n";
+}
+
static void ConvertToWindowsSlash(std::string& s);
static std::string cmVS10EscapeXML(std::string arg)
@@ -28,6 +44,12 @@ static std::string cmVS10EscapeXML(std::string arg)
return arg;
}
+inline void cmVisualStudio10TargetGenerator::WriteElemEscapeXML(
+ const char* tag, std::string const& val, int indentLevel)
+{
+ this->WriteElem(tag, cmVS10EscapeXML(val), indentLevel);
+}
+
static std::string cmVS10EscapeQuotes(std::string arg)
{
cmSystemTools::ReplaceString(arg, "\"", "&quot;");
@@ -265,16 +287,10 @@ void cmVisualStudio10TargetGenerator::Generate()
}
(*this->BuildFileStream) << "</NsightTegraProjectRevisionNumber>\n";
// Tell newer versions to upgrade silently when loading.
- this->WriteString("<NsightTegraUpgradeOnceWithoutPrompt>"
- "true"
- "</NsightTegraUpgradeOnceWithoutPrompt>\n",
- 2);
+ this->WriteElem("NsightTegraUpgradeOnceWithoutPrompt", "true", 2);
} else {
// Require Nsight Tegra 1.6 for JCompile support.
- this->WriteString("<NsightTegraProjectRevisionNumber>"
- "7"
- "</NsightTegraProjectRevisionNumber>\n",
- 2);
+ this->WriteElem("NsightTegraProjectRevisionNumber", "7", 2);
}
this->WriteString("</PropertyGroup>\n", 1);
}
@@ -282,9 +298,7 @@ void cmVisualStudio10TargetGenerator::Generate()
if (const char* hostArch =
this->GlobalGenerator->GetPlatformToolsetHostArchitecture()) {
this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<PreferredToolArchitecture>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(hostArch)
- << "</PreferredToolArchitecture>\n";
+ this->WriteElemEscapeXML("PreferredToolArchitecture", hostArch, 2);
this->WriteString("</PropertyGroup>\n", 1);
}
@@ -292,8 +306,7 @@ void cmVisualStudio10TargetGenerator::Generate()
this->WriteProjectConfigurations();
}
this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1);
- this->WriteString("<ProjectGuid>", 2);
- (*this->BuildFileStream) << "{" << this->GUID << "}</ProjectGuid>\n";
+ this->WriteElem("ProjectGuid", "{" + this->GUID + "}", 2);
if (this->MSTools &&
this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) {
@@ -322,61 +335,45 @@ void cmVisualStudio10TargetGenerator::Generate()
this->GeneratorTarget->GetProperty("VS_SCC_PROVIDER");
if (vsProjectName && vsLocalPath && vsProvider) {
- this->WriteString("<SccProjectName>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsProjectName)
- << "</SccProjectName>\n";
- this->WriteString("<SccLocalPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsLocalPath)
- << "</SccLocalPath>\n";
- this->WriteString("<SccProvider>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsProvider)
- << "</SccProvider>\n";
+ this->WriteElemEscapeXML("SccProjectName", vsProjectName, 2);
+ this->WriteElemEscapeXML("SccLocalPath", vsLocalPath, 2);
+ this->WriteElemEscapeXML("SccProvider", vsProvider, 2);
const char* vsAuxPath =
this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH");
if (vsAuxPath) {
- this->WriteString("<SccAuxPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsAuxPath)
- << "</SccAuxPath>\n";
+ this->WriteElemEscapeXML("SccAuxPath", vsAuxPath, 2);
}
}
if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
- this->WriteString("<WinMDAssembly>true</WinMDAssembly>\n", 2);
+ this->WriteElem("WinMDAssembly", "true", 2);
}
const char* vsGlobalKeyword =
this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
if (!vsGlobalKeyword) {
- this->WriteString("<Keyword>Win32Proj</Keyword>\n", 2);
+ this->WriteElem("Keyword", "Win32Proj", 2);
} else {
- this->WriteString("<Keyword>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalKeyword)
- << "</Keyword>\n";
+ this->WriteElemEscapeXML("Keyword", vsGlobalKeyword, 2);
}
const char* vsGlobalRootNamespace =
this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
if (vsGlobalRootNamespace) {
- this->WriteString("<RootNamespace>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalRootNamespace)
- << "</RootNamespace>\n";
+ this->WriteElemEscapeXML("RootNamespace", vsGlobalRootNamespace, 2);
}
- this->WriteString("<Platform>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
- << "</Platform>\n";
+ this->WriteElemEscapeXML("Platform", this->Platform, 2);
const char* projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL");
if (!projLabel) {
projLabel = this->Name.c_str();
}
- this->WriteString("<ProjectName>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(projLabel) << "</ProjectName>\n";
+ this->WriteElemEscapeXML("ProjectName", projLabel, 2);
if (const char* targetFrameworkVersion = this->GeneratorTarget->GetProperty(
"VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
- this->WriteString("<TargetFrameworkVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetFrameworkVersion)
- << "</TargetFrameworkVersion>\n";
+ this->WriteElemEscapeXML("TargetFrameworkVersion", targetFrameworkVersion,
+ 2);
}
// Disable the project upgrade prompt that is displayed the first time a
@@ -384,9 +381,7 @@ void cmVisualStudio10TargetGenerator::Generate()
// the IDE (respected by VS 2013 and above).
if (this->GlobalGenerator->GetVersion() >=
cmGlobalVisualStudioGenerator::VS12) {
- this->WriteString("<VCProjectUpgraderObjectName>NoUpgrade"
- "</VCProjectUpgraderObjectName>\n",
- 2);
+ this->WriteElem("VCProjectUpgraderObjectName", "NoUpgrade", 2);
}
std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
@@ -437,8 +432,7 @@ void cmVisualStudio10TargetGenerator::Generate()
}
outputType += "</OutputType>\n";
this->WriteString(outputType.c_str(), 2);
- this->WriteString("<AppDesignerFolder>Properties</AppDesignerFolder>\n",
- 2);
+ this->WriteElem("AppDesignerFolder", "Properties", 2);
}
this->WriteString("</PropertyGroup>\n", 1);
@@ -635,12 +629,8 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReference(
{
this->WriteString("<Reference Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(ref) << "\">\n";
- this->WriteString("<CopyLocalSatelliteAssemblies>true"
- "</CopyLocalSatelliteAssemblies>\n",
- 3);
- this->WriteString("<ReferenceOutputAssembly>true"
- "</ReferenceOutputAssembly>\n",
- 3);
+ this->WriteElem("CopyLocalSatelliteAssemblies", "true", 3);
+ this->WriteElem("ReferenceOutputAssembly", "true", 3);
if (!hint.empty()) {
const char* privateReference = "True";
if (const char* value = this->GeneratorTarget->GetProperty(
@@ -649,10 +639,8 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReference(
privateReference = "False";
}
}
- this->WriteString("<Private>", 3);
- (*this->BuildFileStream) << privateReference << "</Private>\n";
- this->WriteString("<HintPath>", 3);
- (*this->BuildFileStream) << hint << "</HintPath>\n";
+ this->WriteElem("Private", privateReference, 3);
+ this->WriteElem("HintPath", hint, 3);
}
this->WriteDotNetReferenceCustomTags(ref);
this->WriteString("</Reference>\n", 2);
@@ -711,9 +699,8 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
(*this->BuildFileStream) << obj << "\">\n";
if (this->ProjectType != csproj) {
- this->WriteString("<DependentUpon>", 3);
std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
- (*this->BuildFileStream) << hFileName << "</DependentUpon>\n";
+ this->WriteElem("DependentUpon", hFileName, 3);
for (std::string const& i : this->Configurations) {
this->WritePlatformConfigTag("LogicalName", i, 3);
@@ -741,8 +728,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
link = cmsys::SystemTools::GetFilenameName(obj);
}
if (!link.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << link << "</Link>\n";
+ this->WriteElem("Link", link, 3);
}
}
// Determine if this is a generated resource from a .Designer.cs file
@@ -756,9 +742,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
generator = g;
}
if (!generator.empty()) {
- this->WriteString("<Generator>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(generator)
- << "</Generator>\n";
+ this->WriteElemEscapeXML("Generator", generator, 3);
if (designerResource.find(srcDir) == 0) {
designerResource = designerResource.substr(srcDir.length() + 1);
} else if (designerResource.find(binDir) == 0) {
@@ -768,9 +752,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
cmsys::SystemTools::GetFilenameName(designerResource);
}
ConvertToWindowsSlash(designerResource);
- this->WriteString("<LastGenOutput>", 3);
- (*this->BuildFileStream) << designerResource
- << "</LastGenOutput>\n";
+ this->WriteElem("LastGenOutput", designerResource, 3);
}
}
const cmPropertyMap& props = oi->GetProperties();
@@ -828,11 +810,10 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
}
if (!link.empty()) {
ConvertToWindowsSlash(link);
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << link << "</Link>\n";
+ this->WriteElem("Link", link, 3);
}
}
- this->WriteString("<SubType>Designer</SubType>\n", 3);
+ this->WriteElem("SubType", "Designer", 3);
this->WriteString("</", 2);
(*this->BuildFileStream) << xamlType << ">\n";
}
@@ -894,7 +875,7 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
for (std::string const& ri : references) {
this->WriteString("<Reference Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(ri) << "\">\n";
- this->WriteString("<IsWinMDFile>true</IsWinMDFile>\n", 3);
+ this->WriteElem("IsWinMDFile", "true", 3);
this->WriteString("</Reference>\n", 2);
}
this->WriteString("</ItemGroup>\n", 1);
@@ -909,11 +890,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurations()
for (std::string const& c : this->Configurations) {
this->WriteString("<ProjectConfiguration Include=\"", 2);
(*this->BuildFileStream) << c << "|" << this->Platform << "\">\n";
- this->WriteString("<Configuration>", 3);
- (*this->BuildFileStream) << c << "</Configuration>\n";
- this->WriteString("<Platform>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
- << "</Platform>\n";
+ this->WriteElem("Configuration", c, 3);
+ this->WriteElemEscapeXML("Platform", this->Platform, 3);
this->WriteString("</ProjectConfiguration>\n", 2);
}
this->WriteString("</ItemGroup>\n", 1);
@@ -997,9 +975,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
useOfMfcValue = "Dynamic";
}
}
- std::string mfcLine = "<UseOfMfc>";
- mfcLine += useOfMfcValue + "</UseOfMfc>\n";
- this->WriteString(mfcLine.c_str(), 2);
+ this->WriteElem("UseOfMfc", useOfMfcValue, 2);
}
if ((this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY &&
@@ -1008,25 +984,20 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
this->GlobalGenerator->TargetsWindowsPhone() ||
this->GlobalGenerator->TargetsWindowsStore() ||
this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
- this->WriteString("<CharacterSet>Unicode</CharacterSet>\n", 2);
+ this->WriteElem("CharacterSet", "Unicode", 2);
} else if (this->GeneratorTarget->GetType() <=
cmStateEnums::MODULE_LIBRARY &&
this->ClOptions[config]->UsingSBCS()) {
- this->WriteString("<CharacterSet>NotSet</CharacterSet>\n", 2);
+ this->WriteElem("CharacterSet", "NotSet", 2);
} else {
- this->WriteString("<CharacterSet>MultiByte</CharacterSet>\n", 2);
+ this->WriteElem("CharacterSet", "MultiByte", 2);
}
if (const char* toolset = gg->GetPlatformToolset()) {
- std::string pts = "<PlatformToolset>";
- pts += toolset;
- pts += "</PlatformToolset>\n";
- this->WriteString(pts.c_str(), 2);
+ this->WriteElem("PlatformToolset", toolset, 2);
}
if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
- this->WriteString("<WindowsAppContainer>true"
- "</WindowsAppContainer>\n",
- 2);
+ this->WriteElem("WindowsAppContainer", "true", 2);
}
}
@@ -1038,26 +1009,21 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
Options& o = *(this->ClOptions[config]);
if (o.IsDebug()) {
- this->WriteString("<DebugSymbols>true</DebugSymbols>\n", 2);
- this->WriteString("<DefineDebug>true</DefineDebug>\n", 2);
+ this->WriteElem("DebugSymbols", "true", 2);
+ this->WriteElem("DefineDebug", "true", 2);
}
std::string outDir = this->GeneratorTarget->GetDirectory(config) + "/";
ConvertToWindowsSlash(outDir);
- this->WriteString("<OutputPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(outDir) << "</OutputPath>\n";
+ this->WriteElemEscapeXML("OutputPath", outDir, 2);
if (o.HasFlag("Platform")) {
- this->WriteString("<PlatformTarget>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(o.GetFlag("Platform"))
- << "</PlatformTarget>\n";
+ this->WriteElemEscapeXML("PlatformTarget", o.GetFlag("Platform"), 2);
o.RemoveFlag("Platform");
}
if (const char* toolset = gg->GetPlatformToolset()) {
- this->WriteString("<PlatformToolset>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(toolset)
- << "</PlatformToolset>\n";
+ this->WriteElemEscapeXML("PlatformToolset", toolset, 2);
}
std::string postfixName = cmSystemTools::UpperCase(config);
@@ -1067,12 +1033,10 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
if (const char* postfix = this->GeneratorTarget->GetProperty(postfixName)) {
assemblyName += postfix;
}
- this->WriteString("<AssemblyName>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(assemblyName)
- << "</AssemblyName>\n";
+ this->WriteElemEscapeXML("AssemblyName", assemblyName, 2);
if (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType()) {
- this->WriteString("<StartAction>Program</StartAction>\n", 2);
+ this->WriteElem("StartAction", "Program", 2);
this->WriteString("<StartProgram>", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(outDir)
<< cmVS10EscapeXML(assemblyName)
@@ -1094,27 +1058,20 @@ void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
this->WriteString(ntv.c_str(), 2);
if (const char* minApi =
this->GeneratorTarget->GetProperty("ANDROID_API_MIN")) {
- this->WriteString("<AndroidMinAPI>", 2);
- (*this->BuildFileStream) << "android-" << cmVS10EscapeXML(minApi)
- << "</AndroidMinAPI>\n";
+ this->WriteElem("AndroidMinAPI", "android-" + cmVS10EscapeXML(minApi), 2);
}
if (const char* api = this->GeneratorTarget->GetProperty("ANDROID_API")) {
- this->WriteString("<AndroidTargetAPI>", 2);
- (*this->BuildFileStream) << "android-" << cmVS10EscapeXML(api)
- << "</AndroidTargetAPI>\n";
+ this->WriteElem("AndroidTargetAPI", "android-" + cmVS10EscapeXML(api), 2);
}
if (const char* cpuArch =
this->GeneratorTarget->GetProperty("ANDROID_ARCH")) {
- this->WriteString("<AndroidArch>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(cpuArch) << "</AndroidArch>\n";
+ this->WriteElemEscapeXML("AndroidArch", cpuArch, 2);
}
if (const char* stlType =
this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) {
- this->WriteString("<AndroidStlType>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(stlType)
- << "</AndroidStlType>\n";
+ this->WriteElemEscapeXML("AndroidStlType", stlType, 2);
}
}
@@ -1199,8 +1156,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
this->GetCSharpSourceLink(source, link);
this->WriteSource("None", source, ">\n");
if (!link.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << link << "</Link>\n";
+ this->WriteElem("Link", link, 3);
}
this->WriteString("</None>\n", 2);
this->WriteString("</ItemGroup>\n", 1);
@@ -1372,23 +1328,23 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
if (fileName == "wmappmanifest.xml") {
this->WriteString("<XML Include=\"", 2);
(*this->BuildFileStream) << oi << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
+ this->WriteElem("Filter", "Resource Files", 3);
this->WriteString("</XML>\n", 2);
} else if (cmSystemTools::GetFilenameExtension(fileName) ==
".appxmanifest") {
this->WriteString("<AppxManifest Include=\"", 2);
(*this->BuildFileStream) << oi << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
+ this->WriteElem("Filter", "Resource Files", 3);
this->WriteString("</AppxManifest>\n", 2);
} else if (cmSystemTools::GetFilenameExtension(fileName) == ".pfx") {
this->WriteString("<None Include=\"", 2);
(*this->BuildFileStream) << oi << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
+ this->WriteElem("Filter", "Resource Files", 3);
this->WriteString("</None>\n", 2);
} else {
this->WriteString("<Image Include=\"", 2);
(*this->BuildFileStream) << oi << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
+ this->WriteElem("Filter", "Resource Files", 3);
this->WriteString("</Image>\n", 2);
}
}
@@ -1404,7 +1360,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
this->WriteString("<EmbeddedResource Include=\"", 2);
ConvertToWindowsSlash(obj);
(*this->BuildFileStream) << cmVS10EscapeXML(obj) << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
+ this->WriteElem("Filter", "Resource Files", 3);
this->WriteString("</EmbeddedResource>\n", 2);
}
this->WriteString("</ItemGroup>\n", 1);
@@ -1423,10 +1379,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
(*this->BuildFileStream) << name << "\">\n";
std::string guidName = "SG_Filter_";
guidName += name;
- this->WriteString("<UniqueIdentifier>", 3);
std::string guid = this->GlobalGenerator->GetGUID(guidName);
- (*this->BuildFileStream) << "{" << guid << "}"
- << "</UniqueIdentifier>\n";
+ this->WriteElem("UniqueIdentifier", "{" + guid + "}", 3);
this->WriteString("</Filter>\n", 2);
}
}
@@ -1434,10 +1388,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
if (!resxObjs.empty() || !this->AddedFiles.empty()) {
this->WriteString("<Filter Include=\"Resource Files\">\n", 2);
std::string guidName = "SG_Filter_Resource Files";
- this->WriteString("<UniqueIdentifier>", 3);
std::string guid = this->GlobalGenerator->GetGUID(guidName);
- (*this->BuildFileStream) << "{" << guid << "}"
- << "</UniqueIdentifier>\n";
+ this->WriteElem("UniqueIdentifier", "{" + guid + "}", 3);
this->WriteString("<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;", 3);
(*this->BuildFileStream) << "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;";
(*this->BuildFileStream) << "mfcribbon-ms</Extensions>\n";
@@ -1508,8 +1460,7 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources(
(*this->BuildFileStream) << name << " Include=\"" << cmVS10EscapeXML(path);
if (!filter.empty()) {
(*this->BuildFileStream) << "\">\n";
- this->WriteString("<Filter>", 3);
- (*this->BuildFileStream) << filter << "</Filter>\n";
+ this->WriteElem("Filter", filter, 3);
this->WriteString("</", 2);
(*this->BuildFileStream) << name << ">\n";
} else {
@@ -1524,13 +1475,12 @@ void cmVisualStudio10TargetGenerator::WriteHeaderSource(cmSourceFile const* sf)
std::string const& fileName = sf->GetFullPath();
if (this->IsResxHeader(fileName)) {
this->WriteSource("ClInclude", sf, ">\n");
- this->WriteString("<FileType>CppForm</FileType>\n", 3);
+ this->WriteElem("FileType", "CppForm", 3);
this->WriteString("</ClInclude>\n", 2);
} else if (this->IsXamlHeader(fileName)) {
this->WriteSource("ClInclude", sf, ">\n");
- this->WriteString("<DependentUpon>", 3);
std::string xamlFileName = fileName.substr(0, fileName.find_last_of("."));
- (*this->BuildFileStream) << xamlFileName << "</DependentUpon>\n";
+ this->WriteElem("DependentUpon", xamlFileName, 3);
this->WriteString("</ClInclude>\n", 2);
} else {
this->WriteSource("ClInclude", sf);
@@ -1725,19 +1675,13 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
}
}
if (!shaderType.empty()) {
- this->WriteString("<ShaderType>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderType)
- << "</ShaderType>\n";
+ this->WriteElemEscapeXML("ShaderType", shaderType, 3);
}
if (!shaderEntryPoint.empty()) {
- this->WriteString("<EntryPointName>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderEntryPoint)
- << "</EntryPointName>\n";
+ this->WriteElemEscapeXML("EntryPointName", shaderEntryPoint, 3);
}
if (!shaderModel.empty()) {
- this->WriteString("<ShaderModel>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderModel)
- << "</ShaderModel>\n";
+ this->WriteElemEscapeXML("ShaderModel", shaderModel, 3);
}
if (!outputHeaderFile.empty()) {
for (size_t i = 0; i != this->Configurations.size(); ++i) {
@@ -1762,47 +1706,33 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
}
}
if (!shaderEnableDebug.empty()) {
- this->WriteString("<EnableDebuggingInformation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderEnableDebug)
- << "</EnableDebuggingInformation>\n";
+ this->WriteElemEscapeXML("EnableDebuggingInformation", shaderEnableDebug,
+ 3);
}
if (!shaderDisableOptimizations.empty()) {
- this->WriteString("<DisableOptimizations>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderDisableOptimizations)
- << "</DisableOptimizations>\n";
+ this->WriteElemEscapeXML("DisableOptimizations",
+ shaderDisableOptimizations, 3);
}
if (!shaderAdditionalFlags.empty()) {
- this->WriteString("<AdditionalOptions>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderAdditionalFlags)
- << "</AdditionalOptions>\n";
+ this->WriteElemEscapeXML("AdditionalOptions", shaderAdditionalFlags, 3);
}
if (!settingsGenerator.empty()) {
- this->WriteString("<Generator>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(settingsGenerator)
- << "</Generator>\n";
+ this->WriteElemEscapeXML("Generator", settingsGenerator, 3);
}
if (!settingsLastGenOutput.empty()) {
- this->WriteString("<LastGenOutput>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(settingsLastGenOutput)
- << "</LastGenOutput>\n";
+ this->WriteElemEscapeXML("LastGenOutput", settingsLastGenOutput, 3);
}
if (!sourceLink.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(sourceLink) << "</Link>\n";
+ this->WriteElemEscapeXML("Link", sourceLink, 3);
}
if (!subType.empty()) {
- this->WriteString("<SubType>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(subType) << "</SubType>\n";
+ this->WriteElemEscapeXML("SubType", subType, 3);
}
if (!copyToOutDir.empty()) {
- this->WriteString("<CopyToOutputDirectory>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(copyToOutDir)
- << "</CopyToOutputDirectory>\n";
+ this->WriteElemEscapeXML("CopyToOutputDirectory", copyToOutDir, 3);
}
if (!includeInVsix.empty()) {
- this->WriteString("<IncludeInVSIX>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(includeInVsix)
- << "</IncludeInVSIX>\n";
+ this->WriteElemEscapeXML("IncludeInVSIX", includeInVsix, 3);
}
// write source file specific tags
this->WriteCSharpSourceProperties(sourceFileTags);
@@ -2057,13 +1987,9 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
firstString = "";
hasFlags = true;
if (lang == "CUDA") {
- this->WriteString("<CompileOut>", 3);
- (*this->BuildFileStream) << "$(IntDir)/" << objectName
- << "</CompileOut>\n";
+ this->WriteElem("CompileOut", "$(IntDir)/" + objectName, 3);
} else {
- this->WriteString("<ObjectFileName>", 3);
- (*this->BuildFileStream) << "$(IntDir)/" << objectName
- << "</ObjectFileName>\n";
+ this->WriteElem("ObjectFileName", "$(IntDir)/" + objectName, 3);
}
}
for (std::string const& config : this->Configurations) {
@@ -2163,10 +2089,9 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
(*this->BuildFileStream) << firstString;
firstString = ""; // only do firstString once
hasFlags = true;
- this->WriteString("<DependentUpon>", 3);
const std::string& fileName = source->GetFullPath();
std::string xamlFileName = fileName.substr(0, fileName.find_last_of("."));
- (*this->BuildFileStream) << xamlFileName << "</DependentUpon>\n";
+ this->WriteElem("DependentUpon", xamlFileName, 3);
}
if (this->ProjectType == csproj) {
std::string f = source->GetFullPath();
@@ -2214,9 +2139,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
}
this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<_ProjectFileVersion>10.0.20506.1"
- "</_ProjectFileVersion>\n",
- 2);
+ this->WriteElem("_ProjectFileVersion", "10.0.20506.1", 2);
for (std::string const& config : this->Configurations) {
if (ttype >= cmStateEnums::UTILITY) {
this->WritePlatformConfigTag("IntDir", config, 2);
@@ -2521,9 +2444,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
if (this->NsightTegra) {
if (const char* processMax =
this->GeneratorTarget->GetProperty("ANDROID_PROCESS_MAX")) {
- this->WriteString("<ProcessMax>", 3);
- *this->BuildFileStream << cmVS10EscapeXML(processMax)
- << "</ProcessMax>\n";
+ this->WriteElemEscapeXML("ProcessMax", processMax, 3);
}
}
@@ -2531,12 +2452,9 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
cmsys::RegularExpression clangToolset("v[0-9]+_clang_.*");
const char* toolset = this->GlobalGenerator->GetPlatformToolset();
if (toolset && clangToolset.find(toolset)) {
- this->WriteString("<ObjectFileName>"
- "$(IntDir)%(filename).obj"
- "</ObjectFileName>\n",
- 3);
+ this->WriteElem("ObjectFileName", "$(IntDir)%(filename).obj", 3);
} else {
- this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3);
+ this->WriteElem("ObjectFileName", "$(IntDir)", 3);
}
// If not in debug mode, write the DebugInformationFormat field
@@ -2552,9 +2470,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
if (!pdb.empty()) {
ConvertToWindowsSlash(pdb);
- this->WriteString("<ProgramDataBaseFileName>", 3);
- *this->BuildFileStream << cmVS10EscapeXML(pdb)
- << "</ProgramDataBaseFileName>\n";
+ this->WriteElemEscapeXML("ProgramDataBaseFileName", pdb, 3);
}
}
@@ -2973,9 +2889,7 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions(
if (this->GlobalGenerator->TargetsWindowsPhone() ||
this->GlobalGenerator->TargetsWindowsStore()) {
this->WriteString("<Link>\n", 2);
- this->WriteString("<GenerateWindowsMetadata>false"
- "</GenerateWindowsMetadata>\n",
- 3);
+ this->WriteElem("GenerateWindowsMetadata", "false", 3);
this->WriteString("</Link>\n", 2);
}
}
@@ -3026,32 +2940,28 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
{
std::string antBuildPath = rootDir;
this->WriteString("<AntBuild>\n", 2);
- this->WriteString("<AntBuildPath>", 3);
ConvertToWindowsSlash(antBuildPath);
- (*this->BuildFileStream) << cmVS10EscapeXML(antBuildPath)
- << "</AntBuildPath>\n";
+ this->WriteElemEscapeXML("AntBuildPath", antBuildPath, 3);
}
if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_SKIP_ANT_STEP")) {
- this->WriteString("<SkipAntStep>true</SkipAntStep>\n", 3);
+ this->WriteElem("SkipAntStep", "true", 3);
}
if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_PROGUARD")) {
- this->WriteString("<EnableProGuard>true</EnableProGuard>\n", 3);
+ this->WriteElem("EnableProGuard", "true", 3);
}
if (const char* proGuardConfigLocation =
this->GeneratorTarget->GetProperty("ANDROID_PROGUARD_CONFIG_PATH")) {
- this->WriteString("<ProGuardConfigLocation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(proGuardConfigLocation)
- << "</ProGuardConfigLocation>\n";
+ this->WriteElemEscapeXML("ProGuardConfigLocation", proGuardConfigLocation,
+ 3);
}
if (const char* securePropertiesLocation =
this->GeneratorTarget->GetProperty("ANDROID_SECURE_PROPS_PATH")) {
- this->WriteString("<SecurePropertiesLocation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(securePropertiesLocation)
- << "</SecurePropertiesLocation>\n";
+ this->WriteElemEscapeXML("SecurePropertiesLocation",
+ securePropertiesLocation, 3);
}
if (const char* nativeLibDirectoriesExpression =
@@ -3061,9 +2971,7 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
ge.Parse(nativeLibDirectoriesExpression);
std::string nativeLibDirs =
cge->Evaluate(this->LocalGenerator, configName);
- this->WriteString("<NativeLibDirectories>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(nativeLibDirs)
- << "</NativeLibDirectories>\n";
+ this->WriteElemEscapeXML("NativeLibDirectories", nativeLibDirs, 3);
}
if (const char* nativeLibDependenciesExpression =
@@ -3074,16 +2982,12 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
ge.Parse(nativeLibDependenciesExpression);
std::string nativeLibDeps =
cge->Evaluate(this->LocalGenerator, configName);
- this->WriteString("<NativeLibDependencies>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(nativeLibDeps)
- << "</NativeLibDependencies>\n";
+ this->WriteElemEscapeXML("NativeLibDependencies", nativeLibDeps, 3);
}
if (const char* javaSourceDir =
this->GeneratorTarget->GetProperty("ANDROID_JAVA_SOURCE_DIR")) {
- this->WriteString("<JavaSourceDir>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(javaSourceDir)
- << "</JavaSourceDir>\n";
+ this->WriteElemEscapeXML("JavaSourceDir", javaSourceDir, 3);
}
if (const char* jarDirectoriesExpression =
@@ -3093,31 +2997,23 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
ge.Parse(jarDirectoriesExpression);
std::string jarDirectories =
cge->Evaluate(this->LocalGenerator, configName);
- this->WriteString("<JarDirectories>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(jarDirectories)
- << "</JarDirectories>\n";
+ this->WriteElemEscapeXML("JarDirectories", jarDirectories, 3);
}
if (const char* jarDeps =
this->GeneratorTarget->GetProperty("ANDROID_JAR_DEPENDENCIES")) {
- this->WriteString("<JarDependencies>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(jarDeps)
- << "</JarDependencies>\n";
+ this->WriteElemEscapeXML("JarDependencies", jarDeps, 3);
}
if (const char* assetsDirectories =
this->GeneratorTarget->GetProperty("ANDROID_ASSETS_DIRECTORIES")) {
- this->WriteString("<AssetsDirectories>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(assetsDirectories)
- << "</AssetsDirectories>\n";
+ this->WriteElemEscapeXML("AssetsDirectories", assetsDirectories, 3);
}
{
std::string manifest_xml = rootDir + "/AndroidManifest.xml";
ConvertToWindowsSlash(manifest_xml);
- this->WriteString("<AndroidManifestLocation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(manifest_xml)
- << "</AndroidManifestLocation>\n";
+ this->WriteElemEscapeXML("AndroidManifestLocation", manifest_xml, 3);
}
if (const char* antAdditionalOptions =
@@ -3335,7 +3231,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
this->GeneratorTarget->GetModuleDefinitionInfo(config);
if (mdi && !mdi->DefFile.empty()) {
- linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile.c_str());
+ linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile);
}
linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries",
"%(IgnoreSpecificDefaultLibraries)");
@@ -3418,8 +3314,7 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(
if (!this->GlobalGenerator->NeedLinkLibraryDependencies(
this->GeneratorTarget)) {
this->WriteString("<ProjectReference>\n", 2);
- this->WriteString(
- "<LinkLibraryDependencies>false</LinkLibraryDependencies>\n", 3);
+ this->WriteElem("LinkLibraryDependencies", "false", 3);
this->WriteString("</ProjectReference>\n", 2);
}
}
@@ -3513,15 +3408,11 @@ void cmVisualStudio10TargetGenerator::WriteMidlOptions(
this->WriteString("%(AdditionalIncludeDirectories)"
"</AdditionalIncludeDirectories>\n",
0);
- this->WriteString("<OutputDirectory>$(ProjectDir)/$(IntDir)"
- "</OutputDirectory>\n",
- 3);
- this->WriteString("<HeaderFileName>%(Filename).h</HeaderFileName>\n", 3);
- this->WriteString("<TypeLibraryName>%(Filename).tlb</TypeLibraryName>\n", 3);
- this->WriteString("<InterfaceIdentifierFileName>"
- "%(Filename)_i.c</InterfaceIdentifierFileName>\n",
- 3);
- this->WriteString("<ProxyFileName>%(Filename)_p.c</ProxyFileName>\n", 3);
+ this->WriteElem("OutputDirectory", "$(ProjectDir)/$(IntDir)", 3);
+ this->WriteElem("HeaderFileName", "%(Filename).h", 3);
+ this->WriteElem("TypeLibraryName", "%(Filename).tlb", 3);
+ this->WriteElem("InterfaceIdentifierFileName", "%(Filename)_i.c", 3);
+ this->WriteElem("ProxyFileName", "%(Filename)_p.c", 3);
this->WriteString("</Midl>\n", 2);
}
@@ -3613,8 +3504,7 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
}
comment = cmVS10EscapeComment(comment);
if (this->ProjectType != csproj) {
- this->WriteString("<Message>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(comment) << "</Message>\n";
+ this->WriteElemEscapeXML("Message", comment, 3);
this->WriteString("<Command>", 3);
} else {
std::string strippedComment = comment;
@@ -3667,17 +3557,13 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
}
ConvertToWindowsSlash(path);
(*this->BuildFileStream) << cmVS10EscapeXML(path) << "\">\n";
- this->WriteString("<Project>", 3);
- (*this->BuildFileStream) << "{" << this->GlobalGenerator->GetGUID(name)
- << "}";
- (*this->BuildFileStream) << "</Project>\n";
- this->WriteString("<Name>", 3);
- (*this->BuildFileStream) << name << "</Name>\n";
+ this->WriteElem("Project",
+ "{" + this->GlobalGenerator->GetGUID(name) + "}", 3);
+ this->WriteElem("Name", name, 3);
this->WriteDotNetReferenceCustomTags(name);
if (csproj == this->ProjectType) {
if (!this->GlobalGenerator->TargetCanBeReferenced(dt)) {
- this->WriteString(
- "<ReferenceOutputAssembly>false</ReferenceOutputAssembly>\n", 3);
+ this->WriteElem("ReferenceOutputAssembly", "false", 3);
}
}
this->WriteString("</ProjectReference>\n", 2);
@@ -3807,14 +3693,12 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
ConvertToWindowsSlash(artifactDir);
this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<AppxPackageArtifactsDir>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(artifactDir)
- << "\\</AppxPackageArtifactsDir>\n";
- this->WriteString("<ProjectPriFullPath>", 2);
+ this->WriteElemEscapeXML("AppxPackageArtifactsDir", artifactDir + "\\",
+ 2);
std::string resourcePriFile =
this->DefaultArtifactDir + "/resources.pri";
ConvertToWindowsSlash(resourcePriFile);
- (*this->BuildFileStream) << resourcePriFile << "</ProjectPriFullPath>\n";
+ this->WriteElem("ProjectPriFullPath", resourcePriFile, 2);
// If we are missing files and we don't have a certificate and
// aren't targeting WP8.0, add a default certificate
@@ -3828,26 +3712,18 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
this->AddedFiles.push_back(pfxFile);
}
- this->WriteString("<", 2);
- (*this->BuildFileStream) << "PackageCertificateKeyFile>" << pfxFile
- << "</PackageCertificateKeyFile>\n";
+ this->WriteElem("PackageCertificateKeyFile", pfxFile, 2);
std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
if (!thumb.empty()) {
- this->WriteString("<PackageCertificateThumbprint>", 2);
- (*this->BuildFileStream) << thumb
- << "</PackageCertificateThumbprint>\n";
+ this->WriteElem("PackageCertificateThumbprint", thumb, 2);
}
this->WriteString("</PropertyGroup>\n", 1);
} else if (!pfxFile.empty()) {
this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<", 2);
- (*this->BuildFileStream) << "PackageCertificateKeyFile>" << pfxFile
- << "</PackageCertificateKeyFile>\n";
+ this->WriteElem("PackageCertificateKeyFile", pfxFile, 2);
std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
if (!thumb.empty()) {
- this->WriteString("<PackageCertificateThumbprint>", 2);
- (*this->BuildFileStream) << thumb
- << "</PackageCertificateThumbprint>\n";
+ this->WriteElem("PackageCertificateThumbprint", thumb, 2);
}
this->WriteString("</PropertyGroup>\n", 1);
}
@@ -3895,45 +3771,29 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings()
bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore();
std::string const& v = this->GlobalGenerator->GetSystemVersion();
if (isWindowsPhone || isWindowsStore) {
- this->WriteString("<ApplicationType>", 2);
- (*this->BuildFileStream)
- << (isWindowsPhone ? "Windows Phone" : "Windows Store")
- << "</ApplicationType>\n";
- this->WriteString("<DefaultLanguage>en-US"
- "</DefaultLanguage>\n",
- 2);
+ this->WriteElem("ApplicationType",
+ (isWindowsPhone ? "Windows Phone" : "Windows Store"), 2);
+ this->WriteElem("DefaultLanguage", "en-US", 2);
if (cmHasLiteralPrefix(v, "10.0")) {
- this->WriteString("<ApplicationTypeRevision>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML("10.0")
- << "</ApplicationTypeRevision>\n";
+ this->WriteElemEscapeXML("ApplicationTypeRevision", "10.0", 2);
// Visual Studio 14.0 is necessary for building 10.0 apps
- this->WriteString("<MinimumVisualStudioVersion>14.0"
- "</MinimumVisualStudioVersion>\n",
- 2);
+ this->WriteElem("MinimumVisualStudioVersion", "14.0", 2);
if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
isAppContainer = true;
}
} else if (v == "8.1") {
- this->WriteString("<ApplicationTypeRevision>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(v)
- << "</ApplicationTypeRevision>\n";
+ this->WriteElemEscapeXML("ApplicationTypeRevision", v, 2);
// Visual Studio 12.0 is necessary for building 8.1 apps
- this->WriteString("<MinimumVisualStudioVersion>12.0"
- "</MinimumVisualStudioVersion>\n",
- 2);
+ this->WriteElem("MinimumVisualStudioVersion", "12.0", 2);
if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
isAppContainer = true;
}
} else if (v == "8.0") {
- this->WriteString("<ApplicationTypeRevision>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(v)
- << "</ApplicationTypeRevision>\n";
+ this->WriteElemEscapeXML("ApplicationTypeRevision", v, 2);
// Visual Studio 11.0 is necessary for building 8.0 apps
- this->WriteString("<MinimumVisualStudioVersion>11.0"
- "</MinimumVisualStudioVersion>\n",
- 2);
+ this->WriteElem("MinimumVisualStudioVersion", "11.0", 2);
if (isWindowsStore &&
this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
@@ -3941,52 +3801,42 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings()
} else if (isWindowsPhone &&
this->GeneratorTarget->GetType() ==
cmStateEnums::EXECUTABLE) {
- this->WriteString("<XapOutputs>true</XapOutputs>\n", 2);
- this->WriteString("<XapFilename>", 2);
- (*this->BuildFileStream)
- << cmVS10EscapeXML(this->Name)
- << "_$(Configuration)_$(Platform).xap</XapFilename>\n";
+ this->WriteElem("XapOutputs", "true", 2);
+ this->WriteElem("XapFilename", cmVS10EscapeXML(this->Name) +
+ "_$(Configuration)_$(Platform).xap",
+ 2);
}
}
}
if (isAppContainer) {
- this->WriteString("<AppContainerApplication>true"
- "</AppContainerApplication>\n",
- 2);
+ this->WriteElem("AppContainerApplication", "true", 2);
} else if (this->Platform == "ARM64") {
- this->WriteString("<WindowsSDKDesktopARM64Support>true"
- "</WindowsSDKDesktopARM64Support>\n",
- 2);
+ this->WriteElem("WindowsSDKDesktopARM64Support", "true", 2);
} else if (this->Platform == "ARM") {
- this->WriteString("<WindowsSDKDesktopARMSupport>true"
- "</WindowsSDKDesktopARMSupport>\n",
- 2);
+ this->WriteElem("WindowsSDKDesktopARMSupport", "true", 2);
}
std::string const& targetPlatformVersion =
gg->GetWindowsTargetPlatformVersion();
if (!targetPlatformVersion.empty()) {
- this->WriteString("<WindowsTargetPlatformVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion)
- << "</WindowsTargetPlatformVersion>\n";
+ this->WriteElemEscapeXML("WindowsTargetPlatformVersion",
+ targetPlatformVersion, 2);
}
const char* targetPlatformMinVersion = this->GeneratorTarget->GetProperty(
"VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION");
if (targetPlatformMinVersion) {
- this->WriteString("<WindowsTargetPlatformMinVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformMinVersion)
- << "</WindowsTargetPlatformMinVersion>\n";
+ this->WriteElemEscapeXML("WindowsTargetPlatformMinVersion",
+ targetPlatformMinVersion, 2);
} else if (isWindowsStore && cmHasLiteralPrefix(v, "10.0")) {
// If the min version is not set, then use the TargetPlatformVersion
if (!targetPlatformVersion.empty()) {
- this->WriteString("<WindowsTargetPlatformMinVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion)
- << "</WindowsTargetPlatformMinVersion>\n";
+ this->WriteElemEscapeXML("WindowsTargetPlatformMinVersion",
+ targetPlatformVersion, 2);
}
}
// Added IoT Startup Task support
if (this->GeneratorTarget->GetPropertyAsBool("VS_IOT_STARTUP_TASK")) {
- this->WriteString("<ContainsStartupTask>true</ContainsStartupTask>\n", 2);
+ this->WriteElem("ContainsStartupTask", "true", 2);
}
}
@@ -4117,7 +3967,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80()
ConvertToWindowsSlash(sourceFile);
this->WriteString("<Xml Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(sourceFile) << "\">\n";
- this->WriteString("<SubType>Designer</SubType>\n", 3);
+ this->WriteElem("SubType", "Designer", 3);
this->WriteString("</Xml>\n", 2);
this->AddedFiles.push_back(sourceFile);
@@ -4395,7 +4245,7 @@ void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
ConvertToWindowsSlash(sourceFile);
this->WriteString("<AppxManifest Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(sourceFile) << "\">\n";
- this->WriteString("<SubType>Designer</SubType>\n", 3);
+ this->WriteElem("SubType", "Designer", 3);
this->WriteString("</AppxManifest>\n", 2);
this->AddedFiles.push_back(sourceFile);
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 124db4e..64121ed 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -55,6 +55,10 @@ private:
std::string ConvertPath(std::string const& path, bool forceRelative);
void WriteString(const char* line, int indentLevel);
+ void WriteElem(const char* tag, const char* val, int indentLevel);
+ void WriteElem(const char* tag, std::string const& val, int indentLevel);
+ void WriteElemEscapeXML(const char* tag, std::string const& val,
+ int indentLevel);
void WriteProjectConfigurations();
void WriteProjectConfigurationValues();
void WriteMSToolConfigurationValues(std::string const& config);
diff --git a/Source/cmWorkingDirectory.cxx b/Source/cmWorkingDirectory.cxx
index 99c9ba8..816f104 100644
--- a/Source/cmWorkingDirectory.cxx
+++ b/Source/cmWorkingDirectory.cxx
@@ -4,10 +4,12 @@
#include "cmSystemTools.h"
+#include <cerrno>
+
cmWorkingDirectory::cmWorkingDirectory(std::string const& newdir)
{
this->OldDir = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(newdir);
+ this->SetDirectory(newdir);
}
cmWorkingDirectory::~cmWorkingDirectory()
@@ -15,10 +17,20 @@ cmWorkingDirectory::~cmWorkingDirectory()
this->Pop();
}
+bool cmWorkingDirectory::SetDirectory(std::string const& newdir)
+{
+ if (cmSystemTools::ChangeDirectory(newdir) == 0) {
+ this->ResultCode = 0;
+ return true;
+ }
+ this->ResultCode = errno;
+ return false;
+}
+
void cmWorkingDirectory::Pop()
{
if (!this->OldDir.empty()) {
- cmSystemTools::ChangeDirectory(this->OldDir);
+ this->SetDirectory(this->OldDir);
this->OldDir.clear();
}
}
diff --git a/Source/cmWorkingDirectory.h b/Source/cmWorkingDirectory.h
index aff9267..1f18ce7 100644
--- a/Source/cmWorkingDirectory.h
+++ b/Source/cmWorkingDirectory.h
@@ -9,6 +9,12 @@
/** \class cmWorkingDirectory
* \brief An RAII class to manipulate the working directory.
+ *
+ * The current working directory is set to the location given to the
+ * constructor. The working directory can be changed again as needed
+ * by calling SetDirectory(). When the object is destroyed, the destructor
+ * will restore the working directory to what it was when the object was
+ * created, regardless of any calls to SetDirectory() in the meantime.
*/
class cmWorkingDirectory
{
@@ -16,10 +22,21 @@ public:
cmWorkingDirectory(std::string const& newdir);
~cmWorkingDirectory();
+ bool SetDirectory(std::string const& newdir);
void Pop();
+ bool Failed() const { return ResultCode != 0; }
+
+ /** \return 0 if the last attempt to set the working directory was
+ * successful. If it failed, the value returned will be the
+ * \c errno value associated with the failure. A description
+ * of the error code can be obtained by passing the result
+ * to \c std::strerror().
+ */
+ int GetLastResult() const { return ResultCode; }
private:
std::string OldDir;
+ int ResultCode;
};
#endif
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index f4f4a15..323bcf6 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -98,13 +98,13 @@
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include <cstring>
#include <iostream>
#include <iterator>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <utility>
namespace {
@@ -2209,6 +2209,15 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
{
// now run cmake on the CMakeLists file
cmWorkingDirectory workdir(destPath);
+ if (workdir.Failed()) {
+ // We created the directory and we were able to copy the CMakeLists.txt
+ // file to it, so we wouldn't expect to get here unless the default
+ // permissions are questionable or some other process has deleted the
+ // directory
+ std::cerr << "Failed to change to directory " << destPath << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl;
+ return 1;
+ }
std::vector<std::string> args2;
args2.push_back(args[0]);
args2.push_back(destPath);
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index c0154c8..4fc176b 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -922,7 +922,7 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
# Set up include usage requirement
IF(COMMAND TARGET_INCLUDE_DIRECTORIES)
TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_INTERFACE} INTERFACE
- $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
+ $<BUILD_INTERFACE:${KWSYS_HEADER_ROOT}>)
IF(KWSYS_INSTALL_INCLUDE_DIR)
TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_INTERFACE} INTERFACE
$<INSTALL_INTERFACE:${KWSYS_INSTALL_INCLUDE_DIR}>)
@@ -976,7 +976,7 @@ IF(KWSYS_ENABLE_C AND KWSYS_C_SRCS)
# Set up include usage requirement
IF(COMMAND TARGET_INCLUDE_DIRECTORIES)
TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_C_INTERFACE} INTERFACE
- $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
+ $<BUILD_INTERFACE:${KWSYS_HEADER_ROOT}>)
IF(KWSYS_INSTALL_INCLUDE_DIR)
TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_C_INTERFACE} INTERFACE
$<INSTALL_INTERFACE:${KWSYS_INSTALL_INCLUDE_DIR}>)
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 7503469..2b9d7b1 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -121,7 +121,11 @@ typedef int siginfo_t;
#if defined(KWSYS_SYS_HAS_IFADDRS_H)
#include <ifaddrs.h>
#include <net/if.h>
-#if !defined(__LSB_VERSION__) /* LSB has no getifaddrs */
+#if defined(__LSB_VERSION__)
+/* LSB has no getifaddrs */
+#elif defined(__ANDROID_API__) && __ANDROID_API__ < 24
+/* Android has no getifaddrs prior to API 24. */
+#else
#define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
#endif
#endif
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 38910c8..106afe5 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -27,7 +27,6 @@
#include <iostream>
#include <set>
#include <sstream>
-#include <utility>
#include <vector>
// Work-around CMake dependency scanning limitation. This must
@@ -3254,7 +3253,7 @@ std::string SystemTools::CollapseFullPath(const std::string& in_path,
SystemTools::CheckTranslationPath(newPath);
#ifdef _WIN32
- newPath = SystemTools::GetActualCaseForPath(newPath);
+ newPath = SystemTools::GetActualCaseForPathCached(newPath);
SystemTools::ConvertToUnixSlashes(newPath);
#endif
// Return the reconstructed path.
@@ -3342,7 +3341,7 @@ std::string SystemTools::RelativePath(const std::string& local,
}
#ifdef _WIN32
-static std::pair<std::string, bool> GetCasePathName(std::string const& pathIn)
+static std::string GetCasePathName(std::string const& pathIn)
{
std::string casePath;
std::vector<std::string> path_components;
@@ -3351,7 +3350,7 @@ static std::pair<std::string, bool> GetCasePathName(std::string const& pathIn)
{
// Relative paths cannot be converted.
casePath = pathIn;
- return std::make_pair(casePath, false);
+ return casePath;
}
// Start with root component.
@@ -3403,7 +3402,7 @@ static std::pair<std::string, bool> GetCasePathName(std::string const& pathIn)
casePath += path_components[idx];
}
- return std::make_pair(casePath, converting);
+ return casePath;
}
#endif
@@ -3412,22 +3411,27 @@ std::string SystemTools::GetActualCaseForPath(const std::string& p)
#ifndef _WIN32
return p;
#else
+ return GetCasePathName(p);
+#endif
+}
+
+#ifdef _WIN32
+std::string SystemTools::GetActualCaseForPathCached(std::string const& p)
+{
// Check to see if actual case has already been called
// for this path, and the result is stored in the PathCaseMap
SystemToolsPathCaseMap::iterator i = SystemTools::PathCaseMap->find(p);
if (i != SystemTools::PathCaseMap->end()) {
return i->second;
}
- std::pair<std::string, bool> casePath = GetCasePathName(p);
- if (casePath.first.size() > MAX_PATH) {
- return casePath.first;
- }
- if (casePath.second) {
- (*SystemTools::PathCaseMap)[p] = casePath.first;
+ std::string casePath = GetCasePathName(p);
+ if (casePath.size() > MAX_PATH) {
+ return casePath;
}
- return casePath.first;
-#endif
+ (*SystemTools::PathCaseMap)[p] = casePath;
+ return casePath;
}
+#endif
const char* SystemTools::SplitPathRootComponent(const std::string& p,
std::string* root)
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index 719d45c..e79e3fc 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -988,6 +988,7 @@ private:
*/
static SystemToolsTranslationMap* TranslationMap;
#ifdef _WIN32
+ static std::string GetActualCaseForPathCached(std::string const& path);
static SystemToolsPathCaseMap* PathCaseMap;
static SystemToolsEnvMap* EnvMap;
#endif