diff options
Diffstat (limited to 'Source')
81 files changed, 2082 insertions, 863 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 278d4df..ca063d5 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -266,7 +266,7 @@ IF(UNIX) SET(SRCS ${SRCS} cmGlobalKdevelopGenerator.cxx) ENDIF(UNIX) -# XCode only works on apple +# Xcode only works on Apple IF(APPLE) SET(SRCS ${SRCS} cmXCodeObject.cxx @@ -394,6 +394,8 @@ SET(CTEST_SRCS cmCTest.cxx CTest/cmCTestTestHandler.cxx CTest/cmCTestUpdateCommand.cxx CTest/cmCTestUpdateHandler.cxx + CTest/cmCTestUploadCommand.cxx + CTest/cmCTestUploadHandler.cxx CTest/cmCTestVC.cxx CTest/cmCTestVC.h diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index b629c63..0ce5b01 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -207,7 +207,7 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup) } //---------------------------------------------------------------------- -int cmCPackArchiveGenerator::PackageComponentsAllInOne(bool allComponent) +int cmCPackArchiveGenerator::PackageComponentsAllInOne() { // reset the package file names packageFileNames.clear(); @@ -221,38 +221,15 @@ int cmCPackArchiveGenerator::PackageComponentsAllInOne(bool allComponent) << std::endl); DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0],archive); - // The ALL GROUP in ONE package case - if (! allComponent) { - // iterate over the component groups - std::map<std::string, cmCPackComponentGroup>::iterator compGIt; - for (compGIt=this->ComponentGroups.begin(); - compGIt!=this->ComponentGroups.end(); ++compGIt) - { - cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: " - << compGIt->first - << std::endl); - // now iterate over the component of this group - std::vector<cmCPackComponent*>::iterator compIt; - for (compIt=(compGIt->second).Components.begin(); - compIt!=(compGIt->second).Components.end(); - ++compIt) - { - // Add the files of this component to the archive - addOneComponentToArchive(archive,*compIt); - } - } - } - // The ALL COMPONENT in ONE package case - else + // The ALL COMPONENTS in ONE package case + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt=this->Components.begin();compIt!=this->Components.end(); + ++compIt ) { - std::map<std::string, cmCPackComponent>::iterator compIt; - for (compIt=this->Components.begin();compIt!=this->Components.end(); - ++compIt ) - { - // Add the files of this component to the archive - addOneComponentToArchive(archive,&(compIt->second)); - } + // Add the files of this component to the archive + addOneComponentToArchive(archive,&(compIt->second)); } + // archive goes out of scope so it will finalized and closed. return 1; } @@ -265,21 +242,20 @@ int cmCPackArchiveGenerator::PackageFiles() if (SupportsComponentInstallation()) { // CASE 1 : COMPONENT ALL-IN-ONE package - // If ALL GROUPS or ALL COMPONENTS in ONE package has been requested + // If ALL COMPONENTS in ONE package has been requested // then the package file is unique and should be open here. - if (allComponentInOne || - (allGroupInOne && (!this->ComponentGroups.empty())) - ) + if (componentPackageMethod == ONE_PACKAGE) { - return PackageComponentsAllInOne(allComponentInOne); + return PackageComponentsAllInOne(); } // CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one) // There will be 1 package for each component group // however one may require to ignore component group and // in this case you'll get 1 package for each component. - else if ((!this->ComponentGroups.empty()) || (ignoreComponentGroup)) + else { - return PackageComponents(ignoreComponentGroup); + return PackageComponents(componentPackageMethod == + ONE_PACKAGE_PER_COMPONENT); } } diff --git a/Source/CPack/cmCPackArchiveGenerator.h b/Source/CPack/cmCPackArchiveGenerator.h index dc17257..b1bbb83 100644 --- a/Source/CPack/cmCPackArchiveGenerator.h +++ b/Source/CPack/cmCPackArchiveGenerator.h @@ -65,7 +65,7 @@ protected: * Special case of component install where all * components will be put in a single installer. */ - int PackageComponentsAllInOne(bool allComponent); + int PackageComponentsAllInOne(); virtual const char* GetOutputExtension() = 0; cmArchiveWrite::Compress Compress; cmArchiveWrite::Type Archive; diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx index 06a0509..af78e78 100644 --- a/Source/CPack/cmCPackBundleGenerator.cxx +++ b/Source/CPack/cmCPackBundleGenerator.cxx @@ -165,5 +165,10 @@ int cmCPackBundleGenerator::PackageFiles() cmSystemTools::SetPermissions(command_target.str().c_str(), 0777); } - return this->CreateDMG(); + return this->CreateDMG(toplevel, packageFileNames[0]); +} + +bool cmCPackBundleGenerator::SupportsComponentInstallation() const +{ + return false; } diff --git a/Source/CPack/cmCPackBundleGenerator.h b/Source/CPack/cmCPackBundleGenerator.h index 82814b0..ed0187d 100644 --- a/Source/CPack/cmCPackBundleGenerator.h +++ b/Source/CPack/cmCPackBundleGenerator.h @@ -32,6 +32,7 @@ protected: virtual int InitializeInternal(); virtual const char* GetPackagingInstallPrefix(); int PackageFiles(); + bool SupportsComponentInstallation() const; std::string InstallPrefix; }; diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index ca2185c..8c19bbd 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -51,6 +51,62 @@ int cmCPackDebGenerator::InitializeInternal() } //---------------------------------------------------------------------- +int cmCPackDebGenerator::PackageOnePack(std::string initialTopLevel, + std::string packageName) + { + int retval = 1; + // Begin the archive for this pack + std::string localToplevel(initialTopLevel); + std::string packageFileName( + cmSystemTools::GetParentDirectory(toplevel.c_str()) + ); + std::string outputFileName( + std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) + +"-"+packageName + this->GetOutputExtension() + ); + + localToplevel += "/"+ packageName; + /* replace the TEMP DIRECTORY with the component one */ + this->SetOption("CPACK_TEMPORARY_DIRECTORY",localToplevel.c_str()); + packageFileName += "/"+ outputFileName; + /* replace proposed CPACK_OUTPUT_FILE_NAME */ + this->SetOption("CPACK_OUTPUT_FILE_NAME",outputFileName.c_str()); + /* replace the TEMPORARY package file name */ + this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", + packageFileName.c_str()); + // Tell CPackDeb.cmake the name of the component GROUP. + this->SetOption("CPACK_DEB_PACKAGE_COMPONENT",packageName.c_str()); + if (!this->ReadListFile("CPackDeb.cmake")) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error while execution CPackDeb.cmake" << std::endl); + retval = 0; + return retval; + } + + cmsys::Glob gl; + std::string findExpr(this->GetOption("WDIR")); + findExpr += "/*"; + gl.RecurseOn(); + if ( !gl.FindFiles(findExpr) ) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot find any files in the installed directory" << std::endl); + return 0; + } + packageFiles = gl.GetFiles(); + + int res = createDeb(); + if (res != 1) + { + retval = 0; + } + // add the generated package to package file names list + packageFileNames.push_back(packageFileName); + return retval; +} + +//---------------------------------------------------------------------- int cmCPackDebGenerator::PackageComponents(bool ignoreGroup) { int retval = 1; @@ -71,53 +127,24 @@ int cmCPackDebGenerator::PackageComponents(bool ignoreGroup) << compGIt->first << std::endl); // Begin the archive for this group - std::string localToplevel(initialTopLevel); - std::string packageFileName( - cmSystemTools::GetParentDirectory(toplevel.c_str()) - ); - std::string outputFileName( - std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) - +"-"+compGIt->first + this->GetOutputExtension() - ); - - localToplevel += "/"+ compGIt->first; - /* replace the TEMP DIRECTORY with the component one */ - this->SetOption("CPACK_TEMPORARY_DIRECTORY",localToplevel.c_str()); - packageFileName += "/"+ outputFileName; - /* replace proposed CPACK_OUTPUT_FILE_NAME */ - this->SetOption("CPACK_OUTPUT_FILE_NAME",outputFileName.c_str()); - /* replace the TEMPORARY package file name */ - this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", - packageFileName.c_str()); - // Tell CPackDeb.cmake the name of the component GROUP. - this->SetOption("CPACK_DEB_PACKAGE_COMPONENT",compGIt->first.c_str()); - if (!this->ReadListFile("CPackDeb.cmake")) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error while execution CPackDeb.cmake" << std::endl); - retval = 0; - return retval; - } - - cmsys::Glob gl; - std::string findExpr(this->GetOption("WDIR")); - findExpr += "/*"; - gl.RecurseOn(); - if ( !gl.FindFiles(findExpr) ) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find any files in the installed directory" << std::endl); - return 0; - } - packageFiles = gl.GetFiles(); - - int res = createDeb(); - if (res != 1) + retval &= PackageOnePack(initialTopLevel,compGIt->first); + } + // Handle Orphan components (components not belonging to any groups) + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt=this->Components.begin(); + compIt!=this->Components.end(); ++compIt ) + { + // Does the component belong to a group? + if (compIt->second.Group==NULL) { - retval = 0; + cmCPackLogger(cmCPackLog::LOG_VERBOSE, + "Component <" + << compIt->second.Name + << "> does not belong to any group, package it separately." + << std::endl); + // Begin the archive for this orphan component + retval &= PackageOnePack(initialTopLevel,compIt->first); } - // add the generated package to package file names list - packageFileNames.push_back(packageFileName); } } // CPACK_COMPONENTS_IGNORE_GROUPS is set @@ -128,59 +155,14 @@ int cmCPackDebGenerator::PackageComponents(bool ignoreGroup) for (compIt=this->Components.begin(); compIt!=this->Components.end(); ++compIt ) { - std::string localToplevel(initialTopLevel); - std::string packageFileName( - cmSystemTools::GetParentDirectory(toplevel.c_str()) - ); - std::string outputFileName( - std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME") - ) - +"-"+compIt->first + this->GetOutputExtension()); - - localToplevel += "/"+ compIt->first; - /* replace the TEMP DIRECTORY with the component one */ - this->SetOption("CPACK_TEMPORARY_DIRECTORY",localToplevel.c_str()); - packageFileName += "/"+ outputFileName; - /* replace proposed CPACK_OUTPUT_FILE_NAME */ - this->SetOption("CPACK_OUTPUT_FILE_NAME",outputFileName.c_str()); - /* replace the TEMPORARY package file name */ - this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", - packageFileName.c_str()); - - this->SetOption("CPACK_DEB_PACKAGE_COMPONENT",compIt->first.c_str()); - if (!this->ReadListFile("CPackDeb.cmake")) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error while execution CPackDeb.cmake" << std::endl); - retval = 0; - return retval; - } - cmsys::Glob gl; - std::string findExpr(this->GetOption("WDIR")); - findExpr += "/*"; - gl.RecurseOn(); - if ( !gl.FindFiles(findExpr) ) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find any files in the installed directory" << std::endl); - return 0; - } - packageFiles = gl.GetFiles(); - - int res = createDeb(); - if (res != 1) - { - retval = 0; - } - // add the generated package to package file names list - packageFileNames.push_back(packageFileName); + retval &= PackageOnePack(initialTopLevel,compIt->first); } } return retval; } //---------------------------------------------------------------------- -int cmCPackDebGenerator::PackageComponentsAllInOne(bool allComponent) +int cmCPackDebGenerator::PackageComponentsAllInOne() { int retval = 1; std::string compInstDirName; @@ -189,15 +171,7 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(bool allComponent) packageFileNames.clear(); std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); - // all GROUP in one vs all COMPONENT in one - if (allComponent) - { - compInstDirName = "ALL_COMPONENTS_IN_ONE"; - } - else - { - compInstDirName = "ALL_GROUPS_IN_ONE"; - } + compInstDirName = "ALL_COMPONENTS_IN_ONE"; cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging all groups in one package..." @@ -266,19 +240,18 @@ int cmCPackDebGenerator::PackageFiles() // CASE 1 : COMPONENT ALL-IN-ONE package // If ALL GROUPS or ALL COMPONENTS in ONE package has been requested // then the package file is unique and should be open here. - if (allComponentInOne || - (allGroupInOne && (!this->ComponentGroups.empty())) - ) + if (componentPackageMethod == ONE_PACKAGE) { - return PackageComponentsAllInOne(allComponentInOne); + return PackageComponentsAllInOne(); } // CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one) // There will be 1 package for each component group // however one may require to ignore component group and // in this case you'll get 1 package for each component. - else if ((!this->ComponentGroups.empty()) || (ignoreComponentGroup)) + else { - return PackageComponents(ignoreComponentGroup); + return PackageComponents(componentPackageMethod == + ONE_PACKAGE_PER_COMPONENT); } } // CASE 3 : NON COMPONENT package. @@ -518,7 +491,7 @@ int cmCPackDebGenerator::createDeb() { std::string filenamename = cmsys::SystemTools::GetFilenameName(i->c_str()); - std::string localcopy = toplevel; + std::string localcopy = this->GetOption("WDIR"); localcopy += "/"; localcopy += filenamename; // if we can copy the file, it means it does exist, let's add it: @@ -588,11 +561,11 @@ bool cmCPackDebGenerator::SupportsComponentInstallation() const std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix( const std::string& componentName) { - if (ignoreComponentGroup) { + if (componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) { return componentName; } - if (allComponentInOne) { + if (componentPackageMethod == ONE_PACKAGE) { return std::string("ALL_COMPONENTS_IN_ONE"); } // We have to find the name of the COMPONENT GROUP @@ -601,14 +574,7 @@ std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix( cmSystemTools::UpperCase(componentName) + "_GROUP"; if (NULL != GetOption(groupVar.c_str())) { - if (allGroupInOne) - { - return std::string("ALL_GROUPS_IN_ONE"); - } - else - { - return std::string(GetOption(groupVar.c_str())); - } + return std::string(GetOption(groupVar.c_str())); } else { diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h index de1ea77..f536c47 100644 --- a/Source/CPack/cmCPackDebGenerator.h +++ b/Source/CPack/cmCPackDebGenerator.h @@ -34,6 +34,10 @@ public: protected: virtual int InitializeInternal(); /** + * This method factors out the work done in component packaging case. + */ + int PackageOnePack(std::string initialToplevel, std::string packageName); + /** * The method used to package files when component * install is used. This will create one * archive for each component group. @@ -43,7 +47,7 @@ protected: * Special case of component install where all * components will be put in a single installer. */ - int PackageComponentsAllInOne(bool allComponent); + int PackageComponentsAllInOne(); virtual int PackageFiles(); virtual const char* GetOutputExtension() { return ".deb"; } virtual bool SupportsComponentInstallation() const; diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index e9ce76c..83b6b64 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -51,6 +51,8 @@ static const char* SLASTREnglish = //---------------------------------------------------------------------- cmCPackDragNDropGenerator::cmCPackDragNDropGenerator() { + // default to one package file for components + this->componentPackageMethod = ONE_PACKAGE; } //---------------------------------------------------------------------- @@ -106,8 +108,57 @@ const char* cmCPackDragNDropGenerator::GetOutputExtension() //---------------------------------------------------------------------- int cmCPackDragNDropGenerator::PackageFiles() { + // gather which directories to make dmg files for + // multiple directories occur if packaging components or groups separately - return this->CreateDMG(); + // monolith + if(this->Components.empty()) + { + return this->CreateDMG(toplevel, packageFileNames[0]); + } + + // component install + std::vector<std::string> package_files; + + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt=this->Components.begin(); + compIt!=this->Components.end(); ++compIt ) + { + std::string name = GetComponentInstallDirNameSuffix(compIt->first); + package_files.push_back(name); + } + std::sort(package_files.begin(), package_files.end()); + package_files.erase(std::unique(package_files.begin(), + package_files.end()), + package_files.end()); + + + // loop to create dmg files + packageFileNames.clear(); + for(size_t i=0; i<package_files.size(); i++) + { + std::string full_package_name = std::string(toplevel) + std::string("/"); + if(package_files[i] == "ALL_IN_ONE") + { + full_package_name += this->GetOption("CPACK_PACKAGE_FILE_NAME"); + } + else + { + full_package_name += package_files[i]; + } + full_package_name += std::string(GetOutputExtension()); + packageFileNames.push_back(full_package_name); + + std::string src_dir = toplevel; + src_dir += "/"; + src_dir += package_files[i]; + + if(0 == this->CreateDMG(src_dir, full_package_name)) + { + return 0; + } + } + return 1; } //---------------------------------------------------------------------- @@ -159,10 +210,11 @@ bool cmCPackDragNDropGenerator::RunCommand(cmOStringStream& command, } //---------------------------------------------------------------------- -int cmCPackDragNDropGenerator::CreateDMG() +int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, + const std::string& output_file) { // Get optional arguments ... - const std::string cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON") + const std::string cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON") ? this->GetOption("CPACK_PACKAGE_ICON") : ""; const std::string cpack_dmg_volume_name = @@ -197,7 +249,7 @@ int cmCPackDragNDropGenerator::CreateDMG() // The staging directory contains everything that will end-up inside the // final disk image ... cmOStringStream staging; - staging << toplevel; + staging << src_dir; // Add a symlink to /Applications so users can drag-and-drop the bundle // into it @@ -472,7 +524,7 @@ int cmCPackDragNDropGenerator::CreateDMG() final_image_command << cpack_dmg_format; final_image_command << " -imagekey"; final_image_command << " zlib-level=9"; - final_image_command << " -o \"" << packageFileNames[0] << "\""; + final_image_command << " -o \"" << output_file << "\""; if(!this->RunCommand(final_image_command)) { @@ -485,3 +537,47 @@ int cmCPackDragNDropGenerator::CreateDMG() return 1; } + +bool cmCPackDragNDropGenerator::SupportsComponentInstallation() const +{ + return true; +} + +std::string +cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix( + const std::string& componentName) +{ + // we want to group components together that go in the same dmg package + std::string package_file_name = this->GetOption("CPACK_PACKAGE_FILE_NAME"); + + // we have 3 mutually exclusive modes to work in + // 1. all components in one package + // 2. each group goes in its own package with left over + // components in their own package + // 3. ignore groups - if grouping is defined, it is ignored + // and each component goes in its own package + + if(this->componentPackageMethod == ONE_PACKAGE) + { + return "ALL_IN_ONE"; + } + + if(this->componentPackageMethod == ONE_PACKAGE_PER_GROUP) + { + // We have to find the name of the COMPONENT GROUP + // the current COMPONENT belongs to. + std::string groupVar = "CPACK_COMPONENT_" + + cmSystemTools::UpperCase(componentName) + "_GROUP"; + const char* _groupName = GetOption(groupVar.c_str()); + if (_groupName) + { + std::string groupName = _groupName; + + groupName = GetComponentPackageFileName(package_file_name, + groupName, true); + return groupName; + } + } + + return GetComponentPackageFileName(package_file_name, componentName, false); +} diff --git a/Source/CPack/cmCPackDragNDropGenerator.h b/Source/CPack/cmCPackDragNDropGenerator.h index dcef7fb..808c618 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.h +++ b/Source/CPack/cmCPackDragNDropGenerator.h @@ -30,11 +30,16 @@ protected: virtual int InitializeInternal(); virtual const char* GetOutputExtension(); int PackageFiles(); + bool SupportsComponentInstallation() const; + bool CopyFile(cmOStringStream& source, cmOStringStream& target); bool RunCommand(cmOStringStream& command, std::string* output = 0); - int CreateDMG(); + std::string + GetComponentInstallDirNameSuffix(const std::string& componentName); + + int CreateDMG(const std::string& src_dir, const std::string& output_file); std::string InstallPrefix; }; diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index c343acf..7e5b26d 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -36,9 +36,7 @@ cmCPackGenerator::cmCPackGenerator() this->GeneratorVerbose = false; this->MakefileMap = 0; this->Logger = 0; - this->allGroupInOne = false; - this->allComponentInOne = false; - this->ignoreComponentGroup = false; + this->componentPackageMethod = ONE_PACKAGE_PER_GROUP; } //---------------------------------------------------------------------- @@ -869,6 +867,28 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( cmCPackLogger(cmCPackLog::LOG_DEBUG, "Got some ABSOLUTE DESTINATION FILES: " << absoluteDestFiles << std::endl); + // define component specific var + if (componentInstall) + { + std::string absoluteDestFileComponent = + std::string("CPACK_ABSOLUTE_DESTINATION_FILES") + + "_" + GetComponentInstallDirNameSuffix(installComponent); + if (NULL != this->GetOption(absoluteDestFileComponent.c_str())) + { + std::string absoluteDestFilesListComponent = + this->GetOption(absoluteDestFileComponent.c_str()); + absoluteDestFilesListComponent +=";"; + absoluteDestFilesListComponent += + mf->GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"); + this->SetOption(absoluteDestFileComponent.c_str(), + absoluteDestFilesListComponent.c_str()); + } + else + { + this->SetOption(absoluteDestFileComponent.c_str(), + mf->GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")); + } + } } if ( cmSystemTools::GetErrorOccuredFlag() || !res ) { @@ -1264,17 +1284,23 @@ int cmCPackGenerator::CleanTemporaryDirectory() //---------------------------------------------------------------------- int cmCPackGenerator::PrepareGroupingKind() { - // The default behavior is to create 1 package by component group - // unless the user asked to put all COMPONENTS in a single package - allGroupInOne = (NULL != - (this->GetOption( - "CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE"))); - allComponentInOne = (NULL != - (this->GetOption( - "CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE"))); - ignoreComponentGroup = (NULL != - (this->GetOption( - "CPACK_COMPONENTS_IGNORE_GROUPS"))); + // find a component package method specified by the user + ComponentPackageMethod method = UNKNOWN_COMPONENT_PACKAGE_METHOD; + + if(this->GetOption("CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE")) + { + method = ONE_PACKAGE; + } + + if(this->GetOption("CPACK_COMPONENTS_IGNORE_GROUPS")) + { + method = ONE_PACKAGE_PER_COMPONENT; + } + + if(this->GetOption("CPACK_COMPONENTS_ONE_PACKAGE_PER_GROUP")) + { + method = ONE_PACKAGE_PER_GROUP; + } std::string groupingType; @@ -1288,47 +1314,66 @@ int cmCPackGenerator::PrepareGroupingKind() cmCPackLogger(cmCPackLog::LOG_VERBOSE, "[" << this->Name << "]" << " requested component grouping = "<< groupingType <<std::endl); - if (groupingType == "ALL_GROUPS_IN_ONE") + if (groupingType == "ALL_COMPONENTS_IN_ONE") { - allGroupInOne = true; + method = ONE_PACKAGE; } - else if (groupingType == "ALL_COMPONENTS_IN_ONE") + else if (groupingType == "IGNORE") { - allComponentInOne = true; + method = ONE_PACKAGE_PER_COMPONENT; } - else if (groupingType == "IGNORE") + else if (groupingType == "ONE_PER_GROUP") { - ignoreComponentGroup = true; + method = ONE_PACKAGE_PER_GROUP; } else { cmCPackLogger(cmCPackLog::LOG_WARNING, "[" - << this->Name << "]" - << " requested component grouping type <"<< groupingType - << "> UNKNOWN not in (ALL_GROUPS_IN_ONE," - "ALL_COMPONENTS_IN_ONE,IGNORE)" <<std::endl); + << this->Name << "]" + << " requested component grouping type <"<< groupingType + << "> UNKNOWN not in (ALL_COMPONENTS_IN_ONE,IGNORE,ONE_PER_GROUP)" + << std::endl); } } + // Some components were defined but NO group + // fallback to default if not group based + if(method == ONE_PACKAGE_PER_GROUP && + this->ComponentGroups.empty() && !this->Components.empty()) + { + if(componentPackageMethod == ONE_PACKAGE) + { + method = ONE_PACKAGE; + } + else + { + method = ONE_PACKAGE_PER_COMPONENT; + } + cmCPackLogger(cmCPackLog::LOG_WARNING, "[" + << this->Name << "]" + << " One package per component group requested, " + << "but NO component groups exist: Ignoring component group." + << std::endl); + } + + // if user specified packaging method, override the default packaging method + if(method != UNKNOWN_COMPONENT_PACKAGE_METHOD) + { + componentPackageMethod = method; + } + + const char* method_names[] = + { + "ALL_COMPONENTS_IN_ONE", + "IGNORE_GROUPS", + "ONE_PER_GROUP" + }; + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "[" << this->Name << "]" - << " requested component grouping = (" - << "ALL_GROUPS_IN_ONE=" << allGroupInOne - << ", ALL_COMPONENTS_IN_ONE=" << allComponentInOne - << ", IGNORE_GROUPS=" << ignoreComponentGroup - << ")" + << " requested component grouping = " + << method_names[componentPackageMethod] << std::endl); - // Some components were defined but NO group - // force ignoreGroups - if (this->ComponentGroups.empty() && (!this->Components.empty()) - && (!ignoreComponentGroup)) { - cmCPackLogger(cmCPackLog::LOG_WARNING, "[" - << this->Name << "]" - << " Some Components defined but NO component group:" - << " Ignoring component group." - << std::endl); - ignoreComponentGroup = true; - } return 1; } diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 0497d1c..05d95b8 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -122,11 +122,10 @@ protected: /** * Prepare requested grouping kind from CPACK_xxx vars - * CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE * CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE * CPACK_COMPONENTS_IGNORE_GROUPS * or - * CPACK_COMPONENTS_GROUPING + * CPACK_COMPONENTS_ONE_PACKAGE_PER_GROUP * @return 1 on success 0 on failure. */ virtual int PrepareGroupingKind(); @@ -238,20 +237,30 @@ protected: */ std::map<std::string, cmCPackComponent> Components; std::map<std::string, cmCPackComponentGroup> ComponentGroups; + /** - * If true All component groups will be put in a single package. - */ - bool allGroupInOne; - /** - * If true All component will be put in a single package. + * If components are enabled, this enum represents the different + * ways of mapping components to package files. */ - bool allComponentInOne; + enum ComponentPackageMethod + { + /* one package for all components */ + ONE_PACKAGE, + /* one package for each component */ + ONE_PACKAGE_PER_COMPONENT, + /* one package for each group, + * with left over components in their own package */ + ONE_PACKAGE_PER_GROUP, + UNKNOWN_COMPONENT_PACKAGE_METHOD + }; + /** - * If true component grouping will be ignored. - * You will still get 1 package for each component unless - * allComponentInOne is true. + * The component package method + * The default is ONE_PACKAGE_PER_GROUP, + * and generators may override the default + * before PrepareGroupingKind() is called. */ - bool ignoreComponentGroup; + ComponentPackageMethod componentPackageMethod; cmCPackLog* Logger; private: diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx index 0e8cbc0..75ad640 100644 --- a/Source/CPack/cmCPackOSXX11Generator.cxx +++ b/Source/CPack/cmCPackOSXX11Generator.cxx @@ -21,6 +21,7 @@ #include <cmsys/SystemTools.hxx> #include <cmsys/Glob.hxx> +#include <sys/stat.h> //---------------------------------------------------------------------- cmCPackOSXX11Generator::cmCPackOSXX11Generator() @@ -135,6 +136,32 @@ int cmCPackOSXX11Generator::PackageFiles() return 0; } + // Two of the files need to have execute permission, so ensure they do: + std::string runTimeScript = dir; + runTimeScript += "/"; + runTimeScript += "RuntimeScript"; + + std::string appScriptName = appdir; + appScriptName += "/"; + appScriptName += this->GetOption("CPACK_PACKAGE_FILE_NAME"); + + mode_t mode; + if (cmsys::SystemTools::GetPermissions(runTimeScript.c_str(), mode)) + { + mode |= (S_IXUSR | S_IXGRP | S_IXOTH); + cmsys::SystemTools::SetPermissions(runTimeScript.c_str(), mode); + cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Setting: " << runTimeScript + << " to permission: " << mode << std::endl); + } + + if (cmsys::SystemTools::GetPermissions(appScriptName.c_str(), mode)) + { + mode |= (S_IXUSR | S_IXGRP | S_IXOTH); + cmsys::SystemTools::SetPermissions(appScriptName.c_str(), mode); + cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Setting: " << appScriptName + << " to permission: " << mode << std::endl); + } + std::string output; std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); tmpFile += "/hdiutilOutput.log"; diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx index 0b0c6b1..1a6c3be 100644 --- a/Source/CPack/cmCPackRPMGenerator.cxx +++ b/Source/CPack/cmCPackRPMGenerator.cxx @@ -50,6 +50,45 @@ int cmCPackRPMGenerator::InitializeInternal() } //---------------------------------------------------------------------- +int cmCPackRPMGenerator::PackageOnePack(std::string initialToplevel, + std::string packageName) +{ + int retval = 1; + // Begin the archive for this pack + std::string localToplevel(initialToplevel); + std::string packageFileName( + cmSystemTools::GetParentDirectory(toplevel.c_str()) + ); + std::string outputFileName( + GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"), + packageName, + true) + + this->GetOutputExtension() + ); + + localToplevel += "/"+ packageName; + /* replace the TEMP DIRECTORY with the component one */ + this->SetOption("CPACK_TEMPORARY_DIRECTORY",localToplevel.c_str()); + packageFileName += "/"+ outputFileName; + /* replace proposed CPACK_OUTPUT_FILE_NAME */ + this->SetOption("CPACK_OUTPUT_FILE_NAME",outputFileName.c_str()); + /* replace the TEMPORARY package file name */ + this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", + packageFileName.c_str()); + // Tell CPackRPM.cmake the name of the component NAME. + this->SetOption("CPACK_RPM_PACKAGE_COMPONENT",packageName.c_str()); + if (!this->ReadListFile("CPackRPM.cmake")) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error while execution CPackRPM.cmake" << std::endl); + retval = 0; + } + // add the generated package to package file names list + packageFileNames.push_back(packageFileName); + return retval; +} + +//---------------------------------------------------------------------- int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup) { int retval = 1; @@ -69,37 +108,23 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup) cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: " << compGIt->first << std::endl); - // Begin the archive for this group - std::string localToplevel(initialTopLevel); - std::string packageFileName( - cmSystemTools::GetParentDirectory(toplevel.c_str()) - ); - std::string outputFileName( - GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"), - compGIt->first, - true) - + this->GetOutputExtension() - ); - - localToplevel += "/"+ compGIt->first; - /* replace the TEMP DIRECTORY with the component one */ - this->SetOption("CPACK_TEMPORARY_DIRECTORY",localToplevel.c_str()); - packageFileName += "/"+ outputFileName; - /* replace proposed CPACK_OUTPUT_FILE_NAME */ - this->SetOption("CPACK_OUTPUT_FILE_NAME",outputFileName.c_str()); - /* replace the TEMPORARY package file name */ - this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", - packageFileName.c_str()); - // Tell CPackRPM.cmake the name of the component GROUP. - this->SetOption("CPACK_RPM_PACKAGE_COMPONENT",compGIt->first.c_str()); - if (!this->ReadListFile("CPackRPM.cmake")) + retval &= PackageOnePack(initialTopLevel,compGIt->first); + } + // Handle Orphan components (components not belonging to any groups) + std::map<std::string, cmCPackComponent>::iterator compIt; + for (compIt=this->Components.begin(); + compIt!=this->Components.end(); ++compIt ) + { + // Does the component belong to a group? + if (compIt->second.Group==NULL) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error while execution CPackRPM.cmake" << std::endl); - retval = 0; + cmCPackLogger(cmCPackLog::LOG_VERBOSE, + "Component <" + << compIt->second.Name + << "> does not belong to any group, package it separately." + << std::endl); + retval &= PackageOnePack(initialTopLevel,compIt->first); } - // add the generated package to package file names list - packageFileNames.push_back(packageFileName); } } // CPACK_COMPONENTS_IGNORE_GROUPS is set @@ -110,42 +135,14 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup) for (compIt=this->Components.begin(); compIt!=this->Components.end(); ++compIt ) { - std::string localToplevel(initialTopLevel); - std::string packageFileName( - cmSystemTools::GetParentDirectory(toplevel.c_str()) - ); - std::string outputFileName( - GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"), - compIt->first, - false) - + this->GetOutputExtension()); - - localToplevel += "/"+ compIt->first; - /* replace the TEMP DIRECTORY with the component one */ - this->SetOption("CPACK_TEMPORARY_DIRECTORY",localToplevel.c_str()); - packageFileName += "/"+ outputFileName; - /* replace proposed CPACK_OUTPUT_FILE_NAME */ - this->SetOption("CPACK_OUTPUT_FILE_NAME",outputFileName.c_str()); - /* replace the TEMPORARY package file name */ - this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", - packageFileName.c_str()); - - this->SetOption("CPACK_RPM_PACKAGE_COMPONENT",compIt->first.c_str()); - if (!this->ReadListFile("CPackRPM.cmake")) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error while execution CPackRPM.cmake" << std::endl); - retval = 0; - } - // add the generated package to package file names list - packageFileNames.push_back(packageFileName); + retval &= PackageOnePack(initialTopLevel,compIt->first); } } return retval; } //---------------------------------------------------------------------- -int cmCPackRPMGenerator::PackageComponentsAllInOne(bool allComponent) +int cmCPackRPMGenerator::PackageComponentsAllInOne() { int retval = 1; std::string compInstDirName; @@ -154,15 +151,7 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne(bool allComponent) packageFileNames.clear(); std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); - // all GROUP in one vs all COMPONENT in one - if (allComponent) - { - compInstDirName = "ALL_COMPONENTS_IN_ONE"; - } - else - { - compInstDirName = "ALL_GROUPS_IN_ONE"; - } + compInstDirName = "ALL_COMPONENTS_IN_ONE"; cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging all groups in one package..." @@ -214,21 +203,20 @@ int cmCPackRPMGenerator::PackageFiles() /* Are we in the component packaging case */ if (SupportsComponentInstallation()) { // CASE 1 : COMPONENT ALL-IN-ONE package - // If ALL GROUPS or ALL COMPONENTS in ONE package has been requested + // If ALL COMPONENTS in ONE package has been requested // then the package file is unique and should be open here. - if (allComponentInOne || - (allGroupInOne && (!this->ComponentGroups.empty())) - ) + if (componentPackageMethod == ONE_PACKAGE) { - return PackageComponentsAllInOne(allComponentInOne); + return PackageComponentsAllInOne(); } // CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one) // There will be 1 package for each component group // however one may require to ignore component group and // in this case you'll get 1 package for each component. - else if ((!this->ComponentGroups.empty()) || (ignoreComponentGroup)) + else { - return PackageComponents(ignoreComponentGroup); + return PackageComponents(componentPackageMethod == + ONE_PACKAGE_PER_COMPONENT); } } // CASE 3 : NON COMPONENT package. @@ -265,11 +253,11 @@ bool cmCPackRPMGenerator::SupportsComponentInstallation() const std::string cmCPackRPMGenerator::GetComponentInstallDirNameSuffix( const std::string& componentName) { - if (ignoreComponentGroup) { + if (componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) { return componentName; } - if (allComponentInOne) { + if (componentPackageMethod == ONE_PACKAGE) { return std::string("ALL_COMPONENTS_IN_ONE"); } // We have to find the name of the COMPONENT GROUP @@ -278,14 +266,7 @@ std::string cmCPackRPMGenerator::GetComponentInstallDirNameSuffix( cmSystemTools::UpperCase(componentName) + "_GROUP"; if (NULL != GetOption(groupVar.c_str())) { - if (allGroupInOne) - { - return std::string("ALL_GROUPS_IN_ONE"); - } - else - { - return std::string(GetOption(groupVar.c_str())); - } + return std::string(GetOption(groupVar.c_str())); } else { diff --git a/Source/CPack/cmCPackRPMGenerator.h b/Source/CPack/cmCPackRPMGenerator.h index 7c2e434..4883a0d 100644 --- a/Source/CPack/cmCPackRPMGenerator.h +++ b/Source/CPack/cmCPackRPMGenerator.h @@ -39,6 +39,10 @@ protected: virtual int InitializeInternal(); virtual int PackageFiles(); /** + * This method factors out the work done in component packaging case. + */ + int PackageOnePack(std::string initialToplevel, std::string packageName); + /** * The method used to package files when component * install is used. This will create one * archive for each component group. @@ -48,7 +52,7 @@ protected: * Special case of component install where all * components will be put in a single installer. */ - int PackageComponentsAllInOne(bool allComponent); + int PackageComponentsAllInOne(); virtual const char* GetOutputExtension() { return ".rpm"; } virtual bool SupportsComponentInstallation() const; virtual std::string GetComponentInstallDirNameSuffix( diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 13a25cb..0612449 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -344,9 +344,21 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os) } this->MemoryTesterGlobalResults[kk] += memcheckresults[kk]; } + + std::string logTag; + if(this->CTest->ShouldCompressMemCheckOutput()) + { + this->CTest->CompressString(memcheckstr); + logTag = "\t<Log compression=\"gzip\" encoding=\"base64\">\n"; + } + else + { + logTag = "\t<Log>\n"; + } + os << "\t\t</Results>\n" - << "\t<Log>\n" << memcheckstr << std::endl + << logTag << memcheckstr << std::endl << "\t</Log>\n"; this->WriteTestResultFooter(os, result); if ( current < cc ) diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 42a4cff..60695da 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -135,7 +135,10 @@ void cmCTestRunTest::CompressOutput() //--------------------------------------------------------- bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) { - if (this->CTest->ShouldCompressTestOutput()) + if ((!this->TestHandler->MemCheck && + this->CTest->ShouldCompressTestOutput()) || + (this->TestHandler->MemCheck && + this->CTest->ShouldCompressMemCheckOutput())) { this->CompressOutput(); } @@ -279,11 +282,11 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) // Output since that is what is parsed by cmCTestMemCheckHandler if(!this->TestHandler->MemCheck && started) { - this->TestHandler->CleanTestOutput(this->ProcessOutput, - static_cast<size_t> - (this->TestResult.Status == cmCTestTestHandler::COMPLETED ? - this->TestHandler->CustomMaximumPassedTestOutputSize : - this->TestHandler->CustomMaximumFailedTestOutputSize)); + this->TestHandler->CleanTestOutput(this->ProcessOutput, + static_cast<size_t> + (this->TestResult.Status == cmCTestTestHandler::COMPLETED ? + this->TestHandler->CustomMaximumPassedTestOutputSize : + this->TestHandler->CustomMaximumFailedTestOutputSize)); } this->TestResult.Reason = reason; if (this->TestHandler->LogFile) @@ -332,7 +335,8 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) // record the results in TestResult if(started) { - bool compress = this->CompressionRatio < 1 && + bool compress = !this->TestHandler->MemCheck && + this->CompressionRatio < 1 && this->CTest->ShouldCompressTestOutput(); this->TestResult.Output = compress ? this->CompressedOutput : this->ProcessOutput; @@ -408,6 +412,30 @@ bool cmCTestRunTest::StartTest(size_t total) this->TestResult.TestCount = this->TestProperties->Index; this->TestResult.Name = this->TestProperties->Name; this->TestResult.Path = this->TestProperties->Directory.c_str(); + + if(args.size() >= 2 && args[1] == "NOT_AVAILABLE") + { + this->TestProcess = new cmProcess; + std::string msg; + if(this->CTest->GetConfigType().empty()) + { + msg = "Test not available without configuration."; + msg += " (Missing \"-C <config>\"?)"; + } + else + { + msg = "Test not available in configuration \""; + msg += this->CTest->GetConfigType(); + msg += "\"."; + } + *this->TestHandler->LogFile << msg << std::endl; + cmCTestLog(this->CTest, ERROR_MESSAGE, msg << std::endl); + this->TestResult.Output = msg; + this->TestResult.FullCommandLine = ""; + this->TestResult.CompletionStatus = "Not Run"; + this->TestResult.Status = cmCTestTestHandler::NOT_RUN; + return false; + } // Check if all required files exist for(std::vector<std::string>::iterator i = diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 12d5fd1..5841b8d 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -50,6 +50,7 @@ #include "cmCTestSubmitCommand.h" #include "cmCTestTestCommand.h" #include "cmCTestUpdateCommand.h" +#include "cmCTestUploadCommand.h" #define CTEST_INITIAL_CMAKE_OUTPUT_FILE_NAME "CTestInitialCMakeOutput.log" @@ -357,6 +358,7 @@ void cmCTestScriptHandler::CreateCMake() this->AddCTestCommand(new cmCTestSubmitCommand); this->AddCTestCommand(new cmCTestTestCommand); this->AddCTestCommand(new cmCTestUpdateCommand); + this->AddCTestCommand(new cmCTestUploadCommand); } void cmCTestScriptHandler::GetCommandDocumentation( diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 43441c0..142bb46 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -1204,6 +1204,7 @@ int cmCTestSubmitHandler::ProcessHandler() this->CTest->AddIfExists(cmCTest::PartMemCheck, "DynamicAnalysis.xml"); this->CTest->AddIfExists(cmCTest::PartMemCheck, "Purify.xml"); this->CTest->AddIfExists(cmCTest::PartNotes, "Notes.xml"); + this->CTest->AddIfExists(cmCTest::PartUpload, "Upload.xml"); // Query parts for files to submit. for(cmCTest::Part p = cmCTest::PartStart; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index f87c929..e3b81df 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -1282,7 +1282,7 @@ void cmCTestTestHandler::AttachFiles(std::ostream& os, result->Properties->AttachedFiles.begin(); file != result->Properties->AttachedFiles.end(); ++file) { - std::string base64 = this->EncodeFile(*file); + std::string base64 = this->CTest->Base64GzipEncodeFile(*file); std::string fname = cmSystemTools::GetFilenameName(*file); os << "\t\t<NamedMeasurement name=\"Attached File\" encoding=\"base64\" " "compression=\"tar/gzip\" filename=\"" << fname << "\" type=\"file\">" @@ -1293,48 +1293,6 @@ void cmCTestTestHandler::AttachFiles(std::ostream& os, } //---------------------------------------------------------------------- -std::string cmCTestTestHandler::EncodeFile(std::string file) -{ - std::string tarFile = file + "_temp.tar.gz"; - std::vector<cmStdString> files; - files.push_back(file); - - if(!cmSystemTools::CreateTar(tarFile.c_str(), files, true, false, false)) - { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Error creating tar while " - "attaching file: " << file << std::endl); - return ""; - } - long len = cmSystemTools::FileLength(tarFile.c_str()); - std::ifstream ifs(tarFile.c_str(), std::ios::in -#ifdef _WIN32 - | std::ios::binary -#endif - ); - unsigned char *file_buffer = new unsigned char [ len + 1 ]; - ifs.read(reinterpret_cast<char*>(file_buffer), len); - ifs.close(); - cmSystemTools::RemoveFile(tarFile.c_str()); - - unsigned char *encoded_buffer - = new unsigned char [ static_cast<int>( - static_cast<double>(len) * 1.5 + 5.0) ]; - - unsigned long rlen - = cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1); - - std::string base64 = ""; - for(unsigned long i = 0; i < rlen; i++) - { - base64 += encoded_buffer[i]; - } - delete [] file_buffer; - delete [] encoded_buffer; - - return base64; -} - -//---------------------------------------------------------------------- int cmCTestTestHandler::ExecuteCommands(std::vector<cmStdString>& vec) { std::vector<cmStdString>::iterator it; @@ -1362,6 +1320,10 @@ std::string cmCTestTestHandler::FindTheExecutable(const char *exe) std::string resConfig; std::vector<std::string> extraPaths; std::vector<std::string> failedPaths; + if(strcmp(exe, "NOT_AVAILABLE") == 0) + { + return exe; + } return cmCTestTestHandler::FindExecutable(this->CTest, exe, resConfig, extraPaths, @@ -1978,6 +1940,7 @@ void cmCTestTestHandler::SetTestsToRunInformation(const char* in) fin.getline(buff, filelen); buff[fin.gcount()] = 0; this->TestsToRunString = buff; + delete [] buff; } } diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 2c4b230..3089d35 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -151,8 +151,6 @@ protected: void WriteTestResultFooter(std::ostream& os, cmCTestTestResult* result); // Write attached test files into the xml void AttachFiles(std::ostream& os, cmCTestTestResult* result); - // Helper function to encode attached test files - std::string EncodeFile(std::string file); //! Clean test output to specified length bool CleanTestOutput(std::string& output, size_t length); diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx new file mode 100644 index 0000000..731c1c7 --- /dev/null +++ b/Source/CTest/cmCTestUploadCommand.cxx @@ -0,0 +1,69 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmCTestUploadCommand.h" + +#include "cmCTest.h" +#include "cmCTestGenericHandler.h" +#include "cmCTestUploadHandler.h" + +cmCTestGenericHandler* cmCTestUploadCommand::InitializeHandler() +{ + cmCTestGenericHandler* handler + = this->CTest->GetInitializedHandler("upload"); + if ( !handler ) + { + this->SetError("internal CTest error. Cannot instantiate upload handler"); + return 0; + } + static_cast<cmCTestUploadHandler*>(handler)->SetFiles(this->Files); + + return handler; +} + + +//---------------------------------------------------------------------------- +bool cmCTestUploadCommand::CheckArgumentKeyword(std::string const& arg) +{ + if(arg == "FILES") + { + this->ArgumentDoing = ArgumentDoingFiles; + return true; + } + return false; +} + + +//---------------------------------------------------------------------------- +bool cmCTestUploadCommand::CheckArgumentValue(std::string const& arg) +{ + if(this->ArgumentDoing == ArgumentDoingFiles) + { + cmStdString filename(arg); + if(cmSystemTools::FileExists(filename.c_str())) + { + this->Files.insert(filename); + return true; + } + else + { + cmOStringStream e; + e << "File \"" << filename << "\" does not exist. Cannot submit " + << "a non-existent file."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + this->ArgumentDoing = ArgumentDoingError; + return false; + } + } + + // Look for other arguments. + return this->Superclass::CheckArgumentValue(arg); +} diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h new file mode 100644 index 0000000..6c2a4c2 --- /dev/null +++ b/Source/CTest/cmCTestUploadCommand.h @@ -0,0 +1,85 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmCTestUploadCommand_h +#define cmCTestUploadCommand_h + +#include "cmCTestHandlerCommand.h" +#include "cmCTest.h" + +/** \class cmCTestUpload + * \brief Run a ctest script + * + * cmCTestUploadCommand defines the command to upload result files for + * the project. + */ +class cmCTestUploadCommand : public cmCTestHandlerCommand +{ +public: + + cmCTestUploadCommand() + { + } + + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + cmCTestUploadCommand* ni = new cmCTestUploadCommand; + ni->CTest = this->CTest; + ni->CTestScriptHandler = this->CTestScriptHandler; + return ni; + } + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() { return "ctest_upload";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() + { + return "Upload files to a dashboard server."; + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() + { + return + " ctest_upload(FILES ...)\n" + "Pass a list of files to be sent along with the build results to " + "the dashboard server.\n"; + } + + cmTypeMacro(cmCTestUploadCommand, cmCTestHandlerCommand); + +protected: + cmCTestGenericHandler* InitializeHandler(); + + virtual bool CheckArgumentKeyword(std::string const& arg); + virtual bool CheckArgumentValue(std::string const& arg); + + enum + { + ArgumentDoingFiles = Superclass::ArgumentDoingLast1, + ArgumentDoingLast2 + }; + + cmCTest::SetOfStrings Files; +}; + + +#endif diff --git a/Source/CTest/cmCTestUploadHandler.cxx b/Source/CTest/cmCTestUploadHandler.cxx new file mode 100644 index 0000000..caf2e53 --- /dev/null +++ b/Source/CTest/cmCTestUploadHandler.cxx @@ -0,0 +1,77 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmCTestUploadHandler.h" + +#include "cmGeneratedFileStream.h" +#include "cmVersion.h" +#include "cmXMLSafe.h" + +//---------------------------------------------------------------------------- +cmCTestUploadHandler::cmCTestUploadHandler() +{ + this->Initialize(); +} + +//---------------------------------------------------------------------------- +void cmCTestUploadHandler::Initialize() +{ + this->Superclass::Initialize(); + this->Files.clear(); +} + +void cmCTestUploadHandler::SetFiles(const cmCTest::SetOfStrings& files) +{ + this->Files = files; +} + +//---------------------------------------------------------------------------- +int cmCTestUploadHandler::ProcessHandler() +{ + cmGeneratedFileStream ofs; + if ( !this->CTest->OpenOutputFile(this->CTest->GetCurrentTag(), + "Upload.xml", ofs)) + { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot open Upload.xml file" << std::endl); + return -1; + } + + cmCTest::SetOfStrings::const_iterator it; + ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + << "<?xml-stylesheet type=\"text/xsl\" " + "href=\"Dart/Source/Server/XSL/Build.xsl " + "<file:///Dart/Source/Server/XSL/Build.xsl> \"?>\n" + << "<Site BuildName=\"" + << this->CTest->GetCTestConfiguration("BuildName") + << "\" BuildStamp=\"" + << this->CTest->GetCurrentTag() << "-" + << this->CTest->GetTestModelString() << "\" Name=\"" + << this->CTest->GetCTestConfiguration("Site") << "\" Generator=\"ctest" + << cmVersion::GetCMakeVersion() + << "\">\n"; + this->CTest->AddSiteProperties(ofs); + ofs << "<Upload>\n"; + + for ( it = this->Files.begin(); it != this->Files.end(); it ++ ) + { + cmCTestLog(this->CTest, OUTPUT, + "\tUpload file: " << it->c_str() << std::endl); + ofs << "<File filename=\"" << cmXMLSafe(*it) << "\">\n" + << "<Content encoding=\"base64\">\n"; + ofs << this->CTest->Base64EncodeFile(*it); + ofs << "\n</Content>\n" + << "</File>\n"; + } + ofs << "</Upload>\n" + << "</Site>\n"; + return 0; +} diff --git a/Source/CTest/cmCTestUploadHandler.h b/Source/CTest/cmCTestUploadHandler.h new file mode 100644 index 0000000..23ed35a --- /dev/null +++ b/Source/CTest/cmCTestUploadHandler.h @@ -0,0 +1,45 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmCTestUploadHandler_h +#define cmCTestUploadHandler_h + +#include "cmCTestGenericHandler.h" + +/** \class cmCTestUploadHandler + * \brief Helper class for CTest + * + * Submit arbitrary files + * + */ +class cmCTestUploadHandler : public cmCTestGenericHandler +{ +public: + cmTypeMacro(cmCTestUploadHandler, cmCTestGenericHandler); + + cmCTestUploadHandler(); + ~cmCTestUploadHandler() {} + + /* + * The main entry point for this class + */ + int ProcessHandler(); + + void Initialize(); + + /** Specify a set of files to submit. */ + void SetFiles(cmCTest::SetOfStrings const& files); + +private: + cmCTest::SetOfStrings Files; +}; + +#endif diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index 502829e..5634849 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -195,11 +195,13 @@ bool cmAddCustomCommandCommand { // An implicit dependency starting point is also an // explicit dependency. - depends.push_back(copy); + std::string dep = copy; + cmSystemTools::ConvertToUnixSlashes(dep); + depends.push_back(dep); // Add the implicit dependency language and file. cmCustomCommand::ImplicitDependsPair - entry(implicit_depends_lang, copy); + entry(implicit_depends_lang, dep); implicit_depends.push_back(entry); // Switch back to looking for a language. @@ -213,7 +215,11 @@ bool cmAddCustomCommandCommand target = copy; break; case doing_depends: - depends.push_back(copy); + { + std::string dep = copy; + cmSystemTools::ConvertToUnixSlashes(dep); + depends.push_back(dep); + } break; case doing_outputs: outputs.push_back(filename); diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index 27dea98..4eba886 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -123,7 +123,11 @@ bool cmAddCustomTargetCommand currentLine.push_back(copy); break; case doing_depends: - depends.push_back(copy); + { + std::string dep = copy; + cmSystemTools::ConvertToUnixSlashes(dep); + depends.push_back(dep); + } break; case doing_comment: comment_buffer = copy; diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index d9e4742..25dc8ba 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -236,6 +236,9 @@ bool cmArchiveWrite::AddFile(const char* file, this->Error += archive_error_string(this->Disk); return false; } + // Clear acl and xattr fields not useful for distribution. + archive_entry_acl_clear(e); + archive_entry_xattr_clear(e); if(archive_write_header(this->Archive, e) != ARCHIVE_OK) { this->Error = "archive_write_header: "; diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 411a28d..e237913 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -518,7 +518,7 @@ public: }; cmCPluginAPISourceFileMap cmCPluginAPISourceFiles; -void * CCONV cmCreateSourceFile() +void * CCONV cmCreateSourceFile(void) { return (void*)new cmCPluginAPISourceFile; } diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 2e05883..75a564e 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -16,6 +16,7 @@ #include "cmMakefile.h" #include "cmLocalGenerator.h" #include "cmGlobalGenerator.h" +#include <cmsys/Base64.h> #include <cmsys/Directory.hxx> #include <cmsys/SystemInformation.hxx> #include "cmDynamicLoader.h" @@ -31,9 +32,10 @@ #include "cmCTestCoverageHandler.h" #include "cmCTestMemCheckHandler.h" #include "cmCTestScriptHandler.h" +#include "cmCTestSubmitHandler.h" #include "cmCTestTestHandler.h" #include "cmCTestUpdateHandler.h" -#include "cmCTestSubmitHandler.h" +#include "cmCTestUploadHandler.h" #include "cmVersion.h" @@ -48,6 +50,9 @@ #include <memory> // auto_ptr +#include <cm_zlib.h> +#include <cmsys/Base64.h> + #if defined(__BEOS__) && !defined(__HAIKU__) #include <be/kernel/OS.h> /* disable_debugger() API. */ #endif @@ -306,7 +311,7 @@ cmCTest::cmCTest() this->UseHTTP10 = false; this->PrintLabels = false; this->CompressTestOutput = true; - this->ComputedCompressOutput = false; + this->CompressMemCheckOutput = true; this->TestModel = cmCTest::EXPERIMENTAL; this->MaxTestNameWidth = 30; this->InteractiveDebugMode = true; @@ -323,6 +328,8 @@ cmCTest::cmCTest() this->SuppressUpdatingCTestConfiguration = false; this->DartVersion = 1; this->OutputTestOutputOnTestFailure = false; + this->ComputedCompressTestOutput = false; + this->ComputedCompressMemCheckOutput = false; if(cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE")) { this->OutputTestOutputOnTestFailure = true; @@ -339,6 +346,7 @@ cmCTest::cmCTest() this->Parts[PartSubmit].SetName("Submit"); this->Parts[PartNotes].SetName("Notes"); this->Parts[PartExtraFiles].SetName("ExtraFiles"); + this->Parts[PartUpload].SetName("Upload"); // Fill the part name-to-id map. for(Part p = PartStart; p != PartCount; p = Part(p+1)) @@ -357,6 +365,7 @@ cmCTest::cmCTest() this->TestingHandlers["configure"] = new cmCTestConfigureHandler; this->TestingHandlers["memcheck"] = new cmCTestMemCheckHandler; this->TestingHandlers["submit"] = new cmCTestSubmitHandler; + this->TestingHandlers["upload"] = new cmCTestUploadHandler; cmCTest::t_TestingHandlers::iterator it; for ( it = this->TestingHandlers.begin(); @@ -390,7 +399,7 @@ void cmCTest::SetParallelLevel(int level) //---------------------------------------------------------------------------- bool cmCTest::ShouldCompressTestOutput() { - if(!this->ComputedCompressOutput) + if(!this->ComputedCompressTestOutput) { std::string cdashVersion = this->GetCDashVersion(); //version >= 1.6? @@ -399,12 +408,27 @@ bool cmCTest::ShouldCompressTestOutput() cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, cdashVersion.c_str(), "1.6"); this->CompressTestOutput &= cdashSupportsGzip; - this->ComputedCompressOutput = true; + this->ComputedCompressTestOutput = true; } return this->CompressTestOutput; } //---------------------------------------------------------------------------- +bool cmCTest::ShouldCompressMemCheckOutput() +{ + if(!this->ComputedCompressMemCheckOutput) + { + std::string cdashVersion = this->GetCDashVersion(); + + bool compressionSupported = cmSystemTools::VersionCompare( + cmSystemTools::OP_GREATER, cdashVersion.c_str(), "1.9.0"); + this->CompressMemCheckOutput &= compressionSupported; + this->ComputedCompressMemCheckOutput = true; + } + return this->CompressMemCheckOutput; +} + +//---------------------------------------------------------------------------- std::string cmCTest::GetCDashVersion() { #ifdef CMAKE_BUILD_WITH_CMAKE @@ -1584,6 +1608,56 @@ int cmCTest::GenerateNotesFile(const char* cfiles) } //---------------------------------------------------------------------- +std::string cmCTest::Base64GzipEncodeFile(std::string file) +{ + std::string tarFile = file + "_temp.tar.gz"; + std::vector<cmStdString> files; + files.push_back(file); + + if(!cmSystemTools::CreateTar(tarFile.c_str(), files, true, false, false)) + { + cmCTestLog(this, ERROR_MESSAGE, "Error creating tar while " + "encoding file: " << file << std::endl); + return ""; + } + std::string base64 = this->Base64EncodeFile(tarFile); + cmSystemTools::RemoveFile(tarFile.c_str()); + return base64; +} + +//---------------------------------------------------------------------- +std::string cmCTest::Base64EncodeFile(std::string file) +{ + long len = cmSystemTools::FileLength(file.c_str()); + std::ifstream ifs(file.c_str(), std::ios::in +#ifdef _WIN32 + | std::ios::binary +#endif + ); + unsigned char *file_buffer = new unsigned char [ len + 1 ]; + ifs.read(reinterpret_cast<char*>(file_buffer), len); + ifs.close(); + + unsigned char *encoded_buffer + = new unsigned char [ static_cast<int>( + static_cast<double>(len) * 1.5 + 5.0) ]; + + unsigned long rlen + = cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1); + + std::string base64 = ""; + for(unsigned long i = 0; i < rlen; i++) + { + base64 += encoded_buffer[i]; + } + delete [] file_buffer; + delete [] encoded_buffer; + + return base64; +} + + +//---------------------------------------------------------------------- bool cmCTest::SubmitExtraFiles(const std::vector<cmStdString> &files) { std::vector<cmStdString>::const_iterator it; @@ -1872,6 +1946,7 @@ void cmCTest::HandleCommandLineArguments(size_t &i, if(this->CheckArgument(arg, "--no-compress-output")) { this->CompressTestOutput = false; + this->CompressMemCheckOutput = false; } if(this->CheckArgument(arg, "--print-labels")) @@ -3001,3 +3076,56 @@ void cmCTest::OutputTestErrors(std::vector<char> const &process_output) } cmCTestLog(this, HANDLER_OUTPUT, test_outputs << std::endl << std::flush); } + +//---------------------------------------------------------------------- +bool cmCTest::CompressString(std::string& str) +{ + int ret; + z_stream strm; + + unsigned char* in = reinterpret_cast<unsigned char*>( + const_cast<char*>(str.c_str())); + //zlib makes the guarantee that this is the maximum output size + int outSize = static_cast<int>( + static_cast<double>(str.size()) * 1.001 + 13.0); + unsigned char* out = new unsigned char[outSize]; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + ret = deflateInit(&strm, -1); //default compression level + if (ret != Z_OK) + { + return false; + } + + strm.avail_in = static_cast<uInt>(str.size()); + strm.next_in = in; + strm.avail_out = outSize; + strm.next_out = out; + ret = deflate(&strm, Z_FINISH); + + if(ret == Z_STREAM_ERROR || ret != Z_STREAM_END) + { + cmCTestLog(this, ERROR_MESSAGE, "Error during gzip compression." + << std::endl); + return false; + } + + (void)deflateEnd(&strm); + + // Now base64 encode the resulting binary string + unsigned char* base64EncodedBuffer + = new unsigned char[static_cast<int>(outSize * 1.5)]; + + unsigned long rlen + = cmsysBase64_Encode(out, strm.total_out, base64EncodedBuffer, 1); + + str = ""; + str.append(reinterpret_cast<char*>(base64EncodedBuffer), rlen); + + delete [] base64EncodedBuffer; + delete [] out; + + return true; +} diff --git a/Source/cmCTest.h b/Source/cmCTest.h index e54a205..44a5349 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -61,6 +61,7 @@ public: PartSubmit, PartNotes, PartExtraFiles, + PartUpload, PartCount // Update names in constructor when adding a part }; @@ -192,8 +193,13 @@ public: ///! Get the current time as string std::string CurrentTime(); + //! tar/gzip and then base 64 encode a file + std::string Base64GzipEncodeFile(std::string file); + //! base64 encode a file + std::string Base64EncodeFile(std::string file); + /** - * Return the time remaianing that the script is allowed to run in + * Return the time remaining that the script is allowed to run in * seconds if the user has set the variable CTEST_TIME_LIMIT. If that has * not been set it returns 1e7 seconds */ @@ -213,6 +219,8 @@ public: bool ShouldPrintLabels() { return this->PrintLabels; } bool ShouldCompressTestOutput(); + bool ShouldCompressMemCheckOutput(); + bool CompressString(std::string& str); std::string GetCDashVersion(); @@ -424,7 +432,8 @@ private: bool RunConfigurationScript; //flag for lazy getter (optimization) - bool ComputedCompressOutput; + bool ComputedCompressTestOutput; + bool ComputedCompressMemCheckOutput; int GenerateNotesFile(const char* files); @@ -481,8 +490,8 @@ private: bool ShortDateFormat; bool CompressXMLFiles; - bool CompressTestOutput; + bool CompressMemCheckOutput; void InitStreams(); std::ostream* StreamOut; @@ -515,7 +524,7 @@ private: //! Reread the configuration file bool UpdateCTestConfiguration(); - //! Create not from files. + //! Create note from files. int GenerateCTestNotesOutput(std::ostream& os, const VectorOfStrings& files); diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index f2431e6..ea25e60 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -546,7 +546,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "make based generators. If this variable is supported, " "then CMake will also provide initial values for the " "variables with the name " - " CMAKE_C_FLAGS_[Debug|Release|RelWithDebInfo|MinSizeRel]." + " CMAKE_C_FLAGS_[DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL]." " For example, if CMAKE_BUILD_TYPE is Debug, then " "CMAKE_C_FLAGS_DEBUG will be added to the CMAKE_C_FLAGS.",false, "Variables That Change Behavior"); @@ -822,6 +822,18 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "set to the output of uname -r. On other " "systems this is set to major-minor version numbers.",false, "Variables That Describe the System"); + cm->DefineProperty + ("CMAKE_LIBRARY_ARCHITECTURE", cmProperty::VARIABLE, + "Target architecture library directory name, if detected.", + "This is the value of CMAKE_<lang>_LIBRARY_ARCHITECTURE as " + "detected for one of the enabled languages.",false, + "Variables That Describe the System"); + cm->DefineProperty + ("CMAKE_LIBRARY_ARCHITECTURE_REGEX", cmProperty::VARIABLE, + "Regex matching possible target architecture library directory names.", + "This is used to detect CMAKE_<lang>_LIBRARY_ARCHITECTURE from the " + "implicit linker search path by matching the <arch> name.",false, + "Variables That Describe the System"); cm->DefineProperty ("CMAKE_HOST_SYSTEM", cmProperty::VARIABLE, @@ -1360,6 +1372,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "Variables for Languages"); cm->DefineProperty + ("CMAKE_<LANG>_LIBRARY_ARCHITECTURE", cmProperty::VARIABLE, + "Target architecture library directory name detected for <lang>.", + "If the <lang> compiler passes to the linker an architecture-specific " + "system library search directory such as <prefix>/lib/<arch> this " + "variable contains the <arch> name if/as detected by CMake.",false, + "Variables for Languages"); + + cm->DefineProperty ("CMAKE_<LANG>_LINKER_PREFERENCE_PROPAGATES", cmProperty::VARIABLE, "True if CMAKE_<LANG>_LINKER_PREFERENCE propagates across targets.", "This is used when CMake selects a linker language for a target. " diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index c4ea425..8e26b8e 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -403,7 +403,7 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() // for each sub project create a linked resource to the source dir // - only if it is an out-of-source build this->AppendLinkedResource(fout, "[Subprojects]", - "virtual:/virtual"); + "virtual:/virtual", true); for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator it = this->GlobalGenerator->GetProjectMap().begin(); @@ -1082,17 +1082,24 @@ void cmExtraEclipseCDT4Generator void cmExtraEclipseCDT4Generator ::AppendLinkedResource (cmGeneratedFileStream& fout, const std::string& name, - const std::string& path) + const std::string& path, + bool isVirtualFolder) { + const char* locationTag = "location"; + if (isVirtualFolder) // ... and not a linked folder + { + locationTag = "locationURI"; + } + fout << "\t\t<link>\n" "\t\t\t<name>" << cmExtraEclipseCDT4Generator::EscapeForXML(name) << "</name>\n" "\t\t\t<type>2</type>\n" - "\t\t\t<locationURI>" + "\t\t\t<" << locationTag << ">" << cmExtraEclipseCDT4Generator::EscapeForXML(path) - << "</locationURI>\n" + << "</" << locationTag << ">\n" "\t\t</link>\n" ; } diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h index 99e69c4..a683731 100644 --- a/Source/cmExtraEclipseCDT4Generator.h +++ b/Source/cmExtraEclipseCDT4Generator.h @@ -87,7 +87,8 @@ private: static void AppendLinkedResource (cmGeneratedFileStream& fout, const std::string& name, - const std::string& path); + const std::string& path, + bool isVirtualFolder = false); bool AppendOutLinkedResource(cmGeneratedFileStream& fout, const std::string& defname, diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index d28de08..9a3de9b 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -2614,6 +2614,7 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) ++i; long timeout = 0; + long inactivity_timeout = 0; std::string verboseLog; std::string statusVar; std::string expectedMD5sum; @@ -2634,6 +2635,19 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) return false; } } + else if(*i == "INACTIVITY_TIMEOUT") + { + ++i; + if(i != args.end()) + { + inactivity_timeout = atol(i->c_str()); + } + else + { + this->SetError("DOWNLOAD missing time for INACTIVITY_TIMEOUT."); + return false; + } + } else if(*i == "LOG") { ++i; @@ -2770,6 +2784,13 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) check_curl_result(res, "DOWNLOAD cannot set timeout: "); } + if(inactivity_timeout > 0) + { + // Give up if there is no progress for a long time. + ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1); + ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, inactivity_timeout); + } + // Need the progress helper's scope to last through the duration of // the curl_easy_perform call... so this object is declared at function // scope intentionally, rather than inside the "if(showProgress)" @@ -2883,6 +2904,7 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) ++i; long timeout = 0; + long inactivity_timeout = 0; std::string logVar; std::string statusVar; bool showProgress = false; @@ -2902,6 +2924,19 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) return false; } } + else if(*i == "INACTIVITY_TIMEOUT") + { + ++i; + if(i != args.end()) + { + inactivity_timeout = atol(i->c_str()); + } + else + { + this->SetError("UPLOAD missing time for INACTIVITY_TIMEOUT."); + return false; + } + } else if(*i == "LOG") { ++i; @@ -3003,6 +3038,13 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) check_curl_result(res, "UPLOAD cannot set timeout: "); } + if(inactivity_timeout > 0) + { + // Give up if there is no progress for a long time. + ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1); + ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, inactivity_timeout); + } + // Need the progress helper's scope to last through the duration of // the curl_easy_perform call... so this object is declared at function // scope intentionally, rather than inside the "if(showProgress)" diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index 1b6dbbf..162890a 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -80,10 +80,11 @@ public: " file(RELATIVE_PATH variable directory file)\n" " file(TO_CMAKE_PATH path result)\n" " file(TO_NATIVE_PATH path result)\n" - " file(DOWNLOAD url file [TIMEOUT timeout] [STATUS status] [LOG log]\n" - " [EXPECTED_MD5 sum] [SHOW_PROGRESS])\n" - " file(UPLOAD filename url [TIMEOUT timeout] [STATUS status]\n" - " [LOG log] [SHOW_PROGRESS])\n" + " file(DOWNLOAD url file [INACTIVITY_TIMEOUT timeout]\n" + " [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS]\n" + " [EXPECTED_MD5 sum])\n" + " file(UPLOAD filename url [INACTIVITY_TIMEOUT timeout]\n" + " [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS])\n" "WRITE will write a message into a file called 'filename'. It " "overwrites the file if it already exists, and creates the file " "if it does not exist.\n" @@ -161,6 +162,8 @@ public: "numeric error means no error in the operation. " "If TIMEOUT time is specified, the operation will " "timeout after time seconds, time should be specified as an integer. " + "The INACTIVITY_TIMEOUT specifies an integer number of seconds of " + "inactivity after which the operation should terminate. " "If EXPECTED_MD5 sum is specified, the operation will verify that the " "downloaded file's actual md5 sum matches the expected value. If it " "does not match, the operation fails with an error. " @@ -176,6 +179,8 @@ public: "numeric error means no error in the operation. " "If TIMEOUT time is specified, the operation will " "timeout after time seconds, time should be specified as an integer. " + "The INACTIVITY_TIMEOUT specifies an integer number of seconds of " + "inactivity after which the operation should terminate. " "If SHOW_PROGRESS is specified, progress information will be printed " "as status messages until the operation is complete." "\n" diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index d0fe99f..ce9deb1 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -72,12 +72,14 @@ void cmFindBase::GenerateDocumentation() "1. Search paths specified in cmake-specific cache variables. " "These are intended to be used on the command line with a -DVAR=value. " "This can be skipped if NO_CMAKE_PATH is passed.\n" + "XXX_EXTRA_PREFIX_ENTRY" " <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n" " CMAKE_XXX_PATH\n" " CMAKE_XXX_MAC_PATH\n" "2. Search paths specified in cmake-specific environment variables. " "These are intended to be set in the user's shell configuration. " "This can be skipped if NO_CMAKE_ENVIRONMENT_PATH is passed.\n" + "XXX_EXTRA_PREFIX_ENTRY" " <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n" " CMAKE_XXX_PATH\n" " CMAKE_XXX_MAC_PATH\n" @@ -92,6 +94,7 @@ void cmFindBase::GenerateDocumentation() "5. Search cmake variables defined in the Platform files " "for the current system. This can be skipped if NO_CMAKE_SYSTEM_PATH " "is passed.\n" + "XXX_EXTRA_PREFIX_ENTRY" " <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_SYSTEM_PREFIX_PATH\n" " CMAKE_SYSTEM_XXX_PATH\n" " CMAKE_SYSTEM_XXX_MAC_PATH\n" @@ -346,6 +349,15 @@ void cmFindBase::AddPrefixPaths(std::vector<std::string> const& in_paths, { dir += "/"; } + if(subdir == "lib") + { + const char* arch = + this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE"); + if(arch && *arch) + { + this->AddPathInternal(dir+"lib/"+arch, pathType); + } + } std::string add = dir + subdir; if(add != "/") { diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index b309376..6355a85 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -44,6 +44,10 @@ void cmFindLibraryCommand::GenerateDocumentation() "SEARCH_XXX", "library"); cmSystemTools::ReplaceString(this->GenericDocumentation, "XXX_SUBDIR", "lib"); + cmSystemTools::ReplaceString( + this->GenericDocumentation, + "XXX_EXTRA_PREFIX_ENTRY", + " <prefix>/lib/<arch> if CMAKE_LIBRARY_ARCHITECTURE is set, and\n"); cmSystemTools::ReplaceString(this->GenericDocumentation, "CMAKE_FIND_ROOT_PATH_MODE_XXX", "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY"); diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index fdc1a01..5f106bc 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -54,7 +54,8 @@ cmFindPackageCommand::cmFindPackageCommand() this->CMakePathName = "PACKAGE"; this->Quiet = false; this->Required = false; - this->NoRegistry = false; + this->NoUserRegistry = false; + this->NoSystemRegistry = false; this->NoBuilds = false; this->NoModule = false; this->DebugMode = false; @@ -101,9 +102,10 @@ void cmFindPackageCommand::GenerateDocumentation() "The [version] argument requests a version with which the package found " "should be compatible (format is major[.minor[.patch[.tweak]]]). " "The EXACT option requests that the version be matched exactly. " - "If no [version] is given to a recursive invocation inside a " - "find-module, the [version] and EXACT arguments are forwarded " - "automatically from the outer call. " + "If no [version] and/or component list is given to a recursive " + "invocation inside a find-module, the corresponding arguments " + "are forwarded automatically from the outer call (including the " + "EXACT flag for [version]). " "Version support is currently provided only on a package-by-package " "basis (details below).\n" "User code should generally look for packages using the above simple " @@ -139,6 +141,7 @@ void cmFindPackageCommand::GenerateDocumentation() " [NO_CMAKE_PACKAGE_REGISTRY]\n" " [NO_CMAKE_BUILDS_PATH]\n" " [NO_CMAKE_SYSTEM_PATH]\n" + " [NO_CMAKE_SYSTEM_PACKAGE_REGISTRY]\n" " [CMAKE_FIND_ROOT_PATH_BOTH |\n" " ONLY_CMAKE_FIND_ROOT_PATH |\n" " NO_CMAKE_FIND_ROOT_PATH])\n" @@ -240,9 +243,9 @@ void cmFindPackageCommand::GenerateDocumentation() " <prefix>/(cmake|CMake)/ (W)\n" " <prefix>/<name>*/ (W)\n" " <prefix>/<name>*/(cmake|CMake)/ (W)\n" - " <prefix>/(share|lib)/cmake/<name>*/ (U)\n" - " <prefix>/(share|lib)/<name>*/ (U)\n" - " <prefix>/(share|lib)/<name>*/(cmake|CMake)/ (U)\n" + " <prefix>/(lib/<arch>|lib|share)/cmake/<name>*/ (U)\n" + " <prefix>/(lib/<arch>|lib|share)/<name>*/ (U)\n" + " <prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/ (U)\n" "On systems supporting OS X Frameworks and Application Bundles " "the following directories are searched for frameworks or bundles " "containing a configuration file:\n" @@ -254,6 +257,7 @@ void cmFindPackageCommand::GenerateDocumentation() " <prefix>/<name>.app/Contents/Resources/CMake/ (A)\n" "In all cases the <name> is treated as case-insensitive and corresponds " "to any of the names specified (<package> or names given by NAMES). " + "Paths with lib/<arch> are enabled if CMAKE_LIBRARY_ARCHITECTURE is set. " "If PATH_SUFFIXES is specified the suffixes are appended to each " "(W) or (U) directory entry one-by-one.\n" "This set of directories is intended to work in cooperation with " @@ -298,9 +302,16 @@ void cmFindPackageCommand::GenerateDocumentation() "dependent projects one after another.\n" "6. Search paths stored in the CMake user package registry. " "This can be skipped if NO_CMAKE_PACKAGE_REGISTRY is passed. " - "Paths are stored in the registry when CMake configures a project " - "that invokes export(PACKAGE <name>). " - "See the export(PACKAGE) command documentation for more details." + "On Windows a <package> may appear under registry key\n" + " HKEY_CURRENT_USER\\Software\\Kitware\\CMake\\Packages\\<package>\n" + "as a REG_SZ value, with arbitrary name, that specifies the directory " + "containing the package configuration file. " + "On UNIX platforms a <package> may appear under the directory\n" + " ~/.cmake/packages/<package>\n" + "as a file, with arbitrary name, whose content specifies the directory " + "containing the package configuration file. " + "See the export(PACKAGE) command to create user package registry entries " + "for project build trees." "\n" "7. Search cmake variables defined in the Platform files " "for the current system. This can be skipped if NO_CMAKE_SYSTEM_PATH " @@ -308,7 +319,15 @@ void cmFindPackageCommand::GenerateDocumentation() " CMAKE_SYSTEM_PREFIX_PATH\n" " CMAKE_SYSTEM_FRAMEWORK_PATH\n" " CMAKE_SYSTEM_APPBUNDLE_PATH\n" - "8. Search paths specified by the PATHS option. " + "8. Search paths stored in the CMake system package registry. " + "This can be skipped if NO_CMAKE_SYSTEM_PACKAGE_REGISTRY is passed. " + "On Windows a <package> may appear under registry key\n" + " HKEY_LOCAL_MACHINE\\Software\\Kitware\\CMake\\Packages\\<package>\n" + "as a REG_SZ value, with arbitrary name, that specifies the directory " + "containing the package configuration file. " + "There is no system package registry on non-Windows platforms." + "\n" + "9. Search paths specified by the PATHS option. " "These are typically hard-coded guesses.\n" ; this->CommandDocumentation += this->GenericDocumentationMacPolicy; @@ -344,6 +363,13 @@ bool cmFindPackageCommand // Check for debug mode. this->DebugMode = this->Makefile->IsOn("CMAKE_FIND_DEBUG_MODE"); + // Lookup target architecture, if any. + if(const char* arch = + this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) + { + this->LibraryArchitecture = arch; + } + // Lookup whether lib64 paths should be used. if(this->Makefile->PlatformIs64Bit() && this->Makefile->GetCMakeInstance() @@ -443,7 +469,14 @@ bool cmFindPackageCommand } else if(args[i] == "NO_CMAKE_PACKAGE_REGISTRY") { - this->NoRegistry = true; + this->NoUserRegistry = true; + this->NoModule = true; + this->Compatibility_1_6 = false; + doing = DoingNone; + } + else if(args[i] == "NO_CMAKE_SYSTEM_PACKAGE_REGISTRY") + { + this->NoSystemRegistry = true; this->NoModule = true; this->Compatibility_1_6 = false; doing = DoingNone; @@ -524,7 +557,7 @@ bool cmFindPackageCommand cmake::AUTHOR_WARNING, "Ignoring EXACT since no version is requested."); } - if(this->Version.empty()) + if(this->Version.empty() || components.empty()) { // Check whether we are recursing inside "Find<name>.cmake" within // another find_package(<name>) call. @@ -532,16 +565,24 @@ bool cmFindPackageCommand mod += "_FIND_MODULE"; if(this->Makefile->IsOn(mod.c_str())) { - // Get version information from the outer call if necessary. - // Requested version string. - std::string ver = this->Name; - ver += "_FIND_VERSION"; - this->Version = this->Makefile->GetSafeDefinition(ver.c_str()); - - // Whether an exact version is required. - std::string exact = this->Name; - exact += "_FIND_VERSION_EXACT"; - this->VersionExact = this->Makefile->IsOn(exact.c_str()); + if(this->Version.empty()) + { + // Get version information from the outer call if necessary. + // Requested version string. + std::string ver = this->Name; + ver += "_FIND_VERSION"; + this->Version = this->Makefile->GetSafeDefinition(ver.c_str()); + + // Whether an exact version is required. + std::string exact = this->Name; + exact += "_FIND_VERSION_EXACT"; + this->VersionExact = this->Makefile->IsOn(exact.c_str()); + } + if(components.empty()) + { + std::string components_var = this->Name + "_FIND_COMPONENTS"; + components = this->Makefile->GetSafeDefinition(components_var.c_str()); + } } } @@ -1172,9 +1213,10 @@ void cmFindPackageCommand::ComputePrefixes() this->AddPrefixesCMakeEnvironment(); this->AddPrefixesUserHints(); this->AddPrefixesSystemEnvironment(); - this->AddPrefixesRegistry(); + this->AddPrefixesUserRegistry(); this->AddPrefixesBuilds(); this->AddPrefixesCMakeSystemVariable(); + this->AddPrefixesSystemRegistry(); this->AddPrefixesUserGuess(); this->ComputeFinalPrefixes(); } @@ -1240,15 +1282,15 @@ void cmFindPackageCommand::AddPrefixesSystemEnvironment() } //---------------------------------------------------------------------------- -void cmFindPackageCommand::AddPrefixesRegistry() +void cmFindPackageCommand::AddPrefixesUserRegistry() { - if(this->NoRegistry || this->NoDefaultPath) + if(this->NoUserRegistry || this->NoDefaultPath) { return; } #if defined(_WIN32) && !defined(__CYGWIN__) - this->LoadPackageRegistryWin(); + this->LoadPackageRegistryWinUser(); #elif defined(__HAIKU__) BPath dir; if (find_directory(B_USER_SETTINGS_DIRECTORY, &dir) == B_OK) @@ -1268,18 +1310,63 @@ void cmFindPackageCommand::AddPrefixesRegistry() #endif } +//---------------------------------------------------------------------------- +void cmFindPackageCommand::AddPrefixesSystemRegistry() +{ + if(this->NoSystemRegistry || this->NoDefaultPath) + { + return; + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + this->LoadPackageRegistryWinSystem(); +#endif +} + #if defined(_WIN32) && !defined(__CYGWIN__) # include <windows.h> # undef GetCurrentDirectory + // http://msdn.microsoft.com/en-us/library/aa384253%28v=vs.85%29.aspx +# if !defined(KEY_WOW64_32KEY) +# define KEY_WOW64_32KEY 0x0200 +# endif +# if !defined(KEY_WOW64_64KEY) +# define KEY_WOW64_64KEY 0x0100 +# endif +//---------------------------------------------------------------------------- +void cmFindPackageCommand::LoadPackageRegistryWinUser() +{ + // HKEY_CURRENT_USER\\Software shares 32-bit and 64-bit views. + this->LoadPackageRegistryWin(true, 0); +} + +//---------------------------------------------------------------------------- +void cmFindPackageCommand::LoadPackageRegistryWinSystem() +{ + // HKEY_LOCAL_MACHINE\\SOFTWARE has separate 32-bit and 64-bit views. + // Prefer the target platform view first. + if(this->Makefile->PlatformIs64Bit()) + { + this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY); + this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY); + } + else + { + this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY); + this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY); + } +} + //---------------------------------------------------------------------------- -void cmFindPackageCommand::LoadPackageRegistryWin() +void cmFindPackageCommand::LoadPackageRegistryWin(bool user, + unsigned int view) { std::string key = "Software\\Kitware\\CMake\\Packages\\"; key += this->Name; std::set<cmStdString> bad; HKEY hKey; - if(RegOpenKeyEx(HKEY_CURRENT_USER, key.c_str(), - 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) + if(RegOpenKeyEx(user? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, key.c_str(), + 0, KEY_QUERY_VALUE|view, &hKey) == ERROR_SUCCESS) { DWORD valueType = REG_NONE; char name[16384]; @@ -1299,13 +1386,12 @@ void cmFindPackageCommand::LoadPackageRegistryWin() { data[dataSize] = 0; cmsys_ios::stringstream ss(&data[0]); - if(this->CheckPackageRegistryEntry(ss)) + if(!this->CheckPackageRegistryEntry(ss)) { - // The entry is okay. - continue; + // The entry is invalid. + bad.insert(name); } } - bad.insert(name); break; case ERROR_MORE_DATA: data.resize(dataSize+1); @@ -1317,9 +1403,9 @@ void cmFindPackageCommand::LoadPackageRegistryWin() } // Remove bad values if possible. - if(!bad.empty() && + if(user && !bad.empty() && RegOpenKeyEx(HKEY_CURRENT_USER, key.c_str(), - 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) + 0, KEY_SET_VALUE|view, &hKey) == ERROR_SUCCESS) { for(std::set<cmStdString>::const_iterator vi = bad.begin(); vi != bad.end(); ++vi) @@ -2111,6 +2197,10 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) // Construct list of common install locations (lib and share). std::vector<std::string> common; + if(!this->LibraryArchitecture.empty()) + { + common.push_back("lib/"+this->LibraryArchitecture); + } if(this->UseLib64Paths) { common.push_back("lib64"); @@ -2118,7 +2208,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) common.push_back("lib"); common.push_back("share"); - // PREFIX/(share|lib)/cmake/(Foo|foo|FOO).*/ + // PREFIX/(lib/ARCH|lib|share)/cmake/(Foo|foo|FOO).*/ { cmFindPackageFileList lister(this); lister @@ -2132,7 +2222,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) } } - // PREFIX/(share|lib)/(Foo|foo|FOO).*/ + // PREFIX/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/ { cmFindPackageFileList lister(this); lister @@ -2145,7 +2235,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) } } - // PREFIX/(share|lib)/(Foo|foo|FOO).*/(cmake|CMake)/ + // PREFIX/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/(cmake|CMake)/ { cmFindPackageFileList lister(this); lister @@ -2277,11 +2367,3 @@ bool cmFindPackageCommand::SearchAppBundlePrefix(std::string const& prefix_in) } // TODO: Debug cmsys::Glob double slash problem. - -// TODO: Add registry entries after cmake system search path? -// Currently the user must specify them with the PATHS option. -// -// [HKEY_CURRENT_USER\Software\*\Foo*;InstallDir] -// [HKEY_CURRENT_USER\Software\*\*\Foo*;InstallDir] -// [HKEY_LOCAL_MACHINE\Software\*\Foo*;InstallDir] -// [HKEY_LOCAL_MACHINE\Software\*\*\Foo*;InstallDir] diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 19d2b10..2b2e1da 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -87,14 +87,17 @@ private: void AddPrefixesCMakeEnvironment(); void AddPrefixesCMakeVariable(); void AddPrefixesSystemEnvironment(); - void AddPrefixesRegistry(); + void AddPrefixesUserRegistry(); + void AddPrefixesSystemRegistry(); void AddPrefixesBuilds(); void AddPrefixesCMakeSystemVariable(); void AddPrefixesUserGuess(); void AddPrefixesUserHints(); void ComputeFinalPrefixes(); void LoadPackageRegistryDir(std::string const& dir); - void LoadPackageRegistryWin(); + void LoadPackageRegistryWinUser(); + void LoadPackageRegistryWinSystem(); + void LoadPackageRegistryWin(bool user, unsigned int view); bool CheckPackageRegistryEntry(std::istream& is); bool SearchDirectory(std::string const& dir); bool CheckDirectory(std::string const& dir); @@ -132,11 +135,13 @@ private: bool Required; bool Compatibility_1_6; bool NoModule; - bool NoRegistry; + bool NoUserRegistry; + bool NoSystemRegistry; bool NoBuilds; bool DebugMode; bool UseLib64Paths; bool PolicyScope; + std::string LibraryArchitecture; std::vector<std::string> Names; std::vector<std::string> Configs; std::set<std::string> IgnoredPaths; diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx index 83b651b..846d187 100644 --- a/Source/cmFindPathCommand.cxx +++ b/Source/cmFindPathCommand.cxx @@ -46,6 +46,8 @@ void cmFindPathCommand::GenerateDocumentation() cmSystemTools::ReplaceString(this->GenericDocumentation, "XXX_SUBDIR", "include"); cmSystemTools::ReplaceString(this->GenericDocumentation, + "XXX_EXTRA_PREFIX_ENTRY", ""); + cmSystemTools::ReplaceString(this->GenericDocumentation, "CMAKE_FIND_ROOT_PATH_MODE_XXX", "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE"); if(!this->IncludeFileInPath) diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 71cfdcb..7c56ad7 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -42,6 +42,8 @@ void cmFindProgramCommand::GenerateDocumentation() cmSystemTools::ReplaceString(this->GenericDocumentation, "XXX_SUBDIR", "[s]bin"); cmSystemTools::ReplaceString(this->GenericDocumentation, + "XXX_EXTRA_PREFIX_ENTRY", ""); + cmSystemTools::ReplaceString(this->GenericDocumentation, "CMAKE_FIND_ROOT_PATH_MODE_XXX", "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM"); } diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 8710dfc..f88ab0b 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -23,7 +23,7 @@ cmGeneratorExpression::cmGeneratorExpression( this->TargetInfo.compile("^\\$<TARGET" "(|_SONAME|_LINKER)" // File with what purpose? "_FILE(|_NAME|_DIR):" // Filename component. - "([A-Za-z0-9_-]+)" // Target name. + "([A-Za-z0-9_.-]+)" // Target name. ">$"); } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index d47fb6f..6c8938e 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -903,8 +903,6 @@ void cmGlobalGenerator::Generate() } this->CMakeInstance->UpdateProgress("Generating done", -1); - - this->CMakeInstance->RunCheckForUnusedVariables("generation"); } //---------------------------------------------------------------------------- diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index d9a341c..169d77d 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -24,13 +24,13 @@ cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3() this->ForceUnixPaths = true; this->FindMakeProgramFile = "CMakeUnixFindMake.cmake"; this->ToolSupportsColor = true; - this->NoRuleMessages = false; #if defined(_WIN32) || defined(__VMS) this->UseLinkScript = false; #else this->UseLinkScript = true; #endif + this->CommandDatabase = NULL; } void cmGlobalUnixMakefileGenerator3 @@ -139,56 +139,87 @@ void cmGlobalUnixMakefileGenerator3 } //---------------------------------------------------------------------------- +std::string EscapeJSON(const std::string& s) { + std::string result; + for (std::string::size_type i = 0; i < s.size(); ++i) { + if (s[i] == '"' || s[i] == '\\') { + result += '\\'; + } + result += s[i]; + } + return result; +} + void cmGlobalUnixMakefileGenerator3::Generate() { // first do superclass method this->cmGlobalGenerator::Generate(); - cmake* cm = this->GetCMakeInstance(); - if(const char* ruleStatus = cm->GetProperty("RULE_MESSAGES")) + // initialize progress + unsigned long total = 0; + for(ProgressMapType::const_iterator pmi = this->ProgressMap.begin(); + pmi != this->ProgressMap.end(); ++pmi) { - this->NoRuleMessages = cmSystemTools::IsOff(ruleStatus); + total += pmi->second.NumberOfActions; } - if(!this->NoRuleMessages) + // write each target's progress.make this loop is done twice. Bascially the + // Generate pass counts all the actions, the first loop below determines + // how many actions have progress updates for each target and writes to + // corrrect variable values for everything except the all targets. The + // second loop actually writes out correct values for the all targets as + // well. This is because the all targets require more information that is + // computed in the first loop. + unsigned long current = 0; + for(ProgressMapType::iterator pmi = this->ProgressMap.begin(); + pmi != this->ProgressMap.end(); ++pmi) { - // initialize progress - unsigned long total = 0; - for(ProgressMapType::const_iterator pmi = this->ProgressMap.begin(); - pmi != this->ProgressMap.end(); ++pmi) - { - total += pmi->second.NumberOfActions; - } - - // write each target's progress.make this loop is done twice. Bascially the - // Generate pass counts all the actions, the first loop below determines - // how many actions have progress updates for each target and writes to - // corrrect variable values for everything except the all targets. The - // second loop actually writes out correct values for the all targets as - // well. This is because the all targets require more information that is - // computed in the first loop. - unsigned long current = 0; - for(ProgressMapType::iterator pmi = this->ProgressMap.begin(); - pmi != this->ProgressMap.end(); ++pmi) - { - pmi->second.WriteProgressVariables(total, current); - } - for(unsigned int i = 0; i < this->LocalGenerators.size(); ++i) - { - cmLocalUnixMakefileGenerator3 *lg = - static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]); - std::string markFileName = lg->GetMakefile()->GetStartOutputDirectory(); - markFileName += "/"; - markFileName += cmake::GetCMakeFilesDirectory(); - markFileName += "/progress.marks"; - cmGeneratedFileStream markFile(markFileName.c_str()); - markFile << this->CountProgressMarksInAll(lg) << "\n"; - } + pmi->second.WriteProgressVariables(total, current); + } + for(unsigned int i = 0; i < this->LocalGenerators.size(); ++i) + { + cmLocalUnixMakefileGenerator3 *lg = + static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]); + std::string markFileName = lg->GetMakefile()->GetStartOutputDirectory(); + markFileName += "/"; + markFileName += cmake::GetCMakeFilesDirectory(); + markFileName += "/progress.marks"; + cmGeneratedFileStream markFile(markFileName.c_str()); + markFile << this->CountProgressMarksInAll(lg) << "\n"; } // write the main makefile this->WriteMainMakefile2(); this->WriteMainCMakefile(); + + if (this->CommandDatabase != NULL) { + *this->CommandDatabase << std::endl << "]"; + delete this->CommandDatabase; + this->CommandDatabase = NULL; + } +} + +void cmGlobalUnixMakefileGenerator3::AddCXXCompileCommand( + const std::string &sourceFile, const std::string &workingDirectory, + const std::string &compileCommand) { + if (this->CommandDatabase == NULL) + { + std::string commandDatabaseName = + std::string(this->GetCMakeInstance()->GetHomeOutputDirectory()) + + "/compile_commands.json"; + this->CommandDatabase = + new cmGeneratedFileStream(commandDatabaseName.c_str()); + *this->CommandDatabase << "[" << std::endl; + } else { + *this->CommandDatabase << "," << std::endl; + } + *this->CommandDatabase << "{" << std::endl + << " \"directory\": \"" << EscapeJSON(workingDirectory) << "\"," + << std::endl + << " \"command\": \"" << EscapeJSON(compileCommand) << "\"," + << std::endl + << " \"file\": \"" << EscapeJSON(sourceFile) << "\"" + << std::endl << "}"; } void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() @@ -747,34 +778,30 @@ cmGlobalUnixMakefileGenerator3 // Write the rule. localName += "/all"; depends.clear(); - std::string progressDir; - if(!this->NoRuleMessages) + std::string progressDir = + lg->GetMakefile()->GetHomeOutputDirectory(); + progressDir += cmake::GetCMakeFilesDirectory(); { - progressDir = - lg->GetMakefile()->GetHomeOutputDirectory(); - progressDir += cmake::GetCMakeFilesDirectory(); + cmOStringStream progCmd; + progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report "; + // all target counts + progCmd << lg->Convert(progressDir.c_str(), + cmLocalGenerator::FULL, + cmLocalGenerator::SHELL); + progCmd << " "; + std::vector<unsigned long>& progFiles = + this->ProgressMap[&t->second].Marks; + for (std::vector<unsigned long>::iterator i = progFiles.begin(); + i != progFiles.end(); ++i) { - cmOStringStream progCmd; - progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report "; - // all target counts - progCmd << lg->Convert(progressDir.c_str(), - cmLocalGenerator::FULL, - cmLocalGenerator::SHELL); - progCmd << " "; - std::vector<unsigned long>& progFiles = - this->ProgressMap[&t->second].Marks; - for (std::vector<unsigned long>::iterator i = progFiles.begin(); - i != progFiles.end(); ++i) - { - progCmd << " " << *i; - } - commands.push_back(progCmd.str()); + progCmd << " " << *i; } - progressDir = "Built target "; - progressDir += t->first; - lg->AppendEcho(commands,progressDir.c_str()); + commands.push_back(progCmd.str()); } + progressDir = "Built target "; + progressDir += t->first; + lg->AppendEcho(commands,progressDir.c_str()); this->AppendGlobalTargetDepends(depends,t->second); lg->WriteMakeRule(ruleFileStream, "All Build rule for target.", @@ -790,42 +817,38 @@ cmGlobalUnixMakefileGenerator3 "all", depends, commands, true); } - if(!this->NoRuleMessages) - { - // Write the rule. - commands.clear(); - progressDir = lg->GetMakefile()->GetHomeOutputDirectory(); - progressDir += cmake::GetCMakeFilesDirectory(); + // Write the rule. + commands.clear(); + progressDir = lg->GetMakefile()->GetHomeOutputDirectory(); + progressDir += cmake::GetCMakeFilesDirectory(); - { - // TODO: Convert the total progress count to a make variable. - cmOStringStream progCmd; - progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; - // # in target - progCmd << lg->Convert(progressDir.c_str(), - cmLocalGenerator::FULL, - cmLocalGenerator::SHELL); - // - std::set<cmTarget *> emitted; - progCmd << " " - << this->CountProgressMarksInTarget(&t->second, emitted); - commands.push_back(progCmd.str()); - } - } + { + // TODO: Convert the total progress count to a make variable. + cmOStringStream progCmd; + progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; + // # in target + progCmd << lg->Convert(progressDir.c_str(), + cmLocalGenerator::FULL, + cmLocalGenerator::SHELL); + // + std::set<cmTarget *> emitted; + progCmd << " " + << this->CountProgressMarksInTarget(&t->second, emitted); + commands.push_back(progCmd.str()); + } std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash(); tmp += "Makefile2"; commands.push_back(lg->GetRecursiveMakeCall (tmp.c_str(),localName.c_str())); - if(!this->NoRuleMessages) - { - cmOStringStream progCmd; - progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0 - progCmd << lg->Convert(progressDir.c_str(), - cmLocalGenerator::FULL, - cmLocalGenerator::SHELL); - progCmd << " 0"; - commands.push_back(progCmd.str()); - } + { + cmOStringStream progCmd; + progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0 + progCmd << lg->Convert(progressDir.c_str(), + cmLocalGenerator::FULL, + cmLocalGenerator::SHELL); + progCmd << " 0"; + commands.push_back(progCmd.str()); + } depends.clear(); depends.push_back("cmake_check_build_system"); localName = lg->GetRelativeTargetDirectory(t->second); diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index cdc9460..d21d5b9 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -112,6 +112,10 @@ public: /** Record per-target progress information. */ void RecordTargetProgress(cmMakefileTargetGenerator* tg); + void AddCXXCompileCommand(const std::string &sourceFile, + const std::string &workingDirectory, + const std::string &compileCommand); + protected: void WriteMainMakefile2(); void WriteMainCMakefile(); @@ -159,8 +163,6 @@ protected: // in the rule to satisfy the make program. std::string EmptyRuleHackCommand; - bool NoRuleMessages; - // Store per-target progress counters. struct TargetProgress { @@ -178,6 +180,8 @@ protected: size_t CountProgressMarksInTarget(cmTarget* target, std::set<cmTarget*>& emitted); size_t CountProgressMarksInAll(cmLocalUnixMakefileGenerator3* lg); + + cmGeneratedFileStream *CommandDatabase; }; #endif diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index d5c0fef..2cbd3ed 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -147,7 +147,7 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::New() } return gg.release(); #else - std::cerr << "CMake should be built with cmake to use XCode, " + std::cerr << "CMake should be built with cmake to use Xcode, " "default to Xcode 1.5\n"; return new cmGlobalXCodeGenerator; #endif @@ -323,6 +323,19 @@ void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator* root) } //---------------------------------------------------------------------------- +std::string +cmGlobalXCodeGenerator::PostBuildMakeTarget(std::string const& tName, + std::string const& configName) +{ + std::string out = "PostBuild." + tName; + if(this->XcodeVersion > 20) + { + out += "." + configName; + } + return out; +} + +//---------------------------------------------------------------------------- void cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, std::vector<cmLocalGenerator*>& gens) @@ -351,12 +364,8 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, makecommand.push_back(dir.c_str()); makecommand.push_back("-f"); makecommand.push_back(this->CurrentXCodeHackMakefile.c_str()); - if(this->XcodeVersion > 20) - { - makecommand.push_back("all.$(CONFIGURATION)"); - } - cmCustomCommandLines commandLines; - commandLines.push_back(makecommand); + makecommand.push_back(""); // placeholder, see below + // Add Re-Run CMake rules this->CreateReRunCMakeFile(root, gens); @@ -383,6 +392,10 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, target.GetType() == cmTarget::SHARED_LIBRARY || target.GetType() == cmTarget::MODULE_LIBRARY)) { + makecommand[makecommand.size()-1] = + this->PostBuildMakeTarget(target.GetName(), "$(CONFIGURATION)"); + cmCustomCommandLines commandLines; + commandLines.push_back(makecommand); lg->GetMakefile()->AddCustomCommandToTarget(target.GetName(), no_depends, commandLines, @@ -963,7 +976,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, this->CreateString("0")); } - // create list of build phases and create the XCode target + // create list of build phases and create the Xcode target cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST); @@ -2437,6 +2450,10 @@ void cmGlobalXCodeGenerator { linkLibs += li->Value; } + if(li->Target && !li->Target->IsImported()) + { + target->AddDependTarget(configName, li->Target->GetName()); + } } this->AppendBuildSettingAttribute(target, "OTHER_LDFLAGS", linkLibs.c_str(), configName); @@ -2500,62 +2517,119 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, } } +cmXCodeObject *cmGlobalXCodeGenerator +::CreatePBXGroup(cmXCodeObject *parent, cmStdString name) +{ + cmXCodeObject* parentChildren = NULL; + if(parent) + parentChildren = parent->GetObject("children"); + cmXCodeObject* group = this->CreateObject(cmXCodeObject::PBXGroup); + cmXCodeObject* groupChildren = + this->CreateObject(cmXCodeObject::OBJECT_LIST); + group->AddAttribute("name", this->CreateString(name.c_str())); + group->AddAttribute("children", groupChildren); + if(this->XcodeVersion == 15) + { + group->AddAttribute("refType", this->CreateString("4")); + } + group->AddAttribute("sourceTree", this->CreateString("<group>")); + if(parentChildren) + parentChildren->AddObject(group); + return group; +} + //---------------------------------------------------------------------------- cmXCodeObject* cmGlobalXCodeGenerator ::CreateOrGetPBXGroup(cmTarget& cmtarget, cmSourceGroup* sg) { - cmStdString s = cmtarget.GetName(); - s += "/"; - s += sg->GetName(); - std::map<cmStdString, cmXCodeObject* >::iterator i = + cmStdString s; + cmStdString target; + const char *targetFolder= cmtarget.GetProperty("FOLDER"); + if(targetFolder) { + target = targetFolder; + target += "/"; + } + target += cmtarget.GetName(); + s = target + "/"; + s += sg->GetFullName(); + std::map<cmStdString, cmXCodeObject* >::iterator it = this->GroupNameMap.find(s); - if(i != this->GroupNameMap.end()) + if(it != this->GroupNameMap.end()) { - return i->second; + return it->second; } - i = this->TargetGroup.find(cmtarget.GetName()); + + it = this->TargetGroup.find(target); cmXCodeObject* tgroup = 0; - if(i != this->TargetGroup.end()) + if(it != this->TargetGroup.end()) { - tgroup = i->second; + tgroup = it->second; } else { - tgroup = this->CreateObject(cmXCodeObject::PBXGroup); - this->TargetGroup[cmtarget.GetName()] = tgroup; - cmXCodeObject* tgroupChildren = - this->CreateObject(cmXCodeObject::OBJECT_LIST); - tgroup->AddAttribute("name", this->CreateString(cmtarget.GetName())); - tgroup->AddAttribute("children", tgroupChildren); - if(this->XcodeVersion == 15) + std::vector<std::string> tgt_folders = + cmSystemTools::tokenize(target, "/"); + cmStdString curr_tgt_folder; + for(std::vector<std::string>::size_type i = 0; i < tgt_folders.size();i++) { - tgroup->AddAttribute("refType", this->CreateString("4")); + curr_tgt_folder += tgt_folders[i]; + it = this->TargetGroup.find(curr_tgt_folder); + if(it == this->TargetGroup.end()) + { + tgroup = this->CreatePBXGroup(tgroup,tgt_folders[i]); + this->TargetGroup[curr_tgt_folder] = tgroup; + } + else + { + tgroup = it->second; + continue; + } + if(i == 0) + { + this->SourcesGroupChildren->AddObject(tgroup); + } + curr_tgt_folder += "/"; } - tgroup->AddAttribute("sourceTree", this->CreateString("<group>")); - this->SourcesGroupChildren->AddObject(tgroup); } + this->TargetGroup[target] = tgroup; // If it's the default source group (empty name) then put the source file // directly in the tgroup... // - if (cmStdString(sg->GetName()) == "") + if (cmStdString(sg->GetFullName()) == "") { this->GroupNameMap[s] = tgroup; return tgroup; } - cmXCodeObject* tgroupChildren = tgroup->GetObject("children"); - cmXCodeObject* group = this->CreateObject(cmXCodeObject::PBXGroup); - cmXCodeObject* groupChildren = - this->CreateObject(cmXCodeObject::OBJECT_LIST); - group->AddAttribute("name", this->CreateString(sg->GetName())); - group->AddAttribute("children", groupChildren); - if(this->XcodeVersion == 15) + //It's a recursive folder structure, let's find the real parent group + if(std::string(sg->GetFullName()) != std::string(sg->GetName())) { - group->AddAttribute("refType", this->CreateString("4")); + std::vector<std::string> folders = + cmSystemTools::tokenize(sg->GetFullName(), "\\"); + cmStdString curr_folder = cmtarget.GetName(); + curr_folder += "/"; + for(std::vector<std::string>::size_type i = 0; i < folders.size();i++) + { + curr_folder += folders[i]; + std::map<cmStdString, cmXCodeObject* >::iterator i_folder = + this->GroupNameMap.find(curr_folder); + //Create new folder + if(i_folder == this->GroupNameMap.end()) + { + cmXCodeObject *group = this->CreatePBXGroup(tgroup,folders[i]); + this->GroupNameMap[curr_folder] = group; + tgroup = group; + } + else + { + tgroup = i_folder->second; + } + curr_folder = curr_folder + "\\"; + } + return tgroup; } - group->AddAttribute("sourceTree", this->CreateString("<group>")); - tgroupChildren->AddObject(group); + cmXCodeObject *group = this->CreatePBXGroup(tgroup,sg->GetName()); this->GroupNameMap[s] = group; return group; } @@ -2882,41 +2956,10 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( // correctly by xcode makefileStream << "# DO NOT EDIT\n"; makefileStream << "# This makefile makes sure all linkable targets are\n"; - makefileStream << "# up-to-date with anything they link to, avoiding a " - "bug in XCode 1.5\n"; - for(std::vector<std::string>::const_iterator - ct = this->CurrentConfigurationTypes.begin(); - ct != this->CurrentConfigurationTypes.end(); ++ct) - { - if(this->XcodeVersion < 21 || ct->empty()) - { - makefileStream << "all: "; - } - else - { - makefileStream << "all." << *ct << ": "; - } - const char* configName = 0; - if(!ct->empty()) - { - configName = ct->c_str(); - } - for(std::vector<cmXCodeObject*>::iterator i = targets.begin(); - i != targets.end(); ++i) - { - cmXCodeObject* target = *i; - cmTarget* t =target->GetTarget(); - if(t->GetType() == cmTarget::EXECUTABLE || - t->GetType() == cmTarget::SHARED_LIBRARY || - t->GetType() == cmTarget::MODULE_LIBRARY) - { - std::string tfull = t->GetFullPath(configName); - makefileStream << "\\\n\t" << - this->ConvertToRelativeForMake(tfull.c_str()); - } - } - makefileStream << "\n\n"; - } + makefileStream << "# up-to-date with anything they link to\n" + "default:\n" + "\techo \"Do not invoke directly\"\n" + "\n"; makefileStream << "# For each target create a dummy rule " "so the target does not have to exist\n"; @@ -2962,14 +3005,40 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( { cmXCodeObject* target = *i; cmTarget* t =target->GetTarget(); + + if(t->GetType() == cmTarget::EXECUTABLE || + t->GetType() == cmTarget::STATIC_LIBRARY || + t->GetType() == cmTarget::SHARED_LIBRARY || + t->GetType() == cmTarget::MODULE_LIBRARY) + { + // Declare an entry point for the target post-build phase. + makefileStream << this->PostBuildMakeTarget(t->GetName(), *ct) + << ":\n"; + } + if(t->GetType() == cmTarget::EXECUTABLE || t->GetType() == cmTarget::SHARED_LIBRARY || t->GetType() == cmTarget::MODULE_LIBRARY) { - // Create a rule for this target. std::string tfull = t->GetFullPath(configName); - makefileStream << this->ConvertToRelativeForMake(tfull.c_str()) - << ":"; + std::string trel = this->ConvertToRelativeForMake(tfull.c_str()); + + // Add this target to the post-build phases of its dependencies. + std::map<cmStdString, cmXCodeObject::StringVec>::const_iterator + y = target->GetDependTargets().find(*ct); + if(y != target->GetDependTargets().end()) + { + std::vector<cmStdString> const& deptgts = y->second; + for(std::vector<cmStdString>::const_iterator d = deptgts.begin(); + d != deptgts.end(); ++d) + { + makefileStream << this->PostBuildMakeTarget(*d, *ct) << ": " + << trel << "\n"; + } + } + + // Create a rule for this target. + makefileStream << trel << ":"; // List dependencies if any exist. std::map<cmStdString, cmXCodeObject::StringVec>::const_iterator @@ -3112,7 +3181,7 @@ void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry) const { entry.Name = this->GetName(); - entry.Brief = "Generate XCode project files."; + entry.Brief = "Generate Xcode project files."; entry.Full = ""; } diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 290532a..39a5fd7 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -88,6 +88,8 @@ public: private: cmXCodeObject* CreateOrGetPBXGroup(cmTarget& cmtarget, cmSourceGroup* sg); + cmXCodeObject* CreatePBXGroup(cmXCodeObject *parent, + cmStdString name); void CreateGroups(cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators); @@ -198,6 +200,8 @@ protected: std::vector<cmXCodeObject*> XCodeObjects; cmXCodeObject* RootObject; private: + std::string PostBuildMakeTarget(std::string const& tName, + std::string const& configName); cmXCodeObject* MainGroupChildren; cmXCodeObject* SourcesGroupChildren; cmXCodeObject* ResourcesGroupChildren; diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index de95aa5..15bad52 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -54,6 +54,7 @@ cmGraphVizWriter::cmGraphVizWriter(const std::vector<cmLocalGenerator*>& ,GenerateForStaticLibs(true) ,GenerateForSharedLibs(true) ,GenerateForModuleLibs(true) +,GenerateForExternals(true) ,LocalGenerators(localGenerators) ,HaveTargetsAndLibs(false) { @@ -115,36 +116,85 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName, __set_bool_if_set(this->GenerateForExecutables, "GRAPHVIZ_EXECUTABLES"); __set_bool_if_set(this->GenerateForStaticLibs, "GRAPHVIZ_STATIC_LIBS"); __set_bool_if_set(this->GenerateForSharedLibs, "GRAPHVIZ_SHARED_LIBS"); - __set_bool_if_set(this->GenerateForModuleLibs , "GRAPHVIZ_MODULE_LIBS"); + __set_bool_if_set(this->GenerateForModuleLibs, "GRAPHVIZ_MODULE_LIBS"); + __set_bool_if_set(this->GenerateForExternals, "GRAPHVIZ_EXTERNAL_LIBS"); - cmStdString tmpRegexString; - __set_if_set(tmpRegexString, "GRAPHVIZ_TARGET_IGNORE_REGEX"); - if (tmpRegexString.size() > 0) + cmStdString ignoreTargetsRegexes; + __set_if_set(ignoreTargetsRegexes, "GRAPHVIZ_IGNORE_TARGETS"); + + this->TargetsToIgnoreRegex.clear(); + if (ignoreTargetsRegexes.size() > 0) { - if (!this->TargetIgnoreRegex.compile(tmpRegexString.c_str())) + std::vector<std::string> ignoreTargetsRegExVector; + cmSystemTools::ExpandListArgument(ignoreTargetsRegexes, + ignoreTargetsRegExVector); + for(std::vector<std::string>::const_iterator itvIt + = ignoreTargetsRegExVector.begin(); + itvIt != ignoreTargetsRegExVector.end(); + ++ itvIt ) { - std::cerr << "Could not compile bad regex \"" << tmpRegexString << "\"" - << std::endl; + cmStdString currentRegexString(*itvIt); + cmsys::RegularExpression currentRegex; + if (!currentRegex.compile(currentRegexString.c_str())) + { + std::cerr << "Could not compile bad regex \"" << currentRegexString + << "\"" << std::endl; + } + this->TargetsToIgnoreRegex.push_back(currentRegex); } } - this->TargetsToIgnore.clear(); - const char* ignoreTargets = mf->GetDefinition("GRAPHVIZ_IGNORE_TARGETS"); - if ( ignoreTargets ) +} + + +// Iterate over all targets and write for each one a graph which shows +// which other targets depend on it. +void cmGraphVizWriter::WriteTargetDependersFiles(const char* fileName) +{ + this->CollectTargetsAndLibs(); + + for(std::map<cmStdString, const cmTarget*>::const_iterator ptrIt = + this->TargetPtrs.begin(); + ptrIt != this->TargetPtrs.end(); + ++ptrIt) { - std::vector<std::string> ignoreTargetsVector; - cmSystemTools::ExpandListArgument(ignoreTargets,ignoreTargetsVector); - for(std::vector<std::string>::iterator itvIt = ignoreTargetsVector.begin(); - itvIt != ignoreTargetsVector.end(); - ++ itvIt ) + if (ptrIt->second == NULL) { - this->TargetsToIgnore.insert(itvIt->c_str()); + continue; + } + + if (this->GenerateForTargetType(ptrIt->second->GetType()) == false) + { + continue; } - } + std::string currentFilename = fileName; + currentFilename += "."; + currentFilename += ptrIt->first; + currentFilename += ".dependers"; + + cmGeneratedFileStream str(currentFilename.c_str()); + if ( !str ) + { + return; + } + + std::set<std::string> insertedConnections; + std::set<std::string> insertedNodes; + + std::cout << "Writing " << currentFilename << "..." << std::endl; + this->WriteHeader(str); + + this->WriteDependerConnections(ptrIt->first.c_str(), + insertedNodes, insertedConnections, str); + + this->WriteFooter(str); + } } +// Iterate over all targets and write for each one a graph which shows +// on which targets it depends. void cmGraphVizWriter::WritePerTargetFiles(const char* fileName) { this->CollectTargetsAndLibs(); @@ -297,6 +347,91 @@ void cmGraphVizWriter::WriteConnections(const char* targetName, } +void cmGraphVizWriter::WriteDependerConnections(const char* targetName, + std::set<std::string>& insertedNodes, + std::set<std::string>& insertedConnections, + cmGeneratedFileStream& str) const +{ + std::map<cmStdString, const cmTarget* >::const_iterator targetPtrIt = + this->TargetPtrs.find(targetName); + + if (targetPtrIt == this->TargetPtrs.end()) // not found at all + { + return; + } + + this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str); + + if (targetPtrIt->second == NULL) // it's an external library + { + return; + } + + + std::string myNodeName = this->TargetNamesNodes.find(targetName)->second; + + // now search who links against me + for(std::map<cmStdString, const cmTarget*>::const_iterator dependerIt = + this->TargetPtrs.begin(); + dependerIt != this->TargetPtrs.end(); + ++dependerIt) + { + if (dependerIt->second == NULL) + { + continue; + } + + if (this->GenerateForTargetType(dependerIt->second->GetType()) == false) + { + continue; + } + + // Now we have a target, check whether it links against targetName. + // If so, draw a connection, and then continue with dependers on that one. + const cmTarget::LinkLibraryVectorType* ll = + &(dependerIt->second->GetOriginalLinkLibraries()); + + for (cmTarget::LinkLibraryVectorType::const_iterator llit = ll->begin(); + llit != ll->end(); + ++ llit ) + { + std::string libName = llit->first.c_str(); + if (libName == targetName) + { + // So this target links against targetName. + std::map<cmStdString, cmStdString>::const_iterator dependerNodeNameIt = + this->TargetNamesNodes.find(dependerIt->first); + + if(dependerNodeNameIt != this->TargetNamesNodes.end()) + { + std::string connectionName = dependerNodeNameIt->second; + connectionName += "-"; + connectionName += myNodeName; + + if (insertedConnections.find(connectionName) == + insertedConnections.end()) + { + insertedConnections.insert(connectionName); + this->WriteNode(dependerIt->first.c_str(), dependerIt->second, + insertedNodes, str); + + str << " \"" << dependerNodeNameIt->second << "\" -> \"" + << myNodeName << "\""; + str << " // " <<targetName<< " -> " <<dependerIt->first<<std::endl; + this->WriteDependerConnections(dependerIt->first.c_str(), + insertedNodes, insertedConnections, str); + } + + + } + break; + } + } + } + +} + + void cmGraphVizWriter::WriteNode(const char* targetName, const cmTarget* target, std::set<std::string>& insertedNodes, @@ -321,7 +456,10 @@ void cmGraphVizWriter::CollectTargetsAndLibs() { this->HaveTargetsAndLibs = true; int cnt = this->CollectAllTargets(); - this->CollectAllExternalLibs(cnt); + if (this->GenerateForExternals) + { + this->CollectAllExternalLibs(cnt); + } } } @@ -410,14 +548,22 @@ int cmGraphVizWriter::CollectAllExternalLibs(int cnt) bool cmGraphVizWriter::IgnoreThisTarget(const char* name) { - if (this->TargetIgnoreRegex.is_valid()) + for(std::vector<cmsys::RegularExpression>::iterator itvIt + = this->TargetsToIgnoreRegex.begin(); + itvIt != this->TargetsToIgnoreRegex.end(); + ++ itvIt ) { - if (this->TargetIgnoreRegex.find(name)) + cmsys::RegularExpression& regEx = *itvIt; + if (regEx.is_valid()) { - return true; + if (regEx.find(name)) + { + return true; + } } } - return (this->TargetsToIgnore.find(name) != this->TargetsToIgnore.end()); + + return false; } diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h index 105eb96..f784aa0 100644 --- a/Source/cmGraphVizWriter.h +++ b/Source/cmGraphVizWriter.h @@ -30,6 +30,7 @@ public: const char* fallbackSettingsFileName); void WritePerTargetFiles(const char* fileName); + void WriteTargetDependersFiles(const char* fileName); void WriteGlobalFile(const char* fileName); @@ -48,6 +49,11 @@ protected: std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const; + void WriteDependerConnections(const char* targetName, + std::set<std::string>& insertedNodes, + std::set<std::string>& insertedConnections, + cmGeneratedFileStream& str) const; + void WriteNode(const char* targetName, const cmTarget* target, std::set<std::string>& insertedNodes, cmGeneratedFileStream& str) const; @@ -67,10 +73,9 @@ protected: bool GenerateForStaticLibs; bool GenerateForSharedLibs; bool GenerateForModuleLibs; + bool GenerateForExternals; - cmsys::RegularExpression TargetIgnoreRegex; - - std::set<cmStdString> TargetsToIgnore; + std::vector<cmsys::RegularExpression> TargetsToIgnoreRegex; const std::vector<cmLocalGenerator*>& LocalGenerators; diff --git a/Source/cmIncludeDirectoryCommand.h b/Source/cmIncludeDirectoryCommand.h index d00f843..3b35d55 100644 --- a/Source/cmIncludeDirectoryCommand.h +++ b/Source/cmIncludeDirectoryCommand.h @@ -61,7 +61,7 @@ public: "Add the given directories to those searched by the compiler for " "include files. By default the directories are appended onto " "the current list of directories. This default behavior can be " - "changed by setting CMAKE_include_directories_BEFORE to ON. " + "changed by setting CMAKE_INCLUDE_DIRECTORIES_BEFORE to ON. " "By using BEFORE or AFTER you can select between appending and " "prepending, independent from the default. " "If the SYSTEM option is given the compiler will be told that the " diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 7b3fc86..7da35eb 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1904,7 +1904,6 @@ bool cmLocalGenerator::GetRealDependency(const char* inName, { // This is a full path. Return it as given. dep = inName; - cmSystemTools::ConvertToUnixSlashes(dep); return true; } diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index d1214d2..5c2cda1 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -2228,17 +2228,23 @@ void cmLocalUnixMakefileGenerator3 return; } + // In a Windows shell we must change drive letter too. The shell + // used by NMake and Borland make does not support "cd /d" so this + // feature simply cannot work with them (Borland make does not even + // support changing the drive letter with just "d:"). + const char* cd_cmd = this->MinGWMake? "cd /d " : "cd "; + if(!this->UnixCD) { // On Windows we must perform each step separately and then change // back because the shell keeps the working directory between // commands. - std::string cmd = "cd "; + std::string cmd = cd_cmd; cmd += this->ConvertToOutputForExisting(tgtDir, relRetDir); commands.insert(commands.begin(),cmd); // Change back to the starting directory. - cmd = "cd "; + cmd = cd_cmd; cmd += this->ConvertToOutputForExisting(relRetDir, tgtDir); commands.push_back(cmd); } @@ -2250,7 +2256,7 @@ void cmLocalUnixMakefileGenerator3 std::vector<std::string>::iterator i = commands.begin(); for (; i != commands.end(); ++i) { - std::string cmd = "cd "; + std::string cmd = cd_cmd; cmd += this->ConvertToOutputForExisting(tgtDir, relRetDir); cmd += " && "; cmd += *i; diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index de2a837..1850c16 100644 --- a/Source/cmLocalVisualStudio10Generator.cxx +++ b/Source/cmLocalVisualStudio10Generator.cxx @@ -119,7 +119,7 @@ void cmLocalVisualStudio10Generator } //---------------------------------------------------------------------------- -std::string cmLocalVisualStudio10Generator::CheckForErrorLine() +const char* cmLocalVisualStudio10Generator::ReportErrorLabel() const { - return "if errorlevel 1 goto :VCEnd"; + return ":VCEnd"; } diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h index 06b8b09..0fccdb0 100644 --- a/Source/cmLocalVisualStudio10Generator.h +++ b/Source/cmLocalVisualStudio10Generator.h @@ -38,7 +38,8 @@ public: const char* path); protected: - virtual std::string CheckForErrorLine(); + virtual const char* ReportErrorLabel() const; + virtual bool CustomCommandUseLocal() const { return true; } private: }; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index b9ffe62..7a62b9c 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1770,10 +1770,14 @@ cmLocalVisualStudio7Generator vskey += "\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion"; cmSystemTools::ReadRegistryValue(vskey.c_str(), intelVersion, cmSystemTools::KeyWOW64_32); - - // Version 10.1 actually uses 9.10 in project files! - if(intelVersion == "10.1") + if (intelVersion == "12.0") + { + // Version 12 actually uses 11.0 in project files! + intelVersion = "11.0" ; + } + else if(intelVersion == "10.1") { + // Version 10.1 actually uses 9.10 in project files! intelVersion = "9.10"; } diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 39f9962..4390a08 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -154,15 +154,15 @@ void cmLocalVisualStudioGenerator::ComputeObjectNameRequirements } //---------------------------------------------------------------------------- -std::string cmLocalVisualStudioGenerator::CheckForErrorLine() +const char* cmLocalVisualStudioGenerator::ReportErrorLabel() const { - return "if errorlevel 1 goto :VCReportError"; + return ":VCReportError"; } //---------------------------------------------------------------------------- -std::string cmLocalVisualStudioGenerator::GetCheckForErrorLine() +const char* cmLocalVisualStudioGenerator::GetReportErrorLabel() const { - return this->CheckForErrorLine(); + return this->ReportErrorLabel(); } //---------------------------------------------------------------------------- @@ -172,6 +172,7 @@ cmLocalVisualStudioGenerator const char* configName, const char* newline_text) { + bool useLocal = this->CustomCommandUseLocal(); const cmCustomCommandLines& commandLines = cc.GetCommandLines(); const char* workingDirectory = cc.GetWorkingDirectory(); cmCustomCommandGenerator ccg(cc, configName, this->Makefile); @@ -180,8 +181,29 @@ cmLocalVisualStudioGenerator // Avoid leading or trailing newlines. const char* newline = ""; + // Line to check for error between commands. + std::string check_error = newline_text; + if(useLocal) + { + check_error += "if %errorlevel% neq 0 goto :cmEnd"; + } + else + { + check_error += "if errorlevel 1 goto "; + check_error += this->GetReportErrorLabel(); + } + // Store the script in a string. std::string script; + + // Open a local context. + if(useLocal) + { + script += newline; + newline = newline_text; + script += "setlocal"; + } + if(workingDirectory) { // Change the working directory. @@ -189,6 +211,7 @@ cmLocalVisualStudioGenerator newline = newline_text; script += "cd "; script += this->Convert(workingDirectory, FULL, SHELL); + script += check_error; // Change the working drive. if(workingDirectory[0] && workingDirectory[1] == ':') @@ -197,8 +220,10 @@ cmLocalVisualStudioGenerator newline = newline_text; script += workingDirectory[0]; script += workingDirectory[1]; + script += check_error; } } + // for visual studio IDE add extra stuff to the PATH // if CMAKE_MSVCIDE_RUN_PATH is set. if(this->Makefile->GetDefinition("MSVC_IDE")) @@ -214,6 +239,7 @@ cmLocalVisualStudioGenerator script += ";%PATH%"; } } + // Write each command on a single line. for(unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) { @@ -230,9 +256,25 @@ cmLocalVisualStudioGenerator // If there was an error, jump to the VCReportError label, // skipping the run of any subsequent commands in this // sequence. - // - script += newline_text; - script += this->GetCheckForErrorLine(); + script += check_error; + } + + // Close the local context. + if(useLocal) + { + script += newline; + script += ":cmEnd"; + script += newline; + script += "endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone"; + script += newline; + script += ":cmErrorLevel"; + script += newline; + script += "exit /b %1"; + script += newline; + script += ":cmDone"; + script += newline; + script += "if %errorlevel% neq 0 goto "; + script += this->GetReportErrorLabel(); } return script; diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index 22112b3..a38bc30 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -37,13 +37,13 @@ public: const char* configName, const char* newline = "\n"); - /** Line of batch file text that skips to the end after - * a failed step in a sequence of custom commands. - */ - std::string GetCheckForErrorLine(); + /** Label to which to jump in a batch file after a failed step in a + sequence of custom commands. */ + const char* GetReportErrorLabel() const; protected: - virtual std::string CheckForErrorLine(); + virtual const char* ReportErrorLabel() const; + virtual bool CustomCommandUseLocal() const { return false; } /** Construct a custom command to make exe import lib dir. */ cmsys::auto_ptr<cmCustomCommand> diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 69320da..d0df8f0 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -249,51 +249,17 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() } //---------------------------------------------------------------------------- -void cmMakefileTargetGenerator::WriteTargetLanguageFlags() +std::string cmMakefileTargetGenerator::GetFlags(const std::string &l) { - // write language flags for target - std::set<cmStdString> languages; - this->Target->GetLanguages(languages); - // put the compiler in the rules.make file so that if it changes - // things rebuild - for(std::set<cmStdString>::const_iterator l = languages.begin(); - l != languages.end(); ++l) - { - cmStdString compiler = "CMAKE_"; - compiler += *l; - compiler += "_COMPILER"; - *this->FlagFileStream << "# compile " << l->c_str() << " with " << - this->Makefile->GetSafeDefinition(compiler.c_str()) << "\n"; - } - - for(std::set<cmStdString>::const_iterator l = languages.begin(); - l != languages.end(); ++l) + ByLanguageMap::iterator i = this->FlagsByLanguage.find(l); + if (i == this->FlagsByLanguage.end()) { - const char *lang = l->c_str(); std::string flags; - std::string defines; + const char *lang = l.c_str(); + bool shared = ((this->Target->GetType() == cmTarget::SHARED_LIBRARY) || (this->Target->GetType() == cmTarget::MODULE_LIBRARY)); - // Add the export symbol definition for shared library objects. - if(const char* exportMacro = this->Target->GetExportMacro()) - { - this->LocalGenerator->AppendDefines(defines, exportMacro, lang); - } - - // Add preprocessor definitions for this target and configuration. - this->LocalGenerator->AppendDefines - (defines, this->Makefile->GetProperty("COMPILE_DEFINITIONS"), lang); - this->LocalGenerator->AppendDefines - (defines, this->Target->GetProperty("COMPILE_DEFINITIONS"), lang); - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += - cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName); - this->LocalGenerator->AppendDefines - (defines, this->Makefile->GetProperty(defPropName.c_str()), lang); - this->LocalGenerator->AppendDefines - (defines, this->Target->GetProperty(defPropName.c_str()), lang); - // Add language feature flags. this->AddFeatureFlags(flags, lang); @@ -301,7 +267,7 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() lang, this->ConfigName); // Fortran-specific flags computed for this target. - if(*l == "Fortran") + if(l == "Fortran") { this->AddFortranFlags(flags); } @@ -320,14 +286,73 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() this->LocalGenerator-> AppendFlags(flags,this->GetFrameworkFlags().c_str()); - *this->FlagFileStream << lang << "_FLAGS = " << flags << "\n\n"; - *this->FlagFileStream << lang << "_DEFINES = " << defines << "\n\n"; + ByLanguageMap::value_type entry(l, flags); + i = this->FlagsByLanguage.insert(entry).first; + } + return i->second; +} + +std::string cmMakefileTargetGenerator::GetDefines(const std::string &l) +{ + ByLanguageMap::iterator i = this->DefinesByLanguage.find(l); + if (i == this->DefinesByLanguage.end()) + { + std::string defines; + const char *lang = l.c_str(); + // Add the export symbol definition for shared library objects. + if(const char* exportMacro = this->Target->GetExportMacro()) + { + this->LocalGenerator->AppendDefines(defines, exportMacro, lang); + } + + // Add preprocessor definitions for this target and configuration. + this->LocalGenerator->AppendDefines + (defines, this->Makefile->GetProperty("COMPILE_DEFINITIONS"), lang); + this->LocalGenerator->AppendDefines + (defines, this->Target->GetProperty("COMPILE_DEFINITIONS"), lang); + std::string defPropName = "COMPILE_DEFINITIONS_"; + defPropName += + cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName); + this->LocalGenerator->AppendDefines + (defines, this->Makefile->GetProperty(defPropName.c_str()), lang); + this->LocalGenerator->AppendDefines + (defines, this->Target->GetProperty(defPropName.c_str()), lang); + + ByLanguageMap::value_type entry(l, defines); + i = this->DefinesByLanguage.insert(entry).first; + } + return i->second; +} + +void cmMakefileTargetGenerator::WriteTargetLanguageFlags() +{ + // write language flags for target + std::set<cmStdString> languages; + this->Target->GetLanguages(languages); + // put the compiler in the rules.make file so that if it changes + // things rebuild + for(std::set<cmStdString>::const_iterator l = languages.begin(); + l != languages.end(); ++l) + { + cmStdString compiler = "CMAKE_"; + compiler += *l; + compiler += "_COMPILER"; + *this->FlagFileStream << "# compile " << l->c_str() << " with " << + this->Makefile->GetSafeDefinition(compiler.c_str()) << "\n"; + } + + for(std::set<cmStdString>::const_iterator l = languages.begin(); + l != languages.end(); ++l) + { + *this->FlagFileStream << *l << "_FLAGS = " << this->GetFlags(*l) << "\n\n"; + *this->FlagFileStream << *l << "_DEFINES = " << this->GetDefines(*l) << + "\n\n"; } // Add target-specific flags. if(this->Target->GetProperty("COMPILE_FLAGS")) { - std::string flags; + std::string flags; this->LocalGenerator->AppendFlags (flags, this->Target->GetProperty("COMPILE_FLAGS")); *this->FlagFileStream << "# TARGET_FLAGS = " << flags << "\n\n"; @@ -641,6 +666,9 @@ cmMakefileTargetGenerator vars.Flags = flags.c_str(); vars.Defines = defines.c_str(); + bool lang_is_c_or_cxx = ((strcmp(lang, "C") == 0) || + (strcmp(lang, "CXX") == 0)); + // Construct the compile rules. { std::string compileRuleVar = "CMAKE_"; @@ -651,6 +679,23 @@ cmMakefileTargetGenerator std::vector<std::string> compileCommands; cmSystemTools::ExpandListArgument(compileRule, compileCommands); + if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") && + lang_is_c_or_cxx && compileCommands.size() == 1) + { + std::string compileCommand = compileCommands[0]; + this->LocalGenerator->ExpandRuleVariables(compileCommand, vars); + std::string workingDirectory = + this->LocalGenerator->Convert( + this->Makefile->GetStartOutputDirectory(), cmLocalGenerator::FULL); + compileCommand.replace(compileCommand.find(langFlags), + langFlags.size(), this->GetFlags(lang)); + std::string langDefines = std::string("$(") + lang + "_DEFINES)"; + compileCommand.replace(compileCommand.find(langDefines), + langDefines.size(), this->GetDefines(lang)); + this->GlobalGenerator->AddCXXCompileCommand( + source.GetFullPath(), workingDirectory, compileCommand); + } + // Expand placeholders in the commands. for(std::vector<std::string>::iterator i = compileCommands.begin(); i != compileCommands.end(); ++i) @@ -691,8 +736,6 @@ cmMakefileTargetGenerator } } - bool lang_is_c_or_cxx = ((strcmp(lang, "C") == 0) || - (strcmp(lang, "CXX") == 0)); bool do_preprocess_rules = lang_is_c_or_cxx && this->LocalGenerator->GetCreatePreprocessedSourceRules(); bool do_assembly_rules = lang_is_c_or_cxx && diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index bd26795..b68f8bf 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -216,6 +216,12 @@ protected: std::string MacContentDirectory; std::set<cmStdString> MacContentFolders; + typedef std::map<cmStdString, cmStdString> ByLanguageMap; + std::string GetFlags(const std::string &l); + ByLanguageMap FlagsByLanguage; + std::string GetDefines(const std::string &l); + ByLanguageMap DefinesByLanguage; + // Target-wide Fortran module output directory. bool FortranModuleDirectoryComputed; std::string FortranModuleDirectory; diff --git a/Source/cmOutputRequiredFilesCommand.h b/Source/cmOutputRequiredFilesCommand.h index 0da7724..6038472 100644 --- a/Source/cmOutputRequiredFilesCommand.h +++ b/Source/cmOutputRequiredFilesCommand.h @@ -47,8 +47,7 @@ public: */ virtual const char* GetTerseDocumentation() { - return - "Output a list of required source files for a specified source file."; + return "Deprecated. Approximate C preprocessor dependency scanning."; } /** @@ -57,12 +56,22 @@ public: virtual const char* GetFullDocumentation() { return + "This command exists only because ancient CMake versions provided it. " + "CMake handles preprocessor dependency scanning automatically using a " + "more advanced scanner.\n" " output_required_files(srcfile outputfile)\n" "Outputs a list of all the source files that are required by the " "specified srcfile. This list is written into outputfile. This is " "similar to writing out the dependencies for srcfile except that it " "jumps from .h files into .cxx, .c and .cpp files if possible."; } + + /** This command is kept for compatibility with older CMake versions. */ + virtual bool IsDiscouraged() + { + return true; + } + cmTypeMacro(cmOutputRequiredFilesCommand, cmCommand); void ListDependencies(cmDependInformation const *info, diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx index 86ecebe..cabe98a 100644 --- a/Source/cmScriptGenerator.cxx +++ b/Source/cmScriptGenerator.cxx @@ -209,6 +209,7 @@ void cmScriptGenerator::GenerateScriptActionsPerConfig(std::ostream& os, // In a multi-configuration generator we produce a separate rule // in a block for each configuration that is built. We restrict // the list of configurations to those to which this rule applies. + bool first = true; for(std::vector<std::string>::const_iterator i = this->ConfigurationTypes->begin(); i != this->ConfigurationTypes->end(); ++i) @@ -218,10 +219,19 @@ void cmScriptGenerator::GenerateScriptActionsPerConfig(std::ostream& os, { // Generate a per-configuration block. std::string config_test = this->CreateConfigTest(config); - os << indent << "IF(" << config_test << ")\n"; + os << indent << (first? "IF(" : "ELSEIF(") << config_test << ")\n"; this->GenerateScriptForConfig(os, config, indent.Next()); - os << indent << "ENDIF(" << config_test << ")\n"; + first = false; } } + if(!first) + { + if(this->NeedsScriptNoConfig()) + { + os << indent << "ELSE()\n"; + this->GenerateScriptNoConfig(os, indent.Next()); + } + os << indent << "ENDIF()\n"; + } } } diff --git a/Source/cmScriptGenerator.h b/Source/cmScriptGenerator.h index e2a0da5..8b2ca33 100644 --- a/Source/cmScriptGenerator.h +++ b/Source/cmScriptGenerator.h @@ -65,6 +65,8 @@ protected: virtual void GenerateScriptForConfig(std::ostream& os, const char* config, Indent const& indent); + virtual void GenerateScriptNoConfig(std::ostream&, Indent const&) {} + virtual bool NeedsScriptNoConfig() const { return false; } // Test if this generator does something for a given configuration. bool GeneratesForConfig(const char*); diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx index 27d90db..8e61d0a 100644 --- a/Source/cmSourceGroupCommand.cxx +++ b/Source/cmSourceGroupCommand.cxx @@ -11,37 +11,6 @@ ============================================================================*/ #include "cmSourceGroupCommand.h" -inline std::vector<std::string> tokenize(const std::string& str, - const std::string& sep) -{ - std::vector<std::string> tokens; - std::string::size_type tokend = 0; - - do - { - std::string::size_type tokstart=str.find_first_not_of(sep, tokend); - if (tokstart==std::string::npos) - { - break; // no more tokens - } - tokend=str.find_first_of(sep,tokstart); - if (tokend==std::string::npos) - { - tokens.push_back(str.substr(tokstart)); - } - else - { - tokens.push_back(str.substr(tokstart,tokend-tokstart)); - } - } while (tokend!=std::string::npos); - - if (tokens.empty()) - { - tokens.push_back(""); - } - return tokens; -} - // cmSourceGroupCommand bool cmSourceGroupCommand ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &) @@ -58,7 +27,8 @@ bool cmSourceGroupCommand delimiter = this->Makefile->GetDefinition("SOURCE_GROUP_DELIMITER"); } - std::vector<std::string> folders = tokenize(args[0], delimiter); + std::vector<std::string> folders = + cmSystemTools::tokenize(args[0], delimiter); cmSourceGroup* sg = 0; sg = this->Makefile->GetSourceGroup(folders); diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 19d2369..d239c06 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -677,7 +677,7 @@ bool cmStringCommand::HandleSubstringCommand(std::vector<std::string> const& if ( end < -1 || end > leftOverLength ) { cmOStringStream ostr; - ostr << "end index: " << end << " is out of range " << 0 << " - " + ostr << "end index: " << end << " is out of range -1 - " << leftOverLength; this->SetError(ostr.str().c_str()); return false; @@ -770,7 +770,7 @@ bool cmStringCommand static bool seeded = false; bool force_seed = false; - int seed = (int) time(NULL); + unsigned int seed = 0; int length = 5; const char cmStringCommandDefaultAlphabet[] = "qwertyuiopasdfghjklzxcvbnm" "QWERTYUIOPASDFGHJKLZXCVBNM" @@ -797,7 +797,7 @@ bool cmStringCommand else if ( args[i] == "RANDOM_SEED" ) { ++i; - seed = atoi(args[i].c_str()); + seed = static_cast<unsigned int>(atoi(args[i].c_str())); force_seed = true; } } @@ -825,7 +825,7 @@ bool cmStringCommand if (!seeded || force_seed) { seeded = true; - srand(seed); + srand(force_seed? seed : cmSystemTools::RandomSeed()); } const char* alphaPtr = alphabet.c_str(); diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index 9586449..52b83d9 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -110,7 +110,8 @@ public: "a file.\n" "TOUPPER/TOLOWER will convert string to upper/lower characters.\n" "LENGTH will return a given string's length.\n" - "SUBSTRING will return a substring of a given string.\n" + "SUBSTRING will return a substring of a given string. If length is " + "-1 the remainder of the string starting at begin will be returned.\n" "STRIP will return a substring of a given string with leading " "and trailing spaces removed.\n" "RANDOM will return a random string of given length consisting of " diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 7bc89a4..dbb2226 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -9,6 +9,9 @@ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ +#if defined(_MSC_VER) && _MSC_VER < 1300 +# define _WIN32_WINNT 0x0400 /* for wincrypt.h */ +#endif #include "cmSystemTools.h" #include <ctype.h> #include <errno.h> @@ -31,7 +34,9 @@ #if defined(_WIN32) # include <windows.h> +# include <wincrypt.h> #else +# include <sys/time.h> # include <sys/types.h> # include <unistd.h> # include <utime.h> @@ -440,6 +445,13 @@ public: args.push_back(*arg); } } + void Store(std::vector<cmStdString>& args) const + { + for(char** arg = this->ArgV; arg && *arg; ++arg) + { + args.push_back(*arg); + } + } }; //---------------------------------------------------------------------------- @@ -451,6 +463,15 @@ void cmSystemTools::ParseUnixCommandLine(const char* command, argv.Store(args); } +//---------------------------------------------------------------------------- +void cmSystemTools::ParseUnixCommandLine(const char* command, + std::vector<cmStdString>& args) +{ + // Invoke the underlying parser. + cmSystemToolsArgV argv = cmsysSystem_Parse_CommandForUnix(command, 0); + argv.Store(args); +} + std::string cmSystemTools::EscapeWindowsShellArgument(const char* arg, int shell_flags) { @@ -2233,6 +2254,71 @@ bool cmSystemTools::FileTimeSet(const char* fname, cmSystemToolsFileTime* t) } //---------------------------------------------------------------------------- +#ifdef _WIN32 +# ifndef CRYPT_SILENT +# define CRYPT_SILENT 0x40 /* Not defined by VS 6 version of header. */ +# endif +static int WinCryptRandom(void* data, size_t size) +{ + int result = 0; + HCRYPTPROV hProvider = 0; + if(CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) + { + result = CryptGenRandom(hProvider, (DWORD)size, (BYTE*)data)? 1:0; + CryptReleaseContext(hProvider, 0); + } + return result; +} +#endif + +//---------------------------------------------------------------------------- +unsigned int cmSystemTools::RandomSeed() +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + unsigned int seed = 0; + + // Try using a real random source. + if(WinCryptRandom(&seed, sizeof(seed))) + { + return seed; + } + + // Fall back to the time and pid. + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + unsigned int t1 = static_cast<unsigned int>(ft.dwHighDateTime); + unsigned int t2 = static_cast<unsigned int>(ft.dwLowDateTime); + unsigned int pid = static_cast<unsigned int>(GetCurrentProcessId()); + return t1 ^ t2 ^ pid; +#else + union + { + unsigned int integer; + char bytes[sizeof(unsigned int)]; + } seed; + + // Try using a real random source. + std::ifstream fin("/dev/urandom"); + if(fin && fin.read(seed.bytes, sizeof(seed)) && + fin.gcount() == sizeof(seed)) + { + return seed.integer; + } + + // Fall back to the time and pid. + struct timeval t; + gettimeofday(&t, 0); + unsigned int pid = static_cast<unsigned int>(getpid()); + unsigned int tv_sec = static_cast<unsigned int>(t.tv_sec); + unsigned int tv_usec = static_cast<unsigned int>(t.tv_usec); + // Since tv_usec never fills more than 11 bits we shift it to fill + // in the slow-changing high-order bits of tv_sec. + return tv_sec ^ (tv_usec << 21) ^ pid; +#endif +} + +//---------------------------------------------------------------------------- static std::string cmSystemToolsExecutableDirectory; void cmSystemTools::FindExecutableDirectory(const char* argv0) { @@ -2603,7 +2689,7 @@ bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op, else if(lhs[i] > rhs[i]) { // lhs > rhs, so true if operation is GREATER - return op == cmSystemTools::OP_GREATER; + return op == cmSystemTools::OP_GREATER; } } // lhs == rhs, so true if operation is EQUAL @@ -2833,3 +2919,35 @@ bool cmSystemTools::RepeatedRemoveDirectory(const char* dir) } return false; } + +//---------------------------------------------------------------------------- +std::vector<std::string> cmSystemTools::tokenize(const std::string& str, + const std::string& sep) +{ + std::vector<std::string> tokens; + std::string::size_type tokend = 0; + + do + { + std::string::size_type tokstart=str.find_first_not_of(sep, tokend); + if (tokstart==std::string::npos) + { + break; // no more tokens + } + tokend=str.find_first_of(sep,tokstart); + if (tokend==std::string::npos) + { + tokens.push_back(str.substr(tokstart)); + } + else + { + tokens.push_back(str.substr(tokstart,tokend-tokstart)); + } + } while (tokend!=std::string::npos); + + if (tokens.empty()) + { + tokens.push_back(""); + } + return tokens; +} diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 6f9147c..ce49959 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -237,6 +237,8 @@ public: /** Parse arguments out of a unix command line string. */ static void ParseUnixCommandLine(const char* command, std::vector<std::string>& args); + static void ParseUnixCommandLine(const char* command, + std::vector<cmStdString>& args); /** Compute an escaped version of the given argument for use in a windows shell. See kwsys/System.h.in for details. */ @@ -402,6 +404,9 @@ public: static bool FileTimeGet(const char* fname, cmSystemToolsFileTime* t); static bool FileTimeSet(const char* fname, cmSystemToolsFileTime* t); + /** Random seed generation. */ + static unsigned int RandomSeed(); + /** Find the directory containing the running executable. Save it in a global location to be queried by GetExecutableDirectory later. */ @@ -439,6 +444,9 @@ public: /** Remove a directory; repeat a few times in case of locked files. */ static bool RepeatedRemoveDirectory(const char* dir); + /** Tokenize a string */ + static std::vector<std::string> tokenize(const std::string& str, + const std::string& sep); private: static bool s_ForceUnixPaths; static bool s_RunCommandHideConsole; diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 39f8638..e0892b2 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -130,6 +130,22 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, } //---------------------------------------------------------------------------- +void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, + Indent const& indent) +{ + os << indent << "ADD_TEST(" << this->Test->GetName() << " NOT_AVAILABLE)\n"; +} + +//---------------------------------------------------------------------------- +bool cmTestGenerator::NeedsScriptNoConfig() const +{ + return (this->TestGenerated && // test generated for at least one config + this->ActionsPerConfig && // test is config-aware + this->Configurations.empty() && // test runs in all configs + !this->ConfigurationTypes->empty()); // config-dependent command +} + +//---------------------------------------------------------------------------- void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent const& indent) { diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h index 85d9091..2c69fc3 100644 --- a/Source/cmTestGenerator.h +++ b/Source/cmTestGenerator.h @@ -34,6 +34,8 @@ protected: virtual void GenerateScriptForConfig(std::ostream& os, const char* config, Indent const& indent); + virtual void GenerateScriptNoConfig(std::ostream& os, Indent const& indent); + virtual bool NeedsScriptNoConfig() const; void GenerateOldStyle(std::ostream& os, Indent const& indent); cmTest* Test; diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h index 0c67a8b..9923d03 100644 --- a/Source/cmTryCompileCommand.h +++ b/Source/cmTryCompileCommand.h @@ -77,14 +77,20 @@ public: "Specify COPY_FILE to get a copy of the linked executable at the " "given fileName." "\n" - "In this version all files in bindir/CMakeFiles/CMakeTmp, " - "will be cleaned automatically, for debugging a --debug-trycompile can " - "be passed to cmake to avoid the clean. Some extra flags that " - " can be included are, " + "In this version all files in bindir/CMakeFiles/CMakeTmp " + "will be cleaned automatically. For debugging, --debug-trycompile can " + "be passed to cmake to avoid this clean. However, multiple sequential " + "try_compile operations reuse this single output directory. If you " + "use --debug-trycompile, you can only debug one try_compile call at a " + "time. The recommended procedure is to configure with cmake all the " + "way through once, then delete the cache entry associated with " + "the try_compile call of interest, and then re-run cmake again with " + "--debug-trycompile." + "\n" + "Some extra flags that can be included are, " "INCLUDE_DIRECTORIES, LINK_DIRECTORIES, and LINK_LIBRARIES. " "COMPILE_DEFINITIONS are -Ddefinition that will be passed to the " "compile line. " - "try_compile creates a CMakeList.txt " "file on the fly that looks like this:\n" " add_definitions( <expanded COMPILE_DEFINITIONS from calling " diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 8a27ffd..2a4ff92 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -351,6 +351,9 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source, { if(!cmSystemTools::FileExists(sourcePath.c_str())) { + // Make sure the path exists for the file + std::string path = cmSystemTools::GetFilenamePath(sourcePath); + cmSystemTools::MakeDirectory(path.c_str()); std::ofstream fout(sourcePath.c_str()); if(fout) { @@ -358,6 +361,14 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source, fout.flush(); fout.close(); } + else + { + std::string error = "Could not create file: ["; + error += sourcePath; + error += "] "; + cmSystemTools::Error + (error.c_str(), cmSystemTools::GetLastSystemError().c_str()); + } } } cmLocalVisualStudio7Generator* lg = this->LocalGenerator; @@ -367,10 +378,7 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source, static_cast<cmGlobalVisualStudio7Generator *> (this->GlobalGenerator)->GetConfigurations(); this->WriteString("<CustomBuild Include=\"", 2); - std::string path = - cmSystemTools::RelativePath( - this->Makefile->GetCurrentOutputDirectory(), - sourcePath.c_str()); + std::string path = sourcePath; this->ConvertToWindowsSlash(path); (*this->BuildFileStream ) << path << "\">\n"; for(std::vector<std::string>::iterator i = configs->begin(); @@ -452,11 +460,17 @@ void cmVisualStudio10TargetGenerator::WriteGroups() bool header = (*s)->GetPropertyAsBool("HEADER_FILE_ONLY") || this->GlobalGenerator->IgnoreFile ((*s)->GetExtension().c_str()); + std::string ext = + cmSystemTools::LowerCase((*s)->GetExtension()); if(!lang) { lang = "None"; } - if(lang[0] == 'C') + if(header) + { + headers.push_back(sf); + } + else if(lang[0] == 'C') { clCompile.push_back(sf); } @@ -468,11 +482,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() { customBuild.push_back(sf); } - else if(header) - { - headers.push_back(sf); - } - else if(sf->GetExtension() == "idl") + else if(ext == "idl") { idls.push_back(sf); } @@ -609,9 +619,6 @@ WriteGroupSources(const char* name, const char* filter = sourceGroup.GetFullName(); this->WriteString("<", 2); std::string path = source; - path = cmSystemTools::RelativePath( - this->Makefile->GetCurrentOutputDirectory(), - source.c_str()); this->ConvertToWindowsSlash(path); (*this->BuildFileStream) << name << " Include=\"" << path; @@ -642,14 +649,28 @@ void cmVisualStudio10TargetGenerator::WriteObjSources() for(std::vector<cmSourceFile*>::const_iterator source = sources.begin(); source != sources.end(); ++source) { - if((*source)->GetExtension() == "obj") + std::string ext = + cmSystemTools::LowerCase((*source)->GetExtension()); + if(ext == "obj" || ext == "o") { if(first) { this->WriteString("<ItemGroup>\n", 1); first = false; } - this->WriteString("<None Include=\"", 2); + // If an object file is generated, then vs10 + // will use it in the build, and we have to list + // it as None instead of Object + if((*source)->GetPropertyAsBool("GENERATED")) + { + this->WriteString("<None Include=\"", 2); + } + // If it is not a generated object then we have + // to use the Object type + else + { + this->WriteString("<Object Include=\"", 2); + } (*this->BuildFileStream ) << (*source)->GetFullPath() << "\" />\n"; } } @@ -671,8 +692,8 @@ void cmVisualStudio10TargetGenerator::WriteCLSources() for(std::vector<cmSourceFile*>::const_iterator source = sources.begin(); source != sources.end(); ++source) { - std::string ext = (*source)->GetExtension(); - if((*source)->GetCustomCommand() || ext == "obj") + std::string ext = cmSystemTools::LowerCase((*source)->GetExtension()); + if((*source)->GetCustomCommand() || ext == "o" || ext == "obj") { continue; } @@ -685,9 +706,6 @@ void cmVisualStudio10TargetGenerator::WriteCLSources() bool rc = lang && (strcmp(lang, "RC") == 0); bool idl = ext == "idl"; std::string sourceFile = (*source)->GetFullPath(); - sourceFile = cmSystemTools::RelativePath( - this->Makefile->GetCurrentOutputDirectory(), - sourceFile.c_str()); this->ConvertToWindowsSlash(sourceFile); // output the source file if(header) diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index ed0d60c..ae496ad 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -299,7 +299,12 @@ cmVisualStudioGeneratorOptions { fout << "<" << m->first << ">"; } - fout << m->second << "</" << m->first << ">\n"; + fout << m->second; + if (m->first == "AdditionalIncludeDirectories") + { + fout << ";%(AdditionalIncludeDirectories)"; + } + fout << "</" << m->first << ">\n"; } } else diff --git a/Source/cmXCodeObject.cxx b/Source/cmXCodeObject.cxx index 5920470..71c7c25 100644 --- a/Source/cmXCodeObject.cxx +++ b/Source/cmXCodeObject.cxx @@ -146,13 +146,15 @@ void cmXCodeObject::Print(std::ostream& out) if(j->second->TypeValue == STRING) { - out << j->first << " = "; + cmXCodeObject::PrintString(out,j->first); + out << " = "; j->second->PrintString(out); out << ";"; } else if(j->second->TypeValue == OBJECT_LIST) { - out << j->first << " = ("; + cmXCodeObject::PrintString(out,j->first); + out << " = ("; for(unsigned int k = 0; k < j->second->List.size(); k++) { if(j->second->List[k]->TypeValue == STRING) @@ -169,7 +171,8 @@ void cmXCodeObject::Print(std::ostream& out) } else { - out << j->first << " = error_unexpected_TypeValue_" << + cmXCodeObject::PrintString(out,j->first); + out << " = error_unexpected_TypeValue_" << j->second->TypeValue << ";"; } @@ -180,7 +183,8 @@ void cmXCodeObject::Print(std::ostream& out) } else if(object->TypeValue == OBJECT_REF) { - out << i->first << " = " << object->Object->Id; + cmXCodeObject::PrintString(out,i->first); + out << " = " << object->Object->Id; if(object->Object->HasComment() && i->first != "remoteGlobalIDString") { out << " "; @@ -190,7 +194,8 @@ void cmXCodeObject::Print(std::ostream& out) } else if(object->TypeValue == STRING) { - out << i->first << " = "; + cmXCodeObject::PrintString(out,i->first); + out << " = "; object->PrintString(out); out << ";" << separator; } @@ -230,19 +235,19 @@ void cmXCodeObject::CopyAttributes(cmXCodeObject* copy) } //---------------------------------------------------------------------------- -void cmXCodeObject::PrintString(std::ostream& os) const +void cmXCodeObject::PrintString(std::ostream& os,cmStdString String) { // The string needs to be quoted if it contains any characters // considered special by the Xcode project file parser. bool needQuote = - (this->String.empty() || - this->String.find_first_of(" <>.+-=@$") != this->String.npos); + (String.empty() || + String.find_first_of(" <>.+-=@$[]") != String.npos); const char* quote = needQuote? "\"" : ""; // Print the string, quoted and escaped as necessary. os << quote; - for(std::string::const_iterator i = this->String.begin(); - i != this->String.end(); ++i) + for(std::string::const_iterator i = String.begin(); + i != String.end(); ++i) { if(*i == '"') { @@ -254,6 +259,11 @@ void cmXCodeObject::PrintString(std::ostream& os) const os << quote; } +void cmXCodeObject::PrintString(std::ostream& os) const +{ + cmXCodeObject::PrintString(os,this->String); +} + //---------------------------------------------------------------------------- void cmXCodeObject::SetString(const char* s) { diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h index 2bea63b..369fe66 100644 --- a/Source/cmXCodeObject.h +++ b/Source/cmXCodeObject.h @@ -139,8 +139,22 @@ public: { return this->DependLibraries; } + void AddDependTarget(const char* configName, + const char* tName) + { + if(!configName) + { + configName = ""; + } + this->DependTargets[configName].push_back(tName); + } + std::map<cmStdString, StringVec> const& GetDependTargets() + { + return this->DependTargets; + } std::vector<cmXCodeObject*> const& GetObjectList() { return this->List;} void SetComment(const char* c) { this->Comment = c;} + static void PrintString(std::ostream& os,cmStdString String); protected: void PrintString(std::ostream& os) const; @@ -155,6 +169,7 @@ protected: cmXCodeObject* PBXTargetDependencyValue; std::vector<cmXCodeObject*> List; std::map<cmStdString, StringVec> DependLibraries; + std::map<cmStdString, StringVec> DependTargets; std::map<cmStdString, cmXCodeObject*> ObjectAttributes; }; #endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index ea8cdfd..45927cb 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2346,11 +2346,6 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) std::string oldstartoutputdir = this->GetStartOutputDirectory(); this->SetStartDirectory(this->GetHomeDirectory()); this->SetStartOutputDirectory(this->GetHomeOutputDirectory()); - const bool warncli = this->WarnUnusedCli; - if (!this->ScriptMode) - { - this->WarnUnusedCli = false; - } int ret = this->Configure(); if (ret || this->ScriptMode) { @@ -2372,7 +2367,6 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) #endif return ret; } - this->WarnUnusedCli = warncli; ret = this->Generate(); std::string message = "Build files have been written to: "; message += this->GetHomeOutputDirectory(); @@ -2394,6 +2388,10 @@ int cmake::Generate() return -1; } this->GlobalGenerator->Generate(); + if(this->WarnUnusedCli) + { + this->RunCheckForUnusedVariables(); + } if(cmSystemTools::GetErrorOccuredFlag()) { return -1; @@ -2934,6 +2932,7 @@ void cmake::GenerateGraphViz(const char* fileName) const gvWriter->ReadSettings(settingsFile.c_str(), fallbackSettingsFile.c_str()); gvWriter->WritePerTargetFiles(fileName); + gvWriter->WriteTargetDependersFiles(fileName); gvWriter->WriteGlobalFile(fileName); #endif @@ -4347,7 +4346,10 @@ void cmake::WatchUnusedCli(const char* var) { #ifdef CMAKE_BUILD_WITH_CMAKE this->VariableWatch->AddWatch(var, cmWarnUnusedCliWarning, this); - this->UsedCliVariables[var] = false; + if(this->UsedCliVariables.find(var) == this->UsedCliVariables.end()) + { + this->UsedCliVariables[var] = false; + } #endif } @@ -4355,27 +4357,29 @@ void cmake::UnwatchUnusedCli(const char* var) { #ifdef CMAKE_BUILD_WITH_CMAKE this->VariableWatch->RemoveWatch(var, cmWarnUnusedCliWarning); - this->UsedCliVariables[var] = true; + this->UsedCliVariables.erase(var); #endif } -void cmake::RunCheckForUnusedVariables(const std::string& reason) const +void cmake::RunCheckForUnusedVariables() { #ifdef CMAKE_BUILD_WITH_CMAKE - if(this->WarnUnusedCli) + bool haveUnused = false; + cmOStringStream msg; + msg << "Manually-specified variables were not used by the project:"; + for(std::map<cmStdString, bool>::const_iterator + it = this->UsedCliVariables.begin(); + it != this->UsedCliVariables.end(); ++it) + { + if(!it->second) { - std::map<std::string, bool>::const_iterator it; - for(it = this->UsedCliVariables.begin(); - it != this->UsedCliVariables.end(); ++it) - { - if(!it->second) - { - std::string message = "CMake Warning: The variable, '" + it->first + - "', specified manually, was not used during the " + reason + - "."; - cmSystemTools::Message(message.c_str()); - } - } + haveUnused = true; + msg << "\n " << it->first; } + } + if(haveUnused) + { + this->IssueMessage(cmake::WARNING, msg.str(), cmListFileBacktrace()); + } #endif } diff --git a/Source/cmake.h b/Source/cmake.h index 132a86d..fac86c1 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -368,8 +368,8 @@ class cmake void UnwatchUnusedCli(const char* var); void WatchUnusedCli(const char* var); - void RunCheckForUnusedVariables(const std::string& reason) const; protected: + void RunCheckForUnusedVariables(); void InitializeProperties(); int HandleDeleteCacheVariables(const char* var); cmPropertyMap Properties; @@ -467,7 +467,7 @@ private: bool WarnUnused; bool WarnUnusedCli; bool CheckSystemVars; - std::map<std::string, bool> UsedCliVariables; + std::map<cmStdString, bool> UsedCliVariables; std::string CMakeEditCommand; std::string CMakeCommand; std::string CXXEnvironment; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index a5dca18..663ce8f 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -109,7 +109,8 @@ static const char * cmDocumentationOptions[][3] = "Dump a wide range of information about the current system. If run " "from the top of a binary tree for a CMake project it will dump " "additional information such as the cache, log files etc."}, - {"--debug-trycompile", "Do not delete the try compile directories..", + {"--debug-trycompile", "Do not delete the try_compile build tree. Only " + "useful on one try_compile at a time.", "Do not delete the files and directories created for try_compile calls. " "This is useful in debugging failed try_compiles. It may however " "change the results of the try-compiles as old junk from a previous " diff --git a/Source/kwsys/CheckCXXSourceRuns.cmake b/Source/kwsys/CheckCXXSourceRuns.cmake deleted file mode 100644 index 7bcc873..0000000 --- a/Source/kwsys/CheckCXXSourceRuns.cmake +++ /dev/null @@ -1,62 +0,0 @@ -# - Check if the source code provided in the SOURCE argument compiles. -# CHECK_CXX_SOURCE_COMPILES(SOURCE VAR) -# - macro which checks if the source code compiles\ -# SOURCE - source code to try to compile -# VAR - variable to store size if the type exists. -# -# The following variables may be set before calling this macro to -# modify the way the check is run: -# -# CMAKE_REQUIRED_FLAGS = string of compile command line flags -# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) -# CMAKE_REQUIRED_INCLUDES = list of include directories -# CMAKE_REQUIRED_LIBRARIES = list of libraries to link - -MACRO(CHECK_CXX_SOURCE_RUNS SOURCE VAR COMMENT) - IF("HAVE_${VAR}" MATCHES "^HAVE_${VAR}$") - SET(MACRO_CHECK_FUNCTION_DEFINITIONS - "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") - IF(CMAKE_REQUIRED_LIBRARIES) - SET(CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES - "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") - ELSE(CMAKE_REQUIRED_LIBRARIES) - SET(CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES) - ENDIF(CMAKE_REQUIRED_LIBRARIES) - IF(CMAKE_REQUIRED_INCLUDES) - SET(CHECK_CXX_SOURCE_COMPILES_ADD_INCLUDES - "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") - ELSE(CMAKE_REQUIRED_INCLUDES) - SET(CHECK_CXX_SOURCE_COMPILES_ADD_INCLUDES) - ENDIF(CMAKE_REQUIRED_INCLUDES) - SET(CMAKE_EMPTY_INPUT_FILE_CONTENT "${SOURCE}") - CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/CMakeEmptyInputFile.in" - "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/src.cxx" IMMEDIATE) - - MESSAGE(STATUS "Performing Test ${COMMENT}") - TRY_RUN(${VAR} HAVE_${VAR} - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/src.cxx - COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} - CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} - "${CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES}" - "${CHECK_CXX_SOURCE_COMPILES_ADD_INCLUDES}" - OUTPUT_VARIABLE OUTPUT) - IF(HAVE_${VAR}) - SET(${VAR} 1 CACHE INTERNAL "Test ${COMMENT}") - MESSAGE(STATUS "Performing Test ${COMMENT} - Success") - FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log - "Performing C++ SOURCE FILE Test ${COMMENT} succeded with the following output:\n" - "${OUTPUT}\n" - "Source file was:\n${SOURCE}\n") - ELSE(HAVE_${VAR}) - MESSAGE(STATUS "Performing Test ${COMMENT} - Failed") - SET(${VAR} "" CACHE INTERNAL "Test ${COMMENT}") - FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log - "Performing C++ SOURCE FILE Test ${COMMENT} failed with the following output:\n" - "${OUTPUT}\n" - "Source file was:\n${SOURCE}\n") - ENDIF(HAVE_${VAR}) - ENDIF("HAVE_${VAR}" MATCHES "^HAVE_${VAR}$") -ENDMACRO(CHECK_CXX_SOURCE_RUNS) - - diff --git a/Source/kwsys/EncodeExecutable.c b/Source/kwsys/EncodeExecutable.c index ba474b8..bc30568 100644 --- a/Source/kwsys/EncodeExecutable.c +++ b/Source/kwsys/EncodeExecutable.c @@ -41,6 +41,7 @@ int main(int argc, char* argv[]) if(!ofp) { fprintf(stderr, "Cannot open output file: \"%s\"\n", argv[2]); + fclose(ifp); return 2; } diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c index 3bf2579..25832c2 100644 --- a/Source/kwsys/Terminal.c +++ b/Source/kwsys/Terminal.c @@ -160,8 +160,10 @@ static const char* kwsysTerminalVT100Names[] = "rxvt-cygwin", "rxvt-cygwin-native", "rxvt-unicode", + "rxvt-unicode-256color", "screen", "screen-256color", + "screen-256color-bce", "screen-bce", "screen-w", "screen.linux", diff --git a/Source/kwsys/kwsysDateStamp.cmake b/Source/kwsys/kwsysDateStamp.cmake index 685baf6..06fe745 100644 --- a/Source/kwsys/kwsysDateStamp.cmake +++ b/Source/kwsys/kwsysDateStamp.cmake @@ -15,7 +15,7 @@ SET(KWSYS_DATE_STAMP_YEAR 2011) # KWSys version date month component. Format is MM. -SET(KWSYS_DATE_STAMP_MONTH 03) +SET(KWSYS_DATE_STAMP_MONTH 06) # KWSys version date day component. Format is DD. -SET(KWSYS_DATE_STAMP_DAY 28) +SET(KWSYS_DATE_STAMP_DAY 20) |