summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt4
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx47
-rw-r--r--Source/cmFilePathChecksum.cxx88
-rw-r--r--Source/cmFilePathChecksum.h65
-rw-r--r--Source/cmFilePathUuid.cxx118
-rw-r--r--Source/cmFilePathUuid.h69
-rw-r--r--Source/cmGeneratorTarget.cxx15
-rw-r--r--Source/cmGeneratorTarget.h6
-rw-r--r--Source/cmLocalGenerator.cxx1
-rw-r--r--Source/cmMakefile.cxx33
-rw-r--r--Source/cmMakefile.h3
-rw-r--r--Source/cmQtAutoGeneratorInitializer.cxx441
-rw-r--r--Source/cmQtAutoGenerators.cxx529
-rw-r--r--Source/cmQtAutoGenerators.h68
-rw-r--r--Source/cmServerProtocol.cxx3
-rw-r--r--Source/cmake.h1
-rw-r--r--Source/kwsys/CMakeLists.txt13
-rw-r--r--Source/kwsys/ConsoleBuf.hxx.in5
-rw-r--r--Source/kwsys/DynamicLoader.cxx154
-rw-r--r--Source/kwsys/EncodingCXX.cxx60
-rw-r--r--Source/kwsys/testConsoleBuf.cxx33
-rw-r--r--Source/kwsys/testConsoleBuf.hxx2
-rw-r--r--Source/kwsys/testConsoleBufChild.cxx3
-rw-r--r--Source/kwsys/testEncoding.cxx31
25 files changed, 1002 insertions, 792 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 5b381b4..d15fdbe 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -243,8 +243,8 @@ set(SRCS
cmFileLockPool.h
cmFileLockResult.cxx
cmFileLockResult.h
- cmFilePathUuid.cxx
- cmFilePathUuid.h
+ cmFilePathChecksum.cxx
+ cmFilePathChecksum.h
cmFileTimeComparison.cxx
cmFileTimeComparison.h
cmFortranLexer.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index d5f5724..f1fca76 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 7)
-set(CMake_VERSION_PATCH 20161202)
+set(CMake_VERSION_PATCH 20161207)
#set(CMake_VERSION_RC 1)
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index ab43dbc..68f9a54 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -797,8 +797,9 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
// Prepare some maps to help us find setup and cleanup tests for
// any given fixture
- typedef std::set<ListOfTests::const_iterator> TestIteratorSet;
- typedef std::map<std::string, TestIteratorSet> FixtureDependencies;
+ typedef ListOfTests::const_iterator TestIterator;
+ typedef std::multimap<std::string, TestIterator> FixtureDependencies;
+ typedef FixtureDependencies::const_iterator FixtureDepsIterator;
FixtureDependencies fixtureSetups;
FixtureDependencies fixtureDeps;
@@ -809,14 +810,14 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
const std::set<std::string>& setups = p.FixturesSetup;
for (std::set<std::string>::const_iterator depsIt = setups.begin();
depsIt != setups.end(); ++depsIt) {
- fixtureSetups[*depsIt].insert(it);
- fixtureDeps[*depsIt].insert(it);
+ fixtureSetups.insert(std::make_pair(*depsIt, it));
+ fixtureDeps.insert(std::make_pair(*depsIt, it));
}
const std::set<std::string>& cleanups = p.FixturesCleanup;
for (std::set<std::string>::const_iterator depsIt = cleanups.begin();
depsIt != cleanups.end(); ++depsIt) {
- fixtureDeps[*depsIt].insert(it);
+ fixtureDeps.insert(std::make_pair(*depsIt, it));
}
}
@@ -859,17 +860,15 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
// associated with the required fixture. If any of those setup
// tests fail, this test should not run. We make the fixture's
// cleanup tests depend on this test case later.
- FixtureDependencies::const_iterator setupIt =
- fixtureSetups.find(requiredFixtureName);
- if (setupIt != fixtureSetups.end()) {
- for (TestIteratorSet::const_iterator sIt = setupIt->second.begin();
- sIt != setupIt->second.end(); ++sIt) {
- const std::string& setupTestName = (**sIt).Name;
- tests[i].RequireSuccessDepends.insert(setupTestName);
- if (std::find(tests[i].Depends.begin(), tests[i].Depends.end(),
- setupTestName) == tests[i].Depends.end()) {
- tests[i].Depends.push_back(setupTestName);
- }
+ std::pair<FixtureDepsIterator, FixtureDepsIterator> setupRange =
+ fixtureSetups.equal_range(requiredFixtureName);
+ for (FixtureDepsIterator sIt = setupRange.first;
+ sIt != setupRange.second; ++sIt) {
+ const std::string& setupTestName = sIt->second->Name;
+ tests[i].RequireSuccessDepends.insert(setupTestName);
+ if (std::find(tests[i].Depends.begin(), tests[i].Depends.end(),
+ setupTestName) == tests[i].Depends.end()) {
+ tests[i].Depends.push_back(setupTestName);
}
}
@@ -882,17 +881,11 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
// Already added this fixture
continue;
}
- FixtureDependencies::const_iterator fixtureIt =
- fixtureDeps.find(requiredFixtureName);
- if (fixtureIt == fixtureDeps.end()) {
- // No setup or cleanup tests for this fixture
- continue;
- }
-
- const TestIteratorSet& testIters = fixtureIt->second;
- for (TestIteratorSet::const_iterator depsIt = testIters.begin();
- depsIt != testIters.end(); ++depsIt) {
- ListOfTests::const_iterator lotIt = *depsIt;
+ std::pair<FixtureDepsIterator, FixtureDepsIterator> fixtureRange =
+ fixtureDeps.equal_range(requiredFixtureName);
+ for (FixtureDepsIterator it = fixtureRange.first;
+ it != fixtureRange.second; ++it) {
+ ListOfTests::const_iterator lotIt = it->second;
const cmCTestTestProperties& p = *lotIt;
if (!addedTests.insert(p.Name).second) {
diff --git a/Source/cmFilePathChecksum.cxx b/Source/cmFilePathChecksum.cxx
new file mode 100644
index 0000000..3d8b695
--- /dev/null
+++ b/Source/cmFilePathChecksum.cxx
@@ -0,0 +1,88 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFilePathChecksum.h"
+
+#include "cmBase32.h"
+#include "cmCryptoHash.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+#include <vector>
+
+cmFilePathChecksum::cmFilePathChecksum()
+{
+}
+
+cmFilePathChecksum::cmFilePathChecksum(const std::string& currentSrcDir,
+ const std::string& currentBinDir,
+ const std::string& projectSrcDir,
+ const std::string& projectBinDir)
+{
+ setupParentDirs(currentSrcDir, currentBinDir, projectSrcDir, projectBinDir);
+}
+
+cmFilePathChecksum::cmFilePathChecksum(cmMakefile* makefile)
+{
+ setupParentDirs(makefile->GetCurrentSourceDirectory(),
+ makefile->GetCurrentBinaryDirectory(),
+ makefile->GetHomeDirectory(),
+ makefile->GetHomeOutputDirectory());
+}
+
+void cmFilePathChecksum::setupParentDirs(const std::string& currentSrcDir,
+ const std::string& currentBinDir,
+ const std::string& projectSrcDir,
+ const std::string& projectBinDir)
+{
+ parentDirs[0].first = cmsys::SystemTools::GetRealPath(currentSrcDir);
+ parentDirs[1].first = cmsys::SystemTools::GetRealPath(currentBinDir);
+ parentDirs[2].first = cmsys::SystemTools::GetRealPath(projectSrcDir);
+ parentDirs[3].first = cmsys::SystemTools::GetRealPath(projectBinDir);
+
+ parentDirs[0].second = "CurrentSource";
+ parentDirs[1].second = "CurrentBinary";
+ parentDirs[2].second = "ProjectSource";
+ parentDirs[3].second = "ProjectBinary";
+}
+
+std::string cmFilePathChecksum::get(const std::string& filePath)
+{
+ std::string relPath;
+ std::string relSeed;
+ {
+ const std::string fileReal = cmsys::SystemTools::GetRealPath(filePath);
+ std::string parentDir;
+ // Find closest project parent directory
+ for (size_t ii = 0; ii != numParentDirs; ++ii) {
+ const std::string& pDir = parentDirs[ii].first;
+ if (!pDir.empty() &&
+ cmsys::SystemTools::IsSubDirectory(fileReal, pDir)) {
+ relSeed = parentDirs[ii].second;
+ parentDir = pDir;
+ break;
+ }
+ }
+ // Use file system root as fallback parent directory
+ if (parentDir.empty()) {
+ relSeed = "FileSystemRoot";
+ cmsys::SystemTools::SplitPathRootComponent(fileReal, &parentDir);
+ }
+ // Calculate relative path from project parent directory
+ relPath = cmsys::SystemTools::RelativePath(
+ parentDir, cmsys::SystemTools::GetParentDirectory(fileReal));
+ }
+
+ // Calculate the file ( seed + relative path ) binary checksum
+ std::vector<unsigned char> hashBytes =
+ cmCryptoHash(cmCryptoHash::AlgoSHA256).ByteHashString(relSeed + relPath);
+
+ // Convert binary checksum to string
+ return cmBase32Encoder().encodeString(&hashBytes[0], hashBytes.size(),
+ false);
+}
+
+std::string cmFilePathChecksum::getPart(const std::string& filePath,
+ size_t length)
+{
+ return get(filePath).substr(0, length);
+}
diff --git a/Source/cmFilePathChecksum.h b/Source/cmFilePathChecksum.h
new file mode 100644
index 0000000..df19053
--- /dev/null
+++ b/Source/cmFilePathChecksum.h
@@ -0,0 +1,65 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmFilePathChecksum_h
+#define cmFilePathChecksum_h
+
+#include <cmConfigure.h> // IWYU pragma: keep
+
+#include <stddef.h>
+#include <string>
+#include <utility>
+
+class cmMakefile;
+
+/** \class cmFilePathChecksum
+ * @brief Generates a checksum for the parent directory of a file
+ *
+ * The checksum is calculated from the relative file path to the
+ * closest known project directory. This guarantees reproducibility
+ * when source and build directory differ e.g. for different project
+ * build directories.
+ */
+class cmFilePathChecksum
+{
+public:
+ /// Maximum number of characters to use from the path checksum
+ static const size_t partLengthDefault = 10;
+
+ /// @brief Parent directories are empty
+ cmFilePathChecksum();
+
+ /// @brief Initilizes the parent directories manually
+ cmFilePathChecksum(const std::string& currentSrcDir,
+ const std::string& currentBinDir,
+ const std::string& projectSrcDir,
+ const std::string& projectBinDir);
+
+ /// @brief Initilizes the parent directories from a makefile
+ cmFilePathChecksum(cmMakefile* makefile);
+
+ /// @brief Allows parent directories setup after construction
+ ///
+ void setupParentDirs(const std::string& currentSrcDir,
+ const std::string& currentBinDir,
+ const std::string& projectSrcDir,
+ const std::string& projectBinDir);
+
+ /* @brief Calculates the path checksum for the parent directory of a file
+ *
+ */
+ std::string get(const std::string& filePath);
+
+ /* @brief Same as get() but returns only the first length characters
+ *
+ */
+ std::string getPart(const std::string& filePath,
+ size_t length = partLengthDefault);
+
+private:
+ /// Size of the parent directory list
+ static const size_t numParentDirs = 4;
+ /// List of (directory name, seed name) pairs
+ std::pair<std::string, std::string> parentDirs[numParentDirs];
+};
+
+#endif
diff --git a/Source/cmFilePathUuid.cxx b/Source/cmFilePathUuid.cxx
deleted file mode 100644
index 03d2524..0000000
--- a/Source/cmFilePathUuid.cxx
+++ /dev/null
@@ -1,118 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmFilePathUuid.h"
-
-#include "cmBase32.h"
-#include "cmCryptoHash.h"
-#include "cmMakefile.h"
-#include "cmSystemTools.h"
-
-#include <vector>
-
-cmFilePathUuid::cmFilePathUuid(cmMakefile* makefile)
-{
- initParentDirs(makefile->GetCurrentSourceDirectory(),
- makefile->GetCurrentBinaryDirectory(),
- makefile->GetHomeDirectory(),
- makefile->GetHomeOutputDirectory());
-}
-
-cmFilePathUuid::cmFilePathUuid(const std::string& currentSrcDir,
- const std::string& currentBinDir,
- const std::string& projectSrcDir,
- const std::string& projectBinDir)
-{
- initParentDirs(currentSrcDir, currentBinDir, projectSrcDir, projectBinDir);
-}
-
-void cmFilePathUuid::initParentDirs(const std::string& currentSrcDir,
- const std::string& currentBinDir,
- const std::string& projectSrcDir,
- const std::string& projectBinDir)
-{
- parentDirs[0].first = cmsys::SystemTools::GetRealPath(currentSrcDir);
- parentDirs[1].first = cmsys::SystemTools::GetRealPath(currentBinDir);
- parentDirs[2].first = cmsys::SystemTools::GetRealPath(projectSrcDir);
- parentDirs[3].first = cmsys::SystemTools::GetRealPath(projectBinDir);
-
- parentDirs[0].second = "CurrentSource";
- parentDirs[1].second = "CurrentBinary";
- parentDirs[2].second = "ProjectSource";
- parentDirs[3].second = "ProjectBinary";
-}
-
-std::string cmFilePathUuid::get(const std::string& filePath,
- const char* outputPrefix,
- const char* outputSuffix)
-{
- std::string sourceFilename = cmsys::SystemTools::GetFilenameName(filePath);
- std::string sourceBasename =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(sourceFilename);
-
- // Acquire checksum string
- std::string checksum;
- {
- std::string sourceRelPath;
- std::string sourceRelSeed;
- GetRelPathSeed(filePath, sourceRelPath, sourceRelSeed);
- checksum = GetChecksumString(sourceFilename, sourceRelPath, sourceRelSeed);
- }
-
- // Compose the file name
- std::string uuid;
- if (outputPrefix) {
- uuid += outputPrefix;
- }
- uuid += sourceBasename.substr(0, partLengthName);
- uuid += "_";
- uuid += checksum.substr(0, partLengthCheckSum);
- if (outputSuffix) {
- uuid += outputSuffix;
- }
- return uuid;
-}
-
-void cmFilePathUuid::GetRelPathSeed(const std::string& filePath,
- std::string& sourceRelPath,
- std::string& sourceRelSeed)
-{
- const std::string sourceNameReal = cmsys::SystemTools::GetRealPath(filePath);
- std::string parentDirectory;
- // Find closest project parent directory
- for (size_t ii = 0; ii != numParentDirs; ++ii) {
- const std::string& pDir = parentDirs[ii].first;
- if (!pDir.empty() &&
- cmsys::SystemTools::IsSubDirectory(sourceNameReal, pDir)) {
- sourceRelSeed = parentDirs[ii].second;
- parentDirectory = pDir;
- break;
- }
- }
- // Check if the file path is below a known project directory
- if (parentDirectory.empty()) {
- // Use file syste root as fallback parent directory
- sourceRelSeed = "FileSystemRoot";
- cmsys::SystemTools::SplitPathRootComponent(sourceNameReal,
- &parentDirectory);
- }
- sourceRelPath = cmsys::SystemTools::RelativePath(
- parentDirectory, cmsys::SystemTools::GetParentDirectory(sourceNameReal));
-}
-
-std::string cmFilePathUuid::GetChecksumString(
- const std::string& sourceFilename, const std::string& sourceRelPath,
- const std::string& sourceRelSeed)
-{
- std::string checksumBase32;
- {
- // Calculate the file ( seed + relative path + name ) checksum
- std::vector<unsigned char> hashBytes =
- cmCryptoHash(cmCryptoHash::AlgoSHA256)
- .ByteHashString(sourceRelSeed + sourceRelPath + sourceFilename);
-
- checksumBase32 =
- cmBase32Encoder().encodeString(&hashBytes[0], hashBytes.size(), false);
- }
-
- return checksumBase32;
-}
diff --git a/Source/cmFilePathUuid.h b/Source/cmFilePathUuid.h
deleted file mode 100644
index a450526..0000000
--- a/Source/cmFilePathUuid.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmFilePathUuid_h
-#define cmFilePathUuid_h
-
-#include <cmConfigure.h> // IWYU pragma: keep
-
-#include <stddef.h>
-#include <string>
-#include <utility>
-
-class cmMakefile;
-
-/** \class cmFilePathUuid
- * @brief Generates a unique pathless file name with a checksum component
- * calculated from the file path.
- *
- * The checksum is calculated from the relative file path to the
- * closest known project directory. This guarantees reproducibility
- * when source and build directory differ e.g. for different project
- * build directories.
- */
-class cmFilePathUuid
-{
-public:
- /// Maximum number of characters to use from the file name
- static const size_t partLengthName = 14;
- /// Maximum number of characters to use from the path checksum
- static const size_t partLengthCheckSum = 14;
-
- /// @brief Initilizes the parent directories from a makefile
- cmFilePathUuid(cmMakefile* makefile);
-
- /// @brief Initilizes the parent directories manually
- cmFilePathUuid(const std::string& currentSrcDir,
- const std::string& currentBinDir,
- const std::string& projectSrcDir,
- const std::string& projectBinDir);
-
- /* @brief Calculates and returns the uuid for a file path
- *
- * @arg outputPrefix optional string to prepend to the result
- * @arg outputSuffix optional string to append to the result
- */
- std::string get(const std::string& filePath,
- const char* outputPrefix = CM_NULLPTR,
- const char* outputSuffix = CM_NULLPTR);
-
-private:
- void initParentDirs(const std::string& currentSrcDir,
- const std::string& currentBinDir,
- const std::string& projectSrcDir,
- const std::string& projectBinDir);
-
- /// Returns the relative path and the parent directory key string (seed)
- void GetRelPathSeed(const std::string& filePath, std::string& sourceRelPath,
- std::string& sourceRelSeed);
-
- std::string GetChecksumString(const std::string& sourceFilename,
- const std::string& sourceRelPath,
- const std::string& sourceRelSeed);
-
- /// Size of the parent directory list
- static const size_t numParentDirs = 4;
- /// List of (directory name, seed name) pairs
- std::pair<std::string, std::string> parentDirs[numParentDirs];
-};
-
-#endif
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 903bcec..6ee2c14 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -533,6 +533,21 @@ void cmGeneratorTarget::AddTracedSources(std::vector<std::string> const& srcs)
}
}
+void cmGeneratorTarget::AddIncludeDirectory(const std::string& src,
+ bool before)
+{
+ this->Target->InsertInclude(src, this->Makefile->GetBacktrace(), before);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ cmGeneratorExpression ge(lfbt);
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(src);
+ cge->SetEvaluateForBuildsystem(true);
+ // Insert before begin/end
+ std::vector<TargetPropertyEntry*>::iterator pos = before
+ ? this->IncludeDirectoriesEntries.begin()
+ : this->IncludeDirectoriesEntries.end();
+ this->IncludeDirectoriesEntries.insert(pos, new TargetPropertyEntry(cge));
+}
+
std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends(
cmSourceFile const* sf) const
{
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 4c3c14b..f568699 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -396,6 +396,12 @@ public:
void AddTracedSources(std::vector<std::string> const& srcs);
/**
+ * Adds an entry to the INCLUDE_DIRECTORIES list.
+ * If before is true the entry is pushed at the front.
+ */
+ void AddIncludeDirectory(const std::string& src, bool before = false);
+
+ /**
* Flags for a given source file as used in this target. Typically assigned
* via SET_TARGET_PROPERTIES when the property is a list of source files.
*/
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 46e49dc..ead1e72 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1470,6 +1470,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("17");
langStdMap["CXX"].push_back("14");
langStdMap["CXX"].push_back("11");
langStdMap["CXX"].push_back("98");
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index a42c8c9..f52fe26 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -4068,7 +4068,7 @@ static const char* const CXX_FEATURES[] = { CM_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" };
+static const char* const CXX_STANDARDS[] = { "98", "11", "14", "17" };
bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
const std::string& feature,
@@ -4301,7 +4301,9 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
bool needCxx98 = false;
bool needCxx11 = false;
bool needCxx14 = false;
- this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14);
+ bool needCxx17 = false;
+ this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14,
+ needCxx17);
const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
if (!existingCxxStandard) {
@@ -4340,7 +4342,7 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
void cmMakefile::CheckNeededCxxLanguage(const std::string& feature,
bool& needCxx98, bool& needCxx11,
- bool& needCxx14) const
+ bool& needCxx14, bool& needCxx17) const
{
if (const char* propCxx98 =
this->GetDefinition("CMAKE_CXX98_COMPILE_FEATURES")) {
@@ -4360,6 +4362,12 @@ void cmMakefile::CheckNeededCxxLanguage(const std::string& feature,
cmSystemTools::ExpandListArgument(propCxx14, props);
needCxx14 = std::find(props.begin(), props.end(), feature) != props.end();
}
+ if (const char* propCxx17 =
+ this->GetDefinition("CMAKE_CXX17_COMPILE_FEATURES")) {
+ std::vector<std::string> props;
+ cmSystemTools::ExpandListArgument(propCxx17, props);
+ needCxx17 = std::find(props.begin(), props.end(), feature) != props.end();
+ }
}
bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
@@ -4369,8 +4377,10 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
bool needCxx98 = false;
bool needCxx11 = false;
bool needCxx14 = false;
+ bool needCxx17 = false;
- this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14);
+ this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14,
+ needCxx17);
const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
if (existingCxxStandard) {
@@ -4397,11 +4407,17 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
bool setCxx98 = needCxx98 && !existingCxxStandard;
bool setCxx11 = needCxx11 && !existingCxxStandard;
bool setCxx14 = needCxx14 && !existingCxxStandard;
+ bool setCxx17 = needCxx17 && !existingCxxStandard;
- if (needCxx14 && existingCxxStandard &&
+ if (needCxx17 && existingCxxStandard &&
existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
cmArrayEnd(CXX_STANDARDS),
- cmStrCmp("14"))) {
+ cmStrCmp("17"))) {
+ setCxx17 = true;
+ } else if (needCxx14 && existingCxxStandard &&
+ existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
+ cmArrayEnd(CXX_STANDARDS),
+ cmStrCmp("14"))) {
setCxx14 = true;
} else if (needCxx11 && existingCxxStandard &&
existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
@@ -4415,7 +4431,10 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
setCxx98 = true;
}
- if (setCxx14) {
+ if (setCxx17) {
+ target->SetProperty("CXX_STANDARD", "17");
+ target->SetProperty("CUDA_STANDARD", "17");
+ } else if (setCxx14) {
target->SetProperty("CXX_STANDARD", "14");
target->SetProperty("CUDA_STANDARD", "14");
} else if (setCxx11) {
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 859b3c8..3484e5a 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -905,7 +905,8 @@ private:
void CheckNeededCLanguage(const std::string& feature, bool& needC90,
bool& needC99, bool& needC11) const;
void CheckNeededCxxLanguage(const std::string& feature, bool& needCxx98,
- bool& needCxx11, bool& needCxx14) const;
+ bool& needCxx11, bool& needCxx14,
+ bool& needCxx17) const;
bool HaveCStandardAvailable(cmTarget const* target,
const std::string& feature) const;
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index 8afd532..f0847b1 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -4,7 +4,7 @@
#include "cmAlgorithms.h"
#include "cmCustomCommandLines.h"
-#include "cmFilePathUuid.h"
+#include "cmFilePathChecksum.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
@@ -35,14 +35,34 @@
#include <utility>
#include <vector>
+static void utilCopyTargetProperty(cmTarget* destinationTarget,
+ cmTarget* sourceTarget,
+ const std::string& propertyName)
+{
+ const char* propertyValue = sourceTarget->GetProperty(propertyName);
+ if (propertyValue) {
+ destinationTarget->SetProperty(propertyName, propertyValue);
+ }
+}
+
+static std::string utilStripCR(std::string const& line)
+{
+ // Strip CR characters rcc may have printed (possibly more than one!).
+ std::string::size_type cr = line.find('\r');
+ if (cr != line.npos) {
+ return line.substr(0, cr);
+ }
+ return line;
+}
+
static std::string GetAutogenTargetName(cmGeneratorTarget const* target)
{
std::string autogenTargetName = target->GetName();
- autogenTargetName += "_automoc";
+ autogenTargetName += "_autogen";
return autogenTargetName;
}
-static std::string GetAutogenTargetDir(cmGeneratorTarget const* target)
+static std::string GetAutogenTargetFilesDir(cmGeneratorTarget const* target)
{
cmMakefile* makefile = target->Target->GetMakefile();
std::string targetDir = makefile->GetCurrentBinaryDirectory();
@@ -59,10 +79,25 @@ static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target)
std::string targetDir = makefile->GetCurrentBinaryDirectory();
targetDir += "/";
targetDir += GetAutogenTargetName(target);
- targetDir += ".dir/";
+ targetDir += "/";
return targetDir;
}
+static std::string GetQtMajorVersion(cmGeneratorTarget const* target)
+{
+ cmMakefile* makefile = target->Target->GetMakefile();
+ std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
+ if (qtMajorVersion.empty()) {
+ qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
+ }
+ const char* targetQtVersion =
+ target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");
+ if (targetQtVersion != CM_NULLPTR) {
+ qtMajorVersion = targetQtVersion;
+ }
+ return qtMajorVersion;
+}
+
static void SetupSourceFiles(cmGeneratorTarget const* target,
std::vector<std::string>& skipMoc,
std::vector<std::string>& mocSources,
@@ -74,41 +109,20 @@ static void SetupSourceFiles(cmGeneratorTarget const* target,
std::vector<cmSourceFile*> srcFiles;
target->GetConfigCommonSourceFiles(srcFiles);
- std::vector<std::string> newRccFiles;
-
- cmFilePathUuid fpathUuid(makefile);
+ cmFilePathChecksum fpathCheckSum(makefile);
for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
fileIt != srcFiles.end(); ++fileIt) {
cmSourceFile* sf = *fileIt;
- std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath());
- bool skipFileForMoc =
- cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC"));
- bool generated = cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"));
+ const std::string absFile =
+ cmsys::SystemTools::GetRealPath(sf->GetFullPath());
+ const std::string ext = sf->GetExtension();
if (cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC"))) {
skipUic.push_back(absFile);
}
- std::string ext = sf->GetExtension();
-
- if (target->GetPropertyAsBool("AUTORCC")) {
- if (ext == "qrc" &&
- !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) {
-
- std::string rcc_output_file = GetAutogenTargetBuildDir(target);
- // Create output directory
- cmSystemTools::MakeDirectory(rcc_output_file.c_str());
- rcc_output_file += fpathUuid.get(absFile, "qrc_", ".cpp");
-
- makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
- rcc_output_file.c_str(), false);
- makefile->GetOrCreateSource(rcc_output_file, true);
- newRccFiles.push_back(rcc_output_file);
- }
- }
-
- if (!generated) {
- if (skipFileForMoc) {
+ if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
+ if (cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC"))) {
skipMoc.push_back(absFile);
} else {
cmSystemTools::FileFormat fileType =
@@ -121,11 +135,6 @@ static void SetupSourceFiles(cmGeneratorTarget const* target,
}
}
}
-
- for (std::vector<std::string>::const_iterator fileIt = newRccFiles.begin();
- fileIt != newRccFiles.end(); ++fileIt) {
- const_cast<cmGeneratorTarget*>(target)->AddSource(*fileIt);
- }
}
static void GetCompileDefinitionsAndDirectories(
@@ -146,7 +155,7 @@ static void GetCompileDefinitionsAndDirectories(
defs += cmJoin(defines, ";");
}
-static void SetupAutoMocTarget(
+static void MocSetupAutoTarget(
cmGeneratorTarget const* target, const std::string& autogenTargetName,
std::vector<std::string> const& skipMoc,
std::vector<std::string> const& mocHeaders,
@@ -229,7 +238,7 @@ static void SetupAutoMocTarget(
}
}
-static void GetUicOpts(cmGeneratorTarget const* target,
+static void UicGetOpts(cmGeneratorTarget const* target,
const std::string& config, std::string& optString)
{
std::vector<std::string> opts;
@@ -237,7 +246,7 @@ static void GetUicOpts(cmGeneratorTarget const* target,
optString = cmJoin(opts, ";");
}
-static void SetupAutoUicTarget(
+static void UicSetupAutoTarget(
cmGeneratorTarget const* target, std::vector<std::string> const& skipUic,
std::map<std::string, std::string>& configUicOptions)
{
@@ -259,7 +268,7 @@ static void SetupAutoUicTarget(
std::string _uic_opts;
std::vector<std::string> configs;
const std::string& config = makefile->GetConfigurations(configs);
- GetUicOpts(target, config, _uic_opts);
+ UicGetOpts(target, config, _uic_opts);
if (!_uic_opts.empty()) {
_uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts);
@@ -268,7 +277,7 @@ static void SetupAutoUicTarget(
for (std::vector<std::string>::const_iterator li = configs.begin();
li != configs.end(); ++li) {
std::string config_uic_opts;
- GetUicOpts(target, *li, config_uic_opts);
+ UicGetOpts(target, *li, config_uic_opts);
if (config_uic_opts != _uic_opts) {
configUicOptions[*li] =
cmOutputConverter::EscapeForCMake(config_uic_opts);
@@ -331,25 +340,13 @@ static void SetupAutoUicTarget(
}
}
-static std::string GetRccExecutable(cmGeneratorTarget const* target)
+static std::string RccGetExecutable(cmGeneratorTarget const* target,
+ const std::string& qtMajorVersion)
{
cmLocalGenerator* lg = target->GetLocalGenerator();
- cmMakefile* makefile = target->Target->GetMakefile();
- const char* qtVersion = makefile->GetDefinition("_target_qt_version");
- if (!qtVersion) {
- qtVersion = makefile->GetDefinition("Qt5Core_VERSION_MAJOR");
- if (!qtVersion) {
- qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR");
- }
- if (const char* targetQtVersion =
- target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION",
- "")) {
- qtVersion = targetQtVersion;
- }
- }
- std::string targetName = target->GetName();
- if (strcmp(qtVersion, "5") == 0) {
+ std::string const& targetName = target->GetName();
+ if (qtMajorVersion == "5") {
cmGeneratorTarget* qt5Rcc = lg->FindGeneratorTargetToUse("Qt5::rcc");
if (!qt5Rcc) {
cmSystemTools::Error("Qt5::rcc target not found ", targetName.c_str());
@@ -357,7 +354,7 @@ static std::string GetRccExecutable(cmGeneratorTarget const* target)
}
return qt5Rcc->ImportedGetLocation("");
}
- if (strcmp(qtVersion, "4") == 0) {
+ if (qtMajorVersion == "4") {
cmGeneratorTarget* qt4Rcc = lg->FindGeneratorTargetToUse("Qt4::rcc");
if (!qt4Rcc) {
cmSystemTools::Error("Qt4::rcc target not found ", targetName.c_str());
@@ -372,7 +369,7 @@ static std::string GetRccExecutable(cmGeneratorTarget const* target)
return std::string();
}
-static void MergeRccOptions(std::vector<std::string>& opts,
+static void RccMergeOptions(std::vector<std::string>& opts,
const std::vector<std::string>& fileOpts,
bool isQt5)
{
@@ -404,41 +401,16 @@ static void MergeRccOptions(std::vector<std::string>& opts,
opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
}
-static void copyTargetProperty(cmTarget* destinationTarget,
- cmTarget* sourceTarget,
- const std::string& propertyName)
-{
- const char* propertyValue = sourceTarget->GetProperty(propertyName);
- if (propertyValue) {
- destinationTarget->SetProperty(propertyName, propertyValue);
- }
-}
-
-static std::string cmQtAutoGeneratorsStripCR(std::string const& line)
-{
- // Strip CR characters rcc may have printed (possibly more than one!).
- std::string::size_type cr = line.find('\r');
- if (cr != line.npos) {
- return line.substr(0, cr);
- }
- return line;
-}
-
-static std::string ReadAll(const std::string& filename)
-{
- cmsys::ifstream file(filename.c_str());
- std::ostringstream stream;
- stream << file.rdbuf();
- file.close();
- return stream.str();
-}
-
/// @brief Reads the resource files list from from a .qrc file - Qt5 version
/// @return True if the .qrc file was successfully parsed
-static bool ListQt5RccInputs(cmSourceFile* sf, cmGeneratorTarget const* target,
+static bool RccListInputsQt5(cmSourceFile* sf, cmGeneratorTarget const* target,
std::vector<std::string>& depends)
{
- std::string rccCommand = GetRccExecutable(target);
+ const std::string rccCommand = RccGetExecutable(target, "5");
+ if (rccCommand.empty()) {
+ cmSystemTools::Error("AUTOGEN: error: rcc executable not available\n");
+ return false;
+ }
bool hasDashDashList = false;
// Read rcc features
@@ -486,7 +458,7 @@ static bool ListQt5RccInputs(cmSourceFile* sf, cmGeneratorTarget const* target,
std::istringstream ostr(rccStdOut);
std::string oline;
while (std::getline(ostr, oline)) {
- oline = cmQtAutoGeneratorsStripCR(oline);
+ oline = utilStripCR(oline);
if (!oline.empty()) {
depends.push_back(oline);
}
@@ -497,7 +469,7 @@ static bool ListQt5RccInputs(cmSourceFile* sf, cmGeneratorTarget const* target,
std::istringstream estr(rccStdErr);
std::string eline;
while (std::getline(estr, eline)) {
- eline = cmQtAutoGeneratorsStripCR(eline);
+ eline = utilStripCR(eline);
if (cmHasLiteralPrefix(eline, "RCC: Error in")) {
static std::string searchString = "Cannot find file '";
@@ -521,10 +493,16 @@ static bool ListQt5RccInputs(cmSourceFile* sf, cmGeneratorTarget const* target,
/// @brief Reads the resource files list from from a .qrc file - Qt4 version
/// @return True if the .qrc file was successfully parsed
-static bool ListQt4RccInputs(cmSourceFile* sf,
+static bool RccListInputsQt4(cmSourceFile* sf,
std::vector<std::string>& depends)
{
- const std::string qrcContents = ReadAll(sf->GetFullPath());
+ // Read file into string
+ std::string qrcContents;
+ {
+ std::ostringstream stream;
+ stream << cmsys::ifstream(sf->GetFullPath().c_str()).rdbuf();
+ qrcContents = stream.str();
+ }
cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
@@ -551,17 +529,18 @@ static bool ListQt4RccInputs(cmSourceFile* sf,
/// @brief Reads the resource files list from from a .qrc file
/// @return True if the rcc file was successfully parsed
-static bool ListQtRccInputs(const std::string& qtMajorVersion,
- cmSourceFile* sf, cmGeneratorTarget const* target,
- std::vector<std::string>& depends)
+static bool RccListInputs(const std::string& qtMajorVersion, cmSourceFile* sf,
+ cmGeneratorTarget const* target,
+ std::vector<std::string>& depends)
{
if (qtMajorVersion == "5") {
- return ListQt5RccInputs(sf, target, depends);
+ return RccListInputsQt5(sf, target, depends);
}
- return ListQt4RccInputs(sf, depends);
+ return RccListInputsQt4(sf, depends);
}
-static void SetupAutoRccTarget(cmGeneratorTarget const* target)
+static void RccSetupAutoTarget(cmGeneratorTarget const* target,
+ const std::string& qtMajorVersion)
{
std::string _rcc_files;
const char* sepRccFiles = "";
@@ -577,16 +556,12 @@ static void SetupAutoRccTarget(cmGeneratorTarget const* target)
std::string rccFileOptions;
const char* optionSep = "";
- const char* qtVersion = makefile->GetDefinition("_target_qt_version");
+ const bool qtMajorVersion5 = (qtMajorVersion == "5");
std::vector<std::string> rccOptions;
if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) {
cmSystemTools::ExpandListArgument(opts, rccOptions);
}
- std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
- if (qtMajorVersion == "") {
- qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
- }
for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
fileIt != srcFiles.end(); ++fileIt) {
@@ -604,7 +579,7 @@ static void SetupAutoRccTarget(cmGeneratorTarget const* target)
if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) {
std::vector<std::string> optsVec;
cmSystemTools::ExpandListArgument(prop, optsVec);
- MergeRccOptions(rccOptions, optsVec, strcmp(qtVersion, "5") == 0);
+ RccMergeOptions(rccOptions, optsVec, qtMajorVersion5);
}
if (!rccOptions.empty()) {
@@ -624,7 +599,7 @@ static void SetupAutoRccTarget(cmGeneratorTarget const* target)
std::string entriesList;
if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
std::vector<std::string> depends;
- if (ListQtRccInputs(qtMajorVersion, sf, target, depends)) {
+ if (RccListInputs(qtMajorVersion, sf, target, depends)) {
entriesList = cmJoin(depends, "@list_sep@");
} else {
return;
@@ -637,38 +612,27 @@ static void SetupAutoRccTarget(cmGeneratorTarget const* target)
}
}
makefile->AddDefinition(
- "_qt_rcc_inputs_" + target->GetName(),
- cmOutputConverter::EscapeForCMake(qrcInputs).c_str());
-
+ "_rcc_inputs", cmOutputConverter::EscapeForCMake(qrcInputs).c_str());
makefile->AddDefinition(
"_rcc_files", cmOutputConverter::EscapeForCMake(_rcc_files).c_str());
-
makefile->AddDefinition(
- "_qt_rcc_options_files",
+ "_rcc_options_files",
cmOutputConverter::EscapeForCMake(rccFileFiles).c_str());
makefile->AddDefinition(
- "_qt_rcc_options_options",
+ "_rcc_options_options",
cmOutputConverter::EscapeForCMake(rccFileOptions).c_str());
-
makefile->AddDefinition("_qt_rcc_executable",
- GetRccExecutable(target).c_str());
+ RccGetExecutable(target, qtMajorVersion).c_str());
}
void cmQtAutoGeneratorInitializer::InitializeAutogenSources(
cmGeneratorTarget* target)
{
- cmMakefile* makefile = target->Target->GetMakefile();
-
if (target->GetPropertyAsBool("AUTOMOC")) {
- std::string automocTargetName = GetAutogenTargetName(target);
- std::string mocCppFile = makefile->GetCurrentBinaryDirectory();
- mocCppFile += "/";
- mocCppFile += automocTargetName;
- mocCppFile += ".cpp";
+ cmMakefile* makefile = target->Target->GetMakefile();
+ const std::string mocCppFile =
+ GetAutogenTargetBuildDir(target) + "moc_compilation.cpp";
makefile->GetOrCreateSource(mocCppFile, true);
- makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", mocCppFile.c_str(),
- false);
-
target->AddSource(mocCppFile);
}
}
@@ -678,56 +642,77 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
{
cmMakefile* makefile = target->Target->GetMakefile();
- std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
- if (qtMajorVersion == "") {
- qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
- }
-
- // create a custom target for running generators at buildtime:
- std::string autogenTargetName = GetAutogenTargetName(target);
-
- std::string targetDir = GetAutogenTargetDir(target);
+ // Create a custom target for running generators at buildtime
+ const std::string autogenTargetName = GetAutogenTargetName(target);
+ const std::string autogenBuildDir = GetAutogenTargetBuildDir(target);
+ const std::string workingDirectory =
+ cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());
+ const std::string qtMajorVersion = GetQtMajorVersion(target);
+ std::vector<std::string> autogenOutputFiles;
- cmCustomCommandLine currentLine;
- currentLine.push_back(cmSystemTools::GetCMakeCommand());
- currentLine.push_back("-E");
- currentLine.push_back("cmake_autogen");
- currentLine.push_back(targetDir);
- currentLine.push_back("$<CONFIGURATION>");
+ // Create autogen target build directory and add it to the clean files
+ cmSystemTools::MakeDirectory(autogenBuildDir);
+ makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
+ autogenBuildDir.c_str(), false);
- cmCustomCommandLines commandLines;
- commandLines.push_back(currentLine);
+ if (target->GetPropertyAsBool("AUTOMOC") ||
+ target->GetPropertyAsBool("AUTOUIC")) {
+ // Create autogen target includes directory and
+ // add it to the origin target INCLUDE_DIRECTORIES
+ const std::string incsDir = autogenBuildDir + "include";
+ cmSystemTools::MakeDirectory(incsDir);
+ target->AddIncludeDirectory(incsDir, true);
+ }
- std::string workingDirectory =
- cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());
+ if (target->GetPropertyAsBool("AUTOMOC")) {
+ // Register moc compilation file as generated
+ autogenOutputFiles.push_back(autogenBuildDir + "moc_compilation.cpp");
+ }
+ // Initialize autogen target dependencies
std::vector<std::string> depends;
if (const char* autogenDepends =
target->GetProperty("AUTOGEN_TARGET_DEPENDS")) {
cmSystemTools::ExpandListArgument(autogenDepends, depends);
}
- std::vector<std::string> toolNames;
- if (target->GetPropertyAsBool("AUTOMOC")) {
- toolNames.push_back("moc");
- }
- if (target->GetPropertyAsBool("AUTOUIC")) {
- toolNames.push_back("uic");
- }
- if (target->GetPropertyAsBool("AUTORCC")) {
- toolNames.push_back("rcc");
+
+ // Compose command lines
+ cmCustomCommandLines commandLines;
+ {
+ cmCustomCommandLine currentLine;
+ currentLine.push_back(cmSystemTools::GetCMakeCommand());
+ currentLine.push_back("-E");
+ currentLine.push_back("cmake_autogen");
+ currentLine.push_back(GetAutogenTargetFilesDir(target));
+ currentLine.push_back("$<CONFIGURATION>");
+ commandLines.push_back(currentLine);
}
- std::string tools = toolNames[0];
- toolNames.erase(toolNames.begin());
- while (toolNames.size() > 1) {
- tools += ", " + toolNames[0];
+ // Compose target comment
+ std::string autogenComment;
+ {
+ std::vector<std::string> toolNames;
+ if (target->GetPropertyAsBool("AUTOMOC")) {
+ toolNames.push_back("MOC");
+ }
+ if (target->GetPropertyAsBool("AUTOUIC")) {
+ toolNames.push_back("UIC");
+ }
+ if (target->GetPropertyAsBool("AUTORCC")) {
+ toolNames.push_back("RCC");
+ }
+
+ std::string tools = toolNames[0];
toolNames.erase(toolNames.begin());
+ while (toolNames.size() > 1) {
+ tools += ", " + toolNames[0];
+ toolNames.erase(toolNames.begin());
+ }
+ if (toolNames.size() == 1) {
+ tools += " and " + toolNames[0];
+ }
+ autogenComment = "Automatic " + tools + " for target " + target->GetName();
}
- if (toolNames.size() == 1) {
- tools += " and " + toolNames[0];
- }
- std::string autogenComment = "Automatic " + tools + " for target ";
- autogenComment += target->GetName();
#if defined(_WIN32) && !defined(__CYGWIN__)
bool usePRE_BUILD = false;
@@ -741,6 +726,8 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
// https://connect.microsoft.com/VisualStudio/feedback/details/769495
usePRE_BUILD = vsgg->GetVersion() >= cmGlobalVisualStudioGenerator::VS7;
if (usePRE_BUILD) {
+ // If the autogen target depends on an other target
+ // don't use PRE_BUILD
for (std::vector<std::string>::iterator it = depends.begin();
it != depends.end(); ++it) {
if (!makefile->FindTargetToUse(it->c_str())) {
@@ -752,35 +739,42 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
}
#endif
- std::vector<std::string> rcc_output;
- bool const isNinja = lg->GetGlobalGenerator()->GetName() == "Ninja";
- if (isNinja
-#if defined(_WIN32) && !defined(__CYGWIN__)
- || usePRE_BUILD
-#endif
- ) {
+ if (target->GetPropertyAsBool("AUTORCC")) {
+ cmFilePathChecksum fpathCheckSum(makefile);
std::vector<cmSourceFile*> srcFiles;
target->GetConfigCommonSourceFiles(srcFiles);
- cmFilePathUuid fpathUuid(makefile);
for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
fileIt != srcFiles.end(); ++fileIt) {
cmSourceFile* sf = *fileIt;
- std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath());
-
- std::string ext = sf->GetExtension();
-
- if (target->GetPropertyAsBool("AUTORCC")) {
- if (ext == "qrc" &&
- !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) {
- {
- std::string rcc_output_file = GetAutogenTargetBuildDir(target);
- // Create output directory
- cmSystemTools::MakeDirectory(rcc_output_file.c_str());
- rcc_output_file += fpathUuid.get(absFile, "qrc_", ".cpp");
- rcc_output.push_back(rcc_output_file);
- }
+ if (sf->GetExtension() == "qrc" &&
+ !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) {
+ {
+ const std::string absFile =
+ cmsys::SystemTools::GetRealPath(sf->GetFullPath());
+
+ // Run cmake again when .qrc file changes
+ makefile->AddCMakeDependFile(absFile);
+
+ std::string rccOutputFile = autogenBuildDir;
+ rccOutputFile += fpathCheckSum.getPart(absFile);
+ rccOutputFile += "/qrc_";
+ rccOutputFile +=
+ cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile);
+ rccOutputFile += ".cpp";
+
+ // Add rcc output file to origin target sources
+ makefile->GetOrCreateSource(rccOutputFile, true);
+ target->AddSource(rccOutputFile);
+ // Register rcc output file as generated
+ autogenOutputFiles.push_back(rccOutputFile);
+ }
+ if (lg->GetGlobalGenerator()->GetName() == "Ninja"
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ || usePRE_BUILD
+#endif
+ ) {
if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
- ListQtRccInputs(qtMajorVersion, sf, target, depends);
+ RccListInputs(qtMajorVersion, sf, target, depends);
#if defined(_WIN32) && !defined(__CYGWIN__)
// Cannot use PRE_BUILD because the resource files themselves
// may not be sources within the target so VS may not know the
@@ -811,7 +805,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
{
cmTarget* autogenTarget = makefile->AddUtilityCommand(
autogenTargetName, true, workingDirectory.c_str(),
- /*byproducts=*/rcc_output, depends, commandLines, false,
+ /*byproducts=*/autogenOutputFiles, depends, commandLines, false,
autogenComment.c_str());
cmGeneratorTarget* gt = new cmGeneratorTarget(autogenTarget, lg);
@@ -828,7 +822,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
autogenTarget->SetProperty("FOLDER", autogenFolder);
} else {
// inherit FOLDER property from target (#13688)
- copyTargetProperty(gt->Target, target->Target, "FOLDER");
+ utilCopyTargetProperty(gt->Target, target->Target, "FOLDER");
}
target->Target->AddUtility(autogenTargetName);
@@ -845,7 +839,8 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
static_cast<void>(varScope);
// create a custom target for running generators at buildtime:
- std::string autogenTargetName = GetAutogenTargetName(target);
+ const std::string autogenTargetName = GetAutogenTargetName(target);
+ const std::string qtMajorVersion = GetQtMajorVersion(target);
makefile->AddDefinition(
"_moc_target_name",
@@ -853,28 +848,14 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
makefile->AddDefinition(
"_origin_target_name",
cmOutputConverter::EscapeForCMake(target->GetName()).c_str());
-
- std::string targetDir = GetAutogenTargetDir(target);
-
- const char* qtVersion = makefile->GetDefinition("Qt5Core_VERSION_MAJOR");
- if (!qtVersion) {
- qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR");
- }
- if (const char* targetQtVersion =
- target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION",
- "")) {
- qtVersion = targetQtVersion;
- }
- if (qtVersion) {
- makefile->AddDefinition("_target_qt_version", qtVersion);
- }
+ makefile->AddDefinition("_target_qt_version", qtMajorVersion.c_str());
std::vector<std::string> skipUic;
std::vector<std::string> skipMoc;
std::vector<std::string> mocSources;
std::vector<std::string> mocHeaders;
- std::map<std::string, std::string> configIncludes;
- std::map<std::string, std::string> configDefines;
+ std::map<std::string, std::string> configMocIncludes;
+ std::map<std::string, std::string> configMocDefines;
std::map<std::string, std::string> configUicOptions;
if (target->GetPropertyAsBool("AUTOMOC") ||
@@ -886,39 +867,41 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
"_cpp_files",
cmOutputConverter::EscapeForCMake(cmJoin(mocSources, ";")).c_str());
if (target->GetPropertyAsBool("AUTOMOC")) {
- SetupAutoMocTarget(target, autogenTargetName, skipMoc, mocHeaders,
- configIncludes, configDefines);
+ MocSetupAutoTarget(target, autogenTargetName, skipMoc, mocHeaders,
+ configMocIncludes, configMocDefines);
}
if (target->GetPropertyAsBool("AUTOUIC")) {
- SetupAutoUicTarget(target, skipUic, configUicOptions);
+ UicSetupAutoTarget(target, skipUic, configUicOptions);
}
if (target->GetPropertyAsBool("AUTORCC")) {
- SetupAutoRccTarget(target);
+ RccSetupAutoTarget(target, qtMajorVersion);
}
+ // Generate config file
std::string inputFile = cmSystemTools::GetCMakeRoot();
inputFile += "/Modules/AutogenInfo.cmake.in";
- std::string outputFile = targetDir;
+ std::string outputFile = GetAutogenTargetFilesDir(target);
outputFile += "/AutogenInfo.cmake";
- makefile->AddDefinition(
- "_qt_rcc_inputs",
- makefile->GetDefinition("_qt_rcc_inputs_" + target->GetName()));
+
makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), false, true,
false);
- // Ensure we have write permission in case .in was read-only.
- mode_t perm = 0;
+ // Append custom definitions to config file
+ if (!configMocDefines.empty() || !configMocIncludes.empty() ||
+ !configUicOptions.empty()) {
+
+ // Ensure we have write permission in case .in was read-only.
+ mode_t perm = 0;
#if defined(_WIN32) && !defined(__CYGWIN__)
- mode_t mode_write = S_IWRITE;
+ mode_t mode_write = S_IWRITE;
#else
- mode_t mode_write = S_IWUSR;
+ mode_t mode_write = S_IWUSR;
#endif
- cmSystemTools::GetPermissions(outputFile, perm);
- if (!(perm & mode_write)) {
- cmSystemTools::SetPermissions(outputFile, perm | mode_write);
- }
- if (!configDefines.empty() || !configIncludes.empty() ||
- !configUicOptions.empty()) {
+ cmSystemTools::GetPermissions(outputFile, perm);
+ if (!(perm & mode_write)) {
+ cmSystemTools::SetPermissions(outputFile, perm | mode_write);
+ }
+
cmsys::ofstream infoFile(outputFile.c_str(), std::ios::app);
if (!infoFile) {
std::string error = "Internal CMake error when trying to open file: ";
@@ -927,19 +910,19 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
cmSystemTools::Error(error.c_str());
return;
}
- if (!configDefines.empty()) {
+ if (!configMocDefines.empty()) {
for (std::map<std::string, std::string>::iterator
- it = configDefines.begin(),
- end = configDefines.end();
+ it = configMocDefines.begin(),
+ end = configMocDefines.end();
it != end; ++it) {
infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " "
<< it->second << ")\n";
}
}
- if (!configIncludes.empty()) {
+ if (!configMocIncludes.empty()) {
for (std::map<std::string, std::string>::iterator
- it = configIncludes.begin(),
- end = configIncludes.end();
+ it = configMocIncludes.begin(),
+ end = configMocIncludes.end();
it != end; ++it) {
infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second
<< ")\n";
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index fa33cf2..eb513e5 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -15,7 +15,6 @@
#include <utility>
#include "cmAlgorithms.h"
-#include "cmFilePathUuid.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
@@ -159,7 +158,6 @@ void cmQtAutoGenerators::MergeUicOptions(
bool cmQtAutoGenerators::Run(const std::string& targetDirectory,
const std::string& config)
{
- bool success = true;
cmake cm;
cm.SetHomeOutputDirectory(targetDirectory);
cm.SetHomeDirectory(targetDirectory);
@@ -173,18 +171,18 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory,
CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(&gg, snapshot));
gg.SetCurrentMakefile(mf.get());
- this->ReadAutogenInfoFile(mf.get(), targetDirectory, config);
+ if (!this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) {
+ return false;
+ }
this->ReadOldMocDefinitionsFile(mf.get(), targetDirectory);
-
this->Init();
if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5") {
- success = this->RunAutogen(mf.get());
+ if (!this->RunAutogen(mf.get())) {
+ return false;
+ }
}
-
- this->WriteOldMocDefinitionsFile(targetDirectory);
-
- return success;
+ return this->WriteOldMocDefinitionsFile(targetDirectory);
}
bool cmQtAutoGenerators::ReadAutogenInfoFile(
@@ -196,30 +194,41 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
filename += "/AutogenInfo.cmake";
if (!makefile->ReadListFile(filename.c_str())) {
- cmSystemTools::Error("Error processing file: ", filename.c_str());
+ std::ostringstream err;
+ err << "AUTOGEN: error processing file: " << filename << std::endl;
+ this->LogError(err.str());
return false;
}
+ // - Target names
+ this->OriginTargetName =
+ makefile->GetSafeDefinition("AM_ORIGIN_TARGET_NAME");
+ this->AutogenTargetName = makefile->GetSafeDefinition("AM_TARGET_NAME");
+
+ // - Directories
+ this->ProjectSourceDir = makefile->GetSafeDefinition("AM_CMAKE_SOURCE_DIR");
+ this->ProjectBinaryDir = makefile->GetSafeDefinition("AM_CMAKE_BINARY_DIR");
+ this->CurrentSourceDir =
+ makefile->GetSafeDefinition("AM_CMAKE_CURRENT_SOURCE_DIR");
+ this->CurrentBinaryDir =
+ makefile->GetSafeDefinition("AM_CMAKE_CURRENT_BINARY_DIR");
+
+ // - Qt environment
this->QtMajorVersion = makefile->GetSafeDefinition("AM_QT_VERSION_MAJOR");
if (this->QtMajorVersion == "") {
this->QtMajorVersion =
makefile->GetSafeDefinition("AM_Qt5Core_VERSION_MAJOR");
}
- this->Sources = makefile->GetSafeDefinition("AM_SOURCES");
- {
- std::string rccSources = makefile->GetSafeDefinition("AM_RCC_SOURCES");
- cmSystemTools::ExpandListArgument(rccSources, this->RccSources);
- }
- this->SkipMoc = makefile->GetSafeDefinition("AM_SKIP_MOC");
- this->SkipUic = makefile->GetSafeDefinition("AM_SKIP_UIC");
- this->Headers = makefile->GetSafeDefinition("AM_HEADERS");
- this->IncludeProjectDirsBefore =
- makefile->IsOn("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
- this->Srcdir = makefile->GetSafeDefinition("AM_CMAKE_CURRENT_SOURCE_DIR");
- this->Builddir = makefile->GetSafeDefinition("AM_CMAKE_CURRENT_BINARY_DIR");
this->MocExecutable = makefile->GetSafeDefinition("AM_QT_MOC_EXECUTABLE");
this->UicExecutable = makefile->GetSafeDefinition("AM_QT_UIC_EXECUTABLE");
this->RccExecutable = makefile->GetSafeDefinition("AM_QT_RCC_EXECUTABLE");
+
+ // - File Lists
+ this->Sources = makefile->GetSafeDefinition("AM_SOURCES");
+ this->Headers = makefile->GetSafeDefinition("AM_HEADERS");
+
+ // - Moc
+ this->SkipMoc = makefile->GetSafeDefinition("AM_SKIP_MOC");
{
std::string compileDefsPropOrig = "AM_MOC_COMPILE_DEFINITIONS";
std::string compileDefsProp = compileDefsPropOrig;
@@ -244,12 +253,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
includes ? includes : makefile->GetSafeDefinition(includesPropOrig);
}
this->MocOptionsStr = makefile->GetSafeDefinition("AM_MOC_OPTIONS");
- this->ProjectBinaryDir = makefile->GetSafeDefinition("AM_CMAKE_BINARY_DIR");
- this->ProjectSourceDir = makefile->GetSafeDefinition("AM_CMAKE_SOURCE_DIR");
- this->TargetName = makefile->GetSafeDefinition("AM_TARGET_NAME");
- this->OriginTargetName =
- makefile->GetSafeDefinition("AM_ORIGIN_TARGET_NAME");
+ // - Uic
+ this->SkipUic = makefile->GetSafeDefinition("AM_SKIP_UIC");
{
const char* uicOptionsFiles =
makefile->GetSafeDefinition("AM_UIC_OPTIONS_FILES");
@@ -280,6 +286,12 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
this->UicOptions[*fileIt] = *optionIt;
}
}
+
+ // - Rcc
+ {
+ std::string rccSources = makefile->GetSafeDefinition("AM_RCC_SOURCES");
+ cmSystemTools::ExpandListArgument(rccSources, this->RccSources);
+ }
{
const char* rccOptionsFiles =
makefile->GetSafeDefinition("AM_RCC_OPTIONS_FILES");
@@ -303,8 +315,15 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
std::vector<std::string> rccInputLists;
cmSystemTools::ExpandListArgument(rccInputs, rccInputLists);
+ // qrc files in the end of the list may have been empty
+ if (rccInputLists.size() < this->RccSources.size()) {
+ rccInputLists.resize(this->RccSources.size());
+ }
if (this->RccSources.size() != rccInputLists.size()) {
- cmSystemTools::Error("Error processing file: ", filename.c_str());
+ std::ostringstream err;
+ err << "AUTOGEN: RCC sources lists size missmatch in: " << filename;
+ err << std::endl;
+ this->LogError(err.str());
return false;
}
@@ -318,9 +337,14 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
this->RccInputs[*fileIt] = rccInputFiles;
}
}
+
+ // - Settings
this->CurrentCompileSettingsStr = this->MakeCompileSettingsString(makefile);
- this->RelaxedMode = makefile->IsOn("AM_RELAXED_MODE");
+ // - Flags
+ this->IncludeProjectDirsBefore =
+ makefile->IsOn("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
+ this->MocRelaxedMode = makefile->IsOn("AM_MOC_RELAXED_MODE");
return true;
}
@@ -341,7 +365,7 @@ std::string cmQtAutoGenerators::MakeCompileSettingsString(cmMakefile* makefile)
return s;
}
-bool cmQtAutoGenerators::ReadOldMocDefinitionsFile(
+void cmQtAutoGenerators::ReadOldMocDefinitionsFile(
cmMakefile* makefile, const std::string& targetDirectory)
{
std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
@@ -352,34 +376,49 @@ bool cmQtAutoGenerators::ReadOldMocDefinitionsFile(
this->OldCompileSettingsStr =
makefile->GetSafeDefinition("AM_OLD_COMPILE_SETTINGS");
}
- return true;
}
-void cmQtAutoGenerators::WriteOldMocDefinitionsFile(
+bool cmQtAutoGenerators::WriteOldMocDefinitionsFile(
const std::string& targetDirectory)
{
+ bool success = true;
+
std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
cmSystemTools::ConvertToUnixSlashes(filename);
filename += "/AutomocOldMocDefinitions.cmake";
- cmsys::ofstream outfile;
- outfile.open(filename.c_str(), std::ios::trunc);
- outfile << "set(AM_OLD_COMPILE_SETTINGS "
- << cmOutputConverter::EscapeForCMake(this->CurrentCompileSettingsStr)
- << ")\n";
+ {
+ cmsys::ofstream outfile;
+ outfile.open(filename.c_str(), std::ios::trunc);
+ if (outfile) {
+ outfile << "set(AM_OLD_COMPILE_SETTINGS "
+ << cmOutputConverter::EscapeForCMake(
+ this->CurrentCompileSettingsStr)
+ << ")\n";
+ success = outfile.good();
+ } else {
+ success = false;
+ }
+ }
- outfile.close();
+ return success;
}
void cmQtAutoGenerators::Init()
{
- this->TargetBuildSubDir = this->TargetName;
- this->TargetBuildSubDir += ".dir/";
+ this->AutogenBuildSubDir = this->AutogenTargetName;
+ this->AutogenBuildSubDir += "/";
- this->OutMocCppFilenameRel = this->TargetName;
- this->OutMocCppFilenameRel += ".cpp";
+ this->OutMocCppFilenameRel = this->AutogenBuildSubDir;
+ this->OutMocCppFilenameRel += "moc_compilation.cpp";
- this->OutMocCppFilenameAbs = this->Builddir + this->OutMocCppFilenameRel;
+ this->OutMocCppFilenameAbs =
+ this->CurrentBinaryDir + this->OutMocCppFilenameRel;
+
+ // Init file path checksum generator
+ fpathCheckSum.setupParentDirs(this->CurrentSourceDir, this->CurrentBinaryDir,
+ this->ProjectSourceDir,
+ this->ProjectBinaryDir);
std::vector<std::string> cdefList;
cmSystemTools::ExpandListArgument(this->MocCompileDefinitionsStr, cdefList);
@@ -464,10 +503,10 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
// the program goes through all .cpp files to see which moc files are
// included. It is not really interesting how the moc file is named, but
// what file the moc is created from. Once a moc is included the same moc
- // may not be included in the _automoc.cpp file anymore. OTOH if there's a
- // header containing Q_OBJECT where no corresponding moc file is included
- // anywhere a moc_<filename>.cpp file is created and included in
- // the _automoc.cpp file.
+ // may not be included in the moc_compilation.cpp file anymore. OTOH if
+ // there's a header containing Q_OBJECT where no corresponding moc file
+ // is included anywhere a moc_<filename>.cpp file is created and included in
+ // the moc_compilation.cpp file.
// key = moc source filepath, value = moc output filepath
std::map<std::string, std::string> includedMocs;
@@ -497,11 +536,16 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
err << "AUTOGEN: Checking " << absFilename << std::endl;
this->LogInfo(err.str());
}
- if (this->RelaxedMode) {
- this->ParseCppFile(absFilename, headerExtensions, includedMocs, uiFiles);
+ if (this->MocRelaxedMode) {
+ if (!this->ParseCppFile(absFilename, headerExtensions, includedMocs,
+ uiFiles)) {
+ return false;
+ }
} else {
- this->StrictParseCppFile(absFilename, headerExtensions, includedMocs,
- uiFiles);
+ if (!this->StrictParseCppFile(absFilename, headerExtensions,
+ includedMocs, uiFiles)) {
+ return false;
+ }
}
this->SearchHeadersForCppFile(absFilename, headerExtensions, headerFiles);
}
@@ -533,38 +577,28 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
this->ParseHeaders(headerFiles, includedMocs, notIncludedMocs, includedUis);
if (!this->MocExecutable.empty()) {
- this->GenerateMocFiles(includedMocs, notIncludedMocs);
+ if (!this->GenerateMocFiles(includedMocs, notIncludedMocs)) {
+ return false;
+ }
}
if (!this->UicExecutable.empty()) {
- this->GenerateUiFiles(includedUis);
+ if (!this->GenerateUiFiles(includedUis)) {
+ return false;
+ }
}
if (!this->RccExecutable.empty()) {
- this->GenerateQrcFiles();
- }
-
- if (this->RunMocFailed) {
- std::ostringstream err;
- err << "moc failed..." << std::endl;
- this->LogError(err.str());
- return false;
- }
- if (this->RunUicFailed) {
- std::ostringstream err;
- err << "uic failed..." << std::endl;
- this->LogError(err.str());
- return false;
- }
- if (this->RunRccFailed) {
- std::ostringstream err;
- err << "rcc failed..." << std::endl;
- this->LogError(err.str());
- return false;
+ if (!this->GenerateQrcFiles()) {
+ return false;
+ }
}
return true;
}
-void cmQtAutoGenerators::ParseCppFile(
+/**
+ * @return True on success
+ */
+bool cmQtAutoGenerators::ParseCppFile(
const std::string& absFilename,
const std::vector<std::string>& headerExtensions,
std::map<std::string, std::string>& includedMocs,
@@ -579,12 +613,12 @@ void cmQtAutoGenerators::ParseCppFile(
std::ostringstream err;
err << "AUTOGEN: warning: " << absFilename << ": file is empty\n"
<< std::endl;
- this->LogError(err.str());
- return;
+ this->LogWarning(err.str());
+ return true;
}
this->ParseForUic(absFilename, contentsString, includedUis);
if (this->MocExecutable.empty()) {
- return;
+ return true;
}
const std::string absPath = cmsys::SystemTools::GetFilenamePath(
@@ -648,7 +682,7 @@ void cmQtAutoGenerators::ParseCppFile(
<< std::endl;
}
this->LogError(err.str());
- ::exit(EXIT_FAILURE);
+ return false;
}
} else {
std::string fileToMoc = absFilename;
@@ -670,7 +704,7 @@ void cmQtAutoGenerators::ParseCppFile(
<< ".cpp\" for a compatibility with "
"strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"
<< std::endl;
- this->LogError(err.str());
+ this->LogWarning(err.str());
} else {
std::ostringstream err;
err << "AUTOGEN: warning: " << absFilename
@@ -683,7 +717,7 @@ void cmQtAutoGenerators::ParseCppFile(
<< ".cpp\" for compatibility with "
"strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"
<< std::endl;
- this->LogError(err.str());
+ this->LogWarning(err.str());
}
} else {
std::ostringstream err;
@@ -696,7 +730,7 @@ void cmQtAutoGenerators::ParseCppFile(
"header.\n"
<< std::endl;
this->LogError(err.str());
- ::exit(EXIT_FAILURE);
+ return false;
}
} else {
dotMocIncluded = true;
@@ -727,7 +761,7 @@ void cmQtAutoGenerators::ParseCppFile(
<< ".moc\" for compatibility with "
"strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"
<< std::endl;
- this->LogError(err.str());
+ this->LogWarning(err.str());
includedMocs[absFilename] = ownMocUnderscoreFile;
includedMocs.erase(ownMocHeaderFile);
@@ -740,13 +774,17 @@ void cmQtAutoGenerators::ParseCppFile(
<< "\"" << scannedFileBasename << ".moc\" !\n"
<< std::endl;
this->LogError(err.str());
-
- ::exit(EXIT_FAILURE);
+ return false;
}
}
+
+ return true;
}
-void cmQtAutoGenerators::StrictParseCppFile(
+/**
+ * @return True on success
+ */
+bool cmQtAutoGenerators::StrictParseCppFile(
const std::string& absFilename,
const std::vector<std::string>& headerExtensions,
std::map<std::string, std::string>& includedMocs,
@@ -761,12 +799,12 @@ void cmQtAutoGenerators::StrictParseCppFile(
std::ostringstream err;
err << "AUTOGEN: warning: " << absFilename << ": file is empty\n"
<< std::endl;
- this->LogError(err.str());
- return;
+ this->LogWarning(err.str());
+ return true;
}
this->ParseForUic(absFilename, contentsString, includedUis);
if (this->MocExecutable.empty()) {
- return;
+ return true;
}
const std::string absPath = cmsys::SystemTools::GetFilenamePath(
@@ -819,7 +857,7 @@ void cmQtAutoGenerators::StrictParseCppFile(
<< std::endl;
}
this->LogError(err.str());
- ::exit(EXIT_FAILURE);
+ return false;
}
} else {
if (basename != scannedFileBasename) {
@@ -835,7 +873,7 @@ void cmQtAutoGenerators::StrictParseCppFile(
"moc on this source file.\n"
<< std::endl;
this->LogError(err.str());
- ::exit(EXIT_FAILURE);
+ return false;
}
dotMocIncluded = true;
includedMocs[absFilename] = currentMoc;
@@ -857,8 +895,10 @@ void cmQtAutoGenerators::StrictParseCppFile(
<< "\"" << scannedFileBasename << ".moc\" !\n"
<< std::endl;
this->LogError(err.str());
- ::exit(EXIT_FAILURE);
+ return false;
}
+
+ return true;
}
void cmQtAutoGenerators::ParseForUic(
@@ -873,7 +913,7 @@ void cmQtAutoGenerators::ParseForUic(
std::ostringstream err;
err << "AUTOGEN: warning: " << absFilename << ": file is empty\n"
<< std::endl;
- this->LogError(err.str());
+ this->LogWarning(err.str());
return;
}
this->ParseForUic(absFilename, contentsString, includedUis);
@@ -950,8 +990,6 @@ void cmQtAutoGenerators::ParseHeaders(
std::map<std::string, std::string>& notIncludedMocs,
std::map<std::string, std::vector<std::string> >& includedUis)
{
- cmFilePathUuid fpathUuid(this->Srcdir, this->Builddir,
- this->ProjectSourceDir, this->ProjectBinaryDir);
for (std::set<std::string>::const_iterator hIt = absHeaders.begin();
hIt != absHeaders.end(); ++hIt) {
const std::string& headerName = *hIt;
@@ -967,8 +1005,10 @@ void cmQtAutoGenerators::ParseHeaders(
std::string macroName;
if (requiresMocing(contents, macroName)) {
- notIncludedMocs[headerName] =
- this->TargetBuildSubDir + fpathUuid.get(headerName, "moc_", ".cpp");
+ notIncludedMocs[headerName] = fpathCheckSum.getPart(headerName) +
+ "/moc_" +
+ cmsys::SystemTools::GetFilenameWithoutLastExtension(headerName) +
+ ".cpp";
}
}
this->ParseForUic(headerName, contents, includedUis);
@@ -994,44 +1034,52 @@ bool cmQtAutoGenerators::GenerateMocFiles(
<< "To avoid this error either" << std::endl
<< "- rename the source files or" << std::endl
<< "- do not include the (moc_NAME.cpp|NAME.moc) file" << std::endl;
- this->NameCollisionLog(err.str(), collisions);
- ::exit(EXIT_FAILURE);
+ this->LogErrorNameCollision(err.str(), collisions);
+ return false;
}
}
// generate moc files that are included by source files.
- for (std::map<std::string, std::string>::const_iterator it =
- includedMocs.begin();
- it != includedMocs.end(); ++it) {
- if (!this->GenerateMoc(it->first, it->second)) {
- if (this->RunMocFailed) {
- return false;
+ {
+ const std::string subDirPrefix = "include/";
+ for (std::map<std::string, std::string>::const_iterator it =
+ includedMocs.begin();
+ it != includedMocs.end(); ++it) {
+ if (!this->GenerateMoc(it->first, it->second, subDirPrefix)) {
+ if (this->RunMocFailed) {
+ return false;
+ }
}
}
}
// generate moc files that are _not_ included by source files.
bool automocCppChanged = false;
- for (std::map<std::string, std::string>::const_iterator it =
- notIncludedMocs.begin();
- it != notIncludedMocs.end(); ++it) {
- if (this->GenerateMoc(it->first, it->second)) {
- automocCppChanged = true;
- } else {
- if (this->RunMocFailed) {
- return false;
+ {
+ const std::string subDirPrefix;
+ for (std::map<std::string, std::string>::const_iterator it =
+ notIncludedMocs.begin();
+ it != notIncludedMocs.end(); ++it) {
+ if (this->GenerateMoc(it->first, it->second, subDirPrefix)) {
+ automocCppChanged = true;
+ } else {
+ if (this->RunMocFailed) {
+ return false;
+ }
}
}
}
- // compose _automoc.cpp content
+ // Compose moc_compilation.cpp content
std::string automocSource;
{
std::ostringstream outStream;
outStream << "/* This file is autogenerated, do not edit*/\n";
if (notIncludedMocs.empty()) {
+ // Dummy content
outStream << "enum some_compilers { need_more_than_nothing };\n";
} else {
+ // Valid content
for (std::map<std::string, std::string>::const_iterator it =
notIncludedMocs.begin();
it != notIncludedMocs.end(); ++it) {
@@ -1042,12 +1090,12 @@ bool cmQtAutoGenerators::GenerateMocFiles(
automocSource = outStream.str();
}
- // check if we even need to update _automoc.cpp
+ // Check if we even need to update moc_compilation.cpp
if (!automocCppChanged) {
- // compare contents of the _automoc.cpp file
+ // compare contents of the moc_compilation.cpp file
const std::string oldContents = ReadAll(this->OutMocCppFilenameAbs);
if (oldContents == automocSource) {
- // nothing changed: don't touch the _automoc.cpp file
+ // nothing changed: don't touch the moc_compilation.cpp file
if (this->Verbose) {
std::ostringstream err;
err << "AUTOGEN: " << this->OutMocCppFilenameRel << " still up to date"
@@ -1058,43 +1106,58 @@ bool cmQtAutoGenerators::GenerateMocFiles(
}
}
- // actually write _automoc.cpp
+ // Actually write moc_compilation.cpp
{
- std::string msg = "Generating moc compilation ";
+ std::string msg = "Generating MOC compilation ";
msg += this->OutMocCppFilenameRel;
- cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
- cmsysTerminal_Color_ForegroundBold,
- msg.c_str(), true, this->ColorOutput);
+ this->LogBold(msg);
}
- {
+ // Make sure the parent directory exists
+ bool success = this->makeParentDirectory(this->OutMocCppFilenameAbs);
+ if (success) {
cmsys::ofstream outfile;
outfile.open(this->OutMocCppFilenameAbs.c_str(), std::ios::trunc);
- outfile << automocSource;
- outfile.close();
+ if (!outfile) {
+ success = false;
+ std::ostringstream err;
+ err << "AUTOGEN: error opening " << this->OutMocCppFilenameAbs << "\n";
+ this->LogError(err.str());
+ } else {
+ outfile << automocSource;
+ // Check for write errors
+ if (!outfile.good()) {
+ success = false;
+ std::ostringstream err;
+ err << "AUTOGEN: error writing " << this->OutMocCppFilenameAbs << "\n";
+ this->LogError(err.str());
+ }
+ }
}
-
- return true;
+ return success;
}
+/**
+ * @return True if a moc file was created. False may indicate an error.
+ */
bool cmQtAutoGenerators::GenerateMoc(const std::string& sourceFile,
- const std::string& mocFileName)
+ const std::string& mocFileName,
+ const std::string& subDirPrefix)
{
- const std::string mocFilePath = this->Builddir + mocFileName;
+ const std::string mocFileRel =
+ this->AutogenBuildSubDir + subDirPrefix + mocFileName;
+ const std::string mocFileAbs = this->CurrentBinaryDir + mocFileRel;
int sourceNewerThanMoc = 0;
- bool success = cmsys::SystemTools::FileTimeCompare(sourceFile, mocFilePath,
+ bool success = cmsys::SystemTools::FileTimeCompare(sourceFile, mocFileAbs,
&sourceNewerThanMoc);
if (this->GenerateAll || !success || sourceNewerThanMoc >= 0) {
- // make sure the directory for the resulting moc file exists
- std::string mocDir = mocFilePath.substr(0, mocFilePath.rfind('/'));
- if (!cmsys::SystemTools::FileExists(mocDir.c_str(), false)) {
- cmsys::SystemTools::MakeDirectory(mocDir.c_str());
- }
+ // Log
+ this->LogBold("Generating MOC source " + mocFileRel);
- std::string msg = "Generating moc source ";
- msg += mocFileName;
- cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
- cmsysTerminal_Color_ForegroundBold,
- msg.c_str(), true, this->ColorOutput);
+ // Make sure the parent directory exists
+ if (!this->makeParentDirectory(mocFileAbs)) {
+ this->RunMocFailed = true;
+ return false;
+ }
std::vector<std::string> command;
command.push_back(this->MocExecutable);
@@ -1108,7 +1171,7 @@ bool cmQtAutoGenerators::GenerateMoc(const std::string& sourceFile,
command.push_back("-DWIN32");
#endif
command.push_back("-o");
- command.push_back(mocFilePath);
+ command.push_back(mocFileAbs);
command.push_back(sourceFile);
if (this->Verbose) {
@@ -1120,12 +1183,15 @@ bool cmQtAutoGenerators::GenerateMoc(const std::string& sourceFile,
bool result =
cmSystemTools::RunSingleCommand(command, &output, &output, &retVal);
if (!result || retVal) {
- std::ostringstream err;
- err << "AUTOGEN: error: process for " << mocFilePath << " failed:\n"
- << output << std::endl;
- this->LogError(err.str());
+ {
+ std::ostringstream err;
+ err << "AUTOGEN: error: moc process for " << mocFileRel << " failed:\n"
+ << output << std::endl;
+ this->LogError(err.str());
+ }
+ cmSystemTools::RemoveFile(mocFileAbs);
this->RunMocFailed = true;
- cmSystemTools::RemoveFile(mocFilePath);
+ return false;
}
return true;
}
@@ -1166,8 +1232,8 @@ bool cmQtAutoGenerators::GenerateUiFiles(
"from different sources."
<< std::endl
<< "To avoid this error rename the source files." << std::endl;
- this->NameCollisionLog(err.str(), collisions);
- ::exit(EXIT_FAILURE);
+ this->LogErrorNameCollision(err.str(), collisions);
+ return false;
}
}
testMap.clear();
@@ -1191,25 +1257,29 @@ bool cmQtAutoGenerators::GenerateUiFiles(
return true;
}
+/**
+ * @return True if a uic file was created. False may indicate an error.
+ */
bool cmQtAutoGenerators::GenerateUi(const std::string& realName,
const std::string& uiInputFile,
const std::string& uiOutputFile)
{
- if (!cmsys::SystemTools::FileExists(this->Builddir.c_str(), false)) {
- cmsys::SystemTools::MakeDirectory(this->Builddir.c_str());
- }
-
- const std::string uiBuildFile = this->Builddir + uiOutputFile;
+ const std::string uicFileRel =
+ this->AutogenBuildSubDir + "include/" + uiOutputFile;
+ const std::string uicFileAbs = this->CurrentBinaryDir + uicFileRel;
int sourceNewerThanUi = 0;
- bool success = cmsys::SystemTools::FileTimeCompare(uiInputFile, uiBuildFile,
+ bool success = cmsys::SystemTools::FileTimeCompare(uiInputFile, uicFileAbs,
&sourceNewerThanUi);
if (this->GenerateAll || !success || sourceNewerThanUi >= 0) {
- std::string msg = "Generating ui header ";
- msg += uiOutputFile;
- cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
- cmsysTerminal_Color_ForegroundBold,
- msg.c_str(), true, this->ColorOutput);
+ // Log
+ this->LogBold("Generating UIC header " + uicFileRel);
+
+ // Make sure the parent directory exists
+ if (!this->makeParentDirectory(uicFileAbs)) {
+ this->RunUicFailed = true;
+ return false;
+ }
std::vector<std::string> command;
command.push_back(this->UicExecutable);
@@ -1226,7 +1296,7 @@ bool cmQtAutoGenerators::GenerateUi(const std::string& realName,
command.insert(command.end(), opts.begin(), opts.end());
command.push_back("-o");
- command.push_back(uiBuildFile);
+ command.push_back(uicFileAbs);
command.push_back(uiInputFile);
if (this->Verbose) {
@@ -1237,13 +1307,15 @@ bool cmQtAutoGenerators::GenerateUi(const std::string& realName,
bool result =
cmSystemTools::RunSingleCommand(command, &output, &output, &retVal);
if (!result || retVal) {
- std::ostringstream err;
- err << "AUTOUIC: error: process for " << uiOutputFile
- << " needed by\n \"" << realName << "\"\nfailed:\n"
- << output << std::endl;
- this->LogError(err.str());
+ {
+ std::ostringstream err;
+ err << "AUTOUIC: error: uic process for " << uicFileRel
+ << " needed by\n \"" << realName << "\"\nfailed:\n"
+ << output << std::endl;
+ this->LogError(err.str());
+ }
+ cmSystemTools::RemoveFile(uicFileAbs);
this->RunUicFailed = true;
- cmSystemTools::RemoveFile(uiOutputFile);
return false;
}
return true;
@@ -1271,18 +1343,13 @@ bool cmQtAutoGenerators::GenerateQrcFiles()
{
// generate single map with input / output names
std::map<std::string, std::string> qrcGenMap;
- {
- cmFilePathUuid fpathUuid(this->Srcdir, this->Builddir,
- this->ProjectSourceDir, this->ProjectBinaryDir);
- for (std::vector<std::string>::const_iterator si =
- this->RccSources.begin();
- si != this->RccSources.end(); ++si) {
- const std::string ext =
- cmsys::SystemTools::GetFilenameLastExtension(*si);
- if (ext == ".qrc") {
- qrcGenMap[*si] =
- (this->TargetBuildSubDir + fpathUuid.get(*si, "qrc_", ".cpp"));
- }
+ for (std::vector<std::string>::const_iterator si = this->RccSources.begin();
+ si != this->RccSources.end(); ++si) {
+ const std::string ext = cmsys::SystemTools::GetFilenameLastExtension(*si);
+ if (ext == ".qrc") {
+ qrcGenMap[*si] = this->AutogenBuildSubDir + fpathCheckSum.getPart(*si) +
+ "/qrc_" + cmsys::SystemTools::GetFilenameWithoutLastExtension(*si) +
+ ".cpp";
}
}
@@ -1295,8 +1362,8 @@ bool cmQtAutoGenerators::GenerateQrcFiles()
" will be generated from different sources."
<< std::endl
<< "To avoid this error rename the source .qrc files." << std::endl;
- this->NameCollisionLog(err.str(), collisions);
- ::exit(EXIT_FAILURE);
+ this->LogErrorNameCollision(err.str(), collisions);
+ return false;
}
}
@@ -1314,25 +1381,24 @@ bool cmQtAutoGenerators::GenerateQrcFiles()
return true;
}
+/**
+ * @return True if a rcc file was created. False may indicate an error.
+ */
bool cmQtAutoGenerators::GenerateQrc(const std::string& qrcInputFile,
const std::string& qrcOutputFile,
bool unique_n)
{
- std::string symbolName;
- if (unique_n) {
- symbolName =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcInputFile);
- } else {
- symbolName =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcOutputFile);
- // Remove "qrc_" at string begin
- symbolName.erase(0, 4);
+ std::string symbolName =
+ cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcInputFile);
+ if (!unique_n) {
+ symbolName += "_";
+ symbolName += fpathCheckSum.getPart(qrcInputFile);
}
// Replace '-' with '_'. The former is valid for
// file names but not for symbol names.
std::replace(symbolName.begin(), symbolName.end(), '-', '_');
- const std::string qrcBuildFile = this->Builddir + qrcOutputFile;
+ const std::string qrcBuildFile = this->CurrentBinaryDir + qrcOutputFile;
int sourceNewerThanQrc = 0;
bool generateQrc = !cmsys::SystemTools::FileTimeCompare(
@@ -1342,21 +1408,27 @@ bool cmQtAutoGenerators::GenerateQrc(const std::string& qrcInputFile,
generateQrc || this->InputFilesNewerThanQrc(qrcInputFile, qrcBuildFile);
if (this->GenerateAll || generateQrc) {
- std::string msg = "Generating qrc source ";
- msg += qrcOutputFile;
- cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
- cmsysTerminal_Color_ForegroundBold,
- msg.c_str(), true, this->ColorOutput);
+ {
+ std::string msg = "Generating RCC source ";
+ msg += qrcOutputFile;
+ this->LogBold(msg);
+ }
+
+ // Make sure the parent directory exists
+ if (!this->makeParentDirectory(qrcOutputFile)) {
+ this->RunRccFailed = true;
+ return false;
+ }
std::vector<std::string> command;
command.push_back(this->RccExecutable);
-
- std::map<std::string, std::string>::const_iterator optionIt =
- this->RccOptions.find(qrcInputFile);
- if (optionIt != this->RccOptions.end()) {
- cmSystemTools::ExpandListArgument(optionIt->second, command);
+ {
+ std::map<std::string, std::string>::const_iterator optionIt =
+ this->RccOptions.find(qrcInputFile);
+ if (optionIt != this->RccOptions.end()) {
+ cmSystemTools::ExpandListArgument(optionIt->second, command);
+ }
}
-
command.push_back("-name");
command.push_back(symbolName);
command.push_back("-o");
@@ -1371,16 +1443,20 @@ bool cmQtAutoGenerators::GenerateQrc(const std::string& qrcInputFile,
bool result =
cmSystemTools::RunSingleCommand(command, &output, &output, &retVal);
if (!result || retVal) {
- std::ostringstream err;
- err << "AUTORCC: error: process for " << qrcOutputFile << " failed:\n"
- << output << std::endl;
- this->LogError(err.str());
- this->RunRccFailed = true;
+ {
+ std::ostringstream err;
+ err << "AUTORCC: error: rcc process for " << qrcOutputFile
+ << " failed:\n"
+ << output << std::endl;
+ this->LogError(err.str());
+ }
cmSystemTools::RemoveFile(qrcBuildFile);
+ this->RunRccFailed = true;
return false;
}
+ return true;
}
- return true;
+ return false;
}
/**
@@ -1413,7 +1489,7 @@ bool cmQtAutoGenerators::NameCollisionTest(
return !collisions.empty();
}
-void cmQtAutoGenerators::NameCollisionLog(
+void cmQtAutoGenerators::LogErrorNameCollision(
const std::string& message,
const std::multimap<std::string, std::string>& collisions)
{
@@ -1429,14 +1505,30 @@ void cmQtAutoGenerators::NameCollisionLog(
this->LogError(err.str());
}
+void cmQtAutoGenerators::LogBold(const std::string& message)
+{
+ cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
+ cmsysTerminal_Color_ForegroundBold,
+ message.c_str(), true, this->ColorOutput);
+}
+
void cmQtAutoGenerators::LogInfo(const std::string& message)
{
- std::cout << message;
+ std::cout << message.c_str();
+}
+
+void cmQtAutoGenerators::LogWarning(const std::string& message)
+{
+ std::ostringstream ostr;
+ ostr << message << "\n";
+ std::cout << message.c_str();
}
void cmQtAutoGenerators::LogError(const std::string& message)
{
- std::cerr << message;
+ std::ostringstream ostr;
+ ostr << message << "\n\n";
+ std::cerr << ostr.str();
}
void cmQtAutoGenerators::LogCommand(const std::vector<std::string>& command)
@@ -1455,6 +1547,25 @@ void cmQtAutoGenerators::LogCommand(const std::vector<std::string>& command)
}
}
+/**
+ * @brief Generates the parent directory of the given file on demand
+ * @return True on success
+ */
+bool cmQtAutoGenerators::makeParentDirectory(const std::string& filename)
+{
+ bool success = true;
+ const std::string dirName = cmSystemTools::GetFilenamePath(filename);
+ if (!dirName.empty()) {
+ success = cmsys::SystemTools::MakeDirectory(dirName);
+ if (!success) {
+ std::ostringstream err;
+ err << "AUTOGEN: Directory creation failed: " << dirName << std::endl;
+ this->LogError(err.str());
+ }
+ }
+ return success;
+}
+
std::string cmQtAutoGenerators::JoinExts(const std::vector<std::string>& lst)
{
if (lst.empty()) {
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index 08d7e03..c241579 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -4,6 +4,7 @@
#define cmQtAutoGenerators_h
#include <cmConfigure.h> // IWYU pragma: keep
+#include <cmFilePathChecksum.h>
#include <list>
#include <map>
@@ -23,32 +24,36 @@ private:
bool ReadAutogenInfoFile(cmMakefile* makefile,
const std::string& targetDirectory,
const std::string& config);
- bool ReadOldMocDefinitionsFile(cmMakefile* makefile,
+ void ReadOldMocDefinitionsFile(cmMakefile* makefile,
const std::string& targetDirectory);
- void WriteOldMocDefinitionsFile(const std::string& targetDirectory);
+ bool WriteOldMocDefinitionsFile(const std::string& targetDirectory);
std::string MakeCompileSettingsString(cmMakefile* makefile);
bool RunAutogen(cmMakefile* makefile);
+
bool GenerateMocFiles(
const std::map<std::string, std::string>& includedMocs,
const std::map<std::string, std::string>& notIncludedMocs);
bool GenerateMoc(const std::string& sourceFile,
- const std::string& mocFileName);
+ const std::string& mocFileName,
+ const std::string& subDirPrefix);
+
bool GenerateUiFiles(
const std::map<std::string, std::vector<std::string> >& includedUis);
bool GenerateUi(const std::string& realName, const std::string& uiInputFile,
const std::string& uiOutputFile);
+
bool GenerateQrcFiles();
bool GenerateQrc(const std::string& qrcInputFile,
const std::string& qrcOutputFile, bool unique_n);
- void ParseCppFile(
+ bool ParseCppFile(
const std::string& absFilename,
const std::vector<std::string>& headerExtensions,
std::map<std::string, std::string>& includedMocs,
std::map<std::string, std::vector<std::string> >& includedUis);
- void StrictParseCppFile(
+ bool StrictParseCppFile(
const std::string& absFilename,
const std::vector<std::string>& headerExtensions,
std::map<std::string, std::string>& includedMocs,
@@ -76,13 +81,18 @@ private:
bool NameCollisionTest(const std::map<std::string, std::string>& genFiles,
std::multimap<std::string, std::string>& collisions);
- void NameCollisionLog(
+
+ void LogErrorNameCollision(
const std::string& message,
const std::multimap<std::string, std::string>& collisions);
-
+ void LogBold(const std::string& message);
void LogInfo(const std::string& message);
+ void LogWarning(const std::string& message);
void LogError(const std::string& message);
void LogCommand(const std::vector<std::string>& command);
+
+ bool makeParentDirectory(const std::string& filename);
+
std::string JoinExts(const std::vector<std::string>& lst);
static void MergeUicOptions(std::vector<std::string>& opts,
@@ -92,39 +102,47 @@ private:
bool InputFilesNewerThanQrc(const std::string& qrcFile,
const std::string& rccOutput);
+ // - Target names
+ std::string OriginTargetName;
+ std::string AutogenTargetName;
+ // - Directories
+ std::string ProjectSourceDir;
+ std::string ProjectBinaryDir;
+ std::string CurrentSourceDir;
+ std::string CurrentBinaryDir;
+ std::string AutogenBuildSubDir;
+ // - Qt environment
std::string QtMajorVersion;
- std::string Sources;
- std::vector<std::string> RccSources;
- std::string SkipMoc;
- std::string SkipUic;
- std::string Headers;
- std::string Srcdir;
- std::string Builddir;
std::string MocExecutable;
std::string UicExecutable;
std::string RccExecutable;
+ // - File lists
+ std::string Sources;
+ std::string Headers;
+ // - Moc
+ std::string SkipMoc;
std::string MocCompileDefinitionsStr;
std::string MocIncludesStr;
std::string MocOptionsStr;
- std::string ProjectBinaryDir;
- std::string ProjectSourceDir;
- std::string TargetName;
- std::string OriginTargetName;
-
- std::string CurrentCompileSettingsStr;
- std::string OldCompileSettingsStr;
-
- std::string TargetBuildSubDir;
std::string OutMocCppFilenameRel;
std::string OutMocCppFilenameAbs;
std::list<std::string> MocIncludes;
std::list<std::string> MocDefinitions;
std::vector<std::string> MocOptions;
+ // - Uic
+ std::string SkipUic;
std::vector<std::string> UicTargetOptions;
std::map<std::string, std::string> UicOptions;
+ // - Rcc
+ std::vector<std::string> RccSources;
std::map<std::string, std::string> RccOptions;
std::map<std::string, std::vector<std::string> > RccInputs;
-
+ // - Settings
+ std::string CurrentCompileSettingsStr;
+ std::string OldCompileSettingsStr;
+ // - Utility
+ cmFilePathChecksum fpathCheckSum;
+ // - Flags
bool IncludeProjectDirsBefore;
bool Verbose;
bool ColorOutput;
@@ -132,7 +150,7 @@ private:
bool RunUicFailed;
bool RunRccFailed;
bool GenerateAll;
- bool RelaxedMode;
+ bool MocRelaxedMode;
};
#endif
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index 3776538..c08a36b 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -672,8 +672,9 @@ static Json::Value DumpSourceFilesList(
std::string compileFlags = ld.Flags;
if (const char* cflags = file->GetProperty("COMPILE_FLAGS")) {
cmGeneratorExpression ge;
+ auto cge = ge.Parse(cflags);
const char* processed =
- ge.Parse(cflags)->Evaluate(target->GetLocalGenerator(), config);
+ cge->Evaluate(target->GetLocalGenerator(), config);
lg->AppendFlags(compileFlags, processed);
}
fileData.Flags = compileFlags;
diff --git a/Source/cmake.h b/Source/cmake.h
index 0f1891d..5347745 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -549,6 +549,7 @@ private:
F(cxx_std_98) \
F(cxx_std_11) \
F(cxx_std_14) \
+ F(cxx_std_17) \
F(cxx_aggregate_default_initializers) \
F(cxx_alias_templates) \
F(cxx_alignas) \
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index b8a9a6b..9eb3b2d 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -429,6 +429,17 @@ SET_SOURCE_FILES_PROPERTIES(ProcessUNIX.c System.c PROPERTIES
COMPILE_FLAGS "-DKWSYS_C_HAS_PTRDIFF_T=${KWSYS_C_HAS_PTRDIFF_T} -DKWSYS_C_HAS_SSIZE_T=${KWSYS_C_HAS_SSIZE_T}"
)
+IF(KWSYS_USE_DynamicLoader)
+ GET_PROPERTY(KWSYS_SUPPORTS_SHARED_LIBS GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
+ IF(KWSYS_SUPPORTS_SHARED_LIBS)
+ SET(KWSYS_SUPPORTS_SHARED_LIBS 1)
+ ELSE()
+ SET(KWSYS_SUPPORTS_SHARED_LIBS 0)
+ ENDIF()
+ SET_PROPERTY(SOURCE DynamicLoader.cxx APPEND PROPERTY COMPILE_DEFINITIONS
+ KWSYS_SUPPORTS_SHARED_LIBS=${KWSYS_SUPPORTS_SHARED_LIBS})
+ENDIF()
+
IF(KWSYS_USE_SystemTools)
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_SETENV
"Checking whether CXX compiler has setenv" DIRECT)
@@ -868,7 +879,7 @@ ENDIF()
IF(KWSYS_USE_Encoding)
# Set default 8 bit encoding in "EndcodingC.c".
- SET_PROPERTY(SOURCE EncodingC.c APPEND PROPERTY COMPILE_DEFINITIONS
+ SET_PROPERTY(SOURCE EncodingC.c EncodingCXX.cxx APPEND PROPERTY COMPILE_DEFINITIONS
KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE})
ENDIF()
diff --git a/Source/kwsys/ConsoleBuf.hxx.in b/Source/kwsys/ConsoleBuf.hxx.in
index c45a351..cb58865 100644
--- a/Source/kwsys/ConsoleBuf.hxx.in
+++ b/Source/kwsys/ConsoleBuf.hxx.in
@@ -327,14 +327,13 @@ private:
const int length =
WideCharToMultiByte(m_activeOutputCodepage, 0, wbuffer.c_str(),
(int)wbuffer.size(), NULL, 0, NULL, NULL);
- char* buf = new char[length + 1];
+ char* buf = new char[length];
const bool success =
WideCharToMultiByte(m_activeOutputCodepage, 0, wbuffer.c_str(),
(int)wbuffer.size(), buf, length, NULL, NULL) > 0
? true
: false;
- buf[length] = '\0';
- buffer = buf;
+ buffer = std::string(buf, length);
delete[] buf;
return success;
}
diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx
index e0268c0..e494db6 100644
--- a/Source/kwsys/DynamicLoader.cxx
+++ b/Source/kwsys/DynamicLoader.cxx
@@ -12,20 +12,63 @@
#include "DynamicLoader.hxx.in"
#endif
-// This file is actually 3 different implementations.
-// 1. HP machines which uses shl_load
-// 2. Mac OS X 10.2.x and earlier which uses NSLinkModule
-// 3. Windows which uses LoadLibrary
-// 4. Most unix systems (including Mac OS X 10.3 and later) which use dlopen
-// (default) Each part of the ifdef contains a complete implementation for
+// This file actually contains several different implementations:
+// * NOOP for environments without dynamic libs
+// * HP machines which uses shl_load
+// * Mac OS X 10.2.x and earlier which uses NSLinkModule
+// * Windows which uses LoadLibrary
+// * BeOS / Haiku
+// * FreeMiNT for Atari
+// * Default implementation for *NIX systems (including Mac OS X 10.3 and
+// later) which use dlopen
+//
+// Each part of the ifdef contains a complete implementation for
// the static methods of DynamicLoader.
-// ---------------------------------------------------------------
-// 1. Implementation for HPUX machines
-#ifdef __hpux
+#if !KWSYS_SUPPORTS_SHARED_LIBS
+//----------------------------------------------------------------------------
+// Implementation for environments without dynamic libs
+#include <string.h> // for strerror()
+
+namespace KWSYS_NAMESPACE {
+
+//----------------------------------------------------------------------------
+DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
+ const std::string& libname)
+{
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
+{
+ if (!lib) {
+ return 0;
+ }
+
+ return 1;
+}
+
+//----------------------------------------------------------------------------
+DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
+ DynamicLoader::LibraryHandle lib, const std::string& sym)
+{
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+const char* DynamicLoader::LastError()
+{
+ return "General error";
+}
+
+} // namespace KWSYS_NAMESPACE
+
+#elif defined(__hpux)
+//----------------------------------------------------------------------------
+// Implementation for HPUX machines
#include <dl.h>
#include <errno.h>
-#define DYNAMICLOADER_DEFINED 1
namespace KWSYS_NAMESPACE {
@@ -88,15 +131,11 @@ const char* DynamicLoader::LastError()
} // namespace KWSYS_NAMESPACE
-#endif //__hpux
-
-// ---------------------------------------------------------------
-// 2. Implementation for Mac OS X 10.2.x and earlier
-#ifdef __APPLE__
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
+#elif defined(__APPLE__) && (MAC_OS_X_VERSION_MAX_ALLOWED < 1030)
+//----------------------------------------------------------------------------
+// Implementation for Mac OS X 10.2.x and earlier
#include <mach-o/dyld.h>
#include <string.h> // for strlen
-#define DYNAMICLOADER_DEFINED 1
namespace KWSYS_NAMESPACE {
@@ -160,14 +199,10 @@ const char* DynamicLoader::LastError()
} // namespace KWSYS_NAMESPACE
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED < 1030
-#endif // __APPLE__
-
-// ---------------------------------------------------------------
-// 3. Implementation for Windows win32 code but not cygwin
-#if defined(_WIN32) && !defined(__CYGWIN__)
+#elif defined(_WIN32) && !defined(__CYGWIN__)
+//----------------------------------------------------------------------------
+// Implementation for Windows win32 code but not cygwin
#include <windows.h>
-#define DYNAMICLOADER_DEFINED 1
namespace KWSYS_NAMESPACE {
@@ -263,19 +298,14 @@ const char* DynamicLoader::LastError()
} // namespace KWSYS_NAMESPACE
-#endif //_WIN32
-
-// ---------------------------------------------------------------
-// 4. Implementation for BeOS
-#if defined __BEOS__
-
+#elif defined(__BEOS__)
+//----------------------------------------------------------------------------
+// Implementation for BeOS / Haiku
#include <string.h> // for strerror()
#include <be/kernel/image.h>
#include <be/support/Errors.h>
-#define DYNAMICLOADER_DEFINED 1
-
namespace KWSYS_NAMESPACE {
static image_id last_dynamic_err = B_OK;
@@ -351,54 +381,10 @@ const char* DynamicLoader::LastError()
}
} // namespace KWSYS_NAMESPACE
-#endif
-
-// ---------------------------------------------------------------
-// 5. Implementation for systems without dynamic libs
-// __gnu_blrts__ is IBM BlueGene/L
-// __LIBCATAMOUNT__ is defined on Catamount on Cray compute nodes
-#if defined(__gnu_blrts__) || defined(__LIBCATAMOUNT__) || \
- defined(__CRAYXT_COMPUTE_LINUX_TARGET)
-#include <string.h> // for strerror()
-#define DYNAMICLOADER_DEFINED 1
-
-namespace KWSYS_NAMESPACE {
-
-//----------------------------------------------------------------------------
-DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
-{
- return 0;
-}
+#elif defined(__MINT__)
//----------------------------------------------------------------------------
-int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
-{
- if (!lib) {
- return 0;
- }
-
- return 1;
-}
-
-//----------------------------------------------------------------------------
-DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
- DynamicLoader::LibraryHandle lib, const std::string& sym)
-{
- return 0;
-}
-
-//----------------------------------------------------------------------------
-const char* DynamicLoader::LastError()
-{
- return "General error";
-}
-
-} // namespace KWSYS_NAMESPACE
-#endif
-
-#ifdef __MINT__
-#define DYNAMICLOADER_DEFINED 1
+// Implementation for FreeMiNT on Atari
#define _GNU_SOURCE /* for program_invocation_name */
#include <dld.h>
#include <errno.h>
@@ -447,14 +433,11 @@ const char* DynamicLoader::LastError()
}
} // namespace KWSYS_NAMESPACE
-#endif
-// ---------------------------------------------------------------
-// 6. Implementation for default UNIX machines.
-// if nothing has been defined then use this
-#ifndef DYNAMICLOADER_DEFINED
-#define DYNAMICLOADER_DEFINED 1
-// Setup for most unix machines
+#else
+//----------------------------------------------------------------------------
+// Default implementation for *NIX systems (including Mac OS X 10.3 and
+// later) which use dlopen
#include <dlfcn.h>
namespace KWSYS_NAMESPACE {
@@ -498,5 +481,4 @@ const char* DynamicLoader::LastError()
}
} // namespace KWSYS_NAMESPACE
-
#endif
diff --git a/Source/kwsys/EncodingCXX.cxx b/Source/kwsys/EncodingCXX.cxx
index 5c58bcb..e904c1a 100644
--- a/Source/kwsys/EncodingCXX.cxx
+++ b/Source/kwsys/EncodingCXX.cxx
@@ -125,12 +125,68 @@ char const* const* Encoding::CommandLineArguments::argv() const
std::wstring Encoding::ToWide(const std::string& str)
{
- return ToWide(str.c_str());
+ std::wstring wstr;
+#if defined(_WIN32)
+ const int wlength = MultiByteToWideChar(
+ KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(), int(str.size()), NULL, 0);
+ if (wlength > 0) {
+ wchar_t* wdata = new wchar_t[wlength];
+ int r = MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(),
+ int(str.size()), wdata, wlength);
+ if (r > 0) {
+ wstr = std::wstring(wdata, wlength);
+ }
+ delete[] wdata;
+ }
+#else
+ size_t pos = 0;
+ size_t nullPos = 0;
+ do {
+ if (pos < str.size() && str.at(pos) != '\0') {
+ wstr += ToWide(str.c_str() + pos);
+ }
+ nullPos = str.find('\0', pos);
+ if (nullPos != str.npos) {
+ pos = nullPos + 1;
+ wstr += wchar_t('\0');
+ }
+ } while (nullPos != str.npos);
+#endif
+ return wstr;
}
std::string Encoding::ToNarrow(const std::wstring& str)
{
- return ToNarrow(str.c_str());
+ std::string nstr;
+#if defined(_WIN32)
+ int length =
+ WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(),
+ int(str.size()), NULL, 0, NULL, NULL);
+ if (length > 0) {
+ char* data = new char[length];
+ int r =
+ WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(),
+ int(str.size()), data, length, NULL, NULL);
+ if (r > 0) {
+ nstr = std::string(data, length);
+ }
+ delete[] data;
+ }
+#else
+ size_t pos = 0;
+ size_t nullPos = 0;
+ do {
+ if (pos < str.size() && str.at(pos) != '\0') {
+ nstr += ToNarrow(str.c_str() + pos);
+ }
+ nullPos = str.find(wchar_t('\0'), pos);
+ if (nullPos != str.npos) {
+ pos = nullPos + 1;
+ nstr += '\0';
+ }
+ } while (nullPos != str.npos);
+#endif
+ return nstr;
}
std::wstring Encoding::ToWide(const char* cstr)
diff --git a/Source/kwsys/testConsoleBuf.cxx b/Source/kwsys/testConsoleBuf.cxx
index bd58fb6..3b8cdab 100644
--- a/Source/kwsys/testConsoleBuf.cxx
+++ b/Source/kwsys/testConsoleBuf.cxx
@@ -18,6 +18,7 @@
#if defined(_WIN32)
+#include <algorithm>
#include <iomanip>
#include <iostream>
#include <stdexcept>
@@ -318,6 +319,7 @@ static int testPipe()
bytesRead == 0) {
throw std::runtime_error("ReadFile#1 failed!");
}
+ buffer[bytesRead] = 0;
if ((bytesRead <
encodedTestString.size() + 1 + encodedInputTestString.size() &&
!ReadFile(outPipeRead, buffer + bytesRead,
@@ -336,8 +338,12 @@ static int testPipe()
bytesRead == 0) {
throw std::runtime_error("ReadFile#3 failed!");
}
- buffer2[bytesRead - 1] = 0;
- didFail = encodedTestString.compare(buffer2) == 0 ? 0 : 1;
+ buffer2[bytesRead] = 0;
+ didFail =
+ encodedTestString.compare(0, encodedTestString.npos, buffer2,
+ encodedTestString.size()) == 0
+ ? 0
+ : 1;
}
if (didFail != 0) {
std::cerr << "Pipe's output didn't match expected output!"
@@ -423,23 +429,28 @@ static int testFile()
bytesRead == 0) {
throw std::runtime_error("ReadFile#1 failed!");
}
- buffer[bytesRead - 1] = 0;
+ buffer[bytesRead] = 0;
if (memcmp(buffer, encodedTestString.c_str(),
encodedTestString.size()) == 0 &&
memcmp(buffer + encodedTestString.size() + 1,
encodedInputTestString.c_str(),
- encodedInputTestString.size() - 1) == 0) {
+ encodedInputTestString.size()) == 0) {
bytesRead = 0;
if (SetFilePointer(errFile, 0, 0, FILE_BEGIN) ==
INVALID_SET_FILE_POINTER) {
throw std::runtime_error("SetFilePointer#2 failed!");
}
+
if (!ReadFile(errFile, buffer2, sizeof(buffer2), &bytesRead, NULL) ||
bytesRead == 0) {
throw std::runtime_error("ReadFile#2 failed!");
}
- buffer2[bytesRead - 1] = 0;
- didFail = encodedTestString.compare(buffer2) == 0 ? 0 : 1;
+ buffer2[bytesRead] = 0;
+ didFail =
+ encodedTestString.compare(0, encodedTestString.npos, buffer2,
+ encodedTestString.size()) == 0
+ ? 0
+ : 1;
}
if (didFail != 0) {
std::cerr << "File's output didn't match expected output!"
@@ -448,7 +459,7 @@ static int testFile()
encodedTestString.size());
dumpBuffers<char>(encodedInputTestString.c_str(),
buffer + encodedTestString.size() + 1,
- encodedInputTestString.size() - 1);
+ encodedInputTestString.size());
dumpBuffers<char>(encodedTestString.c_str(), buffer2,
encodedTestString.size());
}
@@ -685,6 +696,7 @@ static int testConsole()
throw std::runtime_error("ReadConsoleOutputCharacter failed!");
}
std::wstring wideTestString = kwsys::Encoding::ToWide(encodedTestString);
+ std::replace(wideTestString.begin(), wideTestString.end(), '\0', ' ');
std::wstring wideInputTestString =
kwsys::Encoding::ToWide(encodedInputTestString);
if (memcmp(outputBuffer, wideTestString.c_str(),
@@ -757,8 +769,11 @@ int testConsoleBuf(int, char* [])
return 1;
}
- encodedTestString = kwsys::Encoding::ToNarrow(UnicodeTestString);
- encodedInputTestString = kwsys::Encoding::ToNarrow(UnicodeInputTestString);
+ encodedTestString = kwsys::Encoding::ToNarrow(std::wstring(
+ UnicodeTestString, sizeof(UnicodeTestString) / sizeof(wchar_t) - 1));
+ encodedInputTestString = kwsys::Encoding::ToNarrow(
+ std::wstring(UnicodeInputTestString,
+ sizeof(UnicodeInputTestString) / sizeof(wchar_t) - 1));
encodedInputTestString += "\n";
ret |= testPipe();
diff --git a/Source/kwsys/testConsoleBuf.hxx b/Source/kwsys/testConsoleBuf.hxx
index 8891960..e93cb4f 100644
--- a/Source/kwsys/testConsoleBuf.hxx
+++ b/Source/kwsys/testConsoleBuf.hxx
@@ -11,7 +11,7 @@ static const wchar_t AfterOutputEventName[] = L"AfterOutputEvent";
// यूनिकोड είναι здорово!
static const wchar_t UnicodeTestString[] =
L"\u092F\u0942\u0928\u093F\u0915\u094B\u0921 "
- L"\u03B5\u03AF\u03BD\u03B1\u03B9 "
+ L"\u03B5\u03AF\u03BD\0\u03B1\u03B9 "
L"\u0437\u0434\u043E\u0440\u043E\u0432\u043E!";
#endif
diff --git a/Source/kwsys/testConsoleBufChild.cxx b/Source/kwsys/testConsoleBufChild.cxx
index 313323e..83bf545 100644
--- a/Source/kwsys/testConsoleBufChild.cxx
+++ b/Source/kwsys/testConsoleBufChild.cxx
@@ -28,7 +28,8 @@ int main(int argc, const char* argv[])
std::cout << argv[1] << std::endl;
std::cerr << argv[1] << std::endl;
} else {
- std::string str = kwsys::Encoding::ToNarrow(UnicodeTestString);
+ std::string str = kwsys::Encoding::ToNarrow(std::wstring(
+ UnicodeTestString, sizeof(UnicodeTestString) / sizeof(wchar_t) - 1));
std::cout << str << std::endl;
std::cerr << str << std::endl;
}
diff --git a/Source/kwsys/testEncoding.cxx b/Source/kwsys/testEncoding.cxx
index 996976f..03f2ec9 100644
--- a/Source/kwsys/testEncoding.cxx
+++ b/Source/kwsys/testEncoding.cxx
@@ -9,6 +9,7 @@
#include KWSYS_HEADER(Encoding.hxx)
#include KWSYS_HEADER(Encoding.h)
+#include <algorithm>
#include <iostream>
#include <locale.h>
#include <stdlib.h>
@@ -124,6 +125,35 @@ static int testRobustEncoding()
return ret;
}
+static int testWithNulls()
+{
+ int ret = 0;
+ std::vector<std::string> strings;
+ strings.push_back(std::string("ab") + '\0' + 'c');
+ strings.push_back(std::string("d") + '\0' + '\0' + 'e');
+ strings.push_back(std::string() + '\0' + 'f');
+ strings.push_back(std::string() + '\0' + '\0' + "gh");
+ strings.push_back(std::string("ij") + '\0');
+ strings.push_back(std::string("k") + '\0' + '\0');
+ strings.push_back(std::string("\0\0\0\0", 4) + "lmn" +
+ std::string("\0\0\0\0", 4));
+ for (std::vector<std::string>::iterator it = strings.begin();
+ it != strings.end(); ++it) {
+ std::wstring wstr = kwsys::Encoding::ToWide(*it);
+ std::string str = kwsys::Encoding::ToNarrow(wstr);
+ std::string s(*it);
+ std::replace(s.begin(), s.end(), '\0', ' ');
+ std::cout << "'" << s << "' (" << it->size() << ")" << std::endl;
+ if (str != *it) {
+ std::replace(str.begin(), str.end(), '\0', ' ');
+ std::cout << "string with null was different: '" << str << "' ("
+ << str.size() << ")" << std::endl;
+ ret++;
+ }
+ }
+ return ret;
+}
+
static int testCommandLineArguments()
{
int status = 0;
@@ -165,6 +195,7 @@ int testEncoding(int, char* [])
ret |= testHelloWorldEncoding();
ret |= testRobustEncoding();
ret |= testCommandLineArguments();
+ ret |= testWithNulls();
return ret;
}