summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/CMakeVersion.cmake4
-rw-r--r--Source/CMakeVersionCompute.cmake7
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.cxx16
-rw-r--r--Source/CPack/cmCPackGenerator.cxx11
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx22
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx25
-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/Checks/Curses.cmake41
-rw-r--r--Source/Checks/Curses/CMakeLists.txt25
-rw-r--r--Source/Checks/Curses/CheckCurses.c15
-rw-r--r--Source/CursesDialog/cmCursesStandardIncludes.h13
-rw-r--r--Source/cmAffinity.cxx62
-rw-r--r--Source/cmAffinity.h12
-rw-r--r--Source/cmCMakeMinimumRequired.cxx72
-rw-r--r--Source/cmCMakeMinimumRequired.h2
-rw-r--r--Source/cmCMakePolicyCommand.cxx19
-rw-r--r--Source/cmCTest.h2
-rw-r--r--Source/cmCacheManager.cxx16
-rw-r--r--Source/cmComputeLinkInformation.cxx45
-rw-r--r--Source/cmComputeLinkInformation.h30
-rw-r--r--Source/cmComputeTargetDepends.cxx6
-rw-r--r--Source/cmDepends.cxx7
-rw-r--r--Source/cmDepends.h6
-rw-r--r--Source/cmDependsC.cxx11
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.cxx3
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.h6
-rw-r--r--Source/cmExportBuildFileGenerator.cxx33
-rw-r--r--Source/cmExportBuildFileGenerator.h3
-rw-r--r--Source/cmExportCommand.cxx11
-rw-r--r--Source/cmExportFileGenerator.cxx46
-rw-r--r--Source/cmExportFileGenerator.h8
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.cxx3
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.h6
-rw-r--r--Source/cmExportInstallFileGenerator.cxx28
-rw-r--r--Source/cmExportInstallFileGenerator.h4
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx2
-rw-r--r--Source/cmExtraCodeLiteGenerator.cxx11
-rw-r--r--Source/cmFileCommand.cxx184
-rw-r--r--Source/cmFileCommand.h1
-rw-r--r--Source/cmFileTimeComparison.h4
-rw-r--r--Source/cmFindBase.cxx22
-rw-r--r--Source/cmFindCommon.cxx7
-rw-r--r--Source/cmFindCommon.h3
-rw-r--r--Source/cmFindPackageCommand.cxx70
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h12
-rw-r--r--Source/cmGeneratorExpressionNode.cxx93
-rw-r--r--Source/cmGeneratorExpressionParser.cxx7
-rw-r--r--Source/cmGeneratorTarget.cxx99
-rw-r--r--Source/cmGlobalGenerator.cxx14
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx23
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx30
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx193
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx13
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx124
-rw-r--r--Source/cmGlobalVisualStudio8Generator.h19
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx34
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h1
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx40
-rw-r--r--Source/cmIDEOptions.cxx42
-rw-r--r--Source/cmIDEOptions.h13
-rw-r--r--Source/cmInstallCommand.cxx36
-rw-r--r--Source/cmLinkLineDeviceComputer.cxx54
-rw-r--r--Source/cmListCommand.cxx83
-rw-r--r--Source/cmListCommand.h2
-rw-r--r--Source/cmLocalGenerator.cxx1
-rw-r--r--Source/cmLocalNinjaGenerator.cxx88
-rw-r--r--Source/cmLocalNinjaGenerator.h9
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx47
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx40
-rw-r--r--Source/cmLocalVisualStudio7Generator.h15
-rw-r--r--Source/cmMakefile.cxx94
-rw-r--r--Source/cmMakefile.h17
-rw-r--r--Source/cmMakefileTargetGenerator.cxx41
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx8
-rw-r--r--Source/cmNinjaTargetGenerator.cxx61
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx4
-rw-r--r--Source/cmOutputConverter.cxx67
-rw-r--r--Source/cmOutputConverter.h4
-rw-r--r--Source/cmPolicies.cxx97
-rw-r--r--Source/cmPolicies.h16
-rw-r--r--Source/cmProjectCommand.cxx92
-rw-r--r--Source/cmQtAutoGenerator.cxx2
-rw-r--r--Source/cmQtAutoGeneratorMocUic.cxx6
-rw-r--r--Source/cmRulePlaceholderExpander.h2
-rw-r--r--Source/cmSearchPath.h4
-rw-r--r--Source/cmStringCommand.cxx25
-rw-r--r--Source/cmStringCommand.h5
-rw-r--r--Source/cmSystemTools.cxx2
-rw-r--r--Source/cmTarget.cxx69
-rw-r--r--Source/cmTarget.h3
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx15
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx903
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h37
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx179
-rw-r--r--Source/cmVisualStudioGeneratorOptions.h22
-rw-r--r--Source/cmWorkingDirectory.cxx16
-rw-r--r--Source/cmWorkingDirectory.h17
-rw-r--r--Source/cmXMLWriter.h52
-rw-r--r--Source/cmake.cxx26
-rw-r--r--Source/cmake.h1
-rw-r--r--Source/cmcmd.cxx28
-rw-r--r--Source/kwsys/SystemTools.cxx15
-rw-r--r--Source/kwsys/Terminal.c1
-rw-r--r--Source/kwsys/testSystemTools.cxx28
115 files changed, 2544 insertions, 1651 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 533d59f..0f1a352 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 0)
-#set(CMake_VERSION_RC 0)
+set(CMake_VERSION_PATCH 20180404)
+#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..64aba10 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
@@ -994,7 +1002,8 @@ int cmCPackGenerator::DoPackage()
{ // scope that enables package generators to run internal scripts with
// latest CMake policies enabled
cmMakefile::ScopePushPop pp{ this->MakefileMap };
- this->MakefileMap->SetPolicyVersion(cmVersion::GetCMakeVersion());
+ this->MakefileMap->SetPolicyVersion(cmVersion::GetCMakeVersion(),
+ std::string());
if (!this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag()) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem compressing the directory"
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..bafbe9a 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>
@@ -927,7 +928,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
std::string gcovCommand =
this->CTest->GetCTestConfiguration("CoverageCommand");
if (gcovCommand.empty()) {
- cmCTestLog(this->CTest, WARNING, "Could not find gcov." << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Could not find gcov." << std::endl, this->Quiet);
return 0;
}
std::string gcovExtraFlags =
@@ -975,7 +977,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 +1383,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 +1615,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/Checks/Curses.cmake b/Source/Checks/Curses.cmake
new file mode 100644
index 0000000..46dc770
--- /dev/null
+++ b/Source/Checks/Curses.cmake
@@ -0,0 +1,41 @@
+message(STATUS "Checking for curses support")
+
+# Try compiling a simple project using curses.
+# Pass in any cache entries that the user may have set.
+set(CMakeCheckCurses_ARGS "")
+foreach(v
+ CURSES_INCLUDE_PATH
+ CURSES_CURSES_LIBRARY
+ CURSES_NCURSES_LIBRARY
+ CURSES_EXTRA_LIBRARY
+ CURSES_FORM_LIBRARY
+ )
+ if(${v})
+ list(APPEND CMakeCheckCurses_ARGS -D${v}=${${v}})
+ endif()
+endforeach()
+file(REMOVE_RECURSE "${CMake_BINARY_DIR}/Source/Checks/Curses-build")
+try_compile(CMakeCheckCurses_COMPILED
+ ${CMake_BINARY_DIR}/Source/Checks/Curses-build
+ ${CMake_SOURCE_DIR}/Source/Checks/Curses
+ CheckCurses # project name
+ CheckCurses # target name
+ CMAKE_FLAGS
+ "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}"
+ ${CMakeCheckCurses_ARGS}
+ OUTPUT_VARIABLE CMakeCheckCurses_OUTPUT
+ )
+
+# Covnert result from cache entry to normal variable.
+set(CMakeCheckCurses_COMPILED "${CMakeCheckCurses_COMPILED}")
+unset(CMakeCheckCurses_COMPILED CACHE)
+
+if(CMakeCheckCurses_COMPILED)
+ message(STATUS "Checking for curses support - Success")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Checking for curses support passed with the following output:\n${CMakeCheckCurses_OUTPUT}\n\n")
+else()
+ message(STATUS "Checking for curses support - Failed")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Checking for curses support failed with the following output:\n${CMakeCheckCurses_OUTPUT}\n\n")
+endif()
diff --git a/Source/Checks/Curses/CMakeLists.txt b/Source/Checks/Curses/CMakeLists.txt
new file mode 100644
index 0000000..17318a3
--- /dev/null
+++ b/Source/Checks/Curses/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 3.1)
+if(POLICY CMP0060)
+ cmake_policy(SET CMP0060 NEW)
+endif()
+project(CheckCurses C)
+
+set(CURSES_NEED_NCURSES TRUE)
+find_package(Curses)
+if(NOT CURSES_FOUND)
+ return()
+endif()
+include_directories(${CURSES_INCLUDE_DIRS})
+add_executable(CheckCurses CheckCurses.c)
+target_link_libraries(CheckCurses ${CURSES_LIBRARIES})
+
+foreach(h
+ CURSES_HAVE_CURSES_H
+ CURSES_HAVE_NCURSES_H
+ CURSES_HAVE_NCURSES_NCURSES_H
+ CURSES_HAVE_NCURSES_CURSES_H
+ )
+ if(${h})
+ target_compile_definitions(CheckCurses PRIVATE ${h})
+ endif()
+endforeach()
diff --git a/Source/Checks/Curses/CheckCurses.c b/Source/Checks/Curses/CheckCurses.c
new file mode 100644
index 0000000..857ae28
--- /dev/null
+++ b/Source/Checks/Curses/CheckCurses.c
@@ -0,0 +1,15 @@
+#if defined(CURSES_HAVE_NCURSES_H)
+#include <ncurses.h>
+#elif defined(CURSES_HAVE_NCURSES_NCURSES_H)
+#include <ncurses/ncurses.h>
+#elif defined(CURSES_HAVE_NCURSES_CURSES_H)
+#include <ncurses/curses.h>
+#else
+#include <curses.h>
+#endif
+
+int main()
+{
+ curses_version();
+ return 0;
+}
diff --git a/Source/CursesDialog/cmCursesStandardIncludes.h b/Source/CursesDialog/cmCursesStandardIncludes.h
index 332d2af..60bad94 100644
--- a/Source/CursesDialog/cmCursesStandardIncludes.h
+++ b/Source/CursesDialog/cmCursesStandardIncludes.h
@@ -5,6 +5,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
+// Record whether __attribute__ is currently defined. See purpose below.
+#ifndef __attribute__
+#define cm_no__attribute__
+#endif
+
#if defined(__hpux)
#define _BOOL_DEFINED
#include <sys/time.h>
@@ -29,4 +34,12 @@ inline void curses_clear()
#undef erase
#undef clear
+// The curses headers on some platforms (e.g. Solaris) may
+// define __attribute__ as a macro. This breaks C++ headers
+// in some cases, so undefine it now.
+#if defined(cm_no__attribute__) && defined(__attribute__)
+#undef __attribute__
+#endif
+#undef cm_no__attribute__
+
#endif // cmCursesStandardIncludes_h
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/cmCMakeMinimumRequired.cxx b/Source/cmCMakeMinimumRequired.cxx
index bcc41fc..2b51976 100644
--- a/Source/cmCMakeMinimumRequired.cxx
+++ b/Source/cmCMakeMinimumRequired.cxx
@@ -42,12 +42,27 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
// Make sure there was a version to check.
if (version_string.empty()) {
- return this->EnforceUnknownArguments();
+ return this->EnforceUnknownArguments(std::string());
+ }
+
+ // Separate the <min> version and any trailing ...<max> component.
+ std::string::size_type const dd = version_string.find("...");
+ std::string const version_min = version_string.substr(0, dd);
+ std::string const version_max = dd != std::string::npos
+ ? version_string.substr(dd + 3, std::string::npos)
+ : std::string();
+ if (dd != std::string::npos &&
+ (version_min.empty() || version_max.empty())) {
+ std::ostringstream e;
+ e << "VERSION \"" << version_string
+ << "\" does not have a version on both sides of \"...\".";
+ this->SetError(e.str());
+ return false;
}
// Save the required version string.
this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION",
- version_string.c_str());
+ version_min.c_str());
// Get the current version number.
unsigned int current_major = cmVersion::GetMajorVersion();
@@ -61,10 +76,10 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
unsigned int required_minor = 0;
unsigned int required_patch = 0;
unsigned int required_tweak = 0;
- if (sscanf(version_string.c_str(), "%u.%u.%u.%u", &required_major,
+ if (sscanf(version_min.c_str(), "%u.%u.%u.%u", &required_major,
&required_minor, &required_patch, &required_tweak) < 2) {
std::ostringstream e;
- e << "could not parse VERSION \"" << version_string << "\".";
+ e << "could not parse VERSION \"" << version_min << "\".";
this->SetError(e.str());
return false;
}
@@ -78,7 +93,7 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
current_patch == required_patch && current_tweak < required_tweak)) {
// The current version is too low.
std::ostringstream e;
- e << "CMake " << version_string
+ e << "CMake " << version_min
<< " or higher is required. You are running version "
<< cmVersion::GetCMakeVersion();
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
@@ -87,7 +102,7 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
}
// The version is not from the future, so enforce unknown arguments.
- if (!this->EnforceUnknownArguments()) {
+ if (!this->EnforceUnknownArguments(version_max)) {
return false;
}
@@ -95,22 +110,47 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
this->Makefile->IssueMessage(
cmake::AUTHOR_WARNING,
"Compatibility with CMake < 2.4 is not supported by CMake >= 3.0.");
- this->Makefile->SetPolicyVersion("2.4");
+ this->Makefile->SetPolicyVersion("2.4", version_max);
} else {
- this->Makefile->SetPolicyVersion(version_string.c_str());
+ this->Makefile->SetPolicyVersion(version_min, version_max);
}
return true;
}
-bool cmCMakeMinimumRequired::EnforceUnknownArguments()
+bool cmCMakeMinimumRequired::EnforceUnknownArguments(
+ std::string const& version_max)
{
- if (!this->UnknownArguments.empty()) {
- std::ostringstream e;
- e << "called with unknown argument \"" << this->UnknownArguments[0]
- << "\".";
- this->SetError(e.str());
- return false;
+ if (this->UnknownArguments.empty()) {
+ return true;
}
- return true;
+
+ // Consider the max version if at least two components were given.
+ unsigned int max_major = 0;
+ unsigned int max_minor = 0;
+ unsigned int max_patch = 0;
+ unsigned int max_tweak = 0;
+ if (sscanf(version_max.c_str(), "%u.%u.%u.%u", &max_major, &max_minor,
+ &max_patch, &max_tweak) >= 2) {
+ unsigned int current_major = cmVersion::GetMajorVersion();
+ unsigned int current_minor = cmVersion::GetMinorVersion();
+ unsigned int current_patch = cmVersion::GetPatchVersion();
+ unsigned int current_tweak = cmVersion::GetTweakVersion();
+
+ if ((current_major < max_major) ||
+ (current_major == max_major && current_minor < max_minor) ||
+ (current_major == max_major && current_minor == max_minor &&
+ current_patch < max_patch) ||
+ (current_major == max_major && current_minor == max_minor &&
+ current_patch == max_patch && current_tweak < max_tweak)) {
+ // A ...<max> version was given that is larger than the current
+ // version of CMake, so tolerate unknown arguments.
+ return true;
+ }
+ }
+
+ std::ostringstream e;
+ e << "called with unknown argument \"" << this->UnknownArguments[0] << "\".";
+ this->SetError(e.str());
+ return false;
}
diff --git a/Source/cmCMakeMinimumRequired.h b/Source/cmCMakeMinimumRequired.h
index 18d9460..f9b61e1 100644
--- a/Source/cmCMakeMinimumRequired.h
+++ b/Source/cmCMakeMinimumRequired.h
@@ -34,7 +34,7 @@ public:
private:
std::vector<std::string> UnknownArguments;
- bool EnforceUnknownArguments();
+ bool EnforceUnknownArguments(std::string const& version_max);
};
#endif
diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx
index 3ccc815..7ca1cbc 100644
--- a/Source/cmCMakePolicyCommand.cxx
+++ b/Source/cmCMakePolicyCommand.cxx
@@ -156,6 +156,23 @@ bool cmCMakePolicyCommand::HandleVersionMode(
this->SetError("VERSION given too many arguments");
return false;
}
- this->Makefile->SetPolicyVersion(args[1].c_str());
+ std::string const& version_string = args[1];
+
+ // Separate the <min> version and any trailing ...<max> component.
+ std::string::size_type const dd = version_string.find("...");
+ std::string const version_min = version_string.substr(0, dd);
+ std::string const version_max = dd != std::string::npos
+ ? version_string.substr(dd + 3, std::string::npos)
+ : std::string();
+ if (dd != std::string::npos &&
+ (version_min.empty() || version_max.empty())) {
+ std::ostringstream e;
+ e << "VERSION \"" << version_string
+ << "\" does not have a version on both sides of \"...\".";
+ this->SetError(e.str());
+ return false;
+ }
+
+ this->Makefile->SetPolicyVersion(version_min, version_max);
return true;
}
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..6e6e0be 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -240,21 +240,19 @@ because this need be done only for shared libraries without soname-s.
cmComputeLinkInformation::cmComputeLinkInformation(
const cmGeneratorTarget* target, const std::string& config)
-{
// Store context information.
- this->Target = target;
- this->Makefile = this->Target->Target->GetMakefile();
- this->GlobalGenerator =
- this->Target->GetLocalGenerator()->GetGlobalGenerator();
- this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();
-
+ : Target(target),
+ Makefile(target->Target->GetMakefile()),
+ GlobalGenerator(target->GetLocalGenerator()->GetGlobalGenerator()),
+ CMakeInstance(this->GlobalGenerator->GetCMakeInstance())
+ // The configuration being linked.
+ ,
+ Config(config)
+{
// Check whether to recognize OpenBSD-style library versioned names.
this->OpenBSD = this->Makefile->GetState()->GetGlobalPropertyAsBool(
"FIND_LIBRARY_USE_OPENBSD_VERSIONING");
- // The configuration being linked.
- this->Config = config;
-
// Allocate internals.
this->OrderLinkerSearchPath = new cmOrderDirectories(
this->GlobalGenerator, target, "linker search path");
@@ -406,17 +404,18 @@ cmComputeLinkInformation::~cmComputeLinkInformation()
}
cmComputeLinkInformation::ItemVector const&
-cmComputeLinkInformation::GetItems()
+cmComputeLinkInformation::GetItems() const
{
return this->Items;
}
std::vector<std::string> const& cmComputeLinkInformation::GetDirectories()
+ const
{
return this->OrderLinkerSearchPath->GetOrderedDirectories();
}
-std::string cmComputeLinkInformation::GetRPathLinkString()
+std::string cmComputeLinkInformation::GetRPathLinkString() const
{
// If there is no separate linker runtime search flag (-rpath-link)
// there is no reason to compute a string.
@@ -428,18 +427,19 @@ std::string cmComputeLinkInformation::GetRPathLinkString()
return cmJoin(this->OrderDependentRPath->GetOrderedDirectories(), ":");
}
-std::vector<std::string> const& cmComputeLinkInformation::GetDepends()
+std::vector<std::string> const& cmComputeLinkInformation::GetDepends() const
{
return this->Depends;
}
std::vector<std::string> const& cmComputeLinkInformation::GetFrameworkPaths()
+ const
{
return this->FrameworkPaths;
}
const std::set<const cmGeneratorTarget*>&
-cmComputeLinkInformation::GetSharedLibrariesLinked()
+cmComputeLinkInformation::GetSharedLibrariesLinked() const
{
return this->SharedLibrariesLinked;
}
@@ -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 =
@@ -1023,7 +1026,7 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item)
(generator.find("Visual Studio") != std::string::npos ||
generator.find("Xcode") != std::string::npos)) {
std::string file = cmSystemTools::GetFilenameName(item);
- if (!this->ExtractAnyLibraryName.find(file.c_str())) {
+ if (!this->ExtractAnyLibraryName.find(file)) {
this->HandleBadFullItem(item, file);
return;
}
@@ -1230,7 +1233,7 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
void cmComputeLinkInformation::AddFrameworkItem(std::string const& item)
{
// Try to separate the framework name and path.
- if (!this->SplitFramework.find(item.c_str())) {
+ if (!this->SplitFramework.find(item)) {
std::ostringstream e;
e << "Could not parse framework path \"" << item << "\" "
<< "linked by target " << this->Target->GetName() << ".";
@@ -1569,7 +1572,7 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo()
}
std::vector<std::string> const&
-cmComputeLinkInformation::GetRuntimeSearchPath()
+cmComputeLinkInformation::GetRuntimeSearchPath() const
{
return this->OrderRuntimeSearchPath->GetOrderedDirectories();
}
@@ -1635,7 +1638,7 @@ void cmComputeLinkInformation::AddLibraryRuntimeInfo(
if (!is_shared_library) {
// On some platforms (AIX) a shared library may look static.
if (this->ArchivesMayBeShared) {
- if (this->ExtractStaticLibraryName.find(file.c_str())) {
+ if (this->ExtractStaticLibraryName.find(file)) {
// This is the name of a shared library or archive.
is_shared_library = true;
}
@@ -1680,7 +1683,7 @@ static void cmCLI_ExpandListUnique(const char* str,
}
void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
- bool for_install)
+ bool for_install) const
{
// Select whether to generate runtime search directories.
bool outputRuntime =
@@ -1794,7 +1797,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
cmCLI_ExpandListUnique(this->RuntimeAlways.c_str(), runtimeDirs, emitted);
}
-std::string cmComputeLinkInformation::GetRPathString(bool for_install)
+std::string cmComputeLinkInformation::GetRPathString(bool for_install) const
{
// Get the directories to use.
std::vector<std::string> runtimeDirs;
@@ -1822,7 +1825,7 @@ std::string cmComputeLinkInformation::GetRPathString(bool for_install)
return rpath;
}
-std::string cmComputeLinkInformation::GetChrpathString()
+std::string cmComputeLinkInformation::GetChrpathString() const
{
if (!this->RuntimeUseChrpath) {
return "";
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index f8c6214..65c12da 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -48,21 +48,21 @@ public:
cmGeneratorTarget const* Target;
};
typedef std::vector<Item> ItemVector;
- ItemVector const& GetItems();
- std::vector<std::string> const& GetDirectories();
- std::vector<std::string> const& GetDepends();
- std::vector<std::string> const& GetFrameworkPaths();
+ ItemVector const& GetItems() const;
+ std::vector<std::string> const& GetDirectories() const;
+ std::vector<std::string> const& GetDepends() const;
+ std::vector<std::string> const& GetFrameworkPaths() const;
std::string GetLinkLanguage() const { return this->LinkLanguage; }
- std::vector<std::string> const& GetRuntimeSearchPath();
+ std::vector<std::string> const& GetRuntimeSearchPath() const;
std::string const& GetRuntimeFlag() const { return this->RuntimeFlag; }
std::string const& GetRuntimeSep() const { return this->RuntimeSep; }
- void GetRPath(std::vector<std::string>& runtimeDirs, bool for_install);
- std::string GetRPathString(bool for_install);
- std::string GetChrpathString();
- std::set<cmGeneratorTarget const*> const& GetSharedLibrariesLinked();
+ void GetRPath(std::vector<std::string>& runtimeDirs, bool for_install) const;
+ std::string GetRPathString(bool for_install) const;
+ std::string GetChrpathString() const;
+ std::set<cmGeneratorTarget const*> const& GetSharedLibrariesLinked() const;
std::string const& GetRPathLinkFlag() const { return this->RPathLinkFlag; }
- std::string GetRPathLinkString();
+ std::string GetRPathLinkString() const;
std::string GetConfig() const { return this->Config; }
private:
@@ -78,13 +78,13 @@ private:
std::set<cmGeneratorTarget const*> SharedLibrariesLinked;
// Context information.
- cmGeneratorTarget const* Target;
- cmMakefile* Makefile;
- cmGlobalGenerator* GlobalGenerator;
- cmake* CMakeInstance;
+ cmGeneratorTarget const* const Target;
+ cmMakefile* const Makefile;
+ cmGlobalGenerator* const GlobalGenerator;
+ cmake* const CMakeInstance;
// Configuration information.
- std::string Config;
+ std::string const Config;
std::string LinkLanguage;
// Modes for dealing with dependent shared libraries.
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/cmDependsC.cxx b/Source/cmDependsC.cxx
index 62bc8d9..34c0e94 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -96,9 +96,16 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
std::set<std::string> dependencies;
bool haveDeps = false;
+ std::string binDir = this->LocalGenerator->GetBinaryDirectory();
+
+ // Compute a path to the object file to write to the internal depend file.
+ // Any existing content of the internal depend file has already been
+ // loaded in ValidDeps with this path as a key.
+ std::string obj_i = this->LocalGenerator->ConvertToRelativePath(binDir, obj);
+
if (this->ValidDeps != nullptr) {
std::map<std::string, DependencyVector>::const_iterator tmpIt =
- this->ValidDeps->find(obj);
+ this->ValidDeps->find(obj_i);
if (tmpIt != this->ValidDeps->end()) {
dependencies.insert(tmpIt->second.begin(), tmpIt->second.end());
haveDeps = true;
@@ -222,8 +229,6 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
// written by the original local generator for this directory
// convert the dependencies to paths relative to the home output
// directory. We must do the same here.
- std::string binDir = this->LocalGenerator->GetBinaryDirectory();
- std::string obj_i = this->LocalGenerator->ConvertToRelativePath(binDir, obj);
std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i);
internalDepends << obj_i << std::endl;
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx
index 817b5d9..0ceac85 100644
--- a/Source/cmExportBuildAndroidMKGenerator.cxx
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -41,7 +41,8 @@ void cmExportBuildAndroidMKGenerator::GenerateExpectedTargetsCode(
}
void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
- std::ostream& os, const cmGeneratorTarget* target)
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/)
{
std::string targetName = this->Namespace;
targetName += target->GetExportName();
diff --git a/Source/cmExportBuildAndroidMKGenerator.h b/Source/cmExportBuildAndroidMKGenerator.h
index c80839b..a9b6107 100644
--- a/Source/cmExportBuildAndroidMKGenerator.h
+++ b/Source/cmExportBuildAndroidMKGenerator.h
@@ -11,6 +11,7 @@
#include "cmExportBuildFileGenerator.h"
#include "cmExportFileGenerator.h"
+#include "cmStateTypes.h"
class cmGeneratorTarget;
@@ -47,8 +48,9 @@ protected:
void GenerateImportHeaderCode(std::ostream& os,
const std::string& config = "") override;
void GenerateImportFooterCode(std::ostream& os) override;
- void GenerateImportTargetCode(std::ostream& os,
- const cmGeneratorTarget* target) override;
+ void GenerateImportTargetCode(
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/) override;
void GenerateExpectedTargetsCode(
std::ostream& os, const std::string& expectedTargets) override;
void GenerateImportPropertyCode(
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index f7aa6e8..bbbc998 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -59,7 +59,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->LG->GetMakefile()->GetBacktrace());
return false;
}
- if (te->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY) {
this->GenerateRequiredCMakeVersion(os, "3.0.0");
}
}
@@ -71,7 +71,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
// Create all the imported targets.
for (cmGeneratorTarget* gte : this->Exports) {
- this->GenerateImportTargetCode(os, gte);
+ this->GenerateImportTargetCode(os, gte, this->GetExportTargetType(gte));
gte->Target->AppendBuildInterfaceIncludes();
@@ -97,6 +97,15 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gte,
properties);
+
+ std::string errorMessage;
+ if (!this->PopulateExportProperties(gte, properties, errorMessage)) {
+ this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
+ cmake::FATAL_ERROR, errorMessage,
+ this->LG->GetMakefile()->GetBacktrace());
+ return false;
+ }
+
const bool newCMP0022Behavior =
gte->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
gte->GetPolicyStatusCMP0022() != cmPolicies::OLD;
@@ -128,12 +137,13 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
// Collect import properties for this target.
ImportPropertyMap properties;
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(target) != cmStateEnums::INTERFACE_LIBRARY) {
this->SetImportLocationProperty(config, suffix, target, properties);
}
if (!properties.empty()) {
// Get the rest of the target details.
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(target) !=
+ cmStateEnums::INTERFACE_LIBRARY) {
this->SetImportDetailProperties(config, suffix, target, properties,
missingTargets);
this->SetImportLinkInterface(config, suffix,
@@ -153,6 +163,21 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
}
}
+cmStateEnums::TargetType cmExportBuildFileGenerator::GetExportTargetType(
+ cmGeneratorTarget const* target) const
+{
+ cmStateEnums::TargetType targetType = target->GetType();
+ // An object library exports as an interface library if we cannot
+ // 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;
+ }
+ return targetType;
+}
+
void cmExportBuildFileGenerator::SetExportSet(cmExportSet* exportSet)
{
this->ExportSet = exportSet;
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 6457a77..ada2709 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmExportFileGenerator.h"
+#include "cmStateTypes.h"
#include <iosfwd>
#include <string>
@@ -53,6 +54,8 @@ protected:
void GenerateImportTargetsConfig(
std::ostream& os, const std::string& config, std::string const& suffix,
std::vector<std::string>& missingTargets) override;
+ cmStateEnums::TargetType GetExportTargetType(
+ cmGeneratorTarget const* target) const;
void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmGeneratorTarget* depender,
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index c8a727d..655ebe8 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -146,17 +146,6 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
}
if (cmTarget* target = gg->FindTarget(currentTarget)) {
- if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::string reason;
- if (!this->Makefile->GetGlobalGenerator()
- ->HasKnownObjectFileLocation(&reason)) {
- std::ostringstream e;
- e << "given OBJECT library \"" << currentTarget
- << "\" which may not be exported" << reason << ".";
- this->SetError(e.str());
- return false;
- }
- }
if (target->GetType() == cmStateEnums::UTILITY) {
this->SetError("given custom target \"" + currentTarget +
"\" which may not be exported.");
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 434abdc..2dcbfa0 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -11,6 +11,8 @@
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
+#include "cmPropertyMap.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
@@ -901,8 +903,10 @@ void cmExportFileGenerator::GenerateExpectedTargetsCode(
"\n\n";
/* clang-format on */
}
+
void cmExportFileGenerator::GenerateImportTargetCode(
- std::ostream& os, const cmGeneratorTarget* target)
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType targetType)
{
// Construct the imported target name.
std::string targetName = this->Namespace;
@@ -911,7 +915,7 @@ void cmExportFileGenerator::GenerateImportTargetCode(
// Create the imported target.
os << "# Create imported target " << targetName << "\n";
- switch (target->GetType()) {
+ switch (targetType) {
case cmStateEnums::EXECUTABLE:
os << "add_executable(" << targetName << " IMPORTED)\n";
break;
@@ -1095,3 +1099,41 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode(
os << ")\n\n";
}
+
+bool cmExportFileGenerator::PopulateExportProperties(
+ cmGeneratorTarget* gte, ImportPropertyMap& properties,
+ std::string& errorMessage)
+{
+ auto& targetProperties = gte->Target->GetProperties();
+ const auto& exportProperties = targetProperties.find("EXPORT_PROPERTIES");
+ if (exportProperties != targetProperties.end()) {
+ std::vector<std::string> propsToExport;
+ cmSystemTools::ExpandListArgument(exportProperties->second.GetValue(),
+ propsToExport);
+ for (auto& prop : propsToExport) {
+ /* Black list reserved properties */
+ if (cmSystemTools::StringStartsWith(prop, "IMPORTED_") ||
+ cmSystemTools::StringStartsWith(prop, "INTERFACE_")) {
+ std::ostringstream e;
+ e << "Target \"" << gte->Target->GetName() << "\" contains property \""
+ << prop << "\" in EXPORT_PROPERTIES but IMPORTED_* and INTERFACE_* "
+ << "properties are reserved.";
+ errorMessage = e.str();
+ return false;
+ }
+ auto propertyValue = targetProperties.GetPropertyValue(prop);
+ std::string evaluatedValue = cmGeneratorExpression::Preprocess(
+ propertyValue, cmGeneratorExpression::StripAllGeneratorExpressions);
+ if (evaluatedValue != propertyValue) {
+ std::ostringstream e;
+ e << "Target \"" << gte->Target->GetName() << "\" contains property \""
+ << prop << "\" in EXPORT_PROPERTIES but this property contains a "
+ << "generator expression. This is not allowed.";
+ errorMessage = e.str();
+ return false;
+ }
+ properties[prop] = propertyValue;
+ }
+ }
+ return true;
+}
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 985c8f6..954e6c5 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmGeneratorExpression.h"
+#include "cmStateTypes.h"
#include "cmVersion.h"
#include "cmVersionConfig.h"
@@ -76,7 +77,8 @@ protected:
virtual void GenerateImportFooterCode(std::ostream& os);
void GenerateImportVersionCode(std::ostream& os);
virtual void GenerateImportTargetCode(std::ostream& os,
- cmGeneratorTarget const* target);
+ cmGeneratorTarget const* target,
+ cmStateEnums::TargetType targetType);
virtual void GenerateImportPropertyCode(std::ostream& os,
const std::string& config,
cmGeneratorTarget const* target,
@@ -166,6 +168,10 @@ protected:
virtual void GenerateRequiredCMakeVersion(std::ostream& os,
const char* versionString);
+ bool PopulateExportProperties(cmGeneratorTarget* gte,
+ ImportPropertyMap& properties,
+ std::string& errorMessage);
+
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx
index fe565e6..9bc8089 100644
--- a/Source/cmExportInstallAndroidMKGenerator.cxx
+++ b/Source/cmExportInstallAndroidMKGenerator.cxx
@@ -55,7 +55,8 @@ void cmExportInstallAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
}
void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode(
- std::ostream& os, const cmGeneratorTarget* target)
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/)
{
std::string targetName = this->Namespace;
targetName += target->GetExportName();
diff --git a/Source/cmExportInstallAndroidMKGenerator.h b/Source/cmExportInstallAndroidMKGenerator.h
index 91554ee..8883ffa 100644
--- a/Source/cmExportInstallAndroidMKGenerator.h
+++ b/Source/cmExportInstallAndroidMKGenerator.h
@@ -12,6 +12,7 @@
#include "cmExportFileGenerator.h"
#include "cmExportInstallFileGenerator.h"
+#include "cmStateTypes.h"
class cmGeneratorTarget;
class cmInstallExportGenerator;
@@ -41,8 +42,9 @@ protected:
void GenerateImportHeaderCode(std::ostream& os,
const std::string& config = "") override;
void GenerateImportFooterCode(std::ostream& os) override;
- void GenerateImportTargetCode(std::ostream& os,
- const cmGeneratorTarget* target) override;
+ void GenerateImportTargetCode(
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/) override;
void GenerateExpectedTargetsCode(
std::ostream& os, const std::string& expectedTargets) override;
void GenerateImportPropertyCode(
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 954b561..63d04a6 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -75,11 +75,12 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
// Create all the imported targets.
for (cmTargetExport* te : allTargets) {
cmGeneratorTarget* gt = te->Target;
+ cmStateEnums::TargetType targetType = this->GetExportTargetType(te);
requiresConfigFiles =
- requiresConfigFiles || gt->GetType() != cmStateEnums::INTERFACE_LIBRARY;
+ requiresConfigFiles || targetType != cmStateEnums::INTERFACE_LIBRARY;
- this->GenerateImportTargetCode(os, gt);
+ this->GenerateImportTargetCode(os, gt, targetType);
ImportPropertyMap properties;
@@ -103,6 +104,12 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
+ std::string errorMessage;
+ if (!this->PopulateExportProperties(gt, properties, errorMessage)) {
+ cmSystemTools::Error(errorMessage.c_str());
+ return false;
+ }
+
const bool newCMP0022Behavior =
gt->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
gt->GetPolicyStatusCMP0022() != cmPolicies::OLD;
@@ -114,7 +121,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
require2_8_12 = true;
}
}
- if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (targetType == cmStateEnums::INTERFACE_LIBRARY) {
require3_0_0 = true;
}
if (gt->GetProperty("INTERFACE_SOURCES")) {
@@ -308,7 +315,7 @@ void cmExportInstallFileGenerator::GenerateImportTargetsConfig(
// Add each target in the set to the export.
for (cmTargetExport* te : *this->IEGen->GetExportSet()->GetTargetExports()) {
// Collect import properties for this target.
- if (te->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
@@ -426,6 +433,19 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
}
}
+cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType(
+ cmTargetExport const* targetExport) const
+{
+ cmStateEnums::TargetType targetType = targetExport->Target->GetType();
+ // An OBJECT library installed with no OBJECTS DESTINATION
+ // is transformed to an INTERFACE library.
+ if (targetType == cmStateEnums::OBJECT_LIBRARY &&
+ targetExport->ObjectsGenerator == nullptr) {
+ targetType = cmStateEnums::INTERFACE_LIBRARY;
+ }
+ return targetType;
+}
+
void cmExportInstallFileGenerator::HandleMissingTarget(
std::string& link_libs, std::vector<std::string>& missingTargets,
cmGeneratorTarget* depender, cmGeneratorTarget* dependee)
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index cda8433..ea607fb 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmExportFileGenerator.h"
+#include "cmStateTypes.h"
#include <iosfwd>
#include <map>
@@ -17,6 +18,7 @@ class cmGeneratorTarget;
class cmGlobalGenerator;
class cmInstallExportGenerator;
class cmInstallTargetGenerator;
+class cmTargetExport;
/** \class cmExportInstallFileGenerator
* \brief Generate a file exporting targets from an install tree.
@@ -57,6 +59,8 @@ protected:
void GenerateImportTargetsConfig(
std::ostream& os, const std::string& config, std::string const& suffix,
std::vector<std::string>& missingTargets) override;
+ cmStateEnums::TargetType GetExportTargetType(
+ cmTargetExport const* targetExport) const;
void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmGeneratorTarget* depender,
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index ae8cd37..87648cb 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -33,7 +33,7 @@ bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
this->Exports.pop_back();
if (emitted.insert(te).second) {
emittedDeps.insert(te);
- this->GenerateImportTargetCode(os, te);
+ this->GenerateImportTargetCode(os, te, te->GetType());
ImportPropertyMap properties;
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index 4dbaa3f..c7c780c 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -408,7 +408,6 @@ void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
const std::string& projectPath, const cmMakefile* mf,
const std::string& projectType, const std::string& targetName)
{
-
cmXMLWriter& xml(*_xml);
FindMatchingHeaderfiles(cFiles, otherFiles);
// Create 2 virtual folders: src and include
@@ -469,10 +468,14 @@ void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
xml.EndElement(); // ResourceCompiler
xml.StartElement("General");
- std::string outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
+ std::string outputPath =
+ mf->GetSafeDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY");
+ if (outputPath.empty()) {
+ outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
+ }
std::string relapath;
if (!outputPath.empty()) {
- relapath = cmSystemTools::RelativePath(this->WorkspacePath, outputPath);
+ relapath = cmSystemTools::RelativePath(projectPath, outputPath);
xml.Attribute("OutputFile", relapath + "/$(ProjectName)");
} else {
xml.Attribute("OutputFile", "$(IntermediateDirectory)/$(ProjectName)");
@@ -635,7 +638,7 @@ std::string cmExtraCodeLiteGenerator::GetBuildCommand(
if (generator == "NMake Makefiles" || generator == "Ninja") {
ss << make;
} else if (generator == "MinGW Makefiles" || generator == "Unix Makefiles") {
- ss << make << " -j " << this->CpuCount;
+ ss << make << " -f$(ProjectPath)/Makefile -j " << this->CpuCount;
}
if (!targetName.empty()) {
ss << " " << targetName;
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index d3dcc01..90b943b 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -160,6 +160,12 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args,
if (subCommand == "TO_NATIVE_PATH") {
return this->HandleCMakePathCommand(args, true);
}
+ if (subCommand == "TOUCH") {
+ return this->HandleTouchCommand(args, true);
+ }
+ if (subCommand == "TOUCH_NOCREATE") {
+ return this->HandleTouchCommand(args, false);
+ }
if (subCommand == "TIMESTAMP") {
return this->HandleTimestampCommand(args);
}
@@ -751,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()) {
@@ -771,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;
}
@@ -905,6 +913,38 @@ bool cmFileCommand::HandleMakeDirectoryCommand(
return true;
}
+bool cmFileCommand::HandleTouchCommand(std::vector<std::string> const& args,
+ bool create)
+{
+ // File command has at least one argument
+ assert(args.size() > 1);
+
+ std::vector<std::string>::const_iterator i = args.begin();
+
+ i++; // Get rid of subcommand
+
+ for (; i != args.end(); ++i) {
+ std::string tfile = *i;
+ if (!cmsys::SystemTools::FileIsFullPath(tfile)) {
+ tfile = this->Makefile->GetCurrentSourceDirectory();
+ tfile += "/" + *i;
+ }
+ if (!this->Makefile->CanIWriteThisFile(tfile)) {
+ std::string e =
+ "attempted to touch a file: " + tfile + " in a source directory.";
+ this->SetError(e);
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+ if (!cmSystemTools::Touch(tfile, create)) {
+ std::string error = "problem touching file: " + tfile;
+ this->SetError(error);
+ return false;
+ }
+ }
+ return true;
+}
+
bool cmFileCommand::HandleDifferentCommand(
std::vector<std::string> const& args)
{
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index 17269f3..719dca2 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -39,6 +39,7 @@ protected:
bool HandleHashCommand(std::vector<std::string> const& args);
bool HandleStringsCommand(std::vector<std::string> const& args);
bool HandleGlobCommand(std::vector<std::string> const& args, bool recurse);
+ bool HandleTouchCommand(std::vector<std::string> const& args, bool create);
bool HandleMakeDirectoryCommand(std::vector<std::string> const& args);
bool HandleRelativePathCommand(std::vector<std::string> const& args);
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/cmFindBase.cxx b/Source/cmFindBase.cxx
index 417cdd2..865595b 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -67,8 +67,6 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
}
this->AlreadyInCache = false;
- this->SelectDefaultNoPackageRootPath();
-
// Find the current root path mode.
this->SelectDefaultRootPathMode();
@@ -206,16 +204,12 @@ void cmFindBase::FillPackageRootPath()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot];
- // Add package specific search prefixes
- // NOTE: This should be using const_reverse_iterator but HP aCC and
- // Oracle sunCC both currently have standard library issues
- // with the reverse iterator APIs.
- for (std::deque<std::string>::reverse_iterator pkg =
- this->Makefile->FindPackageModuleStack.rbegin();
- pkg != this->Makefile->FindPackageModuleStack.rend(); ++pkg) {
- std::string varName = *pkg + "_ROOT";
- paths.AddCMakePrefixPath(varName);
- paths.AddEnvPrefixPath(varName);
+ // Add the PACKAGE_ROOT_PATH from each enclosing find_package call.
+ for (std::deque<std::vector<std::string>>::const_reverse_iterator pkgPaths =
+ this->Makefile->FindPackageRootPathStack.rbegin();
+ pkgPaths != this->Makefile->FindPackageRootPathStack.rend();
+ ++pkgPaths) {
+ paths.AddPrefixPaths(*pkgPaths);
}
paths.AddSuffixes(this->SearchPathSuffixes);
@@ -225,8 +219,8 @@ void cmFindBase::FillCMakeVariablePath()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::CMake];
- // Add CMake varibles of the same name as the previous environment
- // varibles CMAKE_*_PATH to be used most of the time with -D
+ // Add CMake variables of the same name as the previous environment
+ // variables CMAKE_*_PATH to be used most of the time with -D
// command line options
std::string var = "CMAKE_";
var += this->CMakePathName;
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index 4a467f3..64108d7 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -88,13 +88,6 @@ void cmFindCommon::InitializeSearchPathGroups()
std::make_pair(PathLabel::Guess, cmSearchPath(this)));
}
-void cmFindCommon::SelectDefaultNoPackageRootPath()
-{
- if (!this->Makefile->IsOn("__UNDOCUMENTED_CMAKE_FIND_PACKAGE_ROOT")) {
- this->NoPackageRootPath = true;
- }
-}
-
void cmFindCommon::SelectDefaultRootPathMode()
{
// Check the policy variable for this find command type.
diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h
index b237f1b..89ff174 100644
--- a/Source/cmFindCommon.h
+++ b/Source/cmFindCommon.h
@@ -84,9 +84,6 @@ protected:
/** Compute final search path list (reroot + trailing slash). */
void ComputeFinalPaths();
- /** Decide whether to enable the PACKAGE_ROOT search entries. */
- void SelectDefaultNoPackageRootPath();
-
/** Compute the current default root path mode. */
void SelectDefaultRootPathMode();
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 2f3a85b..46854f7 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -21,6 +21,7 @@
#include "cmAlgorithms.h"
#include "cmMakefile.h"
+#include "cmPolicies.h"
#include "cmSearchPath.h"
#include "cmState.h"
#include "cmStateTypes.h"
@@ -209,8 +210,6 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
this->SortDirection = strcmp(sd, "ASC") == 0 ? Asc : Dec;
}
- this->SelectDefaultNoPackageRootPath();
-
// Find the current root path mode.
this->SelectDefaultRootPathMode();
@@ -454,6 +453,38 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
return true;
}
+ {
+ // Allocate a PACKAGE_ROOT_PATH for the current find_package call.
+ this->Makefile->FindPackageRootPathStack.emplace_back();
+ std::vector<std::string>& rootPaths =
+ *this->Makefile->FindPackageRootPathStack.rbegin();
+
+ // Add root paths from <PackageName>_ROOT CMake and environment variables,
+ // subject to CMP0074.
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0074)) {
+ case cmPolicies::WARN:
+ this->Makefile->MaybeWarnCMP0074(this->Name);
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // OLD behavior is to ignore the <pkg>_ROOT variables.
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0074));
+ break;
+ case cmPolicies::NEW: {
+ // NEW behavior is to honor the <pkg>_ROOT variables.
+ std::string const rootVar = this->Name + "_ROOT";
+ if (const char* pkgRoot = this->Makefile->GetDefinition(rootVar)) {
+ cmSystemTools::ExpandListArgument(pkgRoot, rootPaths, false);
+ }
+ cmSystemTools::GetPath(rootPaths, rootVar.c_str());
+ } break;
+ }
+ }
+
this->SetModuleVariables(components);
// See if there is a Find<package>.cmake module.
@@ -589,9 +620,6 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components)
exact += "_FIND_VERSION_EXACT";
this->AddFindDefinition(exact, this->VersionExact ? "1" : "0");
}
-
- // Push on to the package stack
- this->Makefile->FindPackageModuleStack.push_back(this->Name);
}
void cmFindPackageCommand::AddFindDefinition(const std::string& var,
@@ -1076,7 +1104,7 @@ void cmFindPackageCommand::AppendSuccessInformation()
this->RestoreFindDefinitions();
// Pop the package stack
- this->Makefile->FindPackageModuleStack.pop_back();
+ this->Makefile->FindPackageRootPathStack.pop_back();
}
void cmFindPackageCommand::ComputePrefixes()
@@ -1116,16 +1144,14 @@ void cmFindPackageCommand::FillPrefixesPackageRoot()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot];
- // Add package specific search prefixes
- // NOTE: This should be using const_reverse_iterator but HP aCC and
- // Oracle sunCC both currently have standard library issues
- // with the reverse iterator APIs.
- for (std::deque<std::string>::reverse_iterator pkg =
- this->Makefile->FindPackageModuleStack.rbegin();
- pkg != this->Makefile->FindPackageModuleStack.rend(); ++pkg) {
- std::string varName = *pkg + "_ROOT";
- paths.AddCMakePath(varName);
- paths.AddEnvPath(varName);
+ // Add the PACKAGE_ROOT_PATH from each enclosing find_package call.
+ for (std::deque<std::vector<std::string>>::const_reverse_iterator pkgPaths =
+ this->Makefile->FindPackageRootPathStack.rbegin();
+ pkgPaths != this->Makefile->FindPackageRootPathStack.rend();
+ ++pkgPaths) {
+ for (std::string const& path : *pkgPaths) {
+ paths.AddPath(path);
+ }
}
}
@@ -2039,7 +2065,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
common.push_back("lib");
common.push_back("share");
- // PREFIX/(lib/ARCH|lib|share)/cmake/(Foo|foo|FOO).*/
+ // PREFIX/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
@@ -2052,7 +2078,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
}
}
- // PREFIX/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/
+ // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
@@ -2064,7 +2090,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
}
}
- // PREFIX/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/(cmake|CMake)/
+ // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
@@ -2077,7 +2103,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
}
}
- // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib|share)/cmake/(Foo|foo|FOO).*/
+ // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
@@ -2092,7 +2118,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
}
}
- // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/
+ // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
@@ -2106,7 +2132,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
}
}
- // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/(cmake|CMake)/
+ // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 92dac79..0561799 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <string>
+#include <utility>
#include <vector>
struct cmGeneratorExpressionContext;
@@ -64,17 +65,16 @@ private:
struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator
{
GeneratorExpressionContent(const char* startContent, size_t length);
- void SetIdentifier(
- std::vector<cmGeneratorExpressionEvaluator*> const& identifier)
+
+ void SetIdentifier(std::vector<cmGeneratorExpressionEvaluator*> identifier)
{
- this->IdentifierChildren = identifier;
+ this->IdentifierChildren = std::move(identifier);
}
void SetParameters(
- std::vector<std::vector<cmGeneratorExpressionEvaluator*>> const&
- parameters)
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*>> parameters)
{
- this->ParamChildren = parameters;
+ this->ParamChildren = std::move(parameters);
}
Type GetType() const override
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index c1f1ee4..09b7faf 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -275,6 +275,96 @@ static const struct EqualNode : public cmGeneratorExpressionNode
}
} equalNode;
+static const struct InListNode : public cmGeneratorExpressionNode
+{
+ InListNode() {}
+
+ int NumExpectedParameters() const override { return 2; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ std::vector<std::string> values;
+ cmSystemTools::ExpandListArgument(parameters[1], values);
+ if (values.empty()) {
+ return "0";
+ }
+
+ return std::find(values.cbegin(), values.cend(), parameters.front()) ==
+ values.cend()
+ ? "0"
+ : "1";
+ }
+} inListNode;
+
+static const struct TargetExistsNode : public cmGeneratorExpressionNode
+{
+ TargetExistsNode() {}
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ if (parameters.size() != 1) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_EXISTS:...> expression requires one parameter");
+ return std::string();
+ }
+
+ std::string targetName = parameters.front();
+ if (targetName.empty() ||
+ !cmGeneratorExpression::IsValidTargetName(targetName)) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_EXISTS:tgt> expression requires a non-empty "
+ "valid target name.");
+ return std::string();
+ }
+
+ return context->LG->GetMakefile()->FindTargetToUse(targetName) ? "1" : "0";
+ }
+} targetExistsNode;
+
+static const struct TargetNameIfExistsNode : public cmGeneratorExpressionNode
+{
+ TargetNameIfExistsNode() {}
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ if (parameters.size() != 1) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_NAME_IF_EXISTS:...> expression requires one "
+ "parameter");
+ return std::string();
+ }
+
+ std::string targetName = parameters.front();
+ if (targetName.empty() ||
+ !cmGeneratorExpression::IsValidTargetName(targetName)) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_NAME_IF_EXISTS:tgt> expression requires a "
+ "non-empty valid target name.");
+ return std::string();
+ }
+
+ return context->LG->GetMakefile()->FindTargetToUse(targetName)
+ ? targetName
+ : std::string();
+ }
+} targetNameIfExistsNode;
+
static const struct LowerCaseNode : public cmGeneratorExpressionNode
{
LowerCaseNode() {}
@@ -1827,6 +1917,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
nodeMap["TARGET_BUNDLE_CONTENT_DIR"] = &targetBundleContentDirNode;
nodeMap["STREQUAL"] = &strEqualNode;
nodeMap["EQUAL"] = &equalNode;
+ nodeMap["IN_LIST"] = &inListNode;
nodeMap["LOWER_CASE"] = &lowerCaseNode;
nodeMap["UPPER_CASE"] = &upperCaseNode;
nodeMap["MAKE_C_IDENTIFIER"] = &makeCIdentifierNode;
@@ -1839,6 +1930,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
nodeMap["TARGET_NAME"] = &targetNameNode;
nodeMap["TARGET_OBJECTS"] = &targetObjectsNode;
nodeMap["TARGET_POLICY"] = &targetPolicyNode;
+ nodeMap["TARGET_EXISTS"] = &targetExistsNode;
+ nodeMap["TARGET_NAME_IF_EXISTS"] = &targetNameIfExistsNode;
nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode;
nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode;
nodeMap["INSTALL_PREFIX"] = &installPrefixNode;
diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx
index 278de04..7b4dc7b 100644
--- a/Source/cmGeneratorExpressionParser.cxx
+++ b/Source/cmGeneratorExpressionParser.cxx
@@ -6,6 +6,7 @@
#include <assert.h>
#include <stddef.h>
+#include <utility>
cmGeneratorExpressionParser::cmGeneratorExpressionParser(
const std::vector<cmGeneratorExpressionToken>& tokens)
@@ -92,7 +93,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
assert(this->it != this->Tokens.end());
++this->it;
--this->NestingLevel;
- content->SetIdentifier(identifier);
+ content->SetIdentifier(std::move(identifier));
result.push_back(content);
return;
}
@@ -198,8 +199,8 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
((this->it - 1)->Content - startToken->Content) + (this->it - 1)->Length;
GeneratorExpressionContent* content =
new GeneratorExpressionContent(startToken->Content, contentLength);
- content->SetIdentifier(identifier);
- content->SetParameters(parameters);
+ content->SetIdentifier(std::move(identifier));
+ content->SetParameters(std::move(parameters));
result.push_back(content);
}
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 2bb01b2..63bfbc6 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:
@@ -808,6 +811,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,
@@ -848,13 +871,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());
@@ -931,23 +951,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,
@@ -1053,9 +1082,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") {
@@ -1673,6 +1699,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;
}
@@ -2001,8 +2028,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()) {
@@ -2592,13 +2624,20 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
return includes;
}
+enum class OptionsParse
+{
+ None,
+ Shell
+};
+
static void processCompileOptionsInternal(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
std::vector<std::string>& options,
std::unordered_set<std::string>& uniqueOptions,
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
- bool debugOptions, const char* logName, std::string const& language)
+ bool debugOptions, const char* logName, std::string const& language,
+ OptionsParse parse)
{
for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) {
std::vector<std::string> entryOptions;
@@ -2609,7 +2648,12 @@ static void processCompileOptionsInternal(
std::string usedOptions;
for (std::string const& opt : entryOptions) {
if (uniqueOptions.insert(opt).second) {
- options.push_back(opt);
+ if (parse == OptionsParse::Shell &&
+ cmHasLiteralPrefix(opt, "SHELL:")) {
+ cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, options);
+ } else {
+ options.push_back(opt);
+ }
if (debugOptions) {
usedOptions += " * " + opt + "\n";
}
@@ -2634,7 +2678,7 @@ static void processCompileOptions(
{
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
dagChecker, config, debugOptions, "options",
- language);
+ language, OptionsParse::Shell);
}
void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result,
@@ -2688,7 +2732,7 @@ static void processCompileFeatures(
{
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
dagChecker, config, debugOptions, "features",
- std::string());
+ std::string(), OptionsParse::None);
}
void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
@@ -2738,7 +2782,7 @@ static void processCompileDefinitions(
{
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
dagChecker, config, debugOptions,
- "definitions", language);
+ "definitions", language, OptionsParse::None);
}
void cmGeneratorTarget::GetCompileDefinitions(
@@ -5325,20 +5369,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;
}
@@ -5402,6 +5432,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/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index b251f86..55a403e 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -1223,11 +1223,13 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
for (std::string const& file : files) {
knownDependencies.insert(this->ConvertToNinjaPath(file));
}
- // get list files which are implicit dependencies as well and will be phony
- // for rebuild manifest
- std::vector<std::string> const& lf = lg->GetMakefile()->GetListFiles();
- for (std::string const& j : lf) {
- knownDependencies.insert(this->ConvertToNinjaPath(j));
+ if (!this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ // get list files which are implicit dependencies as well and will be
+ // phony for rebuild manifest
+ std::vector<std::string> const& lf = lg->GetMakefile()->GetListFiles();
+ for (std::string const& j : lf) {
+ knownDependencies.insert(this->ConvertToNinjaPath(j));
+ }
}
std::vector<cmGeneratorExpressionEvaluationFile*> const& ef =
lg->GetMakefile()->GetEvaluationFiles();
@@ -1335,6 +1337,9 @@ void cmGlobalNinjaGenerator::WriteTargetAll(std::ostream& os)
void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
{
+ if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ return;
+ }
cmLocalGenerator* lg = this->LocalGenerators[0];
std::ostringstream cmd;
@@ -1384,8 +1389,14 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
/*explicitDeps=*/cmNinjaDeps(), implicitDeps,
/*orderOnlyDeps=*/cmNinjaDeps(), variables);
+ cmNinjaDeps missingInputs;
+ std::set_difference(std::make_move_iterator(implicitDeps.begin()),
+ std::make_move_iterator(implicitDeps.end()),
+ CustomCommandOutputs.begin(), CustomCommandOutputs.end(),
+ std::back_inserter(missingInputs));
+
this->WritePhonyBuild(os, "A missing CMake input file is not an error.",
- implicitDeps, cmNinjaDeps());
+ missingInputs, cmNinjaDeps());
}
std::string cmGlobalNinjaGenerator::ninjaCmd() const
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index d990a6c..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);
@@ -256,6 +260,10 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
{
+ if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ return;
+ }
+
// Open the output file. This should not be copy-if-different
// because the check-build-system step compares the makefile time to
// see if the build system must be regenerated.
@@ -525,7 +533,10 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
std::vector<std::string> depends;
std::vector<std::string> commands;
- depends.push_back("cmake_check_build_system");
+ bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
// write the target convenience rules
for (cmLocalGenerator* localGen : this->LocalGenerators) {
@@ -558,7 +569,9 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
tmp += "Makefile2";
commands.push_back(lg->GetRecursiveMakeCall(tmp.c_str(), name));
depends.clear();
- depends.push_back("cmake_check_build_system");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
lg->WriteMakeRule(ruleFileStream, "Build rule for target.", name,
depends, commands, true);
@@ -609,7 +622,10 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
// write the directory level rules for this local gen
this->WriteDirectoryRules2(ruleFileStream, lg);
- depends.push_back("cmake_check_build_system");
+ bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
// for each target Generate the rule files for each target.
const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
@@ -715,7 +731,9 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
commands.push_back(progCmd.str());
}
depends.clear();
- depends.push_back("cmake_check_build_system");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
localName = lg->GetRelativeTargetDirectory(gtarget);
localName += "/rule";
lg->WriteMakeRule(ruleFileStream,
@@ -898,7 +916,9 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule(
"for this Makefile:");
lg->AppendEcho(commands, "... all (the default if no target is provided)");
lg->AppendEcho(commands, "... clean");
- lg->AppendEcho(commands, "... depend");
+ if (!this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ lg->AppendEcho(commands, "... depend");
+ }
// Keep track of targets already listed.
std::set<std::string> emittedTargets;
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 73a5dae..205e0d0 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -636,126 +636,89 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
cmsys::ofstream fout(vcxprojAbs.c_str());
cmXMLWriter xw(fout);
- /* clang-format off */
- xw.StartDocument();
- xw.StartElement("Project");
- xw.Attribute("DefaultTargets", "Build");
- xw.Attribute("ToolsVersion", "4.0");
- xw.Attribute("xmlns",
- "http://schemas.microsoft.com/developer/msbuild/2003");
- if (this->IsNsightTegra()) {
- xw.StartElement("PropertyGroup");
- xw.Attribute("Label", "NsightTegraProject");
- xw.StartElement("NsightTegraProjectRevisionNumber");
- xw.Content("6");
- xw.EndElement(); // NsightTegraProjectRevisionNumber
- xw.EndElement(); // PropertyGroup
- }
- xw.StartElement("ItemGroup");
- xw.Attribute("Label", "ProjectConfigurations");
- xw.StartElement("ProjectConfiguration");
- xw.Attribute("Include", "Debug|" + this->GetPlatformName());
- xw.StartElement("Configuration");
- xw.Content("Debug");
- xw.EndElement(); // Configuration
- xw.StartElement("Platform");
- xw.Content(this->GetPlatformName());
- xw.EndElement(); // Platform
- xw.EndElement(); // ProjectConfiguration
- xw.EndElement(); // ItemGroup
- xw.StartElement("PropertyGroup");
- xw.Attribute("Label", "Globals");
- xw.StartElement("ProjectGuid");
- xw.Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}");
- xw.EndElement(); // ProjectGuid
- xw.StartElement("Keyword");
- xw.Content("Win32Proj");
- xw.EndElement(); // Keyword
- xw.StartElement("Platform");
- xw.Content(this->GetPlatformName());
- xw.EndElement(); // Platform
- if (this->GetSystemName() == "WindowsPhone") {
- xw.StartElement("ApplicationType");
- xw.Content("Windows Phone");
- xw.EndElement(); // ApplicationType
- xw.StartElement("ApplicationTypeRevision");
- xw.Content(this->GetSystemVersion());
- xw.EndElement(); // ApplicationTypeRevision
- } else if (this->GetSystemName() == "WindowsStore") {
- xw.StartElement("ApplicationType");
- xw.Content("Windows Store");
- xw.EndElement(); // ApplicationType
- xw.StartElement("ApplicationTypeRevision");
- xw.Content(this->GetSystemVersion());
- xw.EndElement(); // ApplicationTypeRevision
- }
- if (!this->WindowsTargetPlatformVersion.empty()) {
- xw.StartElement("WindowsTargetPlatformVersion");
- xw.Content(this->WindowsTargetPlatformVersion);
- xw.EndElement(); // WindowsTargetPlatformVersion
- }
- if (this->GetPlatformName() == "ARM64") {
- xw.StartElement("WindowsSDKDesktopARM64Support");
- xw.Content("true");
- xw.EndElement(); // WindowsSDK64DesktopARMSupport
- }
- else if (this->GetPlatformName() == "ARM") {
- xw.StartElement("WindowsSDKDesktopARMSupport");
- xw.Content("true");
- xw.EndElement(); // WindowsSDKDesktopARMSupport
- }
- xw.EndElement(); // PropertyGroup
- xw.StartElement("Import");
- xw.Attribute("Project",
- "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
- xw.EndElement(); // Import
+ cmXMLDocument doc(xw);
+ cmXMLElement eprj(doc, "Project");
+ eprj.Attribute("DefaultTargets", "Build");
+ eprj.Attribute("ToolsVersion", "4.0");
+ eprj.Attribute("xmlns",
+ "http://schemas.microsoft.com/developer/msbuild/2003");
+ if (this->IsNsightTegra()) {
+ cmXMLElement epg(eprj, "PropertyGroup");
+ epg.Attribute("Label", "NsightTegraProject");
+ cmXMLElement(epg, "NsightTegraProjectRevisionNumber").Content("6");
+ }
+ {
+ cmXMLElement eig(eprj, "ItemGroup");
+ eig.Attribute("Label", "ProjectConfigurations");
+ cmXMLElement epc(eig, "ProjectConfiguration");
+ epc.Attribute("Include", "Debug|" + this->GetPlatformName());
+ cmXMLElement(epc, "Configuration").Content("Debug");
+ cmXMLElement(epc, "Platform").Content(this->GetPlatformName());
+ }
+ {
+ cmXMLElement epg(eprj, "PropertyGroup");
+ epg.Attribute("Label", "Globals");
+ cmXMLElement(epg, "ProjectGuid")
+ .Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}");
+ cmXMLElement(epg, "Keyword").Content("Win32Proj");
+ cmXMLElement(epg, "Platform").Content(this->GetPlatformName());
+ if (this->GetSystemName() == "WindowsPhone") {
+ cmXMLElement(epg, "ApplicationType").Content("Windows Phone");
+ cmXMLElement(epg, "ApplicationTypeRevision")
+ .Content(this->GetSystemVersion());
+ } else if (this->GetSystemName() == "WindowsStore") {
+ cmXMLElement(epg, "ApplicationType").Content("Windows Store");
+ cmXMLElement(epg, "ApplicationTypeRevision")
+ .Content(this->GetSystemVersion());
+ }
+ if (!this->WindowsTargetPlatformVersion.empty()) {
+ cmXMLElement(epg, "WindowsTargetPlatformVersion")
+ .Content(this->WindowsTargetPlatformVersion);
+ }
+ if (this->GetPlatformName() == "ARM64") {
+ cmXMLElement(epg, "WindowsSDKDesktopARM64Support").Content("true");
+ } else if (this->GetPlatformName() == "ARM") {
+ cmXMLElement(epg, "WindowsSDKDesktopARMSupport").Content("true");
+ }
+ }
+ cmXMLElement(eprj, "Import")
+ .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
if (!this->GeneratorToolsetHostArchitecture.empty()) {
- xw.StartElement("PropertyGroup");
- xw.StartElement("PreferredToolArchitecture");
- xw.Content(this->GeneratorToolsetHostArchitecture);
- xw.EndElement(); // PreferredToolArchitecture
- xw.EndElement(); // PropertyGroup
+ cmXMLElement epg(eprj, "PropertyGroup");
+ cmXMLElement(epg, "PreferredToolArchitecture")
+ .Content(this->GeneratorToolsetHostArchitecture);
}
- xw.StartElement("PropertyGroup");
- xw.Attribute("Label", "Configuration");
- xw.StartElement("ConfigurationType");
+ {
+ cmXMLElement epg(eprj, "PropertyGroup");
+ epg.Attribute("Label", "Configuration");
+ {
+ cmXMLElement ect(epg, "ConfigurationType");
+ if (this->IsNsightTegra()) {
+ // Tegra-Android platform does not understand "Utility".
+ ect.Content("StaticLibrary");
+ } else {
+ ect.Content("Utility");
+ }
+ }
+ cmXMLElement(epg, "CharacterSet").Content("MultiByte");
if (this->IsNsightTegra()) {
- // Tegra-Android platform does not understand "Utility".
- xw.Content("StaticLibrary");
+ cmXMLElement(epg, "NdkToolchainVersion")
+ .Content(this->GetPlatformToolsetString());
} else {
- xw.Content("Utility");
+ cmXMLElement(epg, "PlatformToolset")
+ .Content(this->GetPlatformToolsetString());
}
- xw.EndElement(); // ConfigurationType
- xw.StartElement("CharacterSet");
- xw.Content("MultiByte");
- xw.EndElement(); // CharacterSet
- if (this->IsNsightTegra()) {
- xw.StartElement("NdkToolchainVersion");
- xw.Content(this->GetPlatformToolsetString());
- xw.EndElement(); // NdkToolchainVersion
- } else {
- xw.StartElement("PlatformToolset");
- xw.Content(this->GetPlatformToolsetString());
- xw.EndElement(); // PlatformToolset
- }
- xw.EndElement(); // PropertyGroup
- xw.StartElement("Import");
- xw.Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
- xw.EndElement(); // Import
- xw.StartElement("ItemDefinitionGroup");
- xw.StartElement("PostBuildEvent");
- xw.StartElement("Command");
- xw.Content("echo VCTargetsPath=$(VCTargetsPath)");
- xw.EndElement(); // Command
- xw.EndElement(); // PostBuildEvent
- xw.EndElement(); // ItemDefinitionGroup
- xw.StartElement("Import");
- xw.Attribute("Project",
- "$(VCTargetsPath)\\Microsoft.Cpp.targets");
- xw.EndElement(); // Import
- xw.EndElement(); // Project
- xw.EndDocument();
- /* clang-format on */
+ }
+ cmXMLElement(eprj, "Import")
+ .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
+ {
+ cmXMLElement eidg(eprj, "ItemDefinitionGroup");
+ cmXMLElement epbe(eidg, "PostBuildEvent");
+ cmXMLElement(epbe, "Command")
+ .Content("echo VCTargetsPath=$(VCTargetsPath)");
+ }
+ cmXMLElement(eprj, "Import")
+ .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");
}
std::vector<std::string> cmd;
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index c915dc5..7ff007f 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -294,19 +294,6 @@ void cmGlobalVisualStudio7Generator::Generate()
if (!cmSystemTools::GetErrorOccuredFlag()) {
this->CallVisualStudioMacro(MacroReload);
}
-
- if (this->Version == VS8 && !this->CMakeInstance->GetIsInTryCompile()) {
- const char* cmakeWarnVS8 =
- this->CMakeInstance->GetState()->GetCacheEntryValue("CMAKE_WARN_VS8");
- if (!cmakeWarnVS8 || !cmSystemTools::IsOff(cmakeWarnVS8)) {
- this->CMakeInstance->IssueMessage(
- cmake::WARNING,
- "The \"Visual Studio 8 2005\" generator is deprecated "
- "and will be removed in a future version of CMake."
- "\n"
- "Add CMAKE_WARN_VS8=OFF to the cache to disable this warning.");
- }
- }
}
void cmGlobalVisualStudio7Generator::OutputSLNFile(
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index ab8ad70..ad72f5e 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -11,75 +11,6 @@
#include "cmVisualStudioWCEPlatformParser.h"
#include "cmake.h"
-static const char vs8generatorName[] = "Visual Studio 8 2005";
-
-class cmGlobalVisualStudio8Generator::Factory : public cmGlobalGeneratorFactory
-{
-public:
- cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
- cmake* cm) const override
- {
- if (strncmp(name.c_str(), vs8generatorName,
- sizeof(vs8generatorName) - 1) != 0) {
- return 0;
- }
-
- const char* p = name.c_str() + sizeof(vs8generatorName) - 1;
- if (p[0] == '\0') {
- return new cmGlobalVisualStudio8Generator(cm, name, "");
- }
-
- if (p[0] != ' ') {
- return 0;
- }
-
- ++p;
-
- if (!strcmp(p, "Win64")) {
- return new cmGlobalVisualStudio8Generator(cm, name, "x64");
- }
-
- cmVisualStudioWCEPlatformParser parser(p);
- parser.ParseVersion("8.0");
- if (!parser.Found()) {
- return 0;
- }
-
- cmGlobalVisualStudio8Generator* ret =
- new cmGlobalVisualStudio8Generator(cm, name, p);
- ret->WindowsCEVersion = parser.GetOSVersion();
- return ret;
- }
-
- void GetDocumentation(cmDocumentationEntry& entry) const override
- {
- entry.Name = std::string(vs8generatorName) + " [arch]";
- entry.Brief = "Deprecated. Generates Visual Studio 2005 project files. "
- "Optional [arch] can be \"Win64\".";
- }
-
- void GetGenerators(std::vector<std::string>& names) const override
- {
- names.push_back(vs8generatorName);
- names.push_back(vs8generatorName + std::string(" Win64"));
- cmVisualStudioWCEPlatformParser parser;
- parser.ParseVersion("8.0");
- const std::vector<std::string>& availablePlatforms =
- parser.GetAvailablePlatforms();
- for (std::string const& i : availablePlatforms) {
- names.push_back("Visual Studio 8 2005 " + i);
- }
- }
-
- bool SupportsToolset() const override { return false; }
- bool SupportsPlatform() const override { return true; }
-};
-
-cmGlobalGeneratorFactory* cmGlobalVisualStudio8Generator::NewFactory()
-{
- return new Factory;
-}
-
cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator(
cmake* cm, const std::string& name, const std::string& platformName)
: cmGlobalVisualStudio71Generator(cm, platformName)
@@ -87,12 +18,6 @@ cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator(
this->ProjectConfigurationSectionName = "ProjectConfigurationPlatforms";
this->Name = name;
this->ExtraFlagTable = this->GetExtraFlagTableVS8();
- this->Version = VS8;
- std::string vc8Express;
- this->ExpressEdition = cmSystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\8.0\\Setup\\VC;"
- "ProductDir",
- vc8Express, cmSystemTools::KeyWOW64_32);
}
std::string cmGlobalVisualStudio8Generator::FindDevEnvCommand()
@@ -143,13 +68,6 @@ bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p,
}
}
-// output standard header for dsw file
-void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout)
-{
- fout << "Microsoft Visual Studio Solution File, Format Version 9.00\n";
- fout << "# Visual Studio 2005\n";
-}
-
std::string cmGlobalVisualStudio8Generator::GetGenerateStampList()
{
return "generate.stamp.list";
@@ -165,46 +83,6 @@ bool cmGlobalVisualStudio8Generator::UseFolderProperty()
return IsExpressEdition() ? false : cmGlobalGenerator::UseFolderProperty();
}
-std::string cmGlobalVisualStudio8Generator::GetUserMacrosDirectory()
-{
- // Some VS8 sp0 versions cannot run macros.
- // See http://support.microsoft.com/kb/928209
- const char* vc8sp1Registry =
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\"
- "InstalledProducts\\KB926601;";
- const char* vc8exSP1Registry =
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\"
- "InstalledProducts\\KB926748;";
- std::string vc8sp1;
- if (!cmSystemTools::ReadRegistryValue(vc8sp1Registry, vc8sp1) &&
- !cmSystemTools::ReadRegistryValue(vc8exSP1Registry, vc8sp1)) {
- return "";
- }
-
- std::string base;
- std::string path;
-
- // base begins with the VisualStudioProjectsLocation reg value...
- if (cmSystemTools::ReadRegistryValue(
- "HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio\\8.0;"
- "VisualStudioProjectsLocation",
- base)) {
- cmSystemTools::ConvertToUnixSlashes(base);
-
- // 8.0 macros folder:
- path = base + "/VSMacros80";
- }
-
- // path is (correctly) still empty if we did not read the base value from
- // the Registry value
- return path;
-}
-
-std::string cmGlobalVisualStudio8Generator::GetUserMacrosRegKeyBase()
-{
- return "Software\\Microsoft\\VisualStudio\\8.0\\vsmacros";
-}
-
bool cmGlobalVisualStudio8Generator::AddCheckTarget()
{
// Add a special target on which all other targets depend that
@@ -217,7 +95,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
cmMakefile* mf = lg->GetMakefile();
// Skip the target if no regeneration is to be done.
- if (mf->IsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
return false;
}
diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h
index af83e4f..6f64b9c 100644
--- a/Source/cmGlobalVisualStudio8Generator.h
+++ b/Source/cmGlobalVisualStudio8Generator.h
@@ -15,7 +15,6 @@ class cmGlobalVisualStudio8Generator : public cmGlobalVisualStudio71Generator
public:
cmGlobalVisualStudio8Generator(cmake* cm, const std::string& name,
const std::string& platformName);
- static cmGlobalGeneratorFactory* NewFactory();
///! Get the name for the generator.
std::string GetName() const override { return this->Name; }
@@ -35,19 +34,6 @@ public:
*/
void Configure() override;
- /**
- * Where does this version of Visual Studio look for macros for the
- * current user? Returns the empty string if this version of Visual
- * Studio does not implement support for VB macros.
- */
- std::string GetUserMacrosDirectory() override;
-
- /**
- * What is the reg key path to "vsmacros" for this version of Visual
- * Studio?
- */
- std::string GetUserMacrosRegKeyBase() override;
-
/** Return true if the target project file should have the option
LinkLibraryDependencies and link to .sln dependencies. */
bool NeedLinkLibraryDependencies(cmGeneratorTarget* target) override;
@@ -75,7 +61,6 @@ protected:
virtual bool NeedsDeploy(cmStateEnums::TargetType type) const;
static cmIDEFlagTable const* GetExtraFlagTableVS8();
- void WriteSLNHeader(std::ostream& fout) override;
void WriteSolutionConfigurations(
std::ostream& fout, std::vector<std::string> const& configs) override;
void WriteProjectConfigurations(
@@ -93,9 +78,5 @@ protected:
std::string Name;
std::string WindowsCEVersion;
bool ExpressEdition;
-
-private:
- class Factory;
- friend class Factory;
};
#endif
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index a4570e1..fa7dc51 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -737,26 +737,24 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
bool cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(
cmGeneratorTarget const* gt)
{
- // check to see if this is a C# build
- std::set<std::string> languages;
- {
- // Issue diagnostic if the source files depend on the config.
- std::vector<cmSourceFile*> sources;
- if (!gt->GetConfigCommonSourceFiles(sources)) {
- return false;
- }
- // Only "real" targets are allowed to be C# targets.
- if (gt->Target->GetType() > cmStateEnums::OBJECT_LIBRARY) {
- return false;
- }
+ // C# targets can be defined with add_library() (using SHARED or STATIC) and
+ // also using add_executable(). We do not treat imported C# targets the same
+ // (these come in as UTILITY)
+ if (gt->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ gt->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ gt->GetType() != cmStateEnums::EXECUTABLE) {
+ return false;
}
- gt->GetLanguages(languages, "");
- if (languages.size() == 1) {
- if (*languages.begin() == "CSharp") {
- return true;
- }
+
+ // Issue diagnostic if the source files depend on the config.
+ std::vector<cmSourceFile*> sources;
+ if (!gt->GetConfigCommonSourceFiles(sources)) {
+ return false;
}
- return false;
+
+ std::set<std::string> languages;
+ gt->GetLanguages(languages, "");
+ return languages.size() == 1 && languages.count("CSharp") > 0;
}
bool cmGlobalVisualStudioGenerator::TargetCanBeReferenced(
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index 75b7f22..f39dcca 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -32,7 +32,6 @@ public:
/** Known versions of Visual Studio. */
enum VSVersion
{
- VS8 = 80,
VS9 = 90,
VS10 = 100,
VS11 = 110,
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 8f61071..f8597af 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -458,7 +458,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
makeHelper.push_back(""); // placeholder, see below
// Add ZERO_CHECK
- bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION");
+ bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
bool generateTopLevelProjectOnly =
mf->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY");
bool isTopLevel =
@@ -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;
@@ -3193,7 +3189,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 =
@@ -3221,7 +3217,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);
}
@@ -3236,7 +3232,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);
}
@@ -3244,8 +3240,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) {
@@ -3257,8 +3252,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/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index 354b757..f996788 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -25,7 +25,7 @@ cmIDEOptions::~cmIDEOptions()
{
}
-void cmIDEOptions::HandleFlag(const char* flag)
+void cmIDEOptions::HandleFlag(std::string const& flag)
{
// If the last option was -D then this option is the definition.
if (this->DoingDefine) {
@@ -49,26 +49,27 @@ void cmIDEOptions::HandleFlag(const char* flag)
}
// Look for known arguments.
- if (flag[0] == '-' || (this->AllowSlash && flag[0] == '/')) {
+ size_t len = flag.length();
+ if (len > 0 && (flag[0] == '-' || (this->AllowSlash && flag[0] == '/'))) {
// Look for preprocessor definitions.
- if (this->AllowDefine && flag[1] == 'D') {
- if (flag[2] == '\0') {
+ if (this->AllowDefine && len > 1 && flag[1] == 'D') {
+ if (len <= 2) {
// The next argument will have the definition.
this->DoingDefine = true;
} else {
// Store this definition.
- this->Defines.push_back(flag + 2);
+ this->Defines.push_back(flag.substr(2));
}
return;
}
// Look for include directory.
- if (this->AllowInclude && flag[1] == 'I') {
- if (flag[2] == '\0') {
+ if (this->AllowInclude && len > 1 && flag[1] == 'I') {
+ if (len <= 2) {
// The next argument will have the include directory.
this->DoingInclude = true;
} else {
// Store this include directory.
- this->Includes.push_back(flag + 2);
+ this->Includes.push_back(flag.substr(2));
}
return;
}
@@ -92,8 +93,9 @@ void cmIDEOptions::HandleFlag(const char* flag)
}
bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
- const char* flag, bool& flag_handled)
+ std::string const& flag, bool& flag_handled)
{
+ const char* pf = flag.c_str() + 1;
// Look for an entry in the flag table matching this flag.
for (cmIDEFlagTable const* entry = table; entry->IDEName; ++entry) {
bool entry_found = false;
@@ -102,17 +104,17 @@ bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
// the entry specifies UserRequired we must match only if a
// non-empty value is given.
int n = static_cast<int>(strlen(entry->commandFlag));
- if ((strncmp(flag + 1, entry->commandFlag, n) == 0 ||
+ if ((strncmp(pf, entry->commandFlag, n) == 0 ||
(entry->special & cmIDEFlagTable::CaseInsensitive &&
- cmsysString_strncasecmp(flag + 1, entry->commandFlag, n))) &&
+ cmsysString_strncasecmp(pf, entry->commandFlag, n))) &&
(!(entry->special & cmIDEFlagTable::UserRequired) ||
- static_cast<int>(strlen(flag + 1)) > n)) {
- this->FlagMapUpdate(entry, flag + n + 1);
+ static_cast<int>(strlen(pf)) > n)) {
+ this->FlagMapUpdate(entry, std::string(pf + n));
entry_found = true;
}
- } else if (strcmp(flag + 1, entry->commandFlag) == 0 ||
+ } else if (strcmp(pf, entry->commandFlag) == 0 ||
(entry->special & cmIDEFlagTable::CaseInsensitive &&
- cmsysString_strcasecmp(flag + 1, entry->commandFlag) == 0)) {
+ cmsysString_strcasecmp(pf, entry->commandFlag) == 0)) {
if (entry->special & cmIDEFlagTable::UserFollowing) {
// This flag expects a value in the following argument.
this->DoingFollowing = entry;
@@ -137,7 +139,7 @@ bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
}
void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry,
- const char* new_value)
+ std::string const& new_value)
{
if (entry->special & cmIDEFlagTable::UserIgnored) {
// Ignore the user-specified value.
@@ -157,9 +159,9 @@ void cmIDEOptions::AddDefine(const std::string& def)
this->Defines.push_back(def);
}
-void cmIDEOptions::AddDefines(const char* defines)
+void cmIDEOptions::AddDefines(std::string const& defines)
{
- if (defines) {
+ if (!defines.empty()) {
// Expand the list of definitions.
cmSystemTools::ExpandListArgument(defines, this->Defines);
}
@@ -179,9 +181,9 @@ void cmIDEOptions::AddInclude(const std::string& include)
this->Includes.push_back(include);
}
-void cmIDEOptions::AddIncludes(const char* includes)
+void cmIDEOptions::AddIncludes(std::string const& includes)
{
- if (includes) {
+ if (!includes.empty()) {
// Expand the list of includes.
cmSystemTools::ExpandListArgument(includes, this->Includes);
}
diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h
index 54cb524..a4e5757 100644
--- a/Source/cmIDEOptions.h
+++ b/Source/cmIDEOptions.h
@@ -22,12 +22,12 @@ public:
// Store definitions, includes and flags.
void AddDefine(const std::string& define);
- void AddDefines(const char* defines);
+ void AddDefines(std::string const& defines);
void AddDefines(const std::vector<std::string>& defines);
std::vector<std::string> const& GetDefines() const;
void AddInclude(const std::string& includes);
- void AddIncludes(const char* includes);
+ void AddIncludes(std::string const& includes);
void AddIncludes(const std::vector<std::string>& includes);
std::vector<std::string> const& GetIncludes() const;
@@ -95,11 +95,12 @@ protected:
FlagTableCount = 16
};
cmIDEFlagTable const* FlagTable[FlagTableCount];
- void HandleFlag(const char* flag);
- bool CheckFlagTable(cmIDEFlagTable const* table, const char* flag,
+ void HandleFlag(std::string const& flag);
+ bool CheckFlagTable(cmIDEFlagTable const* table, std::string const& flag,
bool& flag_handled);
- void FlagMapUpdate(cmIDEFlagTable const* entry, const char* new_value);
- virtual void StoreUnknownFlag(const char* flag) = 0;
+ void FlagMapUpdate(cmIDEFlagTable const* entry,
+ std::string const& new_value);
+ virtual void StoreUnknownFlag(std::string const& flag) = 0;
};
#endif
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 394f976..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()) {
@@ -360,17 +361,6 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
this->SetError(e.str());
return false;
}
- if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::string reason;
- if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation(
- &reason)) {
- std::ostringstream e;
- e << "TARGETS given OBJECT library \"" << tgt
- << "\" which may not be installed" << reason << ".";
- this->SetError(e.str());
- return false;
- }
- }
// Store the target in the list to be installed.
targets.push_back(target);
} else {
@@ -534,15 +524,23 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
case cmStateEnums::OBJECT_LIBRARY: {
// Objects use OBJECT properties.
if (!objectArgs.GetDestination().empty()) {
+ // Verify that we know where the objects are to install them.
+ std::string reason;
+ if (!this->Makefile->GetGlobalGenerator()
+ ->HasKnownObjectFileLocation(&reason)) {
+ std::ostringstream e;
+ e << "TARGETS given OBJECT library \"" << target.GetName()
+ << "\" whose objects may not be installed" << reason << ".";
+ this->SetError(e.str());
+ return false;
+ }
+
objectGenerator =
CreateInstallTargetGenerator(target, objectArgs, false);
} else {
- std::ostringstream e;
- e << "TARGETS given no OBJECTS DESTINATION for object library "
- "target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
- return false;
+ // Installing an OBJECT library without a destination transforms
+ // it to an INTERFACE library. It installs no files but can be
+ // exported.
}
} break;
case cmStateEnums::EXECUTABLE: {
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
index 3beeae3..557fa41 100644
--- a/Source/cmLinkLineDeviceComputer.cxx
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -3,9 +3,9 @@
#include "cmLinkLineDeviceComputer.h"
-#include <set>
#include <sstream>
+#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
@@ -32,38 +32,32 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
ItemVector const& items = cli.GetItems();
std::string config = cli.GetConfig();
for (auto const& item : items) {
- if (!item.Target) {
- continue;
- }
-
- bool skippable = false;
- switch (item.Target->GetType()) {
- case cmStateEnums::SHARED_LIBRARY:
- case cmStateEnums::MODULE_LIBRARY:
- case cmStateEnums::INTERFACE_LIBRARY:
- skippable = true;
- break;
- case cmStateEnums::STATIC_LIBRARY:
- // If a static library is resolving its device linking, it should
- // be removed for other device linking
- skippable =
- item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
- break;
- default:
- break;
- }
-
- if (skippable) {
- continue;
- }
-
- std::set<std::string> langs;
- item.Target->GetLanguages(langs, config);
- if (langs.count("CUDA") == 0) {
- continue;
+ if (item.Target) {
+ bool skip = false;
+ switch (item.Target->GetType()) {
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ skip = true;
+ break;
+ case cmStateEnums::STATIC_LIBRARY:
+ skip = item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
+ break;
+ default:
+ break;
+ }
+ if (skip) {
+ continue;
+ }
}
if (item.IsPath) {
+ // nvcc understands absolute paths to libraries ending in '.a' should
+ // be passed to nvlink. Other extensions like '.so' or '.dylib' are
+ // rejected by the nvcc front-end even though nvlink knows to ignore
+ // them. Bypass the front-end via '-Xnvlink'.
+ if (!cmHasLiteralSuffix(item.Value, ".a")) {
+ fout << "-Xnvlink ";
+ }
fout << this->ConvertToOutputFormat(
this->ConvertToLinkReference(item.Value));
} else {
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index ae4f0a8..821e6d1 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -42,6 +42,9 @@ bool cmListCommand::InitialPass(std::vector<std::string> const& args,
if (subCommand == "INSERT") {
return this->HandleInsertCommand(args);
}
+ if (subCommand == "JOIN") {
+ return this->HandleJoinCommand(args);
+ }
if (subCommand == "REMOVE_AT") {
return this->HandleRemoveAtCommand(args);
}
@@ -54,6 +57,9 @@ bool cmListCommand::InitialPass(std::vector<std::string> const& args,
if (subCommand == "SORT") {
return this->HandleSortCommand(args);
}
+ if (subCommand == "SUBLIST") {
+ return this->HandleSublistCommand(args);
+ }
if (subCommand == "REVERSE") {
return this->HandleReverseCommand(args);
}
@@ -294,6 +300,34 @@ bool cmListCommand::HandleInsertCommand(std::vector<std::string> const& args)
return true;
}
+bool cmListCommand::HandleJoinCommand(std::vector<std::string> const& args)
+{
+ if (args.size() != 4) {
+ std::ostringstream error;
+ error << "sub-command JOIN requires three arguments (" << args.size() - 1
+ << " found).";
+ this->SetError(error.str());
+ return false;
+ }
+
+ const std::string& listName = args[1];
+ const std::string& glue = args[2];
+ const std::string& variableName = args[3];
+
+ // expand the variable
+ std::vector<std::string> varArgsExpanded;
+ if (!this->GetList(varArgsExpanded, listName)) {
+ this->Makefile->AddDefinition(variableName, "");
+ return true;
+ }
+
+ std::string value =
+ cmJoin(cmMakeRange(varArgsExpanded.begin(), varArgsExpanded.end()), glue);
+
+ this->Makefile->AddDefinition(variableName, value.c_str());
+ return true;
+}
+
bool cmListCommand::HandleRemoveItemCommand(
std::vector<std::string> const& args)
{
@@ -396,6 +430,55 @@ bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args)
return true;
}
+bool cmListCommand::HandleSublistCommand(std::vector<std::string> const& args)
+{
+ if (args.size() != 5) {
+ std::ostringstream error;
+ error << "sub-command SUBLIST requires four arguments (" << args.size() - 1
+ << " found).";
+ this->SetError(error.str());
+ return false;
+ }
+
+ const std::string& listName = args[1];
+ const std::string& variableName = args[args.size() - 1];
+
+ // expand the variable
+ std::vector<std::string> varArgsExpanded;
+ if (!this->GetList(varArgsExpanded, listName) || varArgsExpanded.empty()) {
+ this->Makefile->AddDefinition(variableName, "");
+ return true;
+ }
+
+ const int start = atoi(args[2].c_str());
+ const int length = atoi(args[3].c_str());
+
+ using size_type = decltype(varArgsExpanded)::size_type;
+
+ if (start < 0 || size_type(start) >= varArgsExpanded.size()) {
+ std::ostringstream error;
+ error << "begin index: " << start << " is out of range 0 - "
+ << varArgsExpanded.size() - 1;
+ this->SetError(error.str());
+ return false;
+ }
+ if (length < -1) {
+ std::ostringstream error;
+ error << "length: " << length << " should be -1 or greater";
+ this->SetError(error.str());
+ return false;
+ }
+
+ const size_type end =
+ (length == -1 || size_type(start + length) > varArgsExpanded.size())
+ ? varArgsExpanded.size()
+ : size_type(start + length);
+ std::vector<std::string> sublist(varArgsExpanded.begin() + start,
+ varArgsExpanded.begin() + end);
+ this->Makefile->AddDefinition(variableName, cmJoin(sublist, ";").c_str());
+ return true;
+}
+
bool cmListCommand::HandleRemoveAtCommand(std::vector<std::string> const& args)
{
if (args.size() < 3) {
diff --git a/Source/cmListCommand.h b/Source/cmListCommand.h
index 2965399..d69d8f9 100644
--- a/Source/cmListCommand.h
+++ b/Source/cmListCommand.h
@@ -37,10 +37,12 @@ protected:
bool HandleAppendCommand(std::vector<std::string> const& args);
bool HandleFindCommand(std::vector<std::string> const& args);
bool HandleInsertCommand(std::vector<std::string> const& args);
+ bool HandleJoinCommand(std::vector<std::string> const& args);
bool HandleRemoveAtCommand(std::vector<std::string> const& args);
bool HandleRemoveItemCommand(std::vector<std::string> const& args);
bool HandleRemoveDuplicatesCommand(std::vector<std::string> const& args);
bool HandleSortCommand(std::vector<std::string> const& args);
+ bool HandleSublistCommand(std::vector<std::string> const& args);
bool HandleReverseCommand(std::vector<std::string> const& args);
bool HandleFilterCommand(std::vector<std::string> const& args);
bool FilterRegex(std::vector<std::string> const& args, bool includeMatches,
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index e942ff4..629d54a 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1561,6 +1561,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
static std::map<std::string, std::vector<std::string>> langStdMap;
if (langStdMap.empty()) {
// Maintain sorted order, most recent first.
+ langStdMap["CXX"].push_back("20");
langStdMap["CXX"].push_back("17");
langStdMap["CXX"].push_back("14");
langStdMap["CXX"].push_back("11");
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 8c889fc..c1af92f 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <utility>
+#include "cmCryptoHash.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
@@ -24,6 +25,7 @@
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmake.h"
+#include "cmsys/FStream.hxx"
cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
cmMakefile* mf)
@@ -286,8 +288,51 @@ void cmLocalNinjaGenerator::AppendCustomCommandDeps(
}
}
+std::string cmLocalNinjaGenerator::WriteCommandScript(
+ std::vector<std::string> const& cmdLines, std::string const& customStep,
+ cmGeneratorTarget const* target) const
+{
+ std::string scriptPath;
+ if (target) {
+ scriptPath = target->GetSupportDirectory();
+ } else {
+ scriptPath = this->GetCurrentBinaryDirectory();
+ scriptPath += cmake::GetCMakeFilesDirectory();
+ }
+ cmSystemTools::MakeDirectory(scriptPath);
+ scriptPath += '/';
+ scriptPath += customStep;
+#ifdef _WIN32
+ scriptPath += ".bat";
+#else
+ scriptPath += ".sh";
+#endif
+
+ cmsys::ofstream script(scriptPath.c_str());
+
+#ifndef _WIN32
+ script << "set -e\n\n";
+#endif
+
+ for (auto const& i : cmdLines) {
+ std::string cmd = i;
+ // The command line was built assuming it would be written to
+ // the build.ninja file, so it uses '$$' for '$'. Remove this
+ // for the raw shell script.
+ cmSystemTools::ReplaceString(cmd, "$$", "$");
+#ifdef _WIN32
+ script << cmd << " || exit /b" << '\n';
+#else
+ script << cmd << '\n';
+#endif
+ }
+
+ return scriptPath;
+}
+
std::string cmLocalNinjaGenerator::BuildCommandLine(
- const std::vector<std::string>& cmdLines)
+ std::vector<std::string> const& cmdLines, std::string const& customStep,
+ cmGeneratorTarget const* target) const
{
// If we have no commands but we need to build a command anyway, use noop.
// This happens when building a POST_BUILD value for link targets that
@@ -296,6 +341,35 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
return cmGlobalNinjaGenerator::SHELL_NOOP;
}
+ // If this is a custom step then we will have no '$VAR' ninja placeholders.
+ // This means we can deal with long command sequences by writing to a script.
+ // Do this if the command lines are on the scale of the OS limit.
+ if (!customStep.empty()) {
+ size_t cmdLinesTotal = 0;
+ for (std::string const& cmd : cmdLines) {
+ cmdLinesTotal += cmd.length() + 6;
+ }
+ if (cmdLinesTotal > cmSystemTools::CalculateCommandLineLengthLimit() / 2) {
+ std::string const scriptPath =
+ this->WriteCommandScript(cmdLines, customStep, target);
+ std::string cmd
+#ifndef _WIN32
+ = "/bin/sh "
+#endif
+ ;
+ cmd += this->ConvertToOutputFormat(
+ this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(scriptPath),
+ cmOutputConverter::SHELL);
+
+ // Add an unused argument based on script content so that Ninja
+ // knows when the command lines change.
+ cmd += " ";
+ cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+ cmd += hash.HashFile(scriptPath).substr(0, 16);
+ return cmd;
+ }
+ }
+
std::ostringstream cmd;
for (std::vector<std::string>::const_iterator li = cmdLines.begin();
li != cmdLines.end(); ++li)
@@ -406,10 +480,16 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
"Phony custom command for " + ninjaOutputs[0], ninjaOutputs, ninjaDeps,
cmNinjaDeps(), orderOnlyDeps, cmNinjaVars());
} else {
+ std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]);
+ // Hash full path to make unique.
+ customStep += '-';
+ cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+ customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
+
this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild(
- this->BuildCommandLine(cmdLines), this->ConstructComment(ccg),
- "Custom command for " + ninjaOutputs[0], cc->GetDepfile(),
- cc->GetUsesTerminal(),
+ this->BuildCommandLine(cmdLines, customStep),
+ this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
+ cc->GetDepfile(), cc->GetUsesTerminal(),
/*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, ninjaDeps,
orderOnlyDeps);
}
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 95d8a61..f772fb0 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -59,7 +59,10 @@ public:
return this->HomeRelativeOutputPath;
}
- std::string BuildCommandLine(const std::vector<std::string>& cmdLines);
+ std::string BuildCommandLine(
+ std::vector<std::string> const& cmdLines,
+ std::string const& customStep = std::string(),
+ cmGeneratorTarget const* target = nullptr) const;
void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs);
void AppendTargetDepends(
@@ -98,6 +101,10 @@ private:
std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg);
+ std::string WriteCommandScript(std::vector<std::string> const& cmdLines,
+ std::string const& customStep,
+ cmGeneratorTarget const* target) const;
+
std::string HomeRelativeOutputPath;
typedef std::map<cmCustomCommand const*, std::set<cmGeneratorTarget*>>
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index ddd8cc4..c9237a8 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -760,7 +760,8 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom(
// Write special "cmake_check_build_system" target to run cmake with
// the --check-build-system flag.
- {
+ if (!this->GlobalGenerator->GlobalSettingIsOn(
+ "CMAKE_SUPPRESS_REGENERATION")) {
// Build command to run CMake to check if anything needs regenerating.
std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash();
cmakefileName += "Makefile.cmake";
@@ -1580,7 +1581,11 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
std::string recursiveTarget = this->GetCurrentBinaryDirectory();
recursiveTarget += "/all";
- depends.push_back("cmake_check_build_system");
+ bool regenerate =
+ !this->GlobalGenerator->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
std::string progressDir = this->GetBinaryDirectory();
progressDir += cmake::GetCMakeFilesDirectory();
@@ -1643,7 +1648,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
if (!noall || cmSystemTools::IsOff(noall)) {
// Drive the build before installing.
depends.push_back("all");
- } else {
+ } else if (regenerate) {
// At least make sure the build system is up to date.
depends.push_back("cmake_check_build_system");
}
@@ -1657,24 +1662,26 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
this->WriteMakeRule(ruleFileStream, "Prepare targets for installation.",
"preinstall/fast", depends, commands, true);
- // write the depend rule, really a recompute depends rule
- depends.clear();
- commands.clear();
- std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash();
- cmakefileName += "Makefile.cmake";
- {
- std::string runRule =
- "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
- runRule += " --check-build-system ";
- runRule +=
- this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL);
- runRule += " 1";
- commands.push_back(std::move(runRule));
+ if (regenerate) {
+ // write the depend rule, really a recompute depends rule
+ depends.clear();
+ commands.clear();
+ std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash();
+ cmakefileName += "Makefile.cmake";
+ {
+ std::string runRule =
+ "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
+ runRule += " --check-build-system ";
+ runRule +=
+ this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL);
+ runRule += " 1";
+ commands.push_back(std::move(runRule));
+ }
+ this->CreateCDCommand(commands, this->GetBinaryDirectory(),
+ this->GetCurrentBinaryDirectory());
+ this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends,
+ commands, true);
}
- this->CreateCDCommand(commands, this->GetBinaryDirectory(),
- this->GetCurrentBinaryDirectory());
- this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends,
- commands, true);
}
void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf,
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 98b1c44..91ee09f 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -210,7 +210,8 @@ void cmLocalVisualStudio7Generator::CreateSingleVCProj(
cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
{
- if (this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ if (this->GlobalGenerator->GlobalSettingIsOn(
+ "CMAKE_SUPPRESS_REGENERATION")) {
return nullptr;
}
@@ -791,10 +792,9 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
<< "\\$(ConfigurationName)\"\n";
}
targetOptions.OutputAdditionalIncludeDirectories(
- fout, "\t\t\t\t", "\n",
- this->FortranProject ? "Fortran" : langForClCompile);
+ fout, "\t\t\t\t", this->FortranProject ? "Fortran" : langForClCompile);
targetOptions.OutputFlagMap(fout, "\t\t\t\t");
- targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n",
+ targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t",
langForClCompile);
fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n";
if (target->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
@@ -814,11 +814,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
"\t\t\t\tName=\"MASM\"\n"
;
/* clang-format on */
- targetOptions.OutputAdditionalIncludeDirectories(fout, "\t\t\t\t", "\n",
+ targetOptions.OutputAdditionalIncludeDirectories(fout, "\t\t\t\t",
"ASM_MASM");
// Use same preprocessor definitions as VCCLCompilerTool.
- targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n",
- "ASM_MASM");
+ targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "ASM_MASM");
masmOptions.OutputFlagMap(fout, "\t\t\t\t");
/* clang-format off */
fout <<
@@ -836,18 +835,16 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
tool = "VFResourceCompilerTool";
}
fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n";
- targetOptions.OutputAdditionalIncludeDirectories(fout, "\n\t\t\t\t", "",
- "RC");
+ targetOptions.OutputAdditionalIncludeDirectories(fout, "\t\t\t\t", "RC");
// add the -D flags to the RC tool
- targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "", "RC");
- fout << "/>\n";
+ targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "RC");
+ fout << "\t\t\t/>\n";
tool = "VCMIDLTool";
if (this->FortranProject) {
tool = "VFMIDLTool";
}
fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n";
- targetOptions.OutputAdditionalIncludeDirectories(fout, "\n\t\t\t\t", "",
- "MIDL");
+ targetOptions.OutputAdditionalIncludeDirectories(fout, "\t\t\t\t", "MIDL");
fout << "\t\t\t\tMkTypLibCompatible=\"false\"\n";
if (gg->GetPlatformName() == "x64") {
fout << "\t\t\t\tTargetEnvironment=\"3\"\n";
@@ -1677,17 +1674,17 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
}
Options fileOptions(this, tool, table, gg->ExtraFlagTable);
fileOptions.Parse(fc.CompileFlags.c_str());
- fileOptions.AddDefines(fc.CompileDefs.c_str());
- fileOptions.AddDefines(fc.CompileDefsConfig.c_str());
+ fileOptions.AddDefines(fc.CompileDefs);
+ fileOptions.AddDefines(fc.CompileDefsConfig);
// validate source level include directories
std::vector<std::string> includes;
this->AppendIncludeDirectories(includes, fc.IncludeDirs, **sf);
fileOptions.AddIncludes(includes);
fileOptions.OutputFlagMap(fout, "\t\t\t\t\t");
fileOptions.OutputAdditionalIncludeDirectories(
- fout, "\t\t\t\t\t", "\n",
+ fout, "\t\t\t\t\t",
ppLang == "CXX" && this->FortranProject ? "Fortran" : ppLang);
- fileOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t\t", "\n",
+ fileOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t\t",
ppLang);
}
if (!fc.AdditionalDeps.empty()) {
@@ -2064,6 +2061,15 @@ std::string cmLocalVisualStudio7Generator::ConvertToXMLOutputPathSingle(
return ret;
}
+void cmVS7GeneratorOptions::OutputFlag(std::ostream& fout, const char* indent,
+ const char* tag,
+ const std::string& content)
+{
+ fout << indent << tag << "=\"";
+ fout << cmLocalVisualStudio7GeneratorEscapeForXML(content);
+ fout << "\"\n";
+}
+
// This class is used to parse an existing vs 7 project
// and extract the GUID
class cmVS7XMLParser : public cmXMLParser
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index 02e6931..22b4264 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -21,6 +21,19 @@ class cmMakefile;
class cmSourceFile;
class cmSourceGroup;
+class cmVS7GeneratorOptions : public cmVisualStudioGeneratorOptions
+{
+public:
+ cmVS7GeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
+ cmVS7FlagTable const* table = nullptr,
+ cmVS7FlagTable const* extraTable = nullptr)
+ : cmVisualStudioGeneratorOptions(lg, tool, table, extraTable)
+ {
+ }
+ void OutputFlag(std::ostream& fout, const char* indent, const char* tag,
+ const std::string& content) override;
+};
+
/** \class cmLocalVisualStudio7Generator
* \brief Write Visual Studio .NET project files.
*
@@ -70,7 +83,7 @@ protected:
void CreateSingleVCProj(const std::string& lname, cmGeneratorTarget* tgt);
private:
- typedef cmVisualStudioGeneratorOptions Options;
+ typedef cmVS7GeneratorOptions Options;
typedef cmLocalVisualStudio7GeneratorFCInfo FCInfo;
std::string GetBuildTypeLinkerFlags(std::string rootLinkerFlags,
const std::string& configName);
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index b468208..3ecd7eb 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"
@@ -158,6 +158,32 @@ bool cmMakefile::CheckCMP0037(std::string const& targetName,
return true;
}
+void cmMakefile::MaybeWarnCMP0074(std::string const& pkg)
+{
+ // Warn if a <pkg>_ROOT variable we may use is set.
+ std::string const varName = pkg + "_ROOT";
+ const char* var = this->GetDefinition(varName);
+ std::string env;
+ cmSystemTools::GetEnv(varName, env);
+
+ bool const haveVar = var && *var;
+ bool const haveEnv = !env.empty();
+ if ((haveVar || haveEnv) && this->WarnedCMP0074.insert(varName).second) {
+ std::ostringstream w;
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0074) << "\n";
+ if (haveVar) {
+ w << "CMake variable " << varName << " is set to:\n"
+ << " " << var << "\n";
+ }
+ if (haveEnv) {
+ w << "Environment variable " << varName << " is set to:\n"
+ << " " << env << "\n";
+ }
+ w << "For compatibility, CMake is ignoring the variable.";
+ this->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
+}
+
cmStringRange cmMakefile::GetIncludeDirectoriesEntries() const
{
return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries();
@@ -1464,7 +1490,7 @@ void cmMakefile::Configure()
this->SetCheckCMP0000(true);
// Implicitly set the version for the user.
- this->SetPolicyVersion("2.4");
+ this->SetPolicyVersion("2.4", std::string());
}
}
bool hasProject = false;
@@ -1867,7 +1893,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");
}
@@ -3138,6 +3164,14 @@ void cmMakefile::SetArgcArgv(const std::vector<std::string>& args)
cmSourceFile* cmMakefile::GetSource(const std::string& sourceName,
cmSourceFileLocationKind kind) const
{
+ // First check "Known" paths (avoids the creation of cmSourceFileLocation)
+ if (kind == cmSourceFileLocationKind::Known) {
+ auto sfsi = this->KnownFileSearchIndex.find(sourceName);
+ if (sfsi != this->KnownFileSearchIndex.end()) {
+ return sfsi->second;
+ }
+ }
+
cmSourceFileLocation sfl(this, sourceName, kind);
auto name = this->GetCMakeInstance()->StripExtension(sfl.GetName());
#if defined(_WIN32) || defined(__APPLE__)
@@ -3170,6 +3204,10 @@ cmSourceFile* cmMakefile::CreateSource(const std::string& sourceName,
name = cmSystemTools::LowerCase(name);
#endif
this->SourceFileSearchIndex[name].push_back(sf);
+ // for "Known" paths add direct lookup (used for faster lookup in GetSource)
+ if (kind == cmSourceFileLocationKind::Known) {
+ this->KnownFileSearchIndex[sourceName] = sf;
+ }
return sf;
}
@@ -3238,6 +3276,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
@@ -3641,6 +3687,20 @@ void cmMakefile::AppendProperty(const std::string& prop, const char* value,
const char* cmMakefile::GetProperty(const std::string& prop) const
{
+ // Check for computed properties.
+ static std::string output;
+ if (prop == "TESTS") {
+ std::vector<std::string> keys;
+ // get list of keys
+ std::transform(this->Tests.begin(), this->Tests.end(),
+ std::back_inserter(keys),
+ [](decltype(this->Tests)::value_type const& pair) {
+ return pair.first;
+ });
+ output = cmJoin(keys, ";");
+ return output.c_str();
+ }
+
return this->StateSnapshot.GetDirectory().GetProperty(prop);
}
@@ -4115,9 +4175,10 @@ void cmMakefile::PopSnapshot(bool reportError)
assert(this->StateSnapshot.IsValid());
}
-bool cmMakefile::SetPolicyVersion(const char* version)
+bool cmMakefile::SetPolicyVersion(std::string const& version_min,
+ std::string const& version_max)
{
- return cmPolicies::ApplyPolicyVersion(this, version);
+ return cmPolicies::ApplyPolicyVersion(this, version_min, version_max);
}
bool cmMakefile::HasCMP0054AlreadyBeenReported(
@@ -4162,7 +4223,7 @@ static const char* const CXX_FEATURES[] = { nullptr FOR_EACH_CXX_FEATURE(
#undef FEATURE_STRING
static const char* const C_STANDARDS[] = { "90", "99", "11" };
-static const char* const CXX_STANDARDS[] = { "98", "11", "14", "17" };
+static const char* const CXX_STANDARDS[] = { "98", "11", "14", "17", "20" };
bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
const std::string& feature,
@@ -4412,8 +4473,9 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
bool needCxx11 = false;
bool needCxx14 = false;
bool needCxx17 = false;
+ bool needCxx20 = false;
this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14,
- needCxx17);
+ needCxx17, needCxx20);
const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
if (!existingCxxStandard) {
@@ -4433,7 +4495,8 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
/* clang-format off */
const char* const* needCxxLevel =
- needCxx17 ? &CXX_STANDARDS[3]
+ needCxx20 ? &CXX_STANDARDS[4]
+ : needCxx17 ? &CXX_STANDARDS[3]
: needCxx14 ? &CXX_STANDARDS[2]
: needCxx11 ? &CXX_STANDARDS[1]
: needCxx98 ? &CXX_STANDARDS[0]
@@ -4445,7 +4508,8 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
void cmMakefile::CheckNeededCxxLanguage(const std::string& feature,
bool& needCxx98, bool& needCxx11,
- bool& needCxx14, bool& needCxx17) const
+ bool& needCxx14, bool& needCxx17,
+ bool& needCxx20) const
{
if (const char* propCxx98 =
this->GetDefinition("CMAKE_CXX98_COMPILE_FEATURES")) {
@@ -4471,6 +4535,12 @@ void cmMakefile::CheckNeededCxxLanguage(const std::string& feature,
cmSystemTools::ExpandListArgument(propCxx17, props);
needCxx17 = std::find(props.begin(), props.end(), feature) != props.end();
}
+ if (const char* propCxx20 =
+ this->GetDefinition("CMAKE_CXX20_COMPILE_FEATURES")) {
+ std::vector<std::string> props;
+ cmSystemTools::ExpandListArgument(propCxx20, props);
+ needCxx20 = std::find(props.begin(), props.end(), feature) != props.end();
+ }
}
bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
@@ -4481,9 +4551,10 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
bool needCxx11 = false;
bool needCxx14 = false;
bool needCxx17 = false;
+ bool needCxx20 = false;
this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14,
- needCxx17);
+ needCxx17, needCxx20);
const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
const char* const* existingCxxLevel = nullptr;
@@ -4528,7 +4599,8 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
/* clang-format off */
const char* const* needCxxLevel =
- needCxx17 ? &CXX_STANDARDS[3]
+ needCxx20 ? &CXX_STANDARDS[4]
+ : needCxx17 ? &CXX_STANDARDS[3]
: needCxx14 ? &CXX_STANDARDS[2]
: needCxx11 ? &CXX_STANDARDS[1]
: needCxx98 ? &CXX_STANDARDS[0]
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 5a30790..d2626cd 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -285,7 +285,8 @@ public:
bool SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status);
bool SetPolicy(const char* id, cmPolicies::PolicyStatus status);
cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id) const;
- bool SetPolicyVersion(const char* version);
+ bool SetPolicyVersion(std::string const& version_min,
+ std::string const& version_max);
void RecordPolicies(cmPolicies::PolicyMap& pm);
//@}
@@ -832,9 +833,11 @@ public:
void RemoveExportBuildFileGeneratorCMP0024(cmExportBuildFileGenerator* gen);
void AddExportBuildFileGenerator(cmExportBuildFileGenerator* gen);
- // Maintain a stack of package names to determine the depth of find modules
- // we are currently being called with
- std::deque<std::string> FindPackageModuleStack;
+ // Maintain a stack of package roots to allow nested PACKAGE_ROOT_PATH
+ // searches
+ std::deque<std::vector<std::string>> FindPackageRootPathStack;
+
+ void MaybeWarnCMP0074(std::string const& pkg);
protected:
// add link libraries and directories to the target
@@ -861,6 +864,9 @@ protected:
typedef std::unordered_map<std::string, SourceFileVec> SourceFileMap;
SourceFileMap SourceFileSearchIndex;
+ // For "Known" paths we can store a direct filename to cmSourceFile map
+ std::unordered_map<std::string, cmSourceFile*> KnownFileSearchIndex;
+
// Tests
std::map<std::string, cmTest*> Tests;
@@ -985,7 +991,7 @@ private:
bool& needC99, bool& needC11) const;
void CheckNeededCxxLanguage(const std::string& feature, bool& needCxx98,
bool& needCxx11, bool& needCxx14,
- bool& needCxx17) const;
+ bool& needCxx17, bool& needCxx20) const;
bool HaveCStandardAvailable(cmTarget const* target,
const std::string& feature) const;
@@ -998,6 +1004,7 @@ private:
bool WarnUnused;
bool CheckSystemVars;
bool CheckCMP0000;
+ std::set<std::string> WarnedCMP0074;
bool IsSourceFileTryCompile;
mutable bool SuppressWatches;
};
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 73cf1f0..abe5ff3 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -643,6 +643,18 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
source.GetFullPath(), workingDirectory, compileCommand);
}
+ // See if we need to use a compiler launcher like ccache or distcc
+ std::string compilerLauncher;
+ if (!compileCommands.empty() && (lang == "C" || lang == "CXX" ||
+ lang == "Fortran" || lang == "CUDA")) {
+ std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
+ const char* clauncher =
+ this->GeneratorTarget->GetProperty(clauncher_prop);
+ if (clauncher && *clauncher) {
+ compilerLauncher = clauncher;
+ }
+ }
+
// Maybe insert an include-what-you-use runner.
if (!compileCommands.empty() && (lang == "C" || lang == "CXX")) {
std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE";
@@ -656,6 +668,13 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
if ((iwyu && *iwyu) || (tidy && *tidy) || (cpplint && *cpplint) ||
(cppcheck && *cppcheck)) {
std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_co_compile";
+ if (!compilerLauncher.empty()) {
+ // In __run_co_compile case the launcher command is supplied
+ // via --launcher=<maybe-list> and consumed
+ run_iwyu += " --launcher=";
+ run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher);
+ compilerLauncher.clear();
+ }
if (iwyu && *iwyu) {
run_iwyu += " --iwyu=";
run_iwyu += this->LocalGenerator->EscapeForShell(iwyu);
@@ -682,21 +701,15 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
}
}
- // Maybe insert a compiler launcher like ccache or distcc
- if (!compileCommands.empty() && (lang == "C" || lang == "CXX" ||
- lang == "Fortran" || lang == "CUDA")) {
- std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
- const char* clauncher =
- this->GeneratorTarget->GetProperty(clauncher_prop);
- if (clauncher && *clauncher) {
- std::vector<std::string> launcher_cmd;
- cmSystemTools::ExpandListArgument(clauncher, launcher_cmd, true);
- for (std::string& i : launcher_cmd) {
- i = this->LocalGenerator->EscapeForShell(i);
- }
- std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " ";
- compileCommands.front().insert(0, run_launcher);
+ // If compiler launcher was specified and not consumed above, it
+ // goes to the beginning of the command line.
+ if (!compileCommands.empty() && !compilerLauncher.empty()) {
+ std::vector<std::string> args;
+ cmSystemTools::ExpandListArgument(compilerLauncher, args, true);
+ for (std::string& i : args) {
+ i = this->LocalGenerator->EscapeForShell(i);
}
+ compileCommands.front().insert(0, cmJoin(args, " ") + " ");
}
std::string launcher;
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index ddbc772..52e3677 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -187,7 +187,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile)
std::string responseFlag;
if (!useResponseFile) {
vars.Objects = "$in";
- vars.LinkLibraries = "$LINK_LIBRARIES";
+ vars.LinkLibraries = "$LINK_PATH $LINK_LIBRARIES";
} else {
std::string cmakeVarLang = "CMAKE_";
cmakeVarLang += this->TargetLinkLanguage;
@@ -976,8 +976,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
preLinkCmdLines.push_back("cd " + homeOutDir);
}
- vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines);
- std::string postBuildCmdLine = localGen.BuildCommandLine(postBuildCmdLines);
+ vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines, "pre-link",
+ this->GeneratorTarget);
+ std::string postBuildCmdLine = localGen.BuildCommandLine(
+ postBuildCmdLines, "post-build", this->GeneratorTarget);
cmNinjaVars symlinkVars;
bool const symlinkNeeded =
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index f4faf47..fa7d95a 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -653,6 +653,17 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
}
+ // See if we need to use a compiler launcher like ccache or distcc
+ std::string compilerLauncher;
+ if (!compileCmds.empty() &&
+ (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA")) {
+ std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
+ const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
+ if (clauncher && *clauncher) {
+ compilerLauncher = clauncher;
+ }
+ }
+
// Maybe insert an include-what-you-use runner.
if (!compileCmds.empty() && (lang == "C" || lang == "CXX")) {
std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE";
@@ -668,6 +679,13 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
std::string run_iwyu = this->GetLocalGenerator()->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
run_iwyu += " -E __run_co_compile";
+ if (!compilerLauncher.empty()) {
+ // In __run_co_compile case the launcher command is supplied
+ // via --launcher=<maybe-list> and consumed
+ run_iwyu += " --launcher=";
+ run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher);
+ compilerLauncher.clear();
+ }
if (iwyu && *iwyu) {
run_iwyu += " --iwyu=";
run_iwyu += this->GetLocalGenerator()->EscapeForShell(iwyu);
@@ -693,20 +711,15 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
}
}
- // Maybe insert a compiler launcher like ccache or distcc
- if (!compileCmds.empty() &&
- (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA")) {
- std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
- const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
- if (clauncher && *clauncher) {
- std::vector<std::string> launcher_cmd;
- cmSystemTools::ExpandListArgument(clauncher, launcher_cmd, true);
- for (std::string& i : launcher_cmd) {
- i = this->LocalGenerator->EscapeForShell(i);
- }
- std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " ";
- compileCmds.front().insert(0, run_launcher);
+ // If compiler launcher was specified and not consumed above, it
+ // goes to the beginning of the command line.
+ if (!compileCmds.empty() && !compilerLauncher.empty()) {
+ std::vector<std::string> args;
+ cmSystemTools::ExpandListArgument(compilerLauncher, args, true);
+ for (std::string& i : args) {
+ i = this->LocalGenerator->EscapeForShell(i);
}
+ compileCmds.front().insert(0, cmJoin(args, " ") + " ");
}
if (!compileCmds.empty()) {
@@ -856,9 +869,27 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
vars["DEFINES"] = this->ComputeDefines(source, language);
vars["INCLUDES"] = this->ComputeIncludes(source, language);
+
if (!this->NeedDepTypeMSVC(language)) {
- vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
- objectFileName + ".d", cmOutputConverter::SHELL);
+ bool replaceExt(false);
+ if (!language.empty()) {
+ std::string repVar = "CMAKE_";
+ repVar += language;
+ repVar += "_DEPFILE_EXTENSION_REPLACE";
+ replaceExt = this->Makefile->IsOn(repVar);
+ }
+ if (!replaceExt) {
+ // use original code
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectFileName + ".d", cmOutputConverter::SHELL);
+ } else {
+ // Replace the original source file extension with the
+ // depend file extension.
+ std::string dependFileName =
+ cmSystemTools::GetFilenameWithoutLastExtension(objectFileName) + ".d";
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectFileDir + "/" + dependFileName, cmOutputConverter::SHELL);
+ }
}
this->ExportObjectCompileCommand(
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 7adeb8e..cc6d4b9 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -96,8 +96,8 @@ void cmNinjaUtilityTargetGenerator::Generate()
this->GetBuildFileStream(),
"Utility command for " + this->GetTargetName(), outputs, deps);
} else {
- std::string command =
- this->GetLocalGenerator()->BuildCommandLine(commands);
+ std::string command = this->GetLocalGenerator()->BuildCommandLine(
+ commands, "utility", this->GeneratorTarget);
const char* echoStr =
this->GetGeneratorTarget()->GetProperty("EchoString");
std::string desc;
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index 25db929..fd42c53 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -6,7 +6,7 @@
#include <assert.h>
#include <ctype.h>
#include <set>
-#include <sstream>
+#include <string.h>
#include <vector>
#include "cmAlgorithms.h"
@@ -341,12 +341,13 @@ redirection character (for example, ^>, ^<, or ^| ). If you need to
use the caret character itself (^), use two in a row (^^).
*/
-int cmOutputConverter::Shell__CharIsWhitespace(char c)
+/* Some helpers to identify character classes */
+static int Shell__CharIsWhitespace(char c)
{
return ((c == ' ') || (c == '\t'));
}
-int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c)
+static int Shell__CharNeedsQuotesOnUnix(char c)
{
return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') ||
(c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') ||
@@ -354,12 +355,17 @@ int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c)
(c == '\\'));
}
-int cmOutputConverter::Shell__CharNeedsQuotesOnWindows(char c)
+static int Shell__CharNeedsQuotesOnWindows(char c)
{
return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') ||
(c == '>') || (c == '|') || (c == '^'));
}
+static int Shell__CharIsMakeVariableName(char c)
+{
+ return c && (c == '_' || isalpha((static_cast<int>(c))));
+}
+
int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
{
/* On Windows the built-in command shell echo never needs quotes. */
@@ -386,11 +392,6 @@ int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
return 0;
}
-int cmOutputConverter::Shell__CharIsMakeVariableName(char c)
-{
- return c && (c == '_' || isalpha((static_cast<int>(c))));
-}
-
const char* cmOutputConverter::Shell__SkipMakeVariables(const char* c)
{
while (*c == '$' && *(c + 1) == '(') {
@@ -481,7 +482,9 @@ int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int flags)
std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
{
- std::ostringstream out;
+ /* Output will be at least as long as input string. */
+ std::string out;
+ out.reserve(strlen(in));
/* String iterator. */
const char* c;
@@ -495,11 +498,11 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
/* Add the opening quote for this argument. */
if (flags & Shell_Flag_WatcomQuote) {
if (flags & Shell_Flag_IsUnix) {
- out << '"';
+ out += '"';
}
- out << '\'';
+ out += '\'';
} else {
- out << '"';
+ out += '"';
}
}
@@ -511,7 +514,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
if (skip != c) {
/* Copy to the end of the make variable references. */
while (c != skip) {
- out << *c++;
+ out += *c++;
}
/* The make variable reference eliminates any escaping needed
@@ -531,7 +534,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
quoted argument. */
if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') {
/* This character needs a backslash to escape it. */
- out << '\\';
+ out += '\\';
}
} else if (flags & Shell_Flag_EchoWindows) {
/* On Windows the built-in command shell echo never needs escaping. */
@@ -545,11 +548,11 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
backslashes. */
while (windows_backslashes > 0) {
--windows_backslashes;
- out << '\\';
+ out += '\\';
}
/* Add the backslash to escape the double-quote. */
- out << '\\';
+ out += '\\';
} else {
/* We encountered a normal character. This eliminates any
escaping needed for preceding backslashes. */
@@ -562,7 +565,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
if (flags & Shell_Flag_Make) {
/* In Makefiles a dollar is written $$. The make tool will
replace it with just $ before passing it to the shell. */
- out << "$$";
+ out += "$$";
} else if (flags & Shell_Flag_VSIDE) {
/* In a VS IDE a dollar is written "$". If this is written in
an un-quoted argument it starts a quoted segment, inserts
@@ -570,30 +573,30 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
argument it ends quoting, inserts the $ and restarts
quoting. Either way the $ is isolated from surrounding
text to avoid looking like a variable reference. */
- out << "\"$\"";
+ out += "\"$\"";
} else {
/* Otherwise a dollar is written just $. */
- out << '$';
+ out += '$';
}
} else if (*c == '#') {
if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) {
/* In Watcom WMake makefiles a pound is written $#. The make
tool will replace it with just # before passing it to the
shell. */
- out << "$#";
+ out += "$#";
} else {
/* Otherwise a pound is written just #. */
- out << '#';
+ out += '#';
}
} else if (*c == '%') {
if ((flags & Shell_Flag_VSIDE) ||
((flags & Shell_Flag_Make) &&
((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) {
/* In the VS IDE, NMake, or MinGW make a percent is written %%. */
- out << "%%";
+ out += "%%";
} else {
/* Otherwise a percent is written just %. */
- out << '%';
+ out += '%';
}
} else if (*c == ';') {
if (flags & Shell_Flag_VSIDE) {
@@ -602,14 +605,14 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
inserts the ; and ends the segment. If it is written in a
quoted argument it ends quoting, inserts the ; and restarts
quoting. Either way the ; is isolated. */
- out << "\";\"";
+ out += "\";\"";
} else {
/* Otherwise a semicolon is written just ;. */
- out << ';';
+ out += ';';
}
} else {
/* Store this character. */
- out << *c;
+ out += *c;
}
}
@@ -617,19 +620,19 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
/* Add enough backslashes to escape any trailing ones. */
while (windows_backslashes > 0) {
--windows_backslashes;
- out << '\\';
+ out += '\\';
}
/* Add the closing quote for this argument. */
if (flags & Shell_Flag_WatcomQuote) {
- out << '\'';
+ out += '\'';
if (flags & Shell_Flag_IsUnix) {
- out << '"';
+ out += '"';
}
} else {
- out << '"';
+ out += '"';
}
}
- return out.str();
+ return out;
}
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index ae15055..ed7143c 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -117,11 +117,7 @@ public:
private:
cmState* GetState() const;
- static int Shell__CharIsWhitespace(char c);
- static int Shell__CharNeedsQuotesOnUnix(char c);
- static int Shell__CharNeedsQuotesOnWindows(char c);
static int Shell__CharNeedsQuotes(char c, int flags);
- static int Shell__CharIsMakeVariableName(char c);
static const char* Shell__SkipMakeVariables(const char* c);
static int Shell__ArgumentNeedsQuotes(const char* in, int flags);
static std::string Shell__GetArgument(const char* in, int flags);
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index e7d1b72..dba22b3 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -153,31 +153,26 @@ static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy,
return true;
}
-bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, const char* version)
+bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf,
+ std::string const& version_min,
+ std::string const& version_max)
{
- std::string ver = "2.4.0";
-
- if (version && strlen(version) > 0) {
- ver = version;
- }
-
- unsigned int majorVer = 2;
- unsigned int minorVer = 0;
- unsigned int patchVer = 0;
- unsigned int tweakVer = 0;
-
- // parse the string
- if (sscanf(ver.c_str(), "%u.%u.%u.%u", &majorVer, &minorVer, &patchVer,
- &tweakVer) < 2) {
+ // Parse components of the minimum version.
+ unsigned int minMajor = 2;
+ unsigned int minMinor = 0;
+ unsigned int minPatch = 0;
+ unsigned int minTweak = 0;
+ if (sscanf(version_min.c_str(), "%u.%u.%u.%u", &minMajor, &minMinor,
+ &minPatch, &minTweak) < 2) {
std::ostringstream e;
- e << "Invalid policy version value \"" << ver << "\". "
+ e << "Invalid policy version value \"" << version_min << "\". "
<< "A numeric major.minor[.patch[.tweak]] must be given.";
mf->IssueMessage(cmake::FATAL_ERROR, e.str());
return false;
}
// it is an error if the policy version is less than 2.4
- if (majorVer < 2 || (majorVer == 2 && minorVer < 4)) {
+ if (minMajor < 2 || (minMajor == 2 && minMinor < 4)) {
mf->IssueMessage(
cmake::FATAL_ERROR,
"Compatibility with CMake < 2.4 is not supported by CMake >= 3.0. "
@@ -188,19 +183,19 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, const char* version)
// It is an error if the policy version is greater than the running
// CMake.
- if (majorVer > cmVersion::GetMajorVersion() ||
- (majorVer == cmVersion::GetMajorVersion() &&
- minorVer > cmVersion::GetMinorVersion()) ||
- (majorVer == cmVersion::GetMajorVersion() &&
- minorVer == cmVersion::GetMinorVersion() &&
- patchVer > cmVersion::GetPatchVersion()) ||
- (majorVer == cmVersion::GetMajorVersion() &&
- minorVer == cmVersion::GetMinorVersion() &&
- patchVer == cmVersion::GetPatchVersion() &&
- tweakVer > cmVersion::GetTweakVersion())) {
+ if (minMajor > cmVersion::GetMajorVersion() ||
+ (minMajor == cmVersion::GetMajorVersion() &&
+ minMinor > cmVersion::GetMinorVersion()) ||
+ (minMajor == cmVersion::GetMajorVersion() &&
+ minMinor == cmVersion::GetMinorVersion() &&
+ minPatch > cmVersion::GetPatchVersion()) ||
+ (minMajor == cmVersion::GetMajorVersion() &&
+ minMinor == cmVersion::GetMinorVersion() &&
+ minPatch == cmVersion::GetPatchVersion() &&
+ minTweak > cmVersion::GetTweakVersion())) {
std::ostringstream e;
e << "An attempt was made to set the policy version of CMake to \""
- << version << "\" which is greater than this version of CMake. "
+ << version_min << "\" which is greater than this version of CMake. "
<< "This is not allowed because the greater version may have new "
<< "policies not known to this CMake. "
<< "You may need a newer CMake version to build this project.";
@@ -208,6 +203,52 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, const char* version)
return false;
}
+ unsigned int polMajor = minMajor;
+ unsigned int polMinor = minMinor;
+ unsigned int polPatch = minPatch;
+
+ if (!version_max.empty()) {
+ // Parse components of the maximum version.
+ unsigned int maxMajor = 0;
+ unsigned int maxMinor = 0;
+ unsigned int maxPatch = 0;
+ unsigned int maxTweak = 0;
+ if (sscanf(version_max.c_str(), "%u.%u.%u.%u", &maxMajor, &maxMinor,
+ &maxPatch, &maxTweak) < 2) {
+ std::ostringstream e;
+ e << "Invalid policy max version value \"" << version_max << "\". "
+ << "A numeric major.minor[.patch[.tweak]] must be given.";
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+
+ // It is an error if the min version is greater than the max version.
+ if (minMajor > maxMajor || (minMajor == maxMajor && minMinor > maxMinor) ||
+ (minMajor == maxMajor && minMinor == maxMinor &&
+ minPatch > maxPatch) ||
+ (minMajor == maxMajor && minMinor == maxMinor &&
+ minPatch == maxPatch && minTweak > maxTweak)) {
+ std::ostringstream e;
+ e << "Policy VERSION range \"" << version_min << "..." << version_max
+ << "\""
+ << " specifies a larger minimum than maximum.";
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+
+ // Use the max version as the policy version.
+ polMajor = maxMajor;
+ polMinor = maxMinor;
+ polPatch = maxPatch;
+ }
+
+ return cmPolicies::ApplyPolicyVersion(mf, polMajor, polMinor, polPatch);
+}
+
+bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
+ unsigned int minorVer,
+ unsigned int patchVer)
+{
// now loop over all the policies and set them as appropriate
std::vector<cmPolicies::PolicyID> ancientPolicies;
for (PolicyID pid = cmPolicies::CMP0000; pid != cmPolicies::CMPCOUNT;
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index c39f927..a21c778 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -214,7 +214,12 @@ class cmMakefile;
3, 10, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0072, \
"FindOpenGL prefers GLVND by default when available.", 3, 11, 0, \
- cmPolicies::WARN)
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0073, \
+ "Do not produce legacy _LIB_DEPENDS cache entries.", 3, 12, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0074, "find_package uses PackageName_ROOT variables.", 3, \
+ 12, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -238,7 +243,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
@@ -284,7 +290,11 @@ public:
static cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id);
///! Set a policy level for this listfile
- static bool ApplyPolicyVersion(cmMakefile* mf, const char* version);
+ static bool ApplyPolicyVersion(cmMakefile* mf,
+ std::string const& version_min,
+ std::string const& version_max);
+ static bool ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
+ unsigned int minorVer, unsigned int patchVer);
///! return a warning string for a given policy
static std::string GetPolicyWarning(cmPolicies::PolicyID id);
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index dfa1858..6ddb0b8 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"
@@ -66,12 +68,19 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
bool haveVersion = false;
bool haveLanguages = false;
bool haveDescription = false;
+ bool haveHomepage = false;
std::string version;
std::string description;
+ std::string homepage;
std::vector<std::string> languages;
+ std::function<void()> missedValueReporter;
+ auto resetReporter = [&missedValueReporter]() {
+ missedValueReporter = std::function<void()>();
+ };
enum Doing
{
DoingDescription,
+ DoingHomepage,
DoingLanguages,
DoingVersion
};
@@ -85,7 +94,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 +114,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 +133,61 @@ 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 (args[i] == "HOMEPAGE_URL") {
+ if (haveHomepage) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR, "HOMEPAGE_URL may be specified at most once.");
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+ haveHomepage = true;
+ doing = DoingHomepage;
+ missedValueReporter = [this, &resetReporter]() {
+ this->Makefile->IssueMessage(
+ cmake::WARNING,
+ "HOMEPAGE_URL 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 if (doing == DoingHomepage) {
+ doing = DoingLanguages;
+ homepage = args[i];
+ resetReporter();
} else // doing == DoingLanguages
{
languages.push_back(args[i]);
}
}
- if (haveVersion && !haveLanguages && !languages.empty()) {
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
+
+ if ((haveVersion || haveDescription || haveHomepage) && !haveLanguages &&
+ !languages.empty()) {
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
- "project with VERSION must use LANGUAGES before language names.");
+ "project with VERSION, DESCRIPTION or HOMEPAGE_URL must "
+ "use LANGUAGES before language names.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
@@ -216,6 +284,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
if (haveDescription) {
this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description.c_str());
+ this->Makefile->AddDefinition(projectName + "_DESCRIPTION",
+ description.c_str());
// Set the CMAKE_PROJECT_DESCRIPTION variable to be the highest-level
// project name in the tree. If there are two project commands
// in the same CMakeLists.txt file, and it is the top level
@@ -230,6 +300,24 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
}
}
+ if (haveHomepage) {
+ this->Makefile->AddDefinition("PROJECT_HOMEPAGE_URL", homepage.c_str());
+ this->Makefile->AddDefinition(projectName + "_HOMEPAGE_URL",
+ homepage.c_str());
+ // Set the CMAKE_PROJECT_HOMEPAGE_URL variable to be the highest-level
+ // project name in the tree. If there are two project commands
+ // in the same CMakeLists.txt file, and it is the top level
+ // CMakeLists.txt file, then go with the last one.
+ if (!this->Makefile->GetDefinition("CMAKE_PROJECT_HOMEPAGE_URL") ||
+ (this->Makefile->IsRootMakefile())) {
+ this->Makefile->AddDefinition("CMAKE_PROJECT_HOMEPAGE_URL",
+ homepage.c_str());
+ this->Makefile->AddCacheDefinition(
+ "CMAKE_PROJECT_HOMEPAGE_URL", homepage.c_str(),
+ "Value Computed by CMake", cmStateEnums::STATIC);
+ }
+ }
+
if (languages.empty()) {
// if no language is specified do c and c++
languages.push_back("C");
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index 4aa1b1f..bf184d8 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -681,7 +681,7 @@ bool cmQtAutoGenerator::Run(std::string const& infoFile,
auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
// The OLD/WARN behavior for policy CMP0053 caused a speed regression.
// https://gitlab.kitware.com/cmake/cmake/issues/17570
- makefile->SetPolicyVersion("3.9");
+ makefile->SetPolicyVersion("3.9", std::string());
gg.SetCurrentMakefile(makefile.get());
success = this->Init(makefile.get());
}
diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx
index e2fd158..b1be967 100644
--- a/Source/cmQtAutoGeneratorMocUic.cxx
+++ b/Source/cmQtAutoGeneratorMocUic.cxx
@@ -434,7 +434,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
JobHandleT jobHandle(new JobMocT(std::move(jobPre.SourceFile), FileName,
std::move(jobPre.IncludeString)));
if (jobPre.self) {
- // Read depdendencies from this source
+ // Read dependencies from this source
static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
}
if (!wrk.Gen().ParallelJobPushMoc(jobHandle)) {
@@ -452,7 +452,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocHeader(WorkerT& wrk,
if (!macroName.empty()) {
JobHandleT jobHandle(
new JobMocT(std::string(FileName), std::string(), std::string()));
- // Read depdendencies from this source
+ // Read dependencies from this source
static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
success = wrk.Gen().ParallelJobPushMoc(jobHandle);
}
@@ -1381,7 +1381,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
// Compare list sizes
if (sources.size() != options.size()) {
std::ostringstream ost;
- ost << "files/options lists sizes missmatch (" << sources.size() << "/"
+ ost << "files/options lists sizes mismatch (" << sources.size() << "/"
<< options.size() << ")";
Log().ErrorFile(GeneratorT::UIC, InfoFile(), ost.str());
return false;
diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h
index 7b19210..a7d8cee 100644
--- a/Source/cmRulePlaceholderExpander.h
+++ b/Source/cmRulePlaceholderExpander.h
@@ -24,7 +24,7 @@ public:
this->TargetImpLib = targetImpLib;
}
- // Create a struct to hold the varibles passed into
+ // Create a struct to hold the variables passed into
// ExpandRuleVariables
struct RuleVariables
{
diff --git a/Source/cmSearchPath.h b/Source/cmSearchPath.h
index fd0c7c5..2a576ed 100644
--- a/Source/cmSearchPath.h
+++ b/Source/cmSearchPath.h
@@ -39,10 +39,10 @@ public:
void AddCMakePrefixPath(const std::string& variable);
void AddEnvPrefixPath(const std::string& variable, bool stripBin = false);
void AddSuffixes(const std::vector<std::string>& suffixes);
-
-protected:
void AddPrefixPaths(const std::vector<std::string>& paths,
const char* base = nullptr);
+
+protected:
void AddPathInternal(const std::string& path, const char* base = nullptr);
cmFindCommon* FC;
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 55af078..9631912 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -68,6 +68,9 @@ bool cmStringCommand::InitialPass(std::vector<std::string> const& args,
if (subCommand == "CONCAT") {
return this->HandleConcatCommand(args);
}
+ if (subCommand == "JOIN") {
+ return this->HandleJoinCommand(args);
+ }
if (subCommand == "SUBSTRING") {
return this->HandleSubstringCommand(args);
}
@@ -677,8 +680,26 @@ bool cmStringCommand::HandleConcatCommand(std::vector<std::string> const& args)
return false;
}
- std::string const& variableName = args[1];
- std::string value = cmJoin(cmMakeRange(args).advance(2), std::string());
+ return this->joinImpl(args, std::string(), 1);
+}
+
+bool cmStringCommand::HandleJoinCommand(std::vector<std::string> const& args)
+{
+ if (args.size() < 3) {
+ this->SetError("sub-command JOIN requires at least two arguments.");
+ return false;
+ }
+
+ return this->joinImpl(args, args[1], 2);
+}
+
+bool cmStringCommand::joinImpl(std::vector<std::string> const& args,
+ std::string const& glue, const size_t varIdx)
+{
+ std::string const& variableName = args[varIdx];
+ // NOTE Items to concat/join placed right after the variable for
+ // both `CONCAT` and `JOIN` sub-commands.
+ std::string value = cmJoin(cmMakeRange(args).advance(varIdx + 1), glue);
this->Makefile->AddDefinition(variableName, value.c_str());
return true;
diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h
index b287e37..569ed83 100644
--- a/Source/cmStringCommand.h
+++ b/Source/cmStringCommand.h
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <string>
#include <vector>
@@ -48,6 +49,7 @@ protected:
bool HandleAppendCommand(std::vector<std::string> const& args);
bool HandlePrependCommand(std::vector<std::string> const& args);
bool HandleConcatCommand(std::vector<std::string> const& args);
+ bool HandleJoinCommand(std::vector<std::string> const& args);
bool HandleStripCommand(std::vector<std::string> const& args);
bool HandleRandomCommand(std::vector<std::string> const& args);
bool HandleFindCommand(std::vector<std::string> const& args);
@@ -56,6 +58,9 @@ protected:
bool HandleGenexStripCommand(std::vector<std::string> const& args);
bool HandleUuidCommand(std::vector<std::string> const& args);
+ bool joinImpl(std::vector<std::string> const& args, std::string const& glue,
+ size_t varIdx);
+
class RegexReplacement
{
public:
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index eeb73c3..94c5ee8 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1509,7 +1509,7 @@ cmSystemTools::SaveRestoreEnvironment::~SaveRestoreEnvironment()
void cmSystemTools::EnableVSConsoleOutput()
{
#ifdef _WIN32
- // Visual Studio 8 2005 (devenv.exe or VCExpress.exe) will not
+ // Visual Studio tools like devenv may not
// display output to the console unless this environment variable is
// set. We need it to capture the output of these build tools.
// Note for future work that one could pass "/out \\.\pipe\NAME" to
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index cd11c4b..d17a85a 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 =
@@ -286,6 +275,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
this->SetPropertyDefault("CUDA_SEPARABLE_COMPILATION", nullptr);
this->SetPropertyDefault("LINK_SEARCH_START_STATIC", nullptr);
this->SetPropertyDefault("LINK_SEARCH_END_STATIC", nullptr);
+ this->SetPropertyDefault("FOLDER", nullptr);
}
// Collect the set of configuration types.
@@ -509,7 +499,7 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s)
{
std::string src = s;
- // For backwards compatibility replace varibles in source names.
+ // For backwards compatibility replace variables in source names.
// This should eventually be removed.
this->Makefile->ExpandVariablesInString(src);
if (src != s) {
@@ -638,27 +628,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,19 +716,15 @@ 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;
}
- {
- cmTarget::LibraryID tmp;
- tmp.first = lib;
- tmp.second = llt;
- this->OriginalLinkLibraries.emplace_back(lib, llt);
- }
+ 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 +732,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 ec31bd6..4bd07ef 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -28,6 +28,98 @@ static std::string cmVS10EscapeXML(std::string arg)
return arg;
}
+struct cmVisualStudio10TargetGenerator::Elem
+{
+ cmGeneratedFileStream& S;
+ int Indent;
+ bool HasElements = false;
+
+ Elem(cmGeneratedFileStream& s, int i)
+ : S(s)
+ , Indent(i)
+ {
+ }
+ Elem(const Elem&) = delete;
+ Elem(Elem& par)
+ : S(par.S)
+ , Indent(par.Indent + 1)
+ {
+ par.SetHasElements();
+ }
+ void SetHasElements()
+ {
+ if (!HasElements) {
+ S << ">\n";
+ HasElements = true;
+ }
+ }
+ void WriteEndTag(const char* tag)
+ {
+ if (HasElements) {
+ S.fill(' ');
+ S.width(Indent * 2);
+ // write an empty string to get the fill level indent to print
+ S << "";
+ S << "</" << tag << ">\n";
+ } else {
+ S << " />\n";
+ }
+ }
+};
+
+class cmVS10GeneratorOptions : public cmVisualStudioGeneratorOptions
+{
+public:
+ cmVS10GeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
+ cmVS7FlagTable const* table,
+ cmVisualStudio10TargetGenerator* g = nullptr)
+ : cmVisualStudioGeneratorOptions(lg, tool, table)
+ , TargetGenerator(g)
+ {
+ }
+
+ void OutputFlag(std::ostream& fout, const char* indent, const char* tag,
+ const std::string& content) override
+ {
+ if (!this->GetConfiguration().empty()) {
+ // if there are configuration specific flags, then
+ // use the configuration specific tag for PreprocessorDefinitions
+ fout << indent;
+ this->TargetGenerator->WritePlatformConfigTag(
+ tag, this->GetConfiguration(), 0);
+ } else {
+ fout << indent << "<" << tag << ">";
+ }
+ fout << cmVS10EscapeXML(content);
+ fout << "</" << tag << ">\n";
+ }
+
+private:
+ cmVisualStudio10TargetGenerator* TargetGenerator;
+};
+
+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";
+}
+
+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;");
@@ -84,16 +176,15 @@ static std::string computeProjectFileExtension(cmGeneratorTarget const* t,
cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
cmGeneratorTarget* target, cmGlobalVisualStudio10Generator* gg)
+ : GeneratorTarget(target)
+ , Makefile(target->Target->GetMakefile())
+ , Platform(gg->GetPlatformName())
+ , Name(target->GetName())
+ , GUID(gg->GetGUID(this->Name))
+ , GlobalGenerator(gg)
+ , LocalGenerator((cmLocalVisualStudio7Generator*)target->GetLocalGenerator())
{
- this->GlobalGenerator = gg;
- this->GeneratorTarget = target;
- this->Makefile = target->Target->GetMakefile();
this->Makefile->GetConfigurations(this->Configurations);
- this->LocalGenerator =
- (cmLocalVisualStudio7Generator*)this->GeneratorTarget->GetLocalGenerator();
- this->Name = this->GeneratorTarget->GetName();
- this->GUID = this->GlobalGenerator->GetGUID(this->Name);
- this->Platform = gg->GetPlatformName();
this->NsightTegra = gg->IsNsightTegra();
for (int i = 0; i < 4; ++i) {
this->NsightTegraVersion[i] = 0;
@@ -127,12 +218,10 @@ cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
void cmVisualStudio10TargetGenerator::WritePlatformConfigTag(
const char* tag, const std::string& config, int indentLevel,
- const char* attribute, const char* end, std::ostream* stream)
+ const char* attribute)
{
- if (!stream) {
- stream = this->BuildFileStream;
- }
+ std::ostream* stream = this->BuildFileStream;
stream->fill(' ');
stream->width(indentLevel * 2);
(*stream) << ""; // applies indentation
@@ -153,8 +242,8 @@ void cmVisualStudio10TargetGenerator::WritePlatformConfigTag(
}
// close the tag
(*stream) << ">";
- if (end) {
- (*stream) << end;
+ if (attribute) {
+ (*stream) << "\n";
}
}
@@ -266,16 +355,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);
}
@@ -283,9 +366,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);
}
@@ -293,8 +374,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) {
@@ -323,61 +403,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
@@ -385,9 +449,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();
@@ -438,8 +500,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);
@@ -602,8 +663,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences()
if (!name.empty()) {
std::string path = i.second.GetValue();
if (!cmsys::SystemTools::FileIsFullPath(path)) {
- path = std::string(this->GeneratorTarget->Target->GetMakefile()
- ->GetCurrentSourceDirectory()) +
+ path = std::string(this->Makefile->GetCurrentSourceDirectory()) +
"/" + path;
}
ConvertToWindowsSlash(path);
@@ -637,12 +697,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(
@@ -651,10 +707,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);
@@ -713,9 +767,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);
@@ -743,8 +796,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
@@ -758,9 +810,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) {
@@ -770,9 +820,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();
@@ -807,7 +855,7 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
this->WriteString("<ItemGroup>\n", 1);
for (cmSourceFile const* oi : xamlObjs) {
std::string obj = oi->GetFullPath();
- std::string xamlType;
+ const char* xamlType;
const char* xamlTypeProperty = oi->GetProperty("VS_XAML_TYPE");
if (xamlTypeProperty) {
xamlType = xamlTypeProperty;
@@ -815,7 +863,9 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
xamlType = "Page";
}
- this->WriteSource(xamlType, oi, ">\n");
+ Elem e2(*this->BuildFileStream, 2);
+ this->WriteSource(xamlType, oi);
+ e2.SetHasElements();
if (this->ProjectType == csproj && !this->InSourceBuild) {
// add <Link> tag to written XAML source if necessary
const std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
@@ -830,13 +880,11 @@ 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->WriteString("</", 2);
- (*this->BuildFileStream) << xamlType << ">\n";
+ this->WriteElem("SubType", "Designer", 3);
+ e2.WriteEndTag(xamlType);
}
this->WriteString("</ItemGroup>\n", 1);
}
@@ -858,10 +906,7 @@ void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences()
void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences()
{
- for (std::vector<TargetsFileAndConfigs>::iterator i =
- this->TargetsFileAndConfigsVec.begin();
- i != this->TargetsFileAndConfigsVec.end(); ++i) {
- TargetsFileAndConfigs const& tac = *i;
+ for (TargetsFileAndConfigs const& tac : this->TargetsFileAndConfigsVec) {
this->WriteString("<Import Project=\"", 3);
(*this->BuildFileStream) << tac.File << "\" ";
(*this->BuildFileStream) << "Condition=\"";
@@ -896,11 +941,10 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
}
if (!references.empty()) {
this->WriteString("<ItemGroup>\n", 1);
- for (std::vector<std::string>::iterator ri = references.begin();
- ri != references.end(); ++ri) {
+ for (std::string const& ri : references) {
this->WriteString("<Reference Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(*ri) << "\">\n";
- this->WriteString("<IsWinMDFile>true</IsWinMDFile>\n", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(ri) << "\">\n";
+ this->WriteElem("IsWinMDFile", "true", 3);
this->WriteString("</Reference>\n", 2);
}
this->WriteString("</ItemGroup>\n", 1);
@@ -912,16 +956,11 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
void cmVisualStudio10TargetGenerator::WriteProjectConfigurations()
{
this->WriteString("<ItemGroup Label=\"ProjectConfigurations\">\n", 1);
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
+ for (std::string const& c : this->Configurations) {
this->WriteString("<ProjectConfiguration Include=\"", 2);
- (*this->BuildFileStream) << *i << "|" << this->Platform << "\">\n";
- this->WriteString("<Configuration>", 3);
- (*this->BuildFileStream) << *i << "</Configuration>\n";
- this->WriteString("<Platform>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
- << "</Platform>\n";
+ (*this->BuildFileStream) << c << "|" << this->Platform << "\">\n";
+ this->WriteElem("Configuration", c, 3);
+ this->WriteElemEscapeXML("Platform", this->Platform, 3);
this->WriteString("</ProjectConfiguration>\n", 2);
}
this->WriteString("</ItemGroup>\n", 1);
@@ -929,11 +968,9 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurations()
void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
{
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- this->WritePlatformConfigTag("PropertyGroup", *i, 1,
- " Label=\"Configuration\"", "\n");
+ for (std::string const& c : this->Configurations) {
+ this->WritePlatformConfigTag("PropertyGroup", c, 1,
+ " Label=\"Configuration\"");
if (this->ProjectType != csproj) {
std::string configType = "<ConfigurationType>";
@@ -979,12 +1016,12 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
if (this->MSTools) {
if (!this->Managed) {
- this->WriteMSToolConfigurationValues(*i);
+ this->WriteMSToolConfigurationValues(c);
} else {
- this->WriteMSToolConfigurationValuesManaged(*i);
+ this->WriteMSToolConfigurationValuesManaged(c);
}
} else if (this->NsightTegra) {
- this->WriteNsightTegraConfigurationValues(*i);
+ this->WriteNsightTegraConfigurationValues(c);
}
this->WriteString("</PropertyGroup>\n", 1);
@@ -994,11 +1031,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
std::string const& config)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- const char* mfcFlag =
- this->GeneratorTarget->Target->GetMakefile()->GetDefinition(
- "CMAKE_MFC_FLAG");
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
if (mfcFlag) {
std::string const mfcFlagValue = mfcFlag;
@@ -1010,9 +1044,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 &&
@@ -1021,57 +1053,46 @@ 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);
}
}
void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
std::string const& config)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
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);
@@ -1081,12 +1102,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)
@@ -1100,8 +1119,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
std::string const&)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
const char* toolset = gg->GetPlatformToolset();
std::string ntv = "<NdkToolchainVersion>";
ntv += toolset ? toolset : "Default";
@@ -1109,27 +1127,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);
}
}
@@ -1139,10 +1150,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommands()
this->CSharpCustomCommandNames.clear();
std::vector<cmSourceFile const*> customCommands;
this->GeneratorTarget->GetCustomCommands(customCommands, "");
- for (std::vector<cmSourceFile const*>::const_iterator si =
- customCommands.begin();
- si != customCommands.end(); ++si) {
- this->WriteCustomCommand(*si);
+ for (cmSourceFile const* si : customCommands) {
+ this->WriteCustomCommand(si);
}
// Add CMakeLists.txt file with rule to re-run CMake for user convenience.
@@ -1161,9 +1170,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommand(
if (this->SourcesVisited.insert(sf).second) {
if (std::vector<cmSourceFile*> const* depends =
this->GeneratorTarget->GetSourceDepends(sf)) {
- for (std::vector<cmSourceFile*>::const_iterator di = depends->begin();
- di != depends->end(); ++di) {
- this->WriteCustomCommand(*di);
+ for (cmSourceFile const* di : *depends) {
+ this->WriteCustomCommand(di);
}
}
if (cmCustomCommand const* command = sf->GetCustomCommand()) {
@@ -1186,10 +1194,10 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
// VS 10 will always rebuild a custom command attached to a .rule
// file that doesn't exist so create the file explicitly.
if (source->GetPropertyAsBool("__CMAKE_RULE")) {
- if (!cmSystemTools::FileExists(sourcePath.c_str())) {
+ if (!cmSystemTools::FileExists(sourcePath)) {
// Make sure the path exists for the file
std::string path = cmSystemTools::GetFilenamePath(sourcePath);
- cmSystemTools::MakeDirectory(path.c_str());
+ cmSystemTools::MakeDirectory(path);
cmsys::ofstream fout(sourcePath.c_str());
if (fout) {
fout << "# generated from CMake\n";
@@ -1209,34 +1217,33 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
}
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
+ Elem e2(*this->BuildFileStream, 2);
if (this->ProjectType != csproj) {
- this->WriteSource("CustomBuild", source, ">\n");
+ this->WriteSource("CustomBuild", source);
+ e2.SetHasElements();
} else {
this->WriteString("<ItemGroup>\n", 1);
std::string link;
this->GetCSharpSourceLink(source, link);
- this->WriteSource("None", source, ">\n");
+ this->WriteSource("None", source);
+ e2.SetHasElements();
if (!link.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << link << "</Link>\n";
+ this->WriteElem("Link", link, 3);
}
- this->WriteString("</None>\n", 2);
+ e2.WriteEndTag("None");
this->WriteString("</ItemGroup>\n", 1);
}
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- cmCustomCommandGenerator ccg(command, *i, this->LocalGenerator);
+ for (std::string const& c : this->Configurations) {
+ cmCustomCommandGenerator ccg(command, c, lg);
std::string comment = lg->ConstructComment(ccg);
comment = cmVS10EscapeComment(comment);
std::string script = cmVS10EscapeXML(lg->ConstructScript(ccg));
// input files for custom command
std::stringstream inputs;
inputs << cmVS10EscapeXML(source->GetFullPath());
- for (std::vector<std::string>::const_iterator d = ccg.GetDepends().begin();
- d != ccg.GetDepends().end(); ++d) {
+ for (std::string const& d : ccg.GetDepends()) {
std::string dep;
- if (this->LocalGenerator->GetRealDependency(*d, *i, dep)) {
+ if (lg->GetRealDependency(d, c, dep)) {
ConvertToWindowsSlash(dep);
inputs << ";" << cmVS10EscapeXML(dep);
}
@@ -1244,15 +1251,14 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
// output files for custom command
std::stringstream outputs;
const char* sep = "";
- for (std::vector<std::string>::const_iterator o = ccg.GetOutputs().begin();
- o != ccg.GetOutputs().end(); ++o) {
- std::string out = *o;
+ for (std::string const& o : ccg.GetOutputs()) {
+ std::string out = o;
ConvertToWindowsSlash(out);
outputs << sep << cmVS10EscapeXML(out);
sep = ";";
}
if (this->ProjectType == csproj) {
- std::string name = "CustomCommand_" + *i + "_" +
+ std::string name = "CustomCommand_" + c + "_" +
cmSystemTools::ComputeStringMD5(sourcePath);
std::string inputs_s = inputs.str();
std::string outputs_s = outputs.str();
@@ -1260,15 +1266,15 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
script = cmVS10EscapeQuotes(script);
inputs_s = cmVS10EscapeQuotes(inputs_s);
outputs_s = cmVS10EscapeQuotes(outputs_s);
- this->WriteCustomRuleCSharp(*i, name, script, inputs_s, outputs_s,
+ this->WriteCustomRuleCSharp(c, name, script, inputs_s, outputs_s,
comment);
} else {
- this->WriteCustomRuleCpp(*i, script, inputs.str(), outputs.str(),
+ this->WriteCustomRuleCpp(c, script, inputs.str(), outputs.str(),
comment);
}
}
if (this->ProjectType != csproj) {
- this->WriteString("</CustomBuild>\n", 2);
+ e2.WriteEndTag("CustomBuild");
}
}
@@ -1304,8 +1310,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRuleCSharp(
attributes << "\n Name=\"" << name << "\"";
attributes << "\n Inputs=\"" << inputs << "\"";
attributes << "\n Outputs=\"" << outputs << "\"";
- this->WritePlatformConfigTag("Target", config, 1, attributes.str().c_str(),
- "\n");
+ this->WritePlatformConfigTag("Target", config, 1, attributes.str().c_str());
if (!comment.empty()) {
this->WriteString("<Exec Command=\"", 2);
(*this->BuildFileStream) << "echo " << cmVS10EscapeXML(comment)
@@ -1321,8 +1326,8 @@ std::string cmVisualStudio10TargetGenerator::ConvertPath(
{
return forceRelative
? cmSystemTools::RelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), path.c_str())
- : path.c_str();
+ this->LocalGenerator->GetCurrentBinaryDirectory(), path)
+ : path;
}
static void ConvertToWindowsSlash(std::string& s)
@@ -1334,6 +1339,7 @@ static void ConvertToWindowsSlash(std::string& s)
pos++;
}
}
+
void cmVisualStudio10TargetGenerator::WriteGroups()
{
if (this->ProjectType == csproj) {
@@ -1347,10 +1353,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
this->GeneratorTarget->GetAllConfigSources();
std::set<cmSourceGroup*> groupsUsed;
- for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si =
- sources.begin();
- si != sources.end(); ++si) {
- std::string const& source = si->Source->GetFullPath();
+ for (cmGeneratorTarget::AllConfigSource const& si : sources) {
+ std::string const& source = si.Source->GetFullPath();
cmSourceGroup* sourceGroup =
this->Makefile->FindSourceGroup(source, sourceGroups);
groupsUsed.insert(sourceGroup);
@@ -1382,9 +1386,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
"xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
this->WriteString(project_defaults.c_str(), 0);
- for (ToolSourceMap::const_iterator ti = this->Tools.begin();
- ti != this->Tools.end(); ++ti) {
- this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups);
+ for (auto const& ti : this->Tools) {
+ this->WriteGroupSources(ti.first.c_str(), ti.second, sourceGroups);
}
// Added files are images and the manifest.
@@ -1396,23 +1399,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);
}
}
@@ -1428,7 +1431,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);
@@ -1447,10 +1450,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);
}
}
@@ -1458,10 +1459,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";
@@ -1516,7 +1515,7 @@ void cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
}
void cmVisualStudio10TargetGenerator::WriteGroupSources(
- const char* name, ToolSources const& sources,
+ std::string const& name, ToolSources const& sources,
std::vector<cmSourceGroup>& sourceGroups)
{
this->WriteString("<ItemGroup>\n", 1);
@@ -1532,8 +1531,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 {
@@ -1546,25 +1544,23 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources(
void cmVisualStudio10TargetGenerator::WriteHeaderSource(cmSourceFile const* sf)
{
std::string const& fileName = sf->GetFullPath();
+ Elem e2(*this->BuildFileStream, 2);
+ this->WriteSource("ClInclude", sf);
if (this->IsResxHeader(fileName)) {
- this->WriteSource("ClInclude", sf, ">\n");
- this->WriteString("<FileType>CppForm</FileType>\n", 3);
- this->WriteString("</ClInclude>\n", 2);
+ e2.SetHasElements();
+ this->WriteElem("FileType", "CppForm", 3);
} 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->WriteString("</ClInclude>\n", 2);
- } else {
- this->WriteSource("ClInclude", sf);
+ e2.SetHasElements();
+ this->WriteElem("DependentUpon", xamlFileName, 3);
}
+ e2.WriteEndTag("ClInclude");
}
void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
{
bool toolHasSettings = false;
- std::string tool = "None";
+ const char* tool = "None";
std::string shaderType;
std::string shaderEntryPoint;
std::string shaderModel;
@@ -1714,8 +1710,10 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
}
}
+ Elem e2(*this->BuildFileStream, 2);
+ this->WriteSource(tool, sf);
if (toolHasSettings) {
- this->WriteSource(tool, sf, ">\n");
+ e2.SetHasElements();
if (!deployContent.empty()) {
cmGeneratorExpression ge;
@@ -1749,19 +1747,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) {
@@ -1786,60 +1778,42 @@ 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);
- this->WriteString("</", 2);
- (*this->BuildFileStream) << tool << ">\n";
- } else {
- this->WriteSource(tool, sf);
}
+ e2.WriteEndTag(tool);
}
void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
- cmSourceFile const* sf,
- const char* end)
+ cmSourceFile const* sf)
{
// Visual Studio tools append relative paths to the current dir, as in:
//
@@ -1853,7 +1827,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative);
if (this->LocalGenerator->GetVersion() ==
cmGlobalVisualStudioGenerator::VS10 &&
- cmSystemTools::FileIsFullPath(sourceFile.c_str())) {
+ cmSystemTools::FileIsFullPath(sourceFile)) {
// Normal path conversion resulted in a full path. VS 10 (but not 11)
// refuses to show the property page in the IDE for a source file with a
// full path (not starting in a '.' or '/' AFAICT). CMake <= 2.8.4 used a
@@ -1876,8 +1850,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
ConvertToWindowsSlash(sourceFile);
this->WriteString("<", 2);
(*this->BuildFileStream) << tool << " Include=\""
- << cmVS10EscapeXML(sourceFile) << "\""
- << (end ? end : " />\n");
+ << cmVS10EscapeXML(sourceFile) << "\"";
ToolSource toolSource = { sf, forceRelative };
this->Tools[tool].push_back(toolSource);
@@ -1899,7 +1872,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
this->GeneratorTarget->GetAllConfigSources();
for (cmGeneratorTarget::AllConfigSource const& si : sources) {
- std::string tool;
+ const char* tool = nullptr;
switch (si.Kind) {
case cmGeneratorTarget::SourceKindAppManifest:
tool = "AppxManifest";
@@ -1968,7 +1941,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
break;
}
- if (!tool.empty()) {
+ if (tool) {
// Compute set of configurations to exclude, if any.
std::vector<size_t> const& include_configs = si.Configs;
std::vector<size_t> exclude_configs;
@@ -1976,31 +1949,15 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
include_configs.begin(), include_configs.end(),
std::back_inserter(exclude_configs));
+ Elem e2(*this->BuildFileStream, 2);
+ this->WriteSource(tool, si.Source);
if (si.Kind == cmGeneratorTarget::SourceKindObjectSource) {
- // FIXME: refactor generation to avoid tracking XML syntax state.
- this->WriteSource(tool, si.Source, "");
- bool have_nested = this->OutputSourceSpecificFlags(si.Source);
- if (!exclude_configs.empty()) {
- if (!have_nested) {
- (*this->BuildFileStream) << ">\n";
- }
- this->WriteExcludeFromBuild(exclude_configs);
- have_nested = true;
- }
- if (have_nested) {
- this->WriteString("</", 2);
- (*this->BuildFileStream) << tool << ">\n";
- } else {
- (*this->BuildFileStream) << " />\n";
- }
- } else if (!exclude_configs.empty()) {
- this->WriteSource(tool, si.Source, ">\n");
- this->WriteExcludeFromBuild(exclude_configs);
- this->WriteString("</", 2);
- (*this->BuildFileStream) << tool << ">\n";
- } else {
- this->WriteSource(tool, si.Source);
+ this->OutputSourceSpecificFlags(e2, si.Source);
}
+ if (!exclude_configs.empty()) {
+ this->WriteExcludeFromBuild(e2, exclude_configs);
+ }
+ e2.WriteEndTag(tool);
}
}
@@ -2011,8 +1968,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
this->WriteString("</ItemGroup>\n", 1);
}
-bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
- cmSourceFile const* source)
+void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
+ Elem& e2, cmSourceFile const* source)
{
cmSourceFile const& sf = *source;
@@ -2072,22 +2029,14 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
}
}
bool noWinRT = this->TargetCompileAsWinRT && lang == "C";
- bool hasFlags = false;
// for the first time we need a new line if there is something
// produced here.
- const char* firstString = ">\n";
if (!objectName.empty()) {
- (*this->BuildFileStream) << firstString;
- firstString = "";
- hasFlags = true;
+ e2.SetHasElements();
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) {
@@ -2107,11 +2056,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
// use them
if (!flags.empty() || !options.empty() || !configDefines.empty() ||
!includes.empty() || compileAs || noWinRT) {
- (*this->BuildFileStream) << firstString;
- firstString = ""; // only do firstString once
- hasFlags = true;
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ e2.SetHasElements();
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
cmIDEFlagTable const* flagtable = nullptr;
const std::string& srclang = source->GetLanguage();
if (srclang == "C" || srclang == "CXX") {
@@ -2130,9 +2076,9 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, this->GeneratorTarget, config,
this->GeneratorTarget->GetName(), lang);
- cmVisualStudioGeneratorOptions clOptions(
+ cmVS10GeneratorOptions clOptions(
this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler,
- flagtable, 0, this);
+ flagtable, this);
if (compileAs) {
clOptions.AddFlag("CompileAs", compileAs);
}
@@ -2163,7 +2109,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
clOptions.AddDefines(
genexInterpreter.Evaluate(configDefines, "COMPILE_DEFINITIONS"));
} else {
- clOptions.AddDefines(configDefines.c_str());
+ clOptions.AddDefines(configDefines);
}
std::vector<std::string> includeList;
if (configDependentIncludes) {
@@ -2175,23 +2121,20 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
*source);
}
clOptions.AddIncludes(includeList);
- clOptions.SetConfiguration(config.c_str());
+ clOptions.SetConfiguration(config);
clOptions.PrependInheritedString("AdditionalOptions");
clOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
- " ", "\n", lang);
+ " ", lang);
clOptions.OutputFlagMap(*this->BuildFileStream, " ");
clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", lang);
+ lang);
}
}
if (this->IsXamlSource(source->GetFullPath())) {
- (*this->BuildFileStream) << firstString;
- firstString = ""; // only do firstString once
- hasFlags = true;
- this->WriteString("<DependentUpon>", 3);
+ e2.SetHasElements();
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();
@@ -2206,19 +2149,16 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
this->GetCSharpSourceProperties(&sf, sourceFileTags);
// write source file specific tags
if (!sourceFileTags.empty()) {
- hasFlags = true;
- (*this->BuildFileStream) << firstString;
- firstString = "";
+ e2.SetHasElements();
this->WriteCSharpSourceProperties(sourceFileTags);
}
}
-
- return hasFlags;
}
void cmVisualStudio10TargetGenerator::WriteExcludeFromBuild(
- std::vector<size_t> const& exclude_configs)
+ Elem& e2, std::vector<size_t> const& exclude_configs)
{
+ e2.SetHasElements();
for (size_t ci : exclude_configs) {
this->WriteString("", 3);
(*this->BuildFileStream)
@@ -2239,9 +2179,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);
@@ -2282,6 +2220,13 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
<< "</LocalDebuggerWorkingDirectory>\n";
}
+ if (const char* debuggerCommand =
+ this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) {
+ this->WritePlatformConfigTag("LocalDebuggerCommand", config, 2);
+ *this->BuildFileStream << cmVS10EscapeXML(debuggerCommand)
+ << "</LocalDebuggerCommand>\n";
+ }
+
std::string name =
cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
this->WritePlatformConfigTag("TargetName", config, 2);
@@ -2374,8 +2319,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
// copied from cmLocalVisualStudio7Generator.cxx 805
// TODO: Integrate code below with cmLocalVisualStudio7Generator.
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
std::unique_ptr<Options> pOptions;
switch (this->ProjectType) {
case vcxproj:
@@ -2422,15 +2366,11 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
std::string baseFlagVar = "CMAKE_";
baseFlagVar += langForClCompile;
baseFlagVar += "_FLAGS";
- flags =
- this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- baseFlagVar);
+ flags = this->Makefile->GetRequiredDefinition(baseFlagVar);
std::string flagVar =
baseFlagVar + std::string("_") + cmSystemTools::UpperCase(configName);
flags += " ";
- flags +=
- this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- flagVar);
+ flags += this->Makefile->GetRequiredDefinition(flagVar);
this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
langForClCompile, configName);
}
@@ -2446,8 +2386,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName);
// Get preprocessor definitions for this directory.
- std::string defineFlags =
- this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+ std::string defineFlags = this->Makefile->GetDefineFlags();
if (this->MSTools) {
if (this->ProjectType == vcxproj) {
clOptions.FixExceptionHandlingDefault();
@@ -2544,17 +2483,15 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
this->WriteString("<ClCompile>\n", 2);
clOptions.PrependInheritedString("AdditionalOptions");
clOptions.OutputAdditionalIncludeDirectories(
- *this->BuildFileStream, " ", "\n", this->LangForClCompile);
+ *this->BuildFileStream, " ", this->LangForClCompile);
clOptions.OutputFlagMap(*this->BuildFileStream, " ");
clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", this->LangForClCompile);
+ this->LangForClCompile);
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);
}
}
@@ -2562,12 +2499,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
@@ -2583,9 +2517,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);
}
}
@@ -2605,8 +2537,7 @@ bool cmVisualStudio10TargetGenerator::ComputeRcOptions()
bool cmVisualStudio10TargetGenerator::ComputeRcOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::ResourceCompiler, gg->GetRcFlagTable());
Options& rcOptions = *pOptions;
@@ -2641,9 +2572,9 @@ void cmVisualStudio10TargetGenerator::WriteRCOptions(
Options& rcOptions = *(this->RcOptions[configName]);
rcOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "RC");
+ "RC");
rcOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
- " ", "\n", "RC");
+ " ", "RC");
rcOptions.PrependInheritedString("AdditionalOptions");
rcOptions.OutputFlagMap(*this->BuildFileStream, " ");
@@ -2666,8 +2597,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions()
bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
Options& cudaOptions = *pOptions;
@@ -2683,8 +2613,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
configName);
// Get preprocessor definitions for this directory.
- std::string defineFlags =
- this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+ std::string defineFlags = this->Makefile->GetDefineFlags();
cudaOptions.Parse(flags.c_str());
cudaOptions.Parse(defineFlags.c_str());
@@ -2779,9 +2708,9 @@ void cmVisualStudio10TargetGenerator::WriteCudaOptions(
Options& cudaOptions = *(this->CudaOptions[configName]);
cudaOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
- " ", "\n", "CUDA");
+ " ", "CUDA");
cudaOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "CUDA");
+ "CUDA");
cudaOptions.PrependInheritedString("AdditionalOptions");
cudaOptions.OutputFlagMap(*this->BuildFileStream, " ");
@@ -2804,8 +2733,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions()
bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
Options& cudaLinkOptions = *pOptions;
@@ -2873,8 +2801,7 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions()
bool cmVisualStudio10TargetGenerator::ComputeMasmOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::MasmCompiler, gg->GetMasmFlagTable());
Options& masmOptions = *pOptions;
@@ -2906,11 +2833,11 @@ void cmVisualStudio10TargetGenerator::WriteMasmOptions(
// Preprocessor definitions and includes are shared with clOptions.
Options& clOptions = *(this->ClOptions[configName]);
clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "ASM_MASM");
+ "ASM_MASM");
Options& masmOptions = *(this->MasmOptions[configName]);
masmOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
- " ", "\n", "ASM_MASM");
+ " ", "ASM_MASM");
masmOptions.PrependInheritedString("AdditionalOptions");
masmOptions.OutputFlagMap(*this->BuildFileStream, " ");
@@ -2933,8 +2860,7 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions()
bool cmVisualStudio10TargetGenerator::ComputeNasmOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::NasmCompiler, gg->GetNasmFlagTable());
Options& nasmOptions = *pOptions;
@@ -2968,16 +2894,16 @@ void cmVisualStudio10TargetGenerator::WriteNasmOptions(
this->GetIncludes(configName, "ASM_NASM");
Options& nasmOptions = *(this->NasmOptions[configName]);
nasmOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
- " ", "\n", "ASM_NASM");
+ " ", "ASM_NASM");
nasmOptions.OutputFlagMap(*this->BuildFileStream, " ");
nasmOptions.PrependInheritedString("AdditionalOptions");
nasmOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "ASM_NASM");
+ "ASM_NASM");
// Preprocessor definitions and includes are shared with clOptions.
Options& clOptions = *(this->ClOptions[configName]);
clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "ASM_NASM");
+ "ASM_NASM");
this->WriteString("</NASM>\n", 2);
}
@@ -2994,11 +2920,10 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions(
libflags, cmSystemTools::UpperCase(config), this->GeneratorTarget);
if (!libflags.empty()) {
this->WriteString("<Lib>\n", 2);
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- cmVisualStudioGeneratorOptions libOptions(
- this->LocalGenerator, cmVisualStudioGeneratorOptions::Linker,
- gg->GetLibFlagTable(), 0, this);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ cmVS10GeneratorOptions libOptions(this->LocalGenerator,
+ cmVisualStudioGeneratorOptions::Linker,
+ gg->GetLibFlagTable(), this);
libOptions.Parse(libflags.c_str());
libOptions.PrependInheritedString("AdditionalOptions");
libOptions.OutputFlagMap(*this->BuildFileStream, " ");
@@ -3011,9 +2936,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);
}
}
@@ -3064,32 +2987,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 =
@@ -3099,9 +3018,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 =
@@ -3112,16 +3029,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 =
@@ -3131,31 +3044,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 =
@@ -3185,11 +3090,9 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
std::string const& config)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- auto pOptions =
- cm::make_unique<Options>(this->LocalGenerator, Options::Linker,
- gg->GetLinkFlagTable(), nullptr, this);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ auto pOptions = cm::make_unique<Options>(
+ this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), this);
Options& linkOptions = *pOptions;
cmGeneratorTarget::LinkClosure const* linkClosure =
@@ -3217,12 +3120,10 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
linkFlagVarBase += linkType;
linkFlagVarBase += "_LINKER_FLAGS";
flags += " ";
- flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- linkFlagVarBase);
+ flags += this->Makefile->GetRequiredDefinition(linkFlagVarBase);
std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
flags += " ";
- flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- linkFlagVar);
+ flags += this->Makefile->GetRequiredDefinition(linkFlagVar);
const char* targetLinkFlags =
this->GeneratorTarget->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
@@ -3376,7 +3277,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)");
@@ -3459,8 +3360,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);
}
}
@@ -3474,6 +3374,17 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
std::string currentBinDir =
this->LocalGenerator->GetCurrentBinaryDirectory();
for (cmComputeLinkInformation::Item const& l : libs) {
+ // Do not allow C# targets to be added to the LIB listing. LIB files are
+ // used for linking C++ dependencies. C# libraries do not have lib files.
+ // Instead, they compile down to C# reference libraries (DLL files). The
+ // `<ProjectReference>` elements added to the vcxproj are enough for the
+ // IDE to deduce the DLL file required by other C# projects that need its
+ // reference library.
+ if (l.Target &&
+ cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(l.Target)) {
+ continue;
+ }
+
if (l.IsPath) {
std::string path =
this->LocalGenerator->ConvertToRelativePath(currentBinDir, l.Value);
@@ -3543,15 +3454,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);
}
@@ -3643,8 +3550,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;
@@ -3679,8 +3585,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
}
// skip fortran targets as they can not be processed by MSBuild
// the only reference will be in the .sln file
- if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetIsFortranOnly(dt)) {
+ if (this->GlobalGenerator->TargetIsFortranOnly(dt)) {
continue;
}
this->WriteString("<ProjectReference Include=\"", 2);
@@ -3698,18 +3603,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 (!static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetCanBeReferenced(dt)) {
- this->WriteString(
- "<ReferenceOutputAssembly>false</ReferenceOutputAssembly>\n", 3);
+ if (!this->GlobalGenerator->TargetCanBeReferenced(dt)) {
+ this->WriteElem("ReferenceOutputAssembly", "false", 3);
}
}
this->WriteString("</ProjectReference>\n", 2);
@@ -3839,14 +3739,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
@@ -3860,26 +3758,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);
}
@@ -3921,52 +3811,35 @@ bool cmVisualStudio10TargetGenerator::IsXamlSource(
void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings()
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
bool isAppContainer = false;
bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone();
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) {
@@ -3974,52 +3847,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);
}
}
@@ -4150,7 +4013,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);
@@ -4428,7 +4291,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 33d4fb7..7106737 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -21,7 +21,7 @@ class cmLocalVisualStudio7Generator;
class cmMakefile;
class cmSourceFile;
class cmSourceGroup;
-class cmVisualStudioGeneratorOptions;
+class cmVS10GeneratorOptions;
class cmVisualStudio10TargetGenerator
{
@@ -34,8 +34,7 @@ public:
void Generate();
// used by cmVisualStudioGeneratorOptions
void WritePlatformConfigTag(const char* tag, const std::string& config,
- int indentLevel, const char* attribute = 0,
- const char* end = 0, std::ostream* strm = 0);
+ int indentLevel, const char* attribute = 0);
private:
struct ToolSource
@@ -53,8 +52,14 @@ private:
std::vector<std::string> Configs;
};
+ struct Elem;
+
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);
@@ -62,9 +67,9 @@ private:
void WriteHeaderSource(cmSourceFile const* sf);
void WriteExtraSource(cmSourceFile const* sf);
void WriteNsightTegraConfigurationValues(std::string const& config);
- void WriteSource(std::string const& tool, cmSourceFile const* sf,
- const char* end = 0);
- void WriteExcludeFromBuild(std::vector<size_t> const& exclude_configs);
+ void WriteSource(std::string const& tool, cmSourceFile const* sf);
+ void WriteExcludeFromBuild(Elem&,
+ std::vector<size_t> const& exclude_configs);
void WriteAllSources();
void WriteDotNetReferences();
void WriteDotNetReference(std::string const& ref, std::string const& hint);
@@ -141,7 +146,7 @@ private:
void WriteGroups();
void WriteProjectReferences();
void WriteApplicationTypeSettings();
- bool OutputSourceSpecificFlags(cmSourceFile const* source);
+ void OutputSourceSpecificFlags(Elem&, cmSourceFile const* source);
void AddLibraries(cmComputeLinkInformation& cli,
std::vector<std::string>& libVec,
std::vector<std::string>& vsTargetVec);
@@ -153,7 +158,7 @@ private:
void WriteEvent(const char* name,
std::vector<cmCustomCommand> const& commands,
std::string const& configName);
- void WriteGroupSources(const char* name, ToolSources const& sources,
+ void WriteGroupSources(std::string const& name, ToolSources const& sources,
std::vector<cmSourceGroup>&);
void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
const std::vector<cmSourceGroup>& allGroups);
@@ -170,7 +175,7 @@ private:
void GetCSharpSourceLink(cmSourceFile const* sf, std::string& link);
private:
- typedef cmVisualStudioGeneratorOptions Options;
+ typedef cmVS10GeneratorOptions Options;
typedef std::map<std::string, std::unique_ptr<Options>> OptionsMap;
OptionsMap ClOptions;
OptionsMap RcOptions;
@@ -190,19 +195,19 @@ private:
bool InSourceBuild;
std::vector<std::string> Configurations;
std::vector<TargetsFileAndConfigs> TargetsFileAndConfigsVec;
- cmGeneratorTarget* GeneratorTarget;
- cmMakefile* Makefile;
- std::string Platform;
- std::string GUID;
- std::string Name;
+ cmGeneratorTarget* const GeneratorTarget;
+ cmMakefile* const Makefile;
+ std::string const Platform;
+ std::string const Name;
+ std::string const GUID;
bool MSTools;
bool Managed;
bool NsightTegra;
int NsightTegraVersion[4];
bool TargetCompileAsWinRT;
- cmGlobalVisualStudio10Generator* GlobalGenerator;
+ cmGlobalVisualStudio10Generator* const GlobalGenerator;
cmGeneratedFileStream* BuildFileStream;
- cmLocalVisualStudio7Generator* LocalGenerator;
+ cmLocalVisualStudio7Generator* const LocalGenerator;
std::set<cmSourceFile const*> SourcesVisited;
std::set<std::string> CSharpCustomCommandNames;
bool IsMissingFiles;
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index ccbff83..8b6f057 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -4,43 +4,19 @@
#include "cmLocalVisualStudioGenerator.h"
#include "cmOutputConverter.h"
#include "cmSystemTools.h"
-#include "cmVisualStudio10TargetGenerator.h"
-static std::string cmVisualStudio10GeneratorOptionsEscapeForXML(
- std::string ret)
+static void cmVS10EscapeForMSBuild(std::string& ret)
{
cmSystemTools::ReplaceString(ret, ";", "%3B");
- cmSystemTools::ReplaceString(ret, "&", "&amp;");
- cmSystemTools::ReplaceString(ret, "<", "&lt;");
- cmSystemTools::ReplaceString(ret, ">", "&gt;");
- return ret;
-}
-
-static std::string cmVisualStudioGeneratorOptionsEscapeForXML(std::string ret)
-{
- cmSystemTools::ReplaceString(ret, "&", "&amp;");
- cmSystemTools::ReplaceString(ret, "\"", "&quot;");
- cmSystemTools::ReplaceString(ret, "<", "&lt;");
- cmSystemTools::ReplaceString(ret, ">", "&gt;");
- cmSystemTools::ReplaceString(ret, "\n", "&#x0D;&#x0A;");
- return ret;
-}
-
-cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
- cmLocalVisualStudioGenerator* lg, Tool tool,
- cmVisualStudio10TargetGenerator* g)
- : cmVisualStudioGeneratorOptions(lg, tool, nullptr, nullptr, g)
-{
}
cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
cmLocalVisualStudioGenerator* lg, Tool tool, cmVS7FlagTable const* table,
- cmVS7FlagTable const* extraTable, cmVisualStudio10TargetGenerator* g)
+ cmVS7FlagTable const* extraTable)
: cmIDEOptions()
, LocalGenerator(lg)
, Version(lg->GetVersion())
, CurrentTool(tool)
- , TargetGenerator(g)
{
// Store the given flag tables.
this->AddTable(table);
@@ -152,9 +128,8 @@ bool cmVisualStudioGeneratorOptions::IsManaged() const
bool cmVisualStudioGeneratorOptions::UsingUnicode() const
{
// Look for the a _UNICODE definition.
- for (std::vector<std::string>::const_iterator di = this->Defines.begin();
- di != this->Defines.end(); ++di) {
- if (*di == "_UNICODE") {
+ for (std::string const& di : this->Defines) {
+ if (di == "_UNICODE") {
return true;
}
}
@@ -163,9 +138,8 @@ bool cmVisualStudioGeneratorOptions::UsingUnicode() const
bool cmVisualStudioGeneratorOptions::UsingSBCS() const
{
// Look for the a _SBCS definition.
- for (std::vector<std::string>::const_iterator di = this->Defines.begin();
- di != this->Defines.end(); ++di) {
- if (*di == "_SBCS") {
+ for (std::string const& di : this->Defines) {
+ if (di == "_SBCS") {
return true;
}
}
@@ -227,7 +201,7 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
// It translates to -arch=<virtual> -code=<real>.
cmSystemTools::ReplaceString(arch_name, "sm_", "compute_");
}
- for (auto const& c : codes) {
+ for (std::string const& c : codes) {
std::string entry = arch_name + "," + c;
result.push_back(entry);
}
@@ -237,7 +211,7 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
// -gencode=<arch>,<code>
// -gencode=<arch>,[<code1>,<code2>]
// -gencode=<arch>,"<code1>,<code2>"
- for (auto const& e : gencode) {
+ for (std::string const& e : gencode) {
std::string entry = e;
cmSystemTools::ReplaceString(entry, "arch=", "");
cmSystemTools::ReplaceString(entry, "code=", "");
@@ -285,7 +259,7 @@ void cmVisualStudioGeneratorOptions::FixManifestUACFlags()
uacExecuteLevelMap["highestAvailable"] = "HighestAvailable";
uacExecuteLevelMap["requireAdministrator"] = "RequireAdministrator";
- for (auto const& subopt : subOptions) {
+ for (std::string const& subopt : subOptions) {
std::vector<std::string> keyValue;
cmsys::SystemTools::Split(subopt, keyValue, '=');
if (keyValue.size() != 2 || (uacMap.find(keyValue[0]) == uacMap.end())) {
@@ -332,9 +306,8 @@ void cmVisualStudioGeneratorOptions::Parse(const char* flags)
// Process flags that need to be represented specially in the IDE
// project file.
- for (std::vector<std::string>::iterator ai = args.begin(); ai != args.end();
- ++ai) {
- this->HandleFlag(ai->c_str());
+ for (std::string const& ai : args) {
+ this->HandleFlag(ai);
}
}
@@ -396,23 +369,23 @@ void cmVisualStudioGeneratorOptions::Reparse(std::string const& key)
this->Parse(original.c_str());
}
-void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag)
+void cmVisualStudioGeneratorOptions::StoreUnknownFlag(std::string const& flag)
{
// Look for Intel Fortran flags that do not map well in the flag table.
if (this->CurrentTool == FortranCompiler) {
- if (strcmp(flag, "/dbglibs") == 0) {
+ if (flag == "/dbglibs") {
this->FortranRuntimeDebug = true;
return;
}
- if (strcmp(flag, "/threads") == 0) {
+ if (flag == "/threads") {
this->FortranRuntimeMT = true;
return;
}
- if (strcmp(flag, "/libs:dll") == 0) {
+ if (flag == "/libs:dll") {
this->FortranRuntimeDLL = true;
return;
}
- if (strcmp(flag, "/libs:static") == 0) {
+ if (flag == "/libs:static") {
this->FortranRuntimeDLL = false;
return;
}
@@ -420,7 +393,7 @@ void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag)
// This option is not known. Store it in the output flags.
std::string const opts = cmOutputConverter::EscapeWindowsShellArgument(
- flag, cmOutputConverter::Shell_Flag_AllowMakeVariables |
+ flag.c_str(), cmOutputConverter::Shell_Flag_AllowMakeVariables |
cmOutputConverter::Shell_Flag_VSIDE);
this->AppendFlagString(this->UnknownFlagField, opts);
}
@@ -437,14 +410,19 @@ cmIDEOptions::FlagValue cmVisualStudioGeneratorOptions::TakeFlag(
return value;
}
-void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config)
+void cmVisualStudioGeneratorOptions::SetConfiguration(
+ const std::string& config)
{
this->Configuration = config;
}
+const std::string& cmVisualStudioGeneratorOptions::GetConfiguration() const
+{
+ return this->Configuration;
+}
+
void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
- std::ostream& fout, const char* prefix, const char* suffix,
- const std::string& lang)
+ std::ostream& fout, const char* prefix, const std::string& lang)
{
if (this->Defines.empty()) {
return;
@@ -453,19 +431,8 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
if (lang == "CUDA") {
tag = "Defines";
}
- if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- // if there are configuration specific flags, then
- // use the configuration specific tag for PreprocessorDefinitions
- if (!this->Configuration.empty()) {
- fout << prefix;
- this->TargetGenerator->WritePlatformConfigTag(
- tag, this->Configuration.c_str(), 0, 0, 0, &fout);
- } else {
- fout << prefix << "<" << tag << ">";
- }
- } else {
- fout << prefix << tag << "=\"";
- }
+
+ std::ostringstream oss;
const char* sep = "";
std::vector<std::string>::const_iterator de =
cmRemoveDuplicates(this->Defines);
@@ -474,34 +441,30 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
// Escape the definition for the compiler.
std::string define;
if (this->Version < cmGlobalVisualStudioGenerator::VS10) {
- define = this->LocalGenerator->EscapeForShell(di->c_str(), true);
+ define = this->LocalGenerator->EscapeForShell(*di, true);
} else {
define = *di;
}
- // Escape this flag for the IDE.
+ // Escape this flag for the MSBuild.
if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- define = cmVisualStudio10GeneratorOptionsEscapeForXML(define);
-
+ cmVS10EscapeForMSBuild(define);
if (lang == "RC") {
cmSystemTools::ReplaceString(define, "\"", "\\\"");
}
- } else {
- define = cmVisualStudioGeneratorOptionsEscapeForXML(define);
}
// Store the flag in the project file.
- fout << sep << define;
+ oss << sep << define;
sep = ";";
}
if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- fout << ";%(" << tag << ")</" << tag << ">" << suffix;
- } else {
- fout << "\"" << suffix;
+ oss << ";%(" << tag << ")";
}
+
+ this->OutputFlag(fout, prefix, tag, oss.str());
}
void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories(
- std::ostream& fout, const char* prefix, const char* suffix,
- const std::string& lang)
+ std::ostream& fout, const char* prefix, const std::string& lang)
{
if (this->Includes.empty()) {
return;
@@ -514,20 +477,7 @@ void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories(
tag = "IncludePaths";
}
- if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- // if there are configuration specific flags, then
- // use the configuration specific tag for PreprocessorDefinitions
- if (!this->Configuration.empty()) {
- fout << prefix;
- this->TargetGenerator->WritePlatformConfigTag(
- tag, this->Configuration.c_str(), 0, 0, 0, &fout);
- } else {
- fout << prefix << "<" << tag << ">";
- }
- } else {
- fout << prefix << tag << "=\"";
- }
-
+ std::ostringstream oss;
const char* sep = "";
for (std::string include : this->Includes) {
// first convert all of the slashes
@@ -541,59 +491,40 @@ void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories(
include += "\\";
}
- // Escape this include for the IDE.
- fout << sep << (this->Version >= cmGlobalVisualStudioGenerator::VS10
- ? cmVisualStudio10GeneratorOptionsEscapeForXML(include)
- : cmVisualStudioGeneratorOptionsEscapeForXML(include));
+ // Escape this include for the MSBuild.
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ cmVS10EscapeForMSBuild(include);
+ }
+ oss << sep << include;
sep = ";";
if (lang == "Fortran") {
include += "/$(ConfigurationName)";
- fout << sep << (this->Version >= cmGlobalVisualStudioGenerator::VS10
- ? cmVisualStudio10GeneratorOptionsEscapeForXML(include)
- : cmVisualStudioGeneratorOptionsEscapeForXML(include));
+ oss << sep << include;
}
}
if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- fout << sep << "%(" << tag << ")</" << tag << ">" << suffix;
- } else {
- fout << "\"" << suffix;
+ oss << sep << "%(" << tag << ")";
}
+
+ this->OutputFlag(fout, prefix, tag, oss.str());
}
void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout,
const char* indent)
{
- if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- for (std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin();
- m != this->FlagMap.end(); ++m) {
- fout << indent;
- if (!this->Configuration.empty()) {
- this->TargetGenerator->WritePlatformConfigTag(
- m->first.c_str(), this->Configuration.c_str(), 0, 0, 0, &fout);
- } else {
- fout << "<" << m->first << ">";
+ for (auto const& m : this->FlagMap) {
+ std::ostringstream oss;
+ const char* sep = "";
+ for (std::string i : m.second) {
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ cmVS10EscapeForMSBuild(i);
}
- const char* sep = "";
- for (std::vector<std::string>::iterator i = m->second.begin();
- i != m->second.end(); ++i) {
- fout << sep << cmVisualStudio10GeneratorOptionsEscapeForXML(*i);
- sep = ";";
- }
- fout << "</" << m->first << ">\n";
- }
- } else {
- for (std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin();
- m != this->FlagMap.end(); ++m) {
- fout << indent << m->first << "=\"";
- const char* sep = "";
- for (std::vector<std::string>::iterator i = m->second.begin();
- i != m->second.end(); ++i) {
- fout << sep << cmVisualStudioGeneratorOptionsEscapeForXML(*i);
- sep = ";";
- }
- fout << "\"\n";
+ oss << sep << i;
+ sep = ";";
}
+
+ this->OutputFlag(fout, indent, m.first.c_str(), oss.str());
}
}
diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h
index 2dffe9b..974ca62 100644
--- a/Source/cmVisualStudioGeneratorOptions.h
+++ b/Source/cmVisualStudioGeneratorOptions.h
@@ -16,8 +16,6 @@ class cmLocalVisualStudioGenerator;
typedef cmIDEFlagTable cmVS7FlagTable;
-class cmVisualStudio10TargetGenerator;
-
class cmVisualStudioGeneratorOptions : public cmIDEOptions
{
public:
@@ -34,12 +32,8 @@ public:
CSharpCompiler
};
cmVisualStudioGeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
- cmVS7FlagTable const* table,
- cmVS7FlagTable const* extraTable = 0,
- cmVisualStudio10TargetGenerator* g = 0);
-
- cmVisualStudioGeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
- cmVisualStudio10TargetGenerator* g = 0);
+ cmVS7FlagTable const* table = nullptr,
+ cmVS7FlagTable const* extraTable = nullptr);
// Add a table of flags.
void AddTable(cmVS7FlagTable const* table);
@@ -84,14 +78,17 @@ public:
bool IsManaged() const;
// Write options to output.
void OutputPreprocessorDefinitions(std::ostream& fout, const char* prefix,
- const char* suffix,
const std::string& lang);
void OutputAdditionalIncludeDirectories(std::ostream& fout,
const char* prefix,
- const char* suffix,
const std::string& lang);
void OutputFlagMap(std::ostream& fout, const char* indent);
- void SetConfiguration(const char* config);
+ void SetConfiguration(const std::string& config);
+ const std::string& GetConfiguration() const;
+
+protected:
+ virtual void OutputFlag(std::ostream& fout, const char* indent,
+ const char* tag, const std::string& content) = 0;
private:
cmLocalVisualStudioGenerator* LocalGenerator;
@@ -99,7 +96,6 @@ private:
std::string Configuration;
Tool CurrentTool;
- cmVisualStudio10TargetGenerator* TargetGenerator;
bool FortranRuntimeDebug;
bool FortranRuntimeDLL;
@@ -107,7 +103,7 @@ private:
std::string UnknownFlagField;
- virtual void StoreUnknownFlag(const char* flag);
+ void StoreUnknownFlag(std::string const& flag) override;
FlagValue TakeFlag(std::string const& key);
};
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/cmXMLWriter.h b/Source/cmXMLWriter.h
index 7bae21e..80940ee 100644
--- a/Source/cmXMLWriter.h
+++ b/Source/cmXMLWriter.h
@@ -133,4 +133,56 @@ private:
bool IsContent;
};
+class cmXMLElement; // IWYU pragma: keep
+
+class cmXMLDocument
+{
+public:
+ cmXMLDocument(cmXMLWriter& xml)
+ : xmlwr(xml)
+ {
+ xmlwr.StartDocument();
+ }
+ ~cmXMLDocument() { xmlwr.EndDocument(); }
+private:
+ friend class cmXMLElement;
+ cmXMLWriter& xmlwr;
+};
+
+class cmXMLElement
+{
+public:
+ cmXMLElement(cmXMLWriter& xml, const char* tag)
+ : xmlwr(xml)
+ {
+ xmlwr.StartElement(tag);
+ }
+ cmXMLElement(cmXMLElement& par, const char* tag)
+ : xmlwr(par.xmlwr)
+ {
+ xmlwr.StartElement(tag);
+ }
+ cmXMLElement(cmXMLDocument& doc, const char* tag)
+ : xmlwr(doc.xmlwr)
+ {
+ xmlwr.StartElement(tag);
+ }
+ ~cmXMLElement() { xmlwr.EndElement(); }
+
+ template <typename T>
+ cmXMLElement& Attribute(const char* name, T const& value)
+ {
+ xmlwr.Attribute(name, value);
+ return *this;
+ }
+ template <typename T>
+ void Content(T const& content)
+ {
+ xmlwr.Content(content);
+ }
+
+private:
+ cmXMLWriter& xmlwr;
+};
+
#endif
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 5620723..83c5384 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -55,7 +55,6 @@
#include "cmGlobalVisualStudio12Generator.h"
#include "cmGlobalVisualStudio14Generator.h"
#include "cmGlobalVisualStudio15Generator.h"
-#include "cmGlobalVisualStudio8Generator.h"
#include "cmGlobalVisualStudio9Generator.h"
#include "cmVSSetupHelper.h"
@@ -98,13 +97,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 {
@@ -1464,8 +1463,7 @@ void cmake::CreateDefaultGlobalGenerator()
{ "12.0", "Visual Studio 12 2013" }, //
{ "11.0", "Visual Studio 11 2012" }, //
{ "10.0", "Visual Studio 10 2010" }, //
- { "9.0", "Visual Studio 9 2008" }, //
- { "8.0", "Visual Studio 8 2005" }
+ { "9.0", "Visual Studio 9 2008" }
};
static const char* const vsEntries[] = {
"\\Setup\\VC;ProductDir", //
@@ -1689,7 +1687,6 @@ void cmake::AddDefaultGenerators()
this->Generators.push_back(cmGlobalVisualStudio11Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio10Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio9Generator::NewFactory());
- this->Generators.push_back(cmGlobalVisualStudio8Generator::NewFactory());
this->Generators.push_back(cmGlobalBorlandMakefileGenerator::NewFactory());
this->Generators.push_back(cmGlobalNMakeMakefileGenerator::NewFactory());
this->Generators.push_back(cmGlobalJOMMakefileGenerator::NewFactory());
@@ -2209,6 +2206,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);
@@ -2387,17 +2393,17 @@ int cmake::Build(const std::string& dir, const std::string& target,
std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n";
return 1;
}
- std::unique_ptr<cmGlobalGenerator> gen(
- this->CreateGlobalGenerator(cachedGenerator));
- if (!gen.get()) {
+ cmGlobalGenerator* gen = this->CreateGlobalGenerator(cachedGenerator);
+ if (!gen) {
std::cerr << "Error: could create CMAKE_GENERATOR \"" << cachedGenerator
<< "\"\n";
return 1;
}
+ this->SetGlobalGenerator(gen);
const char* cachedGeneratorInstance =
this->State->GetCacheEntryValue("CMAKE_GENERATOR_INSTANCE");
if (cachedGeneratorInstance) {
- cmMakefile mf(gen.get(), this->GetCurrentSnapshot());
+ cmMakefile mf(gen, this->GetCurrentSnapshot());
if (!gen->SetGeneratorInstance(cachedGeneratorInstance, &mf)) {
return 1;
}
@@ -2425,7 +2431,7 @@ int cmake::Build(const std::string& dir, const std::string& target,
// to limitations of the underlying build system.
std::string const stampList = cachePath + "/" +
GetCMakeFilesDirectoryPostSlash() +
- cmGlobalVisualStudio8Generator::GetGenerateStampList();
+ cmGlobalVisualStudio9Generator::GetGenerateStampList();
// Note that the stampList file only exists for VS generators.
if (cmSystemTools::FileExists(stampList) &&
diff --git a/Source/cmake.h b/Source/cmake.h
index 1ac549b..cc56a07 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -574,6 +574,7 @@ private:
F(cxx_std_11) \
F(cxx_std_14) \
F(cxx_std_17) \
+ F(cxx_std_20) \
F(cxx_aggregate_default_initializers) \
F(cxx_alias_templates) \
F(cxx_alignas) \
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 0988c3c..6f3a90f 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -359,7 +359,8 @@ struct CoCompileJob
int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
{
std::vector<CoCompileJob> jobs;
- std::string sourceFile; // store --source=
+ std::string sourceFile; // store --source=
+ std::vector<std::string> launchers; // store --launcher=
// Default is to run the original command found after -- if the option
// does not need to do that, it should be specified here, currently only
@@ -390,15 +391,17 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
}
}
}
- if (cmHasLiteralPrefix(arg, "--source=")) {
- sourceFile = arg.substr(9);
- optionFound = true;
- }
- // if it was not a co-compiler or --source then error
if (!optionFound) {
- std::cerr << "__run_co_compile given unknown argument: " << arg
- << "\n";
- return 1;
+ if (cmHasLiteralPrefix(arg, "--source=")) {
+ sourceFile = arg.substr(9);
+ } else if (cmHasLiteralPrefix(arg, "--launcher=")) {
+ cmSystemTools::ExpandListArgument(arg.substr(11), launchers, true);
+ } else {
+ // if it was not a co-compiler or --source/--launcher then error
+ std::cerr << "__run_co_compile given unknown argument: " << arg
+ << "\n";
+ return 1;
+ }
}
} else { // if not doing_options then push to orig_cmd
orig_cmd.push_back(arg);
@@ -436,6 +439,11 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
return 0;
}
+ // Prepend launcher argument(s), if any
+ if (!launchers.empty()) {
+ orig_cmd.insert(orig_cmd.begin(), launchers.begin(), launchers.end());
+ }
+
// Now run the real compiler command and return its result value
int ret;
if (!cmSystemTools::RunSingleCommand(orig_cmd, nullptr, nullptr, &ret,
@@ -689,8 +697,6 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Touch file
if (args[1] == "touch_nocreate" && args.size() > 2) {
for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- // Complain if the file could not be removed, still exists,
- // and the -f option was not given.
if (!cmSystemTools::Touch(args[cc], false)) {
return 1;
}
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 106afe5..52f509a 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -3344,15 +3344,20 @@ std::string SystemTools::RelativePath(const std::string& local,
static std::string GetCasePathName(std::string const& pathIn)
{
std::string casePath;
- std::vector<std::string> path_components;
- SystemTools::SplitPath(pathIn, path_components);
- if (path_components[0].empty()) // First component always exists.
- {
- // Relative paths cannot be converted.
+
+ // First check if the file is relative. We don't fix relative paths since the
+ // real case depends on the root directory and the given path fragment may
+ // have meaning elsewhere in the project.
+ if (!SystemTools::FileIsFullPath(pathIn)) {
+ // This looks unnecessary, but it allows for the return value optimization
+ // since all return paths return the same local variable.
casePath = pathIn;
return casePath;
}
+ std::vector<std::string> path_components;
+ SystemTools::SplitPath(pathIn, path_components);
+
// Start with root component.
std::vector<std::string>::size_type idx = 0;
casePath = path_components[idx++];
diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c
index eaa5c7d..c9f9dc5 100644
--- a/Source/kwsys/Terminal.c
+++ b/Source/kwsys/Terminal.c
@@ -153,6 +153,7 @@ static const char* kwsysTerminalVT100Names[] = { "Eterm",
"xterm-88color",
"xterm-color",
"xterm-debian",
+ "xterm-kitty",
"xterm-termite",
0 };
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index e436a2b..a6d934b 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -738,29 +738,29 @@ static bool CheckGetPath()
#endif
const char* registryPath = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MyApp; MyKey]";
- std::vector<std::string> originalPathes;
- originalPathes.push_back(registryPath);
+ std::vector<std::string> originalPaths;
+ originalPaths.push_back(registryPath);
- std::vector<std::string> expectedPathes;
- expectedPathes.push_back(registryPath);
+ std::vector<std::string> expectedPaths;
+ expectedPaths.push_back(registryPath);
#ifdef _WIN32
- expectedPathes.push_back("C:/Somewhere/something");
- expectedPathes.push_back("D:/Temp");
+ expectedPaths.push_back("C:/Somewhere/something");
+ expectedPaths.push_back("D:/Temp");
#else
- expectedPathes.push_back("/Somewhere/something");
- expectedPathes.push_back("/tmp");
+ expectedPaths.push_back("/Somewhere/something");
+ expectedPaths.push_back("/tmp");
#endif
bool res = true;
res &= CheckPutEnv(std::string(envName) + "=" + envValue, envName, envValue);
- std::vector<std::string> pathes = originalPathes;
- kwsys::SystemTools::GetPath(pathes, envName);
+ std::vector<std::string> paths = originalPaths;
+ kwsys::SystemTools::GetPath(paths, envName);
- if (pathes != expectedPathes) {
- std::cerr << "GetPath(" << StringVectorToString(originalPathes) << ", "
- << envName << ") yielded " << StringVectorToString(pathes)
- << " instead of " << StringVectorToString(expectedPathes)
+ if (paths != expectedPaths) {
+ std::cerr << "GetPath(" << StringVectorToString(originalPaths) << ", "
+ << envName << ") yielded " << StringVectorToString(paths)
+ << " instead of " << StringVectorToString(expectedPaths)
<< std::endl;
res = false;
}