diff options
Diffstat (limited to 'Source')
29 files changed, 472 insertions, 121 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index a8d77b2..54e5063 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -216,6 +216,8 @@ set(SRCS cmFileTimeComparison.cxx cmFileTimeComparison.h cmFortranParserImpl.cxx + cmFSPermissions.cxx + cmFSPermissions.h cmGeneratedFileStream.cxx cmGeneratorExpressionContext.cxx cmGeneratorExpressionContext.h diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c9ec2ee..654a1bf 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 10) -set(CMake_VERSION_PATCH 20171107) +set(CMake_VERSION_PATCH 20171113) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index ecb5adb..be75a9f 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -12,6 +12,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackLog.h" #include "cmCryptoHash.h" +#include "cmFSPermissions.h" #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" @@ -201,6 +202,29 @@ int cmCPackGenerator::InstallProject() cmSystemTools::PutEnv("DESTDIR="); } + // prepare default created directory permissions + mode_t default_dir_mode_v = 0; + mode_t* default_dir_mode = nullptr; + const char* default_dir_install_permissions = + this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); + if (default_dir_install_permissions && *default_dir_install_permissions) { + std::vector<std::string> items; + cmSystemTools::ExpandListArgument(default_dir_install_permissions, items); + for (const auto& arg : items) { + if (!cmFSPermissions::stringToModeT(arg, default_dir_mode_v)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, "Invalid permission value '" + << arg + << "'." + " CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS " + "value is invalid." + << std::endl); + return 0; + } + } + + default_dir_mode = &default_dir_mode_v; + } + // If the CPackConfig file sets CPACK_INSTALL_COMMANDS then run them // as listed if (!this->InstallProjectViaInstallCommands(setDestDir, @@ -218,15 +242,15 @@ int cmCPackGenerator::InstallProject() // If the CPackConfig file sets CPACK_INSTALLED_DIRECTORIES // then glob it and copy it to CPACK_TEMPORARY_DIRECTORY // This is used in Source packaging - if (!this->InstallProjectViaInstalledDirectories(setDestDir, - tempInstallDirectory)) { + if (!this->InstallProjectViaInstalledDirectories( + setDestDir, tempInstallDirectory, default_dir_mode)) { return 0; } // If the project is a CMAKE project then run pre-install // and then read the cmake_install script to run it - if (!this->InstallProjectViaInstallCMakeProjects(setDestDir, - bareTempInstallDirectory)) { + if (!this->InstallProjectViaInstallCMakeProjects( + setDestDir, bareTempInstallDirectory, default_dir_mode)) { return 0; } @@ -274,7 +298,8 @@ int cmCPackGenerator::InstallProjectViaInstallCommands( } int cmCPackGenerator::InstallProjectViaInstalledDirectories( - bool setDestDir, const std::string& tempInstallDirectory) + bool setDestDir, const std::string& tempInstallDirectory, + const mode_t* default_dir_mode) { (void)setDestDir; (void)tempInstallDirectory; @@ -385,7 +410,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( // make sure directory exists for symlink std::string destDir = cmSystemTools::GetFilenamePath(symlinked.second); - if (!destDir.empty() && !cmSystemTools::MakeDirectory(destDir)) { + if (!destDir.empty() && + !cmSystemTools::MakeDirectory(destDir, default_dir_mode)) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create dir: " << destDir << "\nTrying to create symlink: " << symlinked.second << "--> " << symlinked.first @@ -464,7 +490,8 @@ int cmCPackGenerator::InstallProjectViaInstallScript( } int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( - bool setDestDir, const std::string& baseTempInstallDirectory) + bool setDestDir, const std::string& baseTempInstallDirectory, + const mode_t* default_dir_mode) { const char* cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS"); const char* cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR"); @@ -631,6 +658,13 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( } } + const char* default_dir_inst_permissions = + this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); + if (default_dir_inst_permissions && *default_dir_inst_permissions) { + mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS", + default_dir_inst_permissions); + } + if (!setDestDir) { tempInstallDirectory += this->GetPackagingInstallPrefix(); } @@ -690,7 +724,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( cmCPackLogger(cmCPackLog::LOG_DEBUG, "- Creating directory: '" << dir << "'" << std::endl); - if (!cmsys::SystemTools::MakeDirectory(dir.c_str())) { + if (!cmsys::SystemTools::MakeDirectory(dir, default_dir_mode)) { cmCPackLogger( cmCPackLog::LOG_ERROR, "Problem creating temporary directory: " << dir << std::endl); @@ -700,8 +734,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( mf.AddDefinition("CMAKE_INSTALL_PREFIX", tempInstallDirectory.c_str()); - if (!cmsys::SystemTools::MakeDirectory( - tempInstallDirectory.c_str())) { + if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory, + default_dir_mode)) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem creating temporary directory: " << tempInstallDirectory << std::endl); diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 4e3a6e0..8100b66 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -12,6 +12,7 @@ #include "cmCPackComponentGroup.h" #include "cmSystemTools.h" +#include "cm_sys_stat.h" class cmCPackLog; class cmInstalledFile; @@ -168,9 +169,11 @@ protected: virtual int InstallProjectViaInstallScript( bool setDestDir, const std::string& tempInstallDirectory); virtual int InstallProjectViaInstalledDirectories( - bool setDestDir, const std::string& tempInstallDirectory); + bool setDestDir, const std::string& tempInstallDirectory, + const mode_t* default_dir_mode); virtual int InstallProjectViaInstallCMakeProjects( - bool setDestDir, const std::string& tempInstallDirectory); + bool setDestDir, const std::string& tempInstallDirectory, + const mode_t* default_dir_mode); /** * The various level of support of diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 37ff901..92da9ab 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -282,7 +282,6 @@ cmCTest::cmCTest() this->GlobalTimeout = 0; this->LastStopTimeout = 24 * 60 * 60; this->CompressXMLFiles = false; - this->CTestConfigFile.clear(); this->ScheduleType.clear(); this->StopTime.clear(); this->NextDayStopTime = false; @@ -623,12 +622,9 @@ bool cmCTest::UpdateCTestConfiguration() if (this->SuppressUpdatingCTestConfiguration) { return true; } - std::string fileName = this->CTestConfigFile; - if (fileName.empty()) { - fileName = this->BinaryDir + "/CTestConfiguration.ini"; - if (!cmSystemTools::FileExists(fileName.c_str())) { - fileName = this->BinaryDir + "/DartConfiguration.tcl"; - } + std::string fileName = this->BinaryDir + "/CTestConfiguration.ini"; + if (!cmSystemTools::FileExists(fileName.c_str())) { + fileName = this->BinaryDir + "/DartConfiguration.tcl"; } cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "UpdateCTestConfiguration from :" << fileName << "\n"); diff --git a/Source/cmCTest.h b/Source/cmCTest.h index dbd67dc..a2d6fc3 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -487,7 +487,6 @@ private: /** Map of configuration properties */ typedef std::map<std::string, std::string> CTestConfigurationMap; - std::string CTestConfigFile; // TODO: The ctest configuration should be a hierarchy of // configuration option sources: command-line, script, ini file. // Then the ini file can get re-loaded whenever it changes without diff --git a/Source/cmFSPermissions.cxx b/Source/cmFSPermissions.cxx new file mode 100644 index 0000000..4015a51 --- /dev/null +++ b/Source/cmFSPermissions.cxx @@ -0,0 +1,34 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmFSPermissions.h" + +bool cmFSPermissions::stringToModeT(std::string const& arg, + mode_t& permissions) +{ + if (arg == "OWNER_READ") { + permissions |= mode_owner_read; + } else if (arg == "OWNER_WRITE") { + permissions |= mode_owner_write; + } else if (arg == "OWNER_EXECUTE") { + permissions |= mode_owner_execute; + } else if (arg == "GROUP_READ") { + permissions |= mode_group_read; + } else if (arg == "GROUP_WRITE") { + permissions |= mode_group_write; + } else if (arg == "GROUP_EXECUTE") { + permissions |= mode_group_execute; + } else if (arg == "WORLD_READ") { + permissions |= mode_world_read; + } else if (arg == "WORLD_WRITE") { + permissions |= mode_world_write; + } else if (arg == "WORLD_EXECUTE") { + permissions |= mode_world_execute; + } else if (arg == "SETUID") { + permissions |= mode_setuid; + } else if (arg == "SETGID") { + permissions |= mode_setgid; + } else { + return false; + } + return true; +} diff --git a/Source/cmFSPermissions.h b/Source/cmFSPermissions.h new file mode 100644 index 0000000..7a6e708 --- /dev/null +++ b/Source/cmFSPermissions.h @@ -0,0 +1,45 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmFSPermissions_h +#define cmFSPermissions_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cm_sys_stat.h" + +#include <string> + +namespace cmFSPermissions { + +// Table of permissions flags. +#if defined(_WIN32) && !defined(__CYGWIN__) +static const mode_t mode_owner_read = S_IREAD; +static const mode_t mode_owner_write = S_IWRITE; +static const mode_t mode_owner_execute = S_IEXEC; +static const mode_t mode_group_read = 040; +static const mode_t mode_group_write = 020; +static const mode_t mode_group_execute = 010; +static const mode_t mode_world_read = 04; +static const mode_t mode_world_write = 02; +static const mode_t mode_world_execute = 01; +static const mode_t mode_setuid = 04000; +static const mode_t mode_setgid = 02000; +#else +static const mode_t mode_owner_read = S_IRUSR; +static const mode_t mode_owner_write = S_IWUSR; +static const mode_t mode_owner_execute = S_IXUSR; +static const mode_t mode_group_read = S_IRGRP; +static const mode_t mode_group_write = S_IWGRP; +static const mode_t mode_group_execute = S_IXGRP; +static const mode_t mode_world_read = S_IROTH; +static const mode_t mode_world_write = S_IWOTH; +static const mode_t mode_world_execute = S_IXOTH; +static const mode_t mode_setuid = S_ISUID; +static const mode_t mode_setgid = S_ISGID; +#endif + +bool stringToModeT(std::string const& arg, mode_t& permissions); + +} // ns + +#endif diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 191a666..88185bd 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -20,6 +20,7 @@ #include "cmAlgorithms.h" #include "cmCommandArgumentsHelper.h" #include "cmCryptoHash.h" +#include "cmFSPermissions.h" #include "cmFileLockPool.h" #include "cmFileTimeComparison.h" #include "cmGeneratorExpression.h" @@ -50,32 +51,7 @@ class cmSystemToolsFileTime; -// Table of permissions flags. -#if defined(_WIN32) && !defined(__CYGWIN__) -static mode_t mode_owner_read = S_IREAD; -static mode_t mode_owner_write = S_IWRITE; -static mode_t mode_owner_execute = S_IEXEC; -static mode_t mode_group_read = 040; -static mode_t mode_group_write = 020; -static mode_t mode_group_execute = 010; -static mode_t mode_world_read = 04; -static mode_t mode_world_write = 02; -static mode_t mode_world_execute = 01; -static mode_t mode_setuid = 04000; -static mode_t mode_setgid = 02000; -#else -static mode_t mode_owner_read = S_IRUSR; -static mode_t mode_owner_write = S_IWUSR; -static mode_t mode_owner_execute = S_IXUSR; -static mode_t mode_group_read = S_IRGRP; -static mode_t mode_group_write = S_IWGRP; -static mode_t mode_group_execute = S_IXGRP; -static mode_t mode_world_read = S_IROTH; -static mode_t mode_world_write = S_IWOTH; -static mode_t mode_world_execute = S_IXOTH; -static mode_t mode_setuid = S_ISUID; -static mode_t mode_setgid = S_ISGID; -#endif +using namespace cmFSPermissions; #if defined(_WIN32) // libcurl doesn't support file:// urls for unicode filenames on Windows. @@ -1099,29 +1075,7 @@ protected: // Translate an argument to a permissions bit. bool CheckPermissions(std::string const& arg, mode_t& permissions) { - if (arg == "OWNER_READ") { - permissions |= mode_owner_read; - } else if (arg == "OWNER_WRITE") { - permissions |= mode_owner_write; - } else if (arg == "OWNER_EXECUTE") { - permissions |= mode_owner_execute; - } else if (arg == "GROUP_READ") { - permissions |= mode_group_read; - } else if (arg == "GROUP_WRITE") { - permissions |= mode_group_write; - } else if (arg == "GROUP_EXECUTE") { - permissions |= mode_group_execute; - } else if (arg == "WORLD_READ") { - permissions |= mode_world_read; - } else if (arg == "WORLD_WRITE") { - permissions |= mode_world_write; - } else if (arg == "WORLD_EXECUTE") { - permissions |= mode_world_execute; - } else if (arg == "SETUID") { - permissions |= mode_setuid; - } else if (arg == "SETGID") { - permissions |= mode_setgid; - } else { + if (!cmFSPermissions::stringToModeT(arg, permissions)) { std::ostringstream e; e << this->Name << " given invalid permission \"" << arg << "\"."; this->FileCommand->SetError(e.str()); @@ -2015,9 +1969,30 @@ bool cmFileInstaller::HandleInstallDestination() this->DestDirLength = int(sdestdir.size()); } + // check if default dir creation permissions were set + mode_t default_dir_mode_v = 0; + mode_t* default_dir_mode = nullptr; + const char* default_dir_install_permissions = this->Makefile->GetDefinition( + "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); + if (default_dir_install_permissions && *default_dir_install_permissions) { + std::vector<std::string> items; + cmSystemTools::ExpandListArgument(default_dir_install_permissions, items); + for (const auto& arg : items) { + if (!this->CheckPermissions(arg, default_dir_mode_v)) { + std::ostringstream e; + e << this->FileCommand->GetError() + << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable."; + this->FileCommand->SetError(e.str()); + return false; + } + } + + default_dir_mode = &default_dir_mode_v; + } + if (this->InstallType != cmInstallType_DIRECTORY) { if (!cmSystemTools::FileExists(destination.c_str())) { - if (!cmSystemTools::MakeDirectory(destination.c_str())) { + if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) { std::string errstring = "cannot create directory: " + destination + ". Maybe need administrative privileges."; this->FileCommand->SetError(errstring); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 12c0cfd..c8d94c0 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -222,7 +222,14 @@ void cmLocalGenerator::TraceDependencies() void cmLocalGenerator::GenerateTestFiles() { + std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary(); + file += "/"; + file += "CTestTestfile.cmake"; + if (!this->Makefile->IsOn("CMAKE_TESTING_ENABLED")) { + if (cmSystemTools::FileExists(file)) { + cmSystemTools::RemoveFile(file); + } return; } @@ -231,10 +238,6 @@ void cmLocalGenerator::GenerateTestFiles() const std::string& config = this->Makefile->GetConfigurations(configurationTypes, false); - std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary(); - file += "/"; - file += "CTestTestfile.cmake"; - cmGeneratedFileStream fout(file.c_str()); fout.SetCopyIfDifferent(true); @@ -484,6 +487,20 @@ void cmLocalGenerator::GenerateInstallRules() /* clang-format on */ } + // Write default directory permissions. + if (const char* defaultDirPermissions = this->Makefile->GetDefinition( + "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS")) { + /* clang-format off */ + fout << + "# Set default install directory permissions.\n" + "if(NOT DEFINED CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS)\n" + " set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS \"" + << defaultDirPermissions << "\")\n" + "endif()\n" + "\n"; + /* clang-format on */ + } + // Ask each install generator to write its code. std::vector<cmInstallGenerator*> const& installers = this->Makefile->GetInstallGenerators(); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index e4ec469..4109b90 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3319,6 +3319,13 @@ cmGlobalGenerator* cmMakefile::GetGlobalGenerator() const return this->GlobalGenerator; } +void cmMakefile::GetTestNames(std::vector<std::string>& testNames) +{ + for (const auto& iter : Tests) { + testNames.push_back(iter.first); + } +} + #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* cmMakefile::GetVariableWatch() const { diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index bc8c2d1..6867c02 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -617,6 +617,11 @@ public: cmGlobalGenerator* GetGlobalGenerator() const; /** + * Get all the test names this makefile knows about + */ + void GetTestNames(std::vector<std::string>& testNames); + + /** * Get all the source files this makefile knows about */ const std::vector<cmSourceFile*>& GetSourceFiles() const diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h index 03f1cc1..8cd5e14 100644 --- a/Source/cmServerDictionary.h +++ b/Source/cmServerDictionary.h @@ -23,6 +23,7 @@ static const std::string kPROGRESS_TYPE = "progress"; static const std::string kREPLY_TYPE = "reply"; static const std::string kSET_GLOBAL_SETTINGS_TYPE = "setGlobalSettings"; static const std::string kSIGNAL_TYPE = "signal"; +static const std::string kCTEST_INFO_TYPE = "ctestInfo"; static const std::string kARTIFACTS_KEY = "artifacts"; static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory"; @@ -90,6 +91,11 @@ static const std::string kWATCHED_DIRECTORIES_KEY = "watchedDirectories"; static const std::string kWATCHED_FILES_KEY = "watchedFiles"; static const std::string kHAS_INSTALL_RULE = "hasInstallRule"; static const std::string kINSTALL_PATHS = "installPaths"; +static const std::string kHAS_ENABLED_TESTS = "hasEnabledTests"; +static const std::string kCTEST_NAME = "ctestName"; +static const std::string kCTEST_COMMAND = "ctestCommand"; +static const std::string kCTEST_INFO = "ctestInfo"; +static const std::string kMINIMUM_CMAKE_VERSION = "minimumCMakeVersion"; static const std::string kTARGET_CROSS_REFERENCES_KEY = "crossReferences"; static const std::string kLINE_NUMBER_KEY = "line"; diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index fc06fed..07df488 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -14,6 +14,7 @@ #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmServer.h" #include "cmServerDictionary.h" #include "cmSourceFile.h" @@ -23,6 +24,7 @@ #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmTest.h" #include "cm_uv.h" #include "cmake.h" @@ -479,6 +481,9 @@ const cmServerResponse cmServerProtocol1::Process( if (request.Type == kSET_GLOBAL_SETTINGS_TYPE) { return this->ProcessSetGlobalSettings(request); } + if (request.Type == kCTEST_INFO_TYPE) { + return this->ProcessCTests(request); + } return request.ReportError("Unknown command!"); } @@ -766,6 +771,153 @@ static void DumpBacktraceRange(Json::Value& result, const std::string& type, } } +static Json::Value DumpCTestInfo(const std::string& name, cmTest* testInfo) +{ + Json::Value result = Json::objectValue; + result[kCTEST_NAME] = name; + + // Concat command entries together. After the first should be the arguments + // for the command + std::string command; + for (auto const& cmd : testInfo->GetCommand()) { + command.append(cmd); + command.append(" "); + } + result[kCTEST_COMMAND] = command; + + // Build up the list of properties that may have been specified + Json::Value properties = Json::arrayValue; + for (auto& prop : testInfo->GetProperties()) { + Json::Value entry = Json::objectValue; + entry[kKEY_KEY] = prop.first; + entry[kVALUE_KEY] = prop.second.GetValue(); + properties.append(entry); + } + result[kPROPERTIES_KEY] = properties; + + // Need backtrace to figure out where this test was originally added + result[kBACKTRACE_KEY] = DumpBacktrace(testInfo->GetBacktrace()); + + return result; +} + +static Json::Value DumpCTestTarget(cmGeneratorTarget* target, + const std::string& config) +{ + cmLocalGenerator* lg = target->GetLocalGenerator(); + const cmState* state = lg->GetState(); + + const cmStateEnums::TargetType type = target->GetType(); + const std::string typeName = state->GetTargetTypeName(type); + + Json::Value ttl = Json::arrayValue; + ttl.append("EXECUTABLE"); + ttl.append("STATIC_LIBRARY"); + ttl.append("SHARED_LIBRARY"); + ttl.append("MODULE_LIBRARY"); + ttl.append("OBJECT_LIBRARY"); + ttl.append("UTILITY"); + ttl.append("INTERFACE_LIBRARY"); + + if (!hasString(ttl, typeName) || target->IsImported()) { + return Json::Value(); + } + + Json::Value result = Json::objectValue; + result[kNAME_KEY] = target->GetName(); + result[kTYPE_KEY] = typeName; + + if (type == cmStateEnums::INTERFACE_LIBRARY) { + return result; + } + result[kFULL_NAME_KEY] = target->GetFullName(config); + + if (target->Makefile->IsOn("CMAKE_TESTING_ENABLED")) { + result[kHAS_ENABLED_TESTS] = true; + std::vector<std::string> CTestNames; + + Json::Value testInfo = Json::arrayValue; + std::vector<std::string> testNames; + target->Makefile->GetTestNames(testNames); + for (auto& name : testNames) { + auto test = target->Makefile->GetTest(name); + if (test != nullptr) { + testInfo.append(DumpCTestInfo(name, test)); + } + } + result[kCTEST_INFO] = testInfo; + } + + return result; +} + +static Json::Value DumpCTestTargetsList( + const std::vector<cmLocalGenerator*>& generators, const std::string& config) +{ + Json::Value result = Json::arrayValue; + + std::vector<cmGeneratorTarget*> targetList; + for (const auto& lgIt : generators) { + auto list = lgIt->GetGeneratorTargets(); + targetList.insert(targetList.end(), list.begin(), list.end()); + } + std::sort(targetList.begin(), targetList.end()); + + for (cmGeneratorTarget* target : targetList) { + Json::Value tmp = DumpCTestTarget(target, config); + if (!tmp.isNull()) { + result.append(tmp); + } + } + + return result; +} + +static Json::Value DumpCTestProjectList(const cmake* cm, + std::string const& config) +{ + Json::Value result = Json::arrayValue; + + auto globalGen = cm->GetGlobalGenerator(); + + for (const auto& projectIt : globalGen->GetProjectMap()) { + Json::Value pObj = Json::objectValue; + pObj[kNAME_KEY] = projectIt.first; + + // All Projects must have at least one local generator + assert(!projectIt.second.empty()); + + // Project structure information: + pObj[kTARGETS_KEY] = DumpCTestTargetsList(projectIt.second, config); + + result.append(pObj); + } + + return result; +} + +static Json::Value DumpCTestConfiguration(const cmake* cm, + const std::string& config) +{ + Json::Value result = Json::objectValue; + result[kNAME_KEY] = config; + + result[kPROJECTS_KEY] = DumpCTestProjectList(cm, config); + + return result; +} + +static Json::Value DumpCTestConfigurationsList(const cmake* cm) +{ + Json::Value result = Json::arrayValue; + + for (const std::string& c : getConfigurations(cm)) { + result.append(DumpCTestConfiguration(cm, c)); + } + + return result; +} + static Json::Value DumpTarget(cmGeneratorTarget* target, const std::string& config) { @@ -964,6 +1116,8 @@ static Json::Value DumpProjectList(const cmake* cm, std::string const& config) // Project structure information: const cmMakefile* mf = lg->GetMakefile(); + pObj[kMINIMUM_CMAKE_VERSION] = + mf->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"); pObj[kHAS_INSTALL_RULE] = mf->GetInstallGenerators().empty() == false; pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory(); pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory(); @@ -1222,6 +1376,19 @@ cmServerResponse cmServerProtocol1::ProcessFileSystemWatchers( return request.Reply(result); } +cmServerResponse cmServerProtocol1::ProcessCTests( + const cmServerRequest& request) +{ + if (this->m_State < STATE_COMPUTED) { + return request.ReportError("This instance was not yet computed."); + } + + Json::Value result = Json::objectValue; + result[kCONFIGURATIONS_KEY] = + DumpCTestConfigurationsList(this->CMakeInstance()); + return request.Reply(result); +} + cmServerProtocol1::GeneratorInformation::GeneratorInformation( const std::string& generatorName, const std::string& extraGeneratorName, const std::string& toolset, const std::string& platform, diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h index 124ac7f..df71cff 100644 --- a/Source/cmServerProtocol.h +++ b/Source/cmServerProtocol.h @@ -123,6 +123,7 @@ private: cmServerResponse ProcessGlobalSettings(const cmServerRequest& request); cmServerResponse ProcessSetGlobalSettings(const cmServerRequest& request); cmServerResponse ProcessFileSystemWatchers(const cmServerRequest& request); + cmServerResponse ProcessCTests(const cmServerRequest& request); enum State { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index c6cd502..9cf835c 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -884,6 +884,13 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } + if (prop == "IMPORTED_GLOBAL" && !this->IsImported()) { + std::ostringstream e; + e << "IMPORTED_GLOBAL property can't be set on non-imported targets (\"" + << this->Name << "\")\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } if (prop == "INCLUDE_DIRECTORIES") { this->Internal->IncludeDirectoriesEntries.clear(); @@ -933,6 +940,19 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->SourceEntries.push_back(value); this->Internal->SourceBacktraces.push_back(lfbt); } + } else if (prop == "IMPORTED_GLOBAL") { + if (!cmSystemTools::IsOn(value)) { + std::ostringstream e; + e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\"" + << this->Name << "\")\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + /* no need to change anything if value does not change */ + if (!this->ImportedGloballyVisible) { + this->ImportedGloballyVisible = true; + this->GetGlobalGenerator()->IndexTarget(this); + } } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") && !this->CheckImportedLibName(prop, value ? value : "")) { /* error was reported by check method */ @@ -977,6 +997,14 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } + if (prop == "IMPORTED_GLOBAL") { + std::ostringstream e; + e << "IMPORTED_GLOBAL property can't be appended, only set on imported " + "targets (\"" + << this->Name << "\")\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } if (prop == "INCLUDE_DIRECTORIES") { if (value && *value) { this->Internal->IncludeDirectoriesEntries.push_back(value); @@ -1143,6 +1171,21 @@ static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value, context->IssueMessage(cmake::FATAL_ERROR, e.str()); } +static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target, + cmMakefile* context) +{ + std::vector<cmTarget*> targets = context->GetOwnedImportedTargets(); + std::vector<cmTarget*>::const_iterator it = + std::find(targets.begin(), targets.end(), target); + if (it == targets.end()) { + std::ostringstream e; + e << "Attempt to promote imported target \"" << target->GetName() + << "\" to global scope (by setting IMPORTED_GLOBAL) " + "which is not built in this directory."; + context->IssueMessage(cmake::FATAL_ERROR, e.str()); + } +} + void cmTarget::CheckProperty(const std::string& prop, cmMakefile* context) const { @@ -1157,11 +1200,16 @@ void cmTarget::CheckProperty(const std::string& prop, cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true); } } - if (cmHasLiteralPrefix(prop, "INTERFACE_LINK_LIBRARIES")) { + if (prop == "INTERFACE_LINK_LIBRARIES") { if (const char* value = this->GetProperty(prop)) { cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context); } } + if (prop == "IMPORTED_GLOBAL") { + if (this->IsImported()) { + cmTargetCheckIMPORTED_GLOBAL(this, context); + } + } } const char* cmTarget::GetComputedProperty( @@ -1182,6 +1230,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const MAKE_STATIC_PROP(COMPILE_OPTIONS); MAKE_STATIC_PROP(COMPILE_DEFINITIONS); MAKE_STATIC_PROP(IMPORTED); + MAKE_STATIC_PROP(IMPORTED_GLOBAL); MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES); MAKE_STATIC_PROP(NAME); MAKE_STATIC_PROP(BINARY_DIR); @@ -1196,6 +1245,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const specialProps.insert(propCOMPILE_OPTIONS); specialProps.insert(propCOMPILE_DEFINITIONS); specialProps.insert(propIMPORTED); + specialProps.insert(propIMPORTED_GLOBAL); specialProps.insert(propMANUALLY_ADDED_DEPENDENCIES); specialProps.insert(propNAME); specialProps.insert(propBINARY_DIR); @@ -1264,6 +1314,9 @@ const char* cmTarget::GetProperty(const std::string& prop) const if (prop == propIMPORTED) { return this->IsImported() ? "TRUE" : "FALSE"; } + if (prop == propIMPORTED_GLOBAL) { + return this->IsImportedGloballyVisible() ? "TRUE" : "FALSE"; + } if (prop == propNAME) { return this->GetName().c_str(); } diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx index 1d2520d..ed9026e 100644 --- a/Source/cmTargetPropertyComputer.cxx +++ b/Source/cmTargetPropertyComputer.cxx @@ -57,6 +57,7 @@ bool cmTargetPropertyComputer::WhiteListedInterfaceProperty( builtIns.insert("COMPATIBLE_INTERFACE_STRING"); builtIns.insert("EXPORT_NAME"); builtIns.insert("IMPORTED"); + builtIns.insert("IMPORTED_GLOBAL"); builtIns.insert("NAME"); builtIns.insert("TYPE"); } diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 1aadf67..6486c8b 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1689,12 +1689,8 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) } else if (ext == "natvis") { tool = "Natvis"; } else if (ext == "settings") { - // remove path to current source dir (if files are in current source dir) - if (!sourceLink.empty()) { - settingsLastGenOutput = sourceLink; - } else { - settingsLastGenOutput = sf->GetFullPath(); - } + settingsLastGenOutput = + cmsys::SystemTools::GetFilenameName(sf->GetFullPath()); std::size_t pos = settingsLastGenOutput.find(".settings"); settingsLastGenOutput.replace(pos, 9, ".Designer.cs"); settingsGenerator = "SettingsSingleFileGenerator"; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index ef75b01..449db9d 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1577,9 +1577,11 @@ std::ostream& operator<<(std::ostream& stream, stream.flags(flags); return stream; } + static bool RunCommand(const char* comment, std::vector<std::string>& command, bool verbose, NumberFormat exitFormat, - int* retCodeOut = nullptr) + int* retCodeOut = nullptr, + bool (*retCodeOkay)(int) = nullptr) { if (verbose) { std::cout << comment << ":\n"; @@ -1589,18 +1591,17 @@ static bool RunCommand(const char* comment, std::vector<std::string>& command, int retCode = 0; bool commandResult = cmSystemTools::RunSingleCommand( command, &output, &output, &retCode, nullptr, cmSystemTools::OUTPUT_NONE); - bool returnValue; + bool const retCodeSuccess = + retCode == 0 || (retCodeOkay && retCodeOkay(retCode)); + bool const success = commandResult && retCodeSuccess; if (retCodeOut) { - if (!commandResult) { - *retCodeOut = (retCode == 0) ? -1 : retCode; - } else { + if (commandResult || !retCodeSuccess) { *retCodeOut = retCode; + } else { + *retCodeOut = -1; } - returnValue = true; // always return true if retCodeOut is requested - } else { - returnValue = commandResult && (retCode == 0); } - if (!commandResult || retCode) { + if (!success) { std::cout << comment << ": command \"" << cmJoin(command, " ") << "\" failed (exit code " << NumberFormatter(exitFormat, retCode) @@ -1613,7 +1614,7 @@ static bool RunCommand(const char* comment, std::vector<std::string>& command, std::cout << output; } } - return returnValue; + return success; } bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg, @@ -1711,6 +1712,13 @@ int cmVSLink::Link() return LinkNonIncremental(); } +static bool mtRetIsUpdate(int mtRet) +{ + // 'mt /notify_update' returns a special value (differing between + // Windows and POSIX hosts) when it updated the manifest file. + return mtRet == 0x41020001 || mtRet == 0xbb; +} + int cmVSLink::LinkIncremental() { // This follows the steps listed here: @@ -1782,9 +1790,9 @@ int cmVSLink::LinkIncremental() // Run the manifest tool to create the final manifest. int mtRet = this->RunMT("/out:" + this->ManifestFile, true); - // If mt returns 1090650113 (or 187 on a posix host) then it updated the - // manifest file so we need to embed it again. Otherwise we are done. - if (mtRet != 1090650113 && mtRet != 187) { + // If mt returns a special value then it updated the manifest file so + // we need to embed it again. Otherwise we are done. + if (!mtRetIsUpdate(mtRet)) { return mtRet; } @@ -1837,7 +1845,8 @@ int cmVSLink::RunMT(std::string const& out, bool notify) mtCommand.push_back("/notify_update"); } int mtRet = 0; - if (!RunCommand("MT", mtCommand, this->Verbose, FORMAT_HEX, &mtRet)) { + if (!RunCommand("MT", mtCommand, this->Verbose, FORMAT_HEX, &mtRet, + mtRetIsUpdate)) { return -1; } return mtRet; diff --git a/Source/ctest.cxx b/Source/ctest.cxx index f6466fa..ad5fec0 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -104,8 +104,6 @@ static const char* cmDocumentationOptions[][2] = { { "--test-timeout", "The time limit in seconds, internal use only." }, { "--test-load", "CPU load threshold for starting new parallel tests." }, { "--tomorrow-tag", "Nightly or experimental starts with next day tag." }, - { "--ctest-config", "The configuration file used to initialize CTest state " - "when submitting dashboards." }, { "--overwrite", "Overwrite CTest configuration option." }, { "--extra-submit <file>[;<file>]", "Submit extra files to the dashboard." }, { "--force-new-ctest-process", diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index e4406e7..51f4088 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -1150,17 +1150,17 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) SET(testProcess_COMPILE_FLAGS "") # Some Apple compilers produce bad optimizations in this source. IF(APPLE AND CMAKE_C_COMPILER_ID MATCHES "^(GNU|LLVM)$") - STRING(APPEND testProcess_COMPILE_FLAGS " -O0") + SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -O0") ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "XL" AND NOT (CMAKE_SYSTEM MATCHES "Linux.*ppc64le" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "13.1.1")) # Tell IBM XL not to warn about our test infinite loop # v13.1.1 and newer on Linux ppc64le is clang based and does not accept # the -qsuppress option - STRING(APPEND testProcess_COMPILE_FLAGS " -qsuppress=1500-010") + SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -qsuppress=1500-010") ENDIF() IF(CMAKE_C_FLAGS MATCHES "-fsanitize=") - STRING(APPEND testProcess_COMPILE_FLAGS " -DCRASH_USING_ABORT") + SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -DCRASH_USING_ABORT") ENDIF() SET_PROPERTY(SOURCE testProcess.c PROPERTY COMPILE_FLAGS "${testProcess_COMPILE_FLAGS}") diff --git a/Source/kwsys/DynamicLoader.hxx.in b/Source/kwsys/DynamicLoader.hxx.in index 7e71a45..dc34692 100644 --- a/Source/kwsys/DynamicLoader.hxx.in +++ b/Source/kwsys/DynamicLoader.hxx.in @@ -35,7 +35,7 @@ namespace @KWSYS_NAMESPACE@ { * or absolute) pathname. Otherwise, the dynamic linker searches for the * library as follows : see ld.so(8) for further details): * Whereas this distinction does not exist on Win32. Therefore ideally you - * should be doing full path to garantee to have a consistent way of dealing + * should be doing full path to guarantee to have a consistent way of dealing * with dynamic loading of shared library. * * \warning the Cygwin implementation do not use the Win32 HMODULE. Put extra @@ -72,7 +72,7 @@ public: static LibraryHandle OpenLibrary(const std::string&); /** Attempt to detach a dynamic library from the - * process. A value of true is returned if it is sucessful. */ + * process. A value of true is returned if it is successful. */ static int CloseLibrary(LibraryHandle); /** Find the address of the symbol in the given library. */ diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in index 6cb9443..daf334a 100644 --- a/Source/kwsys/Process.h.in +++ b/Source/kwsys/Process.h.in @@ -421,7 +421,7 @@ enum kwsysProcess_Pipes_e /** * Block until the child process terminates or the given timeout - * expires. If no process is running, returns immediatly. The + * expires. If no process is running, returns immediately. The * argument is: * * timeout = Specifies the maximum time this call may block. Upon diff --git a/Source/kwsys/RegularExpression.hxx.in b/Source/kwsys/RegularExpression.hxx.in index 606e3da..763fdab 100644 --- a/Source/kwsys/RegularExpression.hxx.in +++ b/Source/kwsys/RegularExpression.hxx.in @@ -109,12 +109,12 @@ namespace @KWSYS_NAMESPACE@ { * object as an argument and creates an object initialized with the * information from the given RegularExpression object. * - * The find member function finds the first occurence of the regualr + * The find member function finds the first occurrence of the regular * expression of that object in the string given to find as an argument. Find * returns a boolean, and if true, mutates the private data appropriately. * Find sets pointers to the beginning and end of the thing last found, they * are pointers into the actual string that was searched. The start and end - * member functions return indicies into the searched string that correspond + * member functions return indices into the searched string that correspond * to the beginning and end pointers respectively. The compile member * function takes a char* and puts the compiled version of the char* argument * into the object's private data fields. The == and != operators only check diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index 366fe30..ab1f40a 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -3633,7 +3633,7 @@ SystemInformationImplementation::GetHostMemoryAvailable( // apply resource limits across groups of processes. // this is of use on certain SMP systems (eg. SGI UV) // where the host has a large amount of ram but a given user's - // access to it is severly restricted. The system will + // access to it is severely restricted. The system will // apply a limit across a set of processes. Units are in KiB. if (hostLimitEnvVarName) { const char* hostLimitEnvVarValue = getenv(hostLimitEnvVarName); diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in index 516c505..5678e8a 100644 --- a/Source/kwsys/SystemInformation.hxx.in +++ b/Source/kwsys/SystemInformation.hxx.in @@ -124,7 +124,7 @@ public: // are the processes comprising an mpi program which is running in // parallel. The amount of memory reported may differ from the host // total if a host wide resource limit is applied. Such reource limits - // are reported to us via an applicaiton specified environment variable. + // are reported to us via an application specified environment variable. LongLong GetHostMemoryAvailable(const char* hostLimitEnvVarName = NULL); // Get total system RAM in units of KiB available to this process. diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 72babc3..50aa857 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -27,6 +27,7 @@ #include <iostream> #include <set> #include <sstream> +#include <utility> #include <vector> // Work-around CMake dependency scanning limitation. This must @@ -1691,7 +1692,7 @@ bool SystemTools::StringEndsWith(const std::string& str1, const char* str2) : false; } -// Returns a pointer to the last occurence of str2 in str1 +// Returns a pointer to the last occurrence of str2 in str1 const char* SystemTools::FindLastString(const char* str1, const char* str2) { if (!str1 || !str2) { @@ -3372,7 +3373,7 @@ std::string SystemTools::RelativePath(const std::string& local, } #ifdef _WIN32 -static std::string GetCasePathName(std::string const& pathIn) +static std::pair<std::string, bool> GetCasePathName(std::string const& pathIn) { std::string casePath; std::vector<std::string> path_components; @@ -3381,7 +3382,7 @@ static std::string GetCasePathName(std::string const& pathIn) { // Relative paths cannot be converted. casePath = pathIn; - return casePath; + return std::make_pair(casePath, false); } // Start with root component. @@ -3433,7 +3434,7 @@ static std::string GetCasePathName(std::string const& pathIn) casePath += path_components[idx]; } - return casePath; + return std::make_pair(casePath, converting); } #endif @@ -3448,12 +3449,14 @@ std::string SystemTools::GetActualCaseForPath(const std::string& p) if (i != SystemTools::PathCaseMap->end()) { return i->second; } - std::string casePath = GetCasePathName(p); - if (casePath.size() > MAX_PATH) { - return casePath; + std::pair<std::string, bool> casePath = GetCasePathName(p); + if (casePath.first.size() > MAX_PATH) { + return casePath.first; } - (*SystemTools::PathCaseMap)[p] = casePath; - return casePath; + if (casePath.second) { + (*SystemTools::PathCaseMap)[p] = casePath.first; + } + return casePath.first; #endif } diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index 3d109a8..8a02b75 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -107,7 +107,7 @@ public: } /** - * Replace replace all occurences of the string in the source string. + * Replace replace all occurrences of the string in the source string. */ static void ReplaceString(std::string& source, const char* replace, const char* with); @@ -175,7 +175,7 @@ public: static bool StringEndsWith(const std::string& str1, const char* str2); /** - * Returns a pointer to the last occurence of str2 in str1 + * Returns a pointer to the last occurrence of str2 in str1 */ static const char* FindLastString(const char* str1, const char* str2); @@ -905,7 +905,7 @@ public: /** * Delay the execution for a specified amount of time specified - * in miliseconds + * in milliseconds */ static void Delay(unsigned int msec); diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx index e67d436..f1f9ed3 100644 --- a/Source/kwsys/kwsysPlatformTestsCXX.cxx +++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx @@ -281,7 +281,7 @@ int main() #ifdef TEST_KWSYS_CXX_HAS_BACKTRACE #if defined(__PATHSCALE__) || defined(__PATHCC__) || \ (defined(__LSB_VERSION__) && (__LSB_VERSION__ < 41)) -backtrace doesnt work with this compiler or os +backtrace does not work with this compiler or os #endif #if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) #define _GNU_SOURCE |