diff options
Diffstat (limited to 'Source')
216 files changed, 11953 insertions, 4132 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index fe6cc1b..f9405b3 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -308,6 +308,7 @@ set(SRCS cmTest.h cmTestGenerator.cxx cmTestGenerator.h + cmUuid.cxx cmVariableWatch.cxx cmVariableWatch.h cmVersion.cxx @@ -426,6 +427,8 @@ if (WIN32) cmGlobalVisualStudio11Generator.cxx cmGlobalVisualStudio12Generator.h cmGlobalVisualStudio12Generator.cxx + cmGlobalVisualStudio14Generator.h + cmGlobalVisualStudio14Generator.cxx cmGlobalVisualStudioGenerator.cxx cmGlobalVisualStudioGenerator.h cmIDEFlagTable.h @@ -448,7 +451,7 @@ if (WIN32) endif () # Watcom support -if(WIN32 OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") +if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux") set_property(SOURCE cmake.cxx APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_USE_WMAKE) list(APPEND SRCS cmGlobalWatcomWMakeGenerator.cxx @@ -518,6 +521,7 @@ set(CTEST_SRCS cmCTest.cxx CTest/cmParseMumpsCoverage.cxx CTest/cmParseCacheCoverage.cxx CTest/cmParseGTMCoverage.cxx + CTest/cmParseJacocoCoverage.cxx CTest/cmParsePHPCoverage.cxx CTest/cmParseCoberturaCoverage.cxx CTest/cmCTestEmptyBinaryDirectoryCommand.cxx @@ -574,11 +578,16 @@ set(CPACK_SRCS CPack/cmCPackGenerator.cxx CPack/cmCPackLog.cxx CPack/cmCPackNSISGenerator.cxx + CPack/IFW/cmCPackIFWPackage.cxx + CPack/IFW/cmCPackIFWInstaller.cxx + CPack/IFW/cmCPackIFWGenerator.cxx CPack/cmCPackSTGZGenerator.cxx CPack/cmCPackTGZGenerator.cxx + CPack/cmCPackTXZGenerator.cxx CPack/cmCPackTarBZip2Generator.cxx CPack/cmCPackTarCompressGenerator.cxx CPack/cmCPackZIPGenerator.cxx + CPack/cmCPack7zGenerator.cxx ) if(CYGWIN) @@ -598,13 +607,14 @@ endif() if(WIN32) set(CPACK_SRCS ${CPACK_SRCS} CPack/WiX/cmCPackWIXGenerator.cxx - CPack/WiX/cmWIXSourceWriter.cxx + CPack/WiX/cmWIXAccessControlList.cxx CPack/WiX/cmWIXDirectoriesSourceWriter.cxx CPack/WiX/cmWIXFeaturesSourceWriter.cxx CPack/WiX/cmWIXFilesSourceWriter.cxx - CPack/WiX/cmWIXRichTextFormatWriter.cxx CPack/WiX/cmWIXPatch.cxx CPack/WiX/cmWIXPatchParser.cxx + CPack/WiX/cmWIXRichTextFormatWriter.cxx + CPack/WiX/cmWIXSourceWriter.cxx ) endif() diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 34aefb4..716f229 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) -set(CMake_VERSION_MINOR 0) -set(CMake_VERSION_PATCH 20140609) -#set(CMake_VERSION_RC 1) +set(CMake_VERSION_MINOR 1) +set(CMake_VERSION_PATCH 0) +set(CMake_VERSION_RC 1) diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx new file mode 100644 index 0000000..7f06e2d --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -0,0 +1,552 @@ +/*============================================================================ + 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 "cmCPackIFWGenerator.h" + +#include "cmCPackIFWPackage.h" +#include "cmCPackIFWInstaller.h" + +#include <CPack/cmCPackLog.h> +#include <CPack/cmCPackComponentGroup.h> + +#include <cmsys/SystemTools.hxx> +#include <cmsys/Glob.hxx> +#include <cmsys/Directory.hxx> +#include <cmsys/RegularExpression.hxx> + +#include <cmGlobalGenerator.h> +#include <cmLocalGenerator.h> +#include <cmSystemTools.h> +#include <cmMakefile.h> +#include <cmGeneratedFileStream.h> +#include <cmXMLSafe.h> + +//---------------------------------------------------------------------------- +cmCPackIFWGenerator::cmCPackIFWGenerator() +{ +} + +//---------------------------------------------------------------------------- +cmCPackIFWGenerator::~cmCPackIFWGenerator() +{ +} + +//---------------------------------------------------------------------------- +int cmCPackIFWGenerator::PackageFiles() +{ + cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Configuration" << std::endl); + + // Installer configuragion + Installer.GenerateInstallerFile(); + + // Packages configuration + Installer.GeneratePackageFiles(); + + std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + std::string ifwTmpFile = ifwTLD; + ifwTmpFile += "/IFWOutput.log"; + + // Run repogen + if (!Installer.Repositories.empty()) + { + std::string ifwCmd = RepoGen; + ifwCmd += " -c " + this->toplevel + "/config/config.xml"; + ifwCmd += " -p " + this->toplevel + "/packages"; + + if(!PkgsDirsVector.empty()) + { + for(std::vector<std::string>::iterator it = PkgsDirsVector.begin(); + it != PkgsDirsVector.end(); ++it) + { + ifwCmd += " -p " + *it; + } + } + + if (!OnlineOnly && !DownloadedPackages.empty()) + { + ifwCmd += " -i "; + std::set<cmCPackIFWPackage*>::iterator it + = DownloadedPackages.begin(); + ifwCmd += (*it)->Name; + ++it; + while(it != DownloadedPackages.end()) + { + ifwCmd += "," + (*it)->Name; + ++it; + } + } + ifwCmd += " " + this->toplevel + "/repository"; + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd + << std::endl); + std::string output; + int retVal = 1; + cmCPackLogger(cmCPackLog::LOG_OUTPUT, + "- Generate repository" << std::endl); + bool res = cmSystemTools::RunSingleCommand( + ifwCmd.c_str(), &output, &retVal, 0, this->GeneratorVerbose, 0); + if ( !res || retVal ) + { + cmGeneratedFileStream ofs(ifwTmpFile.c_str()); + ofs << "# Run command: " << ifwCmd << std::endl + << "# Output:" << std::endl + << output << std::endl; + cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: " + << ifwCmd << std::endl + << "Please check " << ifwTmpFile << " for errors" + << std::endl); + return 0; + } + cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- repository: " << this->toplevel + << "/repository generated" << std::endl); + } + + // Run binary creator + { + std::string ifwCmd = BinCreator; + ifwCmd += " -c " + this->toplevel + "/config/config.xml"; + ifwCmd += " -p " + this->toplevel + "/packages"; + + if(!PkgsDirsVector.empty()) + { + for(std::vector<std::string>::iterator it = PkgsDirsVector.begin(); + it != PkgsDirsVector.end(); ++it) + { + ifwCmd += " -p " + *it; + } + } + + if (OnlineOnly) + { + ifwCmd += " --online-only"; + } + else if (!DownloadedPackages.empty() && !Installer.Repositories.empty()) + { + ifwCmd += " -e "; + std::set<cmCPackIFWPackage*>::iterator it + = DownloadedPackages.begin(); + ifwCmd += (*it)->Name; + ++it; + while(it != DownloadedPackages.end()) + { + ifwCmd += "," + (*it)->Name; + ++it; + } + } + else if (!DependentPackages.empty()) + { + ifwCmd += " -i "; + // Binary + std::set<cmCPackIFWPackage*>::iterator bit = BinaryPackages.begin(); + while(bit != BinaryPackages.end()) + { + ifwCmd += (*bit)->Name + ","; + ++bit; + } + // Depend + DependenceMap::iterator it = DependentPackages.begin(); + ifwCmd += it->second.Name; + ++it; + while(it != DependentPackages.end()) + { + ifwCmd += "," + it->second.Name; + ++it; + } + } + // TODO: set correct name for multipackages + if (this->packageFileNames.size() > 0) + { + ifwCmd += " " + packageFileNames[0]; + } + else + { + ifwCmd += " installer"; + } + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd + << std::endl); + std::string output; + int retVal = 1; + cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Generate package" << std::endl); + bool res = cmSystemTools::RunSingleCommand( + ifwCmd.c_str(), &output, &retVal, 0, this->GeneratorVerbose, 0); + if ( !res || retVal ) + { + cmGeneratedFileStream ofs(ifwTmpFile.c_str()); + ofs << "# Run command: " << ifwCmd << std::endl + << "# Output:" << std::endl + << output << std::endl; + cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: " + << ifwCmd << std::endl + << "Please check " << ifwTmpFile << " for errors" + << std::endl); + return 0; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +const char *cmCPackIFWGenerator::GetPackagingInstallPrefix() +{ + const char *defPrefix = cmCPackGenerator::GetPackagingInstallPrefix(); + + std::string tmpPref = defPrefix ? defPrefix : ""; + + if(this->Components.empty()) + { + tmpPref += "packages/" + GetRootPackageName() + "/data"; + } + + this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str()); + + return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX"); +} + +//---------------------------------------------------------------------------- +const char *cmCPackIFWGenerator::GetOutputExtension() +{ + const char *suffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX"); + return suffix ? suffix : cmCPackGenerator::GetOutputExtension(); +} + +//---------------------------------------------------------------------------- +int cmCPackIFWGenerator::InitializeInternal() +{ + // Search Qt Installer Framework tools + + const std::string BinCreatorOpt = "CPACK_IFW_BINARYCREATOR_EXECUTABLE"; + const std::string RepoGenOpt = "CPACK_IFW_REPOGEN_EXECUTABLE"; + + if(!this->IsSet(BinCreatorOpt) || + !this->IsSet(RepoGenOpt)) + { + this->ReadListFile("CPackIFW.cmake"); + } + + // Look 'binarycreator' executable (needs) + + const char *BinCreatorStr = this->GetOption(BinCreatorOpt); + if(!BinCreatorStr || cmSystemTools::IsNOTFOUND(BinCreatorStr)) + { + BinCreator = ""; + } + else + { + BinCreator = BinCreatorStr; + } + + if (BinCreator.empty()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot find QtIFW compiler \"binarycreator\": " + "likely it is not installed, or not in your PATH" + << std::endl); + return 0; + } + + // Look 'repogen' executable (optional) + + const char *RepoGenStr = this->GetOption(RepoGenOpt); + if(!RepoGenStr || cmSystemTools::IsNOTFOUND(RepoGenStr)) + { + RepoGen = ""; + } + else + { + RepoGen = RepoGenStr; + } + + // Variables that Change Behavior + + // Resolve duplicate names + ResolveDuplicateNames = this->IsOn("CPACK_IFW_RESOLVE_DUPLICATE_NAMES"); + + // Additional packages dirs + PkgsDirsVector.clear(); + if(const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) + { + cmSystemTools::ExpandListArgument(dirs, + PkgsDirsVector); + } + + // Installer + Installer.Generator = this; + Installer.ConfigureFromOptions(); + + if (const char* ifwDownloadAll = + this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) + { + OnlineOnly = cmSystemTools::IsOn(ifwDownloadAll); + } + else if (const char* cpackDownloadAll = + this->GetOption("CPACK_DOWNLOAD_ALL")) + { + OnlineOnly = cmSystemTools::IsOn(cpackDownloadAll); + } + else + { + OnlineOnly = false; + } + + if (!Installer.Repositories.empty() && RepoGen.empty()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot find QtIFW repository generator \"repogen\": " + "likely it is not installed, or not in your PATH" + << std::endl); + return 0; + } + + return this->Superclass::InitializeInternal(); +} + +//---------------------------------------------------------------------------- +std::string +cmCPackIFWGenerator::GetComponentInstallDirNameSuffix( + const std::string& componentName) +{ + const std::string prefix = "packages/"; + const std::string suffix = "/data"; + + if (componentPackageMethod == ONE_PACKAGE) { + return std::string(prefix + GetRootPackageName() + suffix); + } + + return prefix + + GetComponentPackageName(&Components[componentName]) + + suffix; +} + +//---------------------------------------------------------------------------- +cmCPackComponent* +cmCPackIFWGenerator::GetComponent(const std::string &projectName, + const std::string &componentName) +{ + ComponentsMap::iterator cit = Components.find(componentName); + if ( cit != Components.end() ) return &(cit->second); + + cmCPackComponent* component + = cmCPackGenerator::GetComponent(projectName, componentName); + if(!component) return component; + + std::string name = GetComponentPackageName(component); + PackagesMap::iterator pit = Packages.find(name); + if(pit != Packages.end()) return component; + + cmCPackIFWPackage *package = &Packages[name]; + package->Name = name; + package->Generator = this; + if(package->ConfigureFromComponent(component)) + { + package->Installer = &Installer; + Installer.Packages.insert( + std::pair<std::string, cmCPackIFWPackage*>( + name, package)); + ComponentPackages.insert( + std::pair<cmCPackComponent*, cmCPackIFWPackage*>( + component, package)); + if(component->IsDownloaded) + { + DownloadedPackages.insert(package); + } + else + { + BinaryPackages.insert(package); + } + } + else + { + Packages.erase(name); + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot configure package \"" << name << + "\" for component \"" << component->Name << "\"" + << std::endl); + } + + return component; +} + +//---------------------------------------------------------------------------- +cmCPackComponentGroup* +cmCPackIFWGenerator::GetComponentGroup(const std::string &projectName, + const std::string &groupName) +{ + cmCPackComponentGroup* group + = cmCPackGenerator::GetComponentGroup(projectName, groupName); + if(!group) return group; + + std::string name = GetGroupPackageName(group); + PackagesMap::iterator pit = Packages.find(name); + if(pit != Packages.end()) return group; + + cmCPackIFWPackage *package = &Packages[name]; + package->Name = name; + package->Generator = this; + if(package->ConfigureFromGroup(group)) + { + package->Installer = &Installer; + Installer.Packages.insert( + std::pair<std::string, cmCPackIFWPackage*>( + name, package)); + GroupPackages.insert( + std::pair<cmCPackComponentGroup*, cmCPackIFWPackage*>( + group, package)); + BinaryPackages.insert(package); + } + else + { + Packages.erase(name); + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Cannot configure package \"" << name << + "\" for component group \"" << group->Name << "\"" + << std::endl); + } + return group; +} + +//---------------------------------------------------------------------------- +enum cmCPackGenerator::CPackSetDestdirSupport +cmCPackIFWGenerator::SupportsSetDestdir() const +{ + return cmCPackGenerator::SETDESTDIR_SHOULD_NOT_BE_USED; +} + +//---------------------------------------------------------------------------- +bool cmCPackIFWGenerator::SupportsAbsoluteDestination() const +{ + return false; +} + +//---------------------------------------------------------------------------- +bool cmCPackIFWGenerator::SupportsComponentInstallation() const +{ + return true; +} + +//---------------------------------------------------------------------------- +bool cmCPackIFWGenerator::IsOnePackage() const +{ + return componentPackageMethod == ONE_PACKAGE; +} + +//---------------------------------------------------------------------------- +std::string cmCPackIFWGenerator::GetRootPackageName() +{ + // Default value + std::string name = "root"; + if (const char* optIFW_PACKAGE_GROUP = + this->GetOption("CPACK_IFW_PACKAGE_GROUP")) + { + // Configure from root group + cmCPackIFWPackage package; + package.Generator = this; + package.ConfigureFromGroup(optIFW_PACKAGE_GROUP); + name = package.Name; + } + else if (const char* optIFW_PACKAGE_NAME = + this->GetOption("CPACK_IFW_PACKAGE_NAME")) + { + // Configure from root package name + name = optIFW_PACKAGE_NAME; + } + else if (const char* optPACKAGE_NAME = + this->GetOption("CPACK_PACKAGE_NAME")) + { + // Configure from package name + name = optPACKAGE_NAME; + } + return name; +} + +//---------------------------------------------------------------------------- +std::string +cmCPackIFWGenerator::GetGroupPackageName(cmCPackComponentGroup *group) const +{ + std::string name; + if (!group) return name; + if (cmCPackIFWPackage* package = GetGroupPackage(group)) + { + return package->Name; + } + const char* option = GetOption( + "CPACK_IFW_COMPONENT_GROUP_" + + cmsys::SystemTools::UpperCase(group->Name) + + "_NAME"); + name = option ? option : group->Name; + if(group->ParentGroup) + { + cmCPackIFWPackage* package = GetGroupPackage(group->ParentGroup); + bool dot = !ResolveDuplicateNames; + if(dot && name.substr(0, package->Name.size()) == package->Name) + { + dot = false; + } + if(dot) + { + name = package->Name + "." + name; + } + } + return name; +} + +//---------------------------------------------------------------------------- +std::string cmCPackIFWGenerator::GetComponentPackageName( + cmCPackComponent *component) const +{ + std::string name; + if (!component) return name; + if (cmCPackIFWPackage* package = GetComponentPackage(component)) + { + return package->Name; + } + std::string prefix = "CPACK_IFW_COMPONENT_" + + cmsys::SystemTools::UpperCase(component->Name) + + "_"; + const char* option = GetOption(prefix + "NAME"); + name = option ? option : component->Name; + if(component->Group) + { + cmCPackIFWPackage* package = GetGroupPackage(component->Group); + if((componentPackageMethod == ONE_PACKAGE_PER_GROUP) + || IsOn(prefix + "COMMON")) + { + return package->Name; + } + bool dot = !ResolveDuplicateNames; + if(dot && name.substr(0, package->Name.size()) == package->Name) + { + dot = false; + } + if(dot) + { + name = package->Name + "." + name; + } + } + return name; +} + +//---------------------------------------------------------------------------- +cmCPackIFWPackage* cmCPackIFWGenerator::GetGroupPackage( + cmCPackComponentGroup *group) const +{ + std::map<cmCPackComponentGroup*, cmCPackIFWPackage*>::const_iterator pit + = GroupPackages.find(group); + return pit != GroupPackages.end() ? pit->second : 0; +} + +//---------------------------------------------------------------------------- +cmCPackIFWPackage* cmCPackIFWGenerator::GetComponentPackage( + cmCPackComponent *component) const +{ + std::map<cmCPackComponent*, cmCPackIFWPackage*>::const_iterator pit + = ComponentPackages.find(component); + return pit != ComponentPackages.end() ? pit->second : 0; +} diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.h b/Source/CPack/IFW/cmCPackIFWGenerator.h new file mode 100644 index 0000000..1d4d67b --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWGenerator.h @@ -0,0 +1,135 @@ +/*============================================================================ + 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 cmCPackIFWGenerator_h +#define cmCPackIFWGenerator_h + +#include <CPack/cmCPackGenerator.h> + +#include "cmCPackIFWPackage.h" +#include "cmCPackIFWInstaller.h" + +/** \class cmCPackIFWGenerator + * \brief A generator for Qt Installer Framework tools + * + * http://qt-project.org/doc/qtinstallerframework/index.html + */ +class cmCPackIFWGenerator : public cmCPackGenerator +{ +public: + cmCPackTypeMacro(cmCPackIFWGenerator, cmCPackGenerator); + + typedef std::map<std::string, cmCPackIFWPackage> PackagesMap; + typedef std::map<std::string, cmCPackComponent> ComponentsMap; + typedef std::map<std::string, cmCPackComponentGroup> ComponentGoupsMap; + typedef std::map<std::string, cmCPackIFWPackage::DependenceStruct> + DependenceMap; + + /** + * Construct IFW generator + */ + cmCPackIFWGenerator(); + + /** + * Destruct IFW generator + */ + virtual ~cmCPackIFWGenerator(); + +protected: // cmCPackGenerator reimplementation + + /** + * @brief Initialize generator + * @return 0 on failure + */ + virtual int InitializeInternal(); + virtual int PackageFiles(); + virtual const char* GetPackagingInstallPrefix(); + + /** + * @brief Extension of binary installer + * @return Executable suffix or value from default implementation + */ + virtual const char* GetOutputExtension(); + + virtual std::string GetComponentInstallDirNameSuffix( + const std::string& componentName); + + /** + * @brief Get Component + * @param projectName Project name + * @param componentName Component name + * + * This method calls the base implementation. + * + * @return Pointer to component + */ + virtual cmCPackComponent* GetComponent( + const std::string& projectName, + const std::string& componentName); + + /** + * @brief Get group of component + * @param projectName Project name + * @param groupName Component group name + * + * This method calls the base implementation. + * + * @return Pointer to component group + */ + virtual cmCPackComponentGroup* GetComponentGroup( + const std::string& projectName, + const std::string& groupName); + + enum cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir() const; + virtual bool SupportsAbsoluteDestination() const; + virtual bool SupportsComponentInstallation() const; + +protected: // Methods + + bool IsOnePackage() const; + + std::string GetRootPackageName(); + + std::string GetGroupPackageName(cmCPackComponentGroup *group) const; + std::string GetComponentPackageName(cmCPackComponent *component) const; + + cmCPackIFWPackage* GetGroupPackage(cmCPackComponentGroup *group) const; + cmCPackIFWPackage* GetComponentPackage(cmCPackComponent *component) const; + +protected: // Data + + friend class cmCPackIFWPackage; + friend class cmCPackIFWInstaller; + + // Installer + cmCPackIFWInstaller Installer; + // Collection of packages + PackagesMap Packages; + // Collection of binary packages + std::set<cmCPackIFWPackage*> BinaryPackages; + // Collection of downloaded packages + std::set<cmCPackIFWPackage*> DownloadedPackages; + // Dependent packages + DependenceMap DependentPackages; + std::map<cmCPackComponent*, cmCPackIFWPackage*> ComponentPackages; + std::map<cmCPackComponentGroup*, cmCPackIFWPackage*> GroupPackages; + +private: + std::string RepoGen; + std::string BinCreator; + + bool OnlineOnly; + bool ResolveDuplicateNames; + std::vector<std::string> PkgsDirsVector; +}; + +#endif diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx new file mode 100644 index 0000000..0644ecb --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -0,0 +1,406 @@ +/*============================================================================ + 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 "cmCPackIFWInstaller.h" + +#include "cmCPackIFWGenerator.h" + +#include <CPack/cmCPackLog.h> + +#include <cmGeneratedFileStream.h> +#include <cmXMLSafe.h> + +#ifdef cmCPackLogger +# undef cmCPackLogger +#endif +#define cmCPackLogger(logType, msg) \ + do { \ + cmOStringStream cmCPackLog_msg; \ + cmCPackLog_msg << msg; \ + if(Generator) { \ + Generator->Logger->Log(logType, __FILE__, __LINE__, \ + cmCPackLog_msg.str().c_str()); \ + } \ + } while ( 0 ) + +//---------------------------------------------------------------------------- +cmCPackIFWInstaller::cmCPackIFWInstaller() : + Generator(0) +{ +} + +//---------------------------------------------------------------------------- +const char *cmCPackIFWInstaller::GetOption(const std::string &op) const +{ + return Generator ? Generator->GetOption(op) : 0; +} + +//---------------------------------------------------------------------------- +bool cmCPackIFWInstaller::IsOn(const std::string &op) const +{ + return Generator ? Generator->IsOn(op) : false; +} + +//---------------------------------------------------------------------------- +void cmCPackIFWInstaller::ConfigureFromOptions() +{ + // Name; + if (const char* optIFW_PACKAGE_NAME = + this->GetOption("CPACK_IFW_PACKAGE_NAME")) + { + Name = optIFW_PACKAGE_NAME; + } + else if (const char* optPACKAGE_NAME = + this->GetOption("CPACK_PACKAGE_NAME")) + { + Name = optPACKAGE_NAME; + } + else + { + Name = "Your package"; + } + + // Title; + if (const char* optIFW_PACKAGE_TITLE = + GetOption("CPACK_IFW_PACKAGE_TITLE")) + { + Title = optIFW_PACKAGE_TITLE; + } + else if (const char* optPACKAGE_DESCRIPTION_SUMMARY = + GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) + { + Title = optPACKAGE_DESCRIPTION_SUMMARY; + } + else + { + Title = "Your package description"; + } + + // Version; + if (const char* option = GetOption("CPACK_PACKAGE_VERSION")) + { + Version = option; + } + else + { + Version = "1.0.0"; + } + + // Publisher + if(const char* optIFW_PACKAGE_PUBLISHER = + GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) + { + Publisher = optIFW_PACKAGE_PUBLISHER; + } + else if(const char* optPACKAGE_VENDOR = GetOption("CPACK_PACKAGE_VENDOR")) + { + Publisher = optPACKAGE_VENDOR; + } + + // ProductUrl + if(const char* option = GetOption("CPACK_IFW_PRODUCT_URL")) + { + ProductUrl = option; + } + + // ApplicationIcon + if(const char* option = GetOption("CPACK_IFW_PACKAGE_ICON")) + { + if(cmSystemTools::FileExists(option)) + { + InstallerApplicationIcon = option; + } + else + { + // TODO: implement warning + } + } + + // WindowIcon + if(const char* option = GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) + { + if(cmSystemTools::FileExists(option)) + { + InstallerWindowIcon = option; + } + else + { + // TODO: implement warning + } + } + + // Logo + if(const char* option = GetOption("CPACK_IFW_PACKAGE_LOGO")) + { + if(cmSystemTools::FileExists(option)) + { + Logo = option; + } + else + { + // TODO: implement warning + } + } + + // Default target directory for installation + if (const char* optIFW_TARGET_DIRECTORY = + GetOption("CPACK_IFW_TARGET_DIRECTORY")) + { + TargetDir = optIFW_TARGET_DIRECTORY; + } + else if (const char *optPACKAGE_INSTALL_DIRECTORY = + GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) + { + TargetDir = "@ApplicationsDir@/"; + TargetDir += optPACKAGE_INSTALL_DIRECTORY; + } + else + { + TargetDir = "@RootDir@/usr/local"; + } + + // Default target directory for installation with administrator rights + if (const char* option = GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) + { + AdminTargetDir = option; + } + + // Repositories + Repositories.clear(); + RepositoryStruct Repo; + if (const char *site = this->GetOption("CPACK_DOWNLOAD_SITE")) + { + Repo.Url = site; + Repositories.push_back(Repo); + } + if(const char *RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) + { + std::vector<std::string> RepoAllVector; + cmSystemTools::ExpandListArgument(RepoAllStr, + RepoAllVector); + for(std::vector<std::string>::iterator + rit = RepoAllVector.begin(); rit != RepoAllVector.end(); ++rit) + { + std::string prefix = "CPACK_IFW_REPOSITORY_" + + cmsys::SystemTools::UpperCase(*rit) + + "_"; + // Url + if (const char* url = GetOption(prefix + "URL")) + { + Repo.Url = url; + } + else + { + Repo.Url = ""; + } + // Enabled + if (IsOn(prefix + "DISABLED")) + { + Repo.Enabled = "0"; + } + else + { + Repo.Enabled = ""; + } + // Username + if (const char* username = GetOption(prefix + "USERNAME")) + { + Repo.Username = username; + } + else + { + Repo.Username = ""; + } + // Password + if (const char* password = GetOption(prefix + "PASSWORD")) + { + Repo.Password = password; + } + else + { + Repo.Password = ""; + } + // DisplayName + if (const char* displayName = GetOption(prefix + "DISPLAY_NAME")) + { + Repo.DisplayName = displayName; + } + else + { + Repo.DisplayName = ""; + } + + if(!Repo.Url.empty()) + { + Repositories.push_back(Repo); + } + } + } +} + +//---------------------------------------------------------------------------- +void cmCPackIFWInstaller::GenerateInstallerFile() +{ + // Lazy directory initialization + if(Directory.empty() && Generator) + { + Directory = Generator->toplevel; + } + + // Output stream + cmGeneratedFileStream xout((Directory + "/config/config.xml").data()); + + xout << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl; + xout << "<Installer>" << std::endl; + + xout << " <Name>" << cmXMLSafe(Name).str() << "</Name>" << std::endl; + + xout << " <Version>" << Version << "</Version>" << std::endl; + + xout << " <Title>" << cmXMLSafe(Title).str() << "</Title>" + << std::endl; + + if(!Publisher.empty()) + { + xout << " <Publisher>" << cmXMLSafe(Publisher).str() + << "</Publisher>" << std::endl; + } + + if(!ProductUrl.empty()) + { + xout << " <ProductUrl>" << ProductUrl << "</ProductUrl>" << std::endl; + } + + // ApplicationIcon + if(!InstallerApplicationIcon.empty()) + { + std::string name = + cmSystemTools::GetFilenameName(InstallerApplicationIcon); + std::string path = Directory + "/config/" + name; + name = cmSystemTools::GetFilenameWithoutExtension(name); + cmsys::SystemTools::CopyFileIfDifferent( + InstallerApplicationIcon.data(), path.data()); + xout << " <InstallerApplicationIcon>" << name + << "</InstallerApplicationIcon>" << std::endl; + } + + // WindowIcon + if(!InstallerWindowIcon.empty()) + { + std::string name = cmSystemTools::GetFilenameName(InstallerWindowIcon); + std::string path = Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent( + InstallerWindowIcon.data(), path.data()); + xout << " <InstallerWindowIcon>" << name + << "</InstallerWindowIcon>" << std::endl; + } + + // Logo + if(!Logo.empty()) + { + std::string name = cmSystemTools::GetFilenameName(Logo); + std::string path = Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(Logo.data(), path.data()); + xout << " <Logo>" << name << "</Logo>" << std::endl; + } + + if(!TargetDir.empty()) + { + xout << " <TargetDir>" << TargetDir << "</TargetDir>" << std::endl; + } + + if(!AdminTargetDir.empty()) + { + xout << " <AdminTargetDir>" << AdminTargetDir + << "</AdminTargetDir>" << std::endl; + } + + // Remote repositories + if (!Repositories.empty()) + { + xout << " <RemoteRepositories>" << std::endl; + for(std::vector<RepositoryStruct>::iterator + rit = Repositories.begin(); rit != Repositories.end(); ++rit) + { + xout << " <Repository>" << std::endl; + // Url + xout << " <Url>" << rit->Url + << "</Url>" << std::endl; + // Enabled + if(!rit->Enabled.empty()) + { + xout << " <Enabled>" << rit->Enabled + << "</Enabled>" << std::endl; + } + // Username + if(!rit->Username.empty()) + { + xout << " <Username>" << rit->Username + << "</Username>" << std::endl; + } + // Password + if(!rit->Password.empty()) + { + xout << " <Password>" << rit->Password + << "</Password>" << std::endl; + } + // DisplayName + if(!rit->DisplayName.empty()) + { + xout << " <DisplayName>" << rit->DisplayName + << "</DisplayName>" << std::endl; + } + xout << " </Repository>" << std::endl; + } + xout << " </RemoteRepositories>" << std::endl; + } + + // CPack IFW default policy + xout << " <!-- CPack IFW default policy -->" << std::endl; + xout << " <AllowNonAsciiCharacters>true</AllowNonAsciiCharacters>" + << std::endl; + xout << " <AllowSpaceInPath>true</AllowSpaceInPath>" << std::endl; + + xout << "</Installer>" << std::endl; +} + +//---------------------------------------------------------------------------- +void cmCPackIFWInstaller::GeneratePackageFiles() +{ + if (Packages.empty() || Generator->IsOnePackage()) + { + // Generate default package + cmCPackIFWPackage package; + package.Generator = Generator; + package.Installer = this; + // Check package group + if (const char* option = GetOption("CPACK_IFW_PACKAGE_GROUP")) + { + package.ConfigureFromGroup(option); + package.ForcedInstallation = "true"; + } + else + { + package.ConfigureFromOptions(); + } + package.GeneratePackageFile(); + return; + } + + // Generate packages meta information + for(PackagesMap::iterator pit = Packages.begin(); + pit != Packages.end(); ++pit) + { + cmCPackIFWPackage* package = pit->second; + package->GeneratePackageFile(); + } +} diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h new file mode 100644 index 0000000..5824d33 --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWInstaller.h @@ -0,0 +1,95 @@ +/*============================================================================ + 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 cmCPackIFWInstaller_h +#define cmCPackIFWInstaller_h + +#include <cmStandardIncludes.h> + +class cmCPackIFWPackage; +class cmCPackIFWGenerator; + +/** \class cmCPackIFWInstaller + * \brief A binary installer to be created CPack IFW generator + */ +class cmCPackIFWInstaller +{ +public: // Types + + typedef std::map<std::string, cmCPackIFWPackage*> PackagesMap; + + struct RepositoryStruct + { + std::string Url; + std::string Enabled; + std::string Username; + std::string Password; + std::string DisplayName; + }; + +public: // Constructor + + /** + * Construct installer + */ + cmCPackIFWInstaller(); + +public: // Configuration + + /// Name of the product being installed + std::string Name; + + /// Version number of the product being installed + std::string Version; + + /// Name of the installer as displayed on the title bar + std::string Title; + + /// Publisher of the software (as shown in the Windows Control Panel) + std::string Publisher; + + /// URL to a page that contains product information on your web site + std::string ProductUrl; + + /// Filename for a custom installer icon + std::string InstallerApplicationIcon; + + /// Filename for a custom window icon + std::string InstallerWindowIcon; + + /// Filename for a logo + std::string Logo; + + /// Default target directory for installation + std::string TargetDir; + + /// Default target directory for installation with administrator rights + std::string AdminTargetDir; + +public: // Internal implementation + + const char* GetOption(const std::string& op) const; + bool IsOn(const std::string& op) const; + + void ConfigureFromOptions(); + + void GenerateInstallerFile(); + + void GeneratePackageFiles(); + + cmCPackIFWGenerator* Generator; + PackagesMap Packages; + std::vector<RepositoryStruct> Repositories; + std::string Directory; +}; + +#endif // cmCPackIFWInstaller_h diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx new file mode 100644 index 0000000..3c45639 --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -0,0 +1,540 @@ +/*============================================================================ + 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 "cmCPackIFWPackage.h" + +#include "cmCPackIFWGenerator.h" + +#include <CPack/cmCPackLog.h> + +#include <cmGeneratedFileStream.h> +#include <cmTimestamp.h> + +//----------------------------------------------------------------- Logger --- +#ifdef cmCPackLogger +# undef cmCPackLogger +#endif +#define cmCPackLogger(logType, msg) \ + do { \ + cmOStringStream cmCPackLog_msg; \ + cmCPackLog_msg << msg; \ + if(Generator) { \ + Generator->Logger->Log(logType, __FILE__, __LINE__, \ + cmCPackLog_msg.str().c_str()); \ + } \ + } while ( 0 ) + +//---------------------------------------------------------- CompareStruct --- +cmCPackIFWPackage::CompareStruct::CompareStruct() : + Type(CompareNone) +{ +} + +//------------------------------------------------------- DependenceStruct --- +cmCPackIFWPackage::DependenceStruct::DependenceStruct() +{ +} + +//---------------------------------------------------------------------------- +cmCPackIFWPackage::DependenceStruct::DependenceStruct( + const std::string &dependence) +{ + // Search compare section + size_t pos = std::string::npos; + if((pos = dependence.find("<=")) != std::string::npos) + { + Compare.Type = CompareLessOrEqual; + Compare.Value = dependence.substr(pos + 2); + } + else if((pos = dependence.find(">=")) != std::string::npos) + { + Compare.Type = CompareGreaterOrEqual; + Compare.Value = dependence.substr(pos + 2); + } + else if((pos = dependence.find("<")) != std::string::npos) + { + Compare.Type = CompareLess; + Compare.Value = dependence.substr(pos + 1); + } + else if((pos = dependence.find("=")) != std::string::npos) + { + Compare.Type = CompareEqual; + Compare.Value = dependence.substr(pos + 1); + } + else if((pos = dependence.find(">")) != std::string::npos) + { + Compare.Type = CompareGreater; + Compare.Value = dependence.substr(pos + 1); + } + Name = pos == std::string::npos ? dependence : dependence.substr(0, pos); +} + +//---------------------------------------------------------------------------- +std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const +{ + if (Compare.Type == CompareNone) return Name; + + std::string result = Name; + + if (Compare.Type == CompareLessOrEqual) + { + result += "<="; + } + else if (Compare.Type == CompareGreaterOrEqual) + { + result += ">="; + } + else if (Compare.Type == CompareLess) + { + result += "<"; + } + else if (Compare.Type == CompareEqual) + { + result += "="; + } + else if (Compare.Type == CompareGreater) + { + result += ">"; + } + + result += Compare.Value; + + return result; +} + +//------------------------------------------------------ cmCPackIFWPackage --- +cmCPackIFWPackage::cmCPackIFWPackage() : + Generator(0), + Installer(0) +{ +} + +//---------------------------------------------------------------------------- +const char *cmCPackIFWPackage::GetOption(const std::string &op) const +{ + const char *option = Generator ? Generator->GetOption(op) : 0; + return option && *option ? option : 0; +} + +//---------------------------------------------------------------------------- +bool cmCPackIFWPackage::IsOn(const std::string &op) const +{ + return Generator ? Generator->IsOn(op) : false; +} + +//---------------------------------------------------------------------------- +std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent *component) +{ + if (!component) return ""; + const char* option = GetOption( + "CPACK_IFW_COMPONENT_" + + cmsys::SystemTools::UpperCase(component->Name) + + "_NAME"); + return option ? option : component->Name; +} + +//---------------------------------------------------------------------------- +void cmCPackIFWPackage::DefaultConfiguration() +{ + DisplayName = ""; + Description = ""; + Version = ""; + ReleaseDate = ""; + Script = ""; + Licenses.clear(); + SortingPriority = ""; + Default = ""; + Virtual = ""; + ForcedInstallation = ""; +} + +//---------------------------------------------------------------------------- +// Defaul configuration (all in one package) +int cmCPackIFWPackage::ConfigureFromOptions() +{ + // Restore defaul configuration + DefaultConfiguration(); + + // Name + Name = Generator->GetRootPackageName(); + + // Display name + if (const char *option = this->GetOption("CPACK_PACKAGE_NAME")) + { + DisplayName = option; + } + else + { + DisplayName = "Your package"; + } + + // Description + if (const char* option = + this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) + { + Description = option; + } + else + { + Description = "Your package description"; + } + + // Version + if(const char* option = GetOption("CPACK_PACKAGE_VERSION")) + { + Version = option; + } + else + { + Version = "1.0.0"; + } + + ForcedInstallation = "true"; + + return 1; +} + +//---------------------------------------------------------------------------- +int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent *component) +{ + if(!component) return 0; + + // Restore defaul configuration + DefaultConfiguration(); + + std::string prefix = "CPACK_IFW_COMPONENT_" + + cmsys::SystemTools::UpperCase(component->Name) + + "_"; + + // Display name + DisplayName = component->DisplayName; + + // Description + Description = component->Description; + + // Version + if(const char* optVERSION = GetOption(prefix + "VERSION")) + { + Version = optVERSION; + } + else if(const char* optPACKAGE_VERSION = + GetOption("CPACK_PACKAGE_VERSION")) + { + Version = optPACKAGE_VERSION; + } + else + { + Version = "1.0.0"; + } + + // Script + if (const char* option = GetOption(prefix + "SCRIPT")) + { + Script = option; + } + + // CMake dependencies + if (!component->Dependencies.empty()) + { + std::vector<cmCPackComponent*>::iterator dit; + for(dit = component->Dependencies.begin(); + dit != component->Dependencies.end(); + ++dit) + { + Dependencies.insert(Generator->ComponentPackages[*dit]); + } + } + + // QtIFW dependencies + if(const char* option = this->GetOption(prefix + "DEPENDS")) + { + std::vector<std::string> deps; + cmSystemTools::ExpandListArgument(option, + deps); + for(std::vector<std::string>::iterator + dit = deps.begin(); dit != deps.end(); ++dit) + { + DependenceStruct dep(*dit); + if (!Generator->Packages.count(dep.Name)) + { + bool hasDep = Generator->DependentPackages.count(dep.Name) > 0; + DependenceStruct &depRef = + Generator->DependentPackages[dep.Name]; + if(!hasDep) + { + depRef = dep; + } + AlienDependencies.insert(&depRef); + } + } + } + + // Licenses + if (const char* option = this->GetOption(prefix + "LICENSES")) + { + Licenses.clear(); + cmSystemTools::ExpandListArgument( option, Licenses ); + if ( Licenses.size() % 2 != 0 ) + { + cmCPackLogger(cmCPackLog::LOG_WARNING, prefix << "LICENSES" + << " should contain pairs of <display_name> and <file_path>." + << std::endl); + Licenses.clear(); + } + } + + // Priority + if(const char* option = this->GetOption(prefix + "PRIORITY")) + { + SortingPriority = option; + } + + // Default + Default = component->IsDisabledByDefault ? "false" : "true"; + + // Virtual + Virtual = component->IsHidden ? "true" : ""; + + // ForcedInstallation + ForcedInstallation = component->IsRequired ? "true" : "false"; + + return 1; +} + +//---------------------------------------------------------------------------- +int +cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup *group) +{ + if(!group) return 0; + + // Restore defaul configuration + DefaultConfiguration(); + + std::string prefix = "CPACK_IFW_COMPONENT_GROUP_" + + cmsys::SystemTools::UpperCase(group->Name) + + "_"; + + DisplayName = group->DisplayName; + Description = group->Description; + + // Version + if(const char* optVERSION = GetOption(prefix + "VERSION")) + { + Version = optVERSION; + } + else if(const char* optPACKAGE_VERSION = + GetOption("CPACK_PACKAGE_VERSION")) + { + Version = optPACKAGE_VERSION; + } + else + { + Version = "1.0.0"; + } + + // Script + if (const char* option = GetOption(prefix + "SCRIPT")) + { + Script = option; + } + + // Licenses + if (const char* option = this->GetOption(prefix + "LICENSES")) + { + Licenses.clear(); + cmSystemTools::ExpandListArgument( option, Licenses ); + if ( Licenses.size() % 2 != 0 ) + { + cmCPackLogger(cmCPackLog::LOG_WARNING, prefix << "LICENSES" + << " should contain pairs of <display_name> and <file_path>." + << std::endl); + Licenses.clear(); + } + } + + // Priority + if(const char* option = this->GetOption(prefix + "PRIORITY")) + { + SortingPriority = option; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int cmCPackIFWPackage::ConfigureFromGroup(const std::string &groupName) +{ + // Group configuration + + cmCPackComponentGroup group; + std::string prefix = "CPACK_COMPONENT_GROUP_" + + cmsys::SystemTools::UpperCase(groupName) + + "_"; + + if (const char *option = GetOption(prefix + "DISPLAY_NAME")) + { + group.DisplayName = option; + } + else + { + group.DisplayName = group.Name; + } + + if (const char* option = GetOption(prefix + "DESCRIPTION")) + { + group.Description = option; + } + group.IsBold = IsOn(prefix + "BOLD_TITLE"); + group.IsExpandedByDefault = IsOn(prefix + "EXPANDED"); + + // Package configuration + + group.Name = groupName; + + if(Generator) + { + Name = Generator->GetGroupPackageName(&group); + } + else + { + Name = group.Name; + } + + return ConfigureFromGroup(&group); +} + +//---------------------------------------------------------------------------- +void cmCPackIFWPackage::GeneratePackageFile() +{ + // Lazy directory initialization + if (Directory.empty()) + { + if(Installer) + { + Directory = Installer->Directory + "/packages/" + Name; + } + else if (Generator) + { + Directory = Generator->toplevel + "/packages/" + Name; + } + } + + // Output stream + cmGeneratedFileStream xout((Directory + "/meta/package.xml").data()); + + xout << "<?xml version=\"1.0\"?>" << std::endl; + xout << "<Package>" << std::endl; + + xout << " <DisplayName>" << DisplayName + << "</DisplayName>" << std::endl; + + xout << " <Description>" << Description + << "</Description>" << std::endl; + + xout << " <Name>" << Name << "</Name>" << std::endl; + + xout << " <Version>" << Version + << "</Version>" << std::endl; + + xout << " <ReleaseDate>"; + if(ReleaseDate.empty()) + { + xout << cmTimestamp().CurrentTime("%Y-%m-%d", true); + } + else + { + xout << ReleaseDate; + } + xout << "</ReleaseDate>" << std::endl; + + // Script (copy to meta dir) + if(!Script.empty()) + { + std::string name = cmSystemTools::GetFilenameName(Script); + std::string path = Directory + "/meta/" + name; + cmsys::SystemTools::CopyFileIfDifferent(Script.data(), path.data()); + xout << " <Script>" << name << "</Script>" << std::endl; + } + + // Dependencies + std::set<DependenceStruct> compDepSet; + for(std::set<DependenceStruct*>::iterator ait = AlienDependencies.begin(); + ait != AlienDependencies.end(); ++ait) + { + compDepSet.insert(*(*ait)); + } + for(std::set<cmCPackIFWPackage*>::iterator it = Dependencies.begin(); + it != Dependencies.end(); ++it) + { + compDepSet.insert(DependenceStruct((*it)->Name)); + } + // Write dependencies + if (!compDepSet.empty()) + { + xout << " <Dependencies>"; + std::set<DependenceStruct>::iterator it = compDepSet.begin(); + xout << it->NameWithCompare(); + ++it; + while(it != compDepSet.end()) + { + xout << "," << it->NameWithCompare(); + ++it; + } + xout << "</Dependencies>" << std::endl; + } + + // Licenses (copy to meta dir) + std::vector<std::string> licenses = Licenses; + for(size_t i = 1; i < licenses.size(); i += 2) + { + std::string name = cmSystemTools::GetFilenameName(licenses[i]); + std::string path = Directory + "/meta/" + name; + cmsys::SystemTools::CopyFileIfDifferent(licenses[i].data(), path.data()); + licenses[i] = name; + } + if(!licenses.empty()) + { + xout << " <Licenses>" << std::endl; + for(size_t i = 0; i < licenses.size(); i += 2) + { + xout << " <License " + << "name=\"" << licenses[i] << "\" " + << "file=\"" << licenses[i + 1] << "\" " + << "/>" <<std::endl; + } + xout << " </Licenses>" << std::endl; + } + + if (!ForcedInstallation.empty()) + { + xout << " <ForcedInstallation>" << ForcedInstallation + << "</ForcedInstallation>" << std::endl; + } + + if (!Virtual.empty()) + { + xout << " <Virtual>" << Virtual << "</Virtual>" << std::endl; + } + else if (!Default.empty()) + { + xout << " <Default>" << Default << "</Default>" << std::endl; + } + + // Priority + if(!SortingPriority.empty()) + { + xout << " <SortingPriority>" << SortingPriority + << "</SortingPriority>" << std::endl; + } + + xout << "</Package>" << std::endl; +} diff --git a/Source/CPack/IFW/cmCPackIFWPackage.h b/Source/CPack/IFW/cmCPackIFWPackage.h new file mode 100644 index 0000000..9fc9bd0 --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWPackage.h @@ -0,0 +1,133 @@ +/*============================================================================ + 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 cmCPackIFWPackage_h +#define cmCPackIFWPackage_h + +#include <cmStandardIncludes.h> + +class cmCPackComponent; +class cmCPackComponentGroup; +class cmCPackIFWInstaller; +class cmCPackIFWGenerator; + +/** \class cmCPackIFWPackage + * \brief A single component to be installed by CPack IFW generator + */ +class cmCPackIFWPackage +{ +public: // Types + enum CompareTypes + { + CompareNone = 0x0, + CompareEqual = 0x1, + CompareLess = 0x2, + CompareLessOrEqual = 0x3, + CompareGreater = 0x4, + CompareGreaterOrEqual = 0x5 + }; + + struct CompareStruct + { + CompareStruct(); + + unsigned int Type; + std::string Value; + }; + + struct DependenceStruct + { + DependenceStruct(); + DependenceStruct(const std::string &dependence); + + std::string Name; + CompareStruct Compare; + + std::string NameWithCompare() const; + + bool operator < (const DependenceStruct &other) const + { + return Name < other.Name; + } + }; + +public: // [Con|De]structor + + /** + * Construct package + */ + cmCPackIFWPackage(); + +public: // Configuration + + /// Human-readable name of the component + std::string DisplayName; + + /// Human-readable description of the component + std::string Description; + + /// Version number of the component + std::string Version; + + /// Date when this component version was released + std::string ReleaseDate; + + /// Domain-like identification for this component + std::string Name; + + /// File name of a script being loaded + std::string Script; + + /// List of license agreements to be accepted by the installing user + std::vector<std::string> Licenses; + + /// Priority of the component in the tree + std::string SortingPriority; + + /// Set to true to preselect the component in the installer + std::string Default; + + /// Set to true to hide the component from the installer + std::string Virtual; + + /// Determines that the package must always be installed + std::string ForcedInstallation; + +public: // Internal implementation + + const char* GetOption(const std::string& op) const; + bool IsOn(const std::string& op) const; + + std::string GetComponentName(cmCPackComponent *component); + + void DefaultConfiguration(); + + int ConfigureFromOptions(); + int ConfigureFromComponent(cmCPackComponent *component); + int ConfigureFromGroup(cmCPackComponentGroup *group); + int ConfigureFromGroup(const std::string &groupName); + + void GeneratePackageFile(); + + // Pointer to generator + cmCPackIFWGenerator* Generator; + // Pointer to installer + cmCPackIFWInstaller* Installer; + // Collection of dependencies + std::set<cmCPackIFWPackage*> Dependencies; + // Collection of unresolved dependencies + std::set<DependenceStruct*> AlienDependencies; + // Patch to package directory + std::string Directory; +}; + +#endif // cmCPackIFWPackage_h diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index a2995d1..7e00027 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -360,6 +360,29 @@ void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile() includeFile.EndElement("Property"); } } + + if(GetOption("CPACK_WIX_PROPERTY_ARPINSTALLLOCATION") == 0) + { + includeFile.BeginElement("Property"); + includeFile.AddAttribute("Id", "INSTALL_ROOT"); + includeFile.AddAttribute("Secure", "yes"); + + includeFile.BeginElement("RegistrySearch"); + includeFile.AddAttribute("Id", "FindInstallLocation"); + includeFile.AddAttribute("Root", "HKLM"); + includeFile.AddAttribute("Key", "Software\\Microsoft\\Windows\\" + "CurrentVersion\\Uninstall\\[WIX_UPGRADE_DETECTED]"); + includeFile.AddAttribute("Name", "InstallLocation"); + includeFile.AddAttribute("Type", "raw"); + includeFile.EndElement("RegistrySearch"); + includeFile.EndElement("Property"); + + includeFile.BeginElement("SetProperty"); + includeFile.AddAttribute("Id", "ARPINSTALLLOCATION"); + includeFile.AddAttribute("Value", "[INSTALL_ROOT]"); + includeFile.AddAttribute("After", "CostFinalize"); + includeFile.EndElement("SetProperty"); + } } void cmCPackWIXGenerator::CopyDefinition( @@ -824,13 +847,42 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( cmsys::Directory dir; dir.Load(topdir.c_str()); - if(dir.GetNumberOfFiles() == 2) + std::string relativeDirectoryPath = + cmSystemTools::RelativePath(toplevel.c_str(), topdir.c_str()); + + if(relativeDirectoryPath.empty()) { - std::string componentId = fileDefinitions.EmitComponentCreateFolder( - directoryId, GenerateGUID()); + relativeDirectoryPath = "."; + } + + cmInstalledFile const* directoryInstalledFile = + this->GetInstalledFile(relativeDirectoryPath); + + bool emptyDirectory = dir.GetNumberOfFiles() == 2; + bool createDirectory = false; + + if(emptyDirectory) + { + createDirectory = true; + } + if(directoryInstalledFile) + { + if(directoryInstalledFile->HasProperty("CPACK_WIX_ACL")) + { + createDirectory = true; + } + } + + if(createDirectory) + { + std::string componentId = fileDefinitions.EmitComponentCreateFolder( + directoryId, GenerateGUID(), directoryInstalledFile); featureDefinitions.EmitComponentRef(componentId); + } + if(emptyDirectory) + { return; } diff --git a/Source/CPack/WiX/cmWIXAccessControlList.cxx b/Source/CPack/WiX/cmWIXAccessControlList.cxx new file mode 100644 index 0000000..aeec968 --- /dev/null +++ b/Source/CPack/WiX/cmWIXAccessControlList.cxx @@ -0,0 +1,149 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 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 "cmWIXAccessControlList.h" + +#include <CPack/cmCPackGenerator.h> + +#include <cmSystemTools.h> + +cmWIXAccessControlList::cmWIXAccessControlList( + cmCPackLog *logger, + cmInstalledFile const& installedFile, + cmWIXSourceWriter &sourceWriter): + Logger(logger), + InstalledFile(installedFile), + SourceWriter(sourceWriter) +{ + +} + +bool cmWIXAccessControlList::Apply() +{ + std::vector<std::string> entries; + this->InstalledFile.GetPropertyAsList("CPACK_WIX_ACL", entries); + + for(size_t i = 0; i < entries.size(); ++i) + { + this->CreatePermissionElement(entries[i]); + } + + return true; +} + +void cmWIXAccessControlList::CreatePermissionElement( + std::string const& entry) +{ + std::string::size_type pos = entry.find('='); + if(pos == std::string::npos) + { + this->ReportError(entry, "Did not find mandatory '='"); + return; + } + + std::string user_and_domain = entry.substr(0, pos); + std::string permission_string = entry.substr(pos + 1); + + pos = user_and_domain.find('@'); + std::string user; + std::string domain; + if(pos != std::string::npos) + { + user = user_and_domain.substr(0, pos); + domain = user_and_domain.substr(pos + 1); + } + else + { + user = user_and_domain; + } + + std::vector<std::string> permissions = + cmSystemTools::tokenize(permission_string, ","); + + this->SourceWriter.BeginElement("Permission"); + this->SourceWriter.AddAttribute("User", user); + if(domain.size()) + { + this->SourceWriter.AddAttribute("Domain", domain); + } + for(size_t i = 0; i < permissions.size(); ++i) + { + this->EmitBooleanAttribute(entry, + cmSystemTools::TrimWhitespace(permissions[i])); + } + this->SourceWriter.EndElement("Permission"); +} + +void cmWIXAccessControlList::ReportError( + std::string const& entry, + std::string const& message) +{ + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Failed processing ACL entry '" << entry << + "': " << message << std::endl); +} + +bool cmWIXAccessControlList::IsBooleanAttribute(std::string const& name) +{ + static const char* validAttributes[] = + { + "Append", + "ChangePermission", + "CreateChild", + "CreateFile", + "CreateLink", + "CreateSubkeys", + "Delete", + "DeleteChild", + "EnumerateSubkeys", + "Execute", + "FileAllRights", + "GenericAll", + "GenericExecute", + "GenericRead", + "GenericWrite", + "Notify", + "Read", + "ReadAttributes", + "ReadExtendedAttributes", + "ReadPermission", + "SpecificRightsAll", + "Synchronize", + "TakeOwnership", + "Traverse", + "Write", + "WriteAttributes", + "WriteExtendedAttributes", + 0 + }; + + size_t i = 0; + while(validAttributes[i]) + { + if(name == validAttributes[i++]) return true; + } + + return false; +} + +void cmWIXAccessControlList::EmitBooleanAttribute( + std::string const& entry, std::string const& name) +{ + if(!this->IsBooleanAttribute(name)) + { + std::stringstream message; + message << "Unknown boolean attribute '" << name << "'"; + this->ReportError(entry, message.str()); + } + + this->SourceWriter.AddAttribute(name, "yes"); +} diff --git a/Source/CPack/WiX/cmWIXAccessControlList.h b/Source/CPack/WiX/cmWIXAccessControlList.h new file mode 100644 index 0000000..20902f7 --- /dev/null +++ b/Source/CPack/WiX/cmWIXAccessControlList.h @@ -0,0 +1,46 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 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. +============================================================================*/ + +#ifndef cmWIXAccessControlList_h +#define cmWIXAccessControlList_h + +#include <cmInstalledFile.h> +#include <CPack/cmCPackLog.h> + +#include "cmWIXSourceWriter.h" + +class cmWIXAccessControlList +{ +public: + cmWIXAccessControlList( + cmCPackLog *logger, + cmInstalledFile const& installedFile, + cmWIXSourceWriter &sourceWriter); + + bool Apply(); + +private: + void CreatePermissionElement(std::string const& entry); + + void ReportError(std::string const& entry, std::string const& message); + + bool IsBooleanAttribute(std::string const& name); + + void EmitBooleanAttribute( + std::string const& entry, std::string const& name); + + cmCPackLog* Logger; + cmInstalledFile const& InstalledFile; + cmWIXSourceWriter &SourceWriter; +}; + +#endif diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx index 451188e..1adb06a 100644 --- a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx +++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx @@ -11,6 +11,7 @@ ============================================================================*/ #include "cmWIXFilesSourceWriter.h" +#include "cmWIXAccessControlList.h" #include <cmInstalledFile.h> @@ -112,7 +113,9 @@ void cmWIXFilesSourceWriter::EmitUninstallShortcut( } std::string cmWIXFilesSourceWriter::EmitComponentCreateFolder( - std::string const& directoryId, std::string const& guid) + std::string const& directoryId, + std::string const& guid, + cmInstalledFile const* installedFile) { std::string componentId = std::string("CM_C_EMPTY_") + directoryId; @@ -126,6 +129,12 @@ std::string cmWIXFilesSourceWriter::EmitComponentCreateFolder( BeginElement("CreateFolder"); + if(installedFile) + { + cmWIXAccessControlList acl(Logger, *installedFile, *this); + acl.Apply(); + } + EndElement("CreateFolder"); EndElement("Component"); EndElement("DirectoryRef"); @@ -175,6 +184,12 @@ std::string cmWIXFilesSourceWriter::EmitComponentFile( AddAttribute("ReadOnly", "yes"); } + if(installedFile) + { + cmWIXAccessControlList acl(Logger, *installedFile, *this); + acl.Apply(); + } + patch.ApplyFragment(fileId, *this); EndElement("File"); diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.h b/Source/CPack/WiX/cmWIXFilesSourceWriter.h index 23ef561..b0a4af8 100644 --- a/Source/CPack/WiX/cmWIXFilesSourceWriter.h +++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.h @@ -47,7 +47,8 @@ public: std::string EmitComponentCreateFolder( std::string const& directoryId, - std::string const& guid); + std::string const& guid, + cmInstalledFile const* installedFile); std::string EmitComponentFile( std::string const& directoryId, diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h index 65b7240..3957d96 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.h +++ b/Source/CPack/WiX/cmWIXSourceWriter.h @@ -45,6 +45,9 @@ public: static std::string WindowsCodepageToUtf8(std::string const& value); +protected: + cmCPackLog* Logger; + private: enum State { @@ -58,8 +61,6 @@ private: static std::string EscapeAttributeValue(std::string const& value); - cmCPackLog* Logger; - cmsys::ofstream File; State State; diff --git a/Source/CPack/cmCPack7zGenerator.cxx b/Source/CPack/cmCPack7zGenerator.cxx new file mode 100644 index 0000000..ce31ad4 --- /dev/null +++ b/Source/CPack/cmCPack7zGenerator.cxx @@ -0,0 +1,25 @@ +/*============================================================================ + 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 "cmCPack7zGenerator.h" + +//---------------------------------------------------------------------- +cmCPack7zGenerator::cmCPack7zGenerator() + :cmCPackArchiveGenerator(cmArchiveWrite::CompressNone, + cmArchiveWrite::Type7Zip) +{ +} + +//---------------------------------------------------------------------- +cmCPack7zGenerator::~cmCPack7zGenerator() +{ +} diff --git a/Source/CPack/cmCPack7zGenerator.h b/Source/CPack/cmCPack7zGenerator.h new file mode 100644 index 0000000..f5a323f --- /dev/null +++ b/Source/CPack/cmCPack7zGenerator.h @@ -0,0 +1,36 @@ +/*============================================================================ + 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. +============================================================================*/ + +#ifndef cmCPack7zGenerator_h +#define cmCPack7zGenerator_h + +#include "cmCPackArchiveGenerator.h" + +/** \class cmCPack7zGenerator + * \brief A generator for 7z files + */ +class cmCPack7zGenerator : public cmCPackArchiveGenerator +{ +public: + cmCPackTypeMacro(cmCPack7zGenerator, cmCPackArchiveGenerator); + + /** + * Construct generator + */ + cmCPack7zGenerator(); + virtual ~cmCPack7zGenerator(); + +protected: + virtual const char* GetOutputExtension() { return ".7z"; } +}; + +#endif diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 91f92c5..1461bb1 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -637,8 +637,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( if ( globalGenerator->GetPreinstallTargetName() ) { globalGenerator->FindMakeProgram(this->MakefileMap); - const char* cmakeMakeProgram - = this->MakefileMap->GetDefinition("CMAKE_MAKE_PROGRAM"); + std::string cmakeMakeProgram + = this->MakefileMap->GetSafeDefinition("CMAKE_MAKE_PROGRAM"); std::vector<std::string> buildCommand; globalGenerator->GenerateBuildCommand(buildCommand, cmakeMakeProgram, installProjectName, installDirectory, @@ -1049,7 +1049,6 @@ int cmCPackGenerator::DoPackage() const char* tempPackageFileName = this->GetOption( "CPACK_TEMPORARY_PACKAGE_FILE_NAME"); - const char* packageFileName = this->GetOption("CPACK_OUTPUT_FILE_PATH"); const char* tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl); @@ -1114,7 +1113,7 @@ int cmCPackGenerator::DoPackage() std::string tmpPF(this->GetOption("CPACK_OUTPUT_FILE_PREFIX")); tempPackageFileName = it->c_str(); tmpPF += "/"+cmSystemTools::GetFilenameName(*it); - packageFileName = tmpPF.c_str(); + const char* packageFileName = tmpPF.c_str(); cmCPackLogger(cmCPackLog::LOG_DEBUG, "Copy final package(s): " << (tempPackageFileName ? tempPackageFileName : "(NULL)" ) << " to " diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index 9faf2b0..c8737f4 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -14,11 +14,14 @@ #include "cmCPackGenerator.h" #include "cmCPackTGZGenerator.h" +#include "cmCPackTXZGenerator.h" #include "cmCPackTarBZip2Generator.h" #include "cmCPackTarCompressGenerator.h" #include "cmCPackZIPGenerator.h" +#include "cmCPack7zGenerator.h" #include "cmCPackSTGZGenerator.h" #include "cmCPackNSISGenerator.h" +#include "IFW/cmCPackIFWGenerator.h" #ifdef __APPLE__ # include "cmCPackDragNDropGenerator.h" @@ -56,6 +59,11 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() this->RegisterGenerator("TGZ", "Tar GZip compression", cmCPackTGZGenerator::CreateGenerator); } + if (cmCPackTXZGenerator::CanGenerate()) + { + this->RegisterGenerator("TXZ", "Tar XZ compression", + cmCPackTXZGenerator::CreateGenerator); + } if (cmCPackSTGZGenerator::CanGenerate()) { this->RegisterGenerator("STGZ", "Self extracting Tar GZip compression", @@ -68,6 +76,11 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() this->RegisterGenerator("NSIS64", "Null Soft Installer (64-bit)", cmCPackNSISGenerator::CreateGenerator64); } + if (cmCPackIFWGenerator::CanGenerate()) + { + this->RegisterGenerator("IFW", "Qt Installer Framework", + cmCPackIFWGenerator::CreateGenerator); + } #ifdef __CYGWIN__ if (cmCPackCygwinBinaryGenerator::CanGenerate()) { @@ -86,6 +99,11 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() this->RegisterGenerator("ZIP", "ZIP file format", cmCPackZIPGenerator::CreateGenerator); } + if (cmCPack7zGenerator::CanGenerate()) + { + this->RegisterGenerator("7Z", "7-Zip file format", + cmCPack7zGenerator::CreateGenerator); + } #ifdef _WIN32 if (cmCPackWIXGenerator::CanGenerate()) { diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 0113698..a5eee6b 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -588,8 +588,8 @@ void cmCPackNSISGenerator::CreateMenuLinks( cmOStringStream& str, return; } - cmsys::RegularExpression urlRegex; - urlRegex.compile("^(mailto:|(ftps?|https?|news)://).*$"); + static cmsys::RegularExpression + urlRegex("^(mailto:|(ftps?|https?|news)://).*$"); std::vector<std::string>::iterator it; for ( it = cpackMenuLinksVector.begin(); diff --git a/Source/CPack/cmCPackTXZGenerator.cxx b/Source/CPack/cmCPackTXZGenerator.cxx new file mode 100644 index 0000000..ecfc177 --- /dev/null +++ b/Source/CPack/cmCPackTXZGenerator.cxx @@ -0,0 +1,25 @@ +/*============================================================================ + 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 "cmCPackTXZGenerator.h" + +//---------------------------------------------------------------------- +cmCPackTXZGenerator::cmCPackTXZGenerator() + :cmCPackArchiveGenerator(cmArchiveWrite::CompressXZ, + cmArchiveWrite::TypeTAR) +{ +} + +//---------------------------------------------------------------------- +cmCPackTXZGenerator::~cmCPackTXZGenerator() +{ +} diff --git a/Source/CPack/cmCPackTXZGenerator.h b/Source/CPack/cmCPackTXZGenerator.h new file mode 100644 index 0000000..bf8152f --- /dev/null +++ b/Source/CPack/cmCPackTXZGenerator.h @@ -0,0 +1,35 @@ +/*============================================================================ + 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. +============================================================================*/ + +#ifndef cmCPackTXZGenerator_h +#define cmCPackTXZGenerator_h + +#include "cmCPackArchiveGenerator.h" + +/** \class cmCPackTXZGenerator + * \brief A generator for TXZ files + * + */ +class cmCPackTXZGenerator : public cmCPackArchiveGenerator +{ +public: + cmCPackTypeMacro(cmCPackTXZGenerator, cmCPackArchiveGenerator); + /** + * Construct generator + */ + cmCPackTXZGenerator(); + virtual ~cmCPackTXZGenerator(); +protected: + virtual const char* GetOutputExtension() { return ".tar.xz"; } +}; + +#endif diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index ad37c42..c57028d 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -101,7 +101,7 @@ int cpackDefinitionArgument(const char* argument, const char* cValue, // this is CPack. int main (int argc, char const* const* argv) { - setlocale(LC_ALL, ""); + setlocale(LC_CTYPE, ""); cmsys::Encoding::CommandLineArguments args = cmsys::Encoding::CommandLineArguments::Main(argc, argv); argc = args.argc(); @@ -343,7 +343,6 @@ int main (int argc, char const* const* argv) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "CPack generator not specified" << std::endl); - parsed = 0; } else { diff --git a/Source/CTest/cmCTestBatchTestHandler.cxx b/Source/CTest/cmCTestBatchTestHandler.cxx index 934481b..7f966aa 100644 --- a/Source/CTest/cmCTestBatchTestHandler.cxx +++ b/Source/CTest/cmCTestBatchTestHandler.cxx @@ -33,8 +33,8 @@ void cmCTestBatchTestHandler::WriteBatchScript() { this->Script = this->CTest->GetBinaryDir() + "/Testing/CTestBatch.txt"; - std::fstream fout; - fout.open(this->Script.c_str(), std::ios::out); + cmsys::ofstream fout; + fout.open(this->Script.c_str()); fout << "#!/bin/sh\n"; for(TestMap::iterator i = this->Tests.begin(); i != this->Tests.end(); ++i) @@ -48,7 +48,7 @@ void cmCTestBatchTestHandler::WriteBatchScript() } //--------------------------------------------------------- -void cmCTestBatchTestHandler::WriteSrunArgs(int test, std::fstream& fout) +void cmCTestBatchTestHandler::WriteSrunArgs(int test, cmsys::ofstream& fout) { cmCTestTestHandler::cmCTestTestProperties* properties = this->Properties[test]; @@ -79,7 +79,7 @@ void cmCTestBatchTestHandler::WriteSrunArgs(int test, std::fstream& fout) } //--------------------------------------------------------- -void cmCTestBatchTestHandler::WriteTestCommand(int test, std::fstream& fout) +void cmCTestBatchTestHandler::WriteTestCommand(int test, cmsys::ofstream& fout) { std::vector<std::string> args = this->Properties[test]->Args; std::vector<std::string> processArgs; diff --git a/Source/CTest/cmCTestBatchTestHandler.h b/Source/CTest/cmCTestBatchTestHandler.h index ab0d081..e0c6e48 100644 --- a/Source/CTest/cmCTestBatchTestHandler.h +++ b/Source/CTest/cmCTestBatchTestHandler.h @@ -17,6 +17,7 @@ #include <cmCTestTestHandler.h> #include <cmCTestMultiProcessHandler.h> #include <cmCTestRunTest.h> +#include <cmsys/FStream.hxx> /** \class cmCTestBatchTestHandler * \brief run parallel ctest @@ -30,8 +31,8 @@ public: virtual void RunTests(); protected: void WriteBatchScript(); - void WriteSrunArgs(int test, std::fstream& fout); - void WriteTestCommand(int test, std::fstream& fout); + void WriteSrunArgs(int test, cmsys::ofstream& fout); + void WriteTestCommand(int test, cmsys::ofstream& fout); void SubmitBatchScript(); diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index b4818be..41db042 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -68,6 +68,12 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring, generator += this->BuildGenerator; args.push_back(generator); } + if(!this->BuildGeneratorPlatform.empty()) + { + std::string platform = "-A"; + platform += this->BuildGeneratorPlatform; + args.push_back(platform); + } if(this->BuildGeneratorToolset.size()) { std::string toolset = "-T"; @@ -246,6 +252,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) // Make the generator available for the Build call below. cm.SetGlobalGenerator(cm.CreateGlobalGenerator( this->BuildGenerator)); + cm.SetGeneratorPlatform(this->BuildGeneratorPlatform); cm.SetGeneratorToolset(this->BuildGeneratorToolset); // Load the cache to make CMAKE_MAKE_PROGRAM available. @@ -301,7 +308,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) int retVal = cm.GetGlobalGenerator()->Build( this->SourceDir, this->BinaryDir, this->BuildProject, *tarIt, - &output, this->BuildMakeProgram, + output, this->BuildMakeProgram, config, !this->BuildNoClean, false, remainingTime); @@ -490,6 +497,12 @@ int cmCTestBuildAndTestHandler::ProcessCommandLineArguments( idx++; this->BuildGenerator = allArgs[idx]; } + if(currentArg == "--build-generator-platform" && + idx < allArgs.size() - 1) + { + idx++; + this->BuildGeneratorPlatform = allArgs[idx]; + } if(currentArg == "--build-generator-toolset" && idx < allArgs.size() - 1) { diff --git a/Source/CTest/cmCTestBuildAndTestHandler.h b/Source/CTest/cmCTestBuildAndTestHandler.h index d1e9a4d..5a7b916 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.h +++ b/Source/CTest/cmCTestBuildAndTestHandler.h @@ -57,6 +57,7 @@ protected: std::string Output; std::string BuildGenerator; + std::string BuildGeneratorPlatform; std::string BuildGeneratorToolset; std::vector<std::string> BuildOptions; bool BuildTwoConfig; diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 7922c9a..2ec1365 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -605,6 +605,9 @@ void cmCTestBuildHandler::GenerateXMLLaunched(std::ostream& os) typedef std::set<std::string, FragmentCompare> Fragments; Fragments fragments(fragmentCompare); + // only report the first 50 warnings and first 50 errors + int numErrorsAllowed = this->MaxErrors; + int numWarningsAllowed = this->MaxWarnings; // Identify fragments on disk. cmsys::Directory launchDir; launchDir.Load(this->CTestLaunchDir.c_str()); @@ -612,13 +615,15 @@ void cmCTestBuildHandler::GenerateXMLLaunched(std::ostream& os) for(unsigned long i=0; i < n; ++i) { const char* fname = launchDir.GetFile(i); - if(this->IsLaunchedErrorFile(fname)) + if(this->IsLaunchedErrorFile(fname) && numErrorsAllowed) { + numErrorsAllowed--; fragments.insert(this->CTestLaunchDir + "/" + fname); ++this->TotalErrors; } - else if(this->IsLaunchedWarningFile(fname)) + else if(this->IsLaunchedWarningFile(fname) && numWarningsAllowed) { + numWarningsAllowed--; fragments.insert(this->CTestLaunchDir + "/" + fname); ++this->TotalWarnings; } diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx index 1aa8768..ef62fd3 100644 --- a/Source/CTest/cmCTestConfigureCommand.cxx +++ b/Source/CTest/cmCTestConfigureCommand.cxx @@ -118,6 +118,15 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() cmakeConfigureCommand += cmakeGeneratorName; cmakeConfigureCommand += "\""; + const char* cmakeGeneratorPlatform = + this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_PLATFORM"); + if(cmakeGeneratorPlatform && *cmakeGeneratorPlatform) + { + cmakeConfigureCommand += " \"-A"; + cmakeConfigureCommand += cmakeGeneratorPlatform; + cmakeConfigureCommand += "\""; + } + const char* cmakeGeneratorToolset = this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_TOOLSET"); if(cmakeGeneratorToolset && *cmakeGeneratorToolset) diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx index a6e39a4..c492bf0 100644 --- a/Source/CTest/cmCTestConfigureHandler.cxx +++ b/Source/CTest/cmCTestConfigureHandler.cxx @@ -77,7 +77,7 @@ int cmCTestConfigureHandler::ProcessHandler() this->StartLogFile("Configure", ofs); cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Configure with command: " << cCommand << std::endl); - res = this->CTest->RunMakeCommand(cCommand.c_str(), &output, + res = this->CTest->RunMakeCommand(cCommand.c_str(), output, &retVal, buildDirectory.c_str(), 0, ofs); diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index da27c8c..76f6584 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -14,6 +14,7 @@ #include "cmParseCoberturaCoverage.h" #include "cmParseGTMCoverage.h" #include "cmParseCacheCoverage.h" +#include "cmParseJacocoCoverage.h" #include "cmCTest.h" #include "cmake.h" #include "cmMakefile.h" @@ -415,6 +416,13 @@ int cmCTestCoverageHandler::ProcessHandler() return error; } + file_count += this->HandleJacocoCoverage(&cont); + error = cont.Error; + if ( file_count < 0 ) + { + return error; + } + std::set<std::string> uncovered = this->FindUncoveredFiles(&cont); if ( file_count == 0 ) @@ -872,6 +880,38 @@ struct cmCTestCoverageHandlerLocale }; //---------------------------------------------------------------------- +int cmCTestCoverageHandler::HandleJacocoCoverage( + cmCTestCoverageHandlerContainer* cont) +{ + cmParseJacocoCoverage cov = + cmParseJacocoCoverage(*cont, this->CTest); + cmsys::Glob g; + std::vector<std::string> files; + g.SetRecurse(true); + + std::string SourceDir + = this->CTest->GetCTestConfiguration("SourceDirectory"); + std::string coverageFile = SourceDir+ "/*jacoco.xml"; + + g.FindFiles(coverageFile); + files=g.GetFiles(); + if (files.size() > 0) + { + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Found Jacoco Files, Performing Coverage" << std::endl); + cov.LoadCoverageData(files); + } + else + { + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + " Cannot find Jacoco coverage files: " << coverageFile + << std::endl); + } + return static_cast<int>(cont->TotalCoverage.size()); +} + + +//---------------------------------------------------------------------- int cmCTestCoverageHandler::HandleGCovCoverage( cmCTestCoverageHandlerContainer* cont) { diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h index 38a3353..d0f274c 100644 --- a/Source/CTest/cmCTestCoverageHandler.h +++ b/Source/CTest/cmCTestCoverageHandler.h @@ -81,7 +81,10 @@ private: //! Handle coverage for mumps int HandleMumpsCoverage(cmCTestCoverageHandlerContainer* cont); - //! Handle coverage using Bullseye + //! Handle coverage for Jacoco + int HandleJacocoCoverage(cmCTestCoverageHandlerContainer* cont); + +//! Handle coverage using Bullseye int HandleBullseyeCoverage(cmCTestCoverageHandlerContainer* cont); int RunBullseyeSourceSummary(cmCTestCoverageHandlerContainer* cont); int RunBullseyeCoverageBranch(cmCTestCoverageHandlerContainer* cont, diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx index 535c993..f144066 100644 --- a/Source/CTest/cmCTestMemCheckCommand.cxx +++ b/Source/CTest/cmCTestMemCheckCommand.cxx @@ -21,6 +21,10 @@ cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler() = this->CTest->GetInitializedHandler("memcheck"); this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile, + "MemoryCheckType", "CTEST_MEMORYCHECK_TYPE"); + this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile, + "MemoryCheckSanitizerOptions", "CTEST_MEMORYCHECK_SANITIZER_OPTIONS"); + this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile, "MemoryCheckCommand", "CTEST_MEMORYCHECK_COMMAND"); this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile, "MemoryCheckCommandOptions", "CTEST_MEMORYCHECK_COMMAND_OPTIONS"); diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index ecaa474..4835010 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -18,6 +18,7 @@ #include <cmsys/Process.h> #include <cmsys/RegularExpression.hxx> #include <cmsys/Base64.h> +#include <cmsys/Glob.hxx> #include <cmsys/FStream.hxx> #include "cmMakefile.h" #include "cmXMLSafe.h" @@ -44,11 +45,23 @@ static CatToErrorType cmCTestMemCheckBoundsChecker[] = { {0,0} }; +static void xmlReportError(int line, const char* msg, void* data) +{ + cmCTest* ctest = (cmCTest*)data; + cmCTestLog(ctest, ERROR_MESSAGE, + "Error parsing XML in stream at line " + << line << ": " << msg << std::endl); +} + // parse the xml file containing the results of last BoundsChecker run class cmBoundsCheckerParser : public cmXMLParser { public: - cmBoundsCheckerParser(cmCTest* c) { this->CTest = c;} + cmBoundsCheckerParser(cmCTest* c) + { + this->CTest = c; + this->SetErrorCallback(xmlReportError, (void*)c); + } void StartElement(const std::string& name, const char** atts) { if(name == "MemoryLeak" || @@ -124,60 +137,7 @@ public: #define BOUNDS_CHECKER_MARKER \ "******######*****Begin BOUNDS CHECKER XML******######******" -//---------------------------------------------------------------------- -static const char* cmCTestMemCheckResultStrings[] = { - "ABR", - "ABW", - "ABWL", - "COR", - "EXU", - "FFM", - "FIM", - "FMM", - "FMR", - "FMW", - "FUM", - "IPR", - "IPW", - "MAF", - "MLK", - "MPK", - "NPR", - "ODS", - "PAR", - "PLK", - "UMC", - "UMR", - 0 -}; - -//---------------------------------------------------------------------- -static const char* cmCTestMemCheckResultLongStrings[] = { - "Threading Problem", - "ABW", - "ABWL", - "COR", - "EXU", - "FFM", - "FIM", - "Mismatched deallocation", - "FMR", - "FMW", - "FUM", - "IPR", - "IPW", - "MAF", - "Memory Leak", - "Potential Memory Leak", - "NPR", - "ODS", - "Invalid syscall param", - "PLK", - "Uninitialized Memory Conditional", - "Uninitialized Memory Read", - 0 -}; //---------------------------------------------------------------------- @@ -186,12 +146,14 @@ cmCTestMemCheckHandler::cmCTestMemCheckHandler() this->MemCheck = true; this->CustomMaximumPassedTestOutputSize = 0; this->CustomMaximumFailedTestOutputSize = 0; + this->LogWithPID = false; } //---------------------------------------------------------------------- void cmCTestMemCheckHandler::Initialize() { this->Superclass::Initialize(); + this->LogWithPID = false; this->CustomMaximumPassedTestOutputSize = 0; this->CustomMaximumFailedTestOutputSize = 0; this->MemoryTester = ""; @@ -199,12 +161,6 @@ void cmCTestMemCheckHandler::Initialize() this->MemoryTesterOptions.clear(); this->MemoryTesterStyle = UNKNOWN; this->MemoryTesterOutputFile = ""; - int cc; - for ( cc = 0; cc < NO_MEMORY_FAULT; cc ++ ) - { - this->MemoryTesterGlobalResults[cc] = 0; - } - } //---------------------------------------------------------------------- @@ -249,8 +205,8 @@ void cmCTestMemCheckHandler::GenerateTestCommand( index = stream.str(); for ( pp = 0; pp < this->MemoryTesterDynamicOptions.size(); pp ++ ) { - std::string arg = this->MemoryTesterDynamicOptions[pp]; - std::string::size_type pos = arg.find("??"); + std::string arg = this->MemoryTesterDynamicOptions[pp]; + std::string::size_type pos = arg.find("??"); if (pos != std::string::npos) { arg.replace(pos, 2, index); @@ -260,18 +216,125 @@ void cmCTestMemCheckHandler::GenerateTestCommand( memcheckcommand += arg; memcheckcommand += "\""; } + // Create a copy of the memory tester environment variable. + // This is used for memory testing programs that pass options + // via environment varaibles. + std::string memTesterEnvironmentVariable = + this->MemoryTesterEnvironmentVariable; for ( pp = 0; pp < this->MemoryTesterOptions.size(); pp ++ ) { - args.push_back(this->MemoryTesterOptions[pp]); - memcheckcommand += " \""; - memcheckcommand += this->MemoryTesterOptions[pp]; - memcheckcommand += "\""; + if(memTesterEnvironmentVariable.size()) + { + // If we are using env to pass options, append all the options to + // this string with space separation. + memTesterEnvironmentVariable += " " + this->MemoryTesterOptions[pp]; + } + // for regular options just add them to args and memcheckcommand + // which is just used for display + else + { + args.push_back(this->MemoryTesterOptions[pp]); + memcheckcommand += " \""; + memcheckcommand += this->MemoryTesterOptions[pp]; + memcheckcommand += "\""; + } + } + // if this is an env option type, then add the env string as a single + // argument. + if(memTesterEnvironmentVariable.size()) + { + std::string::size_type pos = memTesterEnvironmentVariable.find("??"); + if (pos != std::string::npos) + { + memTesterEnvironmentVariable.replace(pos, 2, index); + } + memcheckcommand += " " + memTesterEnvironmentVariable; + args.push_back(memTesterEnvironmentVariable); } cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Memory check command: " << memcheckcommand << std::endl); } //---------------------------------------------------------------------- +void cmCTestMemCheckHandler::InitializeResultsVectors() +{ + // fill these members +// cmsys::vector<std::string> ResultStrings; +// cmsys::vector<std::string> ResultStringsLong; +// cmsys::vector<int> GlobalResults; + this->ResultStringsLong.clear(); + this->ResultStrings.clear(); + this->GlobalResults.clear(); + // If we are working with style checkers that dynamically fill + // the results strings then return. + if(this->MemoryTesterStyle > cmCTestMemCheckHandler::BOUNDS_CHECKER) + { + return; + } + + // define the standard set of errors + //---------------------------------------------------------------------- + static const char* cmCTestMemCheckResultStrings[] = { + "ABR", + "ABW", + "ABWL", + "COR", + "EXU", + "FFM", + "FIM", + "FMM", + "FMR", + "FMW", + "FUM", + "IPR", + "IPW", + "MAF", + "MLK", + "MPK", + "NPR", + "ODS", + "PAR", + "PLK", + "UMC", + "UMR", + 0 + }; +//---------------------------------------------------------------------- + static const char* cmCTestMemCheckResultLongStrings[] = { + "Threading Problem", + "ABW", + "ABWL", + "COR", + "EXU", + "FFM", + "FIM", + "Mismatched deallocation", + "FMR", + "FMW", + "FUM", + "IPR", + "IPW", + "MAF", + "Memory Leak", + "Potential Memory Leak", + "NPR", + "ODS", + "Invalid syscall param", + "PLK", + "Uninitialized Memory Conditional", + "Uninitialized Memory Read", + 0 + }; + this->GlobalResults.clear(); + for(int i =0; cmCTestMemCheckResultStrings[i] != 0; ++i) + { + this->ResultStrings.push_back(cmCTestMemCheckResultStrings[i]); + this->ResultStringsLong.push_back(cmCTestMemCheckResultLongStrings[i]); + this->GlobalResults.push_back(0); + } +} + +//---------------------------------------------------------------------- void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile *mf) { this->cmCTestTestHandler::PopulateCustomVectors(mf); @@ -283,6 +346,8 @@ void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile *mf) this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_MEMCHECK_IGNORE", this->CustomTestsIgnore); + std::string cmake = cmSystemTools::GetCMakeCommand(); + this->CTest->SetCTestConfiguration("CMakeCommand", cmake.c_str()); } //---------------------------------------------------------------------- @@ -292,7 +357,6 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os) { return; } - this->CTest->StartXML(os, this->AppendXML); os << "<DynamicAnalysis Checker=\""; switch ( this->MemoryTesterStyle ) @@ -306,6 +370,18 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os) case cmCTestMemCheckHandler::BOUNDS_CHECKER: os << "BoundsChecker"; break; + case cmCTestMemCheckHandler::ADDRESS_SANITIZER: + os << "AddressSanitizer"; + break; + case cmCTestMemCheckHandler::THREAD_SANITIZER: + os << "ThreadSanitizer"; + break; + case cmCTestMemCheckHandler::MEMORY_SANITIZER: + os << "MemorySanitizer"; + break; + case cmCTestMemCheckHandler::UB_SANITIZER: + os << "UndefinedBehaviorSanitizer"; + break; default: os << "Unknown"; } @@ -333,8 +409,7 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os) { cmCTestTestResult *result = &this->TestResults[cc]; std::string memcheckstr; - int memcheckresults[cmCTestMemCheckHandler::NO_MEMORY_FAULT]; - int kk; + std::vector<int> memcheckresults(this->ResultStrings.size(), 0); bool res = this->ProcessMemCheckOutput(result->Output, memcheckstr, memcheckresults); if ( res && result->Status == cmCTestMemCheckHandler::COMPLETED ) @@ -345,16 +420,17 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os) static_cast<size_t>(this->CustomMaximumFailedTestOutputSize)); this->WriteTestResultHeader(os, result); os << "\t\t<Results>" << std::endl; - for ( kk = 0; cmCTestMemCheckResultLongStrings[kk]; kk ++ ) + for(std::vector<int>::size_type kk = 0; + kk < memcheckresults.size(); ++kk) { if ( memcheckresults[kk] ) { - os << "\t\t\t<Defect type=\"" << cmCTestMemCheckResultLongStrings[kk] + os << "\t\t\t<Defect type=\"" << this->ResultStringsLong[kk] << "\">" << memcheckresults[kk] << "</Defect>" << std::endl; } - this->MemoryTesterGlobalResults[kk] += memcheckresults[kk]; + this->GlobalResults[kk] += memcheckresults[kk]; } std::string logTag; @@ -383,9 +459,9 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os) cmCTestLog(this->CTest, HANDLER_OUTPUT, "Memory checking results:" << std::endl); os << "\t<DefectList>" << std::endl; - for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ ) + for ( cc = 0; cc < this->GlobalResults.size(); cc ++ ) { - if ( this->MemoryTesterGlobalResults[cc] ) + if ( this->GlobalResults[cc] ) { #ifdef cerr # undef cerr @@ -393,9 +469,9 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os) std::cerr.width(35); #define cerr no_cerr cmCTestLog(this->CTest, HANDLER_OUTPUT, - cmCTestMemCheckResultLongStrings[cc] << " - " - << this->MemoryTesterGlobalResults[cc] << std::endl); - os << "\t\t<Defect Type=\"" << cmCTestMemCheckResultLongStrings[cc] + this->ResultStringsLong[cc] << " - " + << this->GlobalResults[cc] << std::endl); + os << "\t\t<Defect Type=\"" << this->ResultStringsLong[cc] << "\"/>" << std::endl; } } @@ -410,30 +486,33 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os) os << "</DynamicAnalysis>" << std::endl; this->CTest->EndXML(os); - - } //---------------------------------------------------------------------- bool cmCTestMemCheckHandler::InitializeMemoryChecking() { + this->MemoryTesterEnvironmentVariable = ""; + this->MemoryTester = ""; // Setup the command if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration( "MemoryCheckCommand").c_str()) ) { this->MemoryTester = this->CTest->GetCTestConfiguration("MemoryCheckCommand").c_str(); - + std::string testerName = + cmSystemTools::GetFilenameName(this->MemoryTester); // determine the checker type - if ( this->MemoryTester.find("valgrind") != std::string::npos ) + if ( testerName.find("valgrind") != std::string::npos || + this->CTest->GetCTestConfiguration("MemoryCheckType") + == "Valgrind") { this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND; } - else if ( this->MemoryTester.find("purify") != std::string::npos ) + else if ( testerName.find("purify") != std::string::npos ) { this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY; } - else if ( this->MemoryTester.find("BC") != std::string::npos ) + else if ( testerName.find("BC") != std::string::npos ) { this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER; } @@ -463,12 +542,62 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() = this->CTest->GetCTestConfiguration("BoundsCheckerCommand").c_str(); this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER; } - else + if ( this->CTest->GetCTestConfiguration("MemoryCheckType") + == "AddressSanitizer") + { + this->MemoryTester + = this->CTest->GetCTestConfiguration("CMakeCommand").c_str(); + this->MemoryTesterStyle = cmCTestMemCheckHandler::ADDRESS_SANITIZER; + this->LogWithPID = true; // even if we give the log file the pid is added + } + if ( this->CTest->GetCTestConfiguration("MemoryCheckType") + == "ThreadSanitizer") + { + this->MemoryTester + = this->CTest->GetCTestConfiguration("CMakeCommand").c_str(); + this->MemoryTesterStyle = cmCTestMemCheckHandler::THREAD_SANITIZER; + this->LogWithPID = true; // even if we give the log file the pid is added + } + if ( this->CTest->GetCTestConfiguration("MemoryCheckType") + == "MemorySanitizer") + { + this->MemoryTester + = this->CTest->GetCTestConfiguration("CMakeCommand").c_str(); + this->MemoryTesterStyle = cmCTestMemCheckHandler::MEMORY_SANITIZER; + this->LogWithPID = true; // even if we give the log file the pid is added + } + if ( this->CTest->GetCTestConfiguration("MemoryCheckType") + == "UndefinedBehaviorSanitizer") + { + this->MemoryTester + = this->CTest->GetCTestConfiguration("CMakeCommand").c_str(); + this->MemoryTesterStyle = cmCTestMemCheckHandler::UB_SANITIZER; + this->LogWithPID = true; // even if we give the log file the pid is added + } + // Check the MemoryCheckType + if(this->MemoryTesterStyle == cmCTestMemCheckHandler::UNKNOWN) + { + std::string checkType = + this->CTest->GetCTestConfiguration("MemoryCheckType"); + if(checkType == "Purify") + { + this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY; + } + else if(checkType == "BoundsChecker") + { + this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER; + } + else if(checkType == "Valgrind") + { + this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND; + } + } + if(this->MemoryTester.size() == 0 ) { cmCTestLog(this->CTest, WARNING, - "Memory checker (MemoryCheckCommand) " - "not set, or cannot find the specified program." - << std::endl); + "Memory checker (MemoryCheckCommand) " + "not set, or cannot find the specified program." + << std::endl); return false; } @@ -567,6 +696,46 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTesterOptions.push_back("/M"); break; } + // these are almost the same but the env var used is different + case cmCTestMemCheckHandler::ADDRESS_SANITIZER: + case cmCTestMemCheckHandler::THREAD_SANITIZER: + case cmCTestMemCheckHandler::MEMORY_SANITIZER: + case cmCTestMemCheckHandler::UB_SANITIZER: + { + // To pass arguments to ThreadSanitizer the environment variable + // TSAN_OPTIONS is used. This is done with the cmake -E env command. + // The MemoryTesterDynamicOptions is setup with the -E env + // Then the MemoryTesterEnvironmentVariable gets the + // TSAN_OPTIONS string with the log_path in it. + this->MemoryTesterDynamicOptions.push_back("-E"); + this->MemoryTesterDynamicOptions.push_back("env"); + std::string envVar; + std::string extraOptions = + this->CTest->GetCTestConfiguration("MemoryCheckSanitizerOptions"); + if(this->MemoryTesterStyle == cmCTestMemCheckHandler::ADDRESS_SANITIZER) + { + envVar = "ASAN_OPTIONS"; + extraOptions += " detect_leaks=1"; + } + else if(this->MemoryTesterStyle == + cmCTestMemCheckHandler::THREAD_SANITIZER) + { + envVar = "TSAN_OPTIONS"; + } + else if(this->MemoryTesterStyle == + cmCTestMemCheckHandler::MEMORY_SANITIZER) + { + envVar = "MSAN_OPTIONS"; + } + else if(this->MemoryTesterStyle == cmCTestMemCheckHandler::UB_SANITIZER) + { + envVar = "UBSAN_OPTIONS"; + } + std::string outputFile = envVar + "=log_path=\"" + + this->MemoryTesterOutputFile + "\" "; + this->MemoryTesterEnvironmentVariable = outputFile + extraOptions; + break; + } default: cmCTestLog(this->CTest, ERROR_MESSAGE, "Do not understand memory checker: " << this->MemoryTester @@ -574,24 +743,20 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() return false; } - std::vector<std::string>::size_type cc; - for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ ) - { - this->MemoryTesterGlobalResults[cc] = 0; - } + this->InitializeResultsVectors(); + // std::vector<std::string>::size_type cc; + // for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ ) + // { + // this->MemoryTesterGlobalResults[cc] = 0; + // } return true; } //---------------------------------------------------------------------- -bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str, - std::string& log, int* results) +bool cmCTestMemCheckHandler:: +ProcessMemCheckOutput(const std::string& str, + std::string& log, std::vector<int>& results) { - std::string::size_type cc; - for ( cc = 0; cc < cmCTestMemCheckHandler::NO_MEMORY_FAULT; cc ++ ) - { - results[cc] = 0; - } - if ( this->MemoryTesterStyle == cmCTestMemCheckHandler::VALGRIND ) { return this->ProcessMemCheckValgrindOutput(str, log, results); @@ -601,6 +766,17 @@ bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str, return this->ProcessMemCheckPurifyOutput(str, log, results); } else if ( this->MemoryTesterStyle == + cmCTestMemCheckHandler::ADDRESS_SANITIZER || + this->MemoryTesterStyle == + cmCTestMemCheckHandler::THREAD_SANITIZER || + this->MemoryTesterStyle == + cmCTestMemCheckHandler::MEMORY_SANITIZER || + this->MemoryTesterStyle == + cmCTestMemCheckHandler::UB_SANITIZER) + { + return this->ProcessMemCheckSanitizerOutput(str, log, results); + } + else if ( this->MemoryTesterStyle == cmCTestMemCheckHandler::BOUNDS_CHECKER ) { return this->ProcessMemCheckBoundsCheckerOutput(str, log, results); @@ -611,15 +787,94 @@ bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str, log.append("None that I know"); log = str; } - - return true; } +std::vector<int>::size_type cmCTestMemCheckHandler::FindOrAddWarning( + const std::string& warning) +{ + for(std::vector<std::string>::size_type i =0; + i < this->ResultStrings.size(); ++i) + { + if(this->ResultStrings[i] == warning) + { + return i; + } + } + this->GlobalResults.push_back(0); // this must stay the same size + this->ResultStrings.push_back(warning); + this->ResultStringsLong.push_back(warning); + return this->ResultStrings.size()-1; +} +//---------------------------------------------------------------------- +bool cmCTestMemCheckHandler::ProcessMemCheckSanitizerOutput( + const std::string& str, std::string& log, + std::vector<int>& result) +{ + std::string regex; + switch ( this->MemoryTesterStyle ) + { + case cmCTestMemCheckHandler::ADDRESS_SANITIZER: + regex = "ERROR: AddressSanitizer: (.*) on.*"; + break; + case cmCTestMemCheckHandler::THREAD_SANITIZER: + regex = "WARNING: ThreadSanitizer: (.*) \\(pid=.*\\)"; + break; + case cmCTestMemCheckHandler::MEMORY_SANITIZER: + regex = "WARNING: MemorySanitizer: (.*)"; + break; + case cmCTestMemCheckHandler::UB_SANITIZER: + regex = "runtime error: (.*)"; + break; + default: + break; + } + cmsys::RegularExpression sanitizerWarning(regex); + cmsys::RegularExpression leakWarning("(Direct|Indirect) leak of .*"); + int defects = 0; + std::vector<std::string> lines; + cmSystemTools::Split(str.c_str(), lines); + cmOStringStream ostr; + log = ""; + for( std::vector<std::string>::iterator i = lines.begin(); + i != lines.end(); ++i) + { + std::string resultFound; + if(leakWarning.find(*i)) + { + resultFound = leakWarning.match(1)+" leak"; + } + else if (sanitizerWarning.find(*i)) + { + resultFound = sanitizerWarning.match(1); + } + if(resultFound.size()) + { + std::vector<int>::size_type idx = this->FindOrAddWarning(resultFound); + if(result.size() == 0 || idx > result.size()-1) + { + result.push_back(1); + } + else + { + result[idx]++; + } + defects++; + ostr << "<b>" << this->ResultStrings[idx] << "</b> "; + } + ostr << cmXMLSafe(*i) << std::endl; + } + log = ostr.str(); + if(defects) + { + return false; + } + return true; +} //---------------------------------------------------------------------- bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput( const std::string& str, std::string& log, - int* results) + std::vector<int>& results) { std::vector<std::string> lines; cmSystemTools::Split(str.c_str(), lines); @@ -633,19 +888,19 @@ bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput( for( std::vector<std::string>::iterator i = lines.begin(); i != lines.end(); ++i) { - int failure = cmCTestMemCheckHandler::NO_MEMORY_FAULT; + std::vector<int>::size_type failure = this->ResultStrings.size(); if ( pfW.find(*i) ) { - int cc; - for ( cc = 0; cc < cmCTestMemCheckHandler::NO_MEMORY_FAULT; cc ++ ) + std::vector<int>::size_type cc; + for ( cc = 0; cc < this->ResultStrings.size(); cc ++ ) { - if ( pfW.match(1) == cmCTestMemCheckResultStrings[cc] ) + if ( pfW.match(1) == this->ResultStrings[cc] ) { failure = cc; break; } } - if ( cc == cmCTestMemCheckHandler::NO_MEMORY_FAULT ) + if ( cc == this->ResultStrings.size() ) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown Purify memory fault: " << pfW.match(1) << std::endl); @@ -653,9 +908,9 @@ bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput( << std::endl; } } - if ( failure != NO_MEMORY_FAULT ) + if ( failure != this->ResultStrings.size() ) { - ostr << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> "; + ostr << "<b>" << this->ResultStrings[failure] << "</b> "; results[failure] ++; defects ++; } @@ -673,7 +928,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput( //---------------------------------------------------------------------- bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( const std::string& str, std::string& log, - int* results) + std::vector<int>& results) { std::vector<std::string> lines; cmSystemTools::Split(str.c_str(), lines); @@ -728,7 +983,6 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( double sttime = cmSystemTools::GetTime(); cmCTestLog(this->CTest, DEBUG, "Start test: " << lines.size() << std::endl); std::string::size_type totalOutputSize = 0; - bool outputFull = false; for ( cc = 0; cc < lines.size(); cc ++ ) { cmCTestLog(this->CTest, DEBUG, "test line " @@ -802,7 +1056,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( if ( failure != cmCTestMemCheckHandler::NO_MEMORY_FAULT ) { - ostr << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> "; + ostr << "<b>" << this->ResultStrings[failure] << "</b> "; results[failure] ++; defects ++; } @@ -815,32 +1069,30 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( } } // Now put all all the non valgrind output into the test output - if(!outputFull) + // This should be last in case it gets truncated by the output + // limiting code + for(std::vector<std::string::size_type>::iterator i = + nonValGrindOutput.begin(); i != nonValGrindOutput.end(); ++i) { - for(std::vector<std::string::size_type>::iterator i = - nonValGrindOutput.begin(); i != nonValGrindOutput.end(); ++i) + totalOutputSize += lines[*i].size(); + cmCTestLog(this->CTest, DEBUG, "before xml safe " + << lines[*i] << std::endl); + cmCTestLog(this->CTest, DEBUG, "after xml safe " + << cmXMLSafe(lines[*i]) << std::endl); + ostr << cmXMLSafe(lines[*i]) << std::endl; + if(!unlimitedOutput && totalOutputSize > + static_cast<size_t>(this->CustomMaximumFailedTestOutputSize)) { - totalOutputSize += lines[*i].size(); - cmCTestLog(this->CTest, DEBUG, "before xml safe " - << lines[*i] << std::endl); - cmCTestLog(this->CTest, DEBUG, "after xml safe " - << cmXMLSafe(lines[*i]) << std::endl); - - ostr << cmXMLSafe(lines[*i]) << std::endl; - if(!unlimitedOutput && totalOutputSize > - static_cast<size_t>(this->CustomMaximumFailedTestOutputSize)) - { - outputFull = true; - ostr << "....\n"; - ostr << "Test Output for this test has been truncated see testing" - " machine logs for full output,\n"; - ostr << "or put CTEST_FULL_OUTPUT in the output of " - "this test program.\n"; - } + ostr << "....\n"; + ostr << "Test Output for this test has been truncated see testing" + " machine logs for full output,\n"; + ostr << "or put CTEST_FULL_OUTPUT in the output of " + "this test program.\n"; + break; // stop the copy of output if we are full } } cmCTestLog(this->CTest, DEBUG, "End test (elapsed: " - << (cmSystemTools::GetTime() - sttime) << std::endl); + << (cmSystemTools::GetTime() - sttime) << std::endl); log = ostr.str(); if ( defects ) { @@ -854,7 +1106,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( //---------------------------------------------------------------------- bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput( const std::string& str, std::string& log, - int* results) + std::vector<int>& results) { log = ""; double sttime = cmSystemTools::GetTime(); @@ -908,6 +1160,32 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput( return true; } +// PostProcessTest memcheck results +void +cmCTestMemCheckHandler::PostProcessTest(cmCTestTestResult& res, + int test) +{ + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "PostProcessTest memcheck results for : " + << res.Name << std::endl); + if(this->MemoryTesterStyle + == cmCTestMemCheckHandler::BOUNDS_CHECKER) + { + this->PostProcessBoundsCheckerTest(res, test); + } + else + { + std::vector<std::string> files; + this->TestOutputFileNames(test, files); + for(std::vector<std::string>::iterator i = files.begin(); + i != files.end(); ++i) + { + this->AppendMemTesterOutput(res, *i); + } + } +} + + // This method puts the bounds checker output file into the output // for the test void @@ -917,11 +1195,13 @@ cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res, cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "PostProcessBoundsCheckerTest for : " << res.Name << std::endl); - std::string ofile = testOutputFileName(test); - if ( ofile.empty() ) + std::vector<std::string> files; + this->TestOutputFileNames(test, files); + if ( files.size() == 0 ) { return; } + std::string ofile = files[0]; // put a scope around this to close ifs so the file can be removed { cmsys::ifstream ifs(ofile.c_str()); @@ -950,35 +1230,15 @@ cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res, } void -cmCTestMemCheckHandler::PostProcessPurifyTest(cmCTestTestResult& res, - int test) +cmCTestMemCheckHandler::AppendMemTesterOutput(cmCTestTestResult& res, + std::string const& ofile) { - cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - "PostProcessPurifyTest for : " - << res.Name << std::endl); - appendMemTesterOutput(res, test); -} - -void -cmCTestMemCheckHandler::PostProcessValgrindTest(cmCTestTestResult& res, - int test) -{ - cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - "PostProcessValgrindTest for : " - << res.Name << std::endl); - appendMemTesterOutput(res, test); -} - -void -cmCTestMemCheckHandler::appendMemTesterOutput(cmCTestTestResult& res, - int test) -{ - std::string ofile = testOutputFileName(test); - if ( ofile.empty() ) { return; } + // put ifs in scope so file can be deleted if needed + { cmsys::ifstream ifs(ofile.c_str()); if ( !ifs ) { @@ -992,10 +1252,17 @@ cmCTestMemCheckHandler::appendMemTesterOutput(cmCTestTestResult& res, res.Output += line; res.Output += "\n"; } + } + if(this->LogWithPID) + { + cmSystemTools::RemoveFile(ofile.c_str()); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Remove: "<< ofile <<"\n"); + } } -std::string -cmCTestMemCheckHandler::testOutputFileName(int test) +void cmCTestMemCheckHandler::TestOutputFileNames(int test, + std::vector<std::string>& + files) { std::string index; cmOStringStream stream; @@ -1004,14 +1271,30 @@ cmCTestMemCheckHandler::testOutputFileName(int test) std::string ofile = this->MemoryTesterOutputFile; std::string::size_type pos = ofile.find("??"); ofile.replace(pos, 2, index); - - if ( !cmSystemTools::FileExists(ofile.c_str()) ) + if(this->LogWithPID) + { + ofile += ".*"; + cmsys::Glob g; + g.FindFiles(ofile); + if(g.GetFiles().size() == 0) + { + std::string log = "Cannot find memory tester output file: " + + ofile; + cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl); + ofile = ""; + } + else + { + files = g.GetFiles(); + return; + } + } + else if ( !cmSystemTools::FileExists(ofile.c_str()) ) { std::string log = "Cannot find memory tester output file: " + ofile; cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl); ofile = ""; } - - return ofile; + files.push_back(ofile); } diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index 0521a48..69fdd9f 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -15,7 +15,10 @@ #include "cmCTestTestHandler.h" +#include "cmStandardIncludes.h" #include "cmListFileCache.h" +#include <vector> +#include <string> class cmMakefile; @@ -45,7 +48,12 @@ private: UNKNOWN = 0, VALGRIND, PURIFY, - BOUNDS_CHECKER + BOUNDS_CHECKER, + // checkers after here do not use the standard error list + ADDRESS_SANITIZER, + THREAD_SANITIZER, + MEMORY_SANITIZER, + UB_SANITIZER }; public: enum { // Memory faults @@ -93,7 +101,17 @@ private: std::vector<std::string> MemoryTesterOptions; int MemoryTesterStyle; std::string MemoryTesterOutputFile; - int MemoryTesterGlobalResults[NO_MEMORY_FAULT]; + std::string MemoryTesterEnvironmentVariable; + // these are used to store the types of errors that can show up + std::vector<std::string> ResultStrings; + std::vector<std::string> ResultStringsLong; + std::vector<int> GlobalResults; + bool LogWithPID; // does log file add pid + + std::vector<int>::size_type FindOrAddWarning(const std::string& warning); + // initialize the ResultStrings and ResultStringsLong for + // this type of checker + void InitializeResultsVectors(); ///! Initialize memory checking subsystem. bool InitializeMemoryChecking(); @@ -110,24 +128,29 @@ private: //string. After running, log holds the output and results hold the //different memmory errors. bool ProcessMemCheckOutput(const std::string& str, - std::string& log, int* results); + std::string& log, std::vector<int>& results); bool ProcessMemCheckValgrindOutput(const std::string& str, - std::string& log, int* results); + std::string& log, + std::vector<int>& results); bool ProcessMemCheckPurifyOutput(const std::string& str, - std::string& log, int* results); + std::string& log, + std::vector<int>& results); + bool ProcessMemCheckSanitizerOutput(const std::string& str, + std::string& log, + std::vector<int>& results); bool ProcessMemCheckBoundsCheckerOutput(const std::string& str, - std::string& log, int* results); + std::string& log, + std::vector<int>& results); - void PostProcessPurifyTest(cmCTestTestResult& res, int test); + void PostProcessTest(cmCTestTestResult& res, int test); void PostProcessBoundsCheckerTest(cmCTestTestResult& res, int test); - void PostProcessValgrindTest(cmCTestTestResult& res, int test); ///! append MemoryTesterOutputFile to the test log - void appendMemTesterOutput(cmCTestTestHandler::cmCTestTestResult& res, - int test); + void AppendMemTesterOutput(cmCTestTestHandler::cmCTestTestResult& res, + std::string const& filename); ///! generate the output filename for the given test index - std::string testOutputFileName(int test); + void TestOutputFileNames(int test, std::vector<std::string>& files); }; #endif diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index b9e6721..7ba434c 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -319,8 +319,8 @@ void cmCTestMultiProcessHandler::UpdateCostData() { std::string fname = this->CTest->GetCostDataFile(); std::string tmpout = fname + ".tmp"; - std::fstream fout; - fout.open(tmpout.c_str(), std::ios::out); + cmsys::ofstream fout; + fout.open(tmpout.c_str()); PropertiesMap temp = this->Properties; @@ -610,8 +610,8 @@ void cmCTestMultiProcessHandler::WriteCheckpoint(int index) { std::string fname = this->CTest->GetBinaryDir() + "/Testing/Temporary/CTestCheckpoint.txt"; - std::fstream fout; - fout.open(fname.c_str(), std::ios::app | std::ios::out); + cmsys::ofstream fout; + fout.open(fname.c_str(), std::ios::app); fout << index << "\n"; fout.close(); } diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 385388d..bdd8c02 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -392,20 +392,7 @@ void cmCTestRunTest::MemCheckPostProcess() << this->TestResult.Name << std::endl); cmCTestMemCheckHandler * handler = static_cast<cmCTestMemCheckHandler*> (this->TestHandler); - switch ( handler->MemoryTesterStyle ) - { - case cmCTestMemCheckHandler::VALGRIND: - handler->PostProcessValgrindTest(this->TestResult, this->Index); - break; - case cmCTestMemCheckHandler::PURIFY: - handler->PostProcessPurifyTest(this->TestResult, this->Index); - break; - case cmCTestMemCheckHandler::BOUNDS_CHECKER: - handler->PostProcessBoundsCheckerTest(this->TestResult, this->Index); - break; - default: - break; - } + handler->PostProcessTest(this->TestResult, this->Index); } //---------------------------------------------------------------------- diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 567acfc..f050148 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -317,6 +317,15 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg) return retVal; } +static void ctestScriptProgressCallback(const char *m, float, void* cd) +{ + cmCTest* ctest = static_cast<cmCTest*>(cd); + if(m && *m) + { + cmCTestLog(ctest, HANDLER_OUTPUT, "-- " << m << std::endl); + } +} + void cmCTestScriptHandler::CreateCMake() { // create a cmake instance to read the configuration script @@ -334,6 +343,8 @@ void cmCTestScriptHandler::CreateCMake() this->LocalGenerator = this->GlobalGenerator->CreateLocalGenerator(); this->Makefile = this->LocalGenerator->GetMakefile(); + this->CMake->SetProgressCallback(ctestScriptProgressCallback, this->CTest); + // Set CMAKE_CURRENT_SOURCE_DIR and CMAKE_CURRENT_BINARY_DIR. // Also, some commands need Makefile->GetCurrentDirectory(). std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 7c72cba..06fcb75 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -225,8 +225,8 @@ bool cmCTestSubmitHandler::SubmitUsingFTP(const std::string& localprefix, std::string upload_as = url + "/" + remoteprefix + cmSystemTools::GetFilenameName(*file); - struct stat st; - if ( ::stat(local_file.c_str(), &st) ) + + if ( !cmSystemTools::FileExists(local_file.c_str()) ) { cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: " << local_file << std::endl); @@ -234,6 +234,7 @@ bool cmCTestSubmitHandler::SubmitUsingFTP(const std::string& localprefix, ::curl_global_cleanup(); return false; } + unsigned long filelen = cmSystemTools::FileLength(local_file.c_str()); ftpfile = cmsys::SystemTools::Fopen(local_file.c_str(), "rb"); *this->LogFile << "\tUpload file: " << local_file << " to " @@ -252,7 +253,7 @@ bool cmCTestSubmitHandler::SubmitUsingFTP(const std::string& localprefix, // and give the size of the upload (optional) ::curl_easy_setopt(curl, CURLOPT_INFILESIZE, - static_cast<long>(st.st_size)); + static_cast<long>(filelen)); // and give curl the buffer for errors ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer); @@ -466,8 +467,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, upload_as += md5; } - struct stat st; - if ( ::stat(local_file.c_str(), &st) ) + if( !cmSystemTools::FileExists(local_file.c_str()) ) { cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: " << local_file << std::endl); @@ -475,11 +475,12 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, ::curl_global_cleanup(); return false; } + unsigned long filelen = cmSystemTools::FileLength(local_file.c_str()); ftpfile = cmsys::SystemTools::Fopen(local_file.c_str(), "rb"); cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Upload file: " << local_file << " to " - << upload_as << " Size: " << st.st_size << std::endl); + << upload_as << " Size: " << filelen << std::endl); // specify target ::curl_easy_setopt(curl,CURLOPT_URL, upload_as.c_str()); @@ -489,7 +490,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, // and give the size of the upload (optional) ::curl_easy_setopt(curl, CURLOPT_INFILESIZE, - static_cast<long>(st.st_size)); + static_cast<long>(filelen)); // and give curl the buffer for errors ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer); @@ -1478,8 +1479,10 @@ int cmCTestSubmitHandler::ProcessHandler() //---------------------------------------------------------------------------- std::string cmCTestSubmitHandler::GetSubmitResultsPrefix() { + std::string buildname = cmCTest::SafeBuildIdField( + this->CTest->GetCTestConfiguration("BuildName")); std::string name = this->CTest->GetCTestConfiguration("Site") + - "___" + this->CTest->GetCTestConfiguration("BuildName") + + "___" + buildname + "___" + this->CTest->GetCurrentTag() + "-" + this->CTest->GetTestModelString() + "___XML___"; return name; diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx index 5408a8a..f87466d 100644 --- a/Source/CTest/cmCTestUpdateCommand.cxx +++ b/Source/CTest/cmCTestUpdateCommand.cxx @@ -56,6 +56,8 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler() this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile, "GITUpdateCustom", "CTEST_GIT_UPDATE_CUSTOM"); this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile, + "UpdateVersionOnly", "CTEST_UPDATE_VERSION_ONLY"); + this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile, "HGCommand", "CTEST_HG_COMMAND"); this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile, "HGUpdateOptions", "CTEST_HG_UPDATE_OPTIONS"); diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index fda61ea..68f5fe1 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -258,12 +258,13 @@ int cmCTestUpdateHandler::ProcessHandler() double elapsed_time_start = cmSystemTools::GetTime(); bool updated = vc->Update(); - + std::string buildname = cmCTest::SafeBuildIdField( + this->CTest->GetCTestConfiguration("BuildName")); os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" << "<Update mode=\"Client\" Generator=\"ctest-" << cmVersion::GetCMakeVersion() << "\">\n" << "\t<Site>" << this->CTest->GetCTestConfiguration("Site") << "</Site>\n" - << "\t<BuildName>" << this->CTest->GetCTestConfiguration("BuildName") + << "\t<BuildName>" << buildname << "</BuildName>\n" << "\t<BuildStamp>" << this->CTest->GetCurrentTag() << "-" << this->CTest->GetTestModelString() << "</BuildStamp>" << std::endl; diff --git a/Source/CTest/cmCTestUploadHandler.cxx b/Source/CTest/cmCTestUploadHandler.cxx index 4c3f81b..e33c387 100644 --- a/Source/CTest/cmCTestUploadHandler.cxx +++ b/Source/CTest/cmCTestUploadHandler.cxx @@ -44,14 +44,15 @@ int cmCTestUploadHandler::ProcessHandler() "Cannot open Upload.xml file" << std::endl); return -1; } - + std::string buildname = cmCTest::SafeBuildIdField( + this->CTest->GetCTestConfiguration("BuildName")); 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") + << buildname << "\" BuildStamp=\"" << this->CTest->GetCurrentTag() << "-" << this->CTest->GetTestModelString() << "\" Name=\"" diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index f89fa2b..15f796f 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -166,10 +166,17 @@ void cmCTestVC::CleanupImpl() //---------------------------------------------------------------------------- bool cmCTestVC::Update() { - this->NoteOldRevision(); - this->Log << "--- Begin Update ---\n"; - bool result = this->UpdateImpl(); - this->Log << "--- End Update ---\n"; + bool result = true; + // if update version only is on then do not actually update, + // just note the current version and finish + if(!cmSystemTools::IsOn( + this->CTest->GetCTestConfiguration("UpdateVersionOnly").c_str())) + { + this->NoteOldRevision(); + this->Log << "--- Begin Update ---\n"; + result = this->UpdateImpl(); + this->Log << "--- End Update ---\n"; + } this->NoteNewRevision(); return result; } diff --git a/Source/CTest/cmParseCoberturaCoverage.cxx b/Source/CTest/cmParseCoberturaCoverage.cxx index 6b98056..0742be1 100644 --- a/Source/CTest/cmParseCoberturaCoverage.cxx +++ b/Source/CTest/cmParseCoberturaCoverage.cxx @@ -71,6 +71,7 @@ protected: cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Reading file: " << atts[tagCount+1]<< std::endl); std::string filename = atts[tagCount+1]; + this->CurFileName = ""; for(size_t i=0;i < FilePaths.size();i++) { finalpath = FilePaths[i] + "/" + filename; diff --git a/Source/CTest/cmParseJacocoCoverage.cxx b/Source/CTest/cmParseJacocoCoverage.cxx new file mode 100644 index 0000000..f270adb --- /dev/null +++ b/Source/CTest/cmParseJacocoCoverage.cxx @@ -0,0 +1,170 @@ +#include "cmStandardIncludes.h" +#include <stdio.h> +#include <stdlib.h> +#include "cmSystemTools.h" +#include "cmXMLParser.h" +#include "cmParseJacocoCoverage.h" +#include <cmsys/Directory.hxx> +#include <cmsys/Glob.hxx> +#include <cmsys/FStream.hxx> + + +class cmParseJacocoCoverage::XMLParser: public cmXMLParser +{ + public: + XMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont) + : CTest(ctest), Coverage(cont) + { + this->PackageName = ""; + this->ModuleName = ""; + this->FileName = ""; + this->CurFileName = ""; + this->FilePaths.push_back(this->Coverage.SourceDir); + } + + virtual ~XMLParser() + { + } + + protected: + + virtual void EndElement(const std::string&) + { + } + + virtual void StartElement(const std::string& name, + const char** atts) + { + if(name == "package") + { + this->PackageName = atts[1]; + std::string FilePath = this->Coverage.SourceDir + + "/" + this->ModuleName + "/src/main/java/" + + this->PackageName; + this->FilePaths.push_back(FilePath); + FilePath = this->Coverage.SourceDir + + "/src/main/java/" + this->PackageName; + this->FilePaths.push_back(FilePath); + } + else if(name == "sourcefile") + { + this->FileName = atts[1]; + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Reading file: " + << this->FileName << std::endl); + for(size_t i=0;i < FilePaths.size();i++) + { + std::string finalpath = FilePaths[i] + "/" + this->FileName; + if(cmSystemTools::FileExists(finalpath.c_str())) + { + this->CurFileName = finalpath; + break; + } + } + cmsys::ifstream fin(this->CurFileName.c_str()); + if(this->CurFileName == "" || !fin ) + { + this->CurFileName = this->Coverage.BinaryDir + "/" + + this->FileName; + fin.open(this->CurFileName.c_str()); + if (!fin) + { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Jacoco Coverage: Error opening " << this->CurFileName + << std::endl); + this->Coverage.Error++; + } + } + std::string line; + FileLinesType& curFileLines = + this->Coverage.TotalCoverage[this->CurFileName]; + curFileLines.push_back(-1); + while(cmSystemTools::GetLineFromStream(fin, line)) + { + curFileLines.push_back(-1); + } + } + else if(name == "report") + { + this->ModuleName=atts[1]; + } + else if(name == "line") + { + int tagCount = 0; + int nr = -1; + int ci = -1; + while(true) + { + if(strcmp(atts[tagCount],"ci") == 0) + { + ci = atoi(atts[tagCount+1]); + } + else if (strcmp(atts[tagCount],"nr") == 0) + { + nr = atoi(atts[tagCount+1]); + } + if (ci > -1 && nr > 0) + { + FileLinesType& curFileLines= + this->Coverage.TotalCoverage[this->CurFileName]; + if(curFileLines.size() > 0) + { + curFileLines[nr-1] = ci; + } + break; + } + ++tagCount; + } + } + } + + private: + std::string PackageName; + std::string FileName; + std::string ModuleName; + std::string CurFileName; + std::vector<std::string> FilePaths; + typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector + FileLinesType; + cmCTest* CTest; + cmCTestCoverageHandlerContainer& Coverage; +}; + +cmParseJacocoCoverage::cmParseJacocoCoverage( + cmCTestCoverageHandlerContainer& cont, + cmCTest* ctest) + :Coverage(cont), CTest(ctest) + { + } + +bool cmParseJacocoCoverage::LoadCoverageData( + const std::vector<std::string> files) +{ + // load all the jacoco.xml files in the source directory + cmsys::Directory dir; + size_t i; + std::string path; + size_t numf = files.size(); + for (i = 0; i < numf; i++) + { + path = files[i]; + + cmCTestLog(this->CTest,HANDLER_VERBOSE_OUTPUT, + "Reading XML File " << path << std::endl); + if(cmSystemTools::GetFilenameLastExtension(path) == ".xml") + { + if(!this->ReadJacocoXML(path.c_str())) + { + return false; + } + } + } + return true; +} + +bool cmParseJacocoCoverage::ReadJacocoXML(const char* file) +{ + cmParseJacocoCoverage::XMLParser + parser(this->CTest, this->Coverage); + parser.ParseFile(file); + return true; +} diff --git a/Source/CTest/cmParseJacocoCoverage.h b/Source/CTest/cmParseJacocoCoverage.h new file mode 100644 index 0000000..dad05a3 --- /dev/null +++ b/Source/CTest/cmParseJacocoCoverage.h @@ -0,0 +1,59 @@ +/*============================================================================ + 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. +============================================================================*/ + +#ifndef cmParseJacocoCoverage_h +#define cmParseJacocoCoverage_h + +#include "cmStandardIncludes.h" +#include "cmCTestCoverageHandler.h" + + +/** \class cmParseJacocoCoverage + * \brief Parse JaCoCO coverage information + * + * This class is used to parse coverage information for + * java using the JaCoCo tool: + * + * http://www.eclemma.org/jacoco/trunk/index.html + */ +class cmParseJacocoCoverage +{ +public: + cmParseJacocoCoverage(cmCTestCoverageHandlerContainer& cont, + cmCTest* ctest); + bool LoadCoverageData(const std::vector<std::string> files); + + std::string PackageName; + std::string FileName; + std::string ModuleName; + std::string CurFileName; +private: + // implement virtual from parent + // remove files with no coverage + void RemoveUnCoveredFiles(); + // Read a single mcov file + bool ReadJacocoXML(const char* f); + // split a string based on , + bool SplitString(std::vector<std::string>& args, + std::string const& line); + bool FindJavaFile(std::string const& routine, + std::string& filepath); + void InitializeJavaFile(std::string& file); + bool LoadSource(std::string d); + + class XMLParser; + std::map<std::string, std::string> RoutineToDirectory; + cmCTestCoverageHandlerContainer& Coverage; + cmCTest* CTest; +}; + +#endif diff --git a/Source/CTest/cmParseMumpsCoverage.cxx b/Source/CTest/cmParseMumpsCoverage.cxx index 6236211..225e704 100644 --- a/Source/CTest/cmParseMumpsCoverage.cxx +++ b/Source/CTest/cmParseMumpsCoverage.cxx @@ -96,11 +96,13 @@ void cmParseMumpsCoverage::InitializeMumpsFile(std::string& file) } if(found) { - // (2) If the first character found above is whitespace then continue the - // search for the first following non-whitespace character. + // (2) If the first character found above is whitespace or a period + // then continue the search for the first following non-whitespace + // character. if(line[i] == ' ' || line[i] == '\t') { - while(i < line.size() && (line[i] == ' ' || line[i] == '\t')) + while(i < line.size() && (line[i] == ' ' || line[i] == '\t' + || line[i] == '.')) { i++; } diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index a9d4d98..28f3d9b 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -38,6 +38,18 @@ static const char * cmDocumentationUsage[][2] = {0, " ccmake <path-to-source>\n" " ccmake <path-to-existing-build>"}, + {0, + "Specify a source directory to (re-)generate a build system for " + "it in the current working directory. Specify an existing build " + "directory to re-generate its build system."}, + {0,0} +}; + +//---------------------------------------------------------------------------- +static const char * cmDocumentationUsageNote[][2] = +{ + {0, + "Run 'ccmake --help' for more information."}, {0,0} }; @@ -83,7 +95,7 @@ void CMakeMessageHandler(const char* message, const char* title, bool&, int main(int argc, char const* const* argv) { - setlocale(LC_ALL, ""); + setlocale(LC_CTYPE, ""); cmsys::Encoding::CommandLineArguments encoding_args = cmsys::Encoding::CommandLineArguments::Main(argc, argv); @@ -102,6 +114,10 @@ int main(int argc, char const* const* argv) doc.SetName("ccmake"); doc.SetSection("Name",cmDocumentationName); doc.SetSection("Usage",cmDocumentationUsage); + if ( argc == 1 ) + { + doc.AppendSection("Usage",cmDocumentationUsageNote); + } doc.SetSection("Generators",generators); doc.PrependSection("Options",cmDocumentationOptions); return doc.PrintRequestedDocumentation(std::cout)? 0:1; diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 8da88c1..03c2fb4 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -35,6 +35,32 @@ if (Qt5Widgets_FOUND) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") + # We need to install Cocoa platform plugin and add qt.conf for Qt5 on Mac. + # FIXME: This should be part of Qt5 CMake scripts, but unfortunatelly + # Qt5 Mac support is missing there. + if(APPLE) + macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var) + get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION) + if(EXISTS "${_qt_plugin_path}") + get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME) + get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH) + get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME) + set(_qt_plugin_dest "${CMAKE_INSTALL_PREFIX}/PlugIns/${_qt_plugin_type}") + install(FILES "${_qt_plugin_path}" + DESTINATION "${_qt_plugin_dest}") + set(${_qt_plugins_var} + "${${_qt_plugins_var}};${_qt_plugin_dest}/${_qt_plugin_file}") + else() + message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found") + endif() + endmacro() + install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + "[Paths]\nPlugins = PlugIns\n") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources") + endif() + if(WIN32 AND TARGET Qt5::Core) get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION) get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH) @@ -168,7 +194,7 @@ if(APPLE OR WIN32) install(CODE " include(\"${CMake_SOURCE_DIR}/Modules/BundleUtilities.cmake\") set(BU_CHMOD_BUNDLE_ITEMS ON) - fixup_bundle(\"${fixup_exe}\" \"\" \"${QT_LIBRARY_DIR};${QT_BINARY_DIR}\") + fixup_bundle(\"${fixup_exe}\" \"${QT_PLUGINS}\" \"${QT_LIBRARY_DIR};${QT_BINARY_DIR}\") ") endif() diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index 8a37797..0574681 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -756,6 +756,9 @@ bool CMakeSetupDialog::setupFirstConfigure() QString systemName = dialog.getSystemName(); m->insertProperty(QCMakeProperty::STRING, "CMAKE_SYSTEM_NAME", tr("CMake System Name"), systemName, false); + QString systemVersion = dialog.getSystemVersion(); + m->insertProperty(QCMakeProperty::STRING, "CMAKE_SYSTEM_VERSION", + tr("CMake System Version"), systemVersion, false); QString cxxCompiler = dialog.getCXXCompiler(); m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_CXX_COMPILER", tr("CXX compiler."), cxxCompiler, false); diff --git a/Source/QtIFW/cmake.org.html b/Source/QtIFW/cmake.org.html new file mode 100644 index 0000000..cf5649d --- /dev/null +++ b/Source/QtIFW/cmake.org.html @@ -0,0 +1,7 @@ +<html> +<head> +<meta http-equiv="Refresh" content="0; url=http://cmake.org/" /> +</head> +<body> +</body> +</html> diff --git a/Source/QtIFW/installscript.qs.in b/Source/QtIFW/installscript.qs.in new file mode 100644 index 0000000..5491611 --- /dev/null +++ b/Source/QtIFW/installscript.qs.in @@ -0,0 +1,24 @@ +function Component() +{ + // default constructor +} + +Component.prototype.createOperations = function() +{ + // call default implementation to actually install applications! + component.createOperations(); + + // Create shortcut + if (installer.value("os") === "win") { + +@_CPACK_IFW_SHORTCUT_OPTIONAL@ + + component.addOperation("CreateShortcut", + installer.value("TargetDir") + "/cmake.org.html", + installer.value("StartMenuDir") + "/CMake Web Site.lnk"); + + component.addOperation("CreateShortcut", + installer.value("TargetDir") + "/uninstall.exe", + installer.value("StartMenuDir") + "/Uninstall.lnk"); + } +} diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 58f7573..a2aecac 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -25,6 +25,28 @@ static std::string cm_archive_error_string(struct archive* a) } //---------------------------------------------------------------------------- +static void cm_archive_entry_copy_pathname(struct archive_entry* e, + const std::string& dest) +{ +#if cmsys_STL_HAS_WSTRING + archive_entry_copy_pathname_w(e, cmsys::Encoding::ToWide(dest).c_str()); +#else + archive_entry_copy_pathname(e, dest.c_str()); +#endif +} + +//---------------------------------------------------------------------------- +static void cm_archive_entry_copy_sourcepath(struct archive_entry* e, + const std::string& file) +{ +#if cmsys_STL_HAS_WSTRING + archive_entry_copy_sourcepath_w(e, cmsys::Encoding::ToWide(file).c_str()); +#else + archive_entry_copy_sourcepath(e, file.c_str()); +#endif +} + +//---------------------------------------------------------------------------- class cmArchiveWrite::Entry { struct archive_entry* Object; @@ -137,7 +159,15 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, Type t): this->Error += cm_archive_error_string(this->Archive); return; } - break; + break; + case Type7Zip: + if(archive_write_set_format_7zip(this->Archive) != ARCHIVE_OK) + { + this->Error = "archive_write_set_format_7zip: "; + this->Error += cm_archive_error_string(this->Archive); + return; + } + break; } // do not pad the last block!! @@ -237,8 +267,8 @@ bool cmArchiveWrite::AddFile(const char* file, std::cout << dest << "\n"; } Entry e; - archive_entry_copy_sourcepath(e, file); - archive_entry_set_pathname(e, dest.c_str()); + cm_archive_entry_copy_sourcepath(e, file); + cm_archive_entry_copy_pathname(e, dest); if(archive_read_disk_entry_from_file(this->Disk, e, -1, 0) != ARCHIVE_OK) { this->Error = "archive_read_disk_entry_from_file: "; diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h index 3e3b2f0..a6dcc0e 100644 --- a/Source/cmArchiveWrite.h +++ b/Source/cmArchiveWrite.h @@ -42,7 +42,8 @@ public: enum Type { TypeTAR, - TypeZIP + TypeZIP, + Type7Zip }; /** Construct with output stream to which to write archive. */ diff --git a/Source/cmBootstrapCommands2.cxx b/Source/cmBootstrapCommands2.cxx index be72526..5675295 100644 --- a/Source/cmBootstrapCommands2.cxx +++ b/Source/cmBootstrapCommands2.cxx @@ -14,6 +14,8 @@ // This is sort of a boot strapping approach since you would // like to have CMake to build CMake. #include "cmCommands.h" +#include "cmConditionEvaluator.cxx" +#include "cmExpandedCommandArgument.cxx" #include "cmGeneratorExpressionEvaluationFile.cxx" #include "cmGetCMakePropertyCommand.cxx" #include "cmGetDirectoryPropertyCommand.cxx" diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index d797d3b..a7905a4 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -488,9 +488,11 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) { cmCTestLog(this, DEBUG, "Here: " << __LINE__ << std::endl); cmCTestLog(this, OUTPUT, - " Site: " << this->GetCTestConfiguration("Site") << std::endl - << " Build name: " << this->GetCTestConfiguration("BuildName") - << std::endl); + " Site: " << this->GetCTestConfiguration("Site") << std::endl + << " Build name: " + << cmCTest::SafeBuildIdField( + this->GetCTestConfiguration("BuildName")) + << std::endl); cmCTestLog(this, DEBUG, "Produce XML is on" << std::endl); if ( this->TestModel == cmCTest::NIGHTLY && this->GetCTestConfiguration("NightlyStartTime").empty() ) @@ -1147,7 +1149,7 @@ int cmCTest::GetTestModelFromString(const char* str) //###################################################################### //---------------------------------------------------------------------- -int cmCTest::RunMakeCommand(const char* command, std::string* output, +int cmCTest::RunMakeCommand(const char* command, std::string& output, int* retVal, const char* dir, int timeout, std::ostream& ofs) { // First generate the command and arguments @@ -1166,11 +1168,7 @@ int cmCTest::RunMakeCommand(const char* command, std::string* output, } argv.push_back(0); - if ( output ) - { - *output = ""; - } - + output = ""; cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Run command:"); std::vector<const char*>::iterator ait; for ( ait = argv.begin(); ait != argv.end() && *ait; ++ ait ) @@ -1199,27 +1197,25 @@ int cmCTest::RunMakeCommand(const char* command, std::string* output, << " " << std::flush); while(cmsysProcess_WaitForData(cp, &data, &length, 0)) { - if ( output ) + for(int cc =0; cc < length; ++cc) { - for(int cc =0; cc < length; ++cc) + if(data[cc] == 0) { - if(data[cc] == 0) - { - data[cc] = '\n'; - } + data[cc] = '\n'; } - - output->append(data, length); - while ( output->size() > (tick * tick_len) ) + } + output.append(data, length); + while ( output.size() > (tick * tick_len) ) + { + tick ++; + cmCTestLog(this, HANDLER_OUTPUT, "." << std::flush); + if ( tick % tick_line_len == 0 && tick > 0 ) { - tick ++; - cmCTestLog(this, HANDLER_OUTPUT, "." << std::flush); - if ( tick % tick_line_len == 0 && tick > 0 ) - { - cmCTestLog(this, HANDLER_OUTPUT, " Size: " - << int((double(output->size()) / 1024.0) + 1) << "K" << std::endl - << " " << std::flush); - } + cmCTestLog(this, HANDLER_OUTPUT, + " Size: " + << int((double(output.size()) / 1024.0) + 1) + << "K" << std::endl + << " " << std::flush); } } cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, cmCTestLogWrite(data, length)); @@ -1229,7 +1225,7 @@ int cmCTest::RunMakeCommand(const char* command, std::string* output, } } cmCTestLog(this, OUTPUT, " Size of output: " - << int(double(output->size()) / 1024.0) << "K" << std::endl); + << int(double(output.size()) / 1024.0) << "K" << std::endl); cmsysProcess_WaitForExit(cp, 0); @@ -1253,9 +1249,9 @@ int cmCTest::RunMakeCommand(const char* command, std::string* output, } else if(result == cmsysProcess_State_Error) { - *output += "\n*** ERROR executing: "; - *output += cmsysProcess_GetErrorString(cp); - *output += "\n***The build process failed."; + output += "\n*** ERROR executing: "; + output += cmsysProcess_GetErrorString(cp); + output += "\n***The build process failed."; cmCTestLog(this, ERROR_MESSAGE, "There was an error: " << cmsysProcess_GetErrorString(cp) << std::endl); } @@ -1447,7 +1443,7 @@ std::string cmCTest::SafeBuildIdField(const std::string& value) // Disallow non-filename and non-space whitespace characters. // If they occur, replace them with "" // - const char *disallowed = "\\/:*?\"<>|\n\r\t\f\v"; + const char *disallowed = "\\:*?\"<>|\n\r\t\f\v"; if (safevalue.find_first_of(disallowed) != value.npos) { @@ -1588,12 +1584,14 @@ void cmCTest::EndXML(std::ostream& ostr) int cmCTest::GenerateCTestNotesOutput(std::ostream& os, const cmCTest::VectorOfStrings& files) { + std::string buildname = cmCTest::SafeBuildIdField( + this->GetCTestConfiguration("BuildName")); cmCTest::VectorOfStrings::const_iterator it; os << "<?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->GetCTestConfiguration("BuildName") + << "<Site BuildName=\"" << buildname << "\" BuildStamp=\"" << this->CurrentTag << "-" << this->GetTestModelString() << "\" Name=\"" << this->GetCTestConfiguration("Site") << "\" Generator=\"ctest" diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 246294f..e19d32c 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -271,7 +271,7 @@ public: //! Run command specialized for make and configure. Returns process status // and retVal is return value or exception. - int RunMakeCommand(const char* command, std::string* output, + int RunMakeCommand(const char* command, std::string& output, int* retVal, const char* dir, int timeout, std::ostream& ofs); diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 995f191..b13a125 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -166,18 +166,17 @@ guaranteed to be acyclic. The final list of items produced by this procedure consists of the original user link line followed by minimal additional items needed to -satisfy dependencies. +satisfy dependencies. The final list is then filtered to de-duplicate +items that we know the linker will re-use automatically (shared libs). */ //---------------------------------------------------------------------------- cmComputeLinkDepends -::cmComputeLinkDepends(cmTarget const* target, const std::string& config, - cmTarget const* head) +::cmComputeLinkDepends(cmTarget const* target, const std::string& config) { // Store context information. this->Target = target; - this->HeadTarget = head; this->Makefile = this->Target->GetMakefile(); this->LocalGenerator = this->Makefile->GetLocalGenerator(); this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); @@ -264,10 +263,20 @@ cmComputeLinkDepends::Compute() this->OrderLinkEntires(); // Compute the final set of link entries. + std::set<int> emmitted; for(std::vector<int>::const_iterator li = this->FinalLinkOrder.begin(); li != this->FinalLinkOrder.end(); ++li) { - this->FinalLinkEntries.push_back(this->EntryList[*li]); + int i = *li; + LinkEntry const& e = this->EntryList[i]; + cmTarget const* t = e.Target; + // Entries that we know the linker will re-use for symbols + // needed by later entries do not need to be repeated. + bool uniquify = t && t->GetType() == cmTarget::SHARED_LIBRARY; + if(!uniquify || emmitted.insert(i).second) + { + this->FinalLinkEntries.push_back(e); + } } // Display the final set. @@ -294,8 +303,7 @@ cmComputeLinkDepends::AllocateLinkEntry(std::string const& item) } //---------------------------------------------------------------------------- -int cmComputeLinkDepends::AddLinkEntry(int depender_index, - std::string const& item) +int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) { // Check if the item entry has already been added. std::map<std::string, int>::iterator lei = this->LinkEntryIndex.find(item); @@ -312,7 +320,7 @@ int cmComputeLinkDepends::AddLinkEntry(int depender_index, int index = lei->second; LinkEntry& entry = this->EntryList[index]; entry.Item = item; - entry.Target = this->FindTargetToLink(depender_index, entry.Item); + entry.Target = item.Target; entry.IsFlag = (!entry.Target && item[0] == '-' && item[1] != 'l' && item.substr(0, 10) != "-framework"); @@ -356,7 +364,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe) { // Follow the target dependencies. if(cmTarget::LinkInterface const* iface = - entry.Target->GetLinkInterface(this->Config, this->HeadTarget)) + entry.Target->GetLinkInterface(this->Config, this->Target)) { const bool isIface = entry.Target->GetType() == cmTarget::INTERFACE_LIBRARY; @@ -372,11 +380,11 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe) this->FollowSharedDeps(depender_index, iface); // Support for CMP0003. - for(std::vector<std::string>::const_iterator + for(std::vector<cmLinkItem>::const_iterator oi = iface->WrongConfigLibraries.begin(); oi != iface->WrongConfigLibraries.end(); ++oi) { - this->CheckWrongConfigItem(depender_index, *oi); + this->CheckWrongConfigItem(*oi); } } } @@ -408,9 +416,9 @@ cmComputeLinkDepends void cmComputeLinkDepends ::QueueSharedDependencies(int depender_index, - std::vector<std::string> const& deps) + std::vector<cmLinkItem> const& deps) { - for(std::vector<std::string>::const_iterator li = deps.begin(); + for(std::vector<cmLinkItem>::const_iterator li = deps.begin(); li != deps.end(); ++li) { SharedDepEntry qe; @@ -434,8 +442,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) // Initialize the item entry. LinkEntry& entry = this->EntryList[lei->second]; entry.Item = dep.Item; - entry.Target = this->FindTargetToLink(dep.DependerIndex, - dep.Item); + entry.Target = dep.Item.Target; // This item was added specifically because it is a dependent // shared library. It may get special treatment @@ -455,7 +462,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) if(entry.Target) { if(cmTarget::LinkInterface const* iface = - entry.Target->GetLinkInterface(this->Config, this->HeadTarget)) + entry.Target->GetLinkInterface(this->Config, this->Target)) { // Follow public and private dependencies transitively. this->FollowSharedDeps(index, iface, true); @@ -474,7 +481,7 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index, cmSystemTools::ExpandListArgument(value, deplist); // Look for entries meant for this configuration. - std::vector<std::string> actual_libs; + std::vector<cmLinkItem> actual_libs; cmTarget::LinkLibraryType llt = cmTarget::GENERAL; bool haveLLT = false; for(std::vector<std::string>::const_iterator di = deplist.begin(); @@ -522,11 +529,13 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index, // If the library is meant for this link type then use it. if(llt == cmTarget::GENERAL || llt == this->LinkType) { - actual_libs.push_back(*di); + cmLinkItem item(*di, this->FindTargetToLink(depender_index, *di)); + actual_libs.push_back(item); } else if(this->OldLinkDirMode) { - this->CheckWrongConfigItem(depender_index, *di); + cmLinkItem item(*di, this->FindTargetToLink(depender_index, *di)); + this->CheckWrongConfigItem(item); } // Reset the link type until another explicit type is given. @@ -544,38 +553,39 @@ void cmComputeLinkDepends::AddDirectLinkEntries() { // Add direct link dependencies in this configuration. cmTarget::LinkImplementation const* impl = - this->Target->GetLinkImplementation(this->Config, this->HeadTarget); + this->Target->GetLinkImplementation(this->Config); this->AddLinkEntries(-1, impl->Libraries); - for(std::vector<std::string>::const_iterator + for(std::vector<cmLinkItem>::const_iterator wi = impl->WrongConfigLibraries.begin(); wi != impl->WrongConfigLibraries.end(); ++wi) { - this->CheckWrongConfigItem(-1, *wi); + this->CheckWrongConfigItem(*wi); } } //---------------------------------------------------------------------------- +template <typename T> void -cmComputeLinkDepends::AddLinkEntries(int depender_index, - std::vector<std::string> const& libs) +cmComputeLinkDepends::AddLinkEntries( + int depender_index, std::vector<T> const& libs) { // Track inferred dependency sets implied by this list. std::map<int, DependSet> dependSets; // Loop over the libraries linked directly by the depender. - for(std::vector<std::string>::const_iterator li = libs.begin(); + for(typename std::vector<T>::const_iterator li = libs.begin(); li != libs.end(); ++li) { // Skip entries that will resolve to the target getting linked or // are empty. - std::string item = this->Target->CheckCMP0004(*li); + cmLinkItem const& item = *li; if(item == this->Target->GetName() || item.empty()) { continue; } // Add a link entry for this item. - int dependee_index = this->AddLinkEntry(depender_index, item); + int dependee_index = this->AddLinkEntry(*li); // The dependee must come after the depender. if(depender_index >= 0) @@ -625,40 +635,15 @@ cmTarget const* cmComputeLinkDepends::FindTargetToLink(int depender_index, const std::string& name) { // Look for a target in the scope of the depender. - cmMakefile* mf = this->Makefile; + cmTarget const* from = this->Target; if(depender_index >= 0) { if(cmTarget const* depender = this->EntryList[depender_index].Target) { - mf = depender->GetMakefile(); + from = depender; } } - cmTarget const* tgt = mf->FindTargetToUse(name); - - // Skip targets that will not really be linked. This is probably a - // name conflict between an external library and an executable - // within the project. - if(tgt && tgt->GetType() == cmTarget::EXECUTABLE && - !tgt->IsExecutableWithExports()) - { - tgt = 0; - } - - if(tgt && tgt->GetType() == cmTarget::OBJECT_LIBRARY) - { - cmOStringStream e; - e << "Target \"" << this->Target->GetName() << "\" links to " - "OBJECT library \"" << tgt->GetName() << "\" but this is not " - "allowed. " - "One may link only to STATIC or SHARED libraries, or to executables " - "with the ENABLE_EXPORTS property set."; - this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Target->GetBacktrace()); - tgt = 0; - } - - // Return the target found, if any. - return tgt; + return from->FindTargetToLink(name); } //---------------------------------------------------------------------------- @@ -955,7 +940,7 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl) if(cmTarget const* target = this->EntryList[*ni].Target) { if(cmTarget::LinkInterface const* iface = - target->GetLinkInterface(this->Config, this->HeadTarget)) + target->GetLinkInterface(this->Config, this->Target)) { if(iface->Multiplicity > count) { @@ -988,8 +973,7 @@ void cmComputeLinkDepends::DisplayFinalEntries() } //---------------------------------------------------------------------------- -void cmComputeLinkDepends::CheckWrongConfigItem(int depender_index, - std::string const& item) +void cmComputeLinkDepends::CheckWrongConfigItem(cmLinkItem const& item) { if(!this->OldLinkDirMode) { @@ -999,12 +983,8 @@ void cmComputeLinkDepends::CheckWrongConfigItem(int depender_index, // For CMake 2.4 bug-compatibility we need to consider the output // directories of targets linked in another configuration as link // directories. - if(cmTarget const* tgt - = this->FindTargetToLink(depender_index, item)) + if(item.Target && !item.Target->IsImported()) { - if(!tgt->IsImported()) - { - this->OldWrongConfigItems.insert(tgt); - } + this->OldWrongConfigItems.insert(item.Target); } } diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 13fc993..a931726 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -32,8 +32,7 @@ class cmake; class cmComputeLinkDepends { public: - cmComputeLinkDepends(cmTarget const* target, const std::string& config, - cmTarget const* head); + cmComputeLinkDepends(cmTarget const* target, const std::string& config); ~cmComputeLinkDepends(); // Basic information about each link item. @@ -60,7 +59,6 @@ private: // Context information. cmTarget const* Target; - cmTarget const* HeadTarget; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; cmGlobalGenerator const* GlobalGenerator; @@ -79,11 +77,11 @@ private: std::map<std::string, int>::iterator AllocateLinkEntry(std::string const& item); - int AddLinkEntry(int depender_index, std::string const& item); + int AddLinkEntry(cmLinkItem const& item); void AddVarLinkEntries(int depender_index, const char* value); void AddDirectLinkEntries(); - void AddLinkEntries(int depender_index, - std::vector<std::string> const& libs); + template <typename T> + void AddLinkEntries(int depender_index, std::vector<T> const& libs); cmTarget const* FindTargetToLink(int depender_index, const std::string& name); @@ -105,7 +103,7 @@ private: // of the interface. struct SharedDepEntry { - std::string Item; + cmLinkItem Item; int DependerIndex; }; std::queue<SharedDepEntry> SharedDepQueue; @@ -114,7 +112,7 @@ private: cmTarget::LinkInterface const* iface, bool follow_interface = false); void QueueSharedDependencies(int depender_index, - std::vector<std::string> const& deps); + std::vector<cmLinkItem> const& deps); void HandleSharedDependency(SharedDepEntry const& dep); // Dependency inferral for each link item. @@ -165,7 +163,7 @@ private: // Compatibility help. bool OldLinkDirMode; - void CheckWrongConfigItem(int depender_index, std::string const& item); + void CheckWrongConfigItem(cmLinkItem const& item); std::set<cmTarget const*> OldWrongConfigItems; }; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index ea8536f..e1852a3 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -239,12 +239,10 @@ because this need be done only for shared libraries without soname-s. //---------------------------------------------------------------------------- cmComputeLinkInformation -::cmComputeLinkInformation(cmTarget const* target, const std::string& config, - cmTarget const* headTarget) +::cmComputeLinkInformation(cmTarget const* target, const std::string& config) { // Store context information. this->Target = target; - this->HeadTarget = headTarget; this->Makefile = this->Target->GetMakefile(); this->LocalGenerator = this->Makefile->GetLocalGenerator(); this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); @@ -267,7 +265,7 @@ cmComputeLinkInformation this->OrderDependentRPath = 0; // Get the language used for linking this target. - this->LinkLanguage = this->Target->GetLinkerLanguage(config, headTarget); + this->LinkLanguage = this->Target->GetLinkerLanguage(config); if(this->LinkLanguage.empty()) { // The Compute method will do nothing, so skip the rest of the @@ -505,8 +503,7 @@ bool cmComputeLinkInformation::Compute() } // Compute the ordered link line items. - cmComputeLinkDepends cld(this->Target, this->Config, - this->HeadTarget); + cmComputeLinkDepends cld(this->Target, this->Config); cld.SetOldLinkDirMode(this->OldLinkDirMode); cmComputeLinkDepends::EntryVector const& linkEntries = cld.Compute(); @@ -572,8 +569,7 @@ bool cmComputeLinkInformation::Compute() void cmComputeLinkInformation::AddImplicitLinkInfo() { // The link closure lists all languages whose implicit info is needed. - cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config, - this->HeadTarget); + cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config); for(std::vector<std::string>::const_iterator li = lc->Languages.begin(); li != lc->Languages.end(); ++li) { @@ -1811,7 +1807,7 @@ cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath) } } - is_shared_library = this->ExtractSharedLibraryName.find(file.c_str()); + is_shared_library = this->ExtractSharedLibraryName.find(file); if(!is_shared_library) { @@ -1831,8 +1827,8 @@ cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath) { if(fullPath.find(".framework") != std::string::npos) { - cmsys::RegularExpression splitFramework; - splitFramework.compile("^(.*)/(.*).framework/(.*)$"); + static cmsys::RegularExpression + splitFramework("^(.*)/(.*).framework/(.*)$"); if(splitFramework.find(fullPath) && (std::string::npos != splitFramework.match(3).find(splitFramework.match(2)))) @@ -1972,7 +1968,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, // present. This is done even when skipping rpath support. { cmTarget::LinkClosure const* lc = - this->Target->GetLinkClosure(this->Config, this->HeadTarget); + this->Target->GetLinkClosure(this->Config); for(std::vector<std::string>::const_iterator li = lc->Languages.begin(); li != lc->Languages.end(); ++li) { diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index e345fe2..e5d674a 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -29,8 +29,7 @@ class cmOrderDirectories; class cmComputeLinkInformation { public: - cmComputeLinkInformation(cmTarget const* target, const std::string& config, - cmTarget const* headTarget); + cmComputeLinkInformation(cmTarget const* target, const std::string& config); ~cmComputeLinkInformation(); bool Compute(); @@ -75,7 +74,6 @@ private: // Context information. cmTarget const* Target; - cmTarget const* HeadTarget; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; cmGlobalGenerator* GlobalGenerator; diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index f28217f..75d3967 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -249,20 +249,21 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) const_cast<cmTarget*>(depender)->AddUtility(objLib); } } - std::vector<std::string> tlibs; - depender->GetDirectLinkLibraries(*it, tlibs, depender); + + cmTarget::LinkImplementation const* impl = + depender->GetLinkImplementation(*it); // A target should not depend on itself. emitted.insert(depender->GetName()); - for(std::vector<std::string>::const_iterator lib = tlibs.begin(); - lib != tlibs.end(); ++lib) + for(std::vector<cmLinkImplItem>::const_iterator + lib = impl->Libraries.begin(); + lib != impl->Libraries.end(); ++lib) { // Don't emit the same library twice for this target. if(emitted.insert(*lib).second) { this->AddTargetDepend(depender_index, *lib, true); - this->AddInterfaceDepends(depender_index, *lib, - true, emitted); + this->AddInterfaceDepends(depender_index, *lib, emitted); } } } @@ -270,11 +271,11 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // Loop over all utility dependencies. { - std::set<std::string> const& tutils = depender->GetUtilities(); + std::set<cmLinkItem> const& tutils = depender->GetUtilityItems(); std::set<std::string> emitted; // A target should not depend on itself. emitted.insert(depender->GetName()); - for(std::set<std::string>::const_iterator util = tutils.begin(); + for(std::set<cmLinkItem>::const_iterator util = tutils.begin(); util != tutils.end(); ++util) { // Don't emit the same utility twice for this target. @@ -296,7 +297,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, if(cmTarget::LinkInterface const* iface = dependee->GetLinkInterface(config, depender)) { - for(std::vector<std::string>::const_iterator + for(std::vector<cmLinkItem>::const_iterator lib = iface->Libraries.begin(); lib != iface->Libraries.end(); ++lib) { @@ -304,8 +305,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, if(emitted.insert(*lib).second) { this->AddTargetDepend(depender_index, *lib, true); - this->AddInterfaceDepends(depender_index, *lib, - true, emitted); + this->AddInterfaceDepends(depender_index, *lib, emitted); } } } @@ -313,17 +313,15 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, //---------------------------------------------------------------------------- void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, - const std::string& dependee_name, - bool linking, + cmLinkItem const& dependee_name, std::set<std::string> &emitted) { cmTarget const* depender = this->Targets[depender_index]; - cmTarget const* dependee = - depender->GetMakefile()->FindTargetToUse(dependee_name); + cmTarget const* dependee = dependee_name.Target; // Skip targets that will not really be linked. This is probably a // name conflict between an external library and an executable // within the project. - if(linking && dependee && + if(dependee && dependee->GetType() == cmTarget::EXECUTABLE && !dependee->IsExecutableWithExports()) { @@ -347,16 +345,15 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, } //---------------------------------------------------------------------------- -void cmComputeTargetDepends::AddTargetDepend(int depender_index, - const std::string& dependee_name, - bool linking) +void cmComputeTargetDepends::AddTargetDepend( + int depender_index, cmLinkItem const& dependee_name, + bool linking) { // Get the depender. cmTarget const* depender = this->Targets[depender_index]; // Check the target's makefile first. - cmTarget const* dependee = - depender->GetMakefile()->FindTargetToUse(dependee_name); + cmTarget const* dependee = dependee_name.Target; if(!dependee && !linking && (depender->GetType() != cmTarget::GLOBAL_TARGET)) @@ -424,12 +421,11 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, if(dependee->IsImported()) { // Skip imported targets but follow their utility dependencies. - std::set<std::string> const& utils = dependee->GetUtilities(); - for(std::set<std::string>::const_iterator i = utils.begin(); + std::set<cmLinkItem> const& utils = dependee->GetUtilityItems(); + for(std::set<cmLinkItem>::const_iterator i = utils.begin(); i != utils.end(); ++i) { - if(cmTarget const* transitive_dependee = - dependee->GetMakefile()->FindTargetToUse(*i)) + if(cmTarget const* transitive_dependee = i->Target) { this->AddTargetDepend(depender_index, transitive_dependee, false); } diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index 7553816..902f342 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -20,6 +20,7 @@ class cmComputeComponentGraph; class cmGlobalGenerator; +class cmLinkItem; class cmTarget; class cmTargetDependSet; @@ -46,14 +47,14 @@ private: void CollectDepends(); void CollectTargetDepends(int depender_index); void AddTargetDepend(int depender_index, - const std::string& dependee_name, + cmLinkItem const& dependee_name, bool linking); void AddTargetDepend(int depender_index, cmTarget const* dependee, bool linking); bool ComputeFinalDepends(cmComputeComponentGraph const& ccg); void AddInterfaceDepends(int depender_index, - const std::string& dependee_name, - bool linking, std::set<std::string> &emitted); + cmLinkItem const& dependee_name, + std::set<std::string> &emitted); void AddInterfaceDepends(int depender_index, cmTarget const* dependee, const std::string& config, std::set<std::string> &emitted); diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx new file mode 100644 index 0000000..aba26de --- /dev/null +++ b/Source/cmConditionEvaluator.cxx @@ -0,0 +1,770 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 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 "cmConditionEvaluator.h" + +cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile): + Makefile(makefile), + Policy12Status(makefile.GetPolicyStatus(cmPolicies::CMP0012)), + Policy54Status(makefile.GetPolicyStatus(cmPolicies::CMP0054)) +{ + +} + +//========================================================================= +// order of operations, +// 1. ( ) -- parenthetical groups +// 2. IS_DIRECTORY EXISTS COMMAND DEFINED etc predicates +// 3. MATCHES LESS GREATER EQUAL STRLESS STRGREATER STREQUAL etc binary ops +// 4. NOT +// 5. AND OR +// +// There is an issue on whether the arguments should be values of references, +// for example IF (FOO AND BAR) should that compare the strings FOO and BAR +// or should it really do IF (${FOO} AND ${BAR}) Currently IS_DIRECTORY +// EXISTS COMMAND and DEFINED all take values. EQUAL, LESS and GREATER can +// take numeric values or variable names. STRLESS and STRGREATER take +// variable names but if the variable name is not found it will use the name +// directly. AND OR take variables or the values 0 or 1. + +bool cmConditionEvaluator::IsTrue( + const std::vector<cmExpandedCommandArgument> &args, + std::string &errorString, + cmake::MessageType &status) +{ + errorString = ""; + + // handle empty invocation + if (args.size() < 1) + { + return false; + } + + // store the reduced args in this vector + cmArgumentList newArgs; + + // copy to the list structure + for(unsigned int i = 0; i < args.size(); ++i) + { + newArgs.push_back(args[i]); + } + + // now loop through the arguments and see if we can reduce any of them + // we do this multiple times. Once for each level of precedence + // parens + if (!this->HandleLevel0(newArgs, errorString, status)) + { + return false; + } + //predicates + if (!this->HandleLevel1(newArgs, errorString, status)) + { + return false; + } + // binary ops + if (!this->HandleLevel2(newArgs, errorString, status)) + { + return false; + } + + // NOT + if (!this->HandleLevel3(newArgs, errorString, status)) + { + return false; + } + // AND OR + if (!this->HandleLevel4(newArgs, errorString, status)) + { + return false; + } + + // now at the end there should only be one argument left + if (newArgs.size() != 1) + { + errorString = "Unknown arguments specified"; + status = cmake::FATAL_ERROR; + return false; + } + + return this->GetBooleanValueWithAutoDereference(*(newArgs.begin()), + errorString, status, true); +} + +//========================================================================= +const char* cmConditionEvaluator::GetDefinitionIfUnquoted( + cmExpandedCommandArgument const& argument) const +{ + if((this->Policy54Status != cmPolicies::WARN && + this->Policy54Status != cmPolicies::OLD) && + argument.WasQuoted()) + { + return 0; + } + + const char* def = this->Makefile.GetDefinition(argument.GetValue()); + + if(def && argument.WasQuoted() && this->Policy54Status == cmPolicies::WARN) + { + bool hasBeenReported = this->Makefile.HasCMP0054AlreadyBeenReported( + this->Makefile.GetBacktrace()[0]); + + if(!hasBeenReported) + { + cmOStringStream e; + e << (this->Makefile.GetPolicies()->GetPolicyWarning( + cmPolicies::CMP0054)) << "\n"; + e << "Quoted variables like \"" << argument.GetValue() << + "\" will no longer be dereferenced " + "when the policy is set to NEW. " + "Since the policy is not set the OLD behavior will be used."; + + this->Makefile.IssueMessage(cmake::AUTHOR_WARNING, e.str()); + } + } + + return def; +} + +//========================================================================= +const char* cmConditionEvaluator::GetVariableOrString( + const cmExpandedCommandArgument& argument) const +{ + const char* def = this->GetDefinitionIfUnquoted(argument); + + if(!def) + { + def = argument.c_str(); + } + + return def; +} + +//========================================================================= +bool cmConditionEvaluator::IsKeyword(std::string const& keyword, + cmExpandedCommandArgument& argument) const +{ + if((this->Policy54Status != cmPolicies::WARN && + this->Policy54Status != cmPolicies::OLD) && + argument.WasQuoted()) + { + return false; + } + + bool isKeyword = argument.GetValue() == keyword; + + if(isKeyword && argument.WasQuoted() && + this->Policy54Status == cmPolicies::WARN) + { + bool hasBeenReported = this->Makefile.HasCMP0054AlreadyBeenReported( + this->Makefile.GetBacktrace()[0]); + + if(!hasBeenReported) + { + cmOStringStream e; + e << (this->Makefile.GetPolicies()->GetPolicyWarning( + cmPolicies::CMP0054)) << "\n"; + e << "Quoted keywords like \"" << argument.GetValue() << + "\" will no longer be interpreted as keywords " + "when the policy is set to NEW. " + "Since the policy is not set the OLD behavior will be used."; + + this->Makefile.IssueMessage(cmake::AUTHOR_WARNING, e.str()); + } + } + + return isKeyword; +} + +//========================================================================= +bool cmConditionEvaluator::GetBooleanValue( + cmExpandedCommandArgument& arg) const +{ + // Check basic constants. + if (arg == "0") + { + return false; + } + if (arg == "1") + { + return true; + } + + // Check named constants. + if (cmSystemTools::IsOn(arg.c_str())) + { + return true; + } + if (cmSystemTools::IsOff(arg.c_str())) + { + return false; + } + + // Check for numbers. + if(!arg.empty()) + { + char* end; + double d = strtod(arg.c_str(), &end); + if(*end == '\0') + { + // The whole string is a number. Use C conversion to bool. + return d? true:false; + } + } + + // Check definition. + const char* def = this->GetDefinitionIfUnquoted(arg); + return !cmSystemTools::IsOff(def); +} + +//========================================================================= +// Boolean value behavior from CMake 2.6.4 and below. +bool cmConditionEvaluator::GetBooleanValueOld( + cmExpandedCommandArgument const& arg, bool one) const +{ + if(one) + { + // Old IsTrue behavior for single argument. + if(arg == "0") + { return false; } + else if(arg == "1") + { return true; } + else + { + const char* def = this->GetDefinitionIfUnquoted(arg); + return !cmSystemTools::IsOff(def); + } + } + else + { + // Old GetVariableOrNumber behavior. + const char* def = this->GetDefinitionIfUnquoted(arg); + if(!def && atoi(arg.c_str())) + { + def = arg.c_str(); + } + return !cmSystemTools::IsOff(def); + } +} + +//========================================================================= +// returns the resulting boolean value +bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( + cmExpandedCommandArgument &newArg, + std::string &errorString, + cmake::MessageType &status, + bool oneArg) const +{ + // Use the policy if it is set. + if (this->Policy12Status == cmPolicies::NEW) + { + return GetBooleanValue(newArg); + } + else if (this->Policy12Status == cmPolicies::OLD) + { + return GetBooleanValueOld(newArg, oneArg); + } + + // Check policy only if old and new results differ. + bool newResult = this->GetBooleanValue(newArg); + bool oldResult = this->GetBooleanValueOld(newArg, oneArg); + if(newResult != oldResult) + { + switch(this->Policy12Status) + { + case cmPolicies::WARN: + { + cmPolicies* policies = this->Makefile.GetPolicies(); + errorString = "An argument named \"" + newArg.GetValue() + + "\" appears in a conditional statement. " + + policies->GetPolicyWarning(cmPolicies::CMP0012); + status = cmake::AUTHOR_WARNING; + } + case cmPolicies::OLD: + return oldResult; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + { + cmPolicies* policies = this->Makefile.GetPolicies(); + errorString = "An argument named \"" + newArg.GetValue() + + "\" appears in a conditional statement. " + + policies->GetRequiredPolicyError(cmPolicies::CMP0012); + status = cmake::FATAL_ERROR; + } + case cmPolicies::NEW: + break; + } + } + return newResult; +} + +//========================================================================= +void cmConditionEvaluator::IncrementArguments(cmArgumentList &newArgs, + cmArgumentList::iterator &argP1, + cmArgumentList::iterator &argP2) const +{ + if (argP1 != newArgs.end()) + { + argP1++; + argP2 = argP1; + if (argP1 != newArgs.end()) + { + argP2++; + } + } +} + +//========================================================================= +// helper function to reduce code duplication +void cmConditionEvaluator::HandlePredicate(bool value, int &reducible, + cmArgumentList::iterator &arg, + cmArgumentList &newArgs, + cmArgumentList::iterator &argP1, + cmArgumentList::iterator &argP2) const +{ + if(value) + { + *arg = cmExpandedCommandArgument("1", true); + } + else + { + *arg = cmExpandedCommandArgument("0", true); + } + newArgs.erase(argP1); + argP1 = arg; + this->IncrementArguments(newArgs,argP1,argP2); + reducible = 1; +} + +//========================================================================= +// helper function to reduce code duplication +void cmConditionEvaluator::HandleBinaryOp(bool value, int &reducible, + cmArgumentList::iterator &arg, + cmArgumentList &newArgs, + cmArgumentList::iterator &argP1, + cmArgumentList::iterator &argP2) +{ + if(value) + { + *arg = cmExpandedCommandArgument("1", true); + } + else + { + *arg = cmExpandedCommandArgument("0", true); + } + newArgs.erase(argP2); + newArgs.erase(argP1); + argP1 = arg; + this->IncrementArguments(newArgs,argP1,argP2); + reducible = 1; +} + +//========================================================================= +// level 0 processes parenthetical expressions +bool cmConditionEvaluator::HandleLevel0(cmArgumentList &newArgs, + std::string &errorString, + cmake::MessageType &status) +{ + int reducible; + do + { + reducible = 0; + cmArgumentList::iterator arg = newArgs.begin(); + while (arg != newArgs.end()) + { + if (IsKeyword("(", *arg)) + { + // search for the closing paren for this opening one + cmArgumentList::iterator argClose; + argClose = arg; + argClose++; + unsigned int depth = 1; + while (argClose != newArgs.end() && depth) + { + if (this->IsKeyword("(", *argClose)) + { + depth++; + } + if (this->IsKeyword(")", *argClose)) + { + depth--; + } + argClose++; + } + if (depth) + { + errorString = "mismatched parenthesis in condition"; + status = cmake::FATAL_ERROR; + return false; + } + // store the reduced args in this vector + std::vector<cmExpandedCommandArgument> newArgs2; + + // copy to the list structure + cmArgumentList::iterator argP1 = arg; + argP1++; + for(; argP1 != argClose; argP1++) + { + newArgs2.push_back(*argP1); + } + newArgs2.pop_back(); + // now recursively invoke IsTrue to handle the values inside the + // parenthetical expression + bool value = + this->IsTrue(newArgs2, errorString, status); + if(value) + { + *arg = cmExpandedCommandArgument("1", true); + } + else + { + *arg = cmExpandedCommandArgument("0", true); + } + argP1 = arg; + argP1++; + // remove the now evaluated parenthetical expression + newArgs.erase(argP1,argClose); + } + ++arg; + } + } + while (reducible); + return true; +} + +//========================================================================= +// level one handles most predicates except for NOT +bool cmConditionEvaluator::HandleLevel1(cmArgumentList &newArgs, + std::string &, cmake::MessageType &) +{ + int reducible; + do + { + reducible = 0; + cmArgumentList::iterator arg = newArgs.begin(); + cmArgumentList::iterator argP1; + cmArgumentList::iterator argP2; + while (arg != newArgs.end()) + { + argP1 = arg; + this->IncrementArguments(newArgs,argP1,argP2); + // does a file exist + if (this->IsKeyword("EXISTS", *arg) && argP1 != newArgs.end()) + { + this->HandlePredicate( + cmSystemTools::FileExists(argP1->c_str()), + reducible, arg, newArgs, argP1, argP2); + } + // does a directory with this name exist + if (this->IsKeyword("IS_DIRECTORY", *arg) && argP1 != newArgs.end()) + { + this->HandlePredicate( + cmSystemTools::FileIsDirectory(argP1->c_str()), + reducible, arg, newArgs, argP1, argP2); + } + // does a symlink with this name exist + if (this->IsKeyword("IS_SYMLINK", *arg) && argP1 != newArgs.end()) + { + this->HandlePredicate( + cmSystemTools::FileIsSymlink(argP1->c_str()), + reducible, arg, newArgs, argP1, argP2); + } + // is the given path an absolute path ? + if (this->IsKeyword("IS_ABSOLUTE", *arg) && argP1 != newArgs.end()) + { + this->HandlePredicate( + cmSystemTools::FileIsFullPath(argP1->c_str()), + reducible, arg, newArgs, argP1, argP2); + } + // does a command exist + if (this->IsKeyword("COMMAND", *arg) && argP1 != newArgs.end()) + { + this->HandlePredicate( + this->Makefile.CommandExists(argP1->c_str()), + reducible, arg, newArgs, argP1, argP2); + } + // does a policy exist + if (this->IsKeyword("POLICY", *arg) && argP1 != newArgs.end()) + { + cmPolicies::PolicyID pid; + this->HandlePredicate( + this->Makefile.GetPolicies()->GetPolicyID( + argP1->c_str(), pid), + reducible, arg, newArgs, argP1, argP2); + } + // does a target exist + if (this->IsKeyword("TARGET", *arg) && argP1 != newArgs.end()) + { + this->HandlePredicate( + this->Makefile.FindTargetToUse(argP1->GetValue())?true:false, + reducible, arg, newArgs, argP1, argP2); + } + // is a variable defined + if (this->IsKeyword("DEFINED", *arg) && argP1 != newArgs.end()) + { + size_t argP1len = argP1->GetValue().size(); + bool bdef = false; + if(argP1len > 4 && argP1->GetValue().substr(0, 4) == "ENV{" && + argP1->GetValue().operator[](argP1len-1) == '}') + { + std::string env = argP1->GetValue().substr(4, argP1len-5); + bdef = cmSystemTools::GetEnv(env.c_str())?true:false; + } + else + { + bdef = this->Makefile.IsDefinitionSet(argP1->GetValue()); + } + this->HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2); + } + ++arg; + } + } + while (reducible); + return true; +} + +//========================================================================= +// level two handles most binary operations except for AND OR +bool cmConditionEvaluator::HandleLevel2(cmArgumentList &newArgs, + std::string &errorString, + cmake::MessageType &status) +{ + int reducible; + const char *def; + const char *def2; + do + { + reducible = 0; + cmArgumentList::iterator arg = newArgs.begin(); + cmArgumentList::iterator argP1; + cmArgumentList::iterator argP2; + while (arg != newArgs.end()) + { + argP1 = arg; + this->IncrementArguments(newArgs,argP1,argP2); + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + IsKeyword("MATCHES", *argP1)) + { + def = this->GetVariableOrString(*arg); + const char* rex = argP2->c_str(); + this->Makefile.ClearMatches(); + cmsys::RegularExpression regEntry; + if ( !regEntry.compile(rex) ) + { + cmOStringStream error; + error << "Regular expression \"" << rex << "\" cannot compile"; + errorString = error.str(); + status = cmake::FATAL_ERROR; + return false; + } + if (regEntry.find(def)) + { + this->Makefile.StoreMatches(regEntry); + *arg = cmExpandedCommandArgument("1", true); + } + else + { + *arg = cmExpandedCommandArgument("0", true); + } + newArgs.erase(argP2); + newArgs.erase(argP1); + argP1 = arg; + this->IncrementArguments(newArgs,argP1,argP2); + reducible = 1; + } + + if (argP1 != newArgs.end() && this->IsKeyword("MATCHES", *arg)) + { + *arg = cmExpandedCommandArgument("0", true); + newArgs.erase(argP1); + argP1 = arg; + this->IncrementArguments(newArgs,argP1,argP2); + reducible = 1; + } + + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + (this->IsKeyword("LESS", *argP1) || + this->IsKeyword("GREATER", *argP1) || + this->IsKeyword("EQUAL", *argP1))) + { + def = this->GetVariableOrString(*arg); + def2 = this->GetVariableOrString(*argP2); + double lhs; + double rhs; + bool result; + if(sscanf(def, "%lg", &lhs) != 1 || + sscanf(def2, "%lg", &rhs) != 1) + { + result = false; + } + else if (*(argP1) == "LESS") + { + result = (lhs < rhs); + } + else if (*(argP1) == "GREATER") + { + result = (lhs > rhs); + } + else + { + result = (lhs == rhs); + } + this->HandleBinaryOp(result, + reducible, arg, newArgs, argP1, argP2); + } + + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + (this->IsKeyword("STRLESS", *argP1) || + this->IsKeyword("STREQUAL", *argP1) || + this->IsKeyword("STRGREATER", *argP1))) + { + def = this->GetVariableOrString(*arg); + def2 = this->GetVariableOrString(*argP2); + int val = strcmp(def,def2); + bool result; + if (*(argP1) == "STRLESS") + { + result = (val < 0); + } + else if (*(argP1) == "STRGREATER") + { + result = (val > 0); + } + else // strequal + { + result = (val == 0); + } + this->HandleBinaryOp(result, + reducible, arg, newArgs, argP1, argP2); + } + + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + (this->IsKeyword("VERSION_LESS", *argP1) || + this->IsKeyword("VERSION_GREATER", *argP1) || + this->IsKeyword("VERSION_EQUAL", *argP1))) + { + def = this->GetVariableOrString(*arg); + def2 = this->GetVariableOrString(*argP2); + cmSystemTools::CompareOp op = cmSystemTools::OP_EQUAL; + if(*argP1 == "VERSION_LESS") + { + op = cmSystemTools::OP_LESS; + } + else if(*argP1 == "VERSION_GREATER") + { + op = cmSystemTools::OP_GREATER; + } + bool result = cmSystemTools::VersionCompare(op, def, def2); + this->HandleBinaryOp(result, + reducible, arg, newArgs, argP1, argP2); + } + + // is file A newer than file B + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + this->IsKeyword("IS_NEWER_THAN", *argP1)) + { + int fileIsNewer=0; + bool success=cmSystemTools::FileTimeCompare(arg->GetValue(), + (argP2)->GetValue(), + &fileIsNewer); + this->HandleBinaryOp( + (success==false || fileIsNewer==1 || fileIsNewer==0), + reducible, arg, newArgs, argP1, argP2); + } + + ++arg; + } + } + while (reducible); + return true; +} + +//========================================================================= +// level 3 handles NOT +bool cmConditionEvaluator::HandleLevel3(cmArgumentList &newArgs, + std::string &errorString, + cmake::MessageType &status) +{ + int reducible; + do + { + reducible = 0; + cmArgumentList::iterator arg = newArgs.begin(); + cmArgumentList::iterator argP1; + cmArgumentList::iterator argP2; + while (arg != newArgs.end()) + { + argP1 = arg; + IncrementArguments(newArgs,argP1,argP2); + if (argP1 != newArgs.end() && IsKeyword("NOT", *arg)) + { + bool rhs = this->GetBooleanValueWithAutoDereference(*argP1, + errorString, + status); + this->HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2); + } + ++arg; + } + } + while (reducible); + return true; +} + +//========================================================================= +// level 4 handles AND OR +bool cmConditionEvaluator::HandleLevel4(cmArgumentList &newArgs, + std::string &errorString, + cmake::MessageType &status) +{ + int reducible; + bool lhs; + bool rhs; + do + { + reducible = 0; + cmArgumentList::iterator arg = newArgs.begin(); + cmArgumentList::iterator argP1; + cmArgumentList::iterator argP2; + while (arg != newArgs.end()) + { + argP1 = arg; + IncrementArguments(newArgs,argP1,argP2); + if (argP1 != newArgs.end() && IsKeyword("AND", *argP1) && + argP2 != newArgs.end()) + { + lhs = this->GetBooleanValueWithAutoDereference(*arg, + errorString, + status); + rhs = this->GetBooleanValueWithAutoDereference(*argP2, + errorString, + status); + this->HandleBinaryOp((lhs && rhs), + reducible, arg, newArgs, argP1, argP2); + } + + if (argP1 != newArgs.end() && this->IsKeyword("OR", *argP1) && + argP2 != newArgs.end()) + { + lhs = this->GetBooleanValueWithAutoDereference(*arg, + errorString, + status); + rhs = this->GetBooleanValueWithAutoDereference(*argP2, + errorString, + status); + this->HandleBinaryOp((lhs || rhs), + reducible, arg, newArgs, argP1, argP2); + } + ++arg; + } + } + while (reducible); + return true; +} diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h new file mode 100644 index 0000000..01624f9 --- /dev/null +++ b/Source/cmConditionEvaluator.h @@ -0,0 +1,96 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 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 cmConditionEvaluator_h +#define cmConditionEvaluator_h + +#include "cmCommand.h" +#include "cmExpandedCommandArgument.h" + +class cmConditionEvaluator +{ +public: + typedef std::list<cmExpandedCommandArgument> cmArgumentList; + + cmConditionEvaluator(cmMakefile& makefile); + + // this is a shared function for both If and Else to determine if the + // arguments were valid, and if so, was the response true. If there is + // an error, the errorString will be set. + bool IsTrue(const std::vector<cmExpandedCommandArgument> &args, + std::string &errorString, + cmake::MessageType &status); + +private: + // Filter the given variable definition based on policy CMP0054. + const char* GetDefinitionIfUnquoted( + const cmExpandedCommandArgument& argument) const; + + const char* GetVariableOrString( + const cmExpandedCommandArgument& argument) const; + + bool IsKeyword(std::string const& keyword, + cmExpandedCommandArgument& argument) const; + + bool GetBooleanValue( + cmExpandedCommandArgument& arg) const; + + bool GetBooleanValueOld( + cmExpandedCommandArgument const& arg, bool one) const; + + bool GetBooleanValueWithAutoDereference( + cmExpandedCommandArgument &newArg, + std::string &errorString, + cmake::MessageType &status, + bool oneArg = false) const; + + void IncrementArguments( + cmArgumentList &newArgs, + cmArgumentList::iterator &argP1, + cmArgumentList::iterator &argP2) const; + + void HandlePredicate(bool value, int &reducible, + cmArgumentList::iterator &arg, + cmArgumentList &newArgs, + cmArgumentList::iterator &argP1, + cmArgumentList::iterator &argP2) const; + + void HandleBinaryOp(bool value, int &reducible, + cmArgumentList::iterator &arg, + cmArgumentList &newArgs, + cmArgumentList::iterator &argP1, + cmArgumentList::iterator &argP2); + + bool HandleLevel0(cmArgumentList &newArgs, + std::string &errorString, + cmake::MessageType &status); + + bool HandleLevel1(cmArgumentList &newArgs, + std::string &, cmake::MessageType &); + + bool HandleLevel2(cmArgumentList &newArgs, + std::string &errorString, + cmake::MessageType &status); + + bool HandleLevel3(cmArgumentList &newArgs, + std::string &errorString, + cmake::MessageType &status); + + bool HandleLevel4(cmArgumentList &newArgs, + std::string &errorString, + cmake::MessageType &status); + + cmMakefile& Makefile; + cmPolicies::PolicyStatus Policy12Status; + cmPolicies::PolicyStatus Policy54Status; +}; + +#endif diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index a3f3277..bc5708d 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -489,7 +489,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) targetName, this->SrcFileSignature, &cmakeFlags, - &output); + output); if ( erroroc ) { cmSystemTools::SetErrorOccured(); @@ -634,6 +634,10 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName) searchDirs.push_back(tmp); } searchDirs.push_back("/Debug"); +#if defined(__APPLE__) + std::string app = "/Debug/" + targetName + ".app"; + searchDirs.push_back(app); +#endif searchDirs.push_back("/Development"); for(std::vector<std::string>::const_iterator it = searchDirs.begin(); diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx index babf1c4..fe32dd5 100644 --- a/Source/cmDefinitions.cxx +++ b/Source/cmDefinitions.cxx @@ -15,7 +15,8 @@ cmDefinitions::Def cmDefinitions::NoDef; //---------------------------------------------------------------------------- -cmDefinitions::cmDefinitions(cmDefinitions* parent): Up(parent) +cmDefinitions::cmDefinitions(cmDefinitions* parent) + : Up(parent) { } @@ -35,7 +36,7 @@ cmDefinitions::GetInternal(const std::string& key) { return i->second; } - else if(cmDefinitions* up = this->Up) + if(cmDefinitions* up = this->Up) { // Query the parent scope and store the result locally. Def def = up->GetInternal(key); @@ -51,16 +52,7 @@ cmDefinitions::SetInternal(const std::string& key, Def const& def) if(this->Up || def.Exists) { // In lower scopes we store keys, defined or not. - MapType::iterator i = this->Map.find(key); - if(i == this->Map.end()) - { - i = this->Map.insert(MapType::value_type(key, def)).first; - } - else - { - i->second = def; - } - return i->second; + return (this->Map[key] = def); } else { diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h index d615fb0..a2f053f 100644 --- a/Source/cmDefinitions.h +++ b/Source/cmDefinitions.h @@ -13,6 +13,9 @@ #define cmDefinitions_h #include "cmStandardIncludes.h" +#if defined(CMAKE_BUILD_WITH_CMAKE) +#include "cmsys/hash_map.hxx" +#endif /** \class cmDefinitions * \brief Store a scope of variable definitions for CMake language. @@ -69,7 +72,11 @@ private: cmDefinitions* Up; // Local definitions, set or unset. +#if defined(CMAKE_BUILD_WITH_CMAKE) + typedef cmsys::hash_map<std::string, Def> MapType; +#else typedef std::map<std::string, Def> MapType; +#endif MapType Map; // Internal query and update methods. diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index 50a395e..134f45b 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -58,12 +58,7 @@ bool cmDepends::Write(std::ostream &makeDepends, // Get the source and object file. std::string const& src = *si++; if(si == pairs.end()) { break; } - std::string obj = *si++; - - // Make sure the object file is relative to the top of the build tree. - obj = this->LocalGenerator->Convert(obj, - cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); + std::string const& obj = *si++; dependencies[obj].insert(src); } for(std::map<std::string, std::set<std::string> >::const_iterator diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index d26d3a9..a1fc268 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -269,14 +269,20 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources, // written by the original local generator for this directory // convert the dependencies to paths relative to the home output // directory. We must do the same here. - internalDepends << obj << std::endl; + std::string obj_i = + this->LocalGenerator->Convert(obj, cmLocalGenerator::HOME_OUTPUT); + std::string obj_m = + this->LocalGenerator->ConvertToOutputFormat(obj_i, + cmLocalGenerator::MAKERULE); + internalDepends << obj_i << std::endl; + for(std::set<std::string>::const_iterator i=dependencies.begin(); i != dependencies.end(); ++i) { - makeDepends << obj << ": " << + makeDepends << obj_m << ": " << this->LocalGenerator->Convert(*i, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE) + cmLocalGenerator::MAKERULE) << std::endl; internalDepends << " " << *i << std::endl; } diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 79cb560..8fc8347 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -443,15 +443,20 @@ cmDependsFortran const char* src = info.Source.c_str(); // Write the include dependencies to the output stream. - internalDepends << obj << std::endl; + std::string obj_i = + this->LocalGenerator->Convert(obj, cmLocalGenerator::HOME_OUTPUT); + std::string obj_m = + this->LocalGenerator->ConvertToOutputFormat(obj_i, + cmLocalGenerator::MAKERULE); + internalDepends << obj_i << std::endl; internalDepends << " " << src << std::endl; for(std::set<std::string>::const_iterator i = info.Includes.begin(); i != info.Includes.end(); ++i) { - makeDepends << obj << ": " << + makeDepends << obj_m << ": " << this->LocalGenerator->Convert(*i, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE) + cmLocalGenerator::MAKERULE) << std::endl; internalDepends << " " << *i << std::endl; } @@ -482,10 +487,10 @@ cmDependsFortran proxy += ".mod.proxy"; proxy = this->LocalGenerator->Convert(proxy, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); + cmLocalGenerator::MAKERULE); // since we require some things add them to our list of requirements - makeDepends << obj << ".requires: " << proxy << std::endl; + makeDepends << obj_m << ".requires: " << proxy << std::endl; } // The object file should depend on timestamped files for the @@ -499,8 +504,8 @@ cmDependsFortran std::string stampFile = this->LocalGenerator->Convert(required->second, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); - makeDepends << obj << ": " << stampFile << "\n"; + cmLocalGenerator::MAKERULE); + makeDepends << obj_m << ": " << stampFile << "\n"; } else { @@ -512,8 +517,8 @@ cmDependsFortran module = this->LocalGenerator->Convert(module, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); - makeDepends << obj << ": " << module << "\n"; + cmLocalGenerator::MAKERULE); + makeDepends << obj_m << ": " << module << "\n"; } } } @@ -528,8 +533,8 @@ cmDependsFortran proxy += ".mod.proxy"; proxy = this->LocalGenerator->Convert(proxy, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); - makeDepends << proxy << ": " << obj << ".provides" << std::endl; + cmLocalGenerator::MAKERULE); + makeDepends << proxy << ": " << obj_m << ".provides" << std::endl; } // If any modules are provided then they must be converted to stamp files. @@ -537,7 +542,7 @@ cmDependsFortran { // Create a target to copy the module after the object file // changes. - makeDepends << obj << ".provides.build:\n"; + makeDepends << obj_m << ".provides.build:\n"; for(std::set<std::string>::const_iterator i = info.Provides.begin(); i != info.Provides.end(); ++i) { @@ -575,7 +580,7 @@ cmDependsFortran } // After copying the modules update the timestamp file so that // copying will not be done again until the source rebuilds. - makeDepends << "\t$(CMAKE_COMMAND) -E touch " << obj + makeDepends << "\t$(CMAKE_COMMAND) -E touch " << obj_m << ".provides.build\n"; // Make sure the module timestamp rule is evaluated by the time @@ -584,8 +589,8 @@ cmDependsFortran driver += "/build"; driver = this->LocalGenerator->Convert(driver, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); - makeDepends << driver << ": " << obj << ".provides.build\n"; + cmLocalGenerator::MAKERULE); + makeDepends << driver << ": " << obj_m << ".provides.build\n"; } return true; @@ -765,7 +770,11 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, const char* compilerId) { /* - gnu: + gnu >= 4.9: + A mod file is an ascii file compressed with gzip. + Compiling twice produces identical modules. + + gnu < 4.9: A mod file is an ascii file. <bar.mod> FORTRAN module created from /path/to/foo.f90 on Sun Dec 30 22:47:58 2007 @@ -821,21 +830,30 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile, */ if (strcmp(compilerId, "GNU") == 0 ) { - const char seq[1] = {'\n'}; - const int seqlen = 1; - - if(!cmDependsFortranStreamContainsSequence(finModFile, seq, seqlen)) + // GNU Fortran 4.9 and later compress .mod files with gzip + // but also do not include a date so we can fall through to + // compare them without skipping any prefix. + unsigned char hdr[2]; + bool okay = finModFile.read(reinterpret_cast<char*>(hdr), 2)? true:false; + finModFile.seekg(0); + if(!(okay && hdr[0] == 0x1f && hdr[1] == 0x8b)) { - // The module is of unexpected format. Assume it is different. - std::cerr << compilerId << " fortran module " << modFile - << " has unexpected format." << std::endl; - return true; - } + const char seq[1] = {'\n'}; + const int seqlen = 1; - if(!cmDependsFortranStreamContainsSequence(finStampFile, seq, seqlen)) - { - // The stamp must differ if the sequence is not contained. - return true; + if(!cmDependsFortranStreamContainsSequence(finModFile, seq, seqlen)) + { + // The module is of unexpected format. Assume it is different. + std::cerr << compilerId << " fortran module " << modFile + << " has unexpected format." << std::endl; + return true; + } + + if(!cmDependsFortranStreamContainsSequence(finStampFile, seq, seqlen)) + { + // The stamp must differ if the sequence is not contained. + return true; + } } } else if(strcmp(compilerId, "Intel") == 0) diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index 8d035af..3ff1017 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -113,7 +113,9 @@ bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os) switch (ht) { case cmDocumentation::Usage: - return this->PrintDocumentationUsage(os); + return this->PrintUsage(os); + case cmDocumentation::Help: + return this->PrintHelp(os); case cmDocumentation::Full: return this->PrintHelpFull(os); case cmDocumentation::OneManual: @@ -300,7 +302,7 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv, (strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "-H") == 0)) { - help.HelpType = cmDocumentation::Usage; + help.HelpType = cmDocumentation::Help; GET_OPT_ARGUMENT(help.Argument); help.Argument = cmSystemTools::LowerCase(help.Argument); // special case for single command @@ -841,7 +843,19 @@ bool cmDocumentation::PrintHelpListVariables(std::ostream& os) } //---------------------------------------------------------------------------- -bool cmDocumentation::PrintDocumentationUsage(std::ostream& os) +bool cmDocumentation::PrintUsage(std::ostream& os) +{ + std::map<std::string,cmDocumentationSection*>::iterator si; + si = this->AllSections.find("Usage"); + if(si != this->AllSections.end()) + { + this->Formatter.PrintSection(os, *si->second); + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmDocumentation::PrintHelp(std::ostream& os) { std::map<std::string,cmDocumentationSection*>::iterator si; si = this->AllSections.find("Usage"); diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index c98e48e..b72b5fe 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -102,6 +102,8 @@ private: bool PrintFiles(std::ostream& os, std::string const& pattern); bool PrintVersion(std::ostream& os); + bool PrintUsage(std::ostream& os); + bool PrintHelp(std::ostream& os); bool PrintHelpFull(std::ostream& os); bool PrintHelpOneManual(std::ostream& os); bool PrintHelpOneCommand(std::ostream& os); @@ -115,7 +117,6 @@ private: bool PrintHelpListProperties(std::ostream& os); bool PrintHelpListVariables(std::ostream& os); bool PrintHelpListPolicies(std::ostream& os); - bool PrintDocumentationUsage(std::ostream& os); bool PrintOldCustomModules(std::ostream& os); const char* GetNameString() const; diff --git a/Source/cmDocumentationFormatter.h b/Source/cmDocumentationFormatter.h index 61766b9..59513cc 100644 --- a/Source/cmDocumentationFormatter.h +++ b/Source/cmDocumentationFormatter.h @@ -26,7 +26,7 @@ public: /** Types of help provided. */ enum Type { - None, Version, Usage, Full, ListManuals, + None, Version, Usage, Help, Full, ListManuals, ListCommands, ListModules, ListProperties, ListVariables, ListPolicies, OneManual, OneCommand, OneModule, OneProperty, OneVariable, OnePolicy, OldCustomModules diff --git a/Source/cmExpandedCommandArgument.cxx b/Source/cmExpandedCommandArgument.cxx new file mode 100644 index 0000000..4477cf5 --- /dev/null +++ b/Source/cmExpandedCommandArgument.cxx @@ -0,0 +1,51 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 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 "cmExpandedCommandArgument.h" + +cmExpandedCommandArgument::cmExpandedCommandArgument(): + Quoted(false) +{ + +} + +cmExpandedCommandArgument::cmExpandedCommandArgument( + std::string const& value, bool quoted): + Value(value), Quoted(quoted) +{ + +} + +std::string const& cmExpandedCommandArgument::GetValue() const +{ + return this->Value; +} + +bool cmExpandedCommandArgument::WasQuoted() const +{ + return this->Quoted; +} + +bool cmExpandedCommandArgument::operator== (std::string const& value) const +{ + return this->Value == value; +} + +bool cmExpandedCommandArgument::empty() const +{ + return this->Value.empty(); +} + +const char* cmExpandedCommandArgument::c_str() const +{ + return this->Value.c_str(); +} diff --git a/Source/cmExpandedCommandArgument.h b/Source/cmExpandedCommandArgument.h new file mode 100644 index 0000000..f4e1517 --- /dev/null +++ b/Source/cmExpandedCommandArgument.h @@ -0,0 +1,45 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 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 cmExpandedCommandArgument_h +#define cmExpandedCommandArgument_h + +#include "cmStandardIncludes.h" + +/** \class cmExpandedCommandArgument + * \brief Represents an expanded command argument + * + * cmCommandArgument stores a string representing an expanded + * command argument and context information. + */ + +class cmExpandedCommandArgument +{ +public: + cmExpandedCommandArgument(); + cmExpandedCommandArgument(std::string const& value, bool quoted); + + std::string const& GetValue() const; + + bool WasQuoted() const; + + bool operator== (std::string const& value) const; + + bool empty() const; + + const char* c_str() const; + +private: + std::string Value; + bool Quoted; +}; + +#endif diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 9f5eee5..1f39d7a 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -865,15 +865,16 @@ cmExportFileGenerator } //---------------------------------------------------------------------------- +template <typename T> void cmExportFileGenerator ::SetImportLinkProperty(std::string const& suffix, cmTarget* target, const std::string& propName, - std::vector<std::string> const& entries, + std::vector<T> const& entries, ImportPropertyMap& properties, std::vector<std::string>& missingTargets - ) + ) { // Skip the property if there are no entries. if(entries.empty()) @@ -884,7 +885,7 @@ cmExportFileGenerator // Construct the property value. std::string link_entries; const char* sep = ""; - for(std::vector<std::string>::const_iterator li = entries.begin(); + for(typename std::vector<T>::const_iterator li = entries.begin(); li != entries.end(); ++li) { // Separate this from the previous entry. @@ -902,7 +903,6 @@ cmExportFileGenerator properties[prop] = link_entries; } - //---------------------------------------------------------------------------- void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os, const std::string& config) diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index abd8ad5..919924e 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -95,9 +95,11 @@ protected: std::string const& suffix, cmTarget* target, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); + + template <typename T> void SetImportLinkProperty(std::string const& suffix, cmTarget* target, const std::string& propName, - std::vector<std::string> const& entries, + std::vector<T> const& entries, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index 688d2eb..cb150a7 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -108,14 +108,12 @@ void cmExportLibraryDependenciesCommand::ConstFinalPass() const std::string targetEntry = target.GetName(); targetEntry += "_LIB_DEPENDS"; - // Construct the dependency variable value. It is safe to use - // the target GetLinkLibraries method here because this code is - // called at the end of configure but before generate so library - // dependencies have yet to be analyzed. Therefore the value - // will be the direct link dependencies. + // Construct the dependency variable value with the direct link + // dependencies. std::string valueOld; std::string valueNew; - cmTarget::LinkLibraryVectorType const& libs = target.GetLinkLibraries(); + cmTarget::LinkLibraryVectorType const& libs = + target.GetOriginalLinkLibraries(); for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin(); li != libs.end(); ++li) { diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index 6f76dc4..56a6edb 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -574,7 +574,7 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout, } } - const char* buildType = makefile->GetDefinition("CMAKE_BUILD_TYPE"); + std::string buildType = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); std::string location; if ( target->GetType()==cmTarget::OBJECT_LIBRARY) { diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index e23551e..1beb3fd 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -968,7 +968,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const continue; } std::vector<std::string> includeDirs; - const char *config = mf->GetDefinition("CMAKE_BUILD_TYPE"); + std::string config = mf->GetSafeDefinition("CMAKE_BUILD_TYPE"); (*it)->GetIncludeDirectories(includeDirs, l->second, "C", config); this->AppendIncludeDirectories(fout, includeDirs, emmited); } diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 655f3ba..1325cec 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -428,7 +428,8 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) arg_length_minimum, arg_length_maximum, arg__maximum, - arg_regex }; + arg_regex, + arg_encoding }; unsigned int minlen = 0; unsigned int maxlen = 0; int limit_input = -1; @@ -438,6 +439,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) bool have_regex = false; bool newline_consume = false; bool hex_conversion_enabled = true; + bool utf8_encoding = false; int arg_mode = arg_none; for(unsigned int i=3; i < args.size(); ++i) { @@ -475,6 +477,10 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) hex_conversion_enabled = false; arg_mode = arg_none; } + else if(args[i] == "ENCODING") + { + arg_mode = arg_encoding; + } else if(arg_mode == arg_limit_input) { if(sscanf(args[i].c_str(), "%d", &limit_input) != 1 || @@ -556,6 +562,22 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) have_regex = true; arg_mode = arg_none; } + else if(arg_mode == arg_encoding) + { + if(args[i] == "UTF-8") + { + utf8_encoding = true; + } + else + { + cmOStringStream e; + e << "STRINGS option ENCODING \"" + << args[i] << "\" not recognized."; + this->SetError(e.str()); + return false; + } + arg_mode = arg_none; + } else { cmOStringStream e; @@ -596,11 +618,75 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) int output_size = 0; std::vector<std::string> strings; std::string s; - int c; while((!limit_count || strings.size() < limit_count) && (limit_input < 0 || static_cast<int>(fin.tellg()) < limit_input) && - (c = fin.get(), fin)) + fin) { + std::string current_str; + + int c = fin.get(); + + if(c == '\r') + { + // Ignore CR character to make output always have UNIX newlines. + continue; + } + + else if((c >= 0x20 && c < 0x7F) || c == '\t' || + (c == '\n' && newline_consume)) + { + // This is an ASCII character that may be part of a string. + // Cast added to avoid compiler warning. Cast is ok because + // c is guaranteed to fit in char by the above if... + current_str += static_cast<char>(c); + } + else if(utf8_encoding) + { + // Check for UTF-8 encoded string (up to 4 octets) + static const unsigned char utf8_check_table[3][2] = + { + {0xE0, 0xC0}, + {0xF0, 0xE0}, + {0xF8, 0xF0}, + }; + + // how many octets are there? + unsigned int num_utf8_bytes = 0; + for(unsigned int j=0; num_utf8_bytes == 0 && j<3; j++) + { + if((c & utf8_check_table[j][0]) == utf8_check_table[j][1]) + num_utf8_bytes = j+2; + } + + // get subsequent octets and check that they are valid + for(unsigned int j=0; j<num_utf8_bytes; j++) + { + if(j != 0) + { + c = fin.get(); + if(!fin || (c & 0xC0) != 0x80) + { + fin.putback(static_cast<char>(c)); + break; + } + } + current_str += static_cast<char>(c); + } + + // if this was an invalid utf8 sequence, discard the data, and put + // back subsequent characters + if((current_str.length() != num_utf8_bytes)) + { + for(unsigned int j=0; j<current_str.size()-1; j++) + { + c = current_str[current_str.size() - 1 - j]; + fin.putback(static_cast<char>(c)); + } + current_str = ""; + } + } + + if(c == '\n' && !newline_consume) { // The current line has been terminated. Check if the current @@ -621,26 +707,13 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) // Reset the string to empty. s = ""; } - else if(c == '\r') - { - // Ignore CR character to make output always have UNIX newlines. - } - else if((c >= 0x20 && c < 0x7F) || c == '\t' || - (c == '\n' && newline_consume)) - { - // This is an ASCII character that may be part of a string. - // Cast added to avoid compiler warning. Cast is ok because - // c is guaranteed to fit in char by the above if... - s += static_cast<char>(c); - } - else + else if(current_str.empty()) { - // TODO: Support ENCODING option. See issue #10519. // A non-string character has been found. Check if the current // string matches the requirements. We require that the length // be at least one no matter what the user specified. if(s.length() >= minlen && s.length() >= 1 && - (!have_regex || regex.find(s.c_str()))) + (!have_regex || regex.find(s.c_str()))) { output_size += static_cast<int>(s.size()) + 1; if(limit_output >= 0 && output_size >= limit_output) @@ -654,10 +727,15 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) // Reset the string to empty. s = ""; } + else + { + s += current_str; + } + - // Terminate a string if the maximum length is reached. if(maxlen > 0 && s.size() == maxlen) { + // Terminate a string if the maximum length is reached. if(s.length() >= minlen && (!have_regex || regex.find(s.c_str()))) { @@ -1613,7 +1691,8 @@ bool cmFileCopier::InstallDirectory(const char* source, MatchProperties const& match_properties) { // Inform the user about this directory installation. - this->ReportCopy(destination, TypeDir, true); + this->ReportCopy(destination, TypeDir, + !cmSystemTools::FileIsDirectory(destination)); // Make sure the destination directory exists. if(!cmSystemTools::MakeDirectory(destination)) @@ -1704,6 +1783,9 @@ struct cmFileInstaller: public cmFileCopier cmFileCopier(command, "INSTALL"), InstallType(cmInstallType_FILES), Optional(false), + MessageAlways(false), + MessageLazy(false), + MessageNever(false), DestDirLength(0) { // Installation does not use source permissions by default. @@ -1725,6 +1807,9 @@ struct cmFileInstaller: public cmFileCopier protected: cmInstallType InstallType; bool Optional; + bool MessageAlways; + bool MessageLazy; + bool MessageNever; int DestDirLength; std::string Rename; @@ -1740,9 +1825,12 @@ protected: virtual void ReportCopy(const char* toFile, Type type, bool copy) { - std::string message = (copy? "Installing: " : "Up-to-date: "); - message += toFile; - this->Makefile->DisplayStatus(message.c_str(), -1); + if(!this->MessageNever && (copy || !this->MessageLazy)) + { + std::string message = (copy? "Installing: " : "Up-to-date: "); + message += toFile; + this->Makefile->DisplayStatus(message.c_str(), -1); + } if(type != TypeDir) { // Add the file to the manifest. @@ -1828,6 +1916,16 @@ bool cmFileInstaller::Parse(std::vector<std::string> const& args) return false; } + if(((this->MessageAlways?1:0) + + (this->MessageLazy?1:0) + + (this->MessageNever?1:0)) > 1) + { + this->FileCommand->SetError("INSTALL options MESSAGE_ALWAYS, " + "MESSAGE_LAZY, and MESSAGE_NEVER " + "are mutually exclusive."); + return false; + } + return true; } @@ -1879,6 +1977,42 @@ bool cmFileInstaller::CheckKeyword(std::string const& arg) this->Optional = true; } } + else if(arg == "MESSAGE_ALWAYS") + { + if(this->CurrentMatchRule) + { + this->NotAfterMatch(arg); + } + else + { + this->Doing = DoingNone; + this->MessageAlways = true; + } + } + else if(arg == "MESSAGE_LAZY") + { + if(this->CurrentMatchRule) + { + this->NotAfterMatch(arg); + } + else + { + this->Doing = DoingNone; + this->MessageLazy = true; + } + } + else if(arg == "MESSAGE_NEVER") + { + if(this->CurrentMatchRule) + { + this->NotAfterMatch(arg); + } + else + { + this->Doing = DoingNone; + this->MessageNever = true; + } + } else if(arg == "PERMISSIONS") { if(this->CurrentMatchRule) @@ -2057,23 +2191,26 @@ bool cmFileInstaller::HandleInstallDestination() this->DestDirLength = int(sdestdir.size()); } - if ( !cmSystemTools::FileExists(destination.c_str()) ) + if(this->InstallType != cmInstallType_DIRECTORY) { - if ( !cmSystemTools::MakeDirectory(destination.c_str()) ) + if ( !cmSystemTools::FileExists(destination.c_str()) ) { - std::string errstring = "cannot create directory: " + destination + + if ( !cmSystemTools::MakeDirectory(destination.c_str()) ) + { + std::string errstring = "cannot create directory: " + destination + ". Maybe need administrative privileges."; + this->FileCommand->SetError(errstring); + return false; + } + } + if ( !cmSystemTools::FileIsDirectory(destination.c_str()) ) + { + std::string errstring = "INSTALL destination: " + destination + + " is not a directory."; this->FileCommand->SetError(errstring); return false; } } - if ( !cmSystemTools::FileIsDirectory(destination.c_str()) ) - { - std::string errstring = "INSTALL destination: " + destination + - " is not a directory."; - this->FileCommand->SetError(errstring); - return false; - } return true; } @@ -3113,15 +3250,7 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) return false; } - struct stat st; - if(::stat(filename.c_str(), &st)) - { - std::string errStr = "UPLOAD cannot stat file '"; - errStr += filename + "'."; - this->SetError(errStr); - fclose(fin); - return false; - } + unsigned long file_size = cmsys::SystemTools::FileLength(filename.c_str()); ::CURL *curl; ::curl_global_init(CURL_GLOBAL_DEFAULT); @@ -3211,7 +3340,7 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) // and give the size of the upload (optional) res = ::curl_easy_setopt(curl, - CURLOPT_INFILESIZE, static_cast<long>(st.st_size)); + CURLOPT_INFILESIZE, static_cast<long>(file_size)); check_curl_result(res, "UPLOAD cannot set input file size: "); res = ::curl_easy_perform(curl); diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 028d229..7fc1464 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -97,6 +97,7 @@ const char *cmCompiledGeneratorExpression::Evaluate( context.Quiet = quiet; context.HadError = false; context.HadContextSensitiveCondition = false; + context.HadHeadSensitiveCondition = false; context.HeadTarget = headTarget; context.EvaluateForBuildsystem = this->EvaluateForBuildsystem; context.CurrentTarget = currentTarget ? currentTarget : headTarget; @@ -124,6 +125,7 @@ const char *cmCompiledGeneratorExpression::Evaluate( if (!context.HadError) { this->HadContextSensitiveCondition = context.HadContextSensitiveCondition; + this->HadHeadSensitiveCondition = context.HadHeadSensitiveCondition; } this->DependTargets = context.DependTargets; @@ -137,6 +139,7 @@ cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( const std::string& input) : Backtrace(backtrace), Input(input), HadContextSensitiveCondition(false), + HadHeadSensitiveCondition(false), EvaluateForBuildsystem(false) { cmGeneratorExpressionLexer l; @@ -469,12 +472,11 @@ std::string::size_type cmGeneratorExpression::Find(const std::string &input) //---------------------------------------------------------------------------- bool cmGeneratorExpression::IsValidTargetName(const std::string &input) { - cmsys::RegularExpression targetNameValidator; // The ':' is supported to allow use with IMPORTED targets. At least // Qt 4 and 5 IMPORTED targets use ':' as the namespace delimiter. - targetNameValidator.compile("^[A-Za-z0-9_.:+-]+$"); + static cmsys::RegularExpression targetNameValidator("^[A-Za-z0-9_.:+-]+$"); - return targetNameValidator.find(input.c_str()); + return targetNameValidator.find(input); } //---------------------------------------------------------------------------- diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 324d23c..b952520 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -111,6 +111,10 @@ public: { return this->HadContextSensitiveCondition; } + bool GetHadHeadSensitiveCondition() const + { + return this->HadHeadSensitiveCondition; + } void SetEvaluateForBuildsystem(bool eval) { @@ -141,6 +145,7 @@ private: MaxLanguageStandard; mutable std::string Output; mutable bool HadContextSensitiveCondition; + mutable bool HadHeadSensitiveCondition; bool EvaluateForBuildsystem; }; diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index c54922d..c1478df 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -394,16 +394,14 @@ struct CompilerIdNode : public cmGeneratorExpressionNode cmGeneratorExpressionDAGChecker *, const std::string &lang) const { - const char *compilerId = context->Makefile ? - context->Makefile->GetSafeDefinition( - "CMAKE_" + lang + "_COMPILER_ID") : ""; + const char *compilerId = + context->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID"); if (parameters.size() == 0) { return compilerId ? compilerId : ""; } - cmsys::RegularExpression compilerIdValidator; - compilerIdValidator.compile("^[A-Za-z0-9_]*$"); - if (!compilerIdValidator.find(parameters.begin()->c_str())) + static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$"); + if (!compilerIdValidator.find(*parameters.begin())) { reportError(context, content->GetOriginalExpression(), "Expression syntax not recognized."); @@ -501,17 +499,15 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode cmGeneratorExpressionDAGChecker *, const std::string &lang) const { - const char *compilerVersion = context->Makefile ? - context->Makefile->GetSafeDefinition( - "CMAKE_" + lang + "_COMPILER_VERSION") : ""; + const char *compilerVersion = context->Makefile->GetSafeDefinition( + "CMAKE_" + lang + "_COMPILER_VERSION"); if (parameters.size() == 0) { return compilerVersion ? compilerVersion : ""; } - cmsys::RegularExpression compilerIdValidator; - compilerIdValidator.compile("^[0-9\\.]*$"); - if (!compilerIdValidator.find(parameters.begin()->c_str())) + static cmsys::RegularExpression compilerIdValidator("^[0-9\\.]*$"); + if (!compilerIdValidator.find(*parameters.begin())) { reportError(context, content->GetOriginalExpression(), "Expression syntax not recognized."); @@ -585,9 +581,8 @@ struct PlatformIdNode : public cmGeneratorExpressionNode const GeneratorExpressionContent *, cmGeneratorExpressionDAGChecker *) const { - const char *platformId = context->Makefile ? - context->Makefile->GetSafeDefinition( - "CMAKE_SYSTEM_NAME") : ""; + const char *platformId = + context->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME"); if (parameters.size() == 0) { return platformId ? platformId : ""; @@ -711,9 +706,8 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode { return configurationNode.Evaluate(parameters, context, content, 0); } - cmsys::RegularExpression configValidator; - configValidator.compile("^[A-Za-z0-9_]*$"); - if (!configValidator.find(parameters.begin()->c_str())) + static cmsys::RegularExpression configValidator("^[A-Za-z0-9_]*$"); + if (!configValidator.find(*parameters.begin())) { reportError(context, content->GetOriginalExpression(), "Expression syntax not recognized."); @@ -802,66 +796,55 @@ static const char* targetPropertyTransitiveWhitelist[] = { #undef TRANSITIVE_PROPERTY_NAME -std::string getLinkedTargetsContent(const std::vector<cmTarget*> &targets, - cmTarget const* target, - cmTarget const* headTarget, - cmGeneratorExpressionContext *context, - cmGeneratorExpressionDAGChecker *dagChecker, - const std::string &interfacePropertyName) +template <typename T> +std::string +getLinkedTargetsContent( + std::vector<T> const &libraries, + cmTarget const* target, + cmTarget const* headTarget, + cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *dagChecker, + const std::string &interfacePropertyName) { - cmGeneratorExpression ge(&context->Backtrace); - + std::string linkedTargetsContent; std::string sep; std::string depString; - for (std::vector<cmTarget*>::const_iterator - it = targets.begin(); - it != targets.end(); ++it) + for (typename std::vector<T>::const_iterator it = libraries.begin(); + it != libraries.end(); ++it) { - if (*it == target) - { - // Broken code can have a target in its own link interface. - // Don't follow such link interface entries so as not to create a - // self-referencing loop. - continue; + // Broken code can have a target in its own link interface. + // Don't follow such link interface entries so as not to create a + // self-referencing loop. + if (it->Target && it->Target != target) + { + depString += + sep + "$<TARGET_PROPERTY:" + + it->Target->GetName() + "," + interfacePropertyName + ">"; + sep = ";"; } - depString += - sep + "$<TARGET_PROPERTY:" + - (*it)->GetName() + "," + interfacePropertyName + ">"; - sep = ";"; } - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(depString); - std::string linkedTargetsContent = cge->Evaluate(context->Makefile, - context->Config, - context->Quiet, - headTarget, - target, - dagChecker); - if (cge->GetHadContextSensitiveCondition()) + if(!depString.empty()) { - context->HadContextSensitiveCondition = true; - } - return linkedTargetsContent; -} - -std::string getLinkedTargetsContent(const std::vector<std::string> &libraries, - cmTarget const* target, - cmTarget const* headTarget, - cmGeneratorExpressionContext *context, - cmGeneratorExpressionDAGChecker *dagChecker, - const std::string &interfacePropertyName) -{ - std::vector<cmTarget*> tgts; - for (std::vector<std::string>::const_iterator - it = libraries.begin(); - it != libraries.end(); ++it) - { - if (cmTarget *tgt = context->Makefile->FindTargetToUse(*it)) + cmGeneratorExpression ge(&context->Backtrace); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(depString); + linkedTargetsContent = cge->Evaluate(target->GetMakefile(), + context->Config, + context->Quiet, + headTarget, + target, + dagChecker); + if (cge->GetHadContextSensitiveCondition()) { - tgts.push_back(tgt); + context->HadContextSensitiveCondition = true; + } + if (cge->GetHadHeadSensitiveCondition()) + { + context->HadHeadSensitiveCondition = true; } } - return getLinkedTargetsContent(tgts, target, headTarget, context, - dagChecker, interfacePropertyName); + linkedTargetsContent = + cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent); + return linkedTargetsContent; } //---------------------------------------------------------------------------- @@ -884,12 +867,15 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode "$<TARGET_PROPERTY:...> expression requires one or two parameters"); return std::string(); } - cmsys::RegularExpression propertyNameValidator; - propertyNameValidator.compile("^[A-Za-z0-9_]+$"); + static cmsys::RegularExpression propertyNameValidator("^[A-Za-z0-9_]+$"); cmTarget const* target = context->HeadTarget; std::string propertyName = *parameters.begin(); + if (parameters.size() == 1) + { + context->HadHeadSensitiveCondition = true; + } if (!target && parameters.size() == 1) { reportError(context, content->GetOriginalExpression(), @@ -973,7 +959,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode return std::string(); } - if (!propertyNameValidator.find(propertyName.c_str())) + if (!propertyNameValidator.find(propertyName)) { ::reportError(context, content->GetOriginalExpression(), "Property name not supported."); @@ -1031,6 +1017,19 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode { if (dagCheckerParent->EvaluatingLinkLibraries()) { +#define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \ + (#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) || + if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_COMPARE) + false) + { + reportError(context, content->GetOriginalExpression(), + "$<TARGET_PROPERTY:...> expression in link libraries " + "evaluation depends on target property which is transitive " + "over the link libraries, creating a recursion."); + return std::string(); + } +#undef TRANSITIVE_PROPERTY_COMPARE + if(!prop) { return std::string(); @@ -1045,19 +1044,25 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD( ASSERT_TRANSITIVE_PROPERTY_METHOD) false); - } #undef ASSERT_TRANSITIVE_PROPERTY_METHOD + } } std::string linkedTargetsContent; std::string interfacePropertyName; + bool isInterfaceProperty = false; #define POPULATE_INTERFACE_PROPERTY_NAME(prop) \ - if (propertyName == #prop || propertyName == "INTERFACE_" #prop) \ + if (propertyName == #prop) \ { \ interfacePropertyName = "INTERFACE_" #prop; \ } \ + else if (propertyName == "INTERFACE_" #prop) \ + { \ + interfacePropertyName = "INTERFACE_" #prop; \ + isInterfaceProperty = true; \ + } \ else CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(POPULATE_INTERFACE_PROPERTY_NAME) @@ -1073,50 +1078,34 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode } } #undef POPULATE_INTERFACE_PROPERTY_NAME - - cmTarget const* headTarget = context->HeadTarget + cmTarget const* headTarget = context->HeadTarget && isInterfaceProperty ? context->HeadTarget : target; - const char * const *transBegin = - cmArrayBegin(targetPropertyTransitiveWhitelist) + 1; - const char * const *transEnd = - cmArrayEnd(targetPropertyTransitiveWhitelist); - - if (std::find_if(transBegin, transEnd, - cmStrCmp(propertyName)) != transEnd) + if(isInterfaceProperty) { - - std::vector<cmTarget*> tgts; - target->GetTransitivePropertyTargets(context->Config, - headTarget, tgts); - if (!tgts.empty()) + if(cmTarget::LinkInterfaceLibraries const* iface = + target->GetLinkInterfaceLibraries(context->Config, headTarget, true)) { linkedTargetsContent = - getLinkedTargetsContent(tgts, target, - headTarget, - context, &dagChecker, - interfacePropertyName); + getLinkedTargetsContent(iface->Libraries, target, + headTarget, + context, &dagChecker, + interfacePropertyName); } } - else if (std::find_if(transBegin, transEnd, - cmStrCmp(interfacePropertyName)) != transEnd) + else if(!interfacePropertyName.empty()) { - const cmTarget::LinkImplementation *impl - = target->GetLinkImplementationLibraries(context->Config, - headTarget); - if(impl) + if(cmTarget::LinkImplementationLibraries const* impl = + target->GetLinkImplementationLibraries(context->Config)) { linkedTargetsContent = - getLinkedTargetsContent(impl->Libraries, target, - headTarget, - context, &dagChecker, - interfacePropertyName); + getLinkedTargetsContent(impl->Libraries, target, + target, + context, &dagChecker, + interfacePropertyName); } } - linkedTargetsContent = - cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent); - if (!prop) { if (target->IsImported() @@ -1190,31 +1179,31 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode return propContent ? propContent : ""; } } - for (size_t i = 1; - i < cmArraySize(targetPropertyTransitiveWhitelist); - ++i) + if(!interfacePropertyName.empty()) { - if (targetPropertyTransitiveWhitelist[i] == interfacePropertyName) - { - cmGeneratorExpression ge(&context->Backtrace); - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop); - std::string result = cge->Evaluate(context->Makefile, + cmGeneratorExpression ge(&context->Backtrace); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop); + cge->SetEvaluateForBuildsystem(context->EvaluateForBuildsystem); + std::string result = cge->Evaluate(context->Makefile, context->Config, context->Quiet, headTarget, target, &dagChecker); - if (cge->GetHadContextSensitiveCondition()) - { - context->HadContextSensitiveCondition = true; - } - if (!linkedTargetsContent.empty()) - { - result += (result.empty() ? "" : ";") + linkedTargetsContent; - } - return result; + if (cge->GetHadContextSensitiveCondition()) + { + context->HadContextSensitiveCondition = true; + } + if (cge->GetHadHeadSensitiveCondition()) + { + context->HadHeadSensitiveCondition = true; + } + if (!linkedTargetsContent.empty()) + { + result += (result.empty() ? "" : ";") + linkedTargetsContent; } + return result; } return prop; } @@ -1333,6 +1322,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode "not be used with add_custom_command or add_custom_target."); return std::string(); } + context->HadHeadSensitiveCondition = true; typedef std::map<std::string, std::vector<std::string> > LangMap; static LangMap availableFeatures; @@ -1466,6 +1456,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode } context->HadContextSensitiveCondition = true; + context->HadHeadSensitiveCondition = true; for (size_t i = 1; i < cmArraySize(targetPolicyWhitelist); ++i) { @@ -1529,7 +1520,17 @@ static const struct InstallPrefixNode : public cmGeneratorExpressionNode } installPrefixNode; //---------------------------------------------------------------------------- -template<bool linker, bool soname> +class ArtifactNameTag; +class ArtifactLinkerTag; +class ArtifactSonameTag; +class ArtifactPdbTag; + +class ArtifactPathTag; +class ArtifactDirTag; +class ArtifactNameTag; + +//---------------------------------------------------------------------------- +template<typename ArtifactT> struct TargetFilesystemArtifactResultCreator { static std::string Create(cmTarget* target, @@ -1539,7 +1540,7 @@ struct TargetFilesystemArtifactResultCreator //---------------------------------------------------------------------------- template<> -struct TargetFilesystemArtifactResultCreator<false, true> +struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag> { static std::string Create(cmTarget* target, cmGeneratorExpressionContext *context, @@ -1569,7 +1570,45 @@ struct TargetFilesystemArtifactResultCreator<false, true> //---------------------------------------------------------------------------- template<> -struct TargetFilesystemArtifactResultCreator<true, false> +struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag> +{ + static std::string Create(cmTarget* target, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content) + { + std::string language = target->GetLinkerLanguage(context->Config); + + std::string pdbSupportVar = "CMAKE_" + language + "_LINKER_SUPPORTS_PDB"; + + if(!context->Makefile->IsOn(pdbSupportVar)) + { + ::reportError(context, content->GetOriginalExpression(), + "TARGET_PDB_FILE is not supported by the target linker."); + return std::string(); + } + + cmTarget::TargetType targetType = target->GetType(); + + if(targetType != cmTarget::SHARED_LIBRARY && + targetType != cmTarget::MODULE_LIBRARY && + targetType != cmTarget::EXECUTABLE) + { + ::reportError(context, content->GetOriginalExpression(), + "TARGET_PDB_FILE is allowed only for " + "targets with linker created artifacts."); + return std::string(); + } + + std::string result = target->GetPDBDirectory(context->Config); + result += "/"; + result += target->GetPDBName(context->Config); + return result; + } +}; + +//---------------------------------------------------------------------------- +template<> +struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag> { static std::string Create(cmTarget* target, cmGeneratorExpressionContext *context, @@ -1590,7 +1629,7 @@ struct TargetFilesystemArtifactResultCreator<true, false> //---------------------------------------------------------------------------- template<> -struct TargetFilesystemArtifactResultCreator<false, false> +struct TargetFilesystemArtifactResultCreator<ArtifactNameTag> { static std::string Create(cmTarget* target, cmGeneratorExpressionContext *context, @@ -1602,7 +1641,7 @@ struct TargetFilesystemArtifactResultCreator<false, false> //---------------------------------------------------------------------------- -template<bool dirQual, bool nameQual> +template<typename ArtifactT> struct TargetFilesystemArtifactResultGetter { static std::string Get(const std::string &result); @@ -1610,7 +1649,7 @@ struct TargetFilesystemArtifactResultGetter //---------------------------------------------------------------------------- template<> -struct TargetFilesystemArtifactResultGetter<false, true> +struct TargetFilesystemArtifactResultGetter<ArtifactNameTag> { static std::string Get(const std::string &result) { return cmSystemTools::GetFilenameName(result); } @@ -1618,7 +1657,7 @@ struct TargetFilesystemArtifactResultGetter<false, true> //---------------------------------------------------------------------------- template<> -struct TargetFilesystemArtifactResultGetter<true, false> +struct TargetFilesystemArtifactResultGetter<ArtifactDirTag> { static std::string Get(const std::string &result) { return cmSystemTools::GetFilenamePath(result); } @@ -1626,14 +1665,14 @@ struct TargetFilesystemArtifactResultGetter<true, false> //---------------------------------------------------------------------------- template<> -struct TargetFilesystemArtifactResultGetter<false, false> +struct TargetFilesystemArtifactResultGetter<ArtifactPathTag> { static std::string Get(const std::string &result) { return result; } }; //---------------------------------------------------------------------------- -template<bool linker, bool soname, bool dirQual, bool nameQual> +template<typename ArtifactT, typename ComponentT> struct TargetFilesystemArtifact : public cmGeneratorExpressionNode { TargetFilesystemArtifact() {} @@ -1681,7 +1720,7 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode context->AllTargets.insert(target); std::string result = - TargetFilesystemArtifactResultCreator<linker, soname>::Create( + TargetFilesystemArtifactResultCreator<ArtifactT>::Create( target, context, content); @@ -1690,29 +1729,35 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode return std::string(); } return - TargetFilesystemArtifactResultGetter<dirQual, nameQual>::Get(result); + TargetFilesystemArtifactResultGetter<ComponentT>::Get(result); } }; //---------------------------------------------------------------------------- +template<typename ArtifactT> +struct TargetFilesystemArtifactNodeGroup +{ + TargetFilesystemArtifactNodeGroup() + { + } + + TargetFilesystemArtifact<ArtifactT, ArtifactPathTag> File; + TargetFilesystemArtifact<ArtifactT, ArtifactNameTag> FileName; + TargetFilesystemArtifact<ArtifactT, ArtifactDirTag> FileDir; +}; + +//---------------------------------------------------------------------------- static const -TargetFilesystemArtifact<false, false, false, false> targetFileNode; -static const -TargetFilesystemArtifact<true, false, false, false> targetLinkerFileNode; -static const -TargetFilesystemArtifact<false, true, false, false> targetSoNameFileNode; -static const -TargetFilesystemArtifact<false, false, false, true> targetFileNameNode; -static const -TargetFilesystemArtifact<true, false, false, true> targetLinkerFileNameNode; -static const -TargetFilesystemArtifact<false, true, false, true> targetSoNameFileNameNode; +TargetFilesystemArtifactNodeGroup<ArtifactNameTag> targetNodeGroup; + static const -TargetFilesystemArtifact<false, false, true, false> targetFileDirNode; +TargetFilesystemArtifactNodeGroup<ArtifactLinkerTag> targetLinkerNodeGroup; + static const -TargetFilesystemArtifact<true, false, true, false> targetLinkerFileDirNode; +TargetFilesystemArtifactNodeGroup<ArtifactSonameTag> targetSoNameNodeGroup; + static const -TargetFilesystemArtifact<false, true, true, false> targetSoNameFileDirNode; +TargetFilesystemArtifactNodeGroup<ArtifactPdbTag> targetPdbNodeGroup; //---------------------------------------------------------------------------- static const @@ -1738,15 +1783,18 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) nodeMap["COMPILE_FEATURES"] = &compileFeaturesNode; nodeMap["CONFIGURATION"] = &configurationNode; nodeMap["CONFIG"] = &configurationTestNode; - nodeMap["TARGET_FILE"] = &targetFileNode; - nodeMap["TARGET_LINKER_FILE"] = &targetLinkerFileNode; - nodeMap["TARGET_SONAME_FILE"] = &targetSoNameFileNode; - nodeMap["TARGET_FILE_NAME"] = &targetFileNameNode; - nodeMap["TARGET_LINKER_FILE_NAME"] = &targetLinkerFileNameNode; - nodeMap["TARGET_SONAME_FILE_NAME"] = &targetSoNameFileNameNode; - nodeMap["TARGET_FILE_DIR"] = &targetFileDirNode; - nodeMap["TARGET_LINKER_FILE_DIR"] = &targetLinkerFileDirNode; - nodeMap["TARGET_SONAME_FILE_DIR"] = &targetSoNameFileDirNode; + nodeMap["TARGET_FILE"] = &targetNodeGroup.File; + nodeMap["TARGET_LINKER_FILE"] = &targetLinkerNodeGroup.File; + nodeMap["TARGET_SONAME_FILE"] = &targetSoNameNodeGroup.File; + nodeMap["TARGET_PDB_FILE"] = &targetPdbNodeGroup.File; + nodeMap["TARGET_FILE_NAME"] = &targetNodeGroup.FileName; + nodeMap["TARGET_LINKER_FILE_NAME"] = &targetLinkerNodeGroup.FileName; + nodeMap["TARGET_SONAME_FILE_NAME"] = &targetSoNameNodeGroup.FileName; + nodeMap["TARGET_PDB_FILE_NAME"] = &targetPdbNodeGroup.FileName; + nodeMap["TARGET_FILE_DIR"] = &targetNodeGroup.FileDir; + nodeMap["TARGET_LINKER_FILE_DIR"] = &targetLinkerNodeGroup.FileDir; + nodeMap["TARGET_SONAME_FILE_DIR"] = &targetSoNameNodeGroup.FileDir; + nodeMap["TARGET_PDB_FILE_DIR"] = &targetPdbNodeGroup.FileDir; nodeMap["STREQUAL"] = &strEqualNode; nodeMap["EQUAL"] = &equalNode; nodeMap["LOWER_CASE"] = &lowerCaseNode; diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index 0ffb860..8a529e8 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -41,6 +41,7 @@ struct cmGeneratorExpressionContext bool Quiet; bool HadError; bool HadContextSensitiveCondition; + bool HadHeadSensitiveCondition; bool EvaluateForBuildsystem; }; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index a7576ed..14b5a92 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -38,7 +38,8 @@ void reportBadObjLib(std::vector<cmSourceFile*> const& badObjLib, { e << " " << (*i)->GetLocation().GetName() << "\n"; } - e << "but may contain only headers and sources that compile."; + e << "but may contain only sources that compile, header files, and " + "other files that would not affect linking of a normal library."; cm->IssueMessage(cmake::FATAL_ERROR, e.str(), target->GetBacktrace()); } @@ -52,6 +53,8 @@ struct ExternalObjectsTag {}; struct IDLSourcesTag {}; struct ResxTag {}; struct ModuleDefinitionFileTag {}; +struct AppManifestTag{}; +struct CertificatesTag{}; #if !defined(_MSC_VER) || _MSC_VER >= 1310 template<typename Tag, typename OtherTag> @@ -194,6 +197,14 @@ struct TagVisitor { DoAccept<IsSameTag<Tag, ResxTag>::Result>::Do(this->Data, sf); } + else if (ext == "appxmanifest") + { + DoAccept<IsSameTag<Tag, AppManifestTag>::Result>::Do(this->Data, sf); + } + else if (ext == "pfx") + { + DoAccept<IsSameTag<Tag, CertificatesTag>::Result>::Do(this->Data, sf); + } else if(this->Header.find(sf->GetFullPath().c_str())) { DoAccept<IsSameTag<Tag, HeaderSourcesTag>::Result>::Do(this->Data, sf); @@ -205,10 +216,6 @@ struct TagVisitor else { DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf); - if(this->IsObjLib && ext != "txt") - { - this->BadObjLibFiles.push_back(sf); - } } } }; @@ -252,7 +259,7 @@ cmGeneratorTarget::GetSourceDepends(cmSourceFile const* sf) const return 0; } -static void handleSystemIncludesDep(cmMakefile *mf, cmTarget* depTgt, +static void handleSystemIncludesDep(cmMakefile *mf, cmTarget const* depTgt, const std::string& config, cmTarget *headTarget, cmGeneratorExpressionDAGChecker *dagChecker, @@ -432,6 +439,24 @@ void cmGeneratorTarget } //---------------------------------------------------------------------------- +void +cmGeneratorTarget +::GetAppManifest(std::vector<cmSourceFile const*>& data, + const std::string& config) const +{ + IMPLEMENT_VISIT(AppManifest); +} + +//---------------------------------------------------------------------------- +void +cmGeneratorTarget +::GetCertificates(std::vector<cmSourceFile const*>& data, + const std::string& config) const +{ + IMPLEMENT_VISIT(Certificates); +} + +//---------------------------------------------------------------------------- bool cmGeneratorTarget::IsSystemIncludeDirectory(const std::string& dir, const std::string& config) const { @@ -448,13 +473,6 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(const std::string& dir, if (iter == this->SystemIncludesCache.end()) { - cmTarget::LinkImplementation const* impl - = this->Target->GetLinkImplementation(config, this->Target); - if(!impl) - { - return false; - } - cmGeneratorExpressionDAGChecker dagChecker( this->GetName(), "SYSTEM_INCLUDE_DIRECTORIES", 0, 0); @@ -474,35 +492,15 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(const std::string& dir, &dagChecker), result); } - std::set<cmTarget*> uniqueDeps; - for(std::vector<std::string>::const_iterator li = impl->Libraries.begin(); - li != impl->Libraries.end(); ++li) + std::vector<cmTarget const*> const& deps = + this->Target->GetLinkImplementationClosure(config); + for(std::vector<cmTarget const*>::const_iterator + li = deps.begin(), le = deps.end(); li != le; ++li) { - cmTarget* tgt = this->Makefile->FindTargetToUse(*li); - if (!tgt) - { - continue; - } - - if (uniqueDeps.insert(tgt).second) - { - handleSystemIncludesDep(this->Makefile, tgt, config, this->Target, - &dagChecker, result, excludeImported); - - std::vector<cmTarget*> deps; - tgt->GetTransitivePropertyTargets(config, this->Target, deps); - - for(std::vector<cmTarget*>::const_iterator di = deps.begin(); - di != deps.end(); ++di) - { - if (uniqueDeps.insert(*di).second) - { - handleSystemIncludesDep(this->Makefile, *di, config, this->Target, - &dagChecker, result, excludeImported); - } - } - } + handleSystemIncludesDep(this->Makefile, *li, config, this->Target, + &dagChecker, result, excludeImported); } + std::set<std::string> unique; for(std::vector<std::string>::iterator li = result.begin(); li != result.end(); ++li) @@ -521,9 +519,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(const std::string& dir, iter = this->SystemIncludesCache.insert(entry).first; } - std::string dirString = dir; - return std::binary_search(iter->second.begin(), iter->second.end(), - dirString); + return std::binary_search(iter->second.begin(), iter->second.end(), dir); } //---------------------------------------------------------------------------- diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 29aa410..2083b88 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -54,6 +54,10 @@ public: const std::string& config) const; void GetExpectedResxHeaders(std::set<std::string>&, const std::string& config) const; + void GetAppManifest(std::vector<cmSourceFile const*>&, + const std::string& config) const; + void GetCertificates(std::vector<cmSourceFile const*>&, + const std::string& config) const; void ComputeObjectMapping(); diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx index 8a96289..7667a85 100644 --- a/Source/cmGetSourceFilePropertyCommand.cxx +++ b/Source/cmGetSourceFilePropertyCommand.cxx @@ -29,7 +29,7 @@ bool cmGetSourceFilePropertyCommand // for the location we must create a source file first if (!sf && args[2] == "LOCATION") { - sf = this->Makefile->GetOrCreateSource(file); + sf = this->Makefile->CreateSource(file); } if(sf) { diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h index 470dea4..120d2f8 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.h +++ b/Source/cmGlobalBorlandMakefileGenerator.h @@ -39,7 +39,7 @@ public: virtual cmLocalGenerator *CreateLocalGenerator(); /** - * Try to determine system infomation such as shared library + * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ virtual void EnableLanguage(std::vector<std::string>const& languages, diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 6c8be72..ae0e807 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -76,18 +76,46 @@ cmGlobalGenerator::~cmGlobalGenerator() } } +bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p, + cmMakefile* mf) +{ + if(p.empty()) + { + return true; + } + else + { + cmOStringStream e; + e << + "Generator\n" + " " << this->GetName() << "\n" + "does not support platform specification, but platform\n" + " " << p << "\n" + "was specified."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } +} + bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, cmMakefile* mf) { - cmOStringStream e; - e << - "Generator\n" - " " << this->GetName() << "\n" - "does not support toolset specification, but toolset\n" - " " << ts << "\n" - "was specified."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; + if(ts.empty()) + { + return true; + } + else + { + cmOStringStream e; + e << + "Generator\n" + " " << this->GetName() << "\n" + "does not support toolset specification, but toolset\n" + " " << ts << "\n" + "was specified."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } } std::string cmGlobalGenerator::SelectMakeProgram( @@ -148,8 +176,6 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang, { return; } - std::string doc = lang; - doc += " compiler."; const char* cname = this->GetCMakeInstance()-> GetCacheManager()->GetCacheValue(langComp); std::string changeVars; @@ -186,8 +212,6 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang, changeVars.c_str()); } } - mf->AddCacheDefinition(langComp, path.c_str(), - doc.c_str(), cmCacheManager::FILEPATH); } void cmGlobalGenerator::AddBuildExportSet(cmExportBuildFileGenerator* gen) @@ -294,7 +318,7 @@ void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf) // will run xcodebuild and if it sees the error text file busy // it will stop forwarding output, and let the build finish. // Then it will retry the build. It will continue this - // untill no text file busy errors occur. + // until no text file busy errors occur. std::string cmakexbuild = this->CMakeInstance->GetCacheManager()->GetCacheValue("CMAKE_COMMAND"); cmakexbuild = cmakexbuild.substr(0, cmakexbuild.length()-5); @@ -414,7 +438,8 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, // try and load the CMakeSystem.cmake if it is there std::string fpath = rootBin; - if(!mf->GetDefinition("CMAKE_SYSTEM_LOADED")) + bool const readCMakeSystem = !mf->GetDefinition("CMAKE_SYSTEM_LOADED"); + if(readCMakeSystem) { fpath += "/CMakeSystem.cmake"; if(cmSystemTools::FileExists(fpath.c_str())) @@ -448,13 +473,31 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, mf->ReadListFile(0,fpath.c_str()); } - // Tell the generator about the toolset, if any. - std::string toolset = mf->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET"); - if(!toolset.empty() && - !this->SetGeneratorToolset(toolset, mf)) + if(readCMakeSystem) { - cmSystemTools::SetFatalErrorOccured(); - return; + // Tell the generator about the target system. + std::string system = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME"); + if(!this->SetSystemName(system, mf)) + { + cmSystemTools::SetFatalErrorOccured(); + return; + } + + // Tell the generator about the platform, if any. + std::string platform = mf->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM"); + if(!this->SetGeneratorPlatform(platform, mf)) + { + cmSystemTools::SetFatalErrorOccured(); + return; + } + + // Tell the generator about the toolset, if any. + std::string toolset = mf->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET"); + if(!this->SetGeneratorToolset(toolset, mf)) + { + cmSystemTools::SetFatalErrorOccured(); + return; + } } // **** Load the system specific initialization if not yet loaded @@ -463,8 +506,8 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, fpath = mf->GetModulesFile("CMakeSystemSpecificInitialize.cmake"); if(!mf->ReadListFile(0,fpath.c_str())) { - cmSystemTools::Error("Could not find cmake module file: ", - fpath.c_str()); + cmSystemTools::Error("Could not find cmake module file: " + "CMakeSystemSpecificInitialize.cmake"); } } @@ -532,7 +575,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, if(!mf->ReadListFile(0,determineFile.c_str())) { cmSystemTools::Error("Could not find cmake module file: ", - determineFile.c_str()); + determineCompiler.c_str()); } needTestLanguage[lang] = true; // Some generators like visual studio should not use the env variables @@ -584,8 +627,8 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake"); if(!mf->ReadListFile(0,fpath.c_str())) { - cmSystemTools::Error("Could not find cmake module file: ", - fpath.c_str()); + cmSystemTools::Error("Could not find cmake module file: " + "CMakeSystemSpecificInformation.cmake"); } } // loop over languages again loading CMake(LANG)Information.cmake @@ -616,7 +659,8 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, "No " << compilerName << " could be found.\n" ; } - else if(strcmp(lang, "RC") != 0) + else if(strcmp(lang, "RC") != 0 && + strcmp(lang, "ASM_MASM") != 0) { if(!cmSystemTools::FileIsFullPath(compilerFile)) { @@ -700,7 +744,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, if(!mf->ReadListFile(0,ifpath.c_str())) { cmSystemTools::Error("Could not find cmake module file: ", - ifpath.c_str()); + testLang.c_str()); } std::string compilerWorks = "CMAKE_"; compilerWorks += lang; @@ -840,6 +884,14 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(cmMakefile* mf, case cmPolicies::OLD: // OLD behavior is to convert QCC to GNU. mf->AddDefinition(compilerIdVar, "GNU"); + if(lang == "C") + { + mf->AddDefinition("CMAKE_COMPILER_IS_GNUCC", "1"); + } + else if(lang == "CXX") + { + mf->AddDefinition("CMAKE_COMPILER_IS_GNUCXX", "1"); + } break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: @@ -956,9 +1008,9 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l, if (sscanf(linkerPref, "%d", &preference)!=1) { // backward compatibility: before 2.6 LINKER_PREFERENCE - // was either "None" or "Prefered", and only the first character was + // was either "None" or "Preferred", and only the first character was // tested. So if there is a custom language out there and it is - // "Prefered", set its preference high + // "Preferred", set its preference high if (linkerPref[0]=='P') { preference = 100; @@ -1045,36 +1097,6 @@ void cmGlobalGenerator::ClearEnabledLanguages() this->LanguageEnabled.clear(); } -bool cmGlobalGenerator::IsDependedOn(const std::string& project, - cmTarget const* targetIn) -{ - // Get all local gens for this project - std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator it = - this->ProjectMap.find(project); - if (it == this->ProjectMap.end()) - { - return false; - } - - // loop over local gens and get the targets for each one - for(std::vector<cmLocalGenerator*>::const_iterator geIt = it->second.begin(); - geIt != it->second.end(); ++geIt) - { - cmTargets const& targets = (*geIt)->GetMakefile()->GetTargets(); - for (cmTargets::const_iterator l = targets.begin(); - l != targets.end(); l++) - { - cmTarget const& target = l->second; - TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(target); - if(tgtdeps.count(targetIn)) - { - return true; - } - } - } - return false; -} - void cmGlobalGenerator::Configure() { this->FirstTimeProgress = 0.0f; @@ -1175,7 +1197,7 @@ bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const return false; } -void cmGlobalGenerator::Generate() +void cmGlobalGenerator::DoGenerate() { // Some generators track files replaced during the Generate. // Start with an empty vector: @@ -1184,6 +1206,11 @@ void cmGlobalGenerator::Generate() // clear targets to issue warning CMP0042 for this->CMP0042WarnTargets.clear(); + this->Generate(); +} + +void cmGlobalGenerator::Generate() +{ // Check whether this generator is allowed to run. if(!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS()) { @@ -1637,7 +1664,7 @@ int cmGlobalGenerator::TryCompile(const std::string& srcdir, const std::string& bindir, const std::string& projectName, const std::string& target, bool fast, - std::string *output, cmMakefile *mf) + std::string& output, cmMakefile *mf) { // if this is not set, then this is a first time configure // and there is a good chance that the try compile stuff will @@ -1696,7 +1723,7 @@ void cmGlobalGenerator::GenerateBuildCommand( int cmGlobalGenerator::Build( const std::string&, const std::string& bindir, const std::string& projectName, const std::string& target, - std::string *output, + std::string& output, const std::string& makeCommandCSTR, const std::string& config, bool clean, bool fast, @@ -1709,22 +1736,15 @@ int cmGlobalGenerator::Build( */ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); cmSystemTools::ChangeDirectory(bindir.c_str()); - if(output) - { - *output += "Change Dir: "; - *output += bindir; - *output += "\n"; - } + output += "Change Dir: "; + output += bindir; + output += "\n"; int retVal; bool hideconsole = cmSystemTools::GetRunCommandHideConsole(); cmSystemTools::SetRunCommandHideConsole(true); std::string outputBuffer; - std::string* outputPtr = 0; - if(output) - { - outputPtr = &outputBuffer; - } + std::string* outputPtr = &outputBuffer; // should we do a clean first? if (clean) @@ -1732,32 +1752,23 @@ int cmGlobalGenerator::Build( std::vector<std::string> cleanCommand; this->GenerateBuildCommand(cleanCommand, makeCommandCSTR, projectName, bindir, "clean", config, fast); - if(output) - { - *output += "\nRun Clean Command:"; - *output += cmSystemTools::PrintSingleCommand(cleanCommand); - *output += "\n"; - } + output += "\nRun Clean Command:"; + output += cmSystemTools::PrintSingleCommand(cleanCommand); + output += "\n"; if (!cmSystemTools::RunSingleCommand(cleanCommand, outputPtr, &retVal, 0, outputflag, timeout)) { cmSystemTools::SetRunCommandHideConsole(hideconsole); cmSystemTools::Error("Generator: execution of make clean failed."); - if (output) - { - *output += *outputPtr; - *output += "\nGenerator: execution of make clean failed.\n"; - } + output += *outputPtr; + output += "\nGenerator: execution of make clean failed.\n"; // return to the original directory cmSystemTools::ChangeDirectory(cwd.c_str()); return 1; } - if (output) - { - *output += *outputPtr; - } + output += *outputPtr; } // now build @@ -1765,12 +1776,9 @@ int cmGlobalGenerator::Build( this->GenerateBuildCommand(makeCommand, makeCommandCSTR, projectName, bindir, target, config, fast, nativeOptions); std::string makeCommandStr = cmSystemTools::PrintSingleCommand(makeCommand); - if(output) - { - *output += "\nRun Build Command:"; - *output += makeCommandStr; - *output += "\n"; - } + output += "\nRun Build Command:"; + output += makeCommandStr; + output += "\n"; if (!cmSystemTools::RunSingleCommand(makeCommand, outputPtr, &retVal, 0, outputflag, timeout)) @@ -1779,27 +1787,21 @@ int cmGlobalGenerator::Build( cmSystemTools::Error ("Generator: execution of make failed. Make command was: ", makeCommandStr.c_str()); - if (output) - { - *output += *outputPtr; - *output += "\nGenerator: execution of make failed. Make command was: " + output += *outputPtr; + output += "\nGenerator: execution of make failed. Make command was: " + makeCommandStr + "\n"; - } // return to the original directory cmSystemTools::ChangeDirectory(cwd.c_str()); return 1; } - if (output) - { - *output += *outputPtr; - } + output += *outputPtr; cmSystemTools::SetRunCommandHideConsole(hideconsole); // The SGI MipsPro 7.3 compiler does not return an error code when // the source has a #error in it! This is a work-around for such // compilers. - if((retVal == 0) && (output->find("#error") != std::string::npos)) + if((retVal == 0) && (output.find("#error") != std::string::npos)) { retVal = 1; } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 67bd378..ddd7e91 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -39,7 +39,7 @@ class cmExportBuildFileGenerator; class cmQtAutoGenerators; /** \class cmGlobalGenerator - * \brief Responable for overseeing the generation process for the entire tree + * \brief Responsible for overseeing the generation process for the entire tree * * Subclasses of this class generate makefiles for various * platforms. @@ -61,6 +61,14 @@ public: virtual bool MatchesGeneratorName(const std::string& name) const { return this->GetName() == name; } + /** Tell the generator about the target system. */ + virtual bool SetSystemName(std::string const&, cmMakefile*) + { return true; } + + /** Set the generator-specific platform name. Returns true if platform + is supported and false otherwise. */ + virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf); + /** Set the generator-specific toolset name. Returns true if toolset is supported and false otherwise. */ virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf); @@ -76,7 +84,7 @@ public: * basically creates a series of LocalGenerators for each directory and * requests that they Generate. */ - virtual void Generate(); + void DoGenerate(); /** * Set/Get and Clear the enabled languages. @@ -86,7 +94,7 @@ public: void ClearEnabledLanguages(); void GetEnabledLanguages(std::vector<std::string>& lang) const; /** - * Try to determine system infomation such as shared library + * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ virtual void EnableLanguage(std::vector<std::string>const& languages, @@ -100,7 +108,7 @@ public: bool optional) const; /** - * Try to determine system infomation, get it from another generator + * Try to determine system information, get it from another generator */ virtual void EnableLanguagesFromGenerator(cmGlobalGenerator *gen, cmMakefile* mf); @@ -112,7 +120,7 @@ public: virtual int TryCompile(const std::string& srcdir, const std::string& bindir, const std::string& projectName, const std::string& targetName, - bool fast, std::string *output, cmMakefile* mf); + bool fast, std::string& output, cmMakefile* mf); /** @@ -123,7 +131,7 @@ public: */ int Build(const std::string& srcdir, const std::string& bindir, const std::string& projectName, const std::string& targetName, - std::string *output, + std::string& output, const std::string& makeProgram, const std::string& config, bool clean, bool fast, double timeout, @@ -190,7 +198,7 @@ public: std::string GetLanguageFromExtension(const char* ext) const; ///! is an extension to be ignored bool IgnoreFile(const char* ext) const; - ///! What is the preference for linkers and this language (None or Prefered) + ///! What is the preference for linkers and this language (None or Preferred) int GetLinkerPreference(const std::string& lang) const; ///! What is the object file extension for a given source file? std::string GetLanguageOutputExtension(cmSourceFile const&) const; @@ -214,6 +222,11 @@ public: */ virtual void FindMakeProgram(cmMakefile*); +#if defined(_WIN32) && !defined(__CYGWIN__) + /** Is this the Visual Studio 6 generator? */ + virtual bool IsForVS6() const { return false; } +#endif + ///! Find a target by name by searching the local generators. cmTarget* FindTarget(const std::string& name, bool excludeAliases = false) const; @@ -225,9 +238,6 @@ public: that is a framework. */ bool NameResolvesToFramework(const std::string& libname) const; - /** If check to see if the target is linked to by any other - target in the project */ - bool IsDependedOn(const std::string& project, cmTarget const* target); ///! Find a local generator by its startdirectory cmLocalGenerator* FindLocalGenerator(const std::string& start_dir) const; @@ -332,6 +342,8 @@ public: bool GenerateCPackPropertiesFile(); protected: + virtual void Generate(); + typedef std::vector<cmLocalGenerator*> GeneratorVector; // for a project collect all its targets by following depend // information, and also collect all the targets diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h index 344e013..fbb35f3 100644 --- a/Source/cmGlobalJOMMakefileGenerator.h +++ b/Source/cmGlobalJOMMakefileGenerator.h @@ -40,7 +40,7 @@ public: virtual cmLocalGenerator *CreateLocalGenerator(); /** - * Try to determine system infomation such as shared library + * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ virtual void EnableLanguage(std::vector<std::string>const& languages, diff --git a/Source/cmGlobalMSYSMakefileGenerator.h b/Source/cmGlobalMSYSMakefileGenerator.h index c4825bd..baecde7 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.h +++ b/Source/cmGlobalMSYSMakefileGenerator.h @@ -39,7 +39,7 @@ public: virtual cmLocalGenerator *CreateLocalGenerator(); /** - * Try to determine system infomation such as shared library + * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ virtual void EnableLanguage(std::vector<std::string>const& languages, diff --git a/Source/cmGlobalMinGWMakefileGenerator.h b/Source/cmGlobalMinGWMakefileGenerator.h index 4289422..fa8d9f2 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.h +++ b/Source/cmGlobalMinGWMakefileGenerator.h @@ -38,7 +38,7 @@ public: virtual cmLocalGenerator *CreateLocalGenerator(); /** - * Try to determine system infomation such as shared library + * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ virtual void EnableLanguage(std::vector<std::string>const& languages, diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index 2ff44e3..e7b03dd 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -38,7 +38,7 @@ public: virtual cmLocalGenerator *CreateLocalGenerator(); /** - * Try to determine system infomation such as shared library + * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ virtual void EnableLanguage(std::vector<std::string>const& languages, diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index a0caf0e..6e7b06b 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -151,11 +151,6 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, ++i) { arguments += " " + EncodeIdent(EncodePath(*i), os); - - //we need to track every dependency that comes in, since we are trying - //to find dependencies that are side effects of build commands - // - this->CombinedBuildExplicitDependencies.insert( EncodePath(*i) ); } // Write implicit dependencies. @@ -210,7 +205,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, && args.size() + buildstr.size() + assignments.size() > (size_t) cmdLineLimit) { buildstr += "_RSP_FILE"; - variable_assignments.clear(); + variable_assignments.str(std::string()); cmGlobalNinjaGenerator::WriteVariable(variable_assignments, "RSP_FILE", rspfile, "", 1); assignments += variable_assignments.str(); @@ -280,6 +275,13 @@ cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command, cmNinjaDeps(), orderOnly, vars); + + //we need to track every dependency that comes in, since we are trying + //to find dependencies that are side effects of build commands + for(cmNinjaDeps::const_iterator i = deps.begin(); i != deps.end(); ++i) + { + this->CombinedCustomCommandExplicitDependencies.insert( EncodePath(*i) ); + } } void @@ -538,6 +540,15 @@ void cmGlobalNinjaGenerator cmSystemTools::Error("The Ninja generator does not support Fortran yet."); } this->cmGlobalGenerator::EnableLanguage(langs, makefile, optional); + for(std::vector<std::string>::const_iterator l = langs.begin(); + l != langs.end(); ++l) + { + if(*l == "NONE") + { + continue; + } + this->ResolveLanguageCompiler(*l, makefile, optional); + } } bool cmGlobalNinjaGenerator::UsingMinGW = false; @@ -961,7 +972,16 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) { knownDependencies.insert( ng->ConvertToNinjaPath( j->c_str() ) ); } + //get list files which are implicit dependencies as well and will be phony + //for rebuild manifest + std::vector<std::string> const& lf = (*i)->GetMakefile()->GetListFiles(); + typedef std::vector<std::string>::const_iterator vect_it; + for(vect_it j = lf.begin(); j != lf.end(); ++j) + { + knownDependencies.insert( ng->ConvertToNinjaPath( j->c_str() ) ); + } } + knownDependencies.insert( "CMakeCache.txt" ); for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator li = this->EvaluationFiles.begin(); @@ -1006,17 +1026,17 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) //to keep this data around this->CombinedBuildOutputs.clear(); - //now we difference with CombinedBuildExplicitDependencies to find + //now we difference with CombinedCustomCommandExplicitDependencies to find //the list of items we know nothing about. - //We have encoded all the paths in CombinedBuildExplicitDependencies + //We have encoded all the paths in CombinedCustomCommandExplicitDependencies //and knownDependencies so no matter if unix or windows paths they //should all match now. std::vector<std::string> unkownExplicitDepends; - this->CombinedBuildExplicitDependencies.erase("all"); + this->CombinedCustomCommandExplicitDependencies.erase("all"); - std::set_difference(this->CombinedBuildExplicitDependencies.begin(), - this->CombinedBuildExplicitDependencies.end(), + std::set_difference(this->CombinedCustomCommandExplicitDependencies.begin(), + this->CombinedCustomCommandExplicitDependencies.end(), knownDependencies.begin(), knownDependencies.end(), std::back_inserter(unkownExplicitDepends)); @@ -1118,6 +1138,16 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) implicitDeps.erase(std::unique(implicitDeps.begin(), implicitDeps.end()), implicitDeps.end()); + cmNinjaVars variables; + // Use 'console' pool to get non buffered output of the CMake re-run call + // Available since Ninja 1.5 + if(cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, + ninjaVersion().c_str(), + "1.5") == false) + { + variables["pool"] = "console"; + } + this->WriteBuild(os, "Re-run CMake if any of its inputs changed.", "RERUN_CMAKE", @@ -1125,7 +1155,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) /*explicitDeps=*/ cmNinjaDeps(), implicitDeps, /*orderOnlyDeps=*/ cmNinjaDeps(), - /*variables=*/ cmNinjaVars()); + variables); this->WritePhonyBuild(os, "A missing CMake input file is not an error.", @@ -1144,6 +1174,17 @@ std::string cmGlobalNinjaGenerator::ninjaCmd() const return "ninja"; } +std::string cmGlobalNinjaGenerator::ninjaVersion() const +{ + std::string version; + std::string command = ninjaCmd() + " --version"; + cmSystemTools::RunSingleCommand(command.c_str(), + &version, 0, 0, + cmSystemTools::OUTPUT_NONE); + + return version; +} + void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) { WriteRule(*this->RulesFileStream, diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index f2643af..f666ee3 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -182,9 +182,6 @@ public: /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation() static void GetDocumentation(cmDocumentationEntry& entry); - /// Overloaded methods. @see cmGlobalGenerator::Generate() - virtual void Generate(); - /// Overloaded methods. @see cmGlobalGenerator::EnableLanguage() virtual void EnableLanguage(std::vector<std::string>const& languages, cmMakefile* mf, @@ -300,8 +297,13 @@ public: void AddTargetAlias(const std::string& alias, cmTarget* target); virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const; + + std::string ninjaVersion() const; protected: + /// Overloaded methods. @see cmGlobalGenerator::Generate() + virtual void Generate(); + /// Overloaded methods. /// @see cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const { return true; } @@ -335,8 +337,7 @@ private: std::string ninjaCmd() const; - - /// The file containing the build statement. (the relation ship of the + /// The file containing the build statement. (the relationship of the /// compilation DAG). cmGeneratedFileStream* BuildFileStream; /// The file containing the rule statements. (The action attached to each @@ -363,10 +364,11 @@ private: /// The set of custom command outputs we have seen. std::set<std::string> CustomCommandOutputs; - //The combined explicit dependencies of all build commands that the global - //generator has issued. When combined with CombinedBuildOutputs it allows - //us to detect the set of explicit dependencies that have - std::set<std::string> CombinedBuildExplicitDependencies; + /// The combined explicit dependencies of custom build commands + std::set<std::string> CombinedCustomCommandExplicitDependencies; + + /// When combined with CombinedCustomCommandExplicitDependencies it allows + /// us to detect the set of explicit dependencies that have std::set<std::string> CombinedBuildOutputs; /// The mapping from source file to assumed dependencies. diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 8dae81b..3478534 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -530,7 +530,7 @@ cmGlobalUnixMakefileGenerator3 // Begin the directory-level rules section. std::string dir = lg->GetMakefile()->GetStartOutputDirectory(); dir = lg->Convert(dir, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE); + cmLocalGenerator::MAKERULE); lg->WriteDivider(ruleFileStream); ruleFileStream << "# Directory level rules for directory " diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index f44dd12..c61c36e 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -71,7 +71,7 @@ public: virtual cmLocalGenerator *CreateLocalGenerator(); /** - * Try to determine system infomation such as shared library + * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ virtual void EnableLanguage(std::vector<std::string>const& languages, diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 86d0de3..d70d2af 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -48,20 +48,22 @@ public: const char* p = cmVS10GenName(name, genName); if(!p) { return 0; } - if(strcmp(p, "") == 0) + if(!*p) { return new cmGlobalVisualStudio10Generator( - genName, "", ""); + genName, ""); } - if(strcmp(p, " Win64") == 0) + if(*p++ != ' ') + { return 0; } + if(strcmp(p, "Win64") == 0) { return new cmGlobalVisualStudio10Generator( - genName, "x64", "CMAKE_FORCE_WIN64"); + genName, "x64"); } - if(strcmp(p, " IA64") == 0) + if(strcmp(p, "IA64") == 0) { return new cmGlobalVisualStudio10Generator( - genName, "Itanium", "CMAKE_FORCE_IA64"); + genName, "Itanium"); } return 0; } @@ -88,16 +90,16 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory() //---------------------------------------------------------------------------- cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( - const std::string& name, const std::string& platformName, - const std::string& additionalPlatformDefinition) - : cmGlobalVisualStudio8Generator(name, platformName, - additionalPlatformDefinition) + const std::string& name, const std::string& platformName) + : cmGlobalVisualStudio8Generator(name, platformName) { std::string vc10Express; this->ExpressEdition = cmSystemTools::ReadRegistryValue( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\10.0\\Setup\\VC;" "ProductDir", vc10Express, cmSystemTools::KeyWOW64_32); - this->MasmEnabled = false; + this->SystemIsWindowsCE = false; + this->SystemIsWindowsPhone = false; + this->SystemIsWindowsStore = false; this->MSBuildCommandInitialized = false; } @@ -115,30 +117,158 @@ cmGlobalVisualStudio10Generator::MatchesGeneratorName( } //---------------------------------------------------------------------------- +bool cmGlobalVisualStudio10Generator::SetSystemName(std::string const& s, + cmMakefile* mf) +{ + this->SystemName = s; + this->SystemVersion = mf->GetSafeDefinition("CMAKE_SYSTEM_VERSION"); + if(!this->InitializeSystem(mf)) + { + return false; + } + return this->cmGlobalVisualStudio8Generator::SetSystemName(s, mf); +} + +//---------------------------------------------------------------------------- +bool +cmGlobalVisualStudio10Generator::SetGeneratorPlatform(std::string const& p, + cmMakefile* mf) +{ + if(!this->cmGlobalVisualStudio8Generator::SetGeneratorPlatform(p, mf)) + { + return false; + } + if(this->GetPlatformName() == "Itanium" || this->GetPlatformName() == "x64") + { + if(this->IsExpressEdition() && !this->Find64BitTools(mf)) + { + return false; + } + } + return true; +} + +//---------------------------------------------------------------------------- bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(std::string const& ts, cmMakefile* mf) { + if (this->SystemIsWindowsCE && ts.empty() && + this->DefaultPlatformToolset.empty()) + { + cmOStringStream e; + e << this->GetName() << " Windows CE version '" << this->SystemVersion + << "' requires CMAKE_GENERATOR_TOOLSET to be set."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + this->GeneratorToolset = ts; - this->AddVSPlatformToolsetDefinition(mf); + if(const char* toolset = this->GetPlatformToolset()) + { + mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET", toolset); + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf) +{ + if (this->SystemName == "WindowsCE") + { + this->SystemIsWindowsCE = true; + if (!this->InitializeWindowsCE(mf)) + { + return false; + } + } + else if(this->SystemName == "WindowsPhone") + { + this->SystemIsWindowsPhone = true; + if(!this->InitializeWindowsPhone(mf)) + { + return false; + } + } + else if(this->SystemName == "WindowsStore") + { + this->SystemIsWindowsStore = true; + if(!this->InitializeWindowsStore(mf)) + { + return false; + } + } + else if(this->SystemName == "Android") + { + if(this->DefaultPlatformName != "Win32") + { + cmOStringStream e; + e << "CMAKE_SYSTEM_NAME is 'Android' but CMAKE_GENERATOR " + << "specifies a platform too: '" << this->GetName() << "'"; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + std::string v = this->GetInstalledNsightTegraVersion(); + if(v.empty()) + { + mf->IssueMessage(cmake::FATAL_ERROR, + "CMAKE_SYSTEM_NAME is 'Android' but " + "'NVIDIA Nsight Tegra Visual Studio Edition' " + "is not installed."); + return false; + } + this->DefaultPlatformName = "Tegra-Android"; + this->DefaultPlatformToolset = "Default"; + this->NsightTegraVersion = v; + mf->AddDefinition("CMAKE_VS_NsightTegra_VERSION", v.c_str()); + } + return true; } //---------------------------------------------------------------------------- -void cmGlobalVisualStudio10Generator::AddPlatformDefinitions(cmMakefile* mf) +bool cmGlobalVisualStudio10Generator::InitializeWindowsCE(cmMakefile* mf) { - cmGlobalVisualStudio8Generator::AddPlatformDefinitions(mf); - this->AddVSPlatformToolsetDefinition(mf); + if (this->DefaultPlatformName != "Win32") + { + cmOStringStream e; + e << "CMAKE_SYSTEM_NAME is 'WindowsCE' but CMAKE_GENERATOR " + << "specifies a platform too: '" << this->GetName() << "'"; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + + this->DefaultPlatformToolset = this->SelectWindowsCEToolset(); + + return true; } //---------------------------------------------------------------------------- -void cmGlobalVisualStudio10Generator -::AddVSPlatformToolsetDefinition(cmMakefile* mf) const +bool cmGlobalVisualStudio10Generator::InitializeWindowsPhone(cmMakefile* mf) { - if(const char* toolset = this->GetPlatformToolset()) + cmOStringStream e; + e << this->GetName() << " does not support Windows Phone."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; +} + +//---------------------------------------------------------------------------- +bool cmGlobalVisualStudio10Generator::InitializeWindowsStore(cmMakefile* mf) +{ + cmOStringStream e; + e << this->GetName() << " does not support Windows Store."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; +} + +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudio10Generator::SelectWindowsCEToolset() const +{ + if (this->SystemVersion == "8.0") { - mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET", toolset); + return "CE800"; } + return ""; } //---------------------------------------------------------------------------- @@ -160,7 +290,6 @@ cmLocalGenerator *cmGlobalVisualStudio10Generator::CreateLocalGenerator() { cmLocalVisualStudio10Generator* lg = new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS10); - lg->SetPlatformName(this->GetPlatformName()); lg->SetGlobalGenerator(this); return lg; } @@ -202,23 +331,6 @@ void cmGlobalVisualStudio10Generator ::EnableLanguage(std::vector<std::string>const & lang, cmMakefile *mf, bool optional) { - if(this->PlatformName == "Itanium" || this->PlatformName == "x64") - { - if(this->IsExpressEdition() && !this->Find64BitTools(mf)) - { - return; - } - } - - for(std::vector<std::string>::const_iterator it = lang.begin(); - it != lang.end(); ++it) - { - if(*it == "ASM_MASM") - { - this->MasmEnabled = true; - } - } - cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional); } @@ -436,7 +548,7 @@ bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf) // This edition does not come with 64-bit tools. Look for them. // // TODO: Detect available tools? x64\v100 exists but does not work? - // KHLM\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\4.0;VCTargetsPath + // HKLM\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\4.0;VCTargetsPath // c:/Program Files (x86)/MSBuild/Microsoft.Cpp/v4.0/Platforms/ // {Itanium,Win32,x64}/PlatformToolsets/{v100,v90,Windows7.1SDK} std::string winSDK_7_1; @@ -500,3 +612,25 @@ bool cmGlobalVisualStudio10Generator::UseFolderProperty() { return IsExpressEdition() ? false : cmGlobalGenerator::UseFolderProperty(); } + +//---------------------------------------------------------------------------- +bool cmGlobalVisualStudio10Generator::IsNsightTegra() const +{ + return !this->NsightTegraVersion.empty(); +} + +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudio10Generator::GetNsightTegraVersion() const +{ + return this->NsightTegraVersion; +} + +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudio10Generator::GetInstalledNsightTegraVersion() +{ + std::string version; + cmSystemTools::ReadRegistryValue( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\NVIDIA Corporation\\Nsight Tegra;" + "Version", version, cmSystemTools::KeyWOW64_32); + return version; +} diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index b4dcc7e..686dcdf 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -25,12 +25,13 @@ class cmGlobalVisualStudio10Generator : { public: cmGlobalVisualStudio10Generator(const std::string& name, - const std::string& platformName, - const std::string& additionalPlatformDefinition); + const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); virtual bool MatchesGeneratorName(const std::string& name) const; + virtual bool SetSystemName(std::string const& s, cmMakefile* mf); + virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf); virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf); virtual void GenerateBuildCommand( @@ -44,15 +45,11 @@ public: std::vector<std::string> const& makeOptions = std::vector<std::string>() ); - virtual void AddPlatformDefinitions(cmMakefile* mf); - ///! create the correct local generator virtual cmLocalGenerator *CreateLocalGenerator(); - virtual void Generate(); - /** - * Try to determine system infomation such as shared library + * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ virtual void EnableLanguage(std::vector<std::string>const& languages, @@ -62,12 +59,31 @@ public: /** Is the installed VS an Express edition? */ bool IsExpressEdition() const { return this->ExpressEdition; } - /** Is the Microsoft Assembler enabled? */ - bool IsMasmEnabled() const { return this->MasmEnabled; } + /** Generating for Nsight Tegra VS plugin? */ + bool IsNsightTegra() const; + std::string GetNsightTegraVersion() const; /** The toolset name for the target platform. */ const char* GetPlatformToolset() const; + /** Return the CMAKE_SYSTEM_NAME. */ + std::string const& GetSystemName() const { return this->SystemName; } + + /** Return the CMAKE_SYSTEM_VERSION. */ + std::string const& GetSystemVersion() const { return this->SystemVersion; } + + /** Return true if building for WindowsCE */ + bool TargetsWindowsCE() const + { return this->SystemIsWindowsCE; } + + /** Return true if building for WindowsPhone */ + bool TargetsWindowsPhone() const + { return this->SystemIsWindowsPhone; } + + /** Return true if building for WindowsStore */ + bool TargetsWindowsStore() const + { return this->SystemIsWindowsStore; } + /** * Where does this version of Visual Studio look for macros for the * current user? Returns the empty string if this version of Visual @@ -94,15 +110,31 @@ public: virtual void FindMakeProgram(cmMakefile*); + static std::string GetInstalledNsightTegraVersion(); + protected: + virtual void Generate(); + virtual bool InitializeSystem(cmMakefile* mf); + virtual bool InitializeWindowsCE(cmMakefile* mf); + virtual bool InitializeWindowsPhone(cmMakefile* mf); + virtual bool InitializeWindowsStore(cmMakefile* mf); + virtual std::string SelectWindowsCEToolset() const; + virtual std::string SelectWindowsPhoneToolset() const { return ""; } + virtual std::string SelectWindowsStoreToolset() const { return ""; } + virtual const char* GetIDEVersion() { return "10.0"; } std::string const& GetMSBuildCommand(); std::string GeneratorToolset; std::string DefaultPlatformToolset; + std::string SystemName; + std::string SystemVersion; + std::string NsightTegraVersion; + bool SystemIsWindowsCE; + bool SystemIsWindowsPhone; + bool SystemIsWindowsStore; bool ExpressEdition; - bool MasmEnabled; bool UseFolderProperty(); @@ -123,6 +155,5 @@ private: virtual std::string FindMSBuildCommand(); virtual std::string FindDevEnvCommand(); virtual std::string GetVSMakeProgram() { return this->GetMSBuildCommand(); } - void AddVSPlatformToolsetDefinition(cmMakefile* mf) const; }; #endif diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx index 7033f2a..39bbdc0 100644 --- a/Source/cmGlobalVisualStudio11Generator.cxx +++ b/Source/cmGlobalVisualStudio11Generator.cxx @@ -43,25 +43,22 @@ public: const char* p = cmVS11GenName(name, genName); if(!p) { return 0; } - if(strcmp(p, "") == 0) + if(!*p) { return new cmGlobalVisualStudio11Generator( - genName, "", ""); + genName, ""); } - if(strcmp(p, " Win64") == 0) + if(*p++ != ' ') + { return 0; } + if(strcmp(p, "Win64") == 0) { return new cmGlobalVisualStudio11Generator( - genName, "x64", "CMAKE_FORCE_WIN64"); + genName, "x64"); } - if(strcmp(p, " ARM") == 0) + if(strcmp(p, "ARM") == 0) { return new cmGlobalVisualStudio11Generator( - genName, "ARM", ""); - } - - if(*p++ != ' ') - { - return 0; + genName, "ARM"); } std::set<std::string> installedSDKs = @@ -73,7 +70,7 @@ public: } cmGlobalVisualStudio11Generator* ret = - new cmGlobalVisualStudio11Generator(name, p, NULL); + new cmGlobalVisualStudio11Generator(name, p); ret->WindowsCEVersion = "8.00"; return ret; } @@ -108,10 +105,8 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory() //---------------------------------------------------------------------------- cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator( - const std::string& name, const std::string& platformName, - const std::string& additionalPlatformDefinition) - : cmGlobalVisualStudio10Generator(name, platformName, - additionalPlatformDefinition) + const std::string& name, const std::string& platformName) + : cmGlobalVisualStudio10Generator(name, platformName) { std::string vc11Express; this->ExpressEdition = cmSystemTools::ReadRegistryValue( @@ -134,6 +129,56 @@ cmGlobalVisualStudio11Generator::MatchesGeneratorName( } //---------------------------------------------------------------------------- +bool cmGlobalVisualStudio11Generator::InitializeWindowsPhone(cmMakefile* mf) +{ + this->DefaultPlatformToolset = this->SelectWindowsPhoneToolset(); + if(this->DefaultPlatformToolset.empty()) + { + cmOStringStream e; + e << this->GetName() << " supports Windows Phone '8.0', but not '" + << this->SystemVersion << "'. Check CMAKE_SYSTEM_VERSION."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmGlobalVisualStudio11Generator::InitializeWindowsStore(cmMakefile* mf) +{ + this->DefaultPlatformToolset = this->SelectWindowsStoreToolset(); + if(this->DefaultPlatformToolset.empty()) + { + cmOStringStream e; + e << this->GetName() << " supports Windows Store '8.0', but not '" + << this->SystemVersion << "'. Check CMAKE_SYSTEM_VERSION."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + return true; +} + +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudio11Generator::SelectWindowsPhoneToolset() const +{ + if(this->SystemVersion == "8.0") + { + return "v110_wp80"; + } + return this->cmGlobalVisualStudio10Generator::SelectWindowsPhoneToolset(); +} + +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudio11Generator::SelectWindowsStoreToolset() const +{ + if(this->SystemVersion == "8.0") + { + return "v110"; + } + return this->cmGlobalVisualStudio10Generator::SelectWindowsStoreToolset(); +} + +//---------------------------------------------------------------------------- void cmGlobalVisualStudio11Generator::WriteSLNHeader(std::ostream& fout) { fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; @@ -152,7 +197,6 @@ cmLocalGenerator *cmGlobalVisualStudio11Generator::CreateLocalGenerator() { cmLocalVisualStudio10Generator* lg = new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS11); - lg->SetPlatformName(this->GetPlatformName()); lg->SetGlobalGenerator(this); return lg; } @@ -198,3 +242,17 @@ cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs() return ret; } + +//---------------------------------------------------------------------------- +bool +cmGlobalVisualStudio11Generator::NeedsDeploy(cmTarget::TargetType type) const +{ + if((type == cmTarget::EXECUTABLE || + type == cmTarget::SHARED_LIBRARY) && + (this->SystemIsWindowsPhone || + this->SystemIsWindowsStore)) + { + return true; + } + return cmGlobalVisualStudio10Generator::NeedsDeploy(type); +} diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h index 48ea489..bbd935c 100644 --- a/Source/cmGlobalVisualStudio11Generator.h +++ b/Source/cmGlobalVisualStudio11Generator.h @@ -21,8 +21,7 @@ class cmGlobalVisualStudio11Generator: { public: cmGlobalVisualStudio11Generator(const std::string& name, - const std::string& platformName, - const std::string& additionalPlatformDefinition); + const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); virtual bool MatchesGeneratorName(const std::string& name) const; @@ -35,9 +34,16 @@ public: /** TODO: VS 11 user macro support. */ virtual std::string GetUserMacrosDirectory() { return ""; } protected: + virtual bool InitializeWindowsPhone(cmMakefile* mf); + virtual bool InitializeWindowsStore(cmMakefile* mf); + virtual std::string SelectWindowsPhoneToolset() const; + virtual std::string SelectWindowsStoreToolset() const; virtual const char* GetIDEVersion() { return "11.0"; } bool UseFolderProperty(); static std::set<std::string> GetInstalledWindowsCESDKs(); + + /** Return true if the configuration needs to be deployed */ + virtual bool NeedsDeploy(cmTarget::TargetType type) const; private: class Factory; friend class Factory; diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index 40f8b05..29ecfe0 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -43,20 +43,22 @@ public: const char* p = cmVS12GenName(name, genName); if(!p) { return 0; } - if(strcmp(p, "") == 0) + if(!*p) { return new cmGlobalVisualStudio12Generator( - genName, "", ""); + genName, ""); } - if(strcmp(p, " Win64") == 0) + if(*p++ != ' ') + { return 0; } + if(strcmp(p, "Win64") == 0) { return new cmGlobalVisualStudio12Generator( - genName, "x64", "CMAKE_FORCE_WIN64"); + genName, "x64"); } - if(strcmp(p, " ARM") == 0) + if(strcmp(p, "ARM") == 0) { return new cmGlobalVisualStudio12Generator( - genName, "ARM", ""); + genName, "ARM"); } return 0; } @@ -83,10 +85,8 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory() //---------------------------------------------------------------------------- cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator( - const std::string& name, const std::string& platformName, - const std::string& additionalPlatformDefinition) - : cmGlobalVisualStudio11Generator(name, platformName, - additionalPlatformDefinition) + const std::string& name, const std::string& platformName) + : cmGlobalVisualStudio11Generator(name, platformName) { std::string vc12Express; this->ExpressEdition = cmSystemTools::ReadRegistryValue( @@ -109,6 +109,56 @@ cmGlobalVisualStudio12Generator::MatchesGeneratorName( } //---------------------------------------------------------------------------- +bool cmGlobalVisualStudio12Generator::InitializeWindowsPhone(cmMakefile* mf) +{ + this->DefaultPlatformToolset = this->SelectWindowsPhoneToolset(); + if(this->DefaultPlatformToolset.empty()) + { + cmOStringStream e; + e << this->GetName() << " supports Windows Phone '8.0' and '8.1', " + "but not '" << this->SystemVersion << "'. Check CMAKE_SYSTEM_VERSION."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmGlobalVisualStudio12Generator::InitializeWindowsStore(cmMakefile* mf) +{ + this->DefaultPlatformToolset = this->SelectWindowsStoreToolset(); + if(this->DefaultPlatformToolset.empty()) + { + cmOStringStream e; + e << this->GetName() << " supports Windows Store '8.0' and '8.1', " + "but not '" << this->SystemVersion << "'. Check CMAKE_SYSTEM_VERSION."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + return true; +} + +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudio12Generator::SelectWindowsPhoneToolset() const +{ + if(this->SystemVersion == "8.1") + { + return "v120_wp81"; + } + return this->cmGlobalVisualStudio11Generator::SelectWindowsPhoneToolset(); +} + +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudio12Generator::SelectWindowsStoreToolset() const +{ + if(this->SystemVersion == "8.1") + { + return "v120"; + } + return this->cmGlobalVisualStudio11Generator::SelectWindowsStoreToolset(); +} + +//---------------------------------------------------------------------------- void cmGlobalVisualStudio12Generator::WriteSLNHeader(std::ostream& fout) { fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; @@ -127,7 +177,6 @@ cmLocalGenerator *cmGlobalVisualStudio12Generator::CreateLocalGenerator() { cmLocalVisualStudio10Generator* lg = new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS12); - lg->SetPlatformName(this->GetPlatformName()); lg->SetGlobalGenerator(this); return lg; } diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h index 4557f28..ec85f10 100644 --- a/Source/cmGlobalVisualStudio12Generator.h +++ b/Source/cmGlobalVisualStudio12Generator.h @@ -21,8 +21,7 @@ class cmGlobalVisualStudio12Generator: { public: cmGlobalVisualStudio12Generator(const std::string& name, - const std::string& platformName, - const std::string& additionalPlatformDefinition); + const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); virtual bool MatchesGeneratorName(const std::string& name) const; @@ -40,6 +39,10 @@ public: //version number virtual const char* GetToolsVersion() { return "12.0"; } protected: + virtual bool InitializeWindowsPhone(cmMakefile* mf); + virtual bool InitializeWindowsStore(cmMakefile* mf); + virtual std::string SelectWindowsPhoneToolset() const; + virtual std::string SelectWindowsStoreToolset() const; virtual const char* GetIDEVersion() { return "12.0"; } private: class Factory; diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx new file mode 100644 index 0000000..d001f93 --- /dev/null +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -0,0 +1,113 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2014 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 "cmGlobalVisualStudio14Generator.h" +#include "cmLocalVisualStudio10Generator.h" +#include "cmMakefile.h" + +static const char vs14generatorName[] = "Visual Studio 14"; + +class cmGlobalVisualStudio14Generator::Factory + : public cmGlobalGeneratorFactory +{ +public: + virtual cmGlobalGenerator* CreateGlobalGenerator( + const std::string& genName) const + { + if(strncmp(genName.c_str(), vs14generatorName, + sizeof(vs14generatorName) - 1) != 0) + { + return 0; + } + const char* p = genName.c_str() + sizeof(vs14generatorName) - 1; + if(!*p) + { + return new cmGlobalVisualStudio14Generator( + genName, ""); + } + if(*p++ != ' ') + { return 0; } + if(strcmp(p, "Win64") == 0) + { + return new cmGlobalVisualStudio14Generator( + genName, "x64"); + } + if(strcmp(p, "ARM") == 0) + { + return new cmGlobalVisualStudio14Generator( + genName, "ARM"); + } + return 0; + } + + virtual void GetDocumentation(cmDocumentationEntry& entry) const + { + entry.Name = vs14generatorName; + entry.Brief = "Generates Visual Studio 14 project files."; + } + + virtual void GetGenerators(std::vector<std::string>& names) const + { + names.push_back(vs14generatorName); + names.push_back(vs14generatorName + std::string(" ARM")); + names.push_back(vs14generatorName + std::string(" Win64")); + } +}; + +//---------------------------------------------------------------------------- +cmGlobalGeneratorFactory* cmGlobalVisualStudio14Generator::NewFactory() +{ + return new Factory; +} + +//---------------------------------------------------------------------------- +cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator( + const std::string& name, const std::string& platformName) + : cmGlobalVisualStudio12Generator(name, platformName) +{ + std::string vc14Express; + this->ExpressEdition = cmSystemTools::ReadRegistryValue( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\14.0\\Setup\\VC;" + "ProductDir", vc14Express, cmSystemTools::KeyWOW64_32); + this->DefaultPlatformToolset = "v140"; +} + +//---------------------------------------------------------------------------- +bool +cmGlobalVisualStudio14Generator::MatchesGeneratorName( + const std::string& name) const +{ + return name == this->GetName(); +} + +//---------------------------------------------------------------------------- +void cmGlobalVisualStudio14Generator::WriteSLNHeader(std::ostream& fout) +{ + // Visual Studio 14 writes .sln format 12.00 + fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; + if (this->ExpressEdition) + { + fout << "# Visual Studio Express 14 for Windows Desktop\n"; + } + else + { + fout << "# Visual Studio 14\n"; + } +} + +//---------------------------------------------------------------------------- +cmLocalGenerator *cmGlobalVisualStudio14Generator::CreateLocalGenerator() +{ + cmLocalVisualStudio10Generator* lg = + new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS14); + lg->SetGlobalGenerator(this); + return lg; +} diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h new file mode 100644 index 0000000..3fd60a0 --- /dev/null +++ b/Source/cmGlobalVisualStudio14Generator.h @@ -0,0 +1,43 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2014 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 cmGlobalVisualStudio14Generator_h +#define cmGlobalVisualStudio14Generator_h + +#include "cmGlobalVisualStudio12Generator.h" + + +/** \class cmGlobalVisualStudio14Generator */ +class cmGlobalVisualStudio14Generator: + public cmGlobalVisualStudio12Generator +{ +public: + cmGlobalVisualStudio14Generator(const std::string& name, + const std::string& platformName); + static cmGlobalGeneratorFactory* NewFactory(); + + virtual bool MatchesGeneratorName(const std::string& name) const; + + virtual void WriteSLNHeader(std::ostream& fout); + + ///! create the correct local generator + virtual cmLocalGenerator *CreateLocalGenerator(); + + /** TODO: VS 14 user macro support. */ + virtual std::string GetUserMacrosDirectory() { return ""; } + + virtual const char* GetToolsVersion() { return "14.0"; } +protected: + virtual const char* GetIDEVersion() { return "14.0"; } +private: + class Factory; +}; +#endif diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx index 7397bbb..455a7a2 100644 --- a/Source/cmGlobalVisualStudio6Generator.cxx +++ b/Source/cmGlobalVisualStudio6Generator.cxx @@ -41,7 +41,6 @@ void cmGlobalVisualStudio6Generator cmMakefile *mf, bool optional) { - cmGlobalVisualStudioGenerator::AddPlatformDefinitions(mf); mf->AddDefinition("CMAKE_GENERATOR_RC", "rc"); mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1"); this->GenerateConfigurations(mf); diff --git a/Source/cmGlobalVisualStudio6Generator.h b/Source/cmGlobalVisualStudio6Generator.h index 2797e11..58efb25 100644 --- a/Source/cmGlobalVisualStudio6Generator.h +++ b/Source/cmGlobalVisualStudio6Generator.h @@ -42,7 +42,7 @@ public: virtual cmLocalGenerator *CreateLocalGenerator(); /** - * Try to determine system infomation such as shared library + * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ virtual void EnableLanguage(std::vector<std::string>const& languages, @@ -64,13 +64,6 @@ public: ); /** - * Generate the all required files for building this project/tree. This - * basically creates a series of LocalGenerators for each directory and - * requests that they Generate. - */ - virtual void Generate(); - - /** * Generate the DSW workspace file. */ virtual void OutputDSWFile(); @@ -91,7 +84,10 @@ public: virtual void FindMakeProgram(cmMakefile*); + virtual bool IsForVS6() const { return true; } + protected: + virtual void Generate(); virtual const char* GetIDEVersion() { return "6.0"; } private: virtual std::string GetVSMakeProgram() { return this->GetMSDevCommand(); } diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index 4bea5ac..a67a649 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -118,7 +118,7 @@ void cmGlobalVisualStudio71Generator fout << "\tGlobalSection(" << this->ProjectConfigurationSectionName << ") = postSolution\n"; // Write out the configurations for all the targets in the project - this->WriteTargetConfigurations(fout, root, orderedProjectTargets); + this->WriteTargetConfigurations(fout, orderedProjectTargets); fout << "\tEndGlobalSection\n"; if (useFolderProperty) diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index b581147..401e475 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -23,14 +23,15 @@ cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator( { this->IntelProjectVersion = 0; this->DevEnvCommandInitialized = false; + this->MasmEnabled = false; if (platformName.empty()) { - this->PlatformName = "Win32"; + this->DefaultPlatformName = "Win32"; } else { - this->PlatformName = platformName; + this->DefaultPlatformName = platformName; } } @@ -80,7 +81,6 @@ void cmGlobalVisualStudio7Generator { mf->AddDefinition("CMAKE_GENERATOR_RC", "rc"); mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1"); - this->AddPlatformDefinitions(mf); if(!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { mf->AddCacheDefinition( @@ -260,12 +260,38 @@ cmLocalGenerator *cmGlobalVisualStudio7Generator::CreateLocalGenerator() } //---------------------------------------------------------------------------- -void cmGlobalVisualStudio7Generator::AddPlatformDefinitions(cmMakefile* mf) +std::string const& cmGlobalVisualStudio7Generator::GetPlatformName() const +{ + if(!this->GeneratorPlatform.empty()) + { + return this->GeneratorPlatform; + } + return this->DefaultPlatformName; +} + +//---------------------------------------------------------------------------- +bool cmGlobalVisualStudio7Generator::SetSystemName(std::string const& s, + cmMakefile* mf) { - cmGlobalVisualStudioGenerator::AddPlatformDefinitions(mf); - mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName().c_str()); mf->AddDefinition("CMAKE_VS_INTEL_Fortran_PROJECT_VERSION", this->GetIntelProjectVersion()); + return this->cmGlobalVisualStudioGenerator::SetSystemName(s, mf); +} + +//---------------------------------------------------------------------------- +bool cmGlobalVisualStudio7Generator::SetGeneratorPlatform(std::string const& p, + cmMakefile* mf) +{ + if(this->GetPlatformName() == "x64") + { + mf->AddDefinition("CMAKE_FORCE_WIN64", "TRUE"); + } + else if(this->GetPlatformName() == "Itanium") + { + mf->AddDefinition("CMAKE_FORCE_IA64", "TRUE"); + } + mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName().c_str()); + return this->cmGlobalVisualStudioGenerator::SetGeneratorPlatform(p, mf); } void cmGlobalVisualStudio7Generator::GenerateConfigurations(cmMakefile* mf) @@ -366,7 +392,6 @@ void cmGlobalVisualStudio7Generator::OutputSLNFile() void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( std::ostream& fout, - cmLocalGenerator* root, OrderedTargetDependSet const& projectTargets) { // loop over again and write out configurations for each target @@ -392,8 +417,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( else { const std::set<std::string>& configsPartOfDefaultBuild = - this->IsPartOfDefaultBuild(root->GetMakefile()->GetProjectName(), - target); + this->IsPartOfDefaultBuild(projectTargets, target); const char *vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); if (vcprojName) @@ -579,7 +603,7 @@ void cmGlobalVisualStudio7Generator // Write out the configurations for all the targets in the project fout << "\tGlobalSection(ProjectConfiguration) = postSolution\n"; - this->WriteTargetConfigurations(fout, root, orderedProjectTargets); + this->WriteTargetConfigurations(fout, orderedProjectTargets); fout << "\tEndGlobalSection\n"; // Write out global sections @@ -767,7 +791,6 @@ void cmGlobalVisualStudio7Generator::WriteExternalProject(std::ostream& fout, const char* typeGuid, const std::set<std::string>&) { - std::string d = cmSystemTools::ConvertToOutputPath(location); fout << "Project(" << "\"{" << (typeGuid ? typeGuid : this->ExternalProjectType(location)) @@ -981,8 +1004,7 @@ cmGlobalVisualStudio7Generator std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( - const std::string& project, - cmTarget const* target) + OrderedTargetDependSet const& projectTargets, cmTarget const* target) { std::set<std::string> activeConfigs; // if it is a utilitiy target then only make it part of the @@ -992,7 +1014,7 @@ cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( { return activeConfigs; } - if(type == cmTarget::UTILITY && !this->IsDependedOn(project, target)) + if(type == cmTarget::UTILITY && !this->IsDependedOn(projectTargets, target)) { return activeConfigs; } @@ -1010,6 +1032,24 @@ cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( return activeConfigs; } +bool +cmGlobalVisualStudio7Generator +::IsDependedOn(OrderedTargetDependSet const& projectTargets, + cmTarget const* targetIn) +{ + for (OrderedTargetDependSet::const_iterator l = projectTargets.begin(); + l != projectTargets.end(); ++l) + { + cmTarget const& target = **l; + TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(target); + if(tgtdeps.count(targetIn)) + { + return true; + } + } + return false; +} + //---------------------------------------------------------------------------- static cmVS7FlagTable cmVS7ExtraFlagTable[] = { diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 1dc709d..201a6a6 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -39,18 +39,20 @@ public: static std::string GetActualName() {return "Visual Studio 7";} ///! Get the name for the platform. - const std::string& GetPlatformName() const { return this->PlatformName; } + std::string const& GetPlatformName() const; ///! Create a local generator appropriate to this Global Generator virtual cmLocalGenerator *CreateLocalGenerator(); - virtual void AddPlatformDefinitions(cmMakefile* mf); + virtual bool SetSystemName(std::string const& s, cmMakefile* mf); + + virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf); /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); /** - * Try to determine system infomation such as shared library + * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ virtual void EnableLanguage(std::vector<std::string>const& languages, @@ -72,13 +74,6 @@ public: ); /** - * Generate the all required files for building this project/tree. This - * basically creates a series of LocalGenerators for each directory and - * requests that they Generate. - */ - virtual void Generate(); - - /** * Generate the DSW workspace file. */ virtual void OutputSLNFile(); @@ -109,10 +104,14 @@ public: virtual void FindMakeProgram(cmMakefile*); + /** Is the Microsoft Assembler enabled? */ + bool IsMasmEnabled() const { return this->MasmEnabled; } + // Encoding for Visual Studio files virtual std::string Encoding(); protected: + virtual void Generate(); virtual const char* GetIDEVersion() { return "7.0"; } std::string const& GetDevEnvCommand(); @@ -150,7 +149,6 @@ protected: OrderedTargetDependSet const& projectTargets); virtual void WriteTargetConfigurations( std::ostream& fout, - cmLocalGenerator* root, OrderedTargetDependSet const& projectTargets); void GenerateConfigurations(cmMakefile* mf); @@ -164,8 +162,11 @@ protected: std::string ConvertToSolutionPath(const char* path); - std::set<std::string> IsPartOfDefaultBuild(const std::string& project, - cmTarget const* target); + std::set<std::string> + IsPartOfDefaultBuild(OrderedTargetDependSet const& projectTargets, + cmTarget const* target); + bool IsDependedOn(OrderedTargetDependSet const& projectTargets, + cmTarget const* target); std::vector<std::string> Configurations; std::map<std::string, std::string> GUIDMap; @@ -176,7 +177,9 @@ protected: // Set during OutputSLNFile with the name of the current project. // There is one SLN file per project. std::string CurrentProject; - std::string PlatformName; + std::string GeneratorPlatform; + std::string DefaultPlatformName; + bool MasmEnabled; private: char* IntelProjectVersion; diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index e6672a8..745515b 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -36,7 +36,7 @@ public: if(p[0] == '\0') { return new cmGlobalVisualStudio8Generator( - name, "", ""); + name, ""); } if(p[0] != ' ') @@ -49,7 +49,7 @@ public: if(!strcmp(p, "Win64")) { return new cmGlobalVisualStudio8Generator( - name, "x64", "CMAKE_FORCE_WIN64"); + name, "x64"); } cmVisualStudioWCEPlatformParser parser(p); @@ -60,7 +60,7 @@ public: } cmGlobalVisualStudio8Generator* ret = new cmGlobalVisualStudio8Generator( - name, p, ""); + name, p); ret->WindowsCEVersion = parser.GetOSVersion(); return ret; } @@ -93,17 +93,11 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio8Generator::NewFactory() //---------------------------------------------------------------------------- cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator( - const std::string& name, const std::string& platformName, - const std::string& additionalPlatformDefinition) + const std::string& name, const std::string& platformName) : cmGlobalVisualStudio71Generator(platformName) { this->ProjectConfigurationSectionName = "ProjectConfigurationPlatforms"; this->Name = name; - - if (!additionalPlatformDefinition.empty()) - { - this->AdditionalPlatformDefinition = additionalPlatformDefinition; - } } //---------------------------------------------------------------------------- @@ -132,17 +126,31 @@ cmLocalGenerator *cmGlobalVisualStudio8Generator::CreateLocalGenerator() { cmLocalVisualStudio7Generator *lg = new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS8); - lg->SetPlatformName(this->GetPlatformName()); lg->SetExtraFlagTable(this->GetExtraFlagTableVS8()); lg->SetGlobalGenerator(this); return lg; } //---------------------------------------------------------------------------- -void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf) +void cmGlobalVisualStudio8Generator +::EnableLanguage(std::vector<std::string>const & lang, + cmMakefile *mf, bool optional) { - cmGlobalVisualStudio71Generator::AddPlatformDefinitions(mf); + for(std::vector<std::string>::const_iterator it = lang.begin(); + it != lang.end(); ++it) + { + if(*it == "ASM_MASM") + { + this->MasmEnabled = true; + } + } + this->AddPlatformDefinitions(mf); + cmGlobalVisualStudio7Generator::EnableLanguage(lang, mf, optional); +} +//---------------------------------------------------------------------------- +void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf) +{ if(this->TargetsWindowsCE()) { mf->AddDefinition("CMAKE_VS_WINCE_VERSION", @@ -151,6 +159,21 @@ void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf) } //---------------------------------------------------------------------------- +bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p, + cmMakefile* mf) +{ + if(this->DefaultPlatformName == "Win32") + { + this->GeneratorPlatform = p; + return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform("", mf); + } + else + { + return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform(p, mf); + } +} + +//---------------------------------------------------------------------------- // ouput standard header for dsw file void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout) { @@ -398,9 +421,7 @@ cmGlobalVisualStudio8Generator platformMapping : this->GetPlatformName()) << "\n"; } - bool needsDeploy = (type == cmTarget::EXECUTABLE || - type == cmTarget::SHARED_LIBRARY); - if(this->TargetsWindowsCE() && needsDeploy) + if(this->NeedsDeploy(type)) { fout << "\t\t{" << guid << "}." << *i << "|" << this->GetPlatformName() << ".Deploy.0 = " << *i << "|" @@ -412,6 +433,15 @@ cmGlobalVisualStudio8Generator } //---------------------------------------------------------------------------- +bool +cmGlobalVisualStudio8Generator::NeedsDeploy(cmTarget::TargetType type) const +{ + bool needsDeploy = (type == cmTarget::EXECUTABLE || + type == cmTarget::SHARED_LIBRARY); + return this->TargetsWindowsCE() && needsDeploy; +} + +//---------------------------------------------------------------------------- bool cmGlobalVisualStudio8Generator::ComputeTargetDepends() { // Skip over the cmGlobalVisualStudioGenerator implementation! diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index 2459c05..4b41ed7 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -24,8 +24,7 @@ class cmGlobalVisualStudio8Generator : public cmGlobalVisualStudio71Generator { public: cmGlobalVisualStudio8Generator(const std::string& name, - const std::string& platformName, - const std::string& additionalPlatformDefinition); + const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); ///! Get the name for the generator. @@ -37,14 +36,17 @@ public: ///! Create a local generator appropriate to this Global Generator virtual cmLocalGenerator *CreateLocalGenerator(); + virtual void EnableLanguage(std::vector<std::string>const& languages, + cmMakefile *, bool optional); virtual void AddPlatformDefinitions(cmMakefile* mf); + virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf); + /** * Override Configure and Generate to add the build-system check * target. */ virtual void Configure(); - virtual void Generate(); /** * Where does this version of Visual Studio look for macros for the @@ -68,6 +70,7 @@ public: return !this->WindowsCEVersion.empty(); } protected: + virtual void Generate(); virtual const char* GetIDEVersion() { return "8.0"; } virtual std::string FindDevEnvCommand(); @@ -76,6 +79,9 @@ protected: bool AddCheckTarget(); + /** Return true if the configuration needs to be deployed */ + virtual bool NeedsDeploy(cmTarget::TargetType type) const; + static cmIDEFlagTable const* GetExtraFlagTableVS8(); virtual void WriteSLNHeader(std::ostream& fout); virtual void WriteSolutionConfigurations(std::ostream& fout); diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx index c0051c7..1d73b5c 100644 --- a/Source/cmGlobalVisualStudio9Generator.cxx +++ b/Source/cmGlobalVisualStudio9Generator.cxx @@ -34,7 +34,7 @@ public: if(p[0] == '\0') { return new cmGlobalVisualStudio9Generator( - name, "", ""); + name, ""); } if(p[0] != ' ') @@ -47,13 +47,13 @@ public: if(!strcmp(p, "IA64")) { return new cmGlobalVisualStudio9Generator( - name, "Itanium", "CMAKE_FORCE_IA64"); + name, "Itanium"); } if(!strcmp(p, "Win64")) { return new cmGlobalVisualStudio9Generator( - name, "x64", "CMAKE_FORCE_WIN64"); + name, "x64"); } cmVisualStudioWCEPlatformParser parser(p); @@ -64,7 +64,7 @@ public: } cmGlobalVisualStudio9Generator* ret = new cmGlobalVisualStudio9Generator( - name, p, NULL); + name, p); ret->WindowsCEVersion = parser.GetOSVersion(); return ret; } @@ -98,10 +98,8 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory() //---------------------------------------------------------------------------- cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator( - const std::string& name, const std::string& platformName, - const std::string& additionalPlatformDefinition) - : cmGlobalVisualStudio8Generator(name, platformName, - additionalPlatformDefinition) + const std::string& name, const std::string& platformName) + : cmGlobalVisualStudio8Generator(name, platformName) { } @@ -117,21 +115,12 @@ cmLocalGenerator *cmGlobalVisualStudio9Generator::CreateLocalGenerator() { cmLocalVisualStudio7Generator *lg = new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS9); - lg->SetPlatformName(this->GetPlatformName()); lg->SetExtraFlagTable(this->GetExtraFlagTableVS8()); lg->SetGlobalGenerator(this); return lg; } //---------------------------------------------------------------------------- -void cmGlobalVisualStudio9Generator -::EnableLanguage(std::vector<std::string>const & lang, - cmMakefile *mf, bool optional) -{ - cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional); -} - -//---------------------------------------------------------------------------- std::string cmGlobalVisualStudio9Generator::GetUserMacrosDirectory() { std::string base; diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h index fb87bbe..0a191cd 100644 --- a/Source/cmGlobalVisualStudio9Generator.h +++ b/Source/cmGlobalVisualStudio9Generator.h @@ -25,19 +25,16 @@ class cmGlobalVisualStudio9Generator : { public: cmGlobalVisualStudio9Generator(const std::string& name, - const std::string& platformName, - const std::string& additionalPlatformDefinition); + const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); ///! create the correct local generator virtual cmLocalGenerator *CreateLocalGenerator(); /** - * Try to determine system infomation such as shared library + * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ - virtual void EnableLanguage(std::vector<std::string>const& languages, - cmMakefile *, bool optional); virtual void WriteSLNHeader(std::ostream& fout); /** diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index c5a0e29..2dab23c 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -23,7 +23,6 @@ //---------------------------------------------------------------------------- cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator() { - this->AdditionalPlatformDefinition = ""; } //---------------------------------------------------------------------------- @@ -478,15 +477,6 @@ void cmGlobalVisualStudioGenerator::FindMakeProgram(cmMakefile* mf) } //---------------------------------------------------------------------------- -void cmGlobalVisualStudioGenerator::AddPlatformDefinitions(cmMakefile* mf) -{ - if(!this->AdditionalPlatformDefinition.empty()) - { - mf->AddDefinition(this->AdditionalPlatformDefinition, "TRUE"); - } -} - -//---------------------------------------------------------------------------- std::string cmGlobalVisualStudioGenerator::GetUtilityDepend(cmTarget const* target) { diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 1ab8990..356f4d4 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -27,11 +27,6 @@ public: virtual ~cmGlobalVisualStudioGenerator(); /** - * Basic generate implementation for all VS generators. - */ - virtual void Generate(); - - /** * Configure CMake's Visual Studio macros file into the user's Visual * Studio macros directory. */ @@ -90,6 +85,8 @@ public: void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const; protected: + virtual void Generate(); + // Does this VS version link targets to each other if there are // dependencies in the SLN file? This was done for VS versions // below 8. @@ -97,8 +94,6 @@ protected: virtual const char* GetIDEVersion() = 0; - virtual void AddPlatformDefinitions(cmMakefile* mf); - virtual bool ComputeTargetDepends(); class VSDependSet: public std::set<std::string> {}; class VSDependMap: public std::map<cmTarget const*, VSDependSet> {}; @@ -111,7 +106,6 @@ protected: std::string GetUtilityDepend(cmTarget const* target); typedef std::map<cmTarget const*, std::string> UtilityDependsMap; UtilityDependsMap UtilityDepends; - std::string AdditionalPlatformDefinition; private: virtual std::string GetVSMakeProgram() = 0; diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h index 2057a42..0e577b5 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.h +++ b/Source/cmGlobalWatcomWMakeGenerator.h @@ -38,7 +38,7 @@ public: virtual cmLocalGenerator *CreateLocalGenerator(); /** - * Try to determine system infomation such as shared library + * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ virtual void EnableLanguage(std::vector<std::string>const& languages, diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 29a5955..13e6988 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -208,8 +208,11 @@ bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, if(this->XcodeVersion >= 30) { this->GeneratorToolset = ts; - mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", - this->GeneratorToolset.c_str()); + if(!this->GeneratorToolset.empty()) + { + mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", + this->GeneratorToolset.c_str()); + } return true; } else @@ -830,16 +833,14 @@ cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( const std::string &lang, cmSourceFile* sf) { - std::string fname = fullpath; - cmXCodeObject* fileRef = this->FileRefs[fname]; + std::string key = GetGroupMapKeyFromPath(cmtarget, fullpath); + cmXCodeObject* fileRef = this->FileRefs[key]; if(!fileRef) { fileRef = this->CreateObject(cmXCodeObject::PBXFileReference); - std::string comment = fname; - fileRef->SetComment(fname.c_str()); - this->FileRefs[fname] = fileRef; + fileRef->SetComment(fullpath); + this->FileRefs[key] = fileRef; } - std::string key = GetGroupMapKeyFromPath(cmtarget, fullpath); cmXCodeObject* group = this->GroupMap[key]; cmXCodeObject* children = group->GetObject("children"); if (!children->HasObject(fileRef)) @@ -864,24 +865,24 @@ cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( } if(fileType.empty()) { + // Compute the extension without leading '.'. + std::string ext = cmSystemTools::GetFilenameLastExtension(fullpath); + if(!ext.empty()) + { + ext = ext.substr(1); + } + // If fullpath references a directory, then we need to specify // lastKnownFileType as folder in order for Xcode to be able to // open the contents of the folder. // (Xcode 4.6 does not like explicitFileType=folder). if(cmSystemTools::FileIsDirectory(fullpath.c_str())) { - fileType = "folder"; + fileType = (ext == "xcassets"? "folder.assetcatalog" : "folder"); useLastKnownFileType = true; } else { - // Compute the extension without leading '.'. - std::string ext = cmSystemTools::GetFilenameLastExtension(fullpath); - if(!ext.empty()) - { - ext = ext.substr(1); - } - fileType = GetSourcecodeValueFromFileExtension( ext, lang, useLastKnownFileType); } @@ -1255,7 +1256,7 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget) // If the language is compiled as a source trust Xcode to link with it. cmTarget::LinkImplementation const* impl = - cmtarget.GetLinkImplementation("NOCONFIG", &cmtarget); + cmtarget.GetLinkImplementation("NOCONFIG"); for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); li != impl->Languages.end(); ++li) { @@ -2299,7 +2300,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, } } - buildSettings->AddAttribute("OTHER_LDFLAGS", + buildSettings->AddAttribute(this->GetTargetLinkFlagsVar(target), this->CreateString(extraLinkOptions.c_str())); buildSettings->AddAttribute("OTHER_REZFLAGS", this->CreateString("")); @@ -2527,6 +2528,22 @@ std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target, } //---------------------------------------------------------------------------- +const char* +cmGlobalXCodeGenerator::GetTargetLinkFlagsVar(cmTarget const& cmtarget) const +{ + if(this->XcodeVersion >= 60 && + (cmtarget.GetType() == cmTarget::STATIC_LIBRARY || + cmtarget.GetType() == cmTarget::OBJECT_LIBRARY)) + { + return "OTHER_LIBTOOLFLAGS"; + } + else + { + return "OTHER_LDFLAGS"; + } +} + +//---------------------------------------------------------------------------- const char* cmGlobalXCodeGenerator::GetTargetFileType(cmTarget& cmtarget) { switch(cmtarget.GetType()) @@ -2835,8 +2852,9 @@ void cmGlobalXCodeGenerator sep = " "; linkObjs += this->XCodeEscapePath(oi->c_str()); } - this->AppendBuildSettingAttribute(target, "OTHER_LDFLAGS", - linkObjs.c_str(), configName); + this->AppendBuildSettingAttribute( + target, this->GetTargetLinkFlagsVar(*cmtarget), + linkObjs.c_str(), configName); } // Skip link information for object libraries. @@ -2914,8 +2932,9 @@ void cmGlobalXCodeGenerator target->AddDependTarget(configName, li->Target->GetName()); } } - this->AppendBuildSettingAttribute(target, "OTHER_LDFLAGS", - linkLibs.c_str(), configName); + this->AppendBuildSettingAttribute( + target, this->GetTargetLinkFlagsVar(*cmtarget), + linkLibs.c_str(), configName); } } } diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index ae23e3b..9d7b784 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -44,7 +44,7 @@ public: virtual cmLocalGenerator *CreateLocalGenerator(); /** - * Try to determine system infomation such as shared library + * Try to determine system information such as shared library * extension, pthreads, byte order etc. */ virtual void EnableLanguage(std::vector<std::string>const& languages, @@ -64,13 +64,6 @@ public: std::vector<std::string> const& makeOptions = std::vector<std::string>() ); - /** - * Generate the all required files for building this project/tree. This - * basically creates a series of LocalGenerators for each directory and - * requests that they Generate. - */ - virtual void Generate(); - /** Append the subdirectory for the given configuration. */ virtual void AppendDirectoryForConfig(const std::string& prefix, const std::string& config, @@ -91,6 +84,8 @@ public: virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf); void AppendFlag(std::string& flags, std::string const& flag); +protected: + virtual void Generate(); private: cmXCodeObject* CreateOrGetPBXGroup(cmTarget& cmtarget, cmSourceGroup* sg); @@ -139,6 +134,7 @@ private: cmXCodeObject* buildPhases); void ForceLinkerLanguages(); void ForceLinkerLanguage(cmTarget& cmtarget); + const char* GetTargetLinkFlagsVar(cmTarget const& cmtarget) const; const char* GetTargetFileType(cmTarget& cmtarget); const char* GetTargetProductType(cmTarget& cmtarget); std::string AddConfigurations(cmXCodeObject* target, cmTarget& cmtarget); diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx index 1f3c066..0eb903d 100644 --- a/Source/cmIDEOptions.cxx +++ b/Source/cmIDEOptions.cxx @@ -152,18 +152,7 @@ void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry, } else if(entry->special & cmIDEFlagTable::SemicolonAppendable) { - std::map<std::string,std::string>::iterator itr; - itr = this->FlagMap.find(entry->IDEName); - if(itr != this->FlagMap.end()) - { - // Append to old value (if present) with semicolons; - itr->second += ";"; - itr->second += new_value; - } - else - { - this->FlagMap[entry->IDEName] = new_value; - } + this->FlagMap[entry->IDEName].push_back(new_value); } else { @@ -200,18 +189,47 @@ void cmIDEOptions::AddFlag(const char* flag, const char* value) } //---------------------------------------------------------------------------- +void cmIDEOptions::AddFlag(const char* flag, + std::vector<std::string> const& value) +{ + this->FlagMap[flag] = value; +} + +//---------------------------------------------------------------------------- +void cmIDEOptions::AppendFlag(std::string const& flag, + std::string const& value) +{ + this->FlagMap[flag].push_back(value); +} + +//---------------------------------------------------------------------------- +void cmIDEOptions::AppendFlag(std::string const& flag, + std::vector<std::string> const& value) +{ + FlagValue& fv = this->FlagMap[flag]; + std::copy(value.begin(), value.end(), std::back_inserter(fv)); +} + +//---------------------------------------------------------------------------- void cmIDEOptions::RemoveFlag(const char* flag) { this->FlagMap.erase(flag); } //---------------------------------------------------------------------------- +bool cmIDEOptions::HasFlag(std::string const& flag) const +{ + return this->FlagMap.find(flag) != this->FlagMap.end(); +} + +//---------------------------------------------------------------------------- const char* cmIDEOptions::GetFlag(const char* flag) { - std::map<std::string, std::string>::iterator i = this->FlagMap.find(flag); - if(i != this->FlagMap.end()) + // This method works only for single-valued flags! + std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(flag); + if(i != this->FlagMap.end() && i->second.size() == 1) { - return i->second.c_str(); + return i->second[0].c_str(); } return 0; } diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h index e7749ec..7386016 100644 --- a/Source/cmIDEOptions.h +++ b/Source/cmIDEOptions.h @@ -29,7 +29,12 @@ public: void AddDefines(const char* defines); void AddDefines(const std::vector<std::string> &defines); void AddFlag(const char* flag, const char* value); + void AddFlag(const char* flag, std::vector<std::string> const& value); + void AppendFlag(std::string const& flag, std::string const& value); + void AppendFlag(std::string const& flag, + std::vector<std::string> const& value); void RemoveFlag(const char* flag); + bool HasFlag(std::string const& flag) const; const char* GetFlag(const char* flag); protected: @@ -40,7 +45,23 @@ protected: // Then parse the command line flags specified in CMAKE_CXX_FLAGS // and CMAKE_C_FLAGS // and overwrite or add new values to this map - std::map<std::string, std::string> FlagMap; + class FlagValue: public std::vector<std::string> + { + typedef std::vector<std::string> derived; + public: + FlagValue& operator=(std::string const& r) + { + this->resize(1); + this->operator[](0) = r; + return *this; + } + FlagValue& operator=(std::vector<std::string> const& r) + { + this->derived::operator=(r); + return *this; + } + }; + std::map<std::string, FlagValue > FlagMap; // Preprocessor definitions. std::vector<std::string> Defines; diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 1141b01..f728c15 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -12,21 +12,23 @@ #include "cmIfCommand.h" #include "cmStringCommand.h" +#include "cmConditionEvaluator.h" + #include <stdlib.h> // required for atof #include <list> #include <cmsys/RegularExpression.hxx> static std::string cmIfCommandError( - cmMakefile* mf, std::vector<std::string> const& args) + cmMakefile* mf, std::vector<cmExpandedCommandArgument> const& args) { cmLocalGenerator* lg = mf->GetLocalGenerator(); std::string err = "given arguments:\n "; - for(std::vector<std::string>::const_iterator i = args.begin(); + for(std::vector<cmExpandedCommandArgument>::const_iterator i = args.begin(); i != args.end(); ++i) { err += " "; - err += lg->EscapeForCMake(*i); + err += lg->EscapeForCMake(i->GetValue()); } err += "\n"; return err; @@ -103,14 +105,16 @@ IsFunctionBlocked(const cmListFileFunction& lff, std::string errorString; - std::vector<std::string> expandedArguments; + std::vector<cmExpandedCommandArgument> expandedArguments; mf.ExpandArguments(this->Functions[c].Arguments, expandedArguments); cmake::MessageType messType; - bool isTrue = - cmIfCommand::IsTrue(expandedArguments, errorString, - &mf, messType); + + cmConditionEvaluator conditionEvaluator(mf); + + bool isTrue = conditionEvaluator.IsTrue( + expandedArguments, errorString, messType); if (errorString.size()) { @@ -185,13 +189,15 @@ bool cmIfCommand { std::string errorString; - std::vector<std::string> expandedArguments; + std::vector<cmExpandedCommandArgument> expandedArguments; this->Makefile->ExpandArguments(args, expandedArguments); cmake::MessageType status; - bool isTrue = - cmIfCommand::IsTrue(expandedArguments,errorString, - this->Makefile, status); + + cmConditionEvaluator conditionEvaluator(*(this->Makefile)); + + bool isTrue = conditionEvaluator.IsTrue( + expandedArguments, errorString, status); if (errorString.size()) { @@ -222,698 +228,3 @@ bool cmIfCommand return true; } - -namespace -{ - //========================================================================= - bool GetBooleanValue(std::string& arg, cmMakefile* mf) - { - // Check basic constants. - if (arg == "0") - { - return false; - } - if (arg == "1") - { - return true; - } - - // Check named constants. - if (cmSystemTools::IsOn(arg.c_str())) - { - return true; - } - if (cmSystemTools::IsOff(arg.c_str())) - { - return false; - } - - // Check for numbers. - if(!arg.empty()) - { - char* end; - double d = strtod(arg.c_str(), &end); - if(*end == '\0') - { - // The whole string is a number. Use C conversion to bool. - return d? true:false; - } - } - - // Check definition. - const char* def = mf->GetDefinition(arg); - return !cmSystemTools::IsOff(def); - } - - //========================================================================= - // Boolean value behavior from CMake 2.6.4 and below. - bool GetBooleanValueOld(std::string const& arg, cmMakefile* mf, bool one) - { - if(one) - { - // Old IsTrue behavior for single argument. - if(arg == "0") - { return false; } - else if(arg == "1") - { return true; } - else - { return !cmSystemTools::IsOff(mf->GetDefinition(arg)); } - } - else - { - // Old GetVariableOrNumber behavior. - const char* def = mf->GetDefinition(arg); - if(!def && atoi(arg.c_str())) - { - def = arg.c_str(); - } - return !cmSystemTools::IsOff(def); - } - } - - //========================================================================= - // returns the resulting boolean value - bool GetBooleanValueWithAutoDereference( - std::string &newArg, - cmMakefile *makefile, - std::string &errorString, - cmPolicies::PolicyStatus Policy12Status, - cmake::MessageType &status, - bool oneArg = false) - { - // Use the policy if it is set. - if (Policy12Status == cmPolicies::NEW) - { - return GetBooleanValue(newArg, makefile); - } - else if (Policy12Status == cmPolicies::OLD) - { - return GetBooleanValueOld(newArg, makefile, oneArg); - } - - // Check policy only if old and new results differ. - bool newResult = GetBooleanValue(newArg, makefile); - bool oldResult = GetBooleanValueOld(newArg, makefile, oneArg); - if(newResult != oldResult) - { - switch(Policy12Status) - { - case cmPolicies::WARN: - { - cmPolicies* policies = makefile->GetPolicies(); - errorString = "An argument named \"" + newArg - + "\" appears in a conditional statement. " - + policies->GetPolicyWarning(cmPolicies::CMP0012); - status = cmake::AUTHOR_WARNING; - } - case cmPolicies::OLD: - return oldResult; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - { - cmPolicies* policies = makefile->GetPolicies(); - errorString = "An argument named \"" + newArg - + "\" appears in a conditional statement. " - + policies->GetRequiredPolicyError(cmPolicies::CMP0012); - status = cmake::FATAL_ERROR; - } - case cmPolicies::NEW: - break; - } - } - return newResult; - } - - //========================================================================= - void IncrementArguments(std::list<std::string> &newArgs, - std::list<std::string>::iterator &argP1, - std::list<std::string>::iterator &argP2) - { - if (argP1 != newArgs.end()) - { - argP1++; - argP2 = argP1; - if (argP1 != newArgs.end()) - { - argP2++; - } - } - } - - //========================================================================= - // helper function to reduce code duplication - void HandlePredicate(bool value, int &reducible, - std::list<std::string>::iterator &arg, - std::list<std::string> &newArgs, - std::list<std::string>::iterator &argP1, - std::list<std::string>::iterator &argP2) - { - if(value) - { - *arg = "1"; - } - else - { - *arg = "0"; - } - newArgs.erase(argP1); - argP1 = arg; - IncrementArguments(newArgs,argP1,argP2); - reducible = 1; - } - - //========================================================================= - // helper function to reduce code duplication - void HandleBinaryOp(bool value, int &reducible, - std::list<std::string>::iterator &arg, - std::list<std::string> &newArgs, - std::list<std::string>::iterator &argP1, - std::list<std::string>::iterator &argP2) - { - if(value) - { - *arg = "1"; - } - else - { - *arg = "0"; - } - newArgs.erase(argP2); - newArgs.erase(argP1); - argP1 = arg; - IncrementArguments(newArgs,argP1,argP2); - reducible = 1; - } - - //========================================================================= - // level 0 processes parenthetical expressions - bool HandleLevel0(std::list<std::string> &newArgs, - cmMakefile *makefile, - std::string &errorString, - cmake::MessageType &status) - { - int reducible; - do - { - reducible = 0; - std::list<std::string>::iterator arg = newArgs.begin(); - while (arg != newArgs.end()) - { - if (*arg == "(") - { - // search for the closing paren for this opening one - std::list<std::string>::iterator argClose; - argClose = arg; - argClose++; - unsigned int depth = 1; - while (argClose != newArgs.end() && depth) - { - if (*argClose == "(") - { - depth++; - } - if (*argClose == ")") - { - depth--; - } - argClose++; - } - if (depth) - { - errorString = "mismatched parenthesis in condition"; - status = cmake::FATAL_ERROR; - return false; - } - // store the reduced args in this vector - std::vector<std::string> newArgs2; - - // copy to the list structure - std::list<std::string>::iterator argP1 = arg; - argP1++; - for(; argP1 != argClose; argP1++) - { - newArgs2.push_back(*argP1); - } - newArgs2.pop_back(); - // now recursively invoke IsTrue to handle the values inside the - // parenthetical expression - bool value = - cmIfCommand::IsTrue(newArgs2, errorString, makefile, status); - if(value) - { - *arg = "1"; - } - else - { - *arg = "0"; - } - argP1 = arg; - argP1++; - // remove the now evaluated parenthetical expression - newArgs.erase(argP1,argClose); - } - ++arg; - } - } - while (reducible); - return true; - } - - //========================================================================= - // level one handles most predicates except for NOT - bool HandleLevel1(std::list<std::string> &newArgs, - cmMakefile *makefile, - std::string &, cmake::MessageType &) - { - int reducible; - do - { - reducible = 0; - std::list<std::string>::iterator arg = newArgs.begin(); - std::list<std::string>::iterator argP1; - std::list<std::string>::iterator argP2; - while (arg != newArgs.end()) - { - argP1 = arg; - IncrementArguments(newArgs,argP1,argP2); - // does a file exist - if (*arg == "EXISTS" && argP1 != newArgs.end()) - { - HandlePredicate( - cmSystemTools::FileExists((argP1)->c_str()), - reducible, arg, newArgs, argP1, argP2); - } - // does a directory with this name exist - if (*arg == "IS_DIRECTORY" && argP1 != newArgs.end()) - { - HandlePredicate( - cmSystemTools::FileIsDirectory((argP1)->c_str()), - reducible, arg, newArgs, argP1, argP2); - } - // does a symlink with this name exist - if (*arg == "IS_SYMLINK" && argP1 != newArgs.end()) - { - HandlePredicate( - cmSystemTools::FileIsSymlink((argP1)->c_str()), - reducible, arg, newArgs, argP1, argP2); - } - // is the given path an absolute path ? - if (*arg == "IS_ABSOLUTE" && argP1 != newArgs.end()) - { - HandlePredicate( - cmSystemTools::FileIsFullPath((argP1)->c_str()), - reducible, arg, newArgs, argP1, argP2); - } - // does a command exist - if (*arg == "COMMAND" && argP1 != newArgs.end()) - { - HandlePredicate( - makefile->CommandExists((argP1)->c_str()), - reducible, arg, newArgs, argP1, argP2); - } - // does a policy exist - if (*arg == "POLICY" && argP1 != newArgs.end()) - { - cmPolicies::PolicyID pid; - HandlePredicate( - makefile->GetPolicies()->GetPolicyID((argP1)->c_str(), pid), - reducible, arg, newArgs, argP1, argP2); - } - // does a target exist - if (*arg == "TARGET" && argP1 != newArgs.end()) - { - HandlePredicate( - makefile->FindTargetToUse(*argP1)?true:false, - reducible, arg, newArgs, argP1, argP2); - } - // is a variable defined - if (*arg == "DEFINED" && argP1 != newArgs.end()) - { - size_t argP1len = argP1->size(); - bool bdef = false; - if(argP1len > 4 && argP1->substr(0, 4) == "ENV{" && - argP1->operator[](argP1len-1) == '}') - { - std::string env = argP1->substr(4, argP1len-5); - bdef = cmSystemTools::GetEnv(env.c_str())?true:false; - } - else - { - bdef = makefile->IsDefinitionSet(*(argP1)); - } - HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2); - } - ++arg; - } - } - while (reducible); - return true; - } - - //========================================================================= - // level two handles most binary operations except for AND OR - bool HandleLevel2(std::list<std::string> &newArgs, - cmMakefile *makefile, - std::string &errorString, - cmake::MessageType &status) - { - int reducible; - const char *def; - const char *def2; - do - { - reducible = 0; - std::list<std::string>::iterator arg = newArgs.begin(); - std::list<std::string>::iterator argP1; - std::list<std::string>::iterator argP2; - while (arg != newArgs.end()) - { - argP1 = arg; - IncrementArguments(newArgs,argP1,argP2); - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - *(argP1) == "MATCHES") - { - def = cmIfCommand::GetVariableOrString(*arg, makefile); - const char* rex = (argP2)->c_str(); - makefile->ClearMatches(); - cmsys::RegularExpression regEntry; - if ( !regEntry.compile(rex) ) - { - cmOStringStream error; - error << "Regular expression \"" << rex << "\" cannot compile"; - errorString = error.str(); - status = cmake::FATAL_ERROR; - return false; - } - if (regEntry.find(def)) - { - makefile->StoreMatches(regEntry); - *arg = "1"; - } - else - { - *arg = "0"; - } - newArgs.erase(argP2); - newArgs.erase(argP1); - argP1 = arg; - IncrementArguments(newArgs,argP1,argP2); - reducible = 1; - } - - if (argP1 != newArgs.end() && *arg == "MATCHES") - { - *arg = "0"; - newArgs.erase(argP1); - argP1 = arg; - IncrementArguments(newArgs,argP1,argP2); - reducible = 1; - } - - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - (*(argP1) == "LESS" || *(argP1) == "GREATER" || - *(argP1) == "EQUAL")) - { - def = cmIfCommand::GetVariableOrString(*arg, makefile); - def2 = cmIfCommand::GetVariableOrString(*argP2, makefile); - double lhs; - double rhs; - bool result; - if(sscanf(def, "%lg", &lhs) != 1 || - sscanf(def2, "%lg", &rhs) != 1) - { - result = false; - } - else if (*(argP1) == "LESS") - { - result = (lhs < rhs); - } - else if (*(argP1) == "GREATER") - { - result = (lhs > rhs); - } - else - { - result = (lhs == rhs); - } - HandleBinaryOp(result, - reducible, arg, newArgs, argP1, argP2); - } - - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - (*(argP1) == "STRLESS" || - *(argP1) == "STREQUAL" || - *(argP1) == "STRGREATER")) - { - def = cmIfCommand::GetVariableOrString(*arg, makefile); - def2 = cmIfCommand::GetVariableOrString(*argP2, makefile); - int val = strcmp(def,def2); - bool result; - if (*(argP1) == "STRLESS") - { - result = (val < 0); - } - else if (*(argP1) == "STRGREATER") - { - result = (val > 0); - } - else // strequal - { - result = (val == 0); - } - HandleBinaryOp(result, - reducible, arg, newArgs, argP1, argP2); - } - - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - (*(argP1) == "VERSION_LESS" || *(argP1) == "VERSION_GREATER" || - *(argP1) == "VERSION_EQUAL")) - { - def = cmIfCommand::GetVariableOrString(*arg, makefile); - def2 = cmIfCommand::GetVariableOrString(*argP2, makefile); - cmSystemTools::CompareOp op = cmSystemTools::OP_EQUAL; - if(*argP1 == "VERSION_LESS") - { - op = cmSystemTools::OP_LESS; - } - else if(*argP1 == "VERSION_GREATER") - { - op = cmSystemTools::OP_GREATER; - } - bool result = cmSystemTools::VersionCompare(op, def, def2); - HandleBinaryOp(result, - reducible, arg, newArgs, argP1, argP2); - } - - // is file A newer than file B - if (argP1 != newArgs.end() && argP2 != newArgs.end() && - *(argP1) == "IS_NEWER_THAN") - { - int fileIsNewer=0; - bool success=cmSystemTools::FileTimeCompare(arg->c_str(), - (argP2)->c_str(), - &fileIsNewer); - HandleBinaryOp( - (success==false || fileIsNewer==1 || fileIsNewer==0), - reducible, arg, newArgs, argP1, argP2); - } - - ++arg; - } - } - while (reducible); - return true; - } - - //========================================================================= - // level 3 handles NOT - bool HandleLevel3(std::list<std::string> &newArgs, - cmMakefile *makefile, - std::string &errorString, - cmPolicies::PolicyStatus Policy12Status, - cmake::MessageType &status) - { - int reducible; - do - { - reducible = 0; - std::list<std::string>::iterator arg = newArgs.begin(); - std::list<std::string>::iterator argP1; - std::list<std::string>::iterator argP2; - while (arg != newArgs.end()) - { - argP1 = arg; - IncrementArguments(newArgs,argP1,argP2); - if (argP1 != newArgs.end() && *arg == "NOT") - { - bool rhs = GetBooleanValueWithAutoDereference(*argP1, makefile, - errorString, - Policy12Status, - status); - HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2); - } - ++arg; - } - } - while (reducible); - return true; - } - - //========================================================================= - // level 4 handles AND OR - bool HandleLevel4(std::list<std::string> &newArgs, - cmMakefile *makefile, - std::string &errorString, - cmPolicies::PolicyStatus Policy12Status, - cmake::MessageType &status) - { - int reducible; - bool lhs; - bool rhs; - do - { - reducible = 0; - std::list<std::string>::iterator arg = newArgs.begin(); - std::list<std::string>::iterator argP1; - std::list<std::string>::iterator argP2; - while (arg != newArgs.end()) - { - argP1 = arg; - IncrementArguments(newArgs,argP1,argP2); - if (argP1 != newArgs.end() && *(argP1) == "AND" && - argP2 != newArgs.end()) - { - lhs = GetBooleanValueWithAutoDereference(*arg, makefile, - errorString, - Policy12Status, - status); - rhs = GetBooleanValueWithAutoDereference(*argP2, makefile, - errorString, - Policy12Status, - status); - HandleBinaryOp((lhs && rhs), - reducible, arg, newArgs, argP1, argP2); - } - - if (argP1 != newArgs.end() && *(argP1) == "OR" && - argP2 != newArgs.end()) - { - lhs = GetBooleanValueWithAutoDereference(*arg, makefile, - errorString, - Policy12Status, - status); - rhs = GetBooleanValueWithAutoDereference(*argP2, makefile, - errorString, - Policy12Status, - status); - HandleBinaryOp((lhs || rhs), - reducible, arg, newArgs, argP1, argP2); - } - ++arg; - } - } - while (reducible); - return true; - } -} - - -//========================================================================= -// order of operations, -// 1. ( ) -- parenthetical groups -// 2. IS_DIRECTORY EXISTS COMMAND DEFINED etc predicates -// 3. MATCHES LESS GREATER EQUAL STRLESS STRGREATER STREQUAL etc binary ops -// 4. NOT -// 5. AND OR -// -// There is an issue on whether the arguments should be values of references, -// for example IF (FOO AND BAR) should that compare the strings FOO and BAR -// or should it really do IF (${FOO} AND ${BAR}) Currently IS_DIRECTORY -// EXISTS COMMAND and DEFINED all take values. EQUAL, LESS and GREATER can -// take numeric values or variable names. STRLESS and STRGREATER take -// variable names but if the variable name is not found it will use the name -// directly. AND OR take variables or the values 0 or 1. - - -bool cmIfCommand::IsTrue(const std::vector<std::string> &args, - std::string &errorString, cmMakefile *makefile, - cmake::MessageType &status) -{ - errorString = ""; - - // handle empty invocation - if (args.size() < 1) - { - return false; - } - - // store the reduced args in this vector - std::list<std::string> newArgs; - - // copy to the list structure - for(unsigned int i = 0; i < args.size(); ++i) - { - newArgs.push_back(args[i]); - } - - // now loop through the arguments and see if we can reduce any of them - // we do this multiple times. Once for each level of precedence - // parens - if (!HandleLevel0(newArgs, makefile, errorString, status)) - { - return false; - } - //predicates - if (!HandleLevel1(newArgs, makefile, errorString, status)) - { - return false; - } - // binary ops - if (!HandleLevel2(newArgs, makefile, errorString, status)) - { - return false; - } - - // used to store the value of policy CMP0012 for performance - cmPolicies::PolicyStatus Policy12Status = - makefile->GetPolicyStatus(cmPolicies::CMP0012); - - // NOT - if (!HandleLevel3(newArgs, makefile, errorString, - Policy12Status, status)) - { - return false; - } - // AND OR - if (!HandleLevel4(newArgs, makefile, errorString, - Policy12Status, status)) - { - return false; - } - - // now at the end there should only be one argument left - if (newArgs.size() != 1) - { - errorString = "Unknown arguments specified"; - status = cmake::FATAL_ERROR; - return false; - } - - return GetBooleanValueWithAutoDereference(*(newArgs.begin()), - makefile, - errorString, - Policy12Status, - status, true); -} - -//========================================================================= -const char* cmIfCommand::GetVariableOrString(const std::string& str, - const cmMakefile* mf) -{ - const char* def = mf->GetDefinition(str); - if(!def) - { - def = str.c_str(); - } - return def; -} diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h index 814c052..689efce 100644 --- a/Source/cmIfCommand.h +++ b/Source/cmIfCommand.h @@ -70,17 +70,9 @@ public: */ virtual bool IsScriptable() const { return true; } - // this is a shared function for both If and Else to determine if the - // arguments were valid, and if so, was the response true. If there is - // an error, the errorString will be set. - static bool IsTrue(const std::vector<std::string> &args, - std::string &errorString, cmMakefile *mf, - cmake::MessageType &status); - - // Get a definition from the makefile. If it doesn't exist, - // return the original string. - static const char* GetVariableOrString(const std::string& str, - const cmMakefile* mf); + // Filter the given variable definition based on policy CMP0054. + static const char* GetDefinitionIfUnquoted( + const cmMakefile* mf, cmExpandedCommandArgument const& argument); cmTypeMacro(cmIfCommand, cmCommand); }; diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 0041122..ec500d9 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -25,9 +25,12 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator(cmTarget& target, const cmInstallCommandArguments& args, bool impLib, bool forceOpt = false) { + cmInstallGenerator::MessageLevel message = + cmInstallGenerator::SelectMessageLevel(target.GetMakefile()); return new cmInstallTargetGenerator(target, args.GetDestination().c_str(), impLib, args.GetPermissions().c_str(), args.GetConfigurations(), args.GetComponent().c_str(), + message, args.GetOptional() || forceOpt); } @@ -36,10 +39,13 @@ static cmInstallFilesGenerator* CreateInstallFilesGenerator( const std::vector<std::string>& absFiles, const cmInstallCommandArguments& args, bool programs) { + cmInstallGenerator::MessageLevel message = + cmInstallGenerator::SelectMessageLevel(mf); return new cmInstallFilesGenerator(mf, absFiles, args.GetDestination().c_str(), programs, args.GetPermissions().c_str(), args.GetConfigurations(), args.GetComponent().c_str(), + message, args.GetRename().c_str(), args.GetOptional()); } @@ -911,6 +917,7 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args) Doing doing = DoingDirs; bool in_match_mode = false; bool optional = false; + bool message_never = false; std::vector<std::string> dirs; const char* destination = 0; std::string permissions_file; @@ -949,6 +956,21 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args) optional = true; doing = DoingNone; } + else if(args[i] == "MESSAGE_NEVER") + { + if(in_match_mode) + { + cmOStringStream e; + e << args[0] << " does not allow \"" + << args[i] << "\" after PATTERN or REGEX."; + this->SetError(e.str()); + return false; + } + + // Mark the rule as quiet. + message_never = true; + doing = DoingNone; + } else if(args[i] == "PATTERN") { // Switch to a new pattern match rule. @@ -1208,6 +1230,9 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args) return false; } + cmInstallGenerator::MessageLevel message = + cmInstallGenerator::SelectMessageLevel(this->Makefile, message_never); + // Create the directory install generator. this->Makefile->AddInstallGenerator( new cmInstallDirectoryGenerator(dirs, destination, @@ -1215,6 +1240,7 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args) permissions_dir.c_str(), configurations, component.c_str(), + message, literal_args.c_str(), optional)); @@ -1333,13 +1359,16 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) } } + cmInstallGenerator::MessageLevel message = + cmInstallGenerator::SelectMessageLevel(this->Makefile); + // Create the export install generator. cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator( exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(), ica.GetConfigurations(), - ica.GetComponent().c_str(), fname.c_str(), + ica.GetComponent().c_str(), message, fname.c_str(), name_space.GetCString(), exportOld.IsEnabled(), this->Makefile); this->Makefile->AddInstallGenerator(exportGenerator); diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx index ddf7d08..8c13bab 100644 --- a/Source/cmInstallDirectoryGenerator.cxx +++ b/Source/cmInstallDirectoryGenerator.cxx @@ -21,9 +21,11 @@ cmInstallDirectoryGenerator const char* dir_permissions, std::vector<std::string> const& configurations, const char* component, + MessageLevel message, const char* literal_args, bool optional): - cmInstallGenerator(dest, configurations, component), Directories(dirs), + cmInstallGenerator(dest, configurations, component, message), + Directories(dirs), FilePermissions(file_permissions), DirPermissions(dir_permissions), LiteralArguments(literal_args), Optional(optional) { diff --git a/Source/cmInstallDirectoryGenerator.h b/Source/cmInstallDirectoryGenerator.h index d76ef3c..165ab91 100644 --- a/Source/cmInstallDirectoryGenerator.h +++ b/Source/cmInstallDirectoryGenerator.h @@ -26,6 +26,7 @@ public: const char* dir_permissions, std::vector<std::string> const& configurations, const char* component, + MessageLevel message, const char* literal_args, bool optional = false); virtual ~cmInstallDirectoryGenerator(); diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index 9a17052..ddfd6c5 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -32,10 +32,11 @@ cmInstallExportGenerator::cmInstallExportGenerator( const char* file_permissions, std::vector<std::string> const& configurations, const char* component, + MessageLevel message, const char* filename, const char* name_space, bool exportOld, cmMakefile* mf) - :cmInstallGenerator(destination, configurations, component) + :cmInstallGenerator(destination, configurations, component, message) ,ExportSet(exportSet) ,FilePermissions(file_permissions) ,FileName(filename) diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index 37b5593..eb8c28b 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -30,6 +30,7 @@ public: const char* dest, const char* file_permissions, const std::vector<std::string>& configurations, const char* component, + MessageLevel message, const char* filename, const char* name_space, bool exportOld, cmMakefile* mf); ~cmInstallExportGenerator(); diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx index 7eabbef..f106e1a 100644 --- a/Source/cmInstallFilesCommand.cxx +++ b/Source/cmInstallFilesCommand.cxx @@ -132,11 +132,13 @@ void cmInstallFilesCommand::CreateInstallGenerator() const std::string no_component = this->Makefile->GetSafeDefinition( "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); std::vector<std::string> no_configurations; + cmInstallGenerator::MessageLevel message = + cmInstallGenerator::SelectMessageLevel(this->Makefile); this->Makefile->AddInstallGenerator( new cmInstallFilesGenerator(this->Makefile, this->Files, destination.c_str(), false, no_permissions, no_configurations, - no_component.c_str(), no_rename)); + no_component.c_str(), message, no_rename)); } diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index b2be82e..91b102a 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -23,9 +23,10 @@ cmInstallFilesGenerator const char* file_permissions, std::vector<std::string> const& configurations, const char* component, + MessageLevel message, const char* rename, bool optional): - cmInstallGenerator(dest, configurations, component), + cmInstallGenerator(dest, configurations, component, message), Makefile(mf), Files(files), Programs(programs), FilePermissions(file_permissions), diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h index 23bf935..0dbd712 100644 --- a/Source/cmInstallFilesGenerator.h +++ b/Source/cmInstallFilesGenerator.h @@ -28,6 +28,7 @@ public: const char* file_permissions, std::vector<std::string> const& configurations, const char* component, + MessageLevel message, const char* rename, bool optional = false); virtual ~cmInstallFilesGenerator(); diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx index 9370e48..b261cbf 100644 --- a/Source/cmInstallGenerator.cxx +++ b/Source/cmInstallGenerator.cxx @@ -11,16 +11,19 @@ ============================================================================*/ #include "cmInstallGenerator.h" +#include "cmMakefile.h" #include "cmSystemTools.h" //---------------------------------------------------------------------------- cmInstallGenerator ::cmInstallGenerator(const char* destination, std::vector<std::string> const& configurations, - const char* component): + const char* component, + MessageLevel message): cmScriptGenerator("CMAKE_INSTALL_CONFIG_NAME", configurations), Destination(destination? destination:""), - Component(component? component:"") + Component(component? component:""), + Message(message) { } @@ -96,6 +99,13 @@ void cmInstallGenerator { os << " OPTIONAL"; } + switch(this->Message) + { + case MessageDefault: break; + case MessageAlways: os << " MESSAGE_ALWAYS"; break; + case MessageLazy: os << " MESSAGE_LAZY"; break; + case MessageNever: os << " MESSAGE_NEVER"; break; + } if(permissions_file && *permissions_file) { os << " PERMISSIONS" << permissions_file; @@ -180,3 +190,27 @@ std::string cmInstallGenerator::GetInstallDestination() const result += this->Destination; return result; } + +//---------------------------------------------------------------------------- +cmInstallGenerator::MessageLevel +cmInstallGenerator::SelectMessageLevel(cmMakefile* mf, bool never) +{ + if(never) + { + return MessageNever; + } + std::string m = mf->GetSafeDefinition("CMAKE_INSTALL_MESSAGE"); + if(m == "ALWAYS") + { + return MessageAlways; + } + if(m == "LAZY") + { + return MessageLazy; + } + if(m == "NEVER") + { + return MessageNever; + } + return MessageDefault; +} diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h index c72e9e9..38aac91 100644 --- a/Source/cmInstallGenerator.h +++ b/Source/cmInstallGenerator.h @@ -16,6 +16,7 @@ #include "cmScriptGenerator.h" class cmLocalGenerator; +class cmMakefile; /** \class cmInstallGenerator * \brief Support class for generating install scripts. @@ -24,9 +25,18 @@ class cmLocalGenerator; class cmInstallGenerator: public cmScriptGenerator { public: + enum MessageLevel + { + MessageDefault, + MessageAlways, + MessageLazy, + MessageNever + }; + cmInstallGenerator(const char* destination, std::vector<std::string> const& configurations, - const char* component); + const char* component, + MessageLevel message); virtual ~cmInstallGenerator(); void AddInstallRule( @@ -50,6 +60,9 @@ public: /** Test if this generator installs something for a given configuration. */ bool InstallsForConfig(const std::string& config); + /** Select message level from CMAKE_INSTALL_MESSAGE or 'never'. */ + static MessageLevel SelectMessageLevel(cmMakefile* mf, bool never = false); + protected: virtual void GenerateScript(std::ostream& os); @@ -58,6 +71,7 @@ protected: // Information shared by most generator types. std::string Destination; std::string Component; + MessageLevel Message; }; #endif diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx index 597f7ee..0405769 100644 --- a/Source/cmInstallProgramsCommand.cxx +++ b/Source/cmInstallProgramsCommand.cxx @@ -93,11 +93,13 @@ void cmInstallProgramsCommand::FinalPass() std::string no_component = this->Makefile->GetSafeDefinition( "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); std::vector<std::string> no_configurations; + cmInstallGenerator::MessageLevel message = + cmInstallGenerator::SelectMessageLevel(this->Makefile); this->Makefile->AddInstallGenerator( new cmInstallFilesGenerator(this->Makefile, this->Files, destination.c_str(), true, no_permissions, no_configurations, - no_component.c_str(), no_rename)); + no_component.c_str(), message, no_rename)); } /** diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx index 1ecf021..933aa07 100644 --- a/Source/cmInstallScriptGenerator.cxx +++ b/Source/cmInstallScriptGenerator.cxx @@ -15,7 +15,7 @@ cmInstallScriptGenerator ::cmInstallScriptGenerator(const char* script, bool code, const char* component) : - cmInstallGenerator(0, std::vector<std::string>(), component), + cmInstallGenerator(0, std::vector<std::string>(), component, MessageDefault), Script(script), Code(code) { } diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index ec2b518..d689c89 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -24,8 +24,10 @@ cmInstallTargetGenerator ::cmInstallTargetGenerator(cmTarget& t, const char* dest, bool implib, const char* file_permissions, std::vector<std::string> const& configurations, - const char* component, bool optional): - cmInstallGenerator(dest, configurations, component), Target(&t), + const char* component, + MessageLevel message, + bool optional): + cmInstallGenerator(dest, configurations, component, message), Target(&t), ImportLibrary(implib), FilePermissions(file_permissions), Optional(optional) { this->ActionsPerConfig = true; @@ -213,6 +215,20 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, filesFrom.push_back(from1); filesTo.push_back(to1); } + else if(this->Target->IsCFBundleOnApple()) + { + // Install the whole app bundle directory. + type = cmInstallType_DIRECTORY; + literal_args += " USE_SOURCE_PERMISSIONS"; + + std::string targetNameBase = targetName.substr(0, targetName.find('/')); + + std::string from1 = fromDirConfig + targetNameBase; + std::string to1 = toDir + targetName; + + filesFrom.push_back(from1); + filesTo.push_back(to1); + } else { bool haveNamelink = false; @@ -661,46 +677,72 @@ cmInstallTargetGenerator return; } - if(this->Target->GetMakefile()->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + cmMakefile* mf = this->Target->GetMakefile(); + + if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { // If using install_name_tool, set up the rules to modify the rpaths. std::string installNameTool = - this->Target->GetMakefile()-> - GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL"); + mf->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL"); std::vector<std::string> oldRuntimeDirs, newRuntimeDirs; cli->GetRPath(oldRuntimeDirs, false); cli->GetRPath(newRuntimeDirs, true); - // Note: These paths are kept unique to avoid install_name_tool corruption. - std::set<std::string> runpaths; - for(std::vector<std::string>::const_iterator i = oldRuntimeDirs.begin(); - i != oldRuntimeDirs.end(); ++i) - { - std::string runpath = this->Target->GetMakefile()->GetLocalGenerator()-> - GetGlobalGenerator()->ExpandCFGIntDir(*i, config); + std::string darwin_major_version_s = + mf->GetSafeDefinition("DARWIN_MAJOR_VERSION"); - if(runpaths.find(runpath) == runpaths.end()) - { - runpaths.insert(runpath); - os << indent << "execute_process(COMMAND " << installNameTool << "\n"; - os << indent << " -delete_rpath \"" << runpath << "\"\n"; - os << indent << " \"" << toDestDirPath << "\")\n"; - } + std::stringstream ss(darwin_major_version_s); + int darwin_major_version; + ss >> darwin_major_version; + if(!ss.fail() && darwin_major_version <= 9 && + (!oldRuntimeDirs.empty() || !newRuntimeDirs.empty()) + ) + { + cmOStringStream msg; + msg << "WARNING: Target \"" << this->Target->GetName() + << "\" has runtime paths which cannot be changed during install. " + << "To change runtime paths, OS X version 10.6 or newer is required. " + << "Therefore, runtime paths will not be changed when installing. " + << "CMAKE_BUILD_WITH_INSTALL_RPATH may be used to work around" + " this limitation."; + mf->IssueMessage(cmake::WARNING, msg.str()); } - - runpaths.clear(); - for(std::vector<std::string>::const_iterator i = newRuntimeDirs.begin(); - i != newRuntimeDirs.end(); ++i) + else { - std::string runpath = this->Target->GetMakefile()->GetLocalGenerator()-> - GetGlobalGenerator()->ExpandCFGIntDir(*i, config); + // Note: These paths are kept unique to avoid + // install_name_tool corruption. + std::set<std::string> runpaths; + for(std::vector<std::string>::const_iterator i = oldRuntimeDirs.begin(); + i != oldRuntimeDirs.end(); ++i) + { + std::string runpath = + mf->GetLocalGenerator()-> + GetGlobalGenerator()->ExpandCFGIntDir(*i, config); - if(runpaths.find(runpath) == runpaths.end()) + if(runpaths.find(runpath) == runpaths.end()) + { + runpaths.insert(runpath); + os << indent << "execute_process(COMMAND " << installNameTool <<"\n"; + os << indent << " -delete_rpath \"" << runpath << "\"\n"; + os << indent << " \"" << toDestDirPath << "\")\n"; + } + } + + runpaths.clear(); + for(std::vector<std::string>::const_iterator i = newRuntimeDirs.begin(); + i != newRuntimeDirs.end(); ++i) { - os << indent << "execute_process(COMMAND " << installNameTool << "\n"; - os << indent << " -add_rpath \"" << runpath << "\"\n"; - os << indent << " \"" << toDestDirPath << "\")\n"; + std::string runpath = + mf->GetLocalGenerator()-> + GetGlobalGenerator()->ExpandCFGIntDir(*i, config); + + if(runpaths.find(runpath) == runpaths.end()) + { + os << indent << "execute_process(COMMAND " << installNameTool <<"\n"; + os << indent << " -add_rpath \"" << runpath << "\"\n"; + os << indent << " \"" << toDestDirPath << "\")\n"; + } } } } diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 0f21da7..7e5cc71 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -24,11 +24,11 @@ class cmInstallTargetGenerator: public cmInstallGenerator public: cmInstallTargetGenerator( cmTarget& t, const char* dest, bool implib, - const char* file_permissions = "", - std::vector<std::string> const& configurations - = std::vector<std::string>(), - const char* component = "Unspecified", - bool optional = false + const char* file_permissions, + std::vector<std::string> const& configurations, + const char* component, + MessageLevel message, + bool optional ); virtual ~cmInstallTargetGenerator(); diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx index 7813fcc..4b53752 100644 --- a/Source/cmInstalledFile.cxx +++ b/Source/cmInstalledFile.cxx @@ -77,6 +77,13 @@ void cmInstalledFile::AppendProperty(cmMakefile const* mf, } //---------------------------------------------------------------------------- +bool cmInstalledFile::HasProperty( + const std::string& prop) const +{ + return this->Properties.find(prop) != this->Properties.end(); +} + +//---------------------------------------------------------------------------- bool cmInstalledFile::GetProperty( const std::string& prop, std::string& value) const { @@ -111,3 +118,14 @@ bool cmInstalledFile::GetPropertyAsBool(const std::string& prop) const bool isSet = this->GetProperty(prop, value); return isSet && cmSystemTools::IsOn(value.c_str()); } + +//---------------------------------------------------------------------------- +void cmInstalledFile::GetPropertyAsList(const std::string& prop, + std::vector<std::string>& list) const +{ + std::string value; + this->GetProperty(prop, value); + + list.clear(); + cmSystemTools::ExpandListArgument(value, list); +} diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h index df28221..7134a4e 100644 --- a/Source/cmInstalledFile.h +++ b/Source/cmInstalledFile.h @@ -62,10 +62,15 @@ public: void AppendProperty(cmMakefile const* mf, const std::string& prop, const char* value,bool asString=false); + bool HasProperty(const std::string& prop) const; + bool GetProperty(const std::string& prop, std::string& value) const; bool GetPropertyAsBool(const std::string& prop) const; + void GetPropertyAsList(const std::string& prop, + std::vector<std::string>& list) const; + void SetName(cmMakefile* mf, const std::string& name); std::string const& GetName() const; diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 705666d..3fc5b69 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -142,7 +142,8 @@ bool cmListFile::ParseFile(const char* filename, bool topLevel, cmMakefile *mf) { - if(!cmSystemTools::FileExists(filename)) + if(!cmSystemTools::FileExists(filename) || + cmSystemTools::FileIsDirectory(filename)) { return false; } diff --git a/Source/cmListFileLexer.c b/Source/cmListFileLexer.c index bfa388e..af4fc3d 100644 --- a/Source/cmListFileLexer.c +++ b/Source/cmListFileLexer.c @@ -369,8 +369,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 23 -#define YY_END_OF_BUFFER 24 +#define YY_NUM_RULES 24 +#define YY_END_OF_BUFFER 25 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -381,10 +381,10 @@ struct yy_trans_info static yyconst flex_int16_t yy_accept[77] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, - 24, 13, 21, 1, 15, 3, 13, 5, 6, 7, - 22, 22, 16, 18, 19, 20, 10, 11, 8, 12, - 9, 4, 13, 0, 13, 0, 21, 0, 0, 7, - 13, 0, 13, 0, 2, 0, 13, 16, 0, 17, + 25, 13, 22, 1, 16, 3, 13, 5, 6, 7, + 15, 23, 17, 19, 20, 21, 10, 11, 8, 12, + 9, 4, 13, 0, 13, 0, 22, 0, 0, 7, + 13, 0, 13, 0, 2, 0, 13, 17, 0, 18, 10, 8, 4, 0, 14, 0, 0, 0, 0, 14, 0, 0, 14, 0, 0, 0, 2, 14, 0, 0, 0, 0, 0, 0, 0, 0 @@ -523,10 +523,10 @@ static yyconst flex_int16_t yy_chk[253] = } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[24] = +static yyconst flex_int32_t yy_rule_can_match_eol[25] = { 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, - 0, 0, 0, 0, }; +1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, }; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. @@ -615,7 +615,7 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer); -#line 621 "cmListFileLexer.c" +#line 628 "cmListFileLexer.c" #define INITIAL 0 #define STRING 1 @@ -850,7 +850,7 @@ YY_DECL #line 91 "cmListFileLexer.in.l" -#line 858 "cmListFileLexer.c" +#line 865 "cmListFileLexer.c" if ( !yyg->yy_init ) { @@ -1111,75 +1111,84 @@ case 15: YY_RULE_SETUP #line 215 "cmListFileLexer.in.l" { + lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted; + cmListFileLexerSetToken(lexer, yytext, yyleng); + lexer->column += yyleng; + return 1; +} +case 16: +YY_RULE_SETUP +#line 222 "cmListFileLexer.in.l" +{ lexer->token.type = cmListFileLexer_Token_ArgumentQuoted; cmListFileLexerSetToken(lexer, "", 0); lexer->column += yyleng; BEGIN(STRING); } YY_BREAK -case 16: +case 17: YY_RULE_SETUP -#line 222 "cmListFileLexer.in.l" +#line 229 "cmListFileLexer.in.l" { cmListFileLexerAppend(lexer, yytext, yyleng); lexer->column += yyleng; } YY_BREAK -case 17: -/* rule 17 can match eol */ +case 18: +/* rule 18 can match eol */ YY_RULE_SETUP -#line 227 "cmListFileLexer.in.l" +#line 234 "cmListFileLexer.in.l" { /* Continuation: text is not part of string */ ++lexer->line; lexer->column = 1; } YY_BREAK -case 18: -/* rule 18 can match eol */ +case 19: +/* rule 19 can match eol */ YY_RULE_SETUP -#line 233 "cmListFileLexer.in.l" +#line 240 "cmListFileLexer.in.l" { cmListFileLexerAppend(lexer, yytext, yyleng); ++lexer->line; lexer->column = 1; } YY_BREAK -case 19: +case 20: YY_RULE_SETUP -#line 239 "cmListFileLexer.in.l" +#line 246 "cmListFileLexer.in.l" { lexer->column += yyleng; BEGIN(INITIAL); return 1; } -case 20: +case 21: YY_RULE_SETUP -#line 245 "cmListFileLexer.in.l" +#line 252 "cmListFileLexer.in.l" { cmListFileLexerAppend(lexer, yytext, yyleng); lexer->column += yyleng; } YY_BREAK case YY_STATE_EOF(STRING): -#line 250 "cmListFileLexer.in.l" +#line 257 "cmListFileLexer.in.l" { lexer->token.type = cmListFileLexer_Token_BadString; BEGIN(INITIAL); return 1; } -case 21: +case 22: YY_RULE_SETUP -#line 256 "cmListFileLexer.in.l" +#line 263 "cmListFileLexer.in.l" { lexer->token.type = cmListFileLexer_Token_Space; cmListFileLexerSetToken(lexer, yytext, yyleng); lexer->column += yyleng; return 1; } -case 22: +case 23: YY_RULE_SETUP -#line 263 "cmListFileLexer.in.l" +#line 270 "cmListFileLexer.in.l" { lexer->token.type = cmListFileLexer_Token_BadCharacter; cmListFileLexerSetToken(lexer, yytext, yyleng); @@ -1188,18 +1197,18 @@ YY_RULE_SETUP } case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(COMMENT): -#line 270 "cmListFileLexer.in.l" +#line 277 "cmListFileLexer.in.l" { lexer->token.type = cmListFileLexer_Token_None; cmListFileLexerSetToken(lexer, 0, 0); return 0; } -case 23: +case 24: YY_RULE_SETUP -#line 276 "cmListFileLexer.in.l" +#line 283 "cmListFileLexer.in.l" ECHO; YY_BREAK -#line 1220 "cmListFileLexer.c" +#line 1238 "cmListFileLexer.c" case YY_END_OF_BUFFER: { @@ -2320,7 +2329,7 @@ void cmListFileLexer_yyfree (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 276 "cmListFileLexer.in.l" +#line 282 "cmListFileLexer.in.l" diff --git a/Source/cmListFileLexer.in.l b/Source/cmListFileLexer.in.l index ed4bf6b..a520c72 100644 --- a/Source/cmListFileLexer.in.l +++ b/Source/cmListFileLexer.in.l @@ -212,6 +212,13 @@ LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t[=])*\" return 1; } +\[ { + lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted; + cmListFileLexerSetToken(lexer, yytext, yyleng); + lexer->column += yyleng; + return 1; +} + \" { lexer->token.type = cmListFileLexer_Token_ArgumentQuoted; cmListFileLexerSetToken(lexer, "", 0); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index c8c8c79..50e279b 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -681,7 +681,7 @@ void cmLocalGenerator::AddBuildTargetRule(const std::string& llang, objVector.push_back(ofname); this->AddCustomCommandToCreateObject(ofname.c_str(), llang, *(*i), target); - objs += this->Convert(ofname,START_OUTPUT,MAKEFILE); + objs += this->Convert(ofname,START_OUTPUT,SHELL); objs += " "; } } @@ -1287,9 +1287,11 @@ cmLocalGenerator::ConvertToOutputForExisting(RelativeRoot remote, //---------------------------------------------------------------------------- std::string cmLocalGenerator::ConvertToIncludeReference(std::string const& path, - OutputFormat format) + OutputFormat format, + bool forceFullPaths) { - return this->ConvertToOutputForExisting(path, START_OUTPUT, format); + return this->ConvertToOutputForExisting( + path, forceFullPaths? FULL : START_OUTPUT, format); } //---------------------------------------------------------------------------- @@ -1297,6 +1299,7 @@ std::string cmLocalGenerator::GetIncludeFlags( const std::vector<std::string> &includes, cmGeneratorTarget* target, const std::string& lang, + bool forceFullPaths, bool forResponseFile, const std::string& config) { @@ -1401,7 +1404,7 @@ std::string cmLocalGenerator::GetIncludeFlags( flagUsed = true; } std::string includePath = - this->ConvertToIncludeReference(*i, shellFormat); + this->ConvertToIncludeReference(*i, shellFormat, forceFullPaths); if(quotePaths && includePath.size() && includePath[0] != '\"') { includeFlags << "\""; @@ -1861,7 +1864,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, ((useWatcomQuote) ? WATCOMQUOTE : SHELL); bool escapeAllowMakeVars = !forResponseFile; cmOStringStream fout; - const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); + std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); cmComputeLinkInformation* pcli = tgt.Target->GetLinkInformation(config); if(!pcli) { @@ -2229,7 +2232,10 @@ AddCompilerRequirementFlag(std::string &flags, cmTarget* target, "does not know the compile flags to use to enable it."; this->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str()); } - this->AppendFlags(flags, opt); + else + { + this->AppendFlagEscape(flags, opt); + } return; } @@ -2275,7 +2281,7 @@ AddCompilerRequirementFlag(std::string &flags, cmTarget* target, if (const char *opt = target->GetMakefile()->GetDefinition(option_flag)) { - this->AppendFlags(flags, opt); + this->AppendFlagEscape(flags, opt); return; } } @@ -2752,7 +2758,7 @@ std::string cmLocalGenerator::ConvertToOutputFormat(const std::string& source, { std::string result = source; // Convert it to an output path. - if (output == MAKEFILE) + if (output == MAKERULE) { result = cmSystemTools::ConvertToOutputPath(result.c_str()); } @@ -2995,6 +3001,17 @@ cmLocalGenerator::ConvertToRelativePath(const std::vector<std::string>& local, } //---------------------------------------------------------------------------- +class cmInstallTargetGeneratorLocal: public cmInstallTargetGenerator +{ +public: + cmInstallTargetGeneratorLocal(cmTarget& t, const char* dest, bool implib): + cmInstallTargetGenerator( + t, dest, implib, "", std::vector<std::string>(), "Unspecified", + cmInstallGenerator::SelectMessageLevel(t.GetMakefile()), + false) {} +}; + +//---------------------------------------------------------------------------- void cmLocalGenerator ::GenerateTargetInstallRules( @@ -3039,7 +3056,8 @@ cmLocalGenerator case cmTarget::MODULE_LIBRARY: { // Use a target install generator. - cmInstallTargetGenerator g(l->second, destination.c_str(), false); + cmInstallTargetGeneratorLocal + g(l->second, destination.c_str(), false); g.Generate(os, config, configurationTypes); } break; @@ -3049,16 +3067,19 @@ cmLocalGenerator // Special code to handle DLL. Install the import library // to the normal destination and the DLL to the runtime // destination. - cmInstallTargetGenerator g1(l->second, destination.c_str(), true); + cmInstallTargetGeneratorLocal + g1(l->second, destination.c_str(), true); g1.Generate(os, config, configurationTypes); // We also skip over the leading slash given by the user. destination = l->second.GetRuntimeInstallPath().substr(1); cmSystemTools::ConvertToUnixSlashes(destination); - cmInstallTargetGenerator g2(l->second, destination.c_str(), false); + cmInstallTargetGeneratorLocal + g2(l->second, destination.c_str(), false); g2.Generate(os, config, configurationTypes); #else // Use a target install generator. - cmInstallTargetGenerator g(l->second, destination.c_str(), false); + cmInstallTargetGeneratorLocal + g(l->second, destination.c_str(), false); g.Generate(os, config, configurationTypes); #endif } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index ad73073..3a9d5be 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -106,7 +106,7 @@ public: * path setting */ enum RelativeRoot { NONE, FULL, HOME, START, HOME_OUTPUT, START_OUTPUT }; - enum OutputFormat { UNCHANGED, MAKEFILE, SHELL, WATCOMQUOTE, RESPONSE }; + enum OutputFormat { UNCHANGED, MAKERULE, SHELL, WATCOMQUOTE, RESPONSE }; std::string ConvertToOutputFormat(const std::string& source, OutputFormat output); std::string Convert(const std::string& remote, RelativeRoot local, @@ -160,6 +160,7 @@ public: std::string GetIncludeFlags(const std::vector<std::string> &includes, cmGeneratorTarget* target, const std::string& lang, + bool forceFullPaths = false, bool forResponseFile = false, const std::string& config = ""); @@ -215,7 +216,8 @@ public: OutputFormat format = SHELL); virtual std::string ConvertToIncludeReference(std::string const& path, - OutputFormat format = SHELL); + OutputFormat format = SHELL, + bool forceFullPaths = false); /** Called from command-line hook to clear dependencies. */ virtual void ClearDependencies(cmMakefile* /* mf */, diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 2ac8363..398b55a 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -151,9 +151,10 @@ cmLocalNinjaGenerator::ConvertToLinkReference(std::string const& lib, std::string cmLocalNinjaGenerator::ConvertToIncludeReference(std::string const& path, - OutputFormat format) + OutputFormat format, + bool forceFullPaths) { - return this->Convert(path, HOME_OUTPUT, format); + return this->Convert(path, forceFullPaths? FULL : HOME_OUTPUT, format); } //---------------------------------------------------------------------------- @@ -189,6 +190,7 @@ void cmLocalNinjaGenerator::WriteBuildFileTop() { // For the build file. this->WriteProjectHeader(this->GetBuildFileStream()); + this->WriteNinjaRequiredVersion(this->GetBuildFileStream()); this->WriteNinjaFilesInclusion(this->GetBuildFileStream()); // For the rule file. @@ -205,6 +207,30 @@ void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os) cmGlobalNinjaGenerator::WriteDivider(os); } +void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os) +{ + // Default required version + // Ninja generator uses 'deps' and 'msvc_deps_prefix' introduced in 1.3 + std::string requiredVersion = "1.3"; + + // Ninja generator uses the 'console' pool if available (>= 1.5) + std::string usedVersion = this->GetGlobalNinjaGenerator()->ninjaVersion(); + if(cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, + usedVersion.c_str(), + "1.5") == false) + { + requiredVersion = "1.5"; + } + + cmGlobalNinjaGenerator::WriteComment(os, + "Minimal version of Ninja required by this file"); + os + << "ninja_required_version = " + << requiredVersion + << std::endl << std::endl + ; +} + void cmLocalNinjaGenerator::WritePools(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 11321b8..1d27224 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -108,7 +108,8 @@ public: protected: virtual std::string ConvertToIncludeReference(std::string const& path, - OutputFormat format = SHELL); + OutputFormat format = SHELL, + bool forceFullPaths = false); private: @@ -117,6 +118,7 @@ private: void WriteBuildFileTop(); void WriteProjectHeader(std::ostream& os); + void WriteNinjaRequiredVersion(std::ostream& os); void WriteNinjaFilesInclusion(std::ostream& os); void WriteProcessedMakefile(std::ostream& os); void WritePools(std::ostream& os); diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 94e45e5..23513fa 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -630,7 +630,7 @@ cmLocalUnixMakefileGenerator3 // Construct the left hand side of the rule. replace = target; - std::string tgt = this->Convert(replace,HOME_OUTPUT,MAKEFILE); + std::string tgt = this->Convert(replace,HOME_OUTPUT,MAKERULE); const char* space = ""; if(tgt.size() == 1) { @@ -663,7 +663,7 @@ cmLocalUnixMakefileGenerator3 dep != depends.end(); ++dep) { replace = *dep; - replace = this->Convert(replace,HOME_OUTPUT,MAKEFILE); + replace = this->Convert(replace,HOME_OUTPUT,MAKERULE); os << cmMakeSafe(tgt) << space << ": " << cmMakeSafe(replace) << "\n"; } } diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index 5db735f..c14fb2b 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -1101,7 +1101,8 @@ void cmLocalVisualStudio6Generator } } // find link libraries - const cmTarget::LinkLibraryVectorType& libs = target.GetLinkLibraries(); + const cmTarget::LinkLibraryVectorType& libs = + target.GetLinkLibrariesForVS6(); cmTarget::LinkLibraryVectorType::const_iterator j; for(j = libs.begin(); j != libs.end(); ++j) { diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index a6c6e8d..eb45423 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -44,11 +44,20 @@ private: extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[]; +static void cmConvertToWindowsSlash(std::string& s) +{ + std::string::size_type pos = 0; + while((pos = s.find('/', pos)) != std::string::npos) + { + s[pos] = '\\'; + pos++; + } +} + //---------------------------------------------------------------------------- cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator(VSVersion v): cmLocalVisualStudioGenerator(v) { - this->PlatformName = "Win32"; this->ExtraFlagTable = 0; this->Internal = new cmLocalVisualStudio7GeneratorInternals(this); } @@ -647,8 +656,11 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, { mfcFlag = "0"; } + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator); fout << "\t\t<Configuration\n" - << "\t\t\tName=\"" << configName << "|" << this->PlatformName << "\"\n" + << "\t\t\tName=\"" << configName + << "|" << gg->GetPlatformName() << "\"\n" << "\t\t\tOutputDirectory=\"" << configName << "\"\n"; // This is an internal type to Visual Studio, it seems that: // 4 == static library @@ -784,6 +796,20 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, << "\t\t\tUseOfMFC=\"" << mfcFlag << "\"\n" << "\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n"; + if (this->FortranProject) + { + // Intel Fortran >= 15.0 uses TargetName property. + std::string targetNameFull = target.GetFullName(configName); + std::string targetName = + cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull); + std::string targetExt = + cmSystemTools::GetFilenameLastExtension(targetNameFull); + fout << + "\t\t\tTargetName=\"" << this->EscapeForXML(targetName) << "\"\n" + "\t\t\tTargetExt=\"" << this->EscapeForXML(targetExt) << "\"\n" + ; + } + // If unicode is enabled change the character set to unicode, if not // then default to MBCS. if(targetOptions.UsingUnicode()) @@ -860,6 +886,31 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, } } fout << "/>\n"; // end of <Tool Name=VCCLCompilerTool + if(gg->IsMasmEnabled() && !this->FortranProject) + { + Options masmOptions(this, Options::MasmCompiler, 0, 0); + fout << + "\t\t\t<Tool\n" + "\t\t\t\tName=\"MASM\"\n" + "\t\t\t\tIncludePaths=\"" + ; + const char* sep = ""; + for(i = includes.begin(); i != includes.end(); ++i) + { + std::string inc = *i; + cmConvertToWindowsSlash(inc); + fout << sep << this->EscapeForXML(inc); + sep = ";"; + } + fout << "\"\n"; + // Use same preprocessor definitions as VCCLCompilerTool. + targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n", + "ASM_MASM"); + masmOptions.OutputFlagMap(fout, "\t\t\t\t"); + fout << + "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n" + "\t\t\t/>\n"; + } tool = "VCCustomBuildTool"; if(this->FortranProject) { @@ -896,11 +947,11 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, } fout << "\"\n"; fout << "\t\t\t\tMkTypLibCompatible=\"false\"\n"; - if( this->PlatformName == "x64" ) + if( gg->GetPlatformName() == "x64" ) { fout << "\t\t\t\tTargetEnvironment=\"3\"\n"; } - else if( this->PlatformName == "ia64" ) + else if( gg->GetPlatformName() == "ia64" ) { fout << "\t\t\t\tTargetEnvironment=\"2\"\n"; } @@ -1011,7 +1062,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, if(!this->ModuleDefinitionFile.empty()) { std::string defFile = - this->ConvertToXMLOutputPath(this->ModuleDefinitionFile.c_str()); + this->ConvertToOptionallyRelativeOutputPath(this->ModuleDefinitionFile); linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str()); } switch(target.GetType()) @@ -1640,6 +1691,8 @@ bool cmLocalVisualStudio7Generator std::ostream &fout, const std::string& libName, std::vector<std::string> *configs) { + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); const std::vector<const cmSourceFile *> &sourceFiles = sg->GetSourceFiles(); std::vector<cmSourceGroup> const& children = sg->GetGroupChildren(); @@ -1691,11 +1744,12 @@ bool cmLocalVisualStudio7Generator else if(!fcinfo.FileConfigMap.empty()) { const char* aCompilerTool = "VCCLCompilerTool"; - const char* lang = "CXX"; + const char* ppLang = "CXX"; if(this->FortranProject) { aCompilerTool = "VFFortranCompilerTool"; } + std::string const& lang = (*sf)->GetLanguage(); std::string ext = (*sf)->GetExtension(); ext = cmSystemTools::LowerCase(ext); if(ext == "idl") @@ -1709,7 +1763,7 @@ bool cmLocalVisualStudio7Generator if(ext == "rc") { aCompilerTool = "VCResourceCompilerTool"; - lang = "RC"; + ppLang = "RC"; if(this->FortranProject) { aCompilerTool = "VFResourceCompilerTool"; @@ -1723,6 +1777,11 @@ bool cmLocalVisualStudio7Generator aCompilerTool = "VFCustomBuildTool"; } } + if (gg->IsMasmEnabled() && !this->FortranProject && + lang == "ASM_MASM") + { + aCompilerTool = "MASM"; + } for(std::map<std::string, cmLVS7GFileConfig>::const_iterator fci = fcinfo.FileConfigMap.begin(); fci != fcinfo.FileConfigMap.end(); ++fci) @@ -1730,7 +1789,7 @@ bool cmLocalVisualStudio7Generator cmLVS7GFileConfig const& fc = fci->second; fout << "\t\t\t\t<FileConfiguration\n" << "\t\t\t\t\tName=\"" << fci->first - << "|" << this->PlatformName << "\""; + << "|" << gg->GetPlatformName() << "\""; if(fc.ExcludedFromBuild) { fout << " ExcludedFromBuild=\"true\""; @@ -1759,7 +1818,7 @@ bool cmLocalVisualStudio7Generator fileOptions.OutputFlagMap(fout, "\t\t\t\t\t"); fileOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t\t", "\n", - lang); + ppLang); } if(!fc.AdditionalDeps.empty()) { @@ -1800,6 +1859,9 @@ WriteCustomRule(std::ostream& fout, const cmCustomCommand& command, FCInfo& fcinfo) { + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); + // Write the rule for each configuration. std::vector<std::string>::iterator i; std::vector<std::string> *configs = @@ -1820,7 +1882,8 @@ WriteCustomRule(std::ostream& fout, cmCustomCommandGenerator ccg(command, *i, this->Makefile); cmLVS7GFileConfig const& fc = fcinfo.FileConfigMap[*i]; fout << "\t\t\t\t<FileConfiguration\n"; - fout << "\t\t\t\t\tName=\"" << *i << "|" << this->PlatformName << "\">\n"; + fout << "\t\t\t\t\tName=\"" << *i << "|" + << gg->GetPlatformName() << "\">\n"; if(!fc.CompileFlags.empty()) { fout << "\t\t\t\t\t<Tool\n" @@ -2030,7 +2093,7 @@ cmLocalVisualStudio7Generator fout<< "\tKeyword=\"" << keyword << "\">\n" << "\tProjectGUID=\"{" << gg->GetGUID(libName.c_str()) << "}\">\n" << "\t<Platforms>\n" - << "\t\t<Platform\n\t\t\tName=\"" << this->PlatformName << "\"/>\n" + << "\t\t<Platform\n\t\t\tName=\"" << gg->GetPlatformName() << "\"/>\n" << "\t</Platforms>\n"; } @@ -2085,8 +2148,18 @@ cmLocalVisualStudio7Generator::WriteProjectStart(std::ostream& fout, } fout << "\tKeyword=\"" << keyword << "\">\n" << "\t<Platforms>\n" - << "\t\t<Platform\n\t\t\tName=\"" << this->PlatformName << "\"/>\n" + << "\t\t<Platform\n\t\t\tName=\"" << gg->GetPlatformName() << "\"/>\n" << "\t</Platforms>\n"; + if(gg->IsMasmEnabled()) + { + fout << + "\t<ToolFiles>\n" + "\t\t<DefaultToolFile\n" + "\t\t\tFileName=\"masm.rules\"\n" + "\t\t/>\n" + "\t</ToolFiles>\n" + ; + } } diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index 6c04559..c2caa26 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -53,8 +53,6 @@ public: */ void SetBuildType(BuildType,const std::string& name); - void SetPlatformName(const std::string& n) { this->PlatformName = n;} - void SetExtraFlagTable(cmVS7FlagTable const* table) { this->ExtraFlagTable = table; } virtual std::string GetTargetDirectory(cmTarget const&) const; @@ -124,7 +122,6 @@ private: std::string ModuleDefinitionFile; bool FortranProject; bool WindowsCEProject; - std::string PlatformName; // Win32 or x64 cmLocalVisualStudio7GeneratorInternals* Internal; }; diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index 3bf4f43..d26c2ea 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -40,7 +40,9 @@ public: VS9 = 90, VS10 = 100, VS11 = 110, - VS12 = 120 + VS12 = 120, + /* VS13 = 130 was skipped */ + VS14 = 140 }; cmLocalVisualStudioGenerator(VSVersion v); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 630957f..0bd1624 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -989,7 +989,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs, // Choose a source file on which to store the custom command. cmSourceFile* file = 0; - if(!main_dependency.empty()) + if(!commandLines.empty() && !main_dependency.empty()) { // The main dependency was specified. Use it unless a different // custom command already used it. @@ -1010,11 +1010,9 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs, file = 0; } } - else + else if (!file) { - // The main dependency does not have a custom command or we are - // allowed to replace it. Use it to store the command. - file = this->GetOrCreateSource(main_dependency); + file = this->CreateSource(main_dependency); } } @@ -1041,7 +1039,10 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs, } // Create a cmSourceFile for the rule file. - file = this->GetOrCreateSource(outName, true); + if (!file) + { + file = this->CreateSource(outName, true); + } file->SetProperty("__CMAKE_RULE", "1"); } @@ -1055,16 +1056,16 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs, } } - // Construct a complete list of dependencies. - std::vector<std::string> depends2(depends); - if(!main_dependency.empty()) - { - depends2.push_back(main_dependency); - } - // Attach the custom command to the file. if(file) { + // Construct a complete list of dependencies. + std::vector<std::string> depends2(depends); + if(!main_dependency.empty()) + { + depends2.push_back(main_dependency); + } + cmCustomCommand* cc = new cmCustomCommand(this, outputs, depends2, commandLines, comment, workingDir); @@ -1256,28 +1257,31 @@ cmMakefile::AddUtilityCommand(const std::string& utilityName, } // Store the custom command in the target. - std::string force = this->GetStartOutputDirectory(); - force += cmake::GetCMakeFilesDirectory(); - force += "/"; - force += utilityName; - std::string no_main_dependency = ""; - bool no_replace = false; - this->AddCustomCommandToOutput(force, depends, - no_main_dependency, - commandLines, comment, - workingDirectory, no_replace, - escapeOldStyle); - cmSourceFile* sf = target->AddSourceCMP0049(force); - - // The output is not actually created so mark it symbolic. - if(sf) - { - sf->SetProperty("SYMBOLIC", "1"); - } - else - { - cmSystemTools::Error("Could not get source file entry for ", - force.c_str()); + if (!commandLines.empty() || !depends.empty()) + { + std::string force = this->GetStartOutputDirectory(); + force += cmake::GetCMakeFilesDirectory(); + force += "/"; + force += utilityName; + std::string no_main_dependency = ""; + bool no_replace = false; + this->AddCustomCommandToOutput(force, depends, + no_main_dependency, + commandLines, comment, + workingDirectory, no_replace, + escapeOldStyle); + cmSourceFile* sf = target->AddSourceCMP0049(force); + + // The output is not actually created so mark it symbolic. + if(sf) + { + sf->SetProperty("SYMBOLIC", "1"); + } + else + { + cmSystemTools::Error("Could not get source file entry for ", + force.c_str()); + } } return target; } @@ -3288,6 +3292,7 @@ void cmMakefile::PopFunctionBlockerBarrier(bool reportError) this->FunctionBlockerBarriers.pop_back(); } +//---------------------------------------------------------------------------- bool cmMakefile::ExpandArguments( std::vector<cmListFileArgument> const& inArgs, std::vector<std::string>& outArgs) const @@ -3324,6 +3329,47 @@ bool cmMakefile::ExpandArguments( } //---------------------------------------------------------------------------- +bool cmMakefile::ExpandArguments( + std::vector<cmListFileArgument> const& inArgs, + std::vector<cmExpandedCommandArgument>& outArgs) const +{ + std::vector<cmListFileArgument>::const_iterator i; + std::string value; + outArgs.reserve(inArgs.size()); + for(i = inArgs.begin(); i != inArgs.end(); ++i) + { + // No expansion in a bracket argument. + if(i->Delim == cmListFileArgument::Bracket) + { + outArgs.push_back(cmExpandedCommandArgument(i->Value, true)); + continue; + } + // Expand the variables in the argument. + value = i->Value; + this->ExpandVariablesInString(value, false, false, false, + i->FilePath, i->Line, + false, false); + + // If the argument is quoted, it should be one argument. + // Otherwise, it may be a list of arguments. + if(i->Delim == cmListFileArgument::Quoted) + { + outArgs.push_back(cmExpandedCommandArgument(value, true)); + } + else + { + std::vector<std::string> stringArgs; + cmSystemTools::ExpandListArgument(value, stringArgs); + for(size_t j = 0; j < stringArgs.size(); ++j) + { + outArgs.push_back(cmExpandedCommandArgument(stringArgs[j], false)); + } + } + } + return !cmSystemTools::GetFatalErrorOccured(); +} + +//---------------------------------------------------------------------------- void cmMakefile::AddFunctionBlocker(cmFunctionBlocker* fb) { if(!this->CallStack.empty()) @@ -3451,6 +3497,19 @@ cmSourceFile* cmMakefile::GetSource(const std::string& sourceName) const } //---------------------------------------------------------------------------- +cmSourceFile* cmMakefile::CreateSource(const std::string& sourceName, + bool generated) +{ + cmSourceFile* sf = new cmSourceFile(this, sourceName); + if(generated) + { + sf->SetProperty("GENERATED", "1"); + } + this->SourceFiles.push_back(sf); + return sf; +} + +//---------------------------------------------------------------------------- cmSourceFile* cmMakefile::GetOrCreateSource(const std::string& sourceName, bool generated) { @@ -3460,13 +3519,7 @@ cmSourceFile* cmMakefile::GetOrCreateSource(const std::string& sourceName, } else { - cmSourceFile* sf = new cmSourceFile(this, sourceName); - if(generated) - { - sf->SetProperty("GENERATED", "1"); - } - this->SourceFiles.push_back(sf); - return sf; + return this->CreateSource(sourceName, generated); } } @@ -3499,7 +3552,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, const std::string& targetName, bool fast, const std::vector<std::string> *cmakeArgs, - std::string *output) + std::string& output) { this->Internal->IsSourceFileTryCompile = fast; // does the binary directory exist ? If not create it... @@ -3537,6 +3590,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, cm.SetHomeOutputDirectory(bindir); cm.SetStartDirectory(srcdir); cm.SetStartOutputDirectory(bindir); + cm.SetGeneratorPlatform(this->GetCMakeInstance()->GetGeneratorPlatform()); cm.SetGeneratorToolset(this->GetCMakeInstance()->GetGeneratorToolset()); cm.LoadCache(); if(!gg->IsMultiConfig()) @@ -4927,12 +4981,14 @@ void cmMakefile::PopPolicyBarrier(bool reportError) this->PolicyBarriers.pop_back(); } +//---------------------------------------------------------------------------- bool cmMakefile::SetPolicyVersion(const char *version) { return this->GetCMakeInstance()->GetPolicies()-> ApplyPolicyVersion(this,version); } +//---------------------------------------------------------------------------- cmPolicies *cmMakefile::GetPolicies() const { if (!this->GetCMakeInstance()) @@ -4943,6 +4999,23 @@ cmPolicies *cmMakefile::GetPolicies() const } //---------------------------------------------------------------------------- +bool cmMakefile::HasCMP0054AlreadyBeenReported( + cmListFileContext context) const +{ + cmCMP0054Id id(context); + + bool alreadyReported = + this->CMP0054ReportedIds.find(id) != this->CMP0054ReportedIds.end(); + + if(!alreadyReported) + { + this->CMP0054ReportedIds.insert(id); + } + + return alreadyReported; +} + +//---------------------------------------------------------------------------- void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm) { /* Record the setting of every policy. */ diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index d5ffd98..164290a 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -21,6 +21,7 @@ #include "cmTarget.h" #include "cmNewLineStyle.h" #include "cmGeneratorTarget.h" +#include "cmExpandedCommandArgument.h" #include "cmake.h" #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -130,7 +131,7 @@ public: const std::string& projectName, const std::string& targetName, bool fast, const std::vector<std::string> *cmakeArgs, - std::string *output); + std::string& output); bool GetIsSourceFileTryCompile() const; @@ -375,7 +376,35 @@ public: /** * Get the Policies Instance */ - cmPolicies *GetPolicies() const; + cmPolicies *GetPolicies() const; + + struct cmCMP0054Id + { + cmCMP0054Id(cmListFileContext const& context): + Context(context) + { + + } + + bool operator< (cmCMP0054Id const& id) const + { + if(this->Context.FilePath != id.Context.FilePath) + return this->Context.FilePath < id.Context.FilePath; + + return this->Context.Line < id.Context.Line; + } + + cmListFileContext Context; + }; + + mutable std::set<cmCMP0054Id> CMP0054ReportedIds; + + /** + * Determine if the given context, name pair has already been reported + * in context of CMP0054. + */ + bool HasCMP0054AlreadyBeenReported( + cmListFileContext context) const; /** * Add an auxiliary directory to the build. @@ -560,6 +589,13 @@ public: */ cmSourceFile* GetSource(const std::string& sourceName) const; + /** Create the source file and return it. generated + * indicates if it is a generated file, this is used in determining + * how to create the source file instance e.g. name + */ + cmSourceFile* CreateSource(const std::string& sourceName, + bool generated = false); + /** Get a cmSourceFile pointer for a given source name, if the name is * not found, then create the source file and return it. generated * indicates if it is a generated file, this is used in determining @@ -763,6 +799,10 @@ public: */ bool ExpandArguments(std::vector<cmListFileArgument> const& inArgs, std::vector<std::string>& outArgs) const; + + bool ExpandArguments(std::vector<cmListFileArgument> const& inArgs, + std::vector<cmExpandedCommandArgument>& outArgs) const; + /** * Get the instance */ diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 403f6e6..1f8f686 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -218,7 +218,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << this->LocalGenerator->IncludeDirective << " " << root << this->Convert(dependFileNameFull, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE) + cmLocalGenerator::MAKERULE) << "\n\n"; if(!this->NoRuleMessages) @@ -229,7 +229,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << this->LocalGenerator->IncludeDirective << " " << root << this->Convert(this->ProgressFileNameFull, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE) + cmLocalGenerator::MAKERULE) << "\n\n"; } @@ -262,7 +262,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() << this->LocalGenerator->IncludeDirective << " " << root << this->Convert(this->FlagFileNameFull, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE) + cmLocalGenerator::MAKERULE) << "\n\n"; } @@ -361,9 +361,13 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() for(std::set<std::string>::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"; + std::string flags = this->GetFlags(*l); + std::string defines = this->GetDefines(*l); + // Escape comment characters so they do not terminate assignment. + cmSystemTools::ReplaceString(flags, "#", "\\#"); + cmSystemTools::ReplaceString(defines, "#", "\\#"); + *this->FlagFileStream << *l << "_FLAGS = " << flags << "\n\n"; + *this->FlagFileStream << *l << "_DEFINES = " << defines << "\n\n"; } } @@ -1958,7 +1962,7 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, std::string includeFlags = this->LocalGenerator->GetIncludeFlags(includes, this->GeneratorTarget, - lang, useResponseFile); + lang, false, useResponseFile); if(includeFlags.empty()) { return; diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 6b039bb..617214f 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -54,7 +54,7 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles() << this->LocalGenerator->IncludeDirective << " " << root << this->Convert(this->ProgressFileNameFull, cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE) + cmLocalGenerator::MAKERULE) << "\n\n"; } diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index cfcf9f4..e344df4 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -187,12 +187,7 @@ cmNinjaNormalTargetGenerator responseFlag += rspfile; // build response file content - std::string linkOptionVar = cmakeVarLang; - linkOptionVar += "_COMPILER_LINKER_OPTION_FLAG_"; - linkOptionVar += cmTarget::GetTargetTypeName(targetType); - const std::string linkOption = - GetMakefile()->GetSafeDefinition(linkOptionVar); - rspcontent = "$in_newline "+linkOption+" $LINK_PATH $LINK_LIBRARIES"; + rspcontent = "$in_newline $LINK_PATH $LINK_LIBRARIES"; vars.Objects = responseFlag.c_str(); vars.LinkLibraries = ""; } @@ -608,6 +603,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() std::string(cmake::GetCMakeFilesDirectoryPostSlash()) + target.GetName() + ".rsp"; + // Gather order-only dependencies. + cmNinjaDeps orderOnlyDeps; + this->GetLocalGenerator()->AppendTargetDepends(this->GetTarget(), + orderOnlyDeps); + // Write the build statement for this target. globalGen.WriteBuild(this->GetBuildFileStream(), comment.str(), @@ -615,7 +615,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() outputs, explicitDeps, implicitDeps, - emptyDeps, + orderOnlyDeps, vars, rspfile, commandLineLengthLimit); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 24689fb..816e6d8 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -542,22 +542,24 @@ cmNinjaTargetGenerator std::back_inserter(orderOnlyDeps), MapToNinjaPath()); } - cmNinjaDeps orderOnlyTarget; - orderOnlyTarget.push_back(this->OrderDependsTargetForTarget()); - this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(), - "Order-only phony target for " - + this->GetTargetName(), - orderOnlyTarget, - cmNinjaDeps(), - cmNinjaDeps(), - orderOnlyDeps); - + if (!orderOnlyDeps.empty()) + { + cmNinjaDeps orderOnlyTarget; + orderOnlyTarget.push_back(this->OrderDependsTargetForTarget()); + this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(), + "Order-only phony target for " + + this->GetTargetName(), + orderOnlyTarget, + cmNinjaDeps(), + cmNinjaDeps(), + orderOnlyDeps); + } std::vector<cmSourceFile const*> objectSources; this->GeneratorTarget->GetObjectSources(objectSources, config); for(std::vector<cmSourceFile const*>::const_iterator si = objectSources.begin(); si != objectSources.end(); ++si) { - this->WriteObjectBuildStatement(*si); + this->WriteObjectBuildStatement(*si, !orderOnlyDeps.empty()); } std::string def = this->GeneratorTarget->GetModuleDefinitionFile(config); if(!def.empty()) @@ -570,7 +572,8 @@ cmNinjaTargetGenerator void cmNinjaTargetGenerator -::WriteObjectBuildStatement(cmSourceFile const* source) +::WriteObjectBuildStatement( + cmSourceFile const* source, bool writeOrderDependsTargetForTarget) { std::string comment; const std::string language = source->GetLanguage(); @@ -599,7 +602,10 @@ cmNinjaTargetGenerator } cmNinjaDeps orderOnlyDeps; - orderOnlyDeps.push_back(this->OrderDependsTargetForTarget()); + if (writeOrderDependsTargetForTarget) + { + orderOnlyDeps.push_back(this->OrderDependsTargetForTarget()); + } // If the source file is GENERATED and does not have a custom command // (either attached to this source file or another one), assume that one of diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 94c420f..40a15a3 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -114,7 +114,8 @@ protected: void WriteLanguageRules(const std::string& language); void WriteCompileRule(const std::string& language); void WriteObjectBuildStatements(); - void WriteObjectBuildStatement(cmSourceFile const* source); + void WriteObjectBuildStatement(cmSourceFile const* source, + bool writeOrderDependsTargetForTarget); void WriteCustomCommandBuildStatement(cmCustomCommand *cc); cmNinjaDeps GetObjects() const diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index ec671fc..007364c 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -39,8 +39,8 @@ public: if(file.rfind(".framework") != std::string::npos) { - cmsys::RegularExpression splitFramework; - splitFramework.compile("^(.*)/(.*).framework/(.*)$"); + static cmsys::RegularExpression + splitFramework("^(.*)/(.*).framework/(.*)$"); if(splitFramework.find(file) && (std::string::npos != splitFramework.match(3).find(splitFramework.match(2)))) @@ -72,7 +72,10 @@ public: { // Check if this directory conflicts with the entry. std::string const& dir = this->OD->OriginalDirectories[i]; - if(dir != this->Directory && this->FindConflict(dir)) + if(dir != this->Directory && + cmSystemTools::GetRealPath(dir) != + cmSystemTools::GetRealPath(this->Directory) && + this->FindConflict(dir)) { // The library will be found in this directory but this is not // the directory named for it. Add an entry to make sure the @@ -90,7 +93,10 @@ public: { // Check if this directory conflicts with the entry. std::string const& dir = this->OD->OriginalDirectories[i]; - if(dir != this->Directory && this->FindConflict(dir)) + if(dir != this->Directory && + cmSystemTools::GetRealPath(dir) != + cmSystemTools::GetRealPath(this->Directory) && + this->FindConflict(dir)) { // The library will be found in this directory but it is // supposed to be found in an implicit search directory. @@ -326,8 +332,8 @@ void cmOrderDirectories::AddRuntimeLibrary(std::string const& fullPath, if(fullPath.rfind(".framework") != std::string::npos) { - cmsys::RegularExpression splitFramework; - splitFramework.compile("^(.*)/(.*).framework/(.*)$"); + static cmsys::RegularExpression + splitFramework("^(.*)/(.*).framework/(.*)$"); if(splitFramework.find(fullPath) && (std::string::npos != splitFramework.match(3).find(splitFramework.match(2)))) diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 693945d..a420f59 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -359,6 +359,11 @@ cmPolicies::cmPolicies() CMP0053, "CMP0053", "Simplify variable reference and escape sequence evaluation.", 3,1,0, cmPolicies::WARN); + + this->DefinePolicy( + CMP0054, "CMP0054", + "Only interpret if() arguments as variables or keywords when unquoted.", + 3,1,0, cmPolicies::WARN); } cmPolicies::~cmPolicies() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 5d69d14..7c73da8 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -109,6 +109,8 @@ public: /// INTERFACE_INCLUDE_DIRECTORIES CMP0053, ///< Simplify variable reference and escape sequence evaluation + CMP0054, ///< Only interpret if() arguments as variables + /// or keywords when unquoted. /** \brief Always the last entry. * diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index cc6932d..93ebde6 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -392,7 +392,8 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target) std::map<std::string, std::string> configUicOptions; if (target->GetPropertyAsBool("AUTOMOC") - || target->GetPropertyAsBool("AUTOUIC")) + || target->GetPropertyAsBool("AUTOUIC") + || target->GetPropertyAsBool("AUTORCC")) { this->SetupSourceFiles(target); } @@ -1000,6 +1001,7 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, this->WriteOldMocDefinitionsFile(targetDirectory); + delete gg->GetCurrentLocalGenerator(); delete gg; gg = NULL; makefile = NULL; @@ -1178,9 +1180,9 @@ cmQtAutoGenerators::WriteOldMocDefinitionsFile( cmSystemTools::ConvertToUnixSlashes(filename); filename += "/AutomocOldMocDefinitions.cmake"; - std::fstream outfile; + cmsys::ofstream outfile; outfile.open(filename.c_str(), - std::ios::out | std::ios::trunc); + std::ios::trunc); outfile << "set(AM_OLD_COMPILE_SETTINGS " << cmLocalGenerator::EscapeForCMake( this->CurrentCompileSettingsStr) << ")\n"; @@ -1303,8 +1305,8 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) const std::vector<std::string>& headerExtensions = makefile->GetHeaderExtensions(); - std::map<std::string, std::string> includedUis; - std::map<std::string, std::string> skippedUis; + std::map<std::string, std::vector<std::string> > includedUis; + std::map<std::string, std::vector<std::string> > skippedUis; std::vector<std::string> uicSkipped; cmSystemTools::ExpandListArgument(this->SkipUic, uicSkipped); @@ -1314,7 +1316,7 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) { const bool skipUic = std::find(uicSkipped.begin(), uicSkipped.end(), *it) != uicSkipped.end(); - std::map<std::string, std::string>& uiFiles + std::map<std::string, std::vector<std::string> >& uiFiles = skipUic ? skippedUis : includedUis; const std::string &absFilename = *it; if (this->Verbose) @@ -1375,12 +1377,17 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) { this->GenerateMoc(it->first, it->second); } - for(std::map<std::string, std::string>::const_iterator + for(std::map<std::string, std::vector<std::string> >::const_iterator it = includedUis.begin(); it != includedUis.end(); ++it) { - this->GenerateUi(it->first, it->second); + for (std::vector<std::string>::const_iterator nit = it->second.begin(); + nit != it->second.end(); + ++nit) + { + this->GenerateUi(it->first, *nit); + } } if(!this->RccExecutable.empty()) @@ -1444,9 +1451,9 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) } // source file that includes all remaining moc files (_automoc.cpp file) - std::fstream outfile; + cmsys::ofstream outfile; outfile.open(this->OutMocCppFilename.c_str(), - std::ios::out | std::ios::trunc); + std::ios::trunc); outfile << automocSource; outfile.close(); @@ -1455,9 +1462,9 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) void cmQtAutoGenerators::ParseCppFile(const std::string& absFilename, - const std::vector<std::string>& headerExtensions, - std::map<std::string, std::string>& includedMocs, - std::map<std::string, std::string> &includedUis) + const std::vector<std::string>& headerExtensions, + std::map<std::string, std::string>& includedMocs, + std::map<std::string, std::vector<std::string> > &includedUis) { cmsys::RegularExpression mocIncludeRegExp( "[\n][ \t]*#[ \t]*include[ \t]+" @@ -1643,9 +1650,9 @@ void cmQtAutoGenerators::ParseCppFile(const std::string& absFilename, void cmQtAutoGenerators::StrictParseCppFile(const std::string& absFilename, - const std::vector<std::string>& headerExtensions, - std::map<std::string, std::string>& includedMocs, - std::map<std::string, std::string>& includedUis) + const std::vector<std::string>& headerExtensions, + std::map<std::string, std::string>& includedMocs, + std::map<std::string, std::vector<std::string> >& includedUis) { cmsys::RegularExpression mocIncludeRegExp( "[\n][ \t]*#[ \t]*include[ \t]+" @@ -1763,7 +1770,7 @@ void cmQtAutoGenerators::StrictParseCppFile(const std::string& absFilename, void cmQtAutoGenerators::ParseForUic(const std::string& absFilename, - std::map<std::string, std::string>& includedUis) + std::map<std::string, std::vector<std::string> >& includedUis) { if (this->UicExecutable.empty()) { @@ -1781,8 +1788,8 @@ void cmQtAutoGenerators::ParseForUic(const std::string& absFilename, void cmQtAutoGenerators::ParseForUic(const std::string& absFilename, - const std::string& contentsString, - std::map<std::string, std::string>& includedUis) + const std::string& contentsString, + std::map<std::string, std::vector<std::string> >& includedUis) { if (this->UicExecutable.empty()) { @@ -1812,7 +1819,7 @@ void cmQtAutoGenerators::ParseForUic(const std::string& absFilename, // finding the correct header, so we need to remove the ui_ part basename = basename.substr(3); - includedUis[realName] = basename; + includedUis[realName].push_back(basename); matchOffset += uiIncludeRegExp.end(); } while(uiIncludeRegExp.find(contentsString.c_str() + matchOffset)); @@ -1858,9 +1865,9 @@ cmQtAutoGenerators::SearchHeadersForCppFile(const std::string& absFilename, void cmQtAutoGenerators::ParseHeaders(const std::set<std::string>& absHeaders, - const std::map<std::string, std::string>& includedMocs, - std::map<std::string, std::string>& notIncludedMocs, - std::map<std::string, std::string>& includedUis) + const std::map<std::string, std::string>& includedMocs, + std::map<std::string, std::string>& notIncludedMocs, + std::map<std::string, std::vector<std::string> >& includedUis) { for(std::set<std::string>::const_iterator hIt=absHeaders.begin(); hIt!=absHeaders.end(); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 501e13a..c298f5d 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -51,28 +51,28 @@ private: bool GenerateUi(const std::string& realName, const std::string& uiFileName); bool GenerateQrc(); void ParseCppFile(const std::string& absFilename, - const std::vector<std::string>& headerExtensions, - std::map<std::string, std::string>& includedMocs, - std::map<std::string, std::string>& includedUis); + const std::vector<std::string>& headerExtensions, + std::map<std::string, std::string>& includedMocs, + std::map<std::string, std::vector<std::string> >& includedUis); void StrictParseCppFile(const std::string& absFilename, - const std::vector<std::string>& headerExtensions, - std::map<std::string, std::string>& includedMocs, - std::map<std::string, std::string>& includedUis); + const std::vector<std::string>& headerExtensions, + std::map<std::string, std::string>& includedMocs, + std::map<std::string, std::vector<std::string> >& includedUis); void SearchHeadersForCppFile(const std::string& absFilename, const std::vector<std::string>& headerExtensions, std::set<std::string>& absHeaders); void ParseHeaders(const std::set<std::string>& absHeaders, - const std::map<std::string, std::string>& includedMocs, - std::map<std::string, std::string>& notIncludedMocs, - std::map<std::string, std::string>& includedUis); + const std::map<std::string, std::string>& includedMocs, + std::map<std::string, std::string>& notIncludedMocs, + std::map<std::string, std::vector<std::string> >& includedUis); void ParseForUic(const std::string& fileName, - const std::string& contentsString, - std::map<std::string, std::string>& includedUis); + const std::string& contentsString, + std::map<std::string, std::vector<std::string> >& includedUis); void ParseForUic(const std::string& fileName, - std::map<std::string, std::string>& includedUis); + std::map<std::string, std::vector<std::string> >& includedUis); void Init(); diff --git a/Source/cmStandardIncludes.h b/Source/cmStandardIncludes.h index 3731502..8baf7b3 100644 --- a/Source/cmStandardIncludes.h +++ b/Source/cmStandardIncludes.h @@ -462,12 +462,6 @@ struct cmStrCmp { return strcmp(input, m_test.c_str()) == 0; } - // For use with binary_search - bool operator()(const char *str1, const char *str2) const - { - return strcmp(str1, str2) < 0; - } - private: const std::string m_test; }; diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 65912da..90a8f85 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -20,6 +20,7 @@ #include <time.h> #include <cmTimestamp.h> +#include <cmUuid.h> //---------------------------------------------------------------------------- bool cmStringCommand @@ -105,6 +106,10 @@ bool cmStringCommand { return this->HandleGenexStripCommand(args); } + else if(subCommand == "UUID") + { + return this->HandleUuidCommand(args); + } std::string e = "does not recognize sub-command "+subCommand; this->SetError(e); @@ -981,3 +986,114 @@ bool cmStringCommand return true; } + +bool cmStringCommand +::HandleUuidCommand(std::vector<std::string> const& args) +{ +#if defined(CMAKE_BUILD_WITH_CMAKE) + unsigned int argsIndex = 1; + + if(args.size() < 2) + { + this->SetError("UUID sub-command requires an output variable."); + return false; + } + + const std::string &outputVariable = args[argsIndex++]; + + std::string uuidNamespaceString; + std::string uuidName; + std::string uuidType; + bool uuidUpperCase = false; + + while(args.size() > argsIndex) + { + if(args[argsIndex] == "NAMESPACE") + { + ++argsIndex; + if(argsIndex >= args.size()) + { + this->SetError("UUID sub-command, NAMESPACE requires a value."); + return false; + } + uuidNamespaceString = args[argsIndex++]; + } + else if(args[argsIndex] == "NAME") + { + ++argsIndex; + if(argsIndex >= args.size()) + { + this->SetError("UUID sub-command, NAME requires a value."); + return false; + } + uuidName = args[argsIndex++]; + } + else if(args[argsIndex] == "TYPE") + { + ++argsIndex; + if(argsIndex >= args.size()) + { + this->SetError("UUID sub-command, TYPE requires a value."); + return false; + } + uuidType = args[argsIndex++]; + } + else if(args[argsIndex] == "UPPER") + { + ++argsIndex; + uuidUpperCase = true; + } + else + { + std::string e = "UUID sub-command does not recognize option " + + args[argsIndex] + "."; + this->SetError(e); + return false; + } + } + + std::string uuid; + cmUuid uuidGenerator; + + std::vector<unsigned char> uuidNamespace; + if(!uuidGenerator.StringToBinary(uuidNamespaceString, uuidNamespace)) + { + this->SetError("UUID sub-command, malformed NAMESPACE UUID."); + return false; + } + + if(uuidType == "MD5") + { + uuid = uuidGenerator.FromMd5(uuidNamespace, uuidName); + } + else if(uuidType == "SHA1") + { + uuid = uuidGenerator.FromSha1(uuidNamespace, uuidName); + } + else + { + std::string e = "UUID sub-command, unknown TYPE '" + uuidType + "'."; + this->SetError(e); + return false; + } + + if(uuid.empty()) + { + this->SetError("UUID sub-command, generation failed."); + return false; + } + + if(uuidUpperCase) + { + uuid = cmSystemTools::UpperCase(uuid); + } + + this->Makefile->AddDefinition(outputVariable, uuid.c_str()); + return true; +#else + cmOStringStream e; + e << args[0] << " not available during bootstrap"; + this->SetError(e.str().c_str()); + return false; +#endif +} diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index 8292e64..9c75095 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -74,6 +74,7 @@ protected: bool HandleTimestampCommand(std::vector<std::string> const& args); bool HandleMakeCIdentifierCommand(std::vector<std::string> const& args); bool HandleGenexStripCommand(std::vector<std::string> const& args); + bool HandleUuidCommand(std::vector<std::string> const& args); class RegexReplacement { diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 2e417cb..fbb4416 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -91,6 +91,31 @@ extern char** environ; # endif #endif +#if defined(CMAKE_BUILD_WITH_CMAKE) +static std::string +cm_archive_entry_pathname(struct archive_entry *entry) +{ +#if cmsys_STL_HAS_WSTRING + return cmsys::Encoding::ToNarrow( + archive_entry_pathname_w(entry)).c_str(); +#else + return archive_entry_pathname(entry); +#endif +} + +static int cm_archive_read_open_file(struct archive* a, + const char* file, + int block_size) +{ +#if cmsys_STL_HAS_WSTRING + std::wstring wfile = cmsys::Encoding::ToWide(file); + return archive_read_open_filename_w(a, wfile.c_str(), block_size); +#else + return archive_read_open_filename(a, file, block_size); +#endif +} +#endif + #ifdef _WIN32 class cmSystemToolsWindowsHandle { @@ -359,14 +384,28 @@ bool cmSystemTools::IsOn(const char* val) { return false; } - std::basic_string<char> v = val; + size_t len = strlen(val); + if (len > 4) + { + return false; + } + std::basic_string<char> v(val, len); + static std::set<std::string> onValues; + if(onValues.empty()) + { + onValues.insert("ON"); + onValues.insert("1"); + onValues.insert("YES"); + onValues.insert("TRUE"); + onValues.insert("Y"); + } for(std::basic_string<char>::iterator c = v.begin(); c != v.end(); c++) { *c = static_cast<char>(toupper(*c)); } - return (v == "ON" || v == "1" || v == "YES" || v == "TRUE" || v == "Y"); + return (onValues.count(v) > 0); } bool cmSystemTools::IsNOTFOUND(const char* val) @@ -381,19 +420,35 @@ bool cmSystemTools::IsNOTFOUND(const char* val) bool cmSystemTools::IsOff(const char* val) { - if (!val || strlen(val) == 0) + if (!val || !*val) { return true; } - std::basic_string<char> v = val; + size_t len = strlen(val); + // Try and avoid toupper() for large strings. + if (len > 6) + { + return cmSystemTools::IsNOTFOUND(val); + } + static std::set<std::string> offValues; + if(offValues.empty()) + { + offValues.insert("OFF"); + offValues.insert("0"); + offValues.insert("NO"); + offValues.insert("FALSE"); + offValues.insert("N"); + offValues.insert("IGNORE"); + } + // Try and avoid toupper(). + std::basic_string<char> v(val, len); for(std::basic_string<char>::iterator c = v.begin(); c != v.end(); c++) { *c = static_cast<char>(toupper(*c)); } - return (v == "OFF" || v == "0" || v == "NO" || v == "FALSE" || - v == "N" || cmSystemTools::IsNOTFOUND(v.c_str()) || v == "IGNORE"); + return (offValues.count(v) > 0); } //---------------------------------------------------------------------------- @@ -439,7 +494,7 @@ void cmSystemTools::ParseWindowsCommandLine(const char* command, { arg.append(backslashes, '\\'); backslashes = 0; - if(isspace(*c)) + if(((*c & 0x80) == 0 ) && isspace(*c)) { if(in_quotes) { @@ -1581,7 +1636,7 @@ namespace{ } strftime(tmp, sizeof(tmp), fmt, localtime(&tim)); fprintf(out, " %s ", tmp); - fprintf(out, "%s", archive_entry_pathname(entry)); + fprintf(out, "%s", cm_archive_entry_pathname(entry).c_str()); /* Extra information for links. */ if (archive_entry_hardlink(entry)) /* Hard link */ @@ -1641,11 +1696,13 @@ bool extract_tar(const char* outFileName, bool verbose, archive_read_support_compression_all(a); archive_read_support_format_all(a); struct archive_entry *entry; - int r = archive_read_open_file(a, outFileName, 10240); + int r = cm_archive_read_open_file(a, outFileName, 10240); if(r) { cmSystemTools::Error("Problem with archive_read_open_file(): ", archive_error_string(a)); + archive_write_free(ext); + archive_read_close(a); return false; } for (;;) @@ -1666,7 +1723,7 @@ bool extract_tar(const char* outFileName, bool verbose, if(extract) { cmSystemTools::Stdout("x "); - cmSystemTools::Stdout(archive_entry_pathname(entry)); + cmSystemTools::Stdout(cm_archive_entry_pathname(entry).c_str()); } else { @@ -1676,7 +1733,7 @@ bool extract_tar(const char* outFileName, bool verbose, } else if(!extract) { - cmSystemTools::Stdout(archive_entry_pathname(entry)); + cmSystemTools::Stdout(cm_archive_entry_pathname(entry).c_str()); cmSystemTools::Stdout("\n"); } if(extract) @@ -1706,7 +1763,8 @@ bool extract_tar(const char* outFileName, bool verbose, else if(const char* linktext = archive_entry_symlink(entry)) { std::cerr << "cmake -E tar: warning: skipping symbolic link \"" - << archive_entry_pathname(entry) << "\" -> \"" + << cm_archive_entry_pathname(entry) + << "\" -> \"" << linktext << "\"." << std::endl; } #endif @@ -1715,11 +1773,12 @@ bool extract_tar(const char* outFileName, bool verbose, cmSystemTools::Error("Problem with archive_write_header(): ", archive_error_string(ext)); cmSystemTools::Error("Current file: ", - archive_entry_pathname(entry)); + cm_archive_entry_pathname(entry).c_str()); break; } } } + archive_write_free(ext); archive_read_close(a); archive_read_finish(a); return r == ARCHIVE_EOF || r == ARCHIVE_OK; @@ -2129,6 +2188,11 @@ void cmSystemTools::FindCMakeResources(const char* argv0) cmSystemToolsCMakeCommand = exe_dir; cmSystemToolsCMakeCommand += "/cmake"; cmSystemToolsCMakeCommand += cmSystemTools::GetExecutableExtension(); +#ifndef CMAKE_BUILD_WITH_CMAKE + // The bootstrap cmake does not provide the other tools, + // so use the directory where they are about to be built. + exe_dir = CMAKE_BOOTSTRAP_BINARY_DIR "/bin"; +#endif cmSystemToolsCTestCommand = exe_dir; cmSystemToolsCTestCommand += "/ctest"; cmSystemToolsCTestCommand += cmSystemTools::GetExecutableExtension(); @@ -2181,7 +2245,7 @@ void cmSystemTools::FindCMakeResources(const char* argv0) } #else // Bootstrap build knows its source. - cmSystemToolsCMakeRoot = CMAKE_ROOT_DIR; + cmSystemToolsCMakeRoot = CMAKE_BOOTSTRAP_SOURCE_DIR; #endif } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 59cc14c..b476a27 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -25,6 +25,12 @@ #include <stdlib.h> // required for atof #include <assert.h> #include <errno.h> +#if defined(CMAKE_BUILD_WITH_CMAKE) +#include <cmsys/hash_set.hxx> +#define UNORDERED_SET cmsys::hash_set +#else +#define UNORDERED_SET std::set +#endif const char* cmTarget::GetTargetTypeName(TargetType targetType) { @@ -64,11 +70,16 @@ struct cmTarget::OutputInfo //---------------------------------------------------------------------------- struct cmTarget::ImportInfo { + ImportInfo(): NoSOName(false), Multiplicity(0) {} bool NoSOName; + int Multiplicity; std::string Location; std::string SOName; std::string ImportLibrary; - cmTarget::LinkInterface LinkInterface; + std::string Languages; + std::string Libraries; + std::string LibrariesProp; + std::string SharedDeps; }; //---------------------------------------------------------------------------- @@ -77,11 +88,6 @@ struct cmTarget::CompileInfo std::string CompilePdbDir; }; -struct TargetConfigPair : public std::pair<cmTarget const* , std::string> { - TargetConfigPair(cmTarget const* tgt, const std::string &config) - : std::pair<cmTarget const* , std::string>(tgt, config) {} -}; - //---------------------------------------------------------------------------- class cmTargetInternals { @@ -90,11 +96,13 @@ public: : Backtrace(NULL) { this->PolicyWarnedCMP0022 = false; + this->UtilityItemsDone = false; } cmTargetInternals(cmTargetInternals const&) : Backtrace(NULL) { this->PolicyWarnedCMP0022 = false; + this->UtilityItemsDone = false; } ~cmTargetInternals(); @@ -105,53 +113,100 @@ public: struct OptionalLinkInterface: public cmTarget::LinkInterface { OptionalLinkInterface(): - Exists(false), Complete(false), ExplicitLibraries(0) {} + LibrariesDone(false), AllDone(false), + Exists(false), HadHeadSensitiveCondition(false), + ExplicitLibraries(0) {} + bool LibrariesDone; + bool AllDone; bool Exists; - bool Complete; + bool HadHeadSensitiveCondition; const char* ExplicitLibraries; }; void ComputeLinkInterface(cmTarget const* thisTarget, const std::string& config, OptionalLinkInterface& iface, - cmTarget const* head, - const char *explicitLibraries) const; + cmTarget const* head) const; + void ComputeLinkInterfaceLibraries(cmTarget const* thisTarget, + const std::string& config, + OptionalLinkInterface& iface, + cmTarget const* head, + bool usage_requirements_only); - typedef std::map<TargetConfigPair, OptionalLinkInterface> + struct HeadToLinkInterfaceMap: + public std::map<cmTarget const*, OptionalLinkInterface> {}; + typedef std::map<std::string, HeadToLinkInterfaceMap> LinkInterfaceMapType; LinkInterfaceMapType LinkInterfaceMap; + LinkInterfaceMapType LinkInterfaceUsageRequirementsOnlyMap; bool PolicyWarnedCMP0022; typedef std::map<std::string, cmTarget::OutputInfo> OutputInfoMapType; OutputInfoMapType OutputInfoMap; - typedef std::map<TargetConfigPair, cmTarget::ImportInfo> - ImportInfoMapType; + typedef std::map<std::string, cmTarget::ImportInfo> ImportInfoMapType; ImportInfoMapType ImportInfoMap; typedef std::map<std::string, cmTarget::CompileInfo> CompileInfoMapType; CompileInfoMapType CompileInfoMap; // Cache link implementation computation from each configuration. - typedef std::map<TargetConfigPair, - cmTarget::LinkImplementation> LinkImplMapType; + struct OptionalLinkImplementation: public cmTarget::LinkImplementation + { + OptionalLinkImplementation(): + LibrariesDone(false), LanguagesDone(false), + HadHeadSensitiveCondition(false) {} + bool LibrariesDone; + bool LanguagesDone; + bool HadHeadSensitiveCondition; + }; + void ComputeLinkImplementationLibraries(cmTarget const* thisTarget, + const std::string& config, + OptionalLinkImplementation& impl, + cmTarget const* head) const; + void ComputeLinkImplementationLanguages(cmTarget const* thisTarget, + const std::string& config, + OptionalLinkImplementation& impl + ) const; + + struct HeadToLinkImplementationMap: + public std::map<cmTarget const*, OptionalLinkImplementation> {}; + typedef std::map<std::string, + HeadToLinkImplementationMap> LinkImplMapType; LinkImplMapType LinkImplMap; - typedef std::map<TargetConfigPair, cmTarget::LinkClosure> - LinkClosureMapType; + typedef std::map<std::string, cmTarget::LinkClosure> LinkClosureMapType; LinkClosureMapType LinkClosureMap; - typedef std::map<TargetConfigPair, std::vector<cmSourceFile*> > - SourceFilesMapType; + struct LinkImplClosure: public std::vector<cmTarget const*> + { + LinkImplClosure(): Done(false) {} + bool Done; + }; + std::map<std::string, LinkImplClosure> LinkImplClosureMap; + + struct CompatibleInterfaces: public cmTarget::CompatibleInterfaces + { + CompatibleInterfaces(): Done(false) {} + bool Done; + }; + std::map<std::string, CompatibleInterfaces> CompatibleInterfacesMap; + + typedef std::map<std::string, std::vector<cmSourceFile*> > + SourceFilesMapType; SourceFilesMapType SourceFilesMap; - struct TargetPropertyEntry { + std::set<cmLinkItem> UtilityItems; + bool UtilityItemsDone; + + class TargetPropertyEntry { + static cmLinkImplItem NoLinkImplItem; + public: TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge, - const std::string &targetName = std::string()) - : ge(cge), TargetName(targetName) + cmLinkImplItem const& item = NoLinkImplItem) + : ge(cge), LinkImplItem(item) {} const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge; - std::vector<std::string> CachedEntries; - const std::string TargetName; + cmLinkImplItem const& LinkImplItem; }; std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries; std::vector<TargetPropertyEntry*> CompileOptionsEntries; @@ -160,26 +215,15 @@ public: std::vector<TargetPropertyEntry*> SourceEntries; std::vector<cmValueWithOrigin> LinkImplementationPropertyEntries; - mutable std::map<std::string, std::vector<TargetPropertyEntry*> > - CachedLinkInterfaceIncludeDirectoriesEntries; - mutable std::map<std::string, std::vector<TargetPropertyEntry*> > - CachedLinkInterfaceCompileOptionsEntries; - mutable std::map<std::string, std::vector<TargetPropertyEntry*> > - CachedLinkInterfaceCompileDefinitionsEntries; - mutable std::map<std::string, std::vector<TargetPropertyEntry*> > - CachedLinkInterfaceSourcesEntries; - mutable std::map<std::string, std::vector<TargetPropertyEntry*> > - CachedLinkInterfaceCompileFeaturesEntries; - - mutable std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone; - mutable std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone; - mutable std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone; - mutable std::map<std::string, bool> CacheLinkInterfaceSourcesDone; - mutable std::map<std::string, bool> CacheLinkInterfaceCompileFeaturesDone; + void AddInterfaceEntries( + cmTarget const* thisTarget, std::string const& config, + std::string const& prop, std::vector<TargetPropertyEntry*>& entries); }; +cmLinkImplItem cmTargetInternals::TargetPropertyEntry::NoLinkImplItem; + //---------------------------------------------------------------------------- -void deleteAndClear( +static void deleteAndClear( std::vector<cmTargetInternals::TargetPropertyEntry*> &entries) { for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator @@ -193,26 +237,8 @@ void deleteAndClear( } //---------------------------------------------------------------------------- -void deleteAndClear( - std::map<std::string, - std::vector<cmTargetInternals::TargetPropertyEntry*> > &entries) -{ - for (std::map<std::string, - std::vector<cmTargetInternals::TargetPropertyEntry*> >::iterator - it = entries.begin(), end = entries.end(); it != end; ++it) - { - deleteAndClear(it->second); - } -} - -//---------------------------------------------------------------------------- cmTargetInternals::~cmTargetInternals() { - deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries); - deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries); - deleteAndClear(this->CachedLinkInterfaceCompileFeaturesEntries); - deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries); - deleteAndClear(this->CachedLinkInterfaceSourcesEntries); } //---------------------------------------------------------------------------- @@ -226,9 +252,12 @@ cmTarget::cmTarget() #undef INITIALIZE_TARGET_POLICY_MEMBER this->Makefile = 0; - this->LinkLibrariesAnalyzed = false; +#if defined(_WIN32) && !defined(__CYGWIN__) + this->LinkLibrariesForVS6Analyzed = false; +#endif this->HaveInstallRule = false; this->DLLPlatform = false; + this->IsAndroid = false; this->IsApple = false; this->IsImportedTarget = false; this->BuildInterfaceIncludesAppended = false; @@ -284,12 +313,18 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->Makefile->IsOn("CYGWIN") || this->Makefile->IsOn("MINGW")); + // Check whether we are targeting an Android platform. + this->IsAndroid = + strcmp(this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME"), + "Android") == 0; + // Check whether we are targeting an Apple platform. this->IsApple = this->Makefile->IsOn("APPLE"); // Setup default property values. - if (this->GetType() != INTERFACE_LIBRARY) + if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY) { + this->SetPropertyDefault("ANDROID_API", 0); this->SetPropertyDefault("INSTALL_NAME_DIR", 0); this->SetPropertyDefault("INSTALL_RPATH", ""); this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF"); @@ -329,41 +364,44 @@ void cmTarget::SetMakefile(cmMakefile* mf) mf->GetConfigurations(configNames); // Setup per-configuration property default values. - const char* configProps[] = { - "ARCHIVE_OUTPUT_DIRECTORY_", - "LIBRARY_OUTPUT_DIRECTORY_", - "RUNTIME_OUTPUT_DIRECTORY_", - "PDB_OUTPUT_DIRECTORY_", - "COMPILE_PDB_OUTPUT_DIRECTORY_", - "MAP_IMPORTED_CONFIG_", - 0}; - for(std::vector<std::string>::iterator ci = configNames.begin(); - ci != configNames.end(); ++ci) - { - std::string configUpper = cmSystemTools::UpperCase(*ci); - for(const char** p = configProps; *p; ++p) - { - if (this->TargetTypeValue == INTERFACE_LIBRARY - && strcmp(*p, "MAP_IMPORTED_CONFIG_") != 0) + if (this->GetType() != UTILITY) + { + const char* configProps[] = { + "ARCHIVE_OUTPUT_DIRECTORY_", + "LIBRARY_OUTPUT_DIRECTORY_", + "RUNTIME_OUTPUT_DIRECTORY_", + "PDB_OUTPUT_DIRECTORY_", + "COMPILE_PDB_OUTPUT_DIRECTORY_", + "MAP_IMPORTED_CONFIG_", + 0}; + for(std::vector<std::string>::iterator ci = configNames.begin(); + ci != configNames.end(); ++ci) + { + std::string configUpper = cmSystemTools::UpperCase(*ci); + for(const char** p = configProps; *p; ++p) { - continue; + if (this->TargetTypeValue == INTERFACE_LIBRARY + && strcmp(*p, "MAP_IMPORTED_CONFIG_") != 0) + { + continue; + } + std::string property = *p; + property += configUpper; + this->SetPropertyDefault(property, 0); } - std::string property = *p; - property += configUpper; - this->SetPropertyDefault(property, 0); - } - // Initialize per-configuration name postfix property from the - // variable only for non-executable targets. This preserves - // compatibility with previous CMake versions in which executables - // did not support this variable. Projects may still specify the - // property directly. - if(this->TargetTypeValue != cmTarget::EXECUTABLE - && this->TargetTypeValue != cmTarget::INTERFACE_LIBRARY) - { - std::string property = cmSystemTools::UpperCase(*ci); - property += "_POSTFIX"; - this->SetPropertyDefault(property, 0); + // Initialize per-configuration name postfix property from the + // variable only for non-executable targets. This preserves + // compatibility with previous CMake versions in which executables + // did not support this variable. Projects may still specify the + // property directly. + if(this->TargetTypeValue != cmTarget::EXECUTABLE + && this->TargetTypeValue != cmTarget::INTERFACE_LIBRARY) + { + std::string property = cmSystemTools::UpperCase(*ci); + property += "_POSTFIX"; + this->SetPropertyDefault(property, 0); + } } } @@ -402,19 +440,23 @@ void cmTarget::SetMakefile(cmMakefile* mf) } } - if (this->GetType() != INTERFACE_LIBRARY) + if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY) { this->SetPropertyDefault("C_VISIBILITY_PRESET", 0); this->SetPropertyDefault("CXX_VISIBILITY_PRESET", 0); this->SetPropertyDefault("VISIBILITY_INLINES_HIDDEN", 0); } + if(this->TargetTypeValue == cmTarget::EXECUTABLE) + { + this->SetPropertyDefault("ANDROID_GUI", 0); + } if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY || this->TargetTypeValue == cmTarget::MODULE_LIBRARY) { this->SetProperty("POSITION_INDEPENDENT_CODE", "True"); } - if (this->GetType() != INTERFACE_LIBRARY) + if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY) { this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0); } @@ -436,8 +478,11 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->PolicyStatusCMP0022 = cmPolicies::NEW; } - this->SetPropertyDefault("JOB_POOL_COMPILE", 0); - this->SetPropertyDefault("JOB_POOL_LINK", 0); + if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY) + { + this->SetPropertyDefault("JOB_POOL_COMPILE", 0); + this->SetPropertyDefault("JOB_POOL_LINK", 0); + } } //---------------------------------------------------------------------------- @@ -461,6 +506,22 @@ cmListFileBacktrace const* cmTarget::GetUtilityBacktrace( } //---------------------------------------------------------------------------- +std::set<cmLinkItem> const& cmTarget::GetUtilityItems() const +{ + if(!this->Internal->UtilityItemsDone) + { + this->Internal->UtilityItemsDone = true; + for(std::set<std::string>::const_iterator i = this->Utilities.begin(); + i != this->Utilities.end(); ++i) + { + this->Internal->UtilityItems.insert( + cmLinkItem(*i, this->Makefile->FindTargetToUse(*i))); + } + } + return this->Internal->UtilityItems; +} + +//---------------------------------------------------------------------------- void cmTarget::FinishConfigure() { // Erase any cached link information that might have been comptued @@ -469,8 +530,13 @@ void cmTarget::FinishConfigure() // invalidation code in this source file is buggy. this->ClearLinkMaps(); - // Do old-style link dependency analysis. - this->AnalyzeLibDependencies(*this->Makefile); +#if defined(_WIN32) && !defined(__CYGWIN__) + // Do old-style link dependency analysis only for CM_USE_OLD_VS6. + if(this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->IsForVS6()) + { + this->AnalyzeLibDependenciesForVS6(*this->Makefile); + } +#endif } //---------------------------------------------------------------------------- @@ -479,6 +545,7 @@ void cmTarget::ClearLinkMaps() this->LinkImplementationLanguageIsContextDependent = true; this->Internal->LinkImplMap.clear(); this->Internal->LinkInterfaceMap.clear(); + this->Internal->LinkInterfaceUsageRequirementsOnlyMap.clear(); this->Internal->LinkClosureMap.clear(); for (cmTargetLinkInformationMap::const_iterator it = this->LinkInformation.begin(); @@ -571,9 +638,8 @@ bool cmTarget::IsBundleOnApple() const static bool processSources(cmTarget const* tgt, const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, std::vector<std::string> &srcs, - std::set<std::string> &uniqueSrcs, + UNORDERED_SET<std::string> &uniqueSrcs, cmGeneratorExpressionDAGChecker *dagChecker, - cmTarget const* head, std::string const& config, bool debugSources) { cmMakefile *mf = tgt->GetMakefile(); @@ -583,49 +649,37 @@ static bool processSources(cmTarget const* tgt, for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator it = entries.begin(), end = entries.end(); it != end; ++it) { - bool cacheSources = false; - std::vector<std::string> entrySources = (*it)->CachedEntries; - if(entrySources.empty()) + std::vector<std::string> entrySources; + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, + config, + false, + tgt, + tgt, + dagChecker), + entrySources); + + if ((*it)->ge->GetHadContextSensitiveCondition()) { - cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, - config, - false, - head ? head : tgt, - tgt, - dagChecker), - entrySources); + contextDependent = true; + } - if ((*it)->ge->GetHadContextSensitiveCondition()) - { - contextDependent = true; - } - else if (mf->IsGeneratingBuildSystem()) - { - cacheSources = true; - } + for(std::vector<std::string>::iterator i = entrySources.begin(); + i != entrySources.end(); ++i) + { + std::string& src = *i; - for(std::vector<std::string>::iterator i = entrySources.begin(); - i != entrySources.end(); ++i) + cmSourceFile* sf = mf->GetOrCreateSource(src); + std::string e; + src = sf->GetFullPath(&e); + if(src.empty()) { - std::string& src = *i; - - cmSourceFile* sf = mf->GetOrCreateSource(src); - std::string e; - src = sf->GetFullPath(&e); - if(src.empty()) + if(!e.empty()) { - if(!e.empty()) - { - cmake* cm = mf->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, e, - tgt->GetBacktrace()); - } - return contextDependent; + cmake* cm = mf->GetCMakeInstance(); + cm->IssueMessage(cmake::FATAL_ERROR, e, + tgt->GetBacktrace()); } - } - if (cacheSources) - { - (*it)->CachedEntries = entrySources; + return contextDependent; } } std::string usedSources; @@ -656,8 +710,7 @@ static bool processSources(cmTarget const* tgt, //---------------------------------------------------------------------------- void cmTarget::GetSourceFiles(std::vector<std::string> &files, - const std::string& config, - cmTarget const* head) const + const std::string& config) const { assert(this->GetType() != INTERFACE_LIBRARY); @@ -715,66 +768,28 @@ void cmTarget::GetSourceFiles(std::vector<std::string> &files, cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "SOURCES", 0, 0); - std::set<std::string> uniqueSrcs; + UNORDERED_SET<std::string> uniqueSrcs; bool contextDependentDirectSources = processSources(this, this->Internal->SourceEntries, files, uniqueSrcs, &dagChecker, - head, config, debugSources); - if (!this->Internal->CacheLinkInterfaceSourcesDone[config]) - { - for (std::vector<cmValueWithOrigin>::const_iterator - it = this->Internal->LinkImplementationPropertyEntries.begin(), - end = this->Internal->LinkImplementationPropertyEntries.end(); - it != end; ++it) - { - if (!cmGeneratorExpression::IsValidTargetName(it->Value) - && cmGeneratorExpression::Find(it->Value) == std::string::npos) - { - continue; - } - { - cmGeneratorExpression ge; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(it->Value); - std::string targetResult = cge->Evaluate(this->Makefile, config, - false, this, 0, &dagChecker); - if (!this->Makefile->FindTargetToUse(targetResult)) - { - continue; - } - } - std::string sourceGenex = "$<TARGET_PROPERTY:" + - it->Value + ",INTERFACE_SOURCES>"; - if (cmGeneratorExpression::Find(it->Value) != std::string::npos) - { - // Because it->Value is a generator expression, ensure that it - // evaluates to the non-empty string before being used in the - // TARGET_PROPERTY expression. - sourceGenex = "$<$<BOOL:" + it->Value + ">:" + sourceGenex + ">"; - } - cmGeneratorExpression ge(&it->Backtrace); - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse( - sourceGenex); + std::vector<cmTargetInternals::TargetPropertyEntry*> + linkInterfaceSourcesEntries; - this->Internal - ->CachedLinkInterfaceSourcesEntries[config].push_back( - new cmTargetInternals::TargetPropertyEntry(cge, - it->Value)); - } - } + this->Internal->AddInterfaceEntries( + this, config, "INTERFACE_SOURCES", + linkInterfaceSourcesEntries); - std::vector<std::string>::size_type numFilesBefore = files.size(); - bool contextDependentInterfaceSources = processSources(this, - this->Internal->CachedLinkInterfaceSourcesEntries[config], + std::vector<std::string>::size_type numFilesBefore = files.size(); + bool contextDependentInterfaceSources = processSources(this, + linkInterfaceSourcesEntries, files, uniqueSrcs, &dagChecker, - head, config, debugSources); @@ -784,14 +799,7 @@ void cmTarget::GetSourceFiles(std::vector<std::string> &files, this->LinkImplementationLanguageIsContextDependent = false; } - if (!this->Makefile->IsGeneratingBuildSystem()) - { - deleteAndClear(this->Internal->CachedLinkInterfaceSourcesEntries); - } - else - { - this->Internal->CacheLinkInterfaceSourcesDone[config] = true; - } + deleteAndClear(linkInterfaceSourcesEntries); } //---------------------------------------------------------------------------- @@ -853,12 +861,11 @@ cmTarget::GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const //---------------------------------------------------------------------------- void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files, - const std::string& config, - cmTarget const* head) const + const std::string& config) const { // Lookup any existing link implementation for this configuration. - TargetConfigPair key(head, cmSystemTools::UpperCase(config)); + std::string key = cmSystemTools::UpperCase(config); if(!this->LinkImplementationLanguageIsContextDependent) { @@ -875,7 +882,7 @@ void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files, else { std::vector<std::string> srcs; - this->GetSourceFiles(srcs, config, head); + this->GetSourceFiles(srcs, config); std::set<cmSourceFile*> emitted; @@ -931,10 +938,13 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs) if(!(src[0] == '$' && src[1] == '<')) { - filename = this->ProcessSourceItemCMP0049(filename); - if (cmSystemTools::GetErrorOccuredFlag()) + if(!filename.empty()) { - return; + filename = this->ProcessSourceItemCMP0049(filename); + if(filename.empty()) + { + return; + } } this->Makefile->GetOrCreateSource(filename); } @@ -1002,8 +1012,7 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s) cmSourceFile* cmTarget::AddSourceCMP0049(const std::string& s) { std::string src = this->ProcessSourceItemCMP0049(s); - - if (cmSystemTools::GetErrorOccuredFlag()) + if(!s.empty() && src.empty()) { return 0; } @@ -1195,63 +1204,6 @@ bool cmTarget::NameResolvesToFramework(const std::string& libname) const } //---------------------------------------------------------------------------- -void cmTarget::GetDirectLinkLibraries(const std::string& config, - std::vector<std::string> &libs, - cmTarget const* head) const -{ - const char *prop = this->GetProperty("LINK_LIBRARIES"); - if (prop) - { - cmGeneratorExpression ge; - const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop); - - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), - "LINK_LIBRARIES", 0, 0); - cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile, - config, - false, - head, - &dagChecker), - libs); - - std::set<std::string> const& seenProps = cge->GetSeenTargetProperties(); - for (std::set<std::string>::const_iterator it = seenProps.begin(); - it != seenProps.end(); ++it) - { - if (!this->GetProperty(*it)) - { - this->LinkImplicitNullProperties.insert(*it); - } - } - cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards); - } -} - -//---------------------------------------------------------------------------- -void cmTarget::GetInterfaceLinkLibraries(const std::string& config, - std::vector<std::string> &libs, - cmTarget const* head) const -{ - const char *prop = this->GetProperty("INTERFACE_LINK_LIBRARIES"); - if (prop) - { - cmGeneratorExpression ge; - const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop); - - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), - "INTERFACE_LINK_LIBRARIES", 0, 0); - cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile, - config, - false, - head, - &dagChecker), - libs); - } -} - -//---------------------------------------------------------------------------- std::string cmTarget::GetDebugGeneratorExpressions(const std::string &value, cmTarget::LinkLibraryType llt) const { @@ -1325,7 +1277,7 @@ void cmTarget::GetTllSignatureTraces(cmOStringStream &s, = (sig == cmTarget::KeywordTLLSignature ? "keyword" : "plain"); s << "The uses of the " << sigString << " signature are here:\n"; - std::set<std::string> emitted; + UNORDERED_SET<std::string> emitted; for(std::vector<cmListFileBacktrace>::iterator it = sigs.begin(); it != sigs.end(); ++it) { @@ -1374,7 +1326,9 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, cmTarget::LibraryID tmp; tmp.first = lib; tmp.second = llt; - this->LinkLibraries.push_back( tmp ); +#if defined(_WIN32) && !defined(__CYGWIN__) + this->LinkLibrariesForVS6.push_back( tmp ); +#endif this->OriginalLinkLibraries.push_back(tmp); this->ClearLinkMaps(); @@ -1440,9 +1394,10 @@ cmTarget::AddSystemIncludeDirectories(const std::vector<std::string> &incs) } } +#if defined(_WIN32) && !defined(__CYGWIN__) //---------------------------------------------------------------------------- void -cmTarget::AnalyzeLibDependencies( const cmMakefile& mf ) +cmTarget::AnalyzeLibDependenciesForVS6( const cmMakefile& mf ) { // There are two key parts of the dependency analysis: (1) // determining the libraries in the link line, and (2) constructing @@ -1519,8 +1474,8 @@ cmTarget::AnalyzeLibDependencies( const cmMakefile& mf ) // eventually be removed. This code was moved here from the end of // old source list processing code which was called just before this // method. - for(LinkLibraryVectorType::iterator p = this->LinkLibraries.begin(); - p != this->LinkLibraries.end(); ++p) + for(LinkLibraryVectorType::iterator p = this->LinkLibrariesForVS6.begin(); + p != this->LinkLibrariesForVS6.end(); ++p) { this->Makefile->ExpandVariablesInString(p->first, true, true); } @@ -1532,22 +1487,22 @@ cmTarget::AnalyzeLibDependencies( const cmMakefile& mf ) // 1. Build the dependency graph // for(LinkLibraryVectorType::reverse_iterator lib - = this->LinkLibraries.rbegin(); - lib != this->LinkLibraries.rend(); ++lib) + = this->LinkLibrariesForVS6.rbegin(); + lib != this->LinkLibrariesForVS6.rend(); ++lib) { - this->GatherDependencies( mf, *lib, dep_map); + this->GatherDependenciesForVS6( mf, *lib, dep_map); } // 2. Remove any dependencies that are already satisfied in the original // link line. // - for(LinkLibraryVectorType::iterator lib = this->LinkLibraries.begin(); - lib != this->LinkLibraries.end(); ++lib) + for(LinkLibraryVectorType::iterator lib = this->LinkLibrariesForVS6.begin(); + lib != this->LinkLibrariesForVS6.end(); ++lib) { for( LinkLibraryVectorType::iterator lib2 = lib; - lib2 != this->LinkLibraries.end(); ++lib2) + lib2 != this->LinkLibrariesForVS6.end(); ++lib2) { - this->DeleteDependency( dep_map, *lib, *lib2); + this->DeleteDependencyForVS6( dep_map, *lib, *lib2); } } @@ -1556,43 +1511,43 @@ cmTarget::AnalyzeLibDependencies( const cmMakefile& mf ) // missing. Start from the back and keep adding. // std::set<DependencyMap::key_type> done, visited; - std::vector<DependencyMap::key_type> newLinkLibraries; + std::vector<DependencyMap::key_type> newLinkLibrariesForVS6; for(LinkLibraryVectorType::reverse_iterator lib = - this->LinkLibraries.rbegin(); - lib != this->LinkLibraries.rend(); ++lib) + this->LinkLibrariesForVS6.rbegin(); + lib != this->LinkLibrariesForVS6.rend(); ++lib) { // skip zero size library entries, this may happen // if a variable expands to nothing. if (lib->first.size() != 0) { - this->Emit( *lib, dep_map, done, visited, newLinkLibraries ); + this->EmitForVS6( *lib, dep_map, done, visited, newLinkLibrariesForVS6 ); } } // 4. Add the new libraries to the link line. // for( std::vector<DependencyMap::key_type>::reverse_iterator k = - newLinkLibraries.rbegin(); - k != newLinkLibraries.rend(); ++k ) + newLinkLibrariesForVS6.rbegin(); + k != newLinkLibrariesForVS6.rend(); ++k ) { // get the llt from the dep_map - this->LinkLibraries.push_back( std::make_pair(k->first,k->second) ); + this->LinkLibrariesForVS6.push_back( std::make_pair(k->first,k->second) ); } - this->LinkLibrariesAnalyzed = true; + this->LinkLibrariesForVS6Analyzed = true; } //---------------------------------------------------------------------------- -void cmTarget::InsertDependency( DependencyMap& depMap, - const LibraryID& lib, - const LibraryID& dep) +void cmTarget::InsertDependencyForVS6( DependencyMap& depMap, + const LibraryID& lib, + const LibraryID& dep) { depMap[lib].push_back(dep); } //---------------------------------------------------------------------------- -void cmTarget::DeleteDependency( DependencyMap& depMap, - const LibraryID& lib, - const LibraryID& dep) +void cmTarget::DeleteDependencyForVS6( DependencyMap& depMap, + const LibraryID& lib, + const LibraryID& dep) { // Make sure there is an entry in the map for lib. If so, delete all // dependencies to dep. There may be repeated entries because of @@ -1611,11 +1566,11 @@ void cmTarget::DeleteDependency( DependencyMap& depMap, } //---------------------------------------------------------------------------- -void cmTarget::Emit(const LibraryID lib, - const DependencyMap& dep_map, - std::set<LibraryID>& emitted, - std::set<LibraryID>& visited, - DependencyList& link_line ) +void cmTarget::EmitForVS6(const LibraryID lib, + const DependencyMap& dep_map, + std::set<LibraryID>& emitted, + std::set<LibraryID>& visited, + DependencyList& link_line ) { // It's already been emitted if( emitted.find(lib) != emitted.end() ) @@ -1661,7 +1616,7 @@ void cmTarget::Emit(const LibraryID lib, if( emitted.find(*i) == emitted.end() ) { // emit dependencies - Emit( *i, dep_map, emitted, visited, link_line ); + this->EmitForVS6( *i, dep_map, emitted, visited, link_line ); // emit self emitted.insert(*i); emitted_here.insert(*i); @@ -1674,9 +1629,9 @@ void cmTarget::Emit(const LibraryID lib, } //---------------------------------------------------------------------------- -void cmTarget::GatherDependencies( const cmMakefile& mf, - const LibraryID& lib, - DependencyMap& dep_map) +void cmTarget::GatherDependenciesForVS6( const cmMakefile& mf, + const LibraryID& lib, + DependencyMap& dep_map) { // If the library is already in the dependency map, then it has // already been fully processed. @@ -1720,8 +1675,8 @@ void cmTarget::GatherDependencies( const cmMakefile& mf, else { LibraryID lib2(l,llt); - this->InsertDependency( dep_map, lib, lib2); - this->GatherDependencies( mf, lib2, dep_map); + this->InsertDependencyForVS6( dep_map, lib, lib2); + this->GatherDependenciesForVS6( mf, lib2, dep_map); llt = cmTarget::GENERAL; } } @@ -1729,9 +1684,10 @@ void cmTarget::GatherDependencies( const cmMakefile& mf, end = depline.find( ";", start ); } // cannot depend on itself - this->DeleteDependency( dep_map, lib, lib); + this->DeleteDependencyForVS6( dep_map, lib, lib); } } +#endif //---------------------------------------------------------------------------- static bool whiteListedInterfaceProperty(const std::string& prop) @@ -1740,22 +1696,20 @@ static bool whiteListedInterfaceProperty(const std::string& prop) { return true; } - static const char* builtIns[] = { - // ###: This must remain sorted. It is processed with a binary search. - "COMPATIBLE_INTERFACE_BOOL", - "COMPATIBLE_INTERFACE_NUMBER_MAX", - "COMPATIBLE_INTERFACE_NUMBER_MIN", - "COMPATIBLE_INTERFACE_STRING", - "EXPORT_NAME", - "IMPORTED", - "NAME", - "TYPE" - }; + static UNORDERED_SET<std::string> builtIns; + if (builtIns.empty()) + { + builtIns.insert("COMPATIBLE_INTERFACE_BOOL"); + builtIns.insert("COMPATIBLE_INTERFACE_NUMBER_MAX"); + builtIns.insert("COMPATIBLE_INTERFACE_NUMBER_MIN"); + builtIns.insert("COMPATIBLE_INTERFACE_STRING"); + builtIns.insert("EXPORT_NAME"); + builtIns.insert("IMPORTED"); + builtIns.insert("NAME"); + builtIns.insert("TYPE"); + } - if (std::binary_search(cmArrayBegin(builtIns), - cmArrayEnd(builtIns), - prop.c_str(), - cmStrCmp(prop))) + if (builtIns.count(prop)) { return true; } @@ -1780,15 +1734,14 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } - - if (prop == "NAME") + else if (prop == "NAME") { cmOStringStream e; e << "NAME property is read-only\n"; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } - if(prop == "INCLUDE_DIRECTORIES") + else if(prop == "INCLUDE_DIRECTORIES") { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmGeneratorExpression ge(&lfbt); @@ -1796,9 +1749,8 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); this->Internal->IncludeDirectoriesEntries.push_back( new cmTargetInternals::TargetPropertyEntry(cge)); - return; } - if(prop == "COMPILE_OPTIONS") + else if(prop == "COMPILE_OPTIONS") { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmGeneratorExpression ge(&lfbt); @@ -1806,9 +1758,8 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); this->Internal->CompileOptionsEntries.push_back( new cmTargetInternals::TargetPropertyEntry(cge)); - return; } - if(prop == "COMPILE_FEATURES") + else if(prop == "COMPILE_FEATURES") { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmGeneratorExpression ge(&lfbt); @@ -1816,9 +1767,8 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); this->Internal->CompileFeaturesEntries.push_back( new cmTargetInternals::TargetPropertyEntry(cge)); - return; } - if(prop == "COMPILE_DEFINITIONS") + else if(prop == "COMPILE_DEFINITIONS") { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmGeneratorExpression ge(&lfbt); @@ -1826,25 +1776,22 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); this->Internal->CompileDefinitionsEntries.push_back( new cmTargetInternals::TargetPropertyEntry(cge)); - return; } - if(prop == "EXPORT_NAME" && this->IsImported()) + else if(prop == "EXPORT_NAME" && this->IsImported()) { cmOStringStream e; e << "EXPORT_NAME property can't be set on imported targets (\"" << this->Name << "\")\n"; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); - return; } - if (prop == "LINK_LIBRARIES") + else if (prop == "LINK_LIBRARIES") { this->Internal->LinkImplementationPropertyEntries.clear(); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmValueWithOrigin entry(value, lfbt); this->Internal->LinkImplementationPropertyEntries.push_back(entry); - return; } - if (prop == "SOURCES") + else if (prop == "SOURCES") { if(this->IsImported()) { @@ -1861,10 +1808,12 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); this->Internal->SourceEntries.push_back( new cmTargetInternals::TargetPropertyEntry(cge)); - return; } - this->Properties.SetProperty(prop, value, cmProperty::TARGET); - this->MaybeInvalidatePropertyCache(prop); + else + { + this->Properties.SetProperty(prop, value, cmProperty::TARGET); + this->MaybeInvalidatePropertyCache(prop); + } } //---------------------------------------------------------------------------- @@ -1880,61 +1829,55 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } - if (prop == "NAME") + else if (prop == "NAME") { cmOStringStream e; e << "NAME property is read-only\n"; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } - if(prop == "INCLUDE_DIRECTORIES") + else if(prop == "INCLUDE_DIRECTORIES") { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmGeneratorExpression ge(&lfbt); this->Internal->IncludeDirectoriesEntries.push_back( new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); - return; } - if(prop == "COMPILE_OPTIONS") + else if(prop == "COMPILE_OPTIONS") { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmGeneratorExpression ge(&lfbt); this->Internal->CompileOptionsEntries.push_back( new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); - return; } - if(prop == "COMPILE_FEATURES") + else if(prop == "COMPILE_FEATURES") { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmGeneratorExpression ge(&lfbt); this->Internal->CompileFeaturesEntries.push_back( new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); - return; } - if(prop == "COMPILE_DEFINITIONS") + else if(prop == "COMPILE_DEFINITIONS") { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmGeneratorExpression ge(&lfbt); this->Internal->CompileDefinitionsEntries.push_back( new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); - return; } - if(prop == "EXPORT_NAME" && this->IsImported()) + else if(prop == "EXPORT_NAME" && this->IsImported()) { cmOStringStream e; e << "EXPORT_NAME property can't be set on imported targets (\"" << this->Name << "\")\n"; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); - return; } - if (prop == "LINK_LIBRARIES") + else if (prop == "LINK_LIBRARIES") { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmValueWithOrigin entry(value, lfbt); this->Internal->LinkImplementationPropertyEntries.push_back(entry); - return; } - if (prop == "SOURCES") + else if (prop == "SOURCES") { if(this->IsImported()) { @@ -1950,10 +1893,12 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); this->Internal->SourceEntries.push_back( new cmTargetInternals::TargetPropertyEntry(cge)); - return; } - this->Properties.AppendProperty(prop, value, cmProperty::TARGET, asString); - this->MaybeInvalidatePropertyCache(prop); + else + { + this->Properties.AppendProperty(prop, value, cmProperty::TARGET, asString); + this->MaybeInvalidatePropertyCache(prop); + } } //---------------------------------------------------------------------------- @@ -2049,7 +1994,7 @@ void cmTarget::InsertCompileDefinition(const cmValueWithOrigin &entry) static void processIncludeDirectories(cmTarget const* tgt, const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, std::vector<std::string> &includes, - std::set<std::string> &uniqueIncludes, + UNORDERED_SET<std::string> &uniqueIncludes, cmGeneratorExpressionDAGChecker *dagChecker, const std::string& config, bool debugIncludes) { @@ -2058,61 +2003,28 @@ static void processIncludeDirectories(cmTarget const* tgt, for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator it = entries.begin(), end = entries.end(); it != end; ++it) { - bool testIsOff = true; - bool cacheIncludes = false; - std::vector<std::string>& entryIncludes = (*it)->CachedEntries; - if(!entryIncludes.empty()) - { - testIsOff = false; - } - else - { - cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, - config, - false, - tgt, - dagChecker), - entryIncludes); - if (mf->IsGeneratingBuildSystem() - && !(*it)->ge->GetHadContextSensitiveCondition()) - { - cacheIncludes = true; - } - } + cmLinkImplItem const& item = (*it)->LinkImplItem; + std::string const& targetName = item; + bool const fromImported = item.Target && item.Target->IsImported(); + bool const checkCMP0027 = item.FromGenex; + std::vector<std::string> entryIncludes; + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, + config, + false, + tgt, + dagChecker), + entryIncludes); + std::string usedIncludes; for(std::vector<std::string>::iterator li = entryIncludes.begin(); li != entryIncludes.end(); ++li) { - std::string targetName = (*it)->TargetName; - std::string evaluatedTargetName; - { - cmGeneratorExpression ge; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(targetName); - evaluatedTargetName = cge->Evaluate(mf, config, false, tgt, 0, 0); - } - - cmTarget *dependentTarget = mf->FindTargetToUse(targetName); - - const bool fromImported = dependentTarget - && dependentTarget->IsImported(); - - cmTarget *evaluatedDependentTarget = - (targetName != evaluatedTargetName) - ? mf->FindTargetToUse(evaluatedTargetName) - : 0; - - targetName = evaluatedTargetName; - - const bool fromEvaluatedImported = evaluatedDependentTarget - && evaluatedDependentTarget->IsImported(); - - if ((fromImported || fromEvaluatedImported) + if (fromImported && !cmSystemTools::FileExists(li->c_str())) { cmOStringStream e; cmake::MessageType messageType = cmake::FATAL_ERROR; - if (fromEvaluatedImported) + if (checkCMP0027) { switch(tgt->GetPolicyStatusCMP0027()) { @@ -2184,7 +2096,7 @@ static void processIncludeDirectories(cmTarget const* tgt, } } - if (testIsOff && !cmSystemTools::IsOff(li->c_str())) + if (!cmSystemTools::IsOff(li->c_str())) { cmSystemTools::ConvertToUnixSlashes(*li); } @@ -2199,10 +2111,6 @@ static void processIncludeDirectories(cmTarget const* tgt, } } } - if (cacheIncludes) - { - (*it)->CachedEntries = entryIncludes; - } if (!usedIncludes.empty()) { mf->GetCMakeInstance()->IssueMessage(cmake::LOG, @@ -2218,7 +2126,7 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const std::string& config) const { std::vector<std::string> includes; - std::set<std::string> uniqueIncludes; + UNORDERED_SET<std::string> uniqueIncludes; cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "INCLUDE_DIRECTORIES", 0, 0); @@ -2250,95 +2158,47 @@ cmTarget::GetIncludeDirectories(const std::string& config) const config, debugIncludes); - if (!this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[config]) + std::vector<cmTargetInternals::TargetPropertyEntry*> + linkInterfaceIncludeDirectoriesEntries; + this->Internal->AddInterfaceEntries( + this, config, "INTERFACE_INCLUDE_DIRECTORIES", + linkInterfaceIncludeDirectoriesEntries); + + if(this->Makefile->IsOn("APPLE")) { - for (std::vector<cmValueWithOrigin>::const_iterator - it = this->Internal->LinkImplementationPropertyEntries.begin(), - end = this->Internal->LinkImplementationPropertyEntries.end(); - it != end; ++it) - { - if (!cmGeneratorExpression::IsValidTargetName(it->Value) - && cmGeneratorExpression::Find(it->Value) == std::string::npos) - { - continue; - } + LinkImplementation const* impl = this->GetLinkImplementation(config); + for(std::vector<cmLinkImplItem>::const_iterator + it = impl->Libraries.begin(); + it != impl->Libraries.end(); ++it) { - cmGeneratorExpression ge; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(it->Value); - std::string result = cge->Evaluate(this->Makefile, config, - false, this, 0, 0); - if (!this->Makefile->FindTargetToUse(result)) + std::string libDir = cmSystemTools::CollapseFullPath(it->c_str()); + + static cmsys::RegularExpression + frameworkCheck("(.*\\.framework)(/Versions/[^/]+)?/[^/]+$"); + if(!frameworkCheck.find(libDir)) { continue; } - } - std::string includeGenex = "$<TARGET_PROPERTY:" + - it->Value + ",INTERFACE_INCLUDE_DIRECTORIES>"; - if (cmGeneratorExpression::Find(it->Value) != std::string::npos) - { - // Because it->Value is a generator expression, ensure that it - // evaluates to the non-empty string before being used in the - // TARGET_PROPERTY expression. - includeGenex = "$<$<BOOL:" + it->Value + ">:" + includeGenex + ">"; - } - cmGeneratorExpression ge(&it->Backtrace); - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse( - includeGenex); - - this->Internal - ->CachedLinkInterfaceIncludeDirectoriesEntries[config].push_back( - new cmTargetInternals::TargetPropertyEntry(cge, - it->Value)); - } - - if(this->Makefile->IsOn("APPLE")) - { - LinkImplementation const* impl = this->GetLinkImplementation(config, - this); - for(std::vector<std::string>::const_iterator - it = impl->Libraries.begin(); - it != impl->Libraries.end(); ++it) - { - std::string libDir = cmSystemTools::CollapseFullPath(it->c_str()); - - static cmsys::RegularExpression - frameworkCheck("(.*\\.framework)(/Versions/[^/]+)?/[^/]+$"); - if(!frameworkCheck.find(libDir)) - { - continue; - } - libDir = frameworkCheck.match(1); + libDir = frameworkCheck.match(1); - cmGeneratorExpression ge; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(libDir.c_str()); - this->Internal - ->CachedLinkInterfaceIncludeDirectoriesEntries[config] - .push_back(new cmTargetInternals::TargetPropertyEntry(cge)); - } + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(libDir.c_str()); + linkInterfaceIncludeDirectoriesEntries + .push_back(new cmTargetInternals::TargetPropertyEntry(cge)); } } processIncludeDirectories(this, - this->Internal->CachedLinkInterfaceIncludeDirectoriesEntries[config], + linkInterfaceIncludeDirectoriesEntries, includes, uniqueIncludes, &dagChecker, config, debugIncludes); - if (!this->Makefile->IsGeneratingBuildSystem()) - { - deleteAndClear( - this->Internal->CachedLinkInterfaceIncludeDirectoriesEntries); - } - else - { - this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[config] - = true; - } + deleteAndClear(linkInterfaceIncludeDirectoriesEntries); return includes; } @@ -2347,7 +2207,7 @@ cmTarget::GetIncludeDirectories(const std::string& config) const static void processCompileOptionsInternal(cmTarget const* tgt, const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, std::vector<std::string> &options, - std::set<std::string> &uniqueOptions, + UNORDERED_SET<std::string> &uniqueOptions, cmGeneratorExpressionDAGChecker *dagChecker, const std::string& config, bool debugOptions, const char *logName) { @@ -2356,27 +2216,18 @@ static void processCompileOptionsInternal(cmTarget const* tgt, for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator it = entries.begin(), end = entries.end(); it != end; ++it) { - bool cacheOptions = false; - std::vector<std::string> entryOptions = (*it)->CachedEntries; - if(entryOptions.empty()) - { - cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, - config, - false, - tgt, - dagChecker), - entryOptions); - if (mf->IsGeneratingBuildSystem() - && !(*it)->ge->GetHadContextSensitiveCondition()) - { - cacheOptions = true; - } - } + std::vector<std::string> entryOptions; + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, + config, + false, + tgt, + dagChecker), + entryOptions); std::string usedOptions; for(std::vector<std::string>::iterator li = entryOptions.begin(); li != entryOptions.end(); ++li) { - std::string opt = *li; + std::string const& opt = *li; if(uniqueOptions.insert(opt).second) { @@ -2387,10 +2238,6 @@ static void processCompileOptionsInternal(cmTarget const* tgt, } } } - if (cacheOptions) - { - (*it)->CachedEntries = entryOptions; - } if (!usedOptions.empty()) { mf->GetCMakeInstance()->IssueMessage(cmake::LOG, @@ -2406,7 +2253,7 @@ static void processCompileOptionsInternal(cmTarget const* tgt, static void processCompileOptions(cmTarget const* tgt, const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, std::vector<std::string> &options, - std::set<std::string> &uniqueOptions, + UNORDERED_SET<std::string> &uniqueOptions, cmGeneratorExpressionDAGChecker *dagChecker, const std::string& config, bool debugOptions) { @@ -2443,7 +2290,7 @@ void cmTarget::GetAutoUicOptions(std::vector<std::string> &result, void cmTarget::GetCompileOptions(std::vector<std::string> &result, const std::string& config) const { - std::set<std::string> uniqueOptions; + UNORDERED_SET<std::string> uniqueOptions; cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "COMPILE_OPTIONS", 0, 0); @@ -2475,72 +2322,29 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result, config, debugOptions); - if (!this->Internal->CacheLinkInterfaceCompileOptionsDone[config]) - { - for (std::vector<cmValueWithOrigin>::const_iterator - it = this->Internal->LinkImplementationPropertyEntries.begin(), - end = this->Internal->LinkImplementationPropertyEntries.end(); - it != end; ++it) - { - if (!cmGeneratorExpression::IsValidTargetName(it->Value) - && cmGeneratorExpression::Find(it->Value) == std::string::npos) - { - continue; - } - { - cmGeneratorExpression ge; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(it->Value); - std::string targetResult = cge->Evaluate(this->Makefile, config, - false, this, 0, 0); - if (!this->Makefile->FindTargetToUse(targetResult)) - { - continue; - } - } - std::string optionGenex = "$<TARGET_PROPERTY:" + - it->Value + ",INTERFACE_COMPILE_OPTIONS>"; - if (cmGeneratorExpression::Find(it->Value) != std::string::npos) - { - // Because it->Value is a generator expression, ensure that it - // evaluates to the non-empty string before being used in the - // TARGET_PROPERTY expression. - optionGenex = "$<$<BOOL:" + it->Value + ">:" + optionGenex + ">"; - } - cmGeneratorExpression ge(&it->Backtrace); - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse( - optionGenex); + std::vector<cmTargetInternals::TargetPropertyEntry*> + linkInterfaceCompileOptionsEntries; - this->Internal - ->CachedLinkInterfaceCompileOptionsEntries[config].push_back( - new cmTargetInternals::TargetPropertyEntry(cge, - it->Value)); - } - } + this->Internal->AddInterfaceEntries( + this, config, "INTERFACE_COMPILE_OPTIONS", + linkInterfaceCompileOptionsEntries); processCompileOptions(this, - this->Internal->CachedLinkInterfaceCompileOptionsEntries[config], + linkInterfaceCompileOptionsEntries, result, uniqueOptions, &dagChecker, config, debugOptions); - if (!this->Makefile->IsGeneratingBuildSystem()) - { - deleteAndClear(this->Internal->CachedLinkInterfaceCompileOptionsEntries); - } - else - { - this->Internal->CacheLinkInterfaceCompileOptionsDone[config] = true; - } + deleteAndClear(linkInterfaceCompileOptionsEntries); } //---------------------------------------------------------------------------- static void processCompileDefinitions(cmTarget const* tgt, const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, std::vector<std::string> &options, - std::set<std::string> &uniqueOptions, + UNORDERED_SET<std::string> &uniqueOptions, cmGeneratorExpressionDAGChecker *dagChecker, const std::string& config, bool debugOptions) { @@ -2553,7 +2357,7 @@ static void processCompileDefinitions(cmTarget const* tgt, void cmTarget::GetCompileDefinitions(std::vector<std::string> &list, const std::string& config) const { - std::set<std::string> uniqueOptions; + UNORDERED_SET<std::string> uniqueOptions; cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "COMPILE_DEFINITIONS", 0, 0); @@ -2585,109 +2389,61 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list, config, debugDefines); - if (!this->Internal->CacheLinkInterfaceCompileDefinitionsDone[config]) + std::vector<cmTargetInternals::TargetPropertyEntry*> + linkInterfaceCompileDefinitionsEntries; + this->Internal->AddInterfaceEntries( + this, config, "INTERFACE_COMPILE_DEFINITIONS", + linkInterfaceCompileDefinitionsEntries); + if (!config.empty()) { - for (std::vector<cmValueWithOrigin>::const_iterator - it = this->Internal->LinkImplementationPropertyEntries.begin(), - end = this->Internal->LinkImplementationPropertyEntries.end(); - it != end; ++it) - { - if (!cmGeneratorExpression::IsValidTargetName(it->Value) - && cmGeneratorExpression::Find(it->Value) == std::string::npos) - { - continue; - } - { - cmGeneratorExpression ge; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(it->Value); - std::string targetResult = cge->Evaluate(this->Makefile, config, - false, this, 0, 0); - if (!this->Makefile->FindTargetToUse(targetResult)) - { - continue; - } - } - std::string defsGenex = "$<TARGET_PROPERTY:" + - it->Value + ",INTERFACE_COMPILE_DEFINITIONS>"; - if (cmGeneratorExpression::Find(it->Value) != std::string::npos) - { - // Because it->Value is a generator expression, ensure that it - // evaluates to the non-empty string before being used in the - // TARGET_PROPERTY expression. - defsGenex = "$<$<BOOL:" + it->Value + ">:" + defsGenex + ">"; - } - cmGeneratorExpression ge(&it->Backtrace); - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse( - defsGenex); - - this->Internal - ->CachedLinkInterfaceCompileDefinitionsEntries[config].push_back( - new cmTargetInternals::TargetPropertyEntry(cge, - it->Value)); - } - if (!config.empty()) + std::string configPropName = "COMPILE_DEFINITIONS_" + + cmSystemTools::UpperCase(config); + const char *configProp = this->GetProperty(configPropName); + if (configProp) { - std::string configPropName = "COMPILE_DEFINITIONS_" - + cmSystemTools::UpperCase(config); - const char *configProp = this->GetProperty(configPropName); - if (configProp) + switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0043)) { - switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0043)) + case cmPolicies::WARN: { - case cmPolicies::WARN: - { - cmOStringStream e; - e << this->Makefile->GetCMakeInstance()->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0043); - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, - e.str()); - } - case cmPolicies::OLD: - { - cmGeneratorExpression ge; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(configProp); - this->Internal - ->CachedLinkInterfaceCompileDefinitionsEntries[config] - .push_back(new cmTargetInternals::TargetPropertyEntry(cge)); - } - break; - case cmPolicies::NEW: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::REQUIRED_IF_USED: - break; + cmOStringStream e; + e << this->Makefile->GetCMakeInstance()->GetPolicies() + ->GetPolicyWarning(cmPolicies::CMP0043); + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, + e.str()); + } + case cmPolicies::OLD: + { + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(configProp); + linkInterfaceCompileDefinitionsEntries + .push_back(new cmTargetInternals::TargetPropertyEntry(cge)); } + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + break; } } - } processCompileDefinitions(this, - this->Internal->CachedLinkInterfaceCompileDefinitionsEntries[config], + linkInterfaceCompileDefinitionsEntries, list, uniqueOptions, &dagChecker, config, debugDefines); - if (!this->Makefile->IsGeneratingBuildSystem()) - { - deleteAndClear(this->Internal - ->CachedLinkInterfaceCompileDefinitionsEntries); - } - else - { - this->Internal->CacheLinkInterfaceCompileDefinitionsDone[config] - = true; - } + deleteAndClear(linkInterfaceCompileDefinitionsEntries); } //---------------------------------------------------------------------------- static void processCompileFeatures(cmTarget const* tgt, const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, std::vector<std::string> &options, - std::set<std::string> &uniqueOptions, + UNORDERED_SET<std::string> &uniqueOptions, cmGeneratorExpressionDAGChecker *dagChecker, const std::string& config, bool debugOptions) { @@ -2699,7 +2455,7 @@ static void processCompileFeatures(cmTarget const* tgt, void cmTarget::GetCompileFeatures(std::vector<std::string> &result, const std::string& config) const { - std::set<std::string> uniqueFeatures; + UNORDERED_SET<std::string> uniqueFeatures; cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "COMPILE_FEATURES", @@ -2732,65 +2488,21 @@ void cmTarget::GetCompileFeatures(std::vector<std::string> &result, config, debugFeatures); - if (!this->Internal->CacheLinkInterfaceCompileFeaturesDone[config]) - { - for (std::vector<cmValueWithOrigin>::const_iterator - it = this->Internal->LinkImplementationPropertyEntries.begin(), - end = this->Internal->LinkImplementationPropertyEntries.end(); - it != end; ++it) - { - if (!cmGeneratorExpression::IsValidTargetName(it->Value) - && cmGeneratorExpression::Find(it->Value) == std::string::npos) - { - continue; - } - { - cmGeneratorExpression ge; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(it->Value); - std::string targetResult = cge->Evaluate(this->Makefile, config, - false, this, 0, 0); - if (!this->Makefile->FindTargetToUse(targetResult)) - { - continue; - } - } - std::string featureGenex = "$<TARGET_PROPERTY:" + - it->Value + ",INTERFACE_COMPILE_FEATURES>"; - if (cmGeneratorExpression::Find(it->Value) != std::string::npos) - { - // Because it->Value is a generator expression, ensure that it - // evaluates to the non-empty string before being used in the - // TARGET_PROPERTY expression. - featureGenex = "$<$<BOOL:" + it->Value + ">:" + featureGenex + ">"; - } - cmGeneratorExpression ge(&it->Backtrace); - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse( - featureGenex); - - this->Internal - ->CachedLinkInterfaceCompileFeaturesEntries[config].push_back( - new cmTargetInternals::TargetPropertyEntry(cge, - it->Value)); - } - } + std::vector<cmTargetInternals::TargetPropertyEntry*> + linkInterfaceCompileFeaturesEntries; + this->Internal->AddInterfaceEntries( + this, config, "INTERFACE_COMPILE_FEATURES", + linkInterfaceCompileFeaturesEntries); processCompileFeatures(this, - this->Internal->CachedLinkInterfaceCompileFeaturesEntries[config], + linkInterfaceCompileFeaturesEntries, result, uniqueFeatures, &dagChecker, config, debugFeatures); - if (!this->Makefile->IsGeneratingBuildSystem()) - { - deleteAndClear(this->Internal->CachedLinkInterfaceCompileFeaturesEntries); - } - else - { - this->Internal->CacheLinkInterfaceCompileFeaturesDone[config] = true; - } + deleteAndClear(linkInterfaceCompileFeaturesEntries); } //---------------------------------------------------------------------------- @@ -3068,16 +2780,11 @@ const char* cmTarget::GetLocationForBuild() const // Now handle the deprecated build-time configuration location. location = this->GetDirectory(); - if(!location.empty()) - { - location += "/"; - } const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR"); if(cfgid && strcmp(cfgid, ".") != 0) { location += "/"; location += cfgid; - location += "/"; } if(this->IsAppBundleOnApple()) @@ -3198,6 +2905,22 @@ bool cmTarget::HandleLocationPropertyPolicy(cmMakefile* context) const } //---------------------------------------------------------------------------- +static void MakePropertyList(std::string& output, + std::vector<cmTargetInternals::TargetPropertyEntry*> const& values) +{ + output = ""; + std::string sep; + for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator + it = values.begin(), end = values.end(); + it != end; ++it) + { + output += sep; + output += (*it)->ge->GetInput(); + sep = ";"; + } +} + +//---------------------------------------------------------------------------- const char *cmTarget::GetProperty(const std::string& prop) const { return this->GetProperty(prop, this->Makefile); @@ -3217,11 +2940,6 @@ const char *cmTarget::GetProperty(const std::string& prop, return 0; } - if (prop == "NAME") - { - return this->GetName().c_str(); - } - // Watch for special "computed" properties that are dependent on // other properties or variables. Always recompute them. if(this->GetType() == cmTarget::EXECUTABLE || @@ -3230,7 +2948,8 @@ const char *cmTarget::GetProperty(const std::string& prop, this->GetType() == cmTarget::MODULE_LIBRARY || this->GetType() == cmTarget::UNKNOWN_LIBRARY) { - if(prop == "LOCATION") + static const std::string propLOCATION = "LOCATION"; + if(prop == propLOCATION) { if (!this->HandleLocationPropertyPolicy(context)) { @@ -3246,12 +2965,12 @@ const char *cmTarget::GetProperty(const std::string& prop, // cannot take into account the per-configuration name of the // target because the configuration type may not be known at // CMake time. - this->Properties.SetProperty("LOCATION", this->GetLocationForBuild(), + this->Properties.SetProperty(propLOCATION, this->GetLocationForBuild(), cmProperty::TARGET); } // Support "LOCATION_<CONFIG>". - if(cmHasLiteralPrefix(prop, "LOCATION_")) + else if(cmHasLiteralPrefix(prop, "LOCATION_")) { if (!this->HandleLocationPropertyPolicy(context)) { @@ -3263,7 +2982,7 @@ const char *cmTarget::GetProperty(const std::string& prop, cmProperty::TARGET); } // Support "<CONFIG>_LOCATION". - if(cmHasLiteralSuffix(prop, "_LOCATION")) + else if(cmHasLiteralSuffix(prop, "_LOCATION")) { std::string configName(prop.c_str(), prop.size() - 9); if(configName != "IMPORTED") @@ -3278,198 +2997,210 @@ const char *cmTarget::GetProperty(const std::string& prop, } } } - if(prop == "INCLUDE_DIRECTORIES") - { - static std::string output; - output = ""; - std::string sep; - typedef cmTargetInternals::TargetPropertyEntry - TargetPropertyEntry; - for (std::vector<TargetPropertyEntry*>::const_iterator - it = this->Internal->IncludeDirectoriesEntries.begin(), - end = this->Internal->IncludeDirectoriesEntries.end(); - it != end; ++it) - { - output += sep; - output += (*it)->ge->GetInput(); - sep = ";"; + static UNORDERED_SET<std::string> specialProps; +#define MAKE_STATIC_PROP(PROP) \ + static const std::string prop##PROP = #PROP + MAKE_STATIC_PROP(LINK_LIBRARIES); + MAKE_STATIC_PROP(TYPE); + MAKE_STATIC_PROP(INCLUDE_DIRECTORIES); + MAKE_STATIC_PROP(COMPILE_FEATURES); + MAKE_STATIC_PROP(COMPILE_OPTIONS); + MAKE_STATIC_PROP(COMPILE_DEFINITIONS); + MAKE_STATIC_PROP(IMPORTED); + MAKE_STATIC_PROP(NAME); + MAKE_STATIC_PROP(SOURCES); +#undef MAKE_STATIC_PROP + if(specialProps.empty()) + { + specialProps.insert(propLINK_LIBRARIES); + specialProps.insert(propTYPE); + specialProps.insert(propINCLUDE_DIRECTORIES); + specialProps.insert(propCOMPILE_FEATURES); + specialProps.insert(propCOMPILE_OPTIONS); + specialProps.insert(propCOMPILE_DEFINITIONS); + specialProps.insert(propIMPORTED); + specialProps.insert(propNAME); + specialProps.insert(propSOURCES); + } + if(specialProps.count(prop)) + { + if(prop == propLINK_LIBRARIES) + { + if (this->Internal->LinkImplementationPropertyEntries.empty()) + { + return 0; + } + + static std::string output; + output = ""; + std::string sep; + for (std::vector<cmValueWithOrigin>::const_iterator + it = this->Internal->LinkImplementationPropertyEntries.begin(), + end = this->Internal->LinkImplementationPropertyEntries.end(); + it != end; ++it) + { + output += sep; + output += it->Value; + sep = ";"; + } + return output.c_str(); } - return output.c_str(); - } - if(prop == "COMPILE_OPTIONS") - { - static std::string output; - output = ""; - std::string sep; - typedef cmTargetInternals::TargetPropertyEntry - TargetPropertyEntry; - for (std::vector<TargetPropertyEntry*>::const_iterator - it = this->Internal->CompileOptionsEntries.begin(), - end = this->Internal->CompileOptionsEntries.end(); - it != end; ++it) + // the type property returns what type the target is + else if (prop == propTYPE) { - output += sep; - output += (*it)->ge->GetInput(); - sep = ";"; + return cmTarget::GetTargetTypeName(this->GetType()); } - return output.c_str(); - } - if(prop == "COMPILE_FEATURES") - { - static std::string output; - output = ""; - std::string sep; - typedef cmTargetInternals::TargetPropertyEntry - TargetPropertyEntry; - for (std::vector<TargetPropertyEntry*>::const_iterator - it = this->Internal->CompileFeaturesEntries.begin(), - end = this->Internal->CompileFeaturesEntries.end(); - it != end; ++it) + else if(prop == propINCLUDE_DIRECTORIES) { - output += sep; - output += (*it)->ge->GetInput(); - sep = ";"; + if (this->Internal->IncludeDirectoriesEntries.empty()) + { + return 0; + } + + static std::string output; + MakePropertyList(output, this->Internal->IncludeDirectoriesEntries); + return output.c_str(); } - return output.c_str(); - } - if(prop == "COMPILE_DEFINITIONS") - { - static std::string output; - output = ""; - std::string sep; - typedef cmTargetInternals::TargetPropertyEntry - TargetPropertyEntry; - for (std::vector<TargetPropertyEntry*>::const_iterator - it = this->Internal->CompileDefinitionsEntries.begin(), - end = this->Internal->CompileDefinitionsEntries.end(); - it != end; ++it) + else if(prop == propCOMPILE_FEATURES) { - output += sep; - output += (*it)->ge->GetInput(); - sep = ";"; + if (this->Internal->CompileFeaturesEntries.empty()) + { + return 0; + } + + static std::string output; + MakePropertyList(output, this->Internal->CompileFeaturesEntries); + return output.c_str(); } - return output.c_str(); - } - if(prop == "LINK_LIBRARIES") - { - static std::string output; - output = ""; - std::string sep; - for (std::vector<cmValueWithOrigin>::const_iterator - it = this->Internal->LinkImplementationPropertyEntries.begin(), - end = this->Internal->LinkImplementationPropertyEntries.end(); - it != end; ++it) + else if(prop == propCOMPILE_OPTIONS) { - output += sep; - output += it->Value; - sep = ";"; - } - return output.c_str(); - } + if (this->Internal->CompileOptionsEntries.empty()) + { + return 0; + } - if (prop == "IMPORTED") - { - return this->IsImported()?"TRUE":"FALSE"; - } + static std::string output; + MakePropertyList(output, this->Internal->CompileOptionsEntries); + return output.c_str(); + } + else if(prop == propCOMPILE_DEFINITIONS) + { + if (this->Internal->CompileDefinitionsEntries.empty()) + { + return 0; + } - if(prop == "SOURCES") - { - cmOStringStream ss; - const char* sep = ""; - typedef cmTargetInternals::TargetPropertyEntry - TargetPropertyEntry; - for(std::vector<TargetPropertyEntry*>::const_iterator - i = this->Internal->SourceEntries.begin(); - i != this->Internal->SourceEntries.end(); ++i) + static std::string output; + MakePropertyList(output, this->Internal->CompileDefinitionsEntries); + return output.c_str(); + } + else if (prop == propIMPORTED) { - std::string entry = (*i)->ge->GetInput(); + return this->IsImported()?"TRUE":"FALSE"; + } + else if (prop == propNAME) + { + return this->GetName().c_str(); + } + else if(prop == propSOURCES) + { + if (this->Internal->SourceEntries.empty()) + { + return 0; + } - std::vector<std::string> files; - cmSystemTools::ExpandListArgument(entry, files); - for (std::vector<std::string>::const_iterator - li = files.begin(); li != files.end(); ++li) + cmOStringStream ss; + const char* sep = ""; + typedef cmTargetInternals::TargetPropertyEntry + TargetPropertyEntry; + for(std::vector<TargetPropertyEntry*>::const_iterator + i = this->Internal->SourceEntries.begin(); + i != this->Internal->SourceEntries.end(); ++i) { - if(cmHasLiteralPrefix(*li, "$<TARGET_OBJECTS:") && - (*li)[li->size() - 1] == '>') - { - std::string objLibName = li->substr(17, li->size()-18); + std::string entry = (*i)->ge->GetInput(); - if (cmGeneratorExpression::Find(objLibName) != std::string::npos) + std::vector<std::string> files; + cmSystemTools::ExpandListArgument(entry, files); + for (std::vector<std::string>::const_iterator + li = files.begin(); li != files.end(); ++li) + { + if(cmHasLiteralPrefix(*li, "$<TARGET_OBJECTS:") && + (*li)[li->size() - 1] == '>') { - ss << sep; - sep = ";"; - ss << *li; - continue; - } + std::string objLibName = li->substr(17, li->size()-18); - bool addContent = false; - bool noMessage = true; - cmOStringStream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; - switch(context->GetPolicyStatus(cmPolicies::CMP0051)) - { - case cmPolicies::WARN: - e << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0051)) << "\n"; - noMessage = false; - case cmPolicies::OLD: - break; - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::NEW: - addContent = true; - } - if (!noMessage) - { - e << "Target \"" << this->Name << "\" contains $<TARGET_OBJECTS> " - "generator expression in its sources list. This content was not " - "previously part of the SOURCES property when that property was " - "read at configure time. Code reading that property needs to be " - "adapted to ignore the generator expression using the " - "string(GENEX_STRIP) command."; - context->IssueMessage(messageType, e.str()); + if (cmGeneratorExpression::Find(objLibName) != std::string::npos) + { + ss << sep; + sep = ";"; + ss << *li; + continue; + } + + bool addContent = false; + bool noMessage = true; + cmOStringStream e; + cmake::MessageType messageType = cmake::AUTHOR_WARNING; + switch(context->GetPolicyStatus(cmPolicies::CMP0051)) + { + case cmPolicies::WARN: + e << (this->Makefile->GetPolicies() + ->GetPolicyWarning(cmPolicies::CMP0051)) << "\n"; + noMessage = false; + case cmPolicies::OLD: + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::NEW: + addContent = true; + } + if (!noMessage) + { + e << "Target \"" << this->Name << "\" contains " + "$<TARGET_OBJECTS> generator expression in its sources list. " + "This content was not previously part of the SOURCES property " + "when that property was read at configure time. Code reading " + "that property needs to be adapted to ignore the generator " + "expression using the string(GENEX_STRIP) command."; + context->IssueMessage(messageType, e.str()); + } + if (addContent) + { + ss << sep; + sep = ";"; + ss << *li; + } } - if (addContent) + else if (cmGeneratorExpression::Find(*li) == std::string::npos) { ss << sep; sep = ";"; ss << *li; } - } - else if (cmGeneratorExpression::Find(*li) == std::string::npos) - { - ss << sep; - sep = ";"; - ss << *li; - } - else - { - cmSourceFile *sf = this->Makefile->GetOrCreateSource(*li); - // Construct what is known about this source file location. - cmSourceFileLocation const& location = sf->GetLocation(); - std::string sname = location.GetDirectory(); - if(!sname.empty()) + else { - sname += "/"; - } - sname += location.GetName(); + cmSourceFile *sf = this->Makefile->GetOrCreateSource(*li); + // Construct what is known about this source file location. + cmSourceFileLocation const& location = sf->GetLocation(); + std::string sname = location.GetDirectory(); + if(!sname.empty()) + { + sname += "/"; + } + sname += location.GetName(); - ss << sep; - sep = ";"; - // Append this list entry. - ss << sname; + ss << sep; + sep = ";"; + // Append this list entry. + ss << sname; + } } } + this->Properties.SetProperty("SOURCES", ss.str().c_str(), + cmProperty::TARGET); } - this->Properties.SetProperty("SOURCES", ss.str().c_str(), - cmProperty::TARGET); } - // the type property returns what type the target is - if (prop == "TYPE") - { - return cmTarget::GetTargetTypeName(this->GetType()); - } bool chain = false; const char *retVal = this->Properties.GetPropertyValue(prop, cmProperty::TARGET, chain); @@ -3492,19 +3223,17 @@ class cmTargetCollectLinkLanguages public: cmTargetCollectLinkLanguages(cmTarget const* target, const std::string& config, - std::set<std::string>& languages, + UNORDERED_SET<std::string>& languages, cmTarget const* head): Config(config), Languages(languages), HeadTarget(head), Makefile(target->GetMakefile()), Target(target) { this->Visited.insert(target); } - void Visit(const std::string& name) + void Visit(cmLinkItem const& item) { - cmTarget *target = this->Makefile->FindTargetToUse(name); - - if(!target) + if(!item.Target) { - if(name.find("::") != std::string::npos) + if(item.find("::") != std::string::npos) { bool noMessage = false; cmake::MessageType messageType = cmake::FATAL_ERROR; @@ -3530,7 +3259,7 @@ public: if(!noMessage) { e << "Target \"" << this->Target->GetName() - << "\" links to target \"" << name + << "\" links to target \"" << item << "\" but the target was not found. Perhaps a find_package() " "call is missing for an IMPORTED target, or an ALIAS target is " "missing?"; @@ -3541,13 +3270,13 @@ public: } return; } - if(!this->Visited.insert(target).second) + if(!this->Visited.insert(item.Target).second) { return; } cmTarget::LinkInterface const* iface = - target->GetLinkInterface(this->Config, this->HeadTarget); + item.Target->GetLinkInterface(this->Config, this->HeadTarget); if(!iface) { return; } for(std::vector<std::string>::const_iterator @@ -3556,7 +3285,7 @@ public: this->Languages.insert(*li); } - for(std::vector<std::string>::const_iterator + for(std::vector<cmLinkItem>::const_iterator li = iface->Libraries.begin(); li != iface->Libraries.end(); ++li) { this->Visit(*li); @@ -3564,7 +3293,7 @@ public: } private: std::string Config; - std::set<std::string>& Languages; + UNORDERED_SET<std::string>& Languages; cmTarget const* HeadTarget; cmMakefile* Makefile; const cmTarget* Target; @@ -3572,25 +3301,22 @@ private: }; //---------------------------------------------------------------------------- -std::string cmTarget::GetLinkerLanguage(const std::string& config, - cmTarget const* head) const +std::string cmTarget::GetLinkerLanguage(const std::string& config) const { - cmTarget const* headTarget = head ? head : this; - return this->GetLinkClosure(config, headTarget)->LinkerLanguage; + return this->GetLinkClosure(config)->LinkerLanguage; } //---------------------------------------------------------------------------- -cmTarget::LinkClosure const* cmTarget::GetLinkClosure( - const std::string& config, - cmTarget const* head) const +cmTarget::LinkClosure const* +cmTarget::GetLinkClosure(const std::string& config) const { - TargetConfigPair key(head, cmSystemTools::UpperCase(config)); + std::string key(cmSystemTools::UpperCase(config)); cmTargetInternals::LinkClosureMapType::iterator i = this->Internal->LinkClosureMap.find(key); if(i == this->Internal->LinkClosureMap.end()) { LinkClosure lc; - this->ComputeLinkClosure(config, lc, head); + this->ComputeLinkClosure(config, lc); cmTargetInternals::LinkClosureMapType::value_type entry(key, lc); i = this->Internal->LinkClosureMap.insert(entry).first; } @@ -3604,7 +3330,7 @@ class cmTargetSelectLinker cmTarget const* Target; cmMakefile* Makefile; cmGlobalGenerator* GG; - std::set<std::string> Preferred; + UNORDERED_SET<std::string> Preferred; public: cmTargetSelectLinker(cmTarget const* target): Preference(0), Target(target) { @@ -3636,7 +3362,7 @@ public: e << "Target " << this->Target->GetName() << " contains multiple languages with the highest linker preference" << " (" << this->Preference << "):\n"; - for(std::set<std::string>::const_iterator + for(UNORDERED_SET<std::string>::const_iterator li = this->Preferred.begin(); li != this->Preferred.end(); ++li) { e << " " << *li << "\n"; @@ -3651,12 +3377,12 @@ public: }; //---------------------------------------------------------------------------- -void cmTarget::ComputeLinkClosure(const std::string& config, LinkClosure& lc, - cmTarget const* head) const +void cmTarget::ComputeLinkClosure(const std::string& config, + LinkClosure& lc) const { // Get languages built in this target. - std::set<std::string> languages; - LinkImplementation const* impl = this->GetLinkImplementation(config, head); + UNORDERED_SET<std::string> languages; + LinkImplementation const* impl = this->GetLinkImplementation(config); for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); li != impl->Languages.end(); ++li) { @@ -3664,15 +3390,16 @@ void cmTarget::ComputeLinkClosure(const std::string& config, LinkClosure& lc, } // Add interface languages from linked targets. - cmTargetCollectLinkLanguages cll(this, config, languages, head); - for(std::vector<std::string>::const_iterator li = impl->Libraries.begin(); + cmTargetCollectLinkLanguages cll(this, config, languages, this); + for(std::vector<cmLinkImplItem>::const_iterator + li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) { cll.Visit(*li); } // Store the transitive closure of languages. - for(std::set<std::string>::const_iterator li = languages.begin(); + for(UNORDERED_SET<std::string>::const_iterator li = languages.begin(); li != languages.end(); ++li) { lc.Languages.push_back(*li); @@ -3700,7 +3427,7 @@ void cmTarget::ComputeLinkClosure(const std::string& config, LinkClosure& lc, } // Now consider languages that propagate from linked targets. - for(std::set<std::string>::const_iterator sit = languages.begin(); + for(UNORDERED_SET<std::string>::const_iterator sit = languages.begin(); sit != languages.end(); ++sit) { std::string propagates = "CMAKE_"+*sit+"_LINKER_PREFERENCE_PROPAGATES"; @@ -3715,6 +3442,51 @@ void cmTarget::ComputeLinkClosure(const std::string& config, LinkClosure& lc, } //---------------------------------------------------------------------------- +void cmTarget::ExpandLinkItems(std::string const& prop, + std::string const& value, + std::string const& config, + cmTarget const* headTarget, + bool usage_requirements_only, + std::vector<cmLinkItem>& items, + bool& hadHeadSensitiveCondition) const +{ + cmGeneratorExpression ge; + cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, 0, 0); + // The $<LINK_ONLY> expression may be in a link interface to specify private + // link dependencies that are otherwise excluded from usage requirements. + if(usage_requirements_only) + { + dagChecker.SetTransitivePropertiesOnly(); + } + std::vector<std::string> libs; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); + cmSystemTools::ExpandListArgument(cge->Evaluate( + this->Makefile, + config, + false, + headTarget, + this, &dagChecker), libs); + this->LookupLinkItems(libs, items); + hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); +} + +//---------------------------------------------------------------------------- +void cmTarget::LookupLinkItems(std::vector<std::string> const& names, + std::vector<cmLinkItem>& items) const +{ + for(std::vector<std::string>::const_iterator i = names.begin(); + i != names.end(); ++i) + { + std::string name = this->CheckCMP0004(*i); + if(name == this->GetName() || name.empty()) + { + continue; + } + items.push_back(cmLinkItem(name, this->FindTargetToLink(name))); + } +} + +//---------------------------------------------------------------------------- const char* cmTarget::GetSuffixVariableInternal(bool implib) const { switch(this->GetType()) @@ -3732,7 +3504,10 @@ const char* cmTarget::GetSuffixVariableInternal(bool implib) const case cmTarget::EXECUTABLE: return (implib ? "CMAKE_IMPORT_LIBRARY_SUFFIX" - : "CMAKE_EXECUTABLE_SUFFIX"); + // Android GUI application packages store the native + // binary as a shared library. + : (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")? + "CMAKE_SHARED_LIBRARY_SUFFIX" : "CMAKE_EXECUTABLE_SUFFIX")); default: break; } @@ -3756,7 +3531,12 @@ const char* cmTarget::GetPrefixVariableInternal(bool implib) const ? "CMAKE_IMPORT_LIBRARY_PREFIX" : "CMAKE_SHARED_MODULE_PREFIX"); case cmTarget::EXECUTABLE: - return (implib? "CMAKE_IMPORT_LIBRARY_PREFIX" : ""); + return (implib + ? "CMAKE_IMPORT_LIBRARY_PREFIX" + // Android GUI application packages store the native + // binary as a shared library. + : (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")? + "CMAKE_SHARED_LIBRARY_PREFIX" : "")); default: break; } @@ -3845,8 +3625,7 @@ bool cmTarget::HasSOName(const std::string& config) const return ((this->GetType() == cmTarget::SHARED_LIBRARY || this->GetType() == cmTarget::MODULE_LIBRARY) && !this->GetPropertyAsBool("NO_SONAME") && - this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config, - this))); + this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config))); } //---------------------------------------------------------------------------- @@ -3855,7 +3634,7 @@ std::string cmTarget::GetSOName(const std::string& config) const if(this->IsImported()) { // Lookup the imported soname. - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) { if(info->NoSOName) { @@ -3923,7 +3702,7 @@ bool cmTarget::HasMacOSXRpathInstallNameDir(const std::string& config) const else { // Lookup the imported soname. - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) { if(!info->NoSOName && !info->SOName.empty()) { @@ -4009,7 +3788,7 @@ bool cmTarget::IsImportedSharedLibWithoutSOName( { if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY) { - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) { return info->NoSOName; } @@ -4133,7 +3912,7 @@ std::string cmTarget::ImportedGetFullPath(const std::string& config, bool implib) const { std::string result; - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) { result = implib? info->ImportLibrary : info->Location; } @@ -4219,7 +3998,7 @@ void cmTarget::GetFullNameInternal(const std::string& config, const char* suffixVar = this->GetSuffixVariableInternal(implib); // Check for language-specific default prefix and suffix. - std::string ll = this->GetLinkerLanguage(config, this); + std::string ll = this->GetLinkerLanguage(config); if(!ll.empty()) { if(!targetSuffix && suffixVar && *suffixVar) @@ -4320,6 +4099,7 @@ void cmTarget::GetLibraryNames(std::string& name, const char* version = this->GetProperty("VERSION"); const char* soversion = this->GetProperty("SOVERSION"); if(!this->HasSOName(config) || + this->Makefile->IsOn("CMAKE_PLATFORM_NO_VERSIONED_SONAME") || this->IsFrameworkOnApple()) { // Versioning is supported only for shared libraries and modules, @@ -4506,9 +4286,12 @@ bool cmTarget::HaveBuildTreeRPATH(const std::string& config) const { return false; } - std::vector<std::string> libs; - this->GetDirectLinkLibraries(config, libs, this); - return !libs.empty(); + if(LinkImplementationLibraries const* impl = + this->GetLinkImplementationLibraries(config)) + { + return !impl->Libraries.empty(); + } + return false; } //---------------------------------------------------------------------------- @@ -4557,7 +4340,7 @@ bool cmTarget::NeedRelinkBeforeInstall(const std::string& config) const } // Check for rpath support on this platform. - std::string ll = this->GetLinkerLanguage(config, this); + std::string ll = this->GetLinkerLanguage(config); if(!ll.empty()) { std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; @@ -4949,12 +4732,13 @@ bool cmTarget::IsNullImpliedByLinkLibraries(const std::string &p) const //---------------------------------------------------------------------------- template<typename PropertyType> -PropertyType getTypedProperty(cmTarget const* tgt, const char *prop, +PropertyType getTypedProperty(cmTarget const* tgt, const std::string& prop, PropertyType *); //---------------------------------------------------------------------------- template<> -bool getTypedProperty<bool>(cmTarget const* tgt, const char *prop, bool *) +bool getTypedProperty<bool>(cmTarget const* tgt, const std::string& prop, + bool *) { return tgt->GetPropertyAsBool(prop); } @@ -4962,7 +4746,7 @@ bool getTypedProperty<bool>(cmTarget const* tgt, const char *prop, bool *) //---------------------------------------------------------------------------- template<> const char *getTypedProperty<const char *>(cmTarget const* tgt, - const char *prop, + const std::string& prop, const char **) { return tgt->GetProperty(prop); @@ -5201,7 +4985,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, CompatibleType t, PropertyType *) { - PropertyType propContent = getTypedProperty<PropertyType>(tgt, p.c_str(), + PropertyType propContent = getTypedProperty<PropertyType>(tgt, p, 0); const bool explicitlySet = tgt->GetProperties() .find(p) @@ -5211,8 +4995,8 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, assert((impliedByUse ^ explicitlySet) || (!impliedByUse && !explicitlySet)); - std::vector<cmTarget*> deps; - tgt->GetTransitiveTargetClosure(config, tgt, deps); + std::vector<cmTarget const*> const& deps = + tgt->GetLinkImplementationClosure(config); if(deps.empty()) { @@ -5237,7 +5021,8 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, report += "\" property not set.\n"; } - for(std::vector<cmTarget*>::const_iterator li = + std::string interfaceProperty = "INTERFACE_" + p; + for(std::vector<cmTarget const*>::const_iterator li = deps.begin(); li != deps.end(); ++li) { @@ -5250,11 +5035,11 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, cmTarget const* theTarget = *li; const bool ifaceIsSet = theTarget->GetProperties() - .find("INTERFACE_" + p) + .find(interfaceProperty) != theTarget->GetProperties().end(); PropertyType ifacePropContent = getTypedProperty<PropertyType>(theTarget, - ("INTERFACE_" + p).c_str(), 0); + interfaceProperty, 0); std::string reportEntry; if (ifaceIsSet) @@ -5423,45 +5208,6 @@ const char * cmTarget::GetLinkInterfaceDependentNumberMaxProperty( } //---------------------------------------------------------------------------- -bool isLinkDependentProperty(cmTarget const* tgt, const std::string &p, - const std::string& interfaceProperty, - const std::string& config) -{ - std::vector<cmTarget*> deps; - tgt->GetTransitiveTargetClosure(config, tgt, deps); - - if(deps.empty()) - { - return false; - } - - for(std::vector<cmTarget*>::const_iterator li = - deps.begin(); - li != deps.end(); ++li) - { - const char *prop = (*li)->GetProperty(interfaceProperty); - if (!prop) - { - continue; - } - - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(prop, props); - - for(std::vector<std::string>::iterator pi = props.begin(); - pi != props.end(); ++pi) - { - if (*pi == p) - { - return true; - } - } - } - - return false; -} - -//---------------------------------------------------------------------------- bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p, const std::string& config) const { @@ -5470,9 +5216,7 @@ bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p, { return false; } - return (p == "POSITION_INDEPENDENT_CODE") || - isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_BOOL", - config); + return this->GetCompatibleInterfaces(config).PropsBool.count(p) > 0; } //---------------------------------------------------------------------------- @@ -5484,9 +5228,7 @@ bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p, { return false; } - return (p == "AUTOUIC_OPTIONS") || - isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_STRING", - config); + return this->GetCompatibleInterfaces(config).PropsString.count(p) > 0; } //---------------------------------------------------------------------------- @@ -5498,8 +5240,7 @@ bool cmTarget::IsLinkInterfaceDependentNumberMinProperty(const std::string &p, { return false; } - return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_NUMBER_MIN", - config); + return this->GetCompatibleInterfaces(config).PropsNumberMin.count(p) > 0; } //---------------------------------------------------------------------------- @@ -5511,8 +5252,7 @@ bool cmTarget::IsLinkInterfaceDependentNumberMaxProperty(const std::string &p, { return false; } - return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_NUMBER_MAX", - config); + return this->GetCompatibleInterfaces(config).PropsNumberMax.count(p) > 0; } //---------------------------------------------------------------------------- @@ -5558,11 +5298,10 @@ cmTarget::GetObjectLibrariesCMP0026(std::vector<cmTarget*>& objlibs) const //---------------------------------------------------------------------------- void cmTarget::GetLanguages(std::set<std::string>& languages, - const std::string& config, - cmTarget const* head) const + const std::string& config) const { std::vector<cmSourceFile*> sourceFiles; - this->GetSourceFiles(sourceFiles, config, head); + this->GetSourceFiles(sourceFiles, config); for(std::vector<cmSourceFile*>::const_iterator i = sourceFiles.begin(); i != sourceFiles.end(); ++i) { @@ -5598,7 +5337,7 @@ void cmTarget::GetLanguages(std::set<std::string>& languages, for(std::vector<cmTarget*>::const_iterator i = objectLibraries.begin(); i != objectLibraries.end(); ++i) { - (*i)->GetLanguages(languages, config, head); + (*i)->GetLanguages(languages, config); } } @@ -5646,7 +5385,7 @@ bool cmTarget::IsChrpathUsed(const std::string& config) const #if defined(CMAKE_USE_ELF_PARSER) // Enable if the rpath flag uses a separator and the target uses ELF // binaries. - std::string ll = this->GetLinkerLanguage(config, this); + std::string ll = this->GetLinkerLanguage(config); if(!ll.empty()) { std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; @@ -5671,8 +5410,7 @@ bool cmTarget::IsChrpathUsed(const std::string& config) const //---------------------------------------------------------------------------- cmTarget::ImportInfo const* -cmTarget::GetImportInfo(const std::string& config, - cmTarget const* headTarget) const +cmTarget::GetImportInfo(const std::string& config) const { // There is no imported information for non-imported targets. if(!this->IsImported()) @@ -5691,16 +5429,15 @@ cmTarget::GetImportInfo(const std::string& config, { config_upper = "NOCONFIG"; } - TargetConfigPair key(headTarget, config_upper); typedef cmTargetInternals::ImportInfoMapType ImportInfoMapType; ImportInfoMapType::const_iterator i = - this->Internal->ImportInfoMap.find(key); + this->Internal->ImportInfoMap.find(config_upper); if(i == this->Internal->ImportInfoMap.end()) { ImportInfo info; - this->ComputeImportInfo(config_upper, info, headTarget); - ImportInfoMapType::value_type entry(key, info); + this->ComputeImportInfo(config_upper, info); + ImportInfoMapType::value_type entry(config_upper, info); i = this->Internal->ImportInfoMap.insert(entry).first; } @@ -5852,8 +5589,7 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, //---------------------------------------------------------------------------- void cmTarget::ComputeImportInfo(std::string const& desired_config, - ImportInfo& info, - cmTarget const* headTarget) const + ImportInfo& info) const { // This method finds information about an imported target from its // properties. The "IMPORTED_" namespace is reserved for properties @@ -5892,19 +5628,8 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, } if(propertyLibs) { - cmGeneratorExpression ge; - - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), - linkProp, 0, 0); - cmSystemTools::ExpandListArgument(ge.Parse(propertyLibs) - ->Evaluate(this->Makefile, - desired_config, - false, - headTarget, - this, - &dagChecker), - info.LinkInterface.Libraries); + info.LibrariesProp = linkProp; + info.Libraries = propertyLibs; } } if(this->GetType() == INTERFACE_LIBRARY) @@ -5990,13 +5715,12 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, linkProp += suffix; if(const char* config_libs = this->GetProperty(linkProp)) { - cmSystemTools::ExpandListArgument(config_libs, - info.LinkInterface.SharedDeps); + info.SharedDeps = config_libs; } else if(const char* libs = this->GetProperty("IMPORTED_LINK_DEPENDENT_LIBRARIES")) { - cmSystemTools::ExpandListArgument(libs, info.LinkInterface.SharedDeps); + info.SharedDeps = libs; } } @@ -6007,14 +5731,12 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, linkProp += suffix; if(const char* config_libs = this->GetProperty(linkProp)) { - cmSystemTools::ExpandListArgument(config_libs, - info.LinkInterface.Languages); + info.Languages = config_libs; } else if(const char* libs = this->GetProperty("IMPORTED_LINK_INTERFACE_LANGUAGES")) { - cmSystemTools::ExpandListArgument(libs, - info.LinkInterface.Languages); + info.Languages = libs; } } @@ -6025,12 +5747,12 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, linkProp += suffix; if(const char* config_reps = this->GetProperty(linkProp)) { - sscanf(config_reps, "%u", &info.LinkInterface.Multiplicity); + sscanf(config_reps, "%u", &info.Multiplicity); } else if(const char* reps = this->GetProperty("IMPORTED_LINK_INTERFACE_MULTIPLICITY")) { - sscanf(reps, "%u", &info.LinkInterface.Multiplicity); + sscanf(reps, "%u", &info.Multiplicity); } } } @@ -6043,11 +5765,7 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface( // Imported targets have their own link interface. if(this->IsImported()) { - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, head)) - { - return &info->LinkInterface; - } - return 0; + return this->GetImportLinkInterface(config, head, false); } // Link interfaces are not supported for executables that do not @@ -6059,48 +5777,46 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface( } // Lookup any existing link interface for this configuration. - TargetConfigPair key(head, cmSystemTools::UpperCase(config)); + std::string CONFIG = cmSystemTools::UpperCase(config); + cmTargetInternals::HeadToLinkInterfaceMap& hm = + this->Internal->LinkInterfaceMap[CONFIG]; - cmTargetInternals::LinkInterfaceMapType::iterator - i = this->Internal->LinkInterfaceMap.find(key); - if(i == this->Internal->LinkInterfaceMap.end()) + // If the link interface does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) { - // Compute the link interface for this configuration. - cmTargetInternals::OptionalLinkInterface iface; - iface.ExplicitLibraries = - this->ComputeLinkInterfaceLibraries(config, iface, head, iface.Exists); - if (iface.Exists) - { - this->Internal->ComputeLinkInterface(this, config, iface, - head, iface.ExplicitLibraries); - } + return &hm.begin()->second; + } - // Store the information for this configuration. - cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface); - i = this->Internal->LinkInterfaceMap.insert(entry).first; + cmTargetInternals::OptionalLinkInterface& iface = hm[head]; + if(!iface.LibrariesDone) + { + iface.LibrariesDone = true; + this->Internal->ComputeLinkInterfaceLibraries( + this, config, iface, head, false); } - else if(!i->second.Complete && i->second.Exists) + if(!iface.AllDone) { - this->Internal->ComputeLinkInterface(this, config, i->second, head, - i->second.ExplicitLibraries); + iface.AllDone = true; + if(iface.Exists) + { + this->Internal->ComputeLinkInterface(this, config, iface, head); + } } - return i->second.Exists ? &i->second : 0; + return iface.Exists? &iface : 0; } //---------------------------------------------------------------------------- -cmTarget::LinkInterface const* +cmTarget::LinkInterfaceLibraries const* cmTarget::GetLinkInterfaceLibraries(const std::string& config, - cmTarget const* head) const + cmTarget const* head, + bool usage_requirements_only) const { // Imported targets have their own link interface. if(this->IsImported()) { - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, head)) - { - return &info->LinkInterface; - } - return 0; + return this->GetImportLinkInterface(config, head, usage_requirements_only); } // Link interfaces are not supported for executables that do not @@ -6112,136 +5828,162 @@ cmTarget::GetLinkInterfaceLibraries(const std::string& config, } // Lookup any existing link interface for this configuration. - TargetConfigPair key(head, cmSystemTools::UpperCase(config)); + std::string CONFIG = cmSystemTools::UpperCase(config); + cmTargetInternals::HeadToLinkInterfaceMap& hm = + (usage_requirements_only ? + this->Internal->LinkInterfaceUsageRequirementsOnlyMap[CONFIG] : + this->Internal->LinkInterfaceMap[CONFIG]); - cmTargetInternals::LinkInterfaceMapType::iterator - i = this->Internal->LinkInterfaceMap.find(key); - if(i == this->Internal->LinkInterfaceMap.end()) + // If the link interface does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) { - // Compute the link interface for this configuration. - cmTargetInternals::OptionalLinkInterface iface; - iface.ExplicitLibraries = this->ComputeLinkInterfaceLibraries(config, - iface, - head, - iface.Exists); + return &hm.begin()->second; + } - // Store the information for this configuration. - cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface); - i = this->Internal->LinkInterfaceMap.insert(entry).first; + cmTargetInternals::OptionalLinkInterface& iface = hm[head]; + if(!iface.LibrariesDone) + { + iface.LibrariesDone = true; + this->Internal->ComputeLinkInterfaceLibraries( + this, config, iface, head, usage_requirements_only); } - return i->second.Exists ? &i->second : 0; + return iface.Exists? &iface : 0; } //---------------------------------------------------------------------------- -void processILibs(const std::string& config, - cmTarget const* headTarget, - std::string const& name, - std::vector<cmTarget*>& tgts, std::set<cmTarget*>& emitted) +cmTarget::LinkInterface const* +cmTarget::GetImportLinkInterface(const std::string& config, + cmTarget const* headTarget, + bool usage_requirements_only) const { - if (cmTarget* tgt = headTarget->GetMakefile() - ->FindTargetToUse(name)) + cmTarget::ImportInfo const* info = this->GetImportInfo(config); + if(!info) { - if (emitted.insert(tgt).second) - { - tgts.push_back(tgt); - std::vector<std::string> ilibs; - cmTarget::LinkInterface const* iface = - tgt->GetLinkInterfaceLibraries(config, headTarget); - if (iface) - { - for(std::vector<std::string>::const_iterator - it = iface->Libraries.begin(); - it != iface->Libraries.end(); ++it) - { - processILibs(config, headTarget, *it, tgts, emitted); - } - } - } + return 0; } -} -//---------------------------------------------------------------------------- -void cmTarget::GetTransitiveTargetClosure(const std::string& config, - cmTarget const* headTarget, - std::vector<cmTarget*> &tgts) const -{ - std::set<cmTarget*> emitted; + std::string CONFIG = cmSystemTools::UpperCase(config); + cmTargetInternals::HeadToLinkInterfaceMap& hm = + (usage_requirements_only ? + this->Internal->LinkInterfaceUsageRequirementsOnlyMap[CONFIG] : + this->Internal->LinkInterfaceMap[CONFIG]); - cmTarget::LinkImplementation const* impl - = this->GetLinkImplementationLibraries(config, headTarget); + // If the link interface does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) + { + return &hm.begin()->second; + } - for(std::vector<std::string>::const_iterator it = impl->Libraries.begin(); - it != impl->Libraries.end(); ++it) + cmTargetInternals::OptionalLinkInterface& iface = hm[headTarget]; + if(!iface.AllDone) { - processILibs(config, headTarget, *it, tgts, emitted); + iface.AllDone = true; + iface.Multiplicity = info->Multiplicity; + cmSystemTools::ExpandListArgument(info->Languages, iface.Languages); + this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config, + headTarget, usage_requirements_only, + iface.Libraries, + iface.HadHeadSensitiveCondition); + std::vector<std::string> deps; + cmSystemTools::ExpandListArgument(info->SharedDeps, deps); + this->LookupLinkItems(deps, iface.SharedDeps); } + + return &iface; } //---------------------------------------------------------------------------- -void cmTarget::GetTransitivePropertyTargets(const std::string& config, - cmTarget const* headTarget, - std::vector<cmTarget*> &tgts) const +void processILibs(const std::string& config, + cmTarget const* headTarget, + cmLinkItem const& item, + std::vector<cmTarget const*>& tgts, + std::set<cmTarget const*>& emitted) { - cmTarget::LinkInterface const* iface - = this->GetLinkInterfaceLibraries(config, headTarget); - if (!iface) + if (item.Target && emitted.insert(item.Target).second) { - return; - } - if(this->GetType() != STATIC_LIBRARY - || this->GetPolicyStatusCMP0022() == cmPolicies::WARN - || this->GetPolicyStatusCMP0022() == cmPolicies::OLD) - { - for(std::vector<std::string>::const_iterator it = iface->Libraries.begin(); - it != iface->Libraries.end(); ++it) + tgts.push_back(item.Target); + if(cmTarget::LinkInterfaceLibraries const* iface = + item.Target->GetLinkInterfaceLibraries(config, headTarget, true)) { - if (cmTarget* tgt = headTarget->GetMakefile() - ->FindTargetToUse(*it)) + for(std::vector<cmLinkItem>::const_iterator + it = iface->Libraries.begin(); + it != iface->Libraries.end(); ++it) { - tgts.push_back(tgt); + processILibs(config, headTarget, *it, tgts, emitted); } } - return; } +} - const char* linkIfaceProp = "INTERFACE_LINK_LIBRARIES"; - const char* interfaceLibs = this->GetProperty(linkIfaceProp); - - if (!interfaceLibs) +//---------------------------------------------------------------------------- +std::vector<cmTarget const*> const& +cmTarget::GetLinkImplementationClosure(const std::string& config) const +{ + cmTargetInternals::LinkImplClosure& tgts = + this->Internal->LinkImplClosureMap[config]; + if(!tgts.Done) { - return; - } + tgts.Done = true; + std::set<cmTarget const*> emitted; - // The interface libraries have been explicitly set. - cmGeneratorExpression ge; - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), - linkIfaceProp, 0, 0); - dagChecker.SetTransitivePropertiesOnly(); - std::vector<std::string> libs; - cmSystemTools::ExpandListArgument(ge.Parse(interfaceLibs)->Evaluate( - this->Makefile, - config, - false, - headTarget, - this, &dagChecker), libs); + cmTarget::LinkImplementationLibraries const* impl + = this->GetLinkImplementationLibraries(config); + + for(std::vector<cmLinkImplItem>::const_iterator + it = impl->Libraries.begin(); + it != impl->Libraries.end(); ++it) + { + processILibs(config, this, *it, tgts , emitted); + } + } + return tgts; +} - for(std::vector<std::string>::const_iterator it = libs.begin(); - it != libs.end(); ++it) +//---------------------------------------------------------------------------- +cmTarget::CompatibleInterfaces const& +cmTarget::GetCompatibleInterfaces(std::string const& config) const +{ + cmTargetInternals::CompatibleInterfaces& compat = + this->Internal->CompatibleInterfacesMap[config]; + if(!compat.Done) { - if (cmTarget* tgt = headTarget->GetMakefile() - ->FindTargetToUse(*it)) + compat.Done = true; + compat.PropsBool.insert("POSITION_INDEPENDENT_CODE"); + compat.PropsString.insert("AUTOUIC_OPTIONS"); + std::vector<cmTarget const*> const& deps = + this->GetLinkImplementationClosure(config); + for(std::vector<cmTarget const*>::const_iterator li = deps.begin(); + li != deps.end(); ++li) { - tgts.push_back(tgt); +#define CM_READ_COMPATIBLE_INTERFACE(X, x) \ + if(const char* prop = (*li)->GetProperty("COMPATIBLE_INTERFACE_" #X)) \ + { \ + std::vector<std::string> props; \ + cmSystemTools::ExpandListArgument(prop, props); \ + std::copy(props.begin(), props.end(), \ + std::inserter(compat.Props##x, compat.Props##x.begin())); \ + } + CM_READ_COMPATIBLE_INTERFACE(BOOL, Bool) + CM_READ_COMPATIBLE_INTERFACE(STRING, String) + CM_READ_COMPATIBLE_INTERFACE(NUMBER_MIN, NumberMin) + CM_READ_COMPATIBLE_INTERFACE(NUMBER_MAX, NumberMax) +#undef CM_READ_COMPATIBLE_INTERFACE } } + return compat; } //---------------------------------------------------------------------------- -const char* cmTarget::ComputeLinkInterfaceLibraries(const std::string& config, - LinkInterface& iface, - cmTarget const* headTarget, - bool &exists) const +void +cmTargetInternals::ComputeLinkInterfaceLibraries( + cmTarget const* thisTarget, + const std::string& config, + OptionalLinkInterface& iface, + cmTarget const* headTarget, + bool usage_requirements_only) { // Construct the property name suffix for this configuration. std::string suffix = "_"; @@ -6258,15 +6000,15 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const std::string& config, // libraries and executables that export symbols. const char* explicitLibraries = 0; std::string linkIfaceProp; - if(this->PolicyStatusCMP0022 != cmPolicies::OLD && - this->PolicyStatusCMP0022 != cmPolicies::WARN) + if(thisTarget->PolicyStatusCMP0022 != cmPolicies::OLD && + thisTarget->PolicyStatusCMP0022 != cmPolicies::WARN) { // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES. linkIfaceProp = "INTERFACE_LINK_LIBRARIES"; - explicitLibraries = this->GetProperty(linkIfaceProp); + explicitLibraries = thisTarget->GetProperty(linkIfaceProp); } - else if(this->GetType() == cmTarget::SHARED_LIBRARY || - this->IsExecutableWithExports()) + else if(thisTarget->GetType() == cmTarget::SHARED_LIBRARY || + thisTarget->IsExecutableWithExports()) { // CMP0022 OLD behavior is to use LINK_INTERFACE_LIBRARIES if set on a // shared lib or executable. @@ -6274,31 +6016,32 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const std::string& config, // Lookup the per-configuration property. linkIfaceProp = "LINK_INTERFACE_LIBRARIES"; linkIfaceProp += suffix; - explicitLibraries = this->GetProperty(linkIfaceProp); + explicitLibraries = thisTarget->GetProperty(linkIfaceProp); // If not set, try the generic property. if(!explicitLibraries) { linkIfaceProp = "LINK_INTERFACE_LIBRARIES"; - explicitLibraries = this->GetProperty(linkIfaceProp); + explicitLibraries = thisTarget->GetProperty(linkIfaceProp); } } - if(explicitLibraries && this->PolicyStatusCMP0022 == cmPolicies::WARN && - !this->Internal->PolicyWarnedCMP0022) + if(explicitLibraries && + thisTarget->PolicyStatusCMP0022 == cmPolicies::WARN && + !this->PolicyWarnedCMP0022) { // Compare the explicitly set old link interface properties to the // preferred new link interface property one and warn if different. const char* newExplicitLibraries = - this->GetProperty("INTERFACE_LINK_LIBRARIES"); + thisTarget->GetProperty("INTERFACE_LINK_LIBRARIES"); if (newExplicitLibraries && strcmp(newExplicitLibraries, explicitLibraries) != 0) { cmOStringStream w; w << - (this->Makefile->GetPolicies() + (thisTarget->Makefile->GetPolicies() ->GetPolicyWarning(cmPolicies::CMP0022)) << "\n" - "Target \"" << this->GetName() << "\" has an " + "Target \"" << thisTarget->GetName() << "\" has an " "INTERFACE_LINK_LIBRARIES property which differs from its " << linkIfaceProp << " properties." "\n" @@ -6306,70 +6049,62 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const std::string& config, " " << newExplicitLibraries << "\n" << linkIfaceProp << ":\n" " " << (explicitLibraries ? explicitLibraries : "(empty)") << "\n"; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); - this->Internal->PolicyWarnedCMP0022 = true; + thisTarget->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->PolicyWarnedCMP0022 = true; } } // There is no implicit link interface for executables or modules // so if none was explicitly set then there is no link interface. if(!explicitLibraries && - (this->GetType() == cmTarget::EXECUTABLE || - (this->GetType() == cmTarget::MODULE_LIBRARY))) + (thisTarget->GetType() == cmTarget::EXECUTABLE || + (thisTarget->GetType() == cmTarget::MODULE_LIBRARY))) { - exists = false; - return 0; + return; } - exists = true; + iface.Exists = true; + iface.ExplicitLibraries = explicitLibraries; if(explicitLibraries) { // The interface libraries have been explicitly set. - cmGeneratorExpression ge; - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), - linkIfaceProp, 0, 0); - cmSystemTools::ExpandListArgument(ge.Parse(explicitLibraries)->Evaluate( - this->Makefile, - config, - false, - headTarget, - this, &dagChecker), iface.Libraries); - } - else if (this->PolicyStatusCMP0022 == cmPolicies::WARN - || this->PolicyStatusCMP0022 == cmPolicies::OLD) + thisTarget->ExpandLinkItems(linkIfaceProp, explicitLibraries, config, + headTarget, usage_requirements_only, + iface.Libraries, + iface.HadHeadSensitiveCondition); + } + else if (thisTarget->PolicyStatusCMP0022 == cmPolicies::WARN + || thisTarget->PolicyStatusCMP0022 == cmPolicies::OLD) // If CMP0022 is NEW then the plain tll signature sets the // INTERFACE_LINK_LIBRARIES, so if we get here then the project // cleared the property explicitly and we should not fall back // to the link implementation. { // The link implementation is the default link interface. - LinkImplementation const* impl = - this->GetLinkImplementationLibraries(config, headTarget); - iface.Libraries = impl->Libraries; - if(this->PolicyStatusCMP0022 == cmPolicies::WARN && - !this->Internal->PolicyWarnedCMP0022) + cmTarget::LinkImplementationLibraries const* impl = + thisTarget->GetLinkImplementationLibrariesInternal(config, headTarget); + std::copy(impl->Libraries.begin(), impl->Libraries.end(), + std::back_inserter(iface.Libraries)); + if(thisTarget->PolicyStatusCMP0022 == cmPolicies::WARN && + !this->PolicyWarnedCMP0022 && !usage_requirements_only) { // Compare the link implementation fallback link interface to the // preferred new link interface property and warn if different. - cmGeneratorExpression ge; - cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), - "INTERFACE_LINK_LIBRARIES", 0, 0); - std::vector<std::string> ifaceLibs; - const char* newExplicitLibraries = - this->GetProperty("INTERFACE_LINK_LIBRARIES"); - cmSystemTools::ExpandListArgument( - ge.Parse(newExplicitLibraries)->Evaluate(this->Makefile, - config, - false, - headTarget, - this, &dagChecker), - ifaceLibs); - if (ifaceLibs != impl->Libraries) + std::vector<cmLinkItem> ifaceLibs; + static const std::string newProp = "INTERFACE_LINK_LIBRARIES"; + if(const char* newExplicitLibraries = thisTarget->GetProperty(newProp)) + { + bool hadHeadSensitiveConditionDummy = false; + thisTarget->ExpandLinkItems(newProp, newExplicitLibraries, config, + headTarget, usage_requirements_only, + ifaceLibs, hadHeadSensitiveConditionDummy); + } + if (ifaceLibs != iface.Libraries) { std::string oldLibraries; std::string newLibraries; const char *sep = ""; - for(std::vector<std::string>::const_iterator it + for(std::vector<cmLinkImplItem>::const_iterator it = impl->Libraries.begin(); it != impl->Libraries.end(); ++it) { oldLibraries += sep; @@ -6377,7 +6112,7 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const std::string& config, sep = ";"; } sep = ""; - for(std::vector<std::string>::const_iterator it + for(std::vector<cmLinkItem>::const_iterator it = ifaceLibs.begin(); it != ifaceLibs.end(); ++it) { newLibraries += sep; @@ -6391,9 +6126,9 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const std::string& config, cmOStringStream w; w << - (this->Makefile->GetPolicies() + (thisTarget->Makefile->GetPolicies() ->GetPolicyWarning(cmPolicies::CMP0022)) << "\n" - "Target \"" << this->GetName() << "\" has an " + "Target \"" << thisTarget->GetName() << "\" has an " "INTERFACE_LINK_LIBRARIES property. " "This should be preferred as the source of the link interface " "for this library but because CMP0022 is not set CMake is " @@ -6404,22 +6139,20 @@ const char* cmTarget::ComputeLinkInterfaceLibraries(const std::string& config, " " << newLibraries << "\n" "Link implementation:\n" " " << oldLibraries << "\n"; - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); - this->Internal->PolicyWarnedCMP0022 = true; + thisTarget->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->PolicyWarnedCMP0022 = true; } } } - return explicitLibraries; } //---------------------------------------------------------------------------- void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget, const std::string& config, OptionalLinkInterface& iface, - cmTarget const* headTarget, - const char* explicitLibraries) const + cmTarget const* headTarget) const { - if(explicitLibraries) + if(iface.ExplicitLibraries) { if(thisTarget->GetType() == cmTarget::SHARED_LIBRARY || thisTarget->GetType() == cmTarget::STATIC_LIBRARY @@ -6427,8 +6160,8 @@ void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget, { // Shared libraries may have runtime implementation dependencies // on other shared libraries that are not in the interface. - std::set<std::string> emitted; - for(std::vector<std::string>::const_iterator + UNORDERED_SET<std::string> emitted; + for(std::vector<cmLinkItem>::const_iterator li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li) { emitted.insert(*li); @@ -6436,16 +6169,16 @@ void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget, if (thisTarget->GetType() != cmTarget::INTERFACE_LIBRARY) { cmTarget::LinkImplementation const* impl = - thisTarget->GetLinkImplementation(config, headTarget); - for(std::vector<std::string>::const_iterator + thisTarget->GetLinkImplementation(config); + for(std::vector<cmLinkImplItem>::const_iterator li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) { if(emitted.insert(*li).second) { - if(cmTarget* tgt = thisTarget->Makefile->FindTargetToUse(*li)) + if(li->Target) { // This is a runtime dependency on another shared library. - if(tgt->GetType() == cmTarget::SHARED_LIBRARY) + if(li->Target->GetType() == cmTarget::SHARED_LIBRARY) { iface.SharedDeps.push_back(*li); } @@ -6466,8 +6199,9 @@ void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget, || thisTarget->PolicyStatusCMP0022 == cmPolicies::OLD) { // The link implementation is the default link interface. - cmTarget::LinkImplementation const* - impl = thisTarget->GetLinkImplementation(config, headTarget); + cmTarget::LinkImplementationLibraries const* + impl = thisTarget->GetLinkImplementationLibrariesInternal(config, + headTarget); iface.ImplementationIsInterface = true; iface.WrongConfigLibraries = impl->WrongConfigLibraries; } @@ -6476,7 +6210,7 @@ void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget, { // Targets using this archive need its language runtime libraries. if(cmTarget::LinkImplementation const* impl = - thisTarget->GetLinkImplementation(config, headTarget)) + thisTarget->GetLinkImplementation(config)) { iface.Languages = impl->Languages; } @@ -6509,13 +6243,37 @@ void cmTargetInternals::ComputeLinkInterface(cmTarget const* thisTarget, sscanf(reps, "%u", &iface.Multiplicity); } } - iface.Complete = true; +} + +//---------------------------------------------------------------------------- +void cmTargetInternals::AddInterfaceEntries( + cmTarget const* thisTarget, std::string const& config, + std::string const& prop, std::vector<TargetPropertyEntry*>& entries) +{ + if(cmTarget::LinkImplementationLibraries const* impl = + thisTarget->GetLinkImplementationLibraries(config)) + { + for (std::vector<cmLinkImplItem>::const_iterator + it = impl->Libraries.begin(), end = impl->Libraries.end(); + it != end; ++it) + { + if(it->Target) + { + std::string genex = + "$<TARGET_PROPERTY:" + *it + "," + prop + ">"; + cmGeneratorExpression ge(&it->Backtrace); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex); + cge->SetEvaluateForBuildsystem(true); + entries.push_back( + new cmTargetInternals::TargetPropertyEntry(cge, *it)); + } + } + } } //---------------------------------------------------------------------------- cmTarget::LinkImplementation const* -cmTarget::GetLinkImplementation(const std::string& config, - cmTarget const* head) const +cmTarget::GetLinkImplementation(const std::string& config) const { // There is no link implementation for imported targets. if(this->IsImported()) @@ -6523,34 +6281,35 @@ cmTarget::GetLinkImplementation(const std::string& config, return 0; } - // Lookup any existing link implementation for this configuration. - TargetConfigPair key(head, cmSystemTools::UpperCase(config)); - - cmTargetInternals::LinkImplMapType::iterator - i = this->Internal->LinkImplMap.find(key); - if(i == this->Internal->LinkImplMap.end()) + // Populate the link implementation for this configuration. + std::string CONFIG = cmSystemTools::UpperCase(config); + cmTargetInternals::OptionalLinkImplementation& + impl = this->Internal->LinkImplMap[CONFIG][this]; + if(!impl.LibrariesDone) { - // Compute the link implementation for this configuration. - LinkImplementation impl; - this->ComputeLinkImplementation(config, impl, head); - this->ComputeLinkImplementationLanguages(config, impl, head); - - // Store the information for this configuration. - cmTargetInternals::LinkImplMapType::value_type entry(key, impl); - i = this->Internal->LinkImplMap.insert(entry).first; + impl.LibrariesDone = true; + this->Internal + ->ComputeLinkImplementationLibraries(this, config, impl, this); } - else if (i->second.Languages.empty()) + if(!impl.LanguagesDone) { - this->ComputeLinkImplementationLanguages(config, i->second, head); + impl.LanguagesDone = true; + this->Internal->ComputeLinkImplementationLanguages(this, config, impl); } + return &impl; +} - return &i->second; +//---------------------------------------------------------------------------- +cmTarget::LinkImplementationLibraries const* +cmTarget::GetLinkImplementationLibraries(const std::string& config) const +{ + return this->GetLinkImplementationLibrariesInternal(config, this); } //---------------------------------------------------------------------------- -cmTarget::LinkImplementation const* -cmTarget::GetLinkImplementationLibraries(const std::string& config, - cmTarget const* head) const +cmTarget::LinkImplementationLibraries const* +cmTarget::GetLinkImplementationLibrariesInternal(const std::string& config, + cmTarget const* head) const { // There is no link implementation for imported targets. if(this->IsImported()) @@ -6558,110 +6317,150 @@ cmTarget::GetLinkImplementationLibraries(const std::string& config, return 0; } - // Lookup any existing link implementation for this configuration. - TargetConfigPair key(head, cmSystemTools::UpperCase(config)); + // Populate the link implementation libraries for this configuration. + std::string CONFIG = cmSystemTools::UpperCase(config); + cmTargetInternals::HeadToLinkImplementationMap& hm = + this->Internal->LinkImplMap[CONFIG]; - cmTargetInternals::LinkImplMapType::iterator - i = this->Internal->LinkImplMap.find(key); - if(i == this->Internal->LinkImplMap.end()) + // If the link implementation does not depend on the head target + // then return the one we computed first. + if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) { - // Compute the link implementation for this configuration. - LinkImplementation impl; - this->ComputeLinkImplementation(config, impl, head); - - // Store the information for this configuration. - cmTargetInternals::LinkImplMapType::value_type entry(key, impl); - i = this->Internal->LinkImplMap.insert(entry).first; + return &hm.begin()->second; } - return &i->second; + cmTargetInternals::OptionalLinkImplementation& impl = hm[head]; + if(!impl.LibrariesDone) + { + impl.LibrariesDone = true; + this->Internal + ->ComputeLinkImplementationLibraries(this, config, impl, head); + } + return &impl; } //---------------------------------------------------------------------------- -void cmTarget::ComputeLinkImplementation(const std::string& config, - LinkImplementation& impl, - cmTarget const* head) const +void +cmTargetInternals::ComputeLinkImplementationLibraries( + cmTarget const* thisTarget, + const std::string& config, + OptionalLinkImplementation& impl, + cmTarget const* head) const { // Collect libraries directly linked in this configuration. - std::vector<std::string> llibs; - this->GetDirectLinkLibraries(config, llibs, head); - for(std::vector<std::string>::const_iterator li = llibs.begin(); - li != llibs.end(); ++li) + for (std::vector<cmValueWithOrigin>::const_iterator + le = this->LinkImplementationPropertyEntries.begin(), + end = this->LinkImplementationPropertyEntries.end(); + le != end; ++le) { - // Skip entries that resolve to the target itself or are empty. - std::string item = this->CheckCMP0004(*li); - if(item == this->GetName() || item.empty()) + std::vector<std::string> llibs; + cmGeneratorExpressionDAGChecker dagChecker( + thisTarget->GetName(), + "LINK_LIBRARIES", 0, 0); + cmGeneratorExpression ge(&le->Backtrace); + cmsys::auto_ptr<cmCompiledGeneratorExpression> const cge = + ge.Parse(le->Value); + std::string const evaluated = + cge->Evaluate(thisTarget->Makefile, config, false, head, &dagChecker); + cmSystemTools::ExpandListArgument(evaluated, llibs); + if(cge->GetHadHeadSensitiveCondition()) + { + impl.HadHeadSensitiveCondition = true; + } + + for(std::vector<std::string>::const_iterator li = llibs.begin(); + li != llibs.end(); ++li) { - if(item == this->GetName()) + // Skip entries that resolve to the target itself or are empty. + std::string name = thisTarget->CheckCMP0004(*li); + if(name == thisTarget->GetName() || name.empty()) { - bool noMessage = false; - cmake::MessageType messageType = cmake::FATAL_ERROR; - cmOStringStream e; - switch(this->GetPolicyStatusCMP0038()) + if(name == thisTarget->GetName()) { - case cmPolicies::WARN: + bool noMessage = false; + cmake::MessageType messageType = cmake::FATAL_ERROR; + cmOStringStream e; + switch(thisTarget->GetPolicyStatusCMP0038()) { - e << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0038)) << "\n"; - messageType = cmake::AUTHOR_WARNING; + case cmPolicies::WARN: + { + e << (thisTarget->Makefile->GetPolicies() + ->GetPolicyWarning(cmPolicies::CMP0038)) << "\n"; + messageType = cmake::AUTHOR_WARNING; + } + break; + case cmPolicies::OLD: + noMessage = true; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Issue the fatal message. + break; } - break; - case cmPolicies::OLD: - noMessage = true; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - // Issue the fatal message. - break; - } - if(!noMessage) - { - e << "Target \"" << this->GetName() << "\" links to itself."; - this->Makefile->GetCMakeInstance()->IssueMessage(messageType, - e.str(), - this->GetBacktrace()); - if (messageType == cmake::FATAL_ERROR) + if(!noMessage) { - return; + e << "Target \"" << thisTarget->GetName() << "\" links to itself."; + thisTarget->Makefile->GetCMakeInstance()->IssueMessage( + messageType, e.str(), thisTarget->GetBacktrace()); + if (messageType == cmake::FATAL_ERROR) + { + return; + } } } + continue; } - continue; + + // The entry is meant for this configuration. + impl.Libraries.push_back( + cmLinkImplItem(name, thisTarget->FindTargetToLink(name), + le->Backtrace, evaluated != le->Value)); } - // The entry is meant for this configuration. - impl.Libraries.push_back(item); + std::set<std::string> const& seenProps = cge->GetSeenTargetProperties(); + for (std::set<std::string>::const_iterator it = seenProps.begin(); + it != seenProps.end(); ++it) + { + if (!thisTarget->GetProperty(*it)) + { + thisTarget->LinkImplicitNullProperties.insert(*it); + } + } + cge->GetMaxLanguageStandard(thisTarget, thisTarget->MaxLanguageStandards); } - cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config); - LinkLibraryVectorType const& oldllibs = this->GetOriginalLinkLibraries(); + cmTarget::LinkLibraryType linkType = thisTarget->ComputeLinkType(config); + cmTarget::LinkLibraryVectorType const& oldllibs = + thisTarget->GetOriginalLinkLibraries(); for(cmTarget::LinkLibraryVectorType::const_iterator li = oldllibs.begin(); li != oldllibs.end(); ++li) { if(li->second != cmTarget::GENERAL && li->second != linkType) { - std::string item = this->CheckCMP0004(li->first); - if(item == this->GetName() || item.empty()) + std::string name = thisTarget->CheckCMP0004(li->first); + if(name == thisTarget->GetName() || name.empty()) { continue; } // Support OLD behavior for CMP0003. - impl.WrongConfigLibraries.push_back(item); + impl.WrongConfigLibraries.push_back( + cmLinkItem(name, thisTarget->FindTargetToLink(name))); } } } //---------------------------------------------------------------------------- void -cmTarget::ComputeLinkImplementationLanguages(const std::string& config, - LinkImplementation& impl, - cmTarget const* head) const +cmTargetInternals::ComputeLinkImplementationLanguages( + cmTarget const* thisTarget, + const std::string& config, + OptionalLinkImplementation& impl) const { // This target needs runtime libraries for its source languages. std::set<std::string> languages; // Get languages used in our source files. - this->GetLanguages(languages, config, head); + thisTarget->GetLanguages(languages, config); // Copy the set of langauges to the link implementation. for(std::set<std::string>::iterator li = languages.begin(); li != languages.end(); ++li) @@ -6671,6 +6470,37 @@ cmTarget::ComputeLinkImplementationLanguages(const std::string& config, } //---------------------------------------------------------------------------- +cmTarget const* cmTarget::FindTargetToLink(std::string const& name) const +{ + cmTarget const* tgt = this->Makefile->FindTargetToUse(name); + + // Skip targets that will not really be linked. This is probably a + // name conflict between an external library and an executable + // within the project. + if(tgt && tgt->GetType() == cmTarget::EXECUTABLE && + !tgt->IsExecutableWithExports()) + { + tgt = 0; + } + + if(tgt && tgt->GetType() == cmTarget::OBJECT_LIBRARY) + { + cmOStringStream e; + e << "Target \"" << this->GetName() << "\" links to " + "OBJECT library \"" << tgt->GetName() << "\" but this is not " + "allowed. " + "One may link only to STATIC or SHARED libraries, or to executables " + "with the ENABLE_EXPORTS property set."; + cmake* cm = this->Makefile->GetCMakeInstance(); + cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace()); + tgt = 0; + } + + // Return the target found, if any. + return tgt; +} + +//---------------------------------------------------------------------------- std::string cmTarget::CheckCMP0004(std::string const& item) const { // Strip whitespace off the library names because we used to do this @@ -6868,9 +6698,13 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); std::set<std::string> emittedBools; + static std::string strBool = "COMPATIBLE_INTERFACE_BOOL"; std::set<std::string> emittedStrings; + static std::string strString = "COMPATIBLE_INTERFACE_STRING"; std::set<std::string> emittedMinNumbers; + static std::string strNumMin = "COMPATIBLE_INTERFACE_NUMBER_MIN"; std::set<std::string> emittedMaxNumbers; + static std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX"; for(cmComputeLinkInformation::ItemVector::const_iterator li = deps.begin(); @@ -6882,14 +6716,14 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, } checkPropertyConsistency<bool>(this, li->Target, - std::string("COMPATIBLE_INTERFACE_BOOL"), + strBool, emittedBools, config, BoolType, 0); if (cmSystemTools::GetErrorOccuredFlag()) { return; } checkPropertyConsistency<const char *>(this, li->Target, - std::string("COMPATIBLE_INTERFACE_STRING"), + strString, emittedStrings, config, StringType, 0); if (cmSystemTools::GetErrorOccuredFlag()) @@ -6897,7 +6731,7 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, return; } checkPropertyConsistency<const char *>(this, li->Target, - std::string("COMPATIBLE_INTERFACE_NUMBER_MIN"), + strNumMin, emittedMinNumbers, config, NumberMinType, 0); if (cmSystemTools::GetErrorOccuredFlag()) @@ -6905,7 +6739,7 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, return; } checkPropertyConsistency<const char *>(this, li->Target, - std::string("COMPATIBLE_INTERFACE_NUMBER_MAX"), + strNumMax, emittedMaxNumbers, config, NumberMaxType, 0); if (cmSystemTools::GetErrorOccuredFlag()) @@ -6921,26 +6755,27 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, if (!prop.empty()) { + // Use a std::set to keep the error message sorted. std::set<std::string> props; std::set<std::string>::const_iterator i = emittedBools.find(prop); if (i != emittedBools.end()) { - props.insert("COMPATIBLE_INTERFACE_BOOL"); + props.insert(strBool); } i = emittedStrings.find(prop); if (i != emittedStrings.end()) { - props.insert("COMPATIBLE_INTERFACE_STRING"); + props.insert(strString); } i = emittedMinNumbers.find(prop); if (i != emittedMinNumbers.end()) { - props.insert("COMPATIBLE_INTERFACE_NUMBER_MIN"); + props.insert(strNumMin); } i = emittedMaxNumbers.find(prop); if (i != emittedMaxNumbers.end()) { - props.insert("COMPATIBLE_INTERFACE_NUMBER_MAX"); + props.insert(strNumMax); } std::string propsString = *props.begin(); @@ -6967,19 +6802,17 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, //---------------------------------------------------------------------------- cmComputeLinkInformation* -cmTarget::GetLinkInformation(const std::string& config, - cmTarget const* head) const +cmTarget::GetLinkInformation(const std::string& config) const { - cmTarget const* headTarget = head ? head : this; // Lookup any existing information for this configuration. - TargetConfigPair key(headTarget, cmSystemTools::UpperCase(config)); + std::string key(cmSystemTools::UpperCase(config)); cmTargetLinkInformationMap::iterator i = this->LinkInformation.find(key); if(i == this->LinkInformation.end()) { // Compute information for this configuration. cmComputeLinkInformation* info = - new cmComputeLinkInformation(this, config, headTarget); + new cmComputeLinkInformation(this, config); if(!info || !info->Compute()) { delete info; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 2d51835..a3ecca0 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -18,6 +18,9 @@ #include "cmListFileCache.h" #include <cmsys/auto_ptr.hxx> +#if defined(CMAKE_BUILD_WITH_CMAKE) +#include <cmsys/hash_map.hxx> +#endif #define CM_FOR_EACH_TARGET_POLICY(F) \ F(CMP0003) \ @@ -43,12 +46,36 @@ class cmTarget; class cmGeneratorTarget; class cmTargetTraceDependencies; +// Basic information about each link item. +class cmLinkItem: public std::string +{ + typedef std::string std_string; +public: + cmLinkItem(): std_string(), Target(0) {} + cmLinkItem(const std_string& n, + cmTarget const* t): std_string(n), Target(t) {} + cmLinkItem(cmLinkItem const& r): std_string(r), Target(r.Target) {} + cmTarget const* Target; +}; +class cmLinkImplItem: public cmLinkItem +{ +public: + cmLinkImplItem(): cmLinkItem(), Backtrace(0), FromGenex(false) {} + cmLinkImplItem(std::string const& n, + cmTarget const* t, + cmListFileBacktrace const& bt, + bool fromGenex): + cmLinkItem(n, t), Backtrace(bt), FromGenex(fromGenex) {} + cmLinkImplItem(cmLinkImplItem const& r): + cmLinkItem(r), Backtrace(r.Backtrace), FromGenex(r.FromGenex) {} + cmListFileBacktrace Backtrace; + bool FromGenex; +}; + struct cmTargetLinkInformationMap: - public std::map<std::pair<cmTarget const* , std::string>, - cmComputeLinkInformation*> + public std::map<std::string, cmComputeLinkInformation*> { - typedef std::map<std::pair<cmTarget const* , std::string>, - cmComputeLinkInformation*> derived; + typedef std::map<std::string, cmComputeLinkInformation*> derived; cmTargetLinkInformationMap() {} cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r); ~cmTargetLinkInformationMap(); @@ -137,8 +164,7 @@ public: * Get the list of the source files used by this target */ void GetSourceFiles(std::vector<cmSourceFile*> &files, - const std::string& config, - cmTarget const* head = 0) const; + const std::string& config) const; bool GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const; /** @@ -155,16 +181,8 @@ public: typedef std::pair<std::string, LinkLibraryType> LibraryID; typedef std::vector<LibraryID > LinkLibraryVectorType; - const LinkLibraryVectorType &GetLinkLibraries() const { - return this->LinkLibraries;} const LinkLibraryVectorType &GetOriginalLinkLibraries() const {return this->OriginalLinkLibraries;} - void GetDirectLinkLibraries(const std::string& config, - std::vector<std::string> &, - cmTarget const* head) const; - void GetInterfaceLinkLibraries(const std::string& config, - std::vector<std::string> &, - cmTarget const* head) const; /** Compute the link type to use for the given configuration. */ LinkLibraryType ComputeLinkType(const std::string& config) const; @@ -221,6 +239,7 @@ public: void AddUtility(const std::string& u, cmMakefile *makefile = 0); ///! Get the utilities used by this target std::set<std::string>const& GetUtilities() const { return this->Utilities; } + std::set<cmLinkItem>const& GetUtilityItems() const; cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const; /** Finalize the target at the end of the Configure step. */ @@ -246,16 +265,18 @@ public: /** The link interface specifies transitive library dependencies and other information needed by targets that link to this target. */ - struct LinkInterface + struct LinkInterfaceLibraries + { + // Libraries listed in the interface. + std::vector<cmLinkItem> Libraries; + }; + struct LinkInterface: public LinkInterfaceLibraries { // Languages whose runtime libraries must be linked. std::vector<std::string> Languages; - // Libraries listed in the interface. - std::vector<std::string> Libraries; - // Shared library dependencies needed for linking on some platforms. - std::vector<std::string> SharedDeps; + std::vector<cmLinkItem> SharedDeps; // Number of repetitions of a strongly connected component of two // or more static libraries. @@ -263,7 +284,7 @@ public: // Libraries listed for other configurations. // Needed only for OLD behavior of CMP0003. - std::vector<std::string> WrongConfigLibraries; + std::vector<cmLinkItem> WrongConfigLibraries; bool ImplementationIsInterface; @@ -274,35 +295,45 @@ public: if the target cannot be linked. */ LinkInterface const* GetLinkInterface(const std::string& config, cmTarget const* headTarget) const; - LinkInterface const* GetLinkInterfaceLibraries(const std::string& config, - cmTarget const* headTarget) const; - void GetTransitivePropertyTargets(const std::string& config, - cmTarget const* headTarget, - std::vector<cmTarget*> &libs) const; - void GetTransitiveTargetClosure(const std::string& config, - cmTarget const* headTarget, - std::vector<cmTarget*> &libs) const; + LinkInterfaceLibraries const* + GetLinkInterfaceLibraries(const std::string& config, + cmTarget const* headTarget, + bool usage_requirements_only) const; + + std::vector<cmTarget const*> const& + GetLinkImplementationClosure(const std::string& config) const; + + struct CompatibleInterfaces + { + std::set<std::string> PropsBool; + std::set<std::string> PropsString; + std::set<std::string> PropsNumberMax; + std::set<std::string> PropsNumberMin; + }; + CompatibleInterfaces const& + GetCompatibleInterfaces(std::string const& config) const; /** The link implementation specifies the direct library dependencies needed by the object files of the target. */ - struct LinkImplementation + struct LinkImplementationLibraries { - // Languages whose runtime libraries must be linked. - std::vector<std::string> Languages; - // Libraries linked directly in this configuration. - std::vector<std::string> Libraries; + std::vector<cmLinkImplItem> Libraries; // Libraries linked directly in other configurations. // Needed only for OLD behavior of CMP0003. - std::vector<std::string> WrongConfigLibraries; + std::vector<cmLinkItem> WrongConfigLibraries; + }; + struct LinkImplementation: public LinkImplementationLibraries + { + // Languages whose runtime libraries must be linked. + std::vector<std::string> Languages; }; - LinkImplementation const* GetLinkImplementation(const std::string& config, - cmTarget const* head) const; + LinkImplementation const* + GetLinkImplementation(const std::string& config) const; - LinkImplementation const* GetLinkImplementationLibraries( - const std::string& config, - cmTarget const* head) const; + LinkImplementationLibraries const* + GetLinkImplementationLibraries(const std::string& config) const; /** Link information from the transitive closure of the link implementation and the interfaces of its dependencies. */ @@ -314,8 +345,9 @@ public: // Languages whose runtime libraries must be linked. std::vector<std::string> Languages; }; - LinkClosure const* GetLinkClosure(const std::string& config, - cmTarget const* head) const; + LinkClosure const* GetLinkClosure(const std::string& config) const; + + cmTarget const* FindTargetToLink(std::string const& name) const; /** Strip off leading and trailing whitespace from an item named in the link dependencies of this target. */ @@ -361,8 +393,7 @@ public: GetTargetVersion(bool soversion, int& major, int& minor, int& patch) const; ///! Return the preferred linker language for this target - std::string GetLinkerLanguage(const std::string& config = "", - cmTarget const* head = 0) const; + std::string GetLinkerLanguage(const std::string& config = "") const; /** Get the full name of the target according to the settings in its makefile. */ @@ -446,8 +477,8 @@ public: * install tree. For example: "\@rpath/" or "\@loader_path/". */ std::string GetInstallNameDirForInstallTree() const; - cmComputeLinkInformation* GetLinkInformation(const std::string& config, - cmTarget const* head = 0) const; + cmComputeLinkInformation* + GetLinkInformation(const std::string& config) const; // Get the properties cmPropertyMap &GetProperties() const { return this->Properties; } @@ -473,8 +504,7 @@ public: // information to forward these property changes to the targets // until we have per-target object file properties. void GetLanguages(std::set<std::string>& languages, - std::string const& config, - cmTarget const* head = 0) const; + std::string const& config) const; /** Return whether this target is an executable with symbol exports enabled. */ @@ -595,6 +625,11 @@ public: return this->MaxLanguageStandards; } +#if defined(_WIN32) && !defined(__CYGWIN__) + const LinkLibraryVectorType &GetLinkLibrariesForVS6() const { + return this->LinkLibrariesForVS6;} +#endif + private: bool HandleLocationPropertyPolicy(cmMakefile* context) const; @@ -604,6 +639,7 @@ private: std::vector<std::pair<TLLSignature, cmListFileBacktrace> > TLLCommands; +#if defined(_WIN32) && !defined(__CYGWIN__) /** * A list of direct dependencies. Use in conjunction with DependencyMap. */ @@ -620,16 +656,16 @@ private: /** * Inserts \a dep at the end of the dependency list of \a lib. */ - void InsertDependency( DependencyMap& depMap, - const LibraryID& lib, - const LibraryID& dep); + void InsertDependencyForVS6( DependencyMap& depMap, + const LibraryID& lib, + const LibraryID& dep); /* * Deletes \a dep from the dependency list of \a lib. */ - void DeleteDependency( DependencyMap& depMap, - const LibraryID& lib, - const LibraryID& dep); + void DeleteDependencyForVS6( DependencyMap& depMap, + const LibraryID& lib, + const LibraryID& dep); /** * Emits the library \a lib and all its dependencies into link_line. @@ -639,21 +675,22 @@ private: * link_line is in reverse order, in that the dependencies of a * library are listed before the library itself. */ - void Emit( const LibraryID lib, - const DependencyMap& dep_map, - std::set<LibraryID>& emitted, - std::set<LibraryID>& visited, - DependencyList& link_line); + void EmitForVS6( const LibraryID lib, + const DependencyMap& dep_map, + std::set<LibraryID>& emitted, + std::set<LibraryID>& visited, + DependencyList& link_line); /** * Finds the dependencies for \a lib and inserts them into \a * dep_map. */ - void GatherDependencies( const cmMakefile& mf, - const LibraryID& lib, - DependencyMap& dep_map); + void GatherDependenciesForVS6( const cmMakefile& mf, + const LibraryID& lib, + DependencyMap& dep_map); - void AnalyzeLibDependencies( const cmMakefile& mf ); + void AnalyzeLibDependenciesForVS6( const cmMakefile& mf ); +#endif const char* GetSuffixVariableInternal(bool implib) const; const char* GetPrefixVariableInternal(bool implib) const; @@ -694,17 +731,18 @@ private: bool contentOnly) const; void GetSourceFiles(std::vector<std::string> &files, - const std::string& config, - cmTarget const* head = 0) const; + const std::string& config) const; private: std::string Name; std::vector<cmCustomCommand> PreBuildCommands; std::vector<cmCustomCommand> PreLinkCommands; std::vector<cmCustomCommand> PostBuildCommands; TargetType TargetTypeValue; - LinkLibraryVectorType LinkLibraries; LinkLibraryVectorType PrevLinkedLibraries; - bool LinkLibrariesAnalyzed; +#if defined(_WIN32) && !defined(__CYGWIN__) + LinkLibraryVectorType LinkLibrariesForVS6; + bool LinkLibrariesForVS6Analyzed; +#endif std::vector<std::string> LinkDirectories; std::set<std::string> LinkDirectoriesEmmitted; bool HaveInstallRule; @@ -717,6 +755,7 @@ private: mutable cmPropertyMap Properties; LinkLibraryVectorType OriginalLinkLibraries; bool DLLPlatform; + bool IsAndroid; bool IsApple; bool IsImportedTarget; mutable bool DebugIncludesDone; @@ -740,10 +779,9 @@ private: // Cache import information from properties for each configuration. struct ImportInfo; - ImportInfo const* GetImportInfo(const std::string& config, - cmTarget const* workingTarget) const; - void ComputeImportInfo(std::string const& desired_config, ImportInfo& info, - cmTarget const* head) const; + ImportInfo const* GetImportInfo(const std::string& config) const; + void ComputeImportInfo(std::string const& desired_config, + ImportInfo& info) const; // Cache target compile paths for each configuration. struct CompileInfo; @@ -753,19 +791,22 @@ private: void CheckPropertyCompatibility(cmComputeLinkInformation *info, const std::string& config) const; - const char* ComputeLinkInterfaceLibraries(const std::string& config, - LinkInterface& iface, - cmTarget const* head, - bool &exists) const; + LinkInterface const* + GetImportLinkInterface(const std::string& config, cmTarget const* head, + bool usage_requirements_only) const; - void ComputeLinkImplementation(const std::string& config, - LinkImplementation& impl, - cmTarget const* head) const; - void ComputeLinkImplementationLanguages(const std::string& config, - LinkImplementation& impl, - cmTarget const* head) const; - void ComputeLinkClosure(const std::string& config, LinkClosure& lc, - cmTarget const* head) const; + LinkImplementationLibraries const* + GetLinkImplementationLibrariesInternal(const std::string& config, + cmTarget const* head) const; + void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const; + + void ExpandLinkItems(std::string const& prop, std::string const& value, + std::string const& config, cmTarget const* headTarget, + bool usage_requirements_only, + std::vector<cmLinkItem>& items, + bool& hadHeadSensitiveCondition) const; + void LookupLinkItems(std::vector<std::string> const& names, + std::vector<cmLinkItem>& items) const; std::string ProcessSourceItemCMP0049(const std::string& s); @@ -803,7 +844,11 @@ private: mutable bool LinkImplementationLanguageIsContextDependent; }; +#ifdef CMAKE_BUILD_WITH_CMAKE +typedef cmsys::hash_map<std::string,cmTarget> cmTargets; +#else typedef std::map<std::string,cmTarget> cmTargets; +#endif class cmTargetSet: public std::set<std::string> {}; class cmTargetManifest: public std::map<std::string, cmTargetSet> {}; diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index ac26503..6fd6ab7 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -33,15 +33,13 @@ std::string cmTimestamp::CurrentTime( std::string cmTimestamp::FileModificationTime(const char* path, const std::string& formatString, bool utcFlag) { - struct stat info; - memset(&info, 0, sizeof(info)); - - if(stat(path, &info) != 0) + if(!cmsys::SystemTools::FileExists(path)) { return std::string(); } - return CreateTimestampFromTimeT(info.st_mtime, formatString, utcFlag); + time_t mtime = cmsys::SystemTools::ModifiedTime(path); + return CreateTimestampFromTimeT(mtime, formatString, utcFlag); } //---------------------------------------------------------------------------- diff --git a/Source/cmUuid.cxx b/Source/cmUuid.cxx new file mode 100644 index 0000000..8b5b7ae --- /dev/null +++ b/Source/cmUuid.cxx @@ -0,0 +1,214 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 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 "cmUuid.h" + +#include <string.h> + +#include <cmsys/MD5.h> +#include "cm_sha2.h" + +cmUuid::cmUuid() +{ + Groups.push_back(4); + Groups.push_back(2); + Groups.push_back(2); + Groups.push_back(2); + Groups.push_back(6); +} + +std::string cmUuid::FromMd5(std::vector<unsigned char> const& uuidNamespace, + std::string const& name) const +{ + std::vector<unsigned char> hashInput; + this->CreateHashInput(uuidNamespace, name, hashInput); + + cmsysMD5_s *md5 = cmsysMD5_New(); + cmsysMD5_Initialize(md5); + cmsysMD5_Append(md5, &hashInput[0], int(hashInput.size())); + + unsigned char digest[16] = {0}; + cmsysMD5_Finalize(md5, digest); + + cmsysMD5_Delete(md5); + + return this->FromDigest(digest, 3); +} + +std::string cmUuid::FromSha1(std::vector<unsigned char> const& uuidNamespace, + std::string const& name) const +{ + std::vector<unsigned char> hashInput; + this->CreateHashInput(uuidNamespace, name, hashInput); + + SHA_CTX *sha = new SHA_CTX; + SHA1_Init(sha); + SHA1_Update(sha, &hashInput[0], hashInput.size()); + + unsigned char digest[SHA1_DIGEST_LENGTH] = {0}; + SHA1_Final(digest, sha); + + delete sha; + + return this->FromDigest(digest, 5); +} + +void cmUuid::CreateHashInput(std::vector<unsigned char> const& uuidNamespace, + std::string const& name, std::vector<unsigned char> &output) const +{ + output = uuidNamespace; + + if(name.size()) + { + output.resize(output.size() + name.size()); + + memcpy(&output[0] + uuidNamespace.size(), + name.c_str(), name.size()); + } +} + +std::string cmUuid::FromDigest( + const unsigned char* digest, unsigned char version) const +{ + typedef unsigned char byte_t; + + byte_t uuid[16] = {0}; + memcpy(uuid, digest, 16); + + uuid[6] &= 0xF; + uuid[6] |= byte_t(version << 4); + + uuid[8] &= 0x3F; + uuid[8] |= 0x80; + + return this->BinaryToString(uuid); +} + +bool cmUuid::StringToBinary(std::string const& input, + std::vector<unsigned char> &output) const +{ + output.clear(); + output.reserve(16); + + if(input.length() != 36) + { + return false; + } + size_t index = 0; + for(size_t i = 0; i < this->Groups.size(); ++i) + { + if(i != 0 && input[index++] != '-') + { + return false; + } + size_t digits = this->Groups[i] * 2; + if(!StringToBinaryImpl(input.substr(index, digits), output)) + { + return false; + } + + index += digits; + } + + return true; +} + +std::string cmUuid::BinaryToString(const unsigned char* input) const +{ + std::string output; + + size_t inputIndex = 0; + for(size_t i = 0; i < this->Groups.size(); ++i) + { + if(i != 0) + { + output += '-'; + } + + size_t bytes = this->Groups[i]; + for(size_t j = 0; j < bytes; ++j) + { + unsigned char byte = input[inputIndex++]; + output += this->ByteToHex(byte); + } + } + + return output; +} + +std::string cmUuid::ByteToHex(unsigned char byte) const +{ + std::string result; + for(int i = 0; i < 2; ++i) + { + unsigned char rest = byte % 16; + byte /= 16; + + char c = (rest < 0xA) ? + char('0' + rest) : + char('a' + (rest - 0xA)); + + result = c + result; + } + + return result; +} + +bool cmUuid::StringToBinaryImpl(std::string const& input, + std::vector<unsigned char> &output) const +{ + if(input.size()%2) + { + return false; + } + + for(size_t i = 0; i < input.size(); i +=2) + { + char c1 = 0; + if(!IntFromHexDigit(input[i], c1)) + { + return false; + } + + char c2 = 0; + if(!IntFromHexDigit(input[i + 1], c2)) + { + return false; + } + + output.push_back(char(c1 << 4 | c2)); + } + + return true; +} + +bool cmUuid::IntFromHexDigit(char input, char& output) const +{ + if(input >= '0' && input <= '9') + { + output = char(input - '0'); + return true; + } + else if(input >= 'a' && input <= 'f') + { + output = char(input - 'a' + 0xA); + return true; + } + else if(input >= 'A' && input <= 'F') + { + output = char(input - 'A' + 0xA); + return true; + } + else + { + return false; + } +} diff --git a/Source/cmUuid.h b/Source/cmUuid.h new file mode 100644 index 0000000..0dda357 --- /dev/null +++ b/Source/cmUuid.h @@ -0,0 +1,55 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 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 cmUuid_h +#define cmUuid_h + +#include "cmStandardIncludes.h" + +/** \class cmUuid + * \brief Utility class to generate UUIDs as defined by RFC4122 + * + */ +class cmUuid +{ +public: + cmUuid(); + + std::string FromMd5(std::vector<unsigned char> const& uuidNamespace, + std::string const& name) const; + + std::string FromSha1(std::vector<unsigned char> const& uuidNamespace, + std::string const& name) const; + + bool StringToBinary(std::string const& input, + std::vector<unsigned char> &output) const; + +private: + std::string ByteToHex(unsigned char byte) const; + + void CreateHashInput(std::vector<unsigned char> const& uuidNamespace, + std::string const& name, std::vector<unsigned char> &output) const; + + std::string FromDigest(const unsigned char* digest, + unsigned char version) const; + + bool StringToBinaryImpl(std::string const& input, + std::vector<unsigned char> &output) const; + + std::string BinaryToString(const unsigned char* input) const; + + bool IntFromHexDigit(char input, char& output) const; + + std::vector<int> Groups; +}; + + +#endif diff --git a/Source/cmVS10MASMFlagTable.h b/Source/cmVS10MASMFlagTable.h new file mode 100644 index 0000000..8fb6f33 --- /dev/null +++ b/Source/cmVS10MASMFlagTable.h @@ -0,0 +1,96 @@ +static cmVS7FlagTable cmVS10MASMFlagTable[] = +{ + + //Enum Properties + {"PreserveIdentifierCase", "", + "Default", "0", 0}, + {"PreserveIdentifierCase", "/Cp", + "Preserves Identifier Case (/Cp)", "1", 0}, + {"PreserveIdentifierCase", "/Cu", + "Maps all identifiers to upper case. (/Cu)", "2", 0}, + {"PreserveIdentifierCase", "/Cx", + "Preserves case in public and extern symbols. (/Cx)", "3", 0}, + + {"WarningLevel", "/W0", + "Warning Level 0 (/W0)", "0", 0}, + {"WarningLevel", "/W1", + "Warning Level 1 (/W1)", "1", 0}, + {"WarningLevel", "/W2", + "Warning Level 2 (/W2)", "2", 0}, + {"WarningLevel", "/W3", + "Warning Level 3 (/W3)", "3", 0}, + + {"PackAlignmentBoundary", "", + "Default", "0", 0}, + {"PackAlignmentBoundary", "/Zp1", + "One Byte Boundary (/Zp1)", "1", 0}, + {"PackAlignmentBoundary", "/Zp2", + "Two Byte Boundary (/Zp2)", "2", 0}, + {"PackAlignmentBoundary", "/Zp4", + "Four Byte Boundary (/Zp4)", "3", 0}, + {"PackAlignmentBoundary", "/Zp8", + "Eight Byte Boundary (/Zp8)", "4", 0}, + {"PackAlignmentBoundary", "/Zp16", + "Sixteen Byte Boundary (/Zp16)", "5", 0}, + + {"CallingConvention", "", + "Default", "0", 0}, + {"CallingConvention", "/Gd", + "Use C-style Calling Convention (/Gd)", "1", 0}, + {"CallingConvention", "/Gz", + "Use stdcall Calling Convention (/Gz)", "2", 0}, + {"CallingConvention", "/Gc", + "Use Pascal Calling Convention (/Gc)", "3", 0}, + + {"ErrorReporting", "/errorReport:prompt", + "Prompt to send report immediately (/errorReport:prompt)", "0", 0}, + {"ErrorReporting", "/errorReport:queue", + "Prompt to send report at the next logon (/errorReport:queue)", "1", 0}, + {"ErrorReporting", "/errorReport:send", + "Automatically send report (/errorReport:send)", "2", 0}, + {"ErrorReporting", "/errorReport:none", + "Do not send report (/errorReport:none)", "3", 0}, + + + //Bool Properties + {"NoLogo", "/nologo", "", "true", 0}, + {"GeneratePreprocessedSourceListing", "/EP", "", "true", 0}, + {"ListAllAvailableInformation", "/Sa", "", "true", 0}, + {"UseSafeExceptionHandlers", "/safeseh", "", "true", 0}, + {"AddFirstPassListing", "/Sf", "", "true", 0}, + {"EnableAssemblyGeneratedCodeListing", "/Sg", "", "true", 0}, + {"DisableSymbolTable", "/Sn", "", "true", 0}, + {"EnableFalseConditionalsInListing", "/Sx", "", "true", 0}, + {"TreatWarningsAsErrors", "/WX", "", "true", 0}, + {"MakeAllSymbolsPublic", "/Zf", "", "true", 0}, + {"GenerateDebugInformation", "/Zi", "", "true", 0}, + {"EnableMASM51Compatibility", "/Zm", "", "true", 0}, + {"PerformSyntaxCheckOnly", "/Zs", "", "true", 0}, + + //Bool Properties With Argument + + //String List Properties + {"PreprocessorDefinitions", "/D", + "Preprocessor Definitions", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"IncludePaths", "/I", + "Include Paths", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"BrowseFile", "/FR", + "Generate Browse Information File", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + // Skip [AdditionalDependencies] - no command line Switch. + + //String Properties + // Skip [Inputs] - no command line Switch. + {"ObjectFileName", "/Fo", + "Object File Name", + "", cmVS7FlagTable::UserValue}, + {"AssembledCodeListingFile", "/Fl", + "Assembled Code Listing File", + "", cmVS7FlagTable::UserValue}, + // Skip [CommandLineTemplate] - no command line Switch. + // Skip [ExecutionDescription] - no command line Switch. + // Skip [AdditionalOptions] - no command line Switch. + {0,0,0,0,0} +}; diff --git a/Source/cmVS10RCFlagTable.h b/Source/cmVS10RCFlagTable.h new file mode 100644 index 0000000..9049986 --- /dev/null +++ b/Source/cmVS10RCFlagTable.h @@ -0,0 +1,7 @@ +static cmVS7FlagTable cmVS10RCFlagTable[] = +{ + //Bool Properties + {"NullTerminateStrings", "n", "", "true", 0}, + + {0,0,0,0,0} +}; diff --git a/Source/cmVS11MASMFlagTable.h b/Source/cmVS11MASMFlagTable.h new file mode 100644 index 0000000..2ff95ad --- /dev/null +++ b/Source/cmVS11MASMFlagTable.h @@ -0,0 +1,96 @@ +static cmVS7FlagTable cmVS11MASMFlagTable[] = +{ + + //Enum Properties + {"PreserveIdentifierCase", "", + "Default", "0", 0}, + {"PreserveIdentifierCase", "/Cp", + "Preserves Identifier Case (/Cp)", "1", 0}, + {"PreserveIdentifierCase", "/Cu", + "Maps all identifiers to upper case. (/Cu)", "2", 0}, + {"PreserveIdentifierCase", "/Cx", + "Preserves case in public and extern symbols. (/Cx)", "3", 0}, + + {"WarningLevel", "/W0", + "Warning Level 0 (/W0)", "0", 0}, + {"WarningLevel", "/W1", + "Warning Level 1 (/W1)", "1", 0}, + {"WarningLevel", "/W2", + "Warning Level 2 (/W2)", "2", 0}, + {"WarningLevel", "/W3", + "Warning Level 3 (/W3)", "3", 0}, + + {"PackAlignmentBoundary", "", + "Default", "0", 0}, + {"PackAlignmentBoundary", "/Zp1", + "One Byte Boundary (/Zp1)", "1", 0}, + {"PackAlignmentBoundary", "/Zp2", + "Two Byte Boundary (/Zp2)", "2", 0}, + {"PackAlignmentBoundary", "/Zp4", + "Four Byte Boundary (/Zp4)", "3", 0}, + {"PackAlignmentBoundary", "/Zp8", + "Eight Byte Boundary (/Zp8)", "4", 0}, + {"PackAlignmentBoundary", "/Zp16", + "Sixteen Byte Boundary (/Zp16)", "5", 0}, + + {"CallingConvention", "", + "Default", "0", 0}, + {"CallingConvention", "/Gd", + "Use C-style Calling Convention (/Gd)", "1", 0}, + {"CallingConvention", "/Gz", + "Use stdcall Calling Convention (/Gz)", "2", 0}, + {"CallingConvention", "/Gc", + "Use Pascal Calling Convention (/Gc)", "3", 0}, + + {"ErrorReporting", "/errorReport:prompt", + "Prompt to send report immediately (/errorReport:prompt)", "0", 0}, + {"ErrorReporting", "/errorReport:queue", + "Prompt to send report at the next logon (/errorReport:queue)", "1", 0}, + {"ErrorReporting", "/errorReport:send", + "Automatically send report (/errorReport:send)", "2", 0}, + {"ErrorReporting", "/errorReport:none", + "Do not send report (/errorReport:none)", "3", 0}, + + + //Bool Properties + {"NoLogo", "/nologo", "", "true", 0}, + {"GeneratePreprocessedSourceListing", "/EP", "", "true", 0}, + {"ListAllAvailableInformation", "/Sa", "", "true", 0}, + {"UseSafeExceptionHandlers", "/safeseh", "", "true", 0}, + {"AddFirstPassListing", "/Sf", "", "true", 0}, + {"EnableAssemblyGeneratedCodeListing", "/Sg", "", "true", 0}, + {"DisableSymbolTable", "/Sn", "", "true", 0}, + {"EnableFalseConditionalsInListing", "/Sx", "", "true", 0}, + {"TreatWarningsAsErrors", "/WX", "", "true", 0}, + {"MakeAllSymbolsPublic", "/Zf", "", "true", 0}, + {"GenerateDebugInformation", "/Zi", "", "true", 0}, + {"EnableMASM51Compatibility", "/Zm", "", "true", 0}, + {"PerformSyntaxCheckOnly", "/Zs", "", "true", 0}, + + //Bool Properties With Argument + + //String List Properties + {"PreprocessorDefinitions", "/D", + "Preprocessor Definitions", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"IncludePaths", "/I", + "Include Paths", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"BrowseFile", "/FR", + "Generate Browse Information File", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + // Skip [AdditionalDependencies] - no command line Switch. + + //String Properties + // Skip [Inputs] - no command line Switch. + {"ObjectFileName", "/Fo", + "Object File Name", + "", cmVS7FlagTable::UserValue}, + {"AssembledCodeListingFile", "/Fl", + "Assembled Code Listing File", + "", cmVS7FlagTable::UserValue}, + // Skip [CommandLineTemplate] - no command line Switch. + // Skip [ExecutionDescription] - no command line Switch. + // Skip [AdditionalOptions] - no command line Switch. + {0,0,0,0,0} +}; diff --git a/Source/cmVS11RCFlagTable.h b/Source/cmVS11RCFlagTable.h new file mode 100644 index 0000000..a7d2de1 --- /dev/null +++ b/Source/cmVS11RCFlagTable.h @@ -0,0 +1,7 @@ +static cmVS7FlagTable cmVS11RCFlagTable[] = +{ + //Bool Properties + {"NullTerminateStrings", "n", "", "true", 0}, + + {0,0,0,0,0} +}; diff --git a/Source/cmVS12MASMFlagTable.h b/Source/cmVS12MASMFlagTable.h new file mode 100644 index 0000000..74d529c --- /dev/null +++ b/Source/cmVS12MASMFlagTable.h @@ -0,0 +1,96 @@ +static cmVS7FlagTable cmVS12MASMFlagTable[] = +{ + + //Enum Properties + {"PreserveIdentifierCase", "", + "Default", "0", 0}, + {"PreserveIdentifierCase", "/Cp", + "Preserves Identifier Case (/Cp)", "1", 0}, + {"PreserveIdentifierCase", "/Cu", + "Maps all identifiers to upper case. (/Cu)", "2", 0}, + {"PreserveIdentifierCase", "/Cx", + "Preserves case in public and extern symbols. (/Cx)", "3", 0}, + + {"WarningLevel", "/W0", + "Warning Level 0 (/W0)", "0", 0}, + {"WarningLevel", "/W1", + "Warning Level 1 (/W1)", "1", 0}, + {"WarningLevel", "/W2", + "Warning Level 2 (/W2)", "2", 0}, + {"WarningLevel", "/W3", + "Warning Level 3 (/W3)", "3", 0}, + + {"PackAlignmentBoundary", "", + "Default", "0", 0}, + {"PackAlignmentBoundary", "/Zp1", + "One Byte Boundary (/Zp1)", "1", 0}, + {"PackAlignmentBoundary", "/Zp2", + "Two Byte Boundary (/Zp2)", "2", 0}, + {"PackAlignmentBoundary", "/Zp4", + "Four Byte Boundary (/Zp4)", "3", 0}, + {"PackAlignmentBoundary", "/Zp8", + "Eight Byte Boundary (/Zp8)", "4", 0}, + {"PackAlignmentBoundary", "/Zp16", + "Sixteen Byte Boundary (/Zp16)", "5", 0}, + + {"CallingConvention", "", + "Default", "0", 0}, + {"CallingConvention", "/Gd", + "Use C-style Calling Convention (/Gd)", "1", 0}, + {"CallingConvention", "/Gz", + "Use stdcall Calling Convention (/Gz)", "2", 0}, + {"CallingConvention", "/Gc", + "Use Pascal Calling Convention (/Gc)", "3", 0}, + + {"ErrorReporting", "/errorReport:prompt", + "Prompt to send report immediately (/errorReport:prompt)", "0", 0}, + {"ErrorReporting", "/errorReport:queue", + "Prompt to send report at the next logon (/errorReport:queue)", "1", 0}, + {"ErrorReporting", "/errorReport:send", + "Automatically send report (/errorReport:send)", "2", 0}, + {"ErrorReporting", "/errorReport:none", + "Do not send report (/errorReport:none)", "3", 0}, + + + //Bool Properties + {"NoLogo", "/nologo", "", "true", 0}, + {"GeneratePreprocessedSourceListing", "/EP", "", "true", 0}, + {"ListAllAvailableInformation", "/Sa", "", "true", 0}, + {"UseSafeExceptionHandlers", "/safeseh", "", "true", 0}, + {"AddFirstPassListing", "/Sf", "", "true", 0}, + {"EnableAssemblyGeneratedCodeListing", "/Sg", "", "true", 0}, + {"DisableSymbolTable", "/Sn", "", "true", 0}, + {"EnableFalseConditionalsInListing", "/Sx", "", "true", 0}, + {"TreatWarningsAsErrors", "/WX", "", "true", 0}, + {"MakeAllSymbolsPublic", "/Zf", "", "true", 0}, + {"GenerateDebugInformation", "/Zi", "", "true", 0}, + {"EnableMASM51Compatibility", "/Zm", "", "true", 0}, + {"PerformSyntaxCheckOnly", "/Zs", "", "true", 0}, + + //Bool Properties With Argument + + //String List Properties + {"PreprocessorDefinitions", "/D", + "Preprocessor Definitions", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"IncludePaths", "/I", + "Include Paths", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"BrowseFile", "/FR", + "Generate Browse Information File", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + // Skip [AdditionalDependencies] - no command line Switch. + + //String Properties + // Skip [Inputs] - no command line Switch. + {"ObjectFileName", "/Fo", + "Object File Name", + "", cmVS7FlagTable::UserValue}, + {"AssembledCodeListingFile", "/Fl", + "Assembled Code Listing File", + "", cmVS7FlagTable::UserValue}, + // Skip [CommandLineTemplate] - no command line Switch. + // Skip [ExecutionDescription] - no command line Switch. + // Skip [AdditionalOptions] - no command line Switch. + {0,0,0,0,0} +}; diff --git a/Source/cmVS12RCFlagTable.h b/Source/cmVS12RCFlagTable.h new file mode 100644 index 0000000..1551c66 --- /dev/null +++ b/Source/cmVS12RCFlagTable.h @@ -0,0 +1,7 @@ +static cmVS7FlagTable cmVS12RCFlagTable[] = +{ + //Bool Properties + {"NullTerminateStrings", "n", "", "true", 0}, + + {0,0,0,0,0} +}; diff --git a/Source/cmVS14CLFlagTable.h b/Source/cmVS14CLFlagTable.h new file mode 100644 index 0000000..422f47b --- /dev/null +++ b/Source/cmVS14CLFlagTable.h @@ -0,0 +1,296 @@ +static cmVS7FlagTable cmVS14CLFlagTable[] = +{ + + //Enum Properties + {"DebugInformationFormat", "", + "None", "None", 0}, + {"DebugInformationFormat", "Z7", + "C7 compatible", "OldStyle", 0}, + {"DebugInformationFormat", "Zi", + "Program Database", "ProgramDatabase", 0}, + {"DebugInformationFormat", "ZI", + "Program Database for Edit And Continue", "EditAndContinue", 0}, + + {"WarningLevel", "W0", + "Turn Off All Warnings", "TurnOffAllWarnings", 0}, + {"WarningLevel", "W1", + "Level1", "Level1", 0}, + {"WarningLevel", "W2", + "Level2", "Level2", 0}, + {"WarningLevel", "W3", + "Level3", "Level3", 0}, + {"WarningLevel", "W4", + "Level4", "Level4", 0}, + {"WarningLevel", "Wall", + "EnableAllWarnings", "EnableAllWarnings", 0}, + + {"Optimization", "", + "Custom", "Custom", 0}, + {"Optimization", "Od", + "Disabled", "Disabled", 0}, + {"Optimization", "O1", + "Minimize Size", "MinSpace", 0}, + {"Optimization", "O2", + "Maximize Speed", "MaxSpeed", 0}, + {"Optimization", "Ox", + "Full Optimization", "Full", 0}, + + {"InlineFunctionExpansion", "", + "Default", "Default", 0}, + {"InlineFunctionExpansion", "Ob0", + "Disabled", "Disabled", 0}, + {"InlineFunctionExpansion", "Ob1", + "Only __inline", "OnlyExplicitInline", 0}, + {"InlineFunctionExpansion", "Ob2", + "Any Suitable", "AnySuitable", 0}, + + {"FavorSizeOrSpeed", "Os", + "Favor small code", "Size", 0}, + {"FavorSizeOrSpeed", "Ot", + "Favor fast code", "Speed", 0}, + {"FavorSizeOrSpeed", "", + "Neither", "Neither", 0}, + + {"ExceptionHandling", "EHa", + "Yes with SEH Exceptions", "Async", 0}, + {"ExceptionHandling", "EHsc", + "Yes", "Sync", 0}, + {"ExceptionHandling", "EHs", + "Yes with Extern C functions", "SyncCThrow", 0}, + {"ExceptionHandling", "", + "No", "false", 0}, + + {"BasicRuntimeChecks", "RTCs", + "Stack Frames", "StackFrameRuntimeCheck", 0}, + {"BasicRuntimeChecks", "RTCu", + "Uninitialized variables", "UninitializedLocalUsageCheck", 0}, + {"BasicRuntimeChecks", "RTC1", + "Both (/RTC1, equiv. to /RTCsu)", "EnableFastChecks", 0}, + {"BasicRuntimeChecks", "", + "Default", "Default", 0}, + + {"RuntimeLibrary", "MT", + "Multi-threaded", "MultiThreaded", 0}, + {"RuntimeLibrary", "MTd", + "Multi-threaded Debug", "MultiThreadedDebug", 0}, + {"RuntimeLibrary", "MD", + "Multi-threaded DLL", "MultiThreadedDLL", 0}, + {"RuntimeLibrary", "MDd", + "Multi-threaded Debug DLL", "MultiThreadedDebugDLL", 0}, + + {"StructMemberAlignment", "Zp1", + "1 Byte", "1Byte", 0}, + {"StructMemberAlignment", "Zp2", + "2 Bytes", "2Bytes", 0}, + {"StructMemberAlignment", "Zp4", + "4 Byte", "4Bytes", 0}, + {"StructMemberAlignment", "Zp8", + "8 Bytes", "8Bytes", 0}, + {"StructMemberAlignment", "Zp16", + "16 Bytes", "16Bytes", 0}, + {"StructMemberAlignment", "", + "Default", "Default", 0}, + + {"BufferSecurityCheck", "GS-", + "Disable Security Check", "false", 0}, + {"BufferSecurityCheck", "GS", + "Enable Security Check", "true", 0}, + + {"EnableEnhancedInstructionSet", "arch:SSE", + "Streaming SIMD Extensions", "StreamingSIMDExtensions", 0}, + {"EnableEnhancedInstructionSet", "arch:SSE2", + "Streaming SIMD Extensions 2", "StreamingSIMDExtensions2", 0}, + {"EnableEnhancedInstructionSet", "arch:AVX", + "Advanced Vector Extensions", "AdvancedVectorExtensions", 0}, + {"EnableEnhancedInstructionSet", "arch:AVX2", + "Advanced Vector Extensions 2", "AdvancedVectorExtensions2", 0}, + {"EnableEnhancedInstructionSet", "arch:IA32", + "No Enhanced Instructions", "NoExtensions", 0}, + {"EnableEnhancedInstructionSet", "", + "Not Set", "NotSet", 0}, + + {"FloatingPointModel", "fp:precise", + "Precise", "Precise", 0}, + {"FloatingPointModel", "fp:strict", + "Strict", "Strict", 0}, + {"FloatingPointModel", "fp:fast", + "Fast", "Fast", 0}, + + {"PrecompiledHeader", "Yc", + "Create", "Create", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, + {"PrecompiledHeader", "Yu", + "Use", "Use", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, + {"PrecompiledHeader", "", + "Not Using Precompiled Headers", "NotUsing", 0}, + + {"AssemblerOutput", "", + "No Listing", "NoListing", 0}, + {"AssemblerOutput", "FA", + "Assembly-Only Listing", "AssemblyCode", 0}, + {"AssemblerOutput", "FAc", + "Assembly With Machine Code", "AssemblyAndMachineCode", 0}, + {"AssemblerOutput", "FAs", + "Assembly With Source Code", "AssemblyAndSourceCode", 0}, + {"AssemblerOutput", "FAcs", + "Assembly, Machine Code and Source", "All", 0}, + + {"CallingConvention", "Gd", + "__cdecl", "Cdecl", 0}, + {"CallingConvention", "Gr", + "__fastcall", "FastCall", 0}, + {"CallingConvention", "Gz", + "__stdcall", "StdCall", 0}, + {"CallingConvention", "Gv", + "__vectorcall", "VectorCall", 0}, + + {"CompileAs", "", + "Default", "Default", 0}, + {"CompileAs", "TC", + "Compile as C Code", "CompileAsC", 0}, + {"CompileAs", "TP", + "Compile as C++ Code", "CompileAsCpp", 0}, + + {"ErrorReporting", "errorReport:none", + "Do Not Send Report", "None", 0}, + {"ErrorReporting", "errorReport:prompt", + "Prompt Immediately", "Prompt", 0}, + {"ErrorReporting", "errorReport:queue", + "Queue For Next Login", "Queue", 0}, + {"ErrorReporting", "errorReport:send", + "Send Automatically", "Send", 0}, + + {"CompileAsManaged", "", + "No Common Language RunTime Support", "false", 0}, + {"CompileAsManaged", "clr", + "Common Language RunTime Support", "true", 0}, + {"CompileAsManaged", "clr:pure", + "Pure MSIL Common Language RunTime Support", "Pure", 0}, + {"CompileAsManaged", "clr:safe", + "Safe MSIL Common Language RunTime Support", "Safe", 0}, + {"CompileAsManaged", "clr:oldSyntax", + "Common Language RunTime Support, Old Syntax", "OldSyntax", 0}, + + + //Bool Properties + {"CompileAsWinRT", "ZW", "", "true", 0}, + {"WinRTNoStdLib", "ZW:nostdlib", "", "true", 0}, + {"SuppressStartupBanner", "nologo", "", "true", 0}, + {"TreatWarningAsError", "WX-", "", "false", 0}, + {"TreatWarningAsError", "WX", "", "true", 0}, + {"SDLCheck", "sdl-", "", "false", 0}, + {"SDLCheck", "sdl", "", "true", 0}, + {"IntrinsicFunctions", "Oi", "", "true", 0}, + {"OmitFramePointers", "Oy-", "", "false", 0}, + {"OmitFramePointers", "Oy", "", "true", 0}, + {"EnableFiberSafeOptimizations", "GT", "", "true", 0}, + {"WholeProgramOptimization", "GL", "", "true", 0}, + {"UndefineAllPreprocessorDefinitions", "u", "", "true", 0}, + {"IgnoreStandardIncludePath", "X", "", "true", 0}, + {"PreprocessToFile", "P", "", "true", 0}, + {"PreprocessSuppressLineNumbers", "EP", "", "true", 0}, + {"PreprocessKeepComments", "C", "", "true", 0}, + {"StringPooling", "GF-", "", "false", 0}, + {"StringPooling", "GF", "", "true", 0}, + {"MinimalRebuild", "Gm-", "", "false", 0}, + {"MinimalRebuild", "Gm", "", "true", 0}, + {"SmallerTypeCheck", "RTCc", "", "true", 0}, + {"FunctionLevelLinking", "Gy-", "", "false", 0}, + {"FunctionLevelLinking", "Gy", "", "true", 0}, + {"EnableParallelCodeGeneration", "Qpar-", "", "false", 0}, + {"EnableParallelCodeGeneration", "Qpar", "", "true", 0}, + {"FloatingPointExceptions", "fp:except-", "", "false", 0}, + {"FloatingPointExceptions", "fp:except", "", "true", 0}, + {"CreateHotpatchableImage", "hotpatch", "", "true", 0}, + {"DisableLanguageExtensions", "Za", "", "true", 0}, + {"TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "", "false", 0}, + {"TreatWChar_tAsBuiltInType", "Zc:wchar_t", "", "true", 0}, + {"ForceConformanceInForLoopScope", "Zc:forScope-", "", "false", 0}, + {"ForceConformanceInForLoopScope", "Zc:forScope", "", "true", 0}, + {"RuntimeTypeInfo", "GR-", "", "false", 0}, + {"RuntimeTypeInfo", "GR", "", "true", 0}, + {"OpenMPSupport", "openmp-", "", "false", 0}, + {"OpenMPSupport", "openmp", "", "true", 0}, + {"ExpandAttributedSource", "Fx", "", "true", 0}, + {"UseUnicodeForAssemblerListing", "FAu", "", "true", 0}, + {"ShowIncludes", "showIncludes", "", "true", 0}, + {"EnablePREfast", "analyze-", "", "false", 0}, + {"EnablePREfast", "analyze", "", "true", 0}, + {"UseFullPaths", "FC", "", "true", 0}, + {"OmitDefaultLibName", "Zl", "", "true", 0}, + + //Bool Properties With Argument + {"MultiProcessorCompilation", "MP", "", "true", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, + {"ProcessorNumber", "MP", "Multi-processor Compilation", "", + cmVS7FlagTable::UserValueRequired}, + {"GenerateXMLDocumentationFiles", "doc", "", "true", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, + {"XMLDocumentationFileName", "doc", "Generate XML Documentation Files", "", + cmVS7FlagTable::UserValueRequired}, + {"BrowseInformation", "FR", "", "true", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, + {"BrowseInformationFile", "FR", "Enable Browse Information", "", + cmVS7FlagTable::UserValueRequired}, + + //String List Properties + {"AdditionalIncludeDirectories", "I", + "Additional Include Directories", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"AdditionalUsingDirectories", "AI", + "Additional #using Directories", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"PreprocessorDefinitions", "D ", + "Preprocessor Definitions", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"UndefinePreprocessorDefinitions", "U", + "Undefine Preprocessor Definitions", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"DisableSpecificWarnings", "wd", + "Disable Specific Warnings", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"ForcedIncludeFiles", "FI", + "Forced Include File", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"ForcedUsingFiles", "FU", + "Forced #using File", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"PREfastLog", "analyze:log", + "Code Analysis Log", + "", cmVS7FlagTable::UserFollowing}, + {"PREfastAdditionalPlugins", "analyze:plugin", + "Additional Code Analysis Native plugins", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"TreatSpecificWarningsAsErrors", "we", + "Treat Specific Warnings As Errors", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + + //String Properties + // Skip [TrackerLogDirectory] - no command line Switch. + {"PreprocessOutputPath", "Fi", + "Preprocess Output Path", + "", cmVS7FlagTable::UserValue}, + {"PrecompiledHeaderFile", "Yc", + "Precompiled Header Name", + "", cmVS7FlagTable::UserValueRequired}, + {"PrecompiledHeaderFile", "Yu", + "Precompiled Header Name", + "", cmVS7FlagTable::UserValueRequired}, + {"PrecompiledHeaderOutputFile", "Fp", + "Precompiled Header Output File", + "", cmVS7FlagTable::UserValue}, + {"AssemblerListingLocation", "Fa", + "ASM List Location", + "", cmVS7FlagTable::UserValue}, + {"ObjectFileName", "Fo", + "Object File Name", + "", cmVS7FlagTable::UserValue}, + {"ProgramDataBaseFileName", "Fd", + "Program Database File Name", + "", cmVS7FlagTable::UserValue}, + // Skip [XMLDocumentationFileName] - no command line Switch. + // Skip [BrowseInformationFile] - no command line Switch. + // Skip [AdditionalOptions] - no command line Switch. + {0,0,0,0,0} +}; diff --git a/Source/cmVS14LibFlagTable.h b/Source/cmVS14LibFlagTable.h new file mode 100644 index 0000000..a33f273 --- /dev/null +++ b/Source/cmVS14LibFlagTable.h @@ -0,0 +1,102 @@ +static cmVS7FlagTable cmVS14LibFlagTable[] = +{ + + //Enum Properties + {"ErrorReporting", "ERRORREPORT:PROMPT", + "PromptImmediately", "PromptImmediately", 0}, + {"ErrorReporting", "ERRORREPORT:QUEUE", + "Queue For Next Login", "QueueForNextLogin", 0}, + {"ErrorReporting", "ERRORREPORT:SEND", + "Send Error Report", "SendErrorReport", 0}, + {"ErrorReporting", "ERRORREPORT:NONE", + "No Error Report", "NoErrorReport", 0}, + + {"TargetMachine", "MACHINE:ARM", + "MachineARM", "MachineARM", 0}, + {"TargetMachine", "MACHINE:EBC", + "MachineEBC", "MachineEBC", 0}, + {"TargetMachine", "MACHINE:IA64", + "MachineIA64", "MachineIA64", 0}, + {"TargetMachine", "MACHINE:MIPS", + "MachineMIPS", "MachineMIPS", 0}, + {"TargetMachine", "MACHINE:MIPS16", + "MachineMIPS16", "MachineMIPS16", 0}, + {"TargetMachine", "MACHINE:MIPSFPU", + "MachineMIPSFPU", "MachineMIPSFPU", 0}, + {"TargetMachine", "MACHINE:MIPSFPU16", + "MachineMIPSFPU16", "MachineMIPSFPU16", 0}, + {"TargetMachine", "MACHINE:SH4", + "MachineSH4", "MachineSH4", 0}, + {"TargetMachine", "MACHINE:THUMB", + "MachineTHUMB", "MachineTHUMB", 0}, + {"TargetMachine", "MACHINE:X64", + "MachineX64", "MachineX64", 0}, + {"TargetMachine", "MACHINE:X86", + "MachineX86", "MachineX86", 0}, + + {"SubSystem", "SUBSYSTEM:CONSOLE", + "Console", "Console", 0}, + {"SubSystem", "SUBSYSTEM:WINDOWS", + "Windows", "Windows", 0}, + {"SubSystem", "SUBSYSTEM:NATIVE", + "Native", "Native", 0}, + {"SubSystem", "SUBSYSTEM:EFI_APPLICATION", + "EFI Application", "EFI Application", 0}, + {"SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", + "EFI Boot Service Driver", "EFI Boot Service Driver", 0}, + {"SubSystem", "SUBSYSTEM:EFI_ROM", + "EFI ROM", "EFI ROM", 0}, + {"SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", + "EFI Runtime", "EFI Runtime", 0}, + {"SubSystem", "SUBSYSTEM:WINDOWSCE", + "WindowsCE", "WindowsCE", 0}, + {"SubSystem", "SUBSYSTEM:POSIX", + "POSIX", "POSIX", 0}, + + + //Bool Properties + {"SuppressStartupBanner", "NOLOGO", "", "true", 0}, + {"IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0}, + {"TreatLibWarningAsErrors", "WX:NO", "", "false", 0}, + {"TreatLibWarningAsErrors", "WX", "", "true", 0}, + {"Verbose", "VERBOSE", "", "true", 0}, + {"LinkTimeCodeGeneration", "LTCG", "", "true", 0}, + + //Bool Properties With Argument + + //String List Properties + // Skip [AdditionalDependencies] - no command line Switch. + {"AdditionalLibraryDirectories", "LIBPATH:", + "Additional Library Directories", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:", + "Ignore Specific Default Libraries", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"ExportNamedFunctions", "EXPORT:", + "Export Named Functions", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"RemoveObjects", "REMOVE:", + "Remove Objects", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + + //String Properties + {"OutputFile", "OUT:", + "Output File", + "", cmVS7FlagTable::UserValue}, + {"ModuleDefinitionFile", "DEF:", + "Module Definition File Name", + "", cmVS7FlagTable::UserValue}, + {"ForceSymbolReferences", "INCLUDE:", + "Force Symbol References", + "", cmVS7FlagTable::UserValue}, + {"DisplayLibrary", "LIST:", + "Display Library to standard output", + "", cmVS7FlagTable::UserValue}, + // Skip [MinimumRequiredVersion] - no command line Switch. + {"Name", "NAME:", + "Name", + "", cmVS7FlagTable::UserValue}, + // Skip [AdditionalOptions] - no command line Switch. + // Skip [TrackerLogDirectory] - no command line Switch. + {0,0,0,0,0} +}; diff --git a/Source/cmVS14LinkFlagTable.h b/Source/cmVS14LinkFlagTable.h new file mode 100644 index 0000000..6d81d12 --- /dev/null +++ b/Source/cmVS14LinkFlagTable.h @@ -0,0 +1,340 @@ +static cmVS7FlagTable cmVS14LinkFlagTable[] = +{ + + //Enum Properties + {"ShowProgress", "", + "Not Set", "NotSet", 0}, + {"ShowProgress", "VERBOSE", + "Display all progress messages", "LinkVerbose", 0}, + {"ShowProgress", "VERBOSE:Lib", + "For Libraries Searched", "LinkVerboseLib", 0}, + {"ShowProgress", "VERBOSE:ICF", + "About COMDAT folding during optimized linking", "LinkVerboseICF", 0}, + {"ShowProgress", "VERBOSE:REF", + "About data removed during optimized linking", "LinkVerboseREF", 0}, + {"ShowProgress", "VERBOSE:SAFESEH", + "About Modules incompatible with SEH", "LinkVerboseSAFESEH", 0}, + {"ShowProgress", "VERBOSE:CLR", + "About linker activity related to managed code", "LinkVerboseCLR", 0}, + + {"ForceFileOutput", "FORCE", + "Enabled", "Enabled", 0}, + {"ForceFileOutput", "FORCE:MULTIPLE", + "Multiply Defined Symbol Only", "MultiplyDefinedSymbolOnly", 0}, + {"ForceFileOutput", "FORCE:UNRESOLVED", + "Undefined Symbol Only", "UndefinedSymbolOnly", 0}, + + {"CreateHotPatchableImage", "FUNCTIONPADMIN", + "Enabled", "Enabled", 0}, + {"CreateHotPatchableImage", "FUNCTIONPADMIN:5", + "X86 Image Only", "X86Image", 0}, + {"CreateHotPatchableImage", "FUNCTIONPADMIN:6", + "X64 Image Only", "X64Image", 0}, + {"CreateHotPatchableImage", "FUNCTIONPADMIN:16", + "Itanium Image Only", "ItaniumImage", 0}, + + {"UACExecutionLevel", "level='asInvoker'", + "asInvoker", "AsInvoker", 0}, + {"UACExecutionLevel", "level='highestAvailable'", + "highestAvailable", "HighestAvailable", 0}, + {"UACExecutionLevel", "level='requireAdministrator'", + "requireAdministrator", "RequireAdministrator", 0}, + + {"SubSystem", "", + "Not Set", "NotSet", 0}, + {"SubSystem", "SUBSYSTEM:CONSOLE", + "Console", "Console", 0}, + {"SubSystem", "SUBSYSTEM:WINDOWS", + "Windows", "Windows", 0}, + {"SubSystem", "SUBSYSTEM:NATIVE", + "Native", "Native", 0}, + {"SubSystem", "SUBSYSTEM:EFI_APPLICATION", + "EFI Application", "EFI Application", 0}, + {"SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", + "EFI Boot Service Driver", "EFI Boot Service Driver", 0}, + {"SubSystem", "SUBSYSTEM:EFI_ROM", + "EFI ROM", "EFI ROM", 0}, + {"SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", + "EFI Runtime", "EFI Runtime", 0}, + {"SubSystem", "SUBSYSTEM:POSIX", + "POSIX", "POSIX", 0}, + + {"Driver", "", + "Not Set", "NotSet", 0}, + {"Driver", "Driver", + "Driver", "Driver", 0}, + {"Driver", "DRIVER:UPONLY", + "UP Only", "UpOnly", 0}, + {"Driver", "DRIVER:WDM", + "WDM", "WDM", 0}, + + {"LinkTimeCodeGeneration", "", + "Default", "Default", 0}, + {"LinkTimeCodeGeneration", "LTCG", + "Use Link Time Code Generation", "UseLinkTimeCodeGeneration", 0}, + {"LinkTimeCodeGeneration", "LTCG:PGInstrument", + "Profile Guided Optimization - Instrument", "PGInstrument", 0}, + {"LinkTimeCodeGeneration", "LTCG:PGOptimize", + "Profile Guided Optimization - Optimization", "PGOptimization", 0}, + {"LinkTimeCodeGeneration", "LTCG:PGUpdate", + "Profile Guided Optimization - Update", "PGUpdate", 0}, + + {"GenerateWindowsMetadata", "WINMD", + "Yes", "true", 0}, + {"GenerateWindowsMetadata", "WINMD:NO", + "No", "false", 0}, + + {"WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1", + "SHA1", "SHA1", 0}, + {"WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256", + "SHA256", "SHA256", 0}, + {"WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384", + "SHA384", "SHA384", 0}, + {"WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512", + "SHA512", "SHA512", 0}, + + {"TargetMachine", "", + "Not Set", "NotSet", 0}, + {"TargetMachine", "MACHINE:ARM", + "MachineARM", "MachineARM", 0}, + {"TargetMachine", "MACHINE:EBC", + "MachineEBC", "MachineEBC", 0}, + {"TargetMachine", "MACHINE:IA64", + "MachineIA64", "MachineIA64", 0}, + {"TargetMachine", "MACHINE:MIPS", + "MachineMIPS", "MachineMIPS", 0}, + {"TargetMachine", "MACHINE:MIPS16", + "MachineMIPS16", "MachineMIPS16", 0}, + {"TargetMachine", "MACHINE:MIPSFPU", + "MachineMIPSFPU", "MachineMIPSFPU", 0}, + {"TargetMachine", "MACHINE:MIPSFPU16", + "MachineMIPSFPU16", "MachineMIPSFPU16", 0}, + {"TargetMachine", "MACHINE:SH4", + "MachineSH4", "MachineSH4", 0}, + {"TargetMachine", "MACHINE:THUMB", + "MachineTHUMB", "MachineTHUMB", 0}, + {"TargetMachine", "MACHINE:X64", + "MachineX64", "MachineX64", 0}, + {"TargetMachine", "MACHINE:X86", + "MachineX86", "MachineX86", 0}, + + {"CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", + "MTA threading attribute", "MTAThreadingAttribute", 0}, + {"CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", + "STA threading attribute", "STAThreadingAttribute", 0}, + {"CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE", + "Default threading attribute", "DefaultThreadingAttribute", 0}, + + {"CLRImageType", "CLRIMAGETYPE:IJW", + "Force IJW image", "ForceIJWImage", 0}, + {"CLRImageType", "CLRIMAGETYPE:PURE", + "Force Pure IL Image", "ForcePureILImage", 0}, + {"CLRImageType", "CLRIMAGETYPE:SAFE", + "Force Safe IL Image", "ForceSafeILImage", 0}, + {"CLRImageType", "", + "Default image type", "Default", 0}, + + {"SignHash", "CLRSIGNHASH:SHA1", + "SHA1", "SHA1", 0}, + {"SignHash", "CLRSIGNHASH:SHA256", + "SHA256", "SHA256", 0}, + {"SignHash", "CLRSIGNHASH:SHA384", + "SHA384", "SHA384", 0}, + {"SignHash", "CLRSIGNHASH:SHA512", + "SHA512", "SHA512", 0}, + + {"LinkErrorReporting", "ERRORREPORT:PROMPT", + "PromptImmediately", "PromptImmediately", 0}, + {"LinkErrorReporting", "ERRORREPORT:QUEUE", + "Queue For Next Login", "QueueForNextLogin", 0}, + {"LinkErrorReporting", "ERRORREPORT:SEND", + "Send Error Report", "SendErrorReport", 0}, + {"LinkErrorReporting", "ERRORREPORT:NONE", + "No Error Report", "NoErrorReport", 0}, + + {"CLRSupportLastError", "CLRSupportLastError", + "Enabled", "Enabled", 0}, + {"CLRSupportLastError", "CLRSupportLastError:NO", + "Disabled", "Disabled", 0}, + {"CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", + "System Dlls Only", "SystemDlls", 0}, + + + //Bool Properties + {"LinkIncremental", "INCREMENTAL:NO", "", "false", 0}, + {"LinkIncremental", "INCREMENTAL", "", "true", 0}, + {"SuppressStartupBanner", "NOLOGO", "", "true", 0}, + {"LinkStatus", "LTCG:NOSTATUS", "", "false", 0}, + {"LinkStatus", "LTCG:STATUS", "", "true", 0}, + {"PreventDllBinding", "ALLOWBIND:NO", "", "false", 0}, + {"PreventDllBinding", "ALLOWBIND", "", "true", 0}, + {"TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0}, + {"TreatLinkerWarningAsErrors", "WX", "", "true", 0}, + {"IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0}, + {"GenerateManifest", "MANIFEST:NO", "", "false", 0}, + {"GenerateManifest", "MANIFEST", "", "true", 0}, + {"AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0}, + {"UACUIAccess", "uiAccess='false'", "", "false", 0}, + {"UACUIAccess", "uiAccess='true'", "", "true", 0}, + {"ManifestEmbed", "manifest:embed", "", "true", 0}, + {"GenerateDebugInformation", "DEBUG", "", "true", 0}, + {"MapExports", "MAPINFO:EXPORTS", "", "true", 0}, + {"AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0}, + {"AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0}, + {"LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0}, + {"LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0}, + {"TerminalServerAware", "TSAWARE:NO", "", "false", 0}, + {"TerminalServerAware", "TSAWARE", "", "true", 0}, + {"SwapRunFromCD", "SWAPRUN:CD", "", "true", 0}, + {"SwapRunFromNET", "SWAPRUN:NET", "", "true", 0}, + {"OptimizeReferences", "OPT:NOREF", "", "false", 0}, + {"OptimizeReferences", "OPT:REF", "", "true", 0}, + {"EnableCOMDATFolding", "OPT:NOICF", "", "false", 0}, + {"EnableCOMDATFolding", "OPT:ICF", "", "true", 0}, + {"IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0}, + {"AppContainer", "APPCONTAINER", "", "true", 0}, + {"WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0}, + {"WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0}, + {"NoEntryPoint", "NOENTRY", "", "true", 0}, + {"SetChecksum", "RELEASE", "", "true", 0}, + {"RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0}, + {"RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0}, + {"FixedBaseAddress", "FIXED:NO", "", "false", 0}, + {"FixedBaseAddress", "FIXED", "", "true", 0}, + {"DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0}, + {"DataExecutionPrevention", "NXCOMPAT", "", "true", 0}, + {"TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0}, + {"SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0}, + {"SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0}, + {"Profile", "PROFILE", "", "true", 0}, + {"LinkDelaySign", "DELAYSIGN:NO", "", "false", 0}, + {"LinkDelaySign", "DELAYSIGN", "", "true", 0}, + {"CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0}, + {"CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0}, + {"DetectOneDefinitionRule", "ODR", "", "true", 0}, + {"ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0}, + {"ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0}, + {"LinkDLL", "DLL", "", "true", 0}, + + //Bool Properties With Argument + {"EnableUAC", "MANIFESTUAC:NO", "", "false", 0}, + {"EnableUAC", "MANIFESTUAC:", "", "true", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, + {"UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "", + cmVS7FlagTable::UserValueRequired}, + {"GenerateMapFile", "MAP", "", "true", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, + {"MapFileName", "MAP:", "Generate Map File", "", + cmVS7FlagTable::UserValueRequired}, + + //String List Properties + {"AdditionalLibraryDirectories", "LIBPATH:", + "Additional Library Directories", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + // Skip [AdditionalDependencies] - no command line Switch. + {"IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:", + "Ignore Specific Default Libraries", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"AddModuleNamesToAssembly", "ASSEMBLYMODULE:", + "Add Module to Assembly", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"EmbedManagedResourceFile", "ASSEMBLYRESOURCE:", + "Embed Managed Resource File", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"ForceSymbolReferences", "INCLUDE:", + "Force Symbol References", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"DelayLoadDLLs", "DELAYLOAD:", + "Delay Loaded Dlls", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", + "Assembly Link Resource", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"AdditionalManifestDependencies", "MANIFESTDEPENDENCY:", + "Additional Manifest Dependencies", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"ManifestInput", "manifestinput:", + "Manifest Input", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + + //String Properties + {"OutputFile", "OUT:", + "Output File", + "", cmVS7FlagTable::UserValue}, + {"Version", "VERSION:", + "Version", + "", cmVS7FlagTable::UserValue}, + {"SpecifySectionAttributes", "SECTION:", + "Specify Section Attributes", + "", cmVS7FlagTable::UserValue}, + {"MSDOSStubFileName", "STUB:", + "MS-DOS Stub File Name", + "", cmVS7FlagTable::UserValue}, + // Skip [TrackerLogDirectory] - no command line Switch. + {"ModuleDefinitionFile", "DEF:", + "Module Definition File", + "", cmVS7FlagTable::UserValue}, + {"ManifestFile", "ManifestFile:", + "Manifest File", + "", cmVS7FlagTable::UserValue}, + {"ProgramDatabaseFile", "PDB:", + "Generate Program Database File", + "", cmVS7FlagTable::UserValue}, + {"StripPrivateSymbols", "PDBSTRIPPED:", + "Strip Private Symbols", + "", cmVS7FlagTable::UserValue}, + // Skip [MapFileName] - no command line Switch. + // Skip [MinimumRequiredVersion] - no command line Switch. + {"HeapReserveSize", "HEAP:", + "Heap Reserve Size", + "", cmVS7FlagTable::UserValue}, + // Skip [HeapCommitSize] - no command line Switch. + {"StackReserveSize", "STACK:", + "Stack Reserve Size", + "", cmVS7FlagTable::UserValue}, + // Skip [StackCommitSize] - no command line Switch. + {"FunctionOrder", "ORDER:@", + "Function Order", + "", cmVS7FlagTable::UserValue}, + {"ProfileGuidedDatabase", "PGD:", + "Profile Guided Database", + "", cmVS7FlagTable::UserValue}, + {"MidlCommandFile", "MIDL:@", + "MIDL Commands", + "", cmVS7FlagTable::UserValue}, + {"MergedIDLBaseFileName", "IDLOUT:", + "Merged IDL Base File Name", + "", cmVS7FlagTable::UserValue}, + {"TypeLibraryFile", "TLBOUT:", + "Type Library", + "", cmVS7FlagTable::UserValue}, + {"WindowsMetadataFile", "WINMDFILE:", + "Windows Metadata File", + "", cmVS7FlagTable::UserValue}, + {"WindowsMetadataLinkKeyFile", "WINMDKEYFILE:", + "Windows Metadata Key File", + "", cmVS7FlagTable::UserValue}, + {"WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:", + "Windows Metadata Key Container", + "", cmVS7FlagTable::UserValue}, + {"EntryPointSymbol", "ENTRY:", + "Entry Point", + "", cmVS7FlagTable::UserValue}, + {"BaseAddress", "BASE:", + "Base Address", + "", cmVS7FlagTable::UserValue}, + {"ImportLibrary", "IMPLIB:", + "Import Library", + "", cmVS7FlagTable::UserValue}, + {"MergeSections", "MERGE:", + "Merge Sections", + "", cmVS7FlagTable::UserValue}, + {"LinkKeyFile", "KEYFILE:", + "Key File", + "", cmVS7FlagTable::UserValue}, + {"KeyContainer", "KEYCONTAINER:", + "Key Container", + "", cmVS7FlagTable::UserValue}, + // Skip [AdditionalOptions] - no command line Switch. + {0,0,0,0,0} +}; diff --git a/Source/cmVS14MASMFlagTable.h b/Source/cmVS14MASMFlagTable.h new file mode 100644 index 0000000..dce846f --- /dev/null +++ b/Source/cmVS14MASMFlagTable.h @@ -0,0 +1,96 @@ +static cmVS7FlagTable cmVS14MASMFlagTable[] = +{ + + //Enum Properties + {"PreserveIdentifierCase", "", + "Default", "0", 0}, + {"PreserveIdentifierCase", "/Cp", + "Preserves Identifier Case (/Cp)", "1", 0}, + {"PreserveIdentifierCase", "/Cu", + "Maps all identifiers to upper case. (/Cu)", "2", 0}, + {"PreserveIdentifierCase", "/Cx", + "Preserves case in public and extern symbols. (/Cx)", "3", 0}, + + {"WarningLevel", "/W0", + "Warning Level 0 (/W0)", "0", 0}, + {"WarningLevel", "/W1", + "Warning Level 1 (/W1)", "1", 0}, + {"WarningLevel", "/W2", + "Warning Level 2 (/W2)", "2", 0}, + {"WarningLevel", "/W3", + "Warning Level 3 (/W3)", "3", 0}, + + {"PackAlignmentBoundary", "", + "Default", "0", 0}, + {"PackAlignmentBoundary", "/Zp1", + "One Byte Boundary (/Zp1)", "1", 0}, + {"PackAlignmentBoundary", "/Zp2", + "Two Byte Boundary (/Zp2)", "2", 0}, + {"PackAlignmentBoundary", "/Zp4", + "Four Byte Boundary (/Zp4)", "3", 0}, + {"PackAlignmentBoundary", "/Zp8", + "Eight Byte Boundary (/Zp8)", "4", 0}, + {"PackAlignmentBoundary", "/Zp16", + "Sixteen Byte Boundary (/Zp16)", "5", 0}, + + {"CallingConvention", "", + "Default", "0", 0}, + {"CallingConvention", "/Gd", + "Use C-style Calling Convention (/Gd)", "1", 0}, + {"CallingConvention", "/Gz", + "Use stdcall Calling Convention (/Gz)", "2", 0}, + {"CallingConvention", "/Gc", + "Use Pascal Calling Convention (/Gc)", "3", 0}, + + {"ErrorReporting", "/errorReport:prompt", + "Prompt to send report immediately (/errorReport:prompt)", "0", 0}, + {"ErrorReporting", "/errorReport:queue", + "Prompt to send report at the next logon (/errorReport:queue)", "1", 0}, + {"ErrorReporting", "/errorReport:send", + "Automatically send report (/errorReport:send)", "2", 0}, + {"ErrorReporting", "/errorReport:none", + "Do not send report (/errorReport:none)", "3", 0}, + + + //Bool Properties + {"NoLogo", "/nologo", "", "true", 0}, + {"GeneratePreprocessedSourceListing", "/EP", "", "true", 0}, + {"ListAllAvailableInformation", "/Sa", "", "true", 0}, + {"UseSafeExceptionHandlers", "/safeseh", "", "true", 0}, + {"AddFirstPassListing", "/Sf", "", "true", 0}, + {"EnableAssemblyGeneratedCodeListing", "/Sg", "", "true", 0}, + {"DisableSymbolTable", "/Sn", "", "true", 0}, + {"EnableFalseConditionalsInListing", "/Sx", "", "true", 0}, + {"TreatWarningsAsErrors", "/WX", "", "true", 0}, + {"MakeAllSymbolsPublic", "/Zf", "", "true", 0}, + {"GenerateDebugInformation", "/Zi", "", "true", 0}, + {"EnableMASM51Compatibility", "/Zm", "", "true", 0}, + {"PerformSyntaxCheckOnly", "/Zs", "", "true", 0}, + + //Bool Properties With Argument + + //String List Properties + {"PreprocessorDefinitions", "/D", + "Preprocessor Definitions", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"IncludePaths", "/I", + "Include Paths", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"BrowseFile", "/FR", + "Generate Browse Information File", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + // Skip [AdditionalDependencies] - no command line Switch. + + //String Properties + // Skip [Inputs] - no command line Switch. + {"ObjectFileName", "/Fo", + "Object File Name", + "", cmVS7FlagTable::UserValue}, + {"AssembledCodeListingFile", "/Fl", + "Assembled Code Listing File", + "", cmVS7FlagTable::UserValue}, + // Skip [CommandLineTemplate] - no command line Switch. + // Skip [ExecutionDescription] - no command line Switch. + // Skip [AdditionalOptions] - no command line Switch. + {0,0,0,0,0} +}; diff --git a/Source/cmVS14RCFlagTable.h b/Source/cmVS14RCFlagTable.h new file mode 100644 index 0000000..ebd8d65 --- /dev/null +++ b/Source/cmVS14RCFlagTable.h @@ -0,0 +1,7 @@ +static cmVS7FlagTable cmVS14RCFlagTable[] = +{ + //Bool Properties + {"NullTerminateStrings", "n", "", "true", 0}, + + {0,0,0,0,0} +}; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 72bb020..26fc317 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -21,48 +21,116 @@ #include "cmLocalVisualStudio7Generator.h" #include "cmCustomCommandGenerator.h" #include "cmVS10CLFlagTable.h" +#include "cmVS10RCFlagTable.h" #include "cmVS10LinkFlagTable.h" #include "cmVS10LibFlagTable.h" +#include "cmVS10MASMFlagTable.h" #include "cmVS11CLFlagTable.h" +#include "cmVS11RCFlagTable.h" #include "cmVS11LinkFlagTable.h" #include "cmVS11LibFlagTable.h" +#include "cmVS11MASMFlagTable.h" #include "cmVS12CLFlagTable.h" +#include "cmVS12RCFlagTable.h" #include "cmVS12LinkFlagTable.h" #include "cmVS12LibFlagTable.h" +#include "cmVS12MASMFlagTable.h" +#include "cmVS14CLFlagTable.h" +#include "cmVS14RCFlagTable.h" +#include "cmVS14LinkFlagTable.h" +#include "cmVS14LibFlagTable.h" +#include "cmVS14MASMFlagTable.h" #include <cmsys/auto_ptr.hxx> -static cmVS7FlagTable const* -cmVSGetCLFlagTable(cmLocalVisualStudioGenerator* lg) +cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetClFlagTable() const { - if(lg->GetVersion() >= cmLocalVisualStudioGenerator::VS12) - { return cmVS12CLFlagTable; } - else if(lg->GetVersion() == cmLocalVisualStudioGenerator::VS11) - { return cmVS11CLFlagTable; } - else - { return cmVS10CLFlagTable; } + if(this->MSTools) + { + cmLocalVisualStudioGenerator::VSVersion + v = this->LocalGenerator->GetVersion(); + if(v >= cmLocalVisualStudioGenerator::VS14) + { return cmVS14CLFlagTable; } + else if(v >= cmLocalVisualStudioGenerator::VS12) + { return cmVS12CLFlagTable; } + else if(v == cmLocalVisualStudioGenerator::VS11) + { return cmVS11CLFlagTable; } + else + { return cmVS10CLFlagTable; } + } + return 0; } -static cmVS7FlagTable const* -cmVSGetLibFlagTable(cmLocalVisualStudioGenerator* lg) +cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetRcFlagTable() const { - if(lg->GetVersion() >= cmLocalVisualStudioGenerator::VS12) - { return cmVS12LibFlagTable; } - else if(lg->GetVersion() == cmLocalVisualStudioGenerator::VS11) - { return cmVS11LibFlagTable; } - else - { return cmVS10LibFlagTable; } + if(this->MSTools) + { + cmLocalVisualStudioGenerator::VSVersion + v = this->LocalGenerator->GetVersion(); + if(v >= cmLocalVisualStudioGenerator::VS14) + { return cmVS14RCFlagTable; } + else if(v >= cmLocalVisualStudioGenerator::VS12) + { return cmVS12RCFlagTable; } + else if(v == cmLocalVisualStudioGenerator::VS11) + { return cmVS11RCFlagTable; } + else + { return cmVS10RCFlagTable; } + } + return 0; } -static cmVS7FlagTable const* -cmVSGetLinkFlagTable(cmLocalVisualStudioGenerator* lg) +cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetLibFlagTable() const { - if(lg->GetVersion() >= cmLocalVisualStudioGenerator::VS12) - { return cmVS12LinkFlagTable; } - else if(lg->GetVersion() == cmLocalVisualStudioGenerator::VS11) - { return cmVS11LinkFlagTable; } - else - { return cmVS10LinkFlagTable; } + if(this->MSTools) + { + cmLocalVisualStudioGenerator::VSVersion + v = this->LocalGenerator->GetVersion(); + if(v >= cmLocalVisualStudioGenerator::VS14) + { return cmVS14LibFlagTable; } + else if(v >= cmLocalVisualStudioGenerator::VS12) + { return cmVS12LibFlagTable; } + else if(v == cmLocalVisualStudioGenerator::VS11) + { return cmVS11LibFlagTable; } + else + { return cmVS10LibFlagTable; } + } + return 0; +} + +cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetLinkFlagTable() const +{ + if(this->MSTools) + { + cmLocalVisualStudioGenerator::VSVersion + v = this->LocalGenerator->GetVersion(); + if(v >= cmLocalVisualStudioGenerator::VS14) + { return cmVS14LinkFlagTable; } + else if(v >= cmLocalVisualStudioGenerator::VS12) + { return cmVS12LinkFlagTable; } + else if(v == cmLocalVisualStudioGenerator::VS11) + { return cmVS11LinkFlagTable; } + else + { return cmVS10LinkFlagTable; } + } + return 0; +} + +cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetMasmFlagTable() const +{ + if(this->MSTools) + { + cmLocalVisualStudioGenerator::VSVersion + v = this->LocalGenerator->GetVersion(); + if(v >= cmLocalVisualStudioGenerator::VS14) + { return cmVS14MASMFlagTable; } + else if(v >= cmLocalVisualStudioGenerator::VS12) + { return cmVS12MASMFlagTable; } + else if(v == cmLocalVisualStudioGenerator::VS11) + { return cmVS11MASMFlagTable; } + else + { return cmVS10MASMFlagTable; } + } + return 0; } static std::string cmVS10EscapeXML(std::string arg) @@ -112,7 +180,22 @@ cmVisualStudio10TargetGenerator(cmTarget* target, this->GlobalGenerator->CreateGUID(this->Name.c_str()); this->GUID = this->GlobalGenerator->GetGUID(this->Name.c_str()); this->Platform = gg->GetPlatformName(); + this->NsightTegra = gg->IsNsightTegra(); + for(int i = + sscanf(gg->GetNsightTegraVersion().c_str(), "%u.%u.%u.%u", + &this->NsightTegraVersion[0], &this->NsightTegraVersion[1], + &this->NsightTegraVersion[2], &this->NsightTegraVersion[3]); + i < 4; ++i) + { + this->NsightTegraVersion[i] = 0; + } + this->MSTools = !this->NsightTegra; + this->TargetCompileAsWinRT = false; this->BuildFileStream = 0; + this->IsMissingFiles = false; + this->DefaultArtifactDir = + this->Makefile->GetStartOutputDirectory() + std::string("/") + + this->LocalGenerator->GetTargetDirectory(*this->Target); } cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator() @@ -200,6 +283,14 @@ void cmVisualStudio10TargetGenerator::Generate() { return; } + if(!this->ComputeRcOptions()) + { + return; + } + if(!this->ComputeMasmOptions()) + { + return; + } if(!this->ComputeLinkOptions()) { return; @@ -230,11 +321,41 @@ void cmVisualStudio10TargetGenerator::Generate() "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"); this->WriteString(project_defaults.c_str(),0); + if(this->NsightTegra) + { + this->WriteString("<PropertyGroup Label=\"NsightTegraProject\">\n", 1); + if(this->NsightTegraVersion[0] >= 2) + { + // Nsight Tegra 2.0 uses project revision 8. + this->WriteString("<NsightTegraProjectRevisionNumber>" + "8" + "</NsightTegraProjectRevisionNumber>\n", 2); + // Tell newer versions to upgrade silently when loading. + this->WriteString("<NsightTegraUpgradeOnceWithoutPrompt>" + "true" + "</NsightTegraUpgradeOnceWithoutPrompt>\n", 2); + } + else + { + // Require Nsight Tegra 1.6 for JCompile support. + this->WriteString("<NsightTegraProjectRevisionNumber>" + "7" + "</NsightTegraProjectRevisionNumber>\n", 2); + } + this->WriteString("</PropertyGroup>\n", 1); + } + this->WriteProjectConfigurations(); this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1); this->WriteString("<ProjectGUID>", 2); (*this->BuildFileStream) << "{" << this->GUID << "}</ProjectGUID>\n"; + if(this->MSTools && this->Target->GetType() <= cmTarget::GLOBAL_TARGET) + { + this->WriteApplicationTypeSettings(); + this->VerifyNecessaryFiles(); + } + const char* vsProjectTypes = this->Target->GetProperty("VS_GLOBAL_PROJECT_TYPES"); if(vsProjectTypes) @@ -269,6 +390,11 @@ void cmVisualStudio10TargetGenerator::Generate() } } + if(this->Target->GetPropertyAsBool("VS_WINRT_COMPONENT")) + { + this->WriteString("<WinMDAssembly>true</WinMDAssembly>\n", 2); + } + const char* vsGlobalKeyword = this->Target->GetProperty("VS_GLOBAL_KEYWORD"); if(!vsGlobalKeyword) @@ -292,19 +418,20 @@ void cmVisualStudio10TargetGenerator::Generate() } this->WriteString("<Platform>", 2); - (*this->BuildFileStream) << this->Platform << "</Platform>\n"; + (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform) + << "</Platform>\n"; const char* projLabel = this->Target->GetProperty("PROJECT_LABEL"); if(!projLabel) { projLabel = this->Name.c_str(); } this->WriteString("<ProjectName>", 2); - (*this->BuildFileStream) << projLabel << "</ProjectName>\n"; + (*this->BuildFileStream) << cmVS10EscapeXML(projLabel) << "</ProjectName>\n"; if(const char* targetFrameworkVersion = this->Target->GetProperty( "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) { this->WriteString("<TargetFrameworkVersion>", 2); - (*this->BuildFileStream) << targetFrameworkVersion + (*this->BuildFileStream) << cmVS10EscapeXML(targetFrameworkVersion) << "</TargetFrameworkVersion>\n"; } this->WriteString("</PropertyGroup>\n", 1); @@ -324,9 +451,10 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteString("<ImportGroup Label=\"PropertySheets\">\n", 1); this->WriteString("<Import Project=\"" VS10_USER_PROPS "\"" " Condition=\"exists('" VS10_USER_PROPS "')\"" - " Label=\"LocalAppDataPlatform\" />", 2); + " Label=\"LocalAppDataPlatform\" />\n", 2); this->WriteString("</ImportGroup>\n", 1); this->WriteString("<PropertyGroup Label=\"UserMacros\" />\n", 1); + this->WriteWinRTPackageCertificateKeyFile(); this->WritePathAndIncrementalLinkOptions(); this->WriteItemDefinitionGroups(); this->WriteCustomCommands(); @@ -338,6 +466,7 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteString( "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\"" " />\n", 1); + this->WriteTargetSpecificReferences(); this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1); if (this->GlobalGenerator->IsMasmEnabled()) { @@ -417,6 +546,22 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup() } } +void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences() +{ + if(this->MSTools) + { + if(this->GlobalGenerator->TargetsWindowsPhone() && + this->GlobalGenerator->GetSystemVersion() == "8.0") + { + this->WriteString( + "<Import Project=\"" + "$(MSBuildExtensionsPath)\\Microsoft\\WindowsPhone\\v" + "$(TargetPlatformVersion)\\Microsoft.Cpp.WindowsPhone." + "$(TargetPlatformVersion).targets\" />\n", 1); + } + } +} + void cmVisualStudio10TargetGenerator::WriteWinRTReferences() { std::vector<std::string> references; @@ -425,6 +570,13 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences() { cmSystemTools::ExpandListArgument(vsWinRTReferences, references); } + + if(this->GlobalGenerator->TargetsWindowsPhone() && + this->GlobalGenerator->GetSystemVersion() == "8.0" && + references.empty()) + { + references.push_back("platform.winmd"); + } if(!references.empty()) { this->WriteString("<ItemGroup>\n", 1); @@ -456,7 +608,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurations() this->WriteString("<Configuration>", 3); (*this->BuildFileStream ) << *i << "</Configuration>\n"; this->WriteString("<Platform>", 3); - (*this->BuildFileStream) << this->Platform << "</Platform>\n"; + (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform) + << "</Platform>\n"; this->WriteString("</ProjectConfiguration>\n", 2); } this->WriteString("</ItemGroup>\n", 1); @@ -464,8 +617,6 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurations() void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() { - cmGlobalVisualStudio10Generator* gg = - static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); std::vector<std::string> *configs = static_cast<cmGlobalVisualStudio7Generator *> (this->GlobalGenerator)->GetConfigurations(); @@ -487,12 +638,29 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() configType += "StaticLibrary"; break; case cmTarget::EXECUTABLE: - configType += "Application"; + if(this->NsightTegra && + !this->Target->GetPropertyAsBool("ANDROID_GUI")) + { + // Android executables are .so too. + configType += "DynamicLibrary"; + } + else + { + configType += "Application"; + } break; case cmTarget::UTILITY: - configType += "Utility"; - break; case cmTarget::GLOBAL_TARGET: + if(this->NsightTegra) + { + // Tegra-Android platform does not understand "Utility". + configType += "StaticLibrary"; + } + else + { + configType += "Utility"; + } + break; case cmTarget::UNKNOWN_LIBRARY: case cmTarget::INTERFACE_LIBRARY: break; @@ -500,55 +668,94 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() configType += "</ConfigurationType>\n"; this->WriteString(configType.c_str(), 2); - const char* mfcFlag = - this->Target->GetMakefile()->GetDefinition("CMAKE_MFC_FLAG"); - std::string mfcFlagValue = mfcFlag ? mfcFlag : "0"; - - std::string useOfMfcValue = "false"; - if(mfcFlagValue == "1") - { - useOfMfcValue = "Static"; - } - else if(mfcFlagValue == "2") - { - useOfMfcValue = "Dynamic"; - } - std::string mfcLine = "<UseOfMfc>"; - mfcLine += useOfMfcValue + "</UseOfMfc>\n"; - this->WriteString(mfcLine.c_str(), 2); - - if((this->Target->GetType() <= cmTarget::OBJECT_LIBRARY && - this->ClOptions[*i]->UsingUnicode()) || - this->Target->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) - { - this->WriteString("<CharacterSet>Unicode</CharacterSet>\n", 2); - } - else if (this->Target->GetType() <= cmTarget::MODULE_LIBRARY && - this->ClOptions[*i]->UsingSBCS()) - { - this->WriteString("<CharacterSet>NotSet</CharacterSet>\n", 2); - } - else + if(this->MSTools) { - this->WriteString("<CharacterSet>MultiByte</CharacterSet>\n", 2); + this->WriteMSToolConfigurationValues(*i); } - if(const char* toolset = gg->GetPlatformToolset()) + else if(this->NsightTegra) { - std::string pts = "<PlatformToolset>"; - pts += toolset; - pts += "</PlatformToolset>\n"; - this->WriteString(pts.c_str(), 2); - } - if(this->Target->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) - { - this->WriteString("<WindowsAppContainer>true" - "</WindowsAppContainer>\n", 2); + this->WriteNsightTegraConfigurationValues(*i); } this->WriteString("</PropertyGroup>\n", 1); } } +//---------------------------------------------------------------------------- +void cmVisualStudio10TargetGenerator +::WriteMSToolConfigurationValues(std::string const& config) +{ + cmGlobalVisualStudio10Generator* gg = + static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + const char* mfcFlag = + this->Target->GetMakefile()->GetDefinition("CMAKE_MFC_FLAG"); + std::string mfcFlagValue = mfcFlag ? mfcFlag : "0"; + + std::string useOfMfcValue = "false"; + if(mfcFlagValue == "1") + { + useOfMfcValue = "Static"; + } + else if(mfcFlagValue == "2") + { + useOfMfcValue = "Dynamic"; + } + std::string mfcLine = "<UseOfMfc>"; + mfcLine += useOfMfcValue + "</UseOfMfc>\n"; + this->WriteString(mfcLine.c_str(), 2); + + if((this->Target->GetType() <= cmTarget::OBJECT_LIBRARY && + this->ClOptions[config]->UsingUnicode()) || + this->Target->GetPropertyAsBool("VS_WINRT_COMPONENT") || + this->GlobalGenerator->TargetsWindowsPhone() || + this->GlobalGenerator->TargetsWindowsStore() || + this->Target->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) + { + this->WriteString("<CharacterSet>Unicode</CharacterSet>\n", 2); + } + else if (this->Target->GetType() <= cmTarget::MODULE_LIBRARY && + this->ClOptions[config]->UsingSBCS()) + { + this->WriteString("<CharacterSet>NotSet</CharacterSet>\n", 2); + } + else + { + this->WriteString("<CharacterSet>MultiByte</CharacterSet>\n", 2); + } + if(const char* toolset = gg->GetPlatformToolset()) + { + std::string pts = "<PlatformToolset>"; + pts += toolset; + pts += "</PlatformToolset>\n"; + this->WriteString(pts.c_str(), 2); + } + if(this->Target->GetPropertyAsBool("VS_WINRT_COMPONENT") || + this->Target->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) + { + this->WriteString("<WindowsAppContainer>true" + "</WindowsAppContainer>\n", 2); + } +} + +//---------------------------------------------------------------------------- +void cmVisualStudio10TargetGenerator +::WriteNsightTegraConfigurationValues(std::string const&) +{ + cmGlobalVisualStudio10Generator* gg = + static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + const char* toolset = gg->GetPlatformToolset(); + std::string ntv = "<NdkToolchainVersion>"; + ntv += toolset? toolset : "Default"; + ntv += "</NdkToolchainVersion>\n"; + this->WriteString(ntv.c_str(), 2); + if(const char* api = this->Target->GetProperty("ANDROID_API")) + { + this->WriteString("<AndroidTargetAPI>", 2); + (*this->BuildFileStream ) << + "android-" << cmVS10EscapeXML(api) << "</AndroidTargetAPI>\n"; + } +} + void cmVisualStudio10TargetGenerator::WriteCustomCommands() { this->SourcesVisited.clear(); @@ -639,7 +846,7 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source, (*this->BuildFileStream ) << script << "</Command>\n"; this->WritePlatformConfigTag("AdditionalInputs", i->c_str(), 3); - (*this->BuildFileStream ) << source->GetFullPath(); + (*this->BuildFileStream ) << cmVS10EscapeXML(source->GetFullPath()); for(std::vector<std::string>::const_iterator d = ccg.GetDepends().begin(); d != ccg.GetDepends().end(); @@ -649,7 +856,7 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source, if(this->LocalGenerator->GetRealDependency(d->c_str(), i->c_str(), dep)) { this->ConvertToWindowsSlash(dep); - (*this->BuildFileStream ) << ";" << dep; + (*this->BuildFileStream ) << ";" << cmVS10EscapeXML(dep); } } (*this->BuildFileStream ) << ";%(AdditionalInputs)</AdditionalInputs>\n"; @@ -662,7 +869,7 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source, { std::string out = *o; this->ConvertToWindowsSlash(out); - (*this->BuildFileStream ) << sep << out; + (*this->BuildFileStream ) << sep << cmVS10EscapeXML(out); sep = ";"; } (*this->BuildFileStream ) << "</Outputs>\n"; @@ -752,6 +959,49 @@ void cmVisualStudio10TargetGenerator::WriteGroups() this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups); } + // Added files are images and the manifest. + if (!this->AddedFiles.empty()) + { + this->WriteString("<ItemGroup>\n", 1); + for(std::vector<std::string>::const_iterator + oi = this->AddedFiles.begin(); oi != this->AddedFiles.end(); ++oi) + { + std::string fileName = cmSystemTools::LowerCase( + cmSystemTools::GetFilenameName(*oi)); + if (fileName == "wmappmanifest.xml") + { + this->WriteString("<XML Include=\"", 2); + (*this->BuildFileStream) << *oi << "\">\n"; + this->WriteString("<Filter>Resource Files</Filter>\n", 3); + this->WriteString("</XML>\n", 2); + } + else if(cmSystemTools::GetFilenameExtension(fileName) == + ".appxmanifest") + { + this->WriteString("<AppxManifest Include=\"", 2); + (*this->BuildFileStream) << *oi << "\">\n"; + this->WriteString("<Filter>Resource Files</Filter>\n", 3); + this->WriteString("</AppxManifest>\n", 2); + } + else if(cmSystemTools::GetFilenameExtension(fileName) == + ".pfx") + { + this->WriteString("<None Include=\"", 2); + (*this->BuildFileStream) << *oi << "\">\n"; + this->WriteString("<Filter>Resource Files</Filter>\n", 3); + this->WriteString("</None>\n", 2); + } + else + { + this->WriteString("<Image Include=\"", 2); + (*this->BuildFileStream) << *oi << "\">\n"; + this->WriteString("<Filter>Resource Files</Filter>\n", 3); + this->WriteString("</Image>\n", 2); + } + } + this->WriteString("</ItemGroup>\n", 1); + } + std::vector<cmSourceFile const*> resxObjs; this->GeneratorTarget->GetResxSources(resxObjs, ""); if(!resxObjs.empty()) @@ -763,7 +1013,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() std::string obj = (*oi)->GetFullPath(); this->WriteString("<EmbeddedResource Include=\"", 2); this->ConvertToWindowsSlash(obj); - (*this->BuildFileStream ) << obj << "\">\n"; + (*this->BuildFileStream ) << cmVS10EscapeXML(obj) << "\">\n"; this->WriteString("<Filter>Resource Files</Filter>\n", 3); this->WriteString("</EmbeddedResource>\n", 2); } @@ -782,7 +1032,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() std::string obj = *oi; this->WriteString("<Object Include=\"", 2); this->ConvertToWindowsSlash(obj); - (*this->BuildFileStream ) << obj << "\">\n"; + (*this->BuildFileStream ) << cmVS10EscapeXML(obj) << "\">\n"; this->WriteString("<Filter>Object Libraries</Filter>\n", 3); this->WriteString("</Object>\n", 2); } @@ -825,7 +1075,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() this->WriteString("</Filter>\n", 2); } - if(!resxObjs.empty()) + if(!resxObjs.empty() || !this->AddedFiles.empty()) { this->WriteString("<Filter Include=\"Resource Files\">\n", 2); std::string guidName = "SG_Filter_Resource Files"; @@ -917,7 +1167,7 @@ WriteGroupSources(const char* name, std::string path = this->ConvertPath(source, s->RelativePath); this->ConvertToWindowsSlash(path); (*this->BuildFileStream) << name << " Include=\"" - << path; + << cmVS10EscapeXML(path); if(strlen(filter)) { (*this->BuildFileStream) << "\">\n"; @@ -934,8 +1184,129 @@ WriteGroupSources(const char* name, this->WriteString("</ItemGroup>\n", 1); } +void cmVisualStudio10TargetGenerator::WriteHeaderSource(cmSourceFile const* sf) +{ + if(this->IsResxHeader(sf->GetFullPath())) + { + this->WriteSource("ClInclude", sf, ">\n"); + this->WriteString("<FileType>CppForm</FileType>\n", 3); + this->WriteString("</ClInclude>\n", 2); + } + else + { + this->WriteSource("ClInclude", sf); + } +} + +void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) +{ + bool toolHasSettings = false; + std::string tool = "None"; + std::string shaderType; + std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); + if(ext == "hlsl") + { + tool = "FXCompile"; + // Figure out the type of shader compiler to use. + if(const char* st = sf->GetProperty("VS_SHADER_TYPE")) + { + shaderType = st; + toolHasSettings = true; + } + } + else if(ext == "jpg" || + ext == "png") + { + tool = "Image"; + } + else if(ext == "xml") + { + tool = "XML"; + } + if(this->NsightTegra) + { + // Nsight Tegra needs specific file types to check up-to-dateness. + std::string name = + cmSystemTools::LowerCase(sf->GetLocation().GetName()); + if(name == "androidmanifest.xml" || + name == "build.xml" || + name == "proguard.cfg" || + name == "proguard-project.txt" || + ext == "properties") + { + tool = "AndroidBuild"; + } + else if(ext == "java") + { + tool = "JCompile"; + } + else if(ext == "asm" || ext == "s") + { + tool = "ClCompile"; + } + } + + std::string deployContent; + if(this->GlobalGenerator->TargetsWindowsPhone() || + this->GlobalGenerator->TargetsWindowsStore()) + { + const char* content = sf->GetProperty("VS_DEPLOYMENT_CONTENT"); + if(content && *content) + { + toolHasSettings = true; + deployContent = content; + } + } + + if(toolHasSettings) + { + this->WriteSource(tool, sf, ">\n"); + + if(!deployContent.empty()) + { + std::vector<std::string> const* configs = + this->GlobalGenerator->GetConfigurations(); + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(deployContent); + for(size_t i = 0; i != configs->size(); ++i) + { + if(0 == strcmp(cge->Evaluate(this->Makefile, (*configs)[i]), "1")) + { + this->WriteString("<DeploymentContent Condition=\"" + "'$(Configuration)|$(Platform)'=='", 3); + (*this->BuildFileStream) << (*configs)[i] << "|" + << this->Platform << "'\">true"; + this->WriteString("</DeploymentContent>\n", 0); + } + else + { + this->WriteString("<ExcludedFromBuild Condition=\"" + "'$(Configuration)|$(Platform)'=='", 3); + (*this->BuildFileStream) << (*configs)[i] << "|" + << this->Platform << "'\">true"; + this->WriteString("</ExcludedFromBuild>\n", 0); + } + } + } + if(!shaderType.empty()) + { + this->WriteString("<ShaderType>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(shaderType) + << "</ShaderType>\n"; + } + + this->WriteString("</", 2); + (*this->BuildFileStream) << tool << ">\n"; + } + else + { + this->WriteSource(tool, sf); + } +} + void cmVisualStudio10TargetGenerator::WriteSource( - const char* tool, cmSourceFile const* sf, const char* end) + std::string const& tool, cmSourceFile const* sf, const char* end) { // Visual Studio tools append relative paths to the current dir, as in: // @@ -972,26 +1343,16 @@ void cmVisualStudio10TargetGenerator::WriteSource( } this->ConvertToWindowsSlash(sourceFile); this->WriteString("<", 2); - (*this->BuildFileStream ) << tool << " Include=\"" << sourceFile << "\""; - - if(sf->GetExtension() == "h" && - this->IsResxHeader(sf->GetFullPath())) - { - (*this->BuildFileStream ) << ">\n"; - this->WriteString("<FileType>CppForm</FileType>\n", 3); - this->WriteString("</ClInclude>\n", 2); - } - else - { - (*this->BuildFileStream ) << (end? end : " />\n"); - } + (*this->BuildFileStream ) << tool << " Include=\"" + << cmVS10EscapeXML(sourceFile) << "\"" + << (end? end : " />\n"); ToolSource toolSource = {sf, forceRelative}; this->Tools[tool].push_back(toolSource); } void cmVisualStudio10TargetGenerator::WriteSources( - const char* tool, std::vector<cmSourceFile const*> const& sources) + std::string const& tool, std::vector<cmSourceFile const*> const& sources) { for(std::vector<cmSourceFile const*>::const_iterator si = sources.begin(); si != sources.end(); ++si) @@ -1010,7 +1371,11 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() std::vector<cmSourceFile const*> headerSources; this->GeneratorTarget->GetHeaderSources(headerSources, ""); - this->WriteSources("ClInclude", headerSources); + for(std::vector<cmSourceFile const*>::const_iterator + si = headerSources.begin(); si != headerSources.end(); ++si) + { + this->WriteHeaderSource(*si); + } std::vector<cmSourceFile const*> idlSources; this->GeneratorTarget->GetIDLSources(idlSources, ""); this->WriteSources("Midl", idlSources); @@ -1022,12 +1387,12 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() si != objectSources.end(); ++si) { const std::string& lang = (*si)->GetLanguage(); - const char* tool = NULL; + std::string tool; if (lang == "C"|| lang == "CXX") { tool = "ClCompile"; } - else if (lang == "ASM_NASM" && + else if (lang == "ASM_MASM" && this->GlobalGenerator->IsMasmEnabled()) { tool = "MASM"; @@ -1037,7 +1402,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() tool = "ResourceCompile"; } - if (tool) + if (!tool.empty()) { this->WriteSource(tool, *si, " "); if (this->OutputSourceSpecificFlags(*si)) @@ -1056,6 +1421,14 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() } } + std::vector<cmSourceFile const*> manifestSources; + this->GeneratorTarget->GetAppManifest(manifestSources, ""); + this->WriteSources("AppxManifest", manifestSources); + + std::vector<cmSourceFile const*> certificateSources; + this->GeneratorTarget->GetCertificates(certificateSources, ""); + this->WriteSources("None", certificateSources); + std::vector<cmSourceFile const*> externalObjects; this->GeneratorTarget->GetExternalObjects(externalObjects, ""); for(std::vector<cmSourceFile const*>::iterator @@ -1093,7 +1466,11 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() std::vector<cmSourceFile const*> extraSources; this->GeneratorTarget->GetExtraSources(extraSources, ""); - this->WriteSources("None", extraSources); + for(std::vector<cmSourceFile const*>::const_iterator + si = extraSources.begin(); si != extraSources.end(); ++si) + { + this->WriteExtraSource(*si); + } // Add object library contents as external objects. std::vector<std::string> objs; @@ -1104,7 +1481,12 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() std::string obj = *oi; this->WriteString("<Object Include=\"", 2); this->ConvertToWindowsSlash(obj); - (*this->BuildFileStream ) << obj << "\" />\n"; + (*this->BuildFileStream ) << cmVS10EscapeXML(obj) << "\" />\n"; + } + + if (this->IsMissingFiles) + { + this->WriteMissingFiles(); } this->WriteString("</ItemGroup>\n", 1); @@ -1144,19 +1526,21 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( } // if the source file does not match the linker language // then force c or c++ + const char* compileAs = 0; if(needForceLang || (linkLanguage != lang)) { if(lang == "CXX") { // force a C++ file type - flags += " /TP "; + compileAs = "CompileAsCpp"; } else if(lang == "C") { // force to c - flags += " /TC "; + compileAs = "CompileAsC"; } } + bool noWinRT = this->TargetCompileAsWinRT && lang == "C"; bool hasFlags = false; // for the first time we need a new line if there is something // produced here. @@ -1190,7 +1574,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( } // if we have flags or defines for this config then // use them - if(flags.size() || configDefines.size()) + if(!flags.empty() || !configDefines.empty() || compileAs || noWinRT) { (*this->BuildFileStream ) << firstString; firstString = ""; // only do firstString once @@ -1198,8 +1582,21 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( cmVisualStudioGeneratorOptions clOptions(this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler, - cmVSGetCLFlagTable(this->LocalGenerator), 0, this); + this->GetClFlagTable(), 0, this); + if(compileAs) + { + clOptions.AddFlag("CompileAs", compileAs); + } + if(noWinRT) + { + clOptions.AddFlag("CompileAsWinRT", "false"); + } clOptions.Parse(flags.c_str()); + if(clOptions.HasFlag("AdditionalIncludeDirectories")) + { + clOptions.AppendFlag("AdditionalIncludeDirectories", + "%(AdditionalIncludeDirectories)"); + } clOptions.AddDefines(configDefines.c_str()); clOptions.SetConfiguration((*config).c_str()); clOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); @@ -1260,23 +1657,28 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() this->ConvertToWindowsSlash(outDir); this->WritePlatformConfigTag("OutDir", config->c_str(), 3); - *this->BuildFileStream << outDir + *this->BuildFileStream << cmVS10EscapeXML(outDir) << "</OutDir>\n"; this->WritePlatformConfigTag("IntDir", config->c_str(), 3); - *this->BuildFileStream << intermediateDir + *this->BuildFileStream << cmVS10EscapeXML(intermediateDir) << "</IntDir>\n"; + std::string name = + cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull); this->WritePlatformConfigTag("TargetName", config->c_str(), 3); - *this->BuildFileStream - << cmSystemTools::GetFilenameWithoutLastExtension( - targetNameFull.c_str()) - << "</TargetName>\n"; + *this->BuildFileStream << cmVS10EscapeXML(name) << "</TargetName>\n"; + std::string ext = + cmSystemTools::GetFilenameLastExtension(targetNameFull); + if(ext.empty()) + { + // An empty TargetExt causes a default extension to be used. + // A single "." appears to be treated as an empty extension. + ext = "."; + } this->WritePlatformConfigTag("TargetExt", config->c_str(), 3); - *this->BuildFileStream - << cmSystemTools::GetFilenameLastExtension(targetNameFull.c_str()) - << "</TargetExt>\n"; + *this->BuildFileStream << cmVS10EscapeXML(ext) << "</TargetExt>\n"; this->OutputLinkIncremental(*config); } @@ -1290,6 +1692,10 @@ void cmVisualStudio10TargetGenerator:: OutputLinkIncremental(std::string const& configName) { + if(!this->MSTools) + { + return; + } // static libraries and things greater than modules do not need // to set this option if(this->Target->GetType() == cmTarget::STATIC_LIBRARY @@ -1355,62 +1761,64 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( cmsys::auto_ptr<Options> pOptions( new Options(this->LocalGenerator, Options::Compiler, - cmVSGetCLFlagTable(this->LocalGenerator))); + this->GetClFlagTable())); Options& clOptions = *pOptions; std::string flags; - // collect up flags for - if(this->Target->GetType() < cmTarget::UTILITY) + const std::string& linkLanguage = + this->Target->GetLinkerLanguage(configName.c_str()); + if(linkLanguage.empty()) { - const std::string& linkLanguage = - this->Target->GetLinkerLanguage(configName.c_str()); - if(linkLanguage.empty()) - { - cmSystemTools::Error - ("CMake can not determine linker language for target: ", - this->Name.c_str()); - return false; - } - if(linkLanguage == "C" || linkLanguage == "CXX" - || linkLanguage == "Fortran") - { - std::string baseFlagVar = "CMAKE_"; - baseFlagVar += linkLanguage; - baseFlagVar += "_FLAGS"; - flags = this-> - Target->GetMakefile()->GetRequiredDefinition(baseFlagVar.c_str()); - std::string flagVar = baseFlagVar + std::string("_") + - cmSystemTools::UpperCase(configName); - flags += " "; - flags += this-> - Target->GetMakefile()->GetRequiredDefinition(flagVar.c_str()); - } - // set the correct language - if(linkLanguage == "C") - { - flags += " /TC "; - } - if(linkLanguage == "CXX") - { - flags += " /TP "; - } - this->LocalGenerator->AddCompileOptions(flags, this->Target, - linkLanguage, configName.c_str()); + cmSystemTools::Error + ("CMake can not determine linker language for target: ", + this->Name.c_str()); + return false; + } + if(linkLanguage == "C" || linkLanguage == "CXX" + || linkLanguage == "Fortran") + { + std::string baseFlagVar = "CMAKE_"; + baseFlagVar += linkLanguage; + baseFlagVar += "_FLAGS"; + flags = this-> + Target->GetMakefile()->GetRequiredDefinition(baseFlagVar.c_str()); + std::string flagVar = baseFlagVar + std::string("_") + + cmSystemTools::UpperCase(configName); + flags += " "; + flags += this-> + Target->GetMakefile()->GetRequiredDefinition(flagVar.c_str()); } + // set the correct language + if(linkLanguage == "C") + { + clOptions.AddFlag("CompileAs", "CompileAsC"); + } + if(linkLanguage == "CXX") + { + clOptions.AddFlag("CompileAs", "CompileAsCpp"); + } + this->LocalGenerator->AddCompileOptions(flags, this->Target, + linkLanguage, configName.c_str()); // Get preprocessor definitions for this directory. std::string defineFlags = this->Target->GetMakefile()->GetDefineFlags(); - clOptions.FixExceptionHandlingDefault(); - clOptions.AddFlag("PrecompiledHeader", "NotUsing"); - std::string asmLocation = configName + "/"; - clOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str()); + if(this->MSTools) + { + clOptions.FixExceptionHandlingDefault(); + clOptions.AddFlag("PrecompiledHeader", "NotUsing"); + std::string asmLocation = configName + "/"; + clOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str()); + } clOptions.Parse(flags.c_str()); clOptions.Parse(defineFlags.c_str()); std::vector<std::string> targetDefines; this->Target->GetCompileDefinitions(targetDefines, configName.c_str()); clOptions.AddDefines(targetDefines); - clOptions.SetVerboseMakefile( - this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); + if(this->MSTools) + { + clOptions.SetVerboseMakefile( + this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); + } // Add a definition for the configuration name. std::string configDefine = "CMAKE_INTDIR=\""; @@ -1422,6 +1830,36 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( clOptions.AddDefine(exportMacro); } + if (this->MSTools) + { + // If we have the VS_WINRT_COMPONENT set then force Compile as WinRT. + if (this->Target->GetPropertyAsBool("VS_WINRT_COMPONENT")) + { + clOptions.AddFlag("CompileAsWinRT", "true"); + // For WinRT components, add the _WINRT_DLL define to produce a lib + if (this->Target->GetType() == cmTarget::SHARED_LIBRARY || + this->Target->GetType() == cmTarget::MODULE_LIBRARY ) + { + clOptions.AddDefine("_WINRT_DLL"); + } + } + else if (this->GlobalGenerator->TargetsWindowsStore() || + this->GlobalGenerator->TargetsWindowsPhone()) + { + if (!clOptions.IsWinRt()) + { + clOptions.AddFlag("CompileAsWinRT", "false"); + } + } + if(const char* winRT = clOptions.GetFlag("CompileAsWinRT")) + { + if(cmSystemTools::IsOn(winRT)) + { + this->TargetCompileAsWinRT = true; + } + } + } + this->ClOptions[configName] = pOptions.release(); return true; } @@ -1434,63 +1872,166 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( Options& clOptions = *(this->ClOptions[configName]); this->WriteString("<ClCompile>\n", 2); clOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); - this->OutputIncludes(includes); + clOptions.AppendFlag("AdditionalIncludeDirectories", includes); + clOptions.AppendFlag("AdditionalIncludeDirectories", + "%(AdditionalIncludeDirectories)"); clOptions.OutputFlagMap(*this->BuildFileStream, " "); - - // If not in debug mode, write the DebugInformationFormat field - // without value so PDBs don't get generated uselessly. - if(!clOptions.IsDebug()) - { - this->WriteString("<DebugInformationFormat>" - "</DebugInformationFormat>\n", 3); - } - clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", "\n", "CXX"); - this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3); - // Specify the compiler program database file if configured. - std::string pdb = this->Target->GetCompilePDBPath(configName.c_str()); - if(!pdb.empty()) + if(this->MSTools) { - this->ConvertToWindowsSlash(pdb); - this->WriteString("<ProgramDataBaseFileName>", 3); - *this->BuildFileStream << cmVS10EscapeXML(pdb) - << "</ProgramDataBaseFileName>\n"; + this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3); + + // If not in debug mode, write the DebugInformationFormat field + // without value so PDBs don't get generated uselessly. + if(!clOptions.IsDebug()) + { + this->WriteString("<DebugInformationFormat>" + "</DebugInformationFormat>\n", 3); + } + + // Specify the compiler program database file if configured. + std::string pdb = this->Target->GetCompilePDBPath(configName.c_str()); + if(!pdb.empty()) + { + this->ConvertToWindowsSlash(pdb); + this->WriteString("<ProgramDataBaseFileName>", 3); + *this->BuildFileStream << cmVS10EscapeXML(pdb) + << "</ProgramDataBaseFileName>\n"; + } } this->WriteString("</ClCompile>\n", 2); } -void cmVisualStudio10TargetGenerator:: -OutputIncludes(std::vector<std::string> const & includes) +//---------------------------------------------------------------------------- +bool cmVisualStudio10TargetGenerator::ComputeRcOptions() { - this->WriteString("<AdditionalIncludeDirectories>", 3); - for(std::vector<std::string>::const_iterator i = includes.begin(); - i != includes.end(); ++i) + std::vector<std::string> const* configs = + this->GlobalGenerator->GetConfigurations(); + for(std::vector<std::string>::const_iterator i = configs->begin(); + i != configs->end(); ++i) { - std::string incDir = *i; - this->ConvertToWindowsSlash(incDir); - *this->BuildFileStream << cmVS10EscapeXML(incDir) << ";"; + if(!this->ComputeRcOptions(*i)) + { + return false; + } } - this->WriteString("%(AdditionalIncludeDirectories)" - "</AdditionalIncludeDirectories>\n", 0); + return true; } - +//---------------------------------------------------------------------------- +bool cmVisualStudio10TargetGenerator::ComputeRcOptions( + std::string const& configName) +{ + cmsys::auto_ptr<Options> pOptions( + new Options(this->LocalGenerator, Options::ResourceCompiler, + this->GetRcFlagTable())); + Options& rcOptions = *pOptions; + + std::string CONFIG = cmSystemTools::UpperCase(configName); + std::string rcConfigFlagsVar = std::string("CMAKE_RC_FLAGS_") + CONFIG; + std::string flags = + std::string(this->Makefile->GetSafeDefinition("CMAKE_RC_FLAGS")) + + std::string(" ") + + std::string(this->Makefile->GetSafeDefinition(rcConfigFlagsVar)); + + rcOptions.Parse(flags.c_str()); + this->RcOptions[configName] = pOptions.release(); + return true; +} void cmVisualStudio10TargetGenerator:: WriteRCOptions(std::string const& configName, std::vector<std::string> const & includes) { + if(!this->MSTools) + { + return; + } this->WriteString("<ResourceCompile>\n", 2); + + // Preprocessor definitions and includes are shared with clOptions. Options& clOptions = *(this->ClOptions[configName]); clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", "\n", "RC"); - this->OutputIncludes(includes); + + Options& rcOptions = *(this->RcOptions[configName]); + rcOptions.AppendFlag("AdditionalIncludeDirectories", includes); + rcOptions.AppendFlag("AdditionalIncludeDirectories", + "%(AdditionalIncludeDirectories)"); + rcOptions.OutputFlagMap(*this->BuildFileStream, " "); + rcOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); + this->WriteString("</ResourceCompile>\n", 2); } +//---------------------------------------------------------------------------- +bool cmVisualStudio10TargetGenerator::ComputeMasmOptions() +{ + if(!this->GlobalGenerator->IsMasmEnabled()) + { + return true; + } + std::vector<std::string> const* configs = + this->GlobalGenerator->GetConfigurations(); + for(std::vector<std::string>::const_iterator i = configs->begin(); + i != configs->end(); ++i) + { + if(!this->ComputeMasmOptions(*i)) + { + return false; + } + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmVisualStudio10TargetGenerator::ComputeMasmOptions( + std::string const& configName) +{ + cmsys::auto_ptr<Options> pOptions( + new Options(this->LocalGenerator, Options::MasmCompiler, + this->GetMasmFlagTable())); + Options& masmOptions = *pOptions; + + std::string CONFIG = cmSystemTools::UpperCase(configName); + std::string configFlagsVar = std::string("CMAKE_ASM_MASM_FLAGS_") + CONFIG; + std::string flags = + std::string(this->Makefile->GetSafeDefinition("CMAKE_ASM_MASM_FLAGS")) + + std::string(" ") + + std::string(this->Makefile->GetSafeDefinition(configFlagsVar)); + + masmOptions.Parse(flags.c_str()); + this->MasmOptions[configName] = pOptions.release(); + return true; +} + +void cmVisualStudio10TargetGenerator:: +WriteMasmOptions(std::string const& configName, + std::vector<std::string> const& includes) +{ + if(!this->MSTools || !this->GlobalGenerator->IsMasmEnabled()) + { + return; + } + this->WriteString("<MASM>\n", 2); + + // Preprocessor definitions and includes are shared with clOptions. + Options& clOptions = *(this->ClOptions[configName]); + clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", + "\n", "ASM_MASM"); + + Options& masmOptions = *(this->MasmOptions[configName]); + masmOptions.AppendFlag("IncludePaths", includes); + masmOptions.AppendFlag("IncludePaths", "%(IncludePaths)"); + masmOptions.OutputFlagMap(*this->BuildFileStream, " "); + masmOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); + + this->WriteString("</MASM>\n", 2); +} + void cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const& config) @@ -1508,12 +2049,68 @@ cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const& config) cmVisualStudioGeneratorOptions libOptions(this->LocalGenerator, cmVisualStudioGeneratorOptions::Linker, - cmVSGetLibFlagTable(this->LocalGenerator), 0, this); + this->GetLibFlagTable(), 0, this); libOptions.Parse(libflags.c_str()); libOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); libOptions.OutputFlagMap(*this->BuildFileStream, " "); this->WriteString("</Lib>\n", 2); } + + // We cannot generate metadata for static libraries. WindowsPhone + // and WindowsStore tools look at GenerateWindowsMetadata in the + // Link tool options even for static libraries. + if(this->GlobalGenerator->TargetsWindowsPhone() || + this->GlobalGenerator->TargetsWindowsStore()) + { + this->WriteString("<Link>\n", 2); + this->WriteString("<GenerateWindowsMetadata>false" + "</GenerateWindowsMetadata>\n", 3); + this->WriteString("</Link>\n", 2); + } +} + + +//---------------------------------------------------------------------------- +void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( + std::string const&) +{ + // Look through the sources for AndroidManifest.xml and use + // its location as the root source directory. + std::string rootDir = this->Makefile->GetCurrentDirectory(); + { + std::vector<cmSourceFile const*> extraSources; + this->GeneratorTarget->GetExtraSources(extraSources, ""); + for(std::vector<cmSourceFile const*>::const_iterator si = + extraSources.begin(); si != extraSources.end(); ++si) + { + if("androidmanifest.xml" == cmSystemTools::LowerCase( + (*si)->GetLocation().GetName())) + { + rootDir = (*si)->GetLocation().GetDirectory(); + break; + } + } + } + + // Tell MSBuild to launch Ant. + { + std::string antBuildPath = rootDir; + this->WriteString("<AntBuild>\n", 2); + this->WriteString("<AntBuildPath>", 3); + this->ConvertToWindowsSlash(antBuildPath); + (*this->BuildFileStream) << + cmVS10EscapeXML(antBuildPath) << "</AntBuildPath>\n"; + } + + { + std::string manifest_xml = rootDir + "/AndroidManifest.xml"; + this->ConvertToWindowsSlash(manifest_xml); + this->WriteString("<AndroidManifestLocation>", 3); + (*this->BuildFileStream) << + cmVS10EscapeXML(manifest_xml) << "</AndroidManifestLocation>\n"; + } + + this->WriteString("</AntBuild>\n", 2); } //---------------------------------------------------------------------------- @@ -1543,7 +2140,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) { cmsys::auto_ptr<Options> pOptions( new Options(this->LocalGenerator, Options::Linker, - cmVSGetLinkFlagTable(this->LocalGenerator), 0, this)); + this->GetLinkFlagTable(), 0, this)); Options& linkOptions = *pOptions; const std::string& linkLanguage = @@ -1567,16 +2164,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) { linkType = "EXE"; } - std::string stackVar = "CMAKE_"; - stackVar += linkLanguage; - stackVar += "_STACK_SIZE"; - const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str()); std::string flags; - if(stackVal) - { - flags += " /STACK:"; - flags += stackVal; - } std::string linkFlagVarBase = "CMAKE_"; linkFlagVarBase += linkType; linkFlagVarBase += "_LINKER_FLAGS"; @@ -1600,14 +2188,6 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) flags += " "; flags += flagsConfig; } - if ( this->Target->GetPropertyAsBool("WIN32_EXECUTABLE") ) - { - linkOptions.AddFlag("SubSystem", "Windows"); - } - else - { - linkOptions.AddFlag("SubSystem", "Console"); - } std::string standardLibsVar = "CMAKE_"; standardLibsVar += linkLanguage; standardLibsVar += "_STANDARD_LIBRARIES"; @@ -1628,6 +2208,9 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) } // Replace spaces in libs with ; cmSystemTools::ReplaceString(libs, " ", ";"); + std::vector<std::string> libVec; + cmSystemTools::ExpandListArgument(libs, libVec); + cmComputeLinkInformation* pcli = this->Target->GetLinkInformation(config.c_str()); if(!pcli) @@ -1639,37 +2222,22 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) } // add the libraries for the target to libs string cmComputeLinkInformation& cli = *pcli; - this->AddLibraries(cli, libs); - linkOptions.AddFlag("AdditionalDependencies", libs.c_str()); + this->AddLibraries(cli, libVec); + linkOptions.AddFlag("AdditionalDependencies", libVec); std::vector<std::string> const& ldirs = cli.GetDirectories(); - const char* sep = ""; - std::string linkDirs; + std::vector<std::string> linkDirs; for(std::vector<std::string>::const_iterator d = ldirs.begin(); d != ldirs.end(); ++d) { // first just full path - linkDirs += sep; - linkDirs += *d; - sep = ";"; - linkDirs += sep; + linkDirs.push_back(*d); // next path with configuration type Debug, Release, etc - linkDirs += *d; - linkDirs += "/$(Configuration)"; - linkDirs += sep; - } - linkDirs += "%(AdditionalLibraryDirectories)"; - linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs.c_str()); - linkOptions.AddFlag("AdditionalDependencies", libs.c_str()); - linkOptions.AddFlag("Version", ""); - if(linkOptions.IsDebug() || flags.find("/debug") != flags.npos) - { - linkOptions.AddFlag("GenerateDebugInformation", "true"); - } - else - { - linkOptions.AddFlag("GenerateDebugInformation", "false"); + linkDirs.push_back(*d + "/$(Configuration)"); } + linkDirs.push_back("%(AdditionalLibraryDirectories)"); + linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs); + std::string targetName; std::string targetNameSO; std::string targetNameFull; @@ -1688,20 +2256,103 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) config.c_str()); } - std::string pdb = this->Target->GetPDBDirectory(config.c_str()); - pdb += "/"; - pdb += targetNamePDB; - std::string imLib = this->Target->GetDirectory(config.c_str(), true); - imLib += "/"; - imLib += targetNameImport; + if(this->MSTools) + { + linkOptions.AddFlag("Version", ""); + + if ( this->Target->GetPropertyAsBool("WIN32_EXECUTABLE") ) + { + if (this->GlobalGenerator->TargetsWindowsCE()) + { + linkOptions.AddFlag("SubSystem", "WindowsCE"); + if (this->Target->GetType() == cmTarget::EXECUTABLE) + { + linkOptions.AddFlag("EntryPointSymbol", "WinMainCRTStartup"); + } + } + else + { + linkOptions.AddFlag("SubSystem", "Windows"); + } + } + else + { + if (this->GlobalGenerator->TargetsWindowsCE()) + { + linkOptions.AddFlag("SubSystem", "WindowsCE"); + if (this->Target->GetType() == cmTarget::EXECUTABLE) + { + linkOptions.AddFlag("EntryPointSymbol", "mainACRTStartup"); + } + } + else + { + linkOptions.AddFlag("SubSystem", "Console"); + }; + } + + if(const char* stackVal = + this->Makefile->GetDefinition("CMAKE_"+linkLanguage+"_STACK_SIZE")) + { + linkOptions.AddFlag("StackReserveSize", stackVal); + } + + if(linkOptions.IsDebug() || flags.find("/debug") != flags.npos) + { + linkOptions.AddFlag("GenerateDebugInformation", "true"); + } + else + { + linkOptions.AddFlag("GenerateDebugInformation", "false"); + } + std::string pdb = this->Target->GetPDBDirectory(config.c_str()); + pdb += "/"; + pdb += targetNamePDB; + std::string imLib = this->Target->GetDirectory(config.c_str(), true); + imLib += "/"; + imLib += targetNameImport; + + linkOptions.AddFlag("ImportLibrary", imLib.c_str()); + linkOptions.AddFlag("ProgramDataBaseFile", pdb.c_str()); + + // A Windows Runtime component uses internal .NET metadata, + // so does not have an import library. + if(this->Target->GetPropertyAsBool("VS_WINRT_COMPONENT")) + { + linkOptions.AddFlag("GenerateWindowsMetadata", "true"); + } + else if (this->GlobalGenerator->TargetsWindowsPhone() || + this->GlobalGenerator->TargetsWindowsStore()) + { + // WindowsPhone and WindowsStore components are in an app container + // and produce WindowsMetadata. If we are not producing a WINRT + // component, then do not generate the metadata here. + linkOptions.AddFlag("GenerateWindowsMetadata", "false"); + } + + if (this->GlobalGenerator->TargetsWindowsPhone() && + this->GlobalGenerator->GetSystemVersion() == "8.0") + { + // WindowsPhone 8.0 does not have ole32. + linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries", "ole32.lib"); + } + } + else if(this->NsightTegra) + { + linkOptions.AddFlag("SoName", targetNameSO.c_str()); + } - linkOptions.AddFlag("ImportLibrary", imLib.c_str()); - linkOptions.AddFlag("ProgramDataBaseFile", pdb.c_str()); linkOptions.Parse(flags.c_str()); - std::string def = this->GeneratorTarget->GetModuleDefinitionFile(""); - if(!def.empty()) + + if(this->MSTools) { - linkOptions.AddFlag("ModuleDefinitionFile", def.c_str()); + std::string def = this->GeneratorTarget->GetModuleDefinitionFile(""); + if(!def.empty()) + { + linkOptions.AddFlag("ModuleDefinitionFile", def.c_str()); + } + linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries", + "%(IgnoreSpecificDefaultLibraries)"); } this->LinkOptions[config] = pOptions.release(); @@ -1735,11 +2386,10 @@ cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& config) void cmVisualStudio10TargetGenerator::AddLibraries( cmComputeLinkInformation& cli, - std::string& libstring) + std::vector<std::string>& libVec) { typedef cmComputeLinkInformation::ItemVector ItemVector; ItemVector libs = cli.GetItems(); - const char* sep = ";"; for(ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l) { if(l->IsPath) @@ -1749,14 +2399,12 @@ void cmVisualStudio10TargetGenerator::AddLibraries( cmLocalGenerator::START_OUTPUT, cmLocalGenerator::UNCHANGED); this->ConvertToWindowsSlash(path); - libstring += sep; - libstring += path; + libVec.push_back(path); } else if (!l->Target || l->Target->GetType() != cmTarget::INTERFACE_LIBRARY) { - libstring += sep; - libstring += l->Value; + libVec.push_back(l->Value); } } } @@ -1766,6 +2414,11 @@ void cmVisualStudio10TargetGenerator:: WriteMidlOptions(std::string const& /*config*/, std::vector<std::string> const & includes) { + if(!this->MSTools) + { + return; + } + // This processes *any* of the .idl files specified in the project's file // list (and passed as the item metadata %(Filename) expressing the rule // input filename) into output files at the per-config *build* dir @@ -1782,7 +2435,14 @@ WriteMidlOptions(std::string const& /*config*/, // only). Perhaps there's something to be done to make this more automatic // on the CMake side? this->WriteString("<Midl>\n", 2); - this->OutputIncludes(includes); + this->WriteString("<AdditionalIncludeDirectories>", 3); + for(std::vector<std::string>::const_iterator i = includes.begin(); + i != includes.end(); ++i) + { + *this->BuildFileStream << cmVS10EscapeXML(*i) << ";"; + } + this->WriteString("%(AdditionalIncludeDirectories)" + "</AdditionalIncludeDirectories>\n", 0); this->WriteString("<OutputDirectory>$(IntDir)</OutputDirectory>\n", 3); this->WriteString("<HeaderFileName>%(Filename).h</HeaderFileName>\n", 3); this->WriteString( @@ -1807,6 +2467,11 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, "C", i->c_str()); + for(std::vector<std::string>::iterator ii = includes.begin(); + ii != includes.end(); ++ii) + { + this->ConvertToWindowsSlash(*ii); + } this->WritePlatformConfigTag("ItemDefinitionGroup", i->c_str(), 1); *this->BuildFileStream << "\n"; // output cl compile flags <ClCompile></ClCompile> @@ -1815,6 +2480,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() this->WriteClOptions(*i, includes); // output rc compile flags <ResourceCompile></ResourceCompile> this->WriteRCOptions(*i, includes); + this->WriteMasmOptions(*i, includes); } // output midl flags <Midl></Midl> this->WriteMidlOptions(*i, includes); @@ -1824,6 +2490,12 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() this->WriteLinkOptions(*i); // output lib flags <Lib></Lib> this->WriteLibOptions(*i); + if(this->NsightTegra && + this->Target->GetType() == cmTarget::EXECUTABLE && + this->Target->GetPropertyAsBool("ANDROID_GUI")) + { + this->WriteAntBuildOptions(*i); + } this->WriteString("</ItemDefinitionGroup>\n", 1); } } @@ -1914,7 +2586,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() path += dt->GetName(); path += ".vcxproj"; } - (*this->BuildFileStream) << path << "\">\n"; + (*this->BuildFileStream) << cmVS10EscapeXML(path) << "\">\n"; this->WriteString("<Project>", 3); (*this->BuildFileStream) << this->GlobalGenerator->GetGUID(name.c_str()) @@ -1924,6 +2596,67 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() this->WriteString("</ItemGroup>\n", 1); } +void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile() +{ + if((this->GlobalGenerator->TargetsWindowsStore() || + this->GlobalGenerator->TargetsWindowsPhone()) + && (cmTarget::EXECUTABLE == this->Target->GetType())) + { + std::string pfxFile; + std::vector<cmSourceFile const*> certificates; + this->GeneratorTarget->GetCertificates(certificates, ""); + for(std::vector<cmSourceFile const*>::const_iterator si = + certificates.begin(); si != certificates.end(); ++si) + { + pfxFile = this->ConvertPath((*si)->GetFullPath(), false); + this->ConvertToWindowsSlash(pfxFile); + break; + } + + if(this->IsMissingFiles && + !(this->GlobalGenerator->TargetsWindowsPhone() && + this->GlobalGenerator->GetSystemVersion() == "8.0")) + { + // Move the manifest to a project directory to avoid clashes + std::string artifactDir = + this->LocalGenerator->GetTargetDirectory(*this->Target); + this->ConvertToWindowsSlash(artifactDir); + this->WriteString("<PropertyGroup>\n", 1); + this->WriteString("<AppxPackageArtifactsDir>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(artifactDir) << + "\\</AppxPackageArtifactsDir>\n"; + this->WriteString("<ProjectPriFullPath>" + "$(TargetDir)resources.pri</ProjectPriFullPath>", 2); + + // If we are missing files and we don't have a certificate and + // aren't targeting WP8.0, add a default certificate + if(pfxFile.empty()) + { + std::string templateFolder = cmSystemTools::GetCMakeRoot() + + "/Templates/Windows"; + pfxFile = this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx"; + cmSystemTools::CopyAFile(templateFolder + "/Windows_TemporaryKey.pfx", + pfxFile, false); + this->ConvertToWindowsSlash(pfxFile); + this->AddedFiles.push_back(pfxFile); + } + + this->WriteString("<", 2); + (*this->BuildFileStream) << "PackageCertificateKeyFile>" + << pfxFile << "</PackageCertificateKeyFile>\n"; + this->WriteString("</PropertyGroup>\n", 1); + } + else if(!pfxFile.empty()) + { + this->WriteString("<PropertyGroup>\n", 1); + this->WriteString("<", 2); + (*this->BuildFileStream) << "PackageCertificateKeyFile>" + << pfxFile << "</PackageCertificateKeyFile>\n"; + this->WriteString("</PropertyGroup>\n", 1); + } + } +} + bool cmVisualStudio10TargetGenerator:: IsResxHeader(const std::string& headerFile) { @@ -1934,3 +2667,460 @@ bool cmVisualStudio10TargetGenerator:: expectedResxHeaders.find(headerFile); return it != expectedResxHeaders.end(); } + +void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings() +{ + bool isAppContainer = false; + bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone(); + bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore(); + std::string const& v = this->GlobalGenerator->GetSystemVersion(); + if(isWindowsPhone || isWindowsStore) + { + this->WriteString("<ApplicationType>", 2); + (*this->BuildFileStream) << (isWindowsPhone ? + "Windows Phone" : "Windows Store") + << "</ApplicationType>\n"; + this->WriteString("<ApplicationTypeRevision>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(v) + << "</ApplicationTypeRevision>\n"; + if(v == "8.1") + { + // Visual Studio 12.0 is necessary for building 8.1 apps + this->WriteString("<MinimumVisualStudioVersion>12.0" + "</MinimumVisualStudioVersion>\n", 2); + + if (this->Target->GetType() < cmTarget::UTILITY) + { + isAppContainer = true; + } + } + else if (v == "8.0") + { + // Visual Studio 11.0 is necessary for building 8.0 apps + this->WriteString("<MinimumVisualStudioVersion>11.0" + "</MinimumVisualStudioVersion>\n", 2); + + if (isWindowsStore && this->Target->GetType() < cmTarget::UTILITY) + { + isAppContainer = true; + } + else if (isWindowsPhone && + this->Target->GetType() == cmTarget::EXECUTABLE) + { + this->WriteString("<XapOutputs>true</XapOutputs>\n", 2); + this->WriteString("<XapFilename>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(this->Name.c_str()) << + "_$(Configuration)_$(Platform).xap</XapFilename>\n"; + } + } + } + if(isAppContainer) + { + this->WriteString("<AppContainerApplication>true" + "</AppContainerApplication>", 2); + } + else if (this->Platform == "ARM") + { + this->WriteString("<WindowsSDKDesktopARMSupport>true" + "</WindowsSDKDesktopARMSupport>", 2); + } +} + +void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles() +{ + // For Windows and Windows Phone executables, we will assume that if a + // manifest is not present that we need to add all the necessary files + if (this->Target->GetType() == cmTarget::EXECUTABLE) + { + std::vector<cmSourceFile const*> manifestSources; + this->GeneratorTarget->GetAppManifest(manifestSources, ""); + { + std::string const& v = this->GlobalGenerator->GetSystemVersion(); + if(this->GlobalGenerator->TargetsWindowsPhone()) + { + if (v == "8.0") + { + // Look through the sources for WMAppManifest.xml + std::vector<cmSourceFile const*> extraSources; + this->GeneratorTarget->GetExtraSources(extraSources, ""); + bool foundManifest = false; + for(std::vector<cmSourceFile const*>::const_iterator si = + extraSources.begin(); si != extraSources.end(); ++si) + { + // Need to do a lowercase comparison on the filename + if("wmappmanifest.xml" == cmSystemTools::LowerCase( + (*si)->GetLocation().GetName())) + { + foundManifest = true; + break; + } + } + if (!foundManifest) + { + this->IsMissingFiles = true; + } + } + else if (v == "8.1") + { + if(manifestSources.empty()) + { + this->IsMissingFiles = true; + } + } + } + else if (this->GlobalGenerator->TargetsWindowsStore()) + { + if (manifestSources.empty()) + { + if (v == "8.0") + { + this->IsMissingFiles = true; + } + else if (v == "8.1") + { + this->IsMissingFiles = true; + } + } + } + } + } +} + +void cmVisualStudio10TargetGenerator::WriteMissingFiles() +{ + std::string const& v = this->GlobalGenerator->GetSystemVersion(); + if(this->GlobalGenerator->TargetsWindowsPhone()) + { + if (v == "8.0") + { + this->WriteMissingFilesWP80(); + } + else if (v == "8.1") + { + this->WriteMissingFilesWP81(); + } + } + else if (this->GlobalGenerator->TargetsWindowsStore()) + { + if (v == "8.0") + { + this->WriteMissingFilesWS80(); + } + else if (v == "8.1") + { + this->WriteMissingFilesWS81(); + } + } +} + +void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80() +{ + std::string templateFolder = cmSystemTools::GetCMakeRoot() + + "/Templates/Windows"; + + // For WP80, the manifest needs to be in the same folder as the project + // this can cause an overwrite problem if projects aren't organized in + // folders + std::string manifestFile = this->Makefile->GetStartOutputDirectory() + + std::string("/WMAppManifest.xml"); + std::string artifactDir = + this->LocalGenerator->GetTargetDirectory(*this->Target); + this->ConvertToWindowsSlash(artifactDir); + std::string artifactDirXML = cmVS10EscapeXML(artifactDir); + std::string targetNameXML = cmVS10EscapeXML(this->Target->GetName()); + + cmGeneratedFileStream fout(manifestFile.c_str()); + fout.SetCopyIfDifferent(true); + + fout << + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<Deployment" + " xmlns=\"http://schemas.microsoft.com/windowsphone/2012/deployment\"" + " AppPlatformVersion=\"8.0\">\n" + "\t<DefaultLanguage xmlns=\"\" code=\"en-US\"/>\n" + "\t<App xmlns=\"\" ProductID=\"{" << this->GUID << "}\"" + " Title=\"CMake Test Program\" RuntimeType=\"Modern Native\"" + " Version=\"1.0.0.0\" Genre=\"apps.normal\" Author=\"CMake\"" + " Description=\"Default CMake App\" Publisher=\"CMake\"" + " PublisherID=\"{" << this->GUID << "}\">\n" + "\t\t<IconPath IsRelative=\"true\" IsResource=\"false\">" + << artifactDirXML << "\\ApplicationIcon.png</IconPath>\n" + "\t\t<Capabilities/>\n" + "\t\t<Tasks>\n" + "\t\t\t<DefaultTask Name=\"_default\"" + " ImagePath=\"" << targetNameXML << ".exe\" ImageParams=\"\" />\n" + "\t\t</Tasks>\n" + "\t\t<Tokens>\n" + "\t\t\t<PrimaryToken TokenID=\"" << targetNameXML << "Token\"" + " TaskName=\"_default\">\n" + "\t\t\t\t<TemplateFlip>\n" + "\t\t\t\t\t<SmallImageURI IsRelative=\"true\" IsResource=\"false\">" + << artifactDirXML << "\\SmallLogo.png</SmallImageURI>\n" + "\t\t\t\t\t<Count>0</Count>\n" + "\t\t\t\t\t<BackgroundImageURI IsRelative=\"true\" IsResource=\"false\">" + << artifactDirXML << "\\Logo.png</BackgroundImageURI>\n" + "\t\t\t\t</TemplateFlip>\n" + "\t\t\t</PrimaryToken>\n" + "\t\t</Tokens>\n" + "\t\t<ScreenResolutions>\n" + "\t\t\t<ScreenResolution Name=\"ID_RESOLUTION_WVGA\" />\n" + "\t\t</ScreenResolutions>\n" + "\t</App>\n" + "</Deployment>\n"; + + std::string sourceFile = this->ConvertPath(manifestFile, false); + this->ConvertToWindowsSlash(sourceFile); + this->WriteString("<Xml Include=\"", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(sourceFile) << "\">\n"; + this->WriteString("<SubType>Designer</SubType>\n", 3); + this->WriteString("</Xml>\n", 2); + this->AddedFiles.push_back(sourceFile); + + std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png"; + cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", + smallLogo, false); + this->ConvertToWindowsSlash(smallLogo); + this->WriteString("<Image Include=\"", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(smallLogo) << "\" />\n"; + this->AddedFiles.push_back(smallLogo); + + std::string logo = this->DefaultArtifactDir + "/Logo.png"; + cmSystemTools::CopyAFile(templateFolder + "/Logo.png", + logo, false); + this->ConvertToWindowsSlash(logo); + this->WriteString("<Image Include=\"", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(logo) << "\" />\n"; + this->AddedFiles.push_back(logo); + + std::string applicationIcon = + this->DefaultArtifactDir + "/ApplicationIcon.png"; + cmSystemTools::CopyAFile(templateFolder + "/ApplicationIcon.png", + applicationIcon, false); + this->ConvertToWindowsSlash(applicationIcon); + this->WriteString("<Image Include=\"", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(applicationIcon) << "\" />\n"; + this->AddedFiles.push_back(applicationIcon); +} + +void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81() +{ + std::string manifestFile = + this->DefaultArtifactDir + "/package.appxManifest"; + std::string artifactDir = + this->LocalGenerator->GetTargetDirectory(*this->Target); + this->ConvertToWindowsSlash(artifactDir); + std::string artifactDirXML = cmVS10EscapeXML(artifactDir); + std::string targetNameXML = cmVS10EscapeXML(this->Target->GetName()); + + cmGeneratedFileStream fout(manifestFile.c_str()); + fout.SetCopyIfDifferent(true); + + fout << + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\"" + " xmlns:m2=\"http://schemas.microsoft.com/appx/2013/manifest\"" + " xmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\">\n" + "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\"" + " Version=\"1.0.0.0\" />\n" + "\t<mp:PhoneIdentity PhoneProductId=\"" << this->GUID << "\"" + " PhonePublisherId=\"00000000-0000-0000-0000-000000000000\"/>\n" + "\t<Properties>\n" + "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n" + "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n" + "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n" + "\t</Properties>\n" + "\t<Prerequisites>\n" + "\t\t<OSMinVersion>6.3.1</OSMinVersion>\n" + "\t\t<OSMaxVersionTested>6.3.1</OSMaxVersionTested>\n" + "\t</Prerequisites>\n" + "\t<Resources>\n" + "\t\t<Resource Language=\"x-generate\" />\n" + "\t</Resources>\n" + "\t<Applications>\n" + "\t\t<Application Id=\"App\"" + " Executable=\"" << targetNameXML << ".exe\"" + " EntryPoint=\"" << targetNameXML << ".App\">\n" + "\t\t\t<m2:VisualElements\n" + "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n" + "\t\t\t\tDescription=\"" << targetNameXML << "\"\n" + "\t\t\t\tBackgroundColor=\"#336699\"\n" + "\t\t\t\tForegroundText=\"light\"\n" + "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n" + "\t\t\t\tSquare30x30Logo=\"" << artifactDirXML << "\\SmallLogo.png\">\n" + "\t\t\t\t<m2:DefaultTile ShortName=\"" << targetNameXML << "\">\n" + "\t\t\t\t\t<m2:ShowNameOnTiles>\n" + "\t\t\t\t\t\t<m2:ShowOn Tile=\"square150x150Logo\" />\n" + "\t\t\t\t\t</m2:ShowNameOnTiles>\n" + "\t\t\t\t</m2:DefaultTile>\n" + "\t\t\t\t<m2:SplashScreen" + " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n" + "\t\t\t</m2:VisualElements>\n" + "\t\t</Application>\n" + "\t</Applications>\n" + "</Package>\n"; + + this->WriteCommonMissingFiles(manifestFile); +} + +void cmVisualStudio10TargetGenerator::WriteMissingFilesWS80() +{ + std::string manifestFile = + this->DefaultArtifactDir + "/package.appxManifest"; + std::string artifactDir = + this->LocalGenerator->GetTargetDirectory(*this->Target); + this->ConvertToWindowsSlash(artifactDir); + std::string artifactDirXML = cmVS10EscapeXML(artifactDir); + std::string targetNameXML = cmVS10EscapeXML(this->Target->GetName()); + + cmGeneratedFileStream fout(manifestFile.c_str()); + fout.SetCopyIfDifferent(true); + + fout << + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\">\n" + "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\"" + " Version=\"1.0.0.0\" />\n" + "\t<Properties>\n" + "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n" + "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n" + "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n" + "\t</Properties>\n" + "\t<Prerequisites>\n" + "\t\t<OSMinVersion>6.2.1</OSMinVersion>\n" + "\t\t<OSMaxVersionTested>6.2.1</OSMaxVersionTested>\n" + "\t</Prerequisites>\n" + "\t<Resources>\n" + "\t\t<Resource Language=\"x-generate\" />\n" + "\t</Resources>\n" + "\t<Applications>\n" + "\t\t<Application Id=\"App\"" + " Executable=\"" << targetNameXML << ".exe\"" + " EntryPoint=\"" << targetNameXML << ".App\">\n" + "\t\t\t<VisualElements" + " DisplayName=\"" << targetNameXML << "\"" + " Description=\"" << targetNameXML << "\"" + " BackgroundColor=\"#336699\" ForegroundText=\"light\"" + " Logo=\"" << artifactDirXML << "\\Logo.png\"" + " SmallLogo=\"" << artifactDirXML << "\\SmallLogo.png\">\n" + "\t\t\t\t<DefaultTile ShowName=\"allLogos\"" + " ShortName=\"" << targetNameXML << "\" />\n" + "\t\t\t\t<SplashScreen" + " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n" + "\t\t\t</VisualElements>\n" + "\t\t</Application>\n" + "\t</Applications>\n" + "</Package>\n"; + + this->WriteCommonMissingFiles(manifestFile); +} + +void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81() +{ + std::string manifestFile = + this->DefaultArtifactDir + "/package.appxManifest"; + std::string artifactDir = + this->LocalGenerator->GetTargetDirectory(*this->Target); + this->ConvertToWindowsSlash(artifactDir); + std::string artifactDirXML = cmVS10EscapeXML(artifactDir); + std::string targetNameXML = cmVS10EscapeXML(this->Target->GetName()); + + cmGeneratedFileStream fout(manifestFile.c_str()); + fout.SetCopyIfDifferent(true); + + fout << + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\"" + " xmlns:m2=\"http://schemas.microsoft.com/appx/2013/manifest\">\n" + "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\"" + " Version=\"1.0.0.0\" />\n" + "\t<Properties>\n" + "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n" + "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n" + "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n" + "\t</Properties>\n" + "\t<Prerequisites>\n" + "\t\t<OSMinVersion>6.3</OSMinVersion>\n" + "\t\t<OSMaxVersionTested>6.3</OSMaxVersionTested>\n" + "\t</Prerequisites>\n" + "\t<Resources>\n" + "\t\t<Resource Language=\"x-generate\" />\n" + "\t</Resources>\n" + "\t<Applications>\n" + "\t\t<Application Id=\"App\"" + " Executable=\"" << targetNameXML << ".exe\"" + " EntryPoint=\"" << targetNameXML << ".App\">\n" + "\t\t\t<m2:VisualElements\n" + "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n" + "\t\t\t\tDescription=\"" << targetNameXML << "\"\n" + "\t\t\t\tBackgroundColor=\"#336699\"\n" + "\t\t\t\tForegroundText=\"light\"\n" + "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n" + "\t\t\t\tSquare30x30Logo=\"" << artifactDirXML << "\\SmallLogo.png\">\n" + "\t\t\t\t<m2:DefaultTile ShortName=\"" << targetNameXML << "\">\n" + "\t\t\t\t\t<m2:ShowNameOnTiles>\n" + "\t\t\t\t\t\t<m2:ShowOn Tile=\"square150x150Logo\" />\n" + "\t\t\t\t\t</m2:ShowNameOnTiles>\n" + "\t\t\t\t</m2:DefaultTile>\n" + "\t\t\t\t<m2:SplashScreen" + " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n" + "\t\t\t</m2:VisualElements>\n" + "\t\t</Application>\n" + "\t</Applications>\n" + "</Package>\n"; + + this->WriteCommonMissingFiles(manifestFile); +} + +void +cmVisualStudio10TargetGenerator +::WriteCommonMissingFiles(const std::string& manifestFile) +{ + std::string templateFolder = cmSystemTools::GetCMakeRoot() + + "/Templates/Windows"; + + std::string sourceFile = this->ConvertPath(manifestFile, false); + this->ConvertToWindowsSlash(sourceFile); + this->WriteString("<AppxManifest Include=\"", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(sourceFile) << "\">\n"; + this->WriteString("<SubType>Designer</SubType>\n", 3); + this->WriteString("</AppxManifest>\n", 2); + this->AddedFiles.push_back(sourceFile); + + std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png"; + cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", + smallLogo, false); + this->ConvertToWindowsSlash(smallLogo); + this->WriteString("<Image Include=\"", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(smallLogo) << "\" />\n"; + this->AddedFiles.push_back(smallLogo); + + std::string logo = this->DefaultArtifactDir + "/Logo.png"; + cmSystemTools::CopyAFile(templateFolder + "/Logo.png", + logo, false); + this->ConvertToWindowsSlash(logo); + this->WriteString("<Image Include=\"", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(logo) << "\" />\n"; + this->AddedFiles.push_back(logo); + + std::string storeLogo = this->DefaultArtifactDir + "/StoreLogo.png"; + cmSystemTools::CopyAFile(templateFolder + "/StoreLogo.png", + storeLogo, false); + this->ConvertToWindowsSlash(storeLogo); + this->WriteString("<Image Include=\"", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(storeLogo) << "\" />\n"; + this->AddedFiles.push_back(storeLogo); + + std::string splashScreen = this->DefaultArtifactDir + "/SplashScreen.png"; + cmSystemTools::CopyAFile(templateFolder + "/SplashScreen.png", + splashScreen, false); + this->ConvertToWindowsSlash(splashScreen); + this->WriteString("<Image Include=\"", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(splashScreen) << "\" />\n"; + this->AddedFiles.push_back(splashScreen); + + // This file has already been added to the build so don't copy it + std::string keyFile = this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx"; + this->ConvertToWindowsSlash(keyFile); + this->WriteString("<None Include=\"", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(keyFile) << "\" />\n"; +} diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index d72c6fd..a02dfa8 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -23,6 +23,7 @@ class cmCustomCommand; class cmLocalVisualStudio7Generator; class cmComputeLinkInformation; class cmVisualStudioGeneratorOptions; +struct cmIDEFlagTable; #include "cmSourceGroup.h" class cmVisualStudio10TargetGenerator @@ -55,29 +56,48 @@ private: void WriteString(const char* line, int indentLevel); void WriteProjectConfigurations(); void WriteProjectConfigurationValues(); - void WriteSource(const char* tool, cmSourceFile const* sf, + void WriteMSToolConfigurationValues(std::string const& config); + void WriteHeaderSource(cmSourceFile const* sf); + void WriteExtraSource(cmSourceFile const* sf); + void WriteNsightTegraConfigurationValues(std::string const& config); + void WriteSource(std::string const& tool, cmSourceFile const* sf, const char* end = 0); - void WriteSources(const char* tool, + void WriteSources(std::string const& tool, std::vector<cmSourceFile const*> const&); void WriteAllSources(); void WriteDotNetReferences(); void WriteEmbeddedResourceGroup(); void WriteWinRTReferences(); + void WriteWinRTPackageCertificateKeyFile(); void WritePathAndIncrementalLinkOptions(); void WriteItemDefinitionGroups(); + void VerifyNecessaryFiles(); + void WriteMissingFiles(); + void WriteMissingFilesWP80(); + void WriteMissingFilesWP81(); + void WriteMissingFilesWS80(); + void WriteMissingFilesWS81(); + void WriteCommonMissingFiles(const std::string& manifestFile); + void WriteTargetSpecificReferences(); bool ComputeClOptions(); bool ComputeClOptions(std::string const& configName); void WriteClOptions(std::string const& config, std::vector<std::string> const & includes); + bool ComputeRcOptions(); + bool ComputeRcOptions(std::string const& config); void WriteRCOptions(std::string const& config, std::vector<std::string> const & includes); + bool ComputeMasmOptions(); + bool ComputeMasmOptions(std::string const& config); + void WriteMasmOptions(std::string const& config, + std::vector<std::string> const& includes); bool ComputeLinkOptions(); bool ComputeLinkOptions(std::string const& config); void WriteLinkOptions(std::string const& config); void WriteMidlOptions(std::string const& config, std::vector<std::string> const & includes); - void OutputIncludes(std::vector<std::string> const & includes); + void WriteAntBuildOptions(std::string const& config); void OutputLinkIncremental(std::string const& configName); void WriteCustomRule(cmSourceFile const* source, cmCustomCommand const & command); @@ -85,8 +105,10 @@ private: void WriteCustomCommand(cmSourceFile const* sf); void WriteGroups(); void WriteProjectReferences(); + void WriteApplicationTypeSettings(); bool OutputSourceSpecificFlags(cmSourceFile const* source); - void AddLibraries(cmComputeLinkInformation& cli, std::string& libstring); + void AddLibraries(cmComputeLinkInformation& cli, + std::vector<std::string>& libVec); void WriteLibOptions(std::string const& config); void WriteEvents(std::string const& configName); void WriteEvent(const char* name, @@ -98,10 +120,18 @@ private: const std::vector<cmSourceGroup>& allGroups); bool IsResxHeader(const std::string& headerFile); + cmIDEFlagTable const* GetClFlagTable() const; + cmIDEFlagTable const* GetRcFlagTable() const; + cmIDEFlagTable const* GetLibFlagTable() const; + cmIDEFlagTable const* GetLinkFlagTable() const; + cmIDEFlagTable const* GetMasmFlagTable() const; + private: typedef cmVisualStudioGeneratorOptions Options; typedef std::map<std::string, Options*> OptionsMap; OptionsMap ClOptions; + OptionsMap RcOptions; + OptionsMap MasmOptions; OptionsMap LinkOptions; std::string PathToVcxproj; cmTarget* Target; @@ -110,10 +140,17 @@ private: std::string Platform; std::string GUID; std::string Name; + bool MSTools; + bool NsightTegra; + int NsightTegraVersion[4]; + bool TargetCompileAsWinRT; cmGlobalVisualStudio10Generator* GlobalGenerator; cmGeneratedFileStream* BuildFileStream; cmLocalVisualStudio7Generator* LocalGenerator; std::set<cmSourceFile const*> SourcesVisited; + bool IsMissingFiles; + std::vector<std::string> AddedFiles; + std::string DefaultArtifactDir; typedef std::map<std::string, ToolSources> ToolSourceMap; ToolSourceMap Tools; diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 81adb56..cdc8879 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -3,9 +3,9 @@ #include <cmsys/System.h> #include "cmVisualStudio10TargetGenerator.h" -inline std::string cmVisualStudio10GeneratorOptionsEscapeForXML(const char* s) +static +std::string cmVisualStudio10GeneratorOptionsEscapeForXML(std::string ret) { - std::string ret = s; cmSystemTools::ReplaceString(ret, ";", "%3B"); cmSystemTools::ReplaceString(ret, "&", "&"); cmSystemTools::ReplaceString(ret, "<", "<"); @@ -13,9 +13,9 @@ inline std::string cmVisualStudio10GeneratorOptionsEscapeForXML(const char* s) return ret; } -inline std::string cmVisualStudioGeneratorOptionsEscapeForXML(const char* s) +static +std::string cmVisualStudioGeneratorOptionsEscapeForXML(std::string ret) { - std::string ret = s; cmSystemTools::ReplaceString(ret, "&", "&"); cmSystemTools::ReplaceString(ret, "\"", """); cmSystemTools::ReplaceString(ret, "<", "<"); @@ -68,6 +68,7 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault() case cmLocalVisualStudioGenerator::VS10: case cmLocalVisualStudioGenerator::VS11: case cmLocalVisualStudioGenerator::VS12: + case cmLocalVisualStudioGenerator::VS14: // by default VS puts <ExceptionHandling></ExceptionHandling> empty // for a project, to make our projects look the same put a new line // and space over for the closing </ExceptionHandling> as the default @@ -106,6 +107,12 @@ bool cmVisualStudioGeneratorOptions::IsDebug() const } //---------------------------------------------------------------------------- +bool cmVisualStudioGeneratorOptions::IsWinRt() const +{ + return this->FlagMap.find("CompileAsWinRT") != this->FlagMap.end(); +} + +//---------------------------------------------------------------------------- bool cmVisualStudioGeneratorOptions::UsingUnicode() const { // Look for the a _UNICODE definition. @@ -268,7 +275,7 @@ cmVisualStudioGeneratorOptions // Escape this flag for the IDE. if(this->Version >= cmLocalVisualStudioGenerator::VS10) { - define = cmVisualStudio10GeneratorOptionsEscapeForXML(define.c_str()); + define = cmVisualStudio10GeneratorOptionsEscapeForXML(define); if(lang == "RC") { @@ -277,7 +284,7 @@ cmVisualStudioGeneratorOptions } else { - define = cmVisualStudioGeneratorOptionsEscapeForXML(define.c_str()); + define = cmVisualStudioGeneratorOptionsEscapeForXML(define); } // Store the flag in the project file. fout << sep << define; @@ -300,7 +307,7 @@ cmVisualStudioGeneratorOptions { if(this->Version >= cmLocalVisualStudioGenerator::VS10) { - for(std::map<std::string, std::string>::iterator m = this->FlagMap.begin(); + for(std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin(); m != this->FlagMap.end(); ++m) { fout << indent; @@ -316,20 +323,30 @@ cmVisualStudioGeneratorOptions { fout << "<" << m->first << ">"; } - fout << m->second; - if (m->first == "AdditionalIncludeDirectories") + const char* sep = ""; + for(std::vector<std::string>::iterator i = m->second.begin(); + i != m->second.end(); ++i) { - fout << ";%(AdditionalIncludeDirectories)"; + fout << sep << cmVisualStudio10GeneratorOptionsEscapeForXML(*i); + sep = ";"; } fout << "</" << m->first << ">\n"; } } else { - for(std::map<std::string, std::string>::iterator m = this->FlagMap.begin(); + for(std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin(); m != this->FlagMap.end(); ++m) { - fout << indent << m->first << "=\"" << m->second << "\"\n"; + fout << indent << m->first << "=\""; + const char* sep = ""; + for(std::vector<std::string>::iterator i = m->second.begin(); + i != m->second.end(); ++i) + { + fout << sep << cmVisualStudioGeneratorOptionsEscapeForXML(*i); + sep = ";"; + } + fout << "\"\n"; } } } @@ -358,14 +375,13 @@ cmVisualStudioGeneratorOptions { fout << "<AdditionalOptions>"; } - fout << this->FlagString.c_str() + fout << cmVisualStudio10GeneratorOptionsEscapeForXML(this->FlagString) << " %(AdditionalOptions)</AdditionalOptions>\n"; } else { fout << prefix << "AdditionalOptions=\""; - fout << - cmVisualStudioGeneratorOptionsEscapeForXML(this->FlagString.c_str()); + fout << cmVisualStudioGeneratorOptionsEscapeForXML(this->FlagString); fout << "\"" << suffix; } } diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index 214b893..9951033 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -27,6 +27,8 @@ public: enum Tool { Compiler, + ResourceCompiler, + MasmCompiler, Linker, FortranCompiler }; @@ -51,6 +53,7 @@ public: bool UsingSBCS() const; bool IsDebug() const; + bool IsWinRt() const; // Write options to output. void OutputPreprocessorDefinitions(std::ostream& fout, const char* prefix, diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index 7d2eead..851c4cb 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -10,7 +10,7 @@ See the License for more information. ============================================================================*/ #include "cmWhileCommand.h" -#include "cmIfCommand.h" +#include "cmConditionEvaluator.h" bool cmWhileFunctionBlocker:: IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf, @@ -34,12 +34,14 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf, std::string errorString; - std::vector<std::string> expandedArguments; + std::vector<cmExpandedCommandArgument> expandedArguments; mf.ExpandArguments(this->Args, expandedArguments); cmake::MessageType messageType; - bool isTrue = - cmIfCommand::IsTrue(expandedArguments,errorString, - &mf, messageType); + + cmConditionEvaluator conditionEvaluator(mf); + + bool isTrue = conditionEvaluator.IsTrue( + expandedArguments, errorString, messageType); while (isTrue) { @@ -86,9 +88,8 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf, } expandedArguments.clear(); mf.ExpandArguments(this->Args, expandedArguments); - isTrue = - cmIfCommand::IsTrue(expandedArguments,errorString, - &mf, messageType); + isTrue = conditionEvaluator.IsTrue( + expandedArguments, errorString, messageType); } return true; } diff --git a/Source/cmXMLParser.cxx b/Source/cmXMLParser.cxx index a73fd70..391b874 100644 --- a/Source/cmXMLParser.cxx +++ b/Source/cmXMLParser.cxx @@ -20,6 +20,8 @@ cmXMLParser::cmXMLParser() { this->Parser = 0; this->ParseError = 0; + this->ReportCallback = 0; + this->ReportCallbackData = 0; } //---------------------------------------------------------------------------- @@ -233,6 +235,13 @@ void cmXMLParser::ReportXmlParseError() //---------------------------------------------------------------------------- void cmXMLParser::ReportError(int line, int, const char* msg) { - std::cerr << "Error parsing XML in stream at line " - << line << ": " << msg << std::endl; + if(this->ReportCallback) + { + this->ReportCallback(line, msg, this->ReportCallbackData); + } + else + { + std::cerr << "Error parsing XML in stream at line " + << line << ": " << msg << std::endl; + } } diff --git a/Source/cmXMLParser.h b/Source/cmXMLParser.h index 84a5a7d..e72da66 100644 --- a/Source/cmXMLParser.h +++ b/Source/cmXMLParser.h @@ -50,11 +50,18 @@ public: virtual int ParseChunk(const char* inputString, std::string::size_type length); virtual int CleanupParser(); - + typedef void (*ReportFunction)(int, const char*, void*); + void SetErrorCallback(ReportFunction f, void* d) + { + this->ReportCallback = f; + this->ReportCallbackData = d; + } protected: //! This variable is true if there was a parse error while parsing in //chunks. int ParseError; + ReportFunction ReportCallback; + void* ReportCallbackData; //1 Expat parser structure. Exists only during call to Parse(). void* Parser; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index e3bebbd..09d270d 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -58,6 +58,7 @@ # include "cmGlobalVisualStudio10Generator.h" # include "cmGlobalVisualStudio11Generator.h" # include "cmGlobalVisualStudio12Generator.h" +# include "cmGlobalVisualStudio14Generator.h" # include "cmGlobalBorlandMakefileGenerator.h" # include "cmGlobalNMakeMakefileGenerator.h" # include "cmGlobalJOMMakefileGenerator.h" @@ -343,16 +344,24 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) // The value is transformed if it is a filepath for example, so // we can't compare whether the value is already in the cache until // after we call AddCacheEntry. - const char *cachedValue = - this->CacheManager->GetCacheValue(var); + bool haveValue = false; + std::string cachedValue; + if(this->WarnUnusedCli) + { + if(const char *v = this->CacheManager->GetCacheValue(var)) + { + haveValue = true; + cachedValue = v; + } + } this->CacheManager->AddCacheEntry(var, value.c_str(), "No help, variable specified on the command line.", type); + if(this->WarnUnusedCli) { - if (!cachedValue - || strcmp(this->CacheManager->GetCacheValue(var), - cachedValue) != 0) + if (!haveValue || + cachedValue != this->CacheManager->GetCacheValue(var)) { this->WatchUnusedCli(var); } @@ -630,6 +639,7 @@ void cmake::SetArgs(const std::vector<std::string>& args, { bool directoriesSet = directoriesSetBefore; bool haveToolset = false; + bool havePlatform = false; for(unsigned int i=1; i < args.size(); ++i) { std::string arg = args[i]; @@ -758,6 +768,27 @@ void cmake::SetArgs(const std::vector<std::string>& args, "uninitialized variables.\n"; this->SetCheckSystemVars(true); } + else if(arg.find("-A",0) == 0) + { + std::string value = arg.substr(2); + if(value.size() == 0) + { + ++i; + if(i >= args.size()) + { + cmSystemTools::Error("No platform specified for -A"); + return; + } + value = args[i]; + } + if(havePlatform) + { + cmSystemTools::Error("Multiple -A options not allowed"); + return; + } + this->GeneratorPlatform = value; + havePlatform = true; + } else if(arg.find("-T",0) == 0) { std::string value = arg.substr(2); @@ -1372,6 +1403,7 @@ int cmake::ActualConfigure() {"10.0", "Visual Studio 10 2010"}, {"11.0", "Visual Studio 11 2012"}, {"12.0", "Visual Studio 12 2013"}, + {"14.0", "Visual Studio 14"}, {0, 0}}; for(int i=0; version[i].MSVersion != 0; i++) { @@ -1435,6 +1467,34 @@ int cmake::ActualConfigure() cmCacheManager::INTERNAL); } + if(const char* platformName = + this->CacheManager->GetCacheValue("CMAKE_GENERATOR_PLATFORM")) + { + if(this->GeneratorPlatform.empty()) + { + this->GeneratorPlatform = platformName; + } + else if(this->GeneratorPlatform != platformName) + { + std::string message = "Error: generator platform: "; + message += this->GeneratorPlatform; + message += "\nDoes not match the platform used previously: "; + message += platformName; + message += + "\nEither remove the CMakeCache.txt file and CMakeFiles " + "directory or choose a different binary directory."; + cmSystemTools::Error(message.c_str()); + return -2; + } + } + else + { + this->CacheManager->AddCacheEntry("CMAKE_GENERATOR_PLATFORM", + this->GeneratorPlatform.c_str(), + "Name of generator platform.", + cmCacheManager::INTERNAL); + } + if(const char* tsName = this->CacheManager->GetCacheValue("CMAKE_GENERATOR_TOOLSET")) { @@ -1705,7 +1765,7 @@ int cmake::Generate() { return -1; } - this->GlobalGenerator->Generate(); + this->GlobalGenerator->DoGenerate(); if ( !this->GraphVizFile.empty() ) { std::cout << "Generate graphviz: " << this->GraphVizFile << std::endl; @@ -1771,6 +1831,8 @@ void cmake::AddDefaultGenerators() this->Generators.push_back( cmGlobalVisualStudio12Generator::NewFactory()); this->Generators.push_back( + cmGlobalVisualStudio14Generator::NewFactory()); + this->Generators.push_back( cmGlobalVisualStudio71Generator::NewFactory()); this->Generators.push_back( cmGlobalVisualStudio8Generator::NewFactory()); @@ -2745,7 +2807,7 @@ int cmake::Build(const std::string& dir, projName = it.GetValue(); return gen->Build("", dir, projName, target, - &output, + output, "", config, clean, false, 0, cmSystemTools::OUTPUT_PASSTHROUGH, diff --git a/Source/cmake.h b/Source/cmake.h index 2d04902..60ffcd4 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -191,6 +191,14 @@ class cmake ///! Get the names of the current registered generators void GetRegisteredGenerators(std::vector<std::string>& names); + ///! Set the name of the selected generator-specific platform. + void SetGeneratorPlatform(std::string const& ts) + { this->GeneratorPlatform = ts; } + + ///! Get the name of the selected generator-specific platform. + std::string const& GetGeneratorPlatform() const + { return this->GeneratorPlatform; } + ///! Set the name of the selected generator-specific toolset. void SetGeneratorToolset(std::string const& ts) { this->GeneratorToolset = ts; } @@ -403,6 +411,7 @@ protected: std::string StartOutputDirectory; bool SuppressDevWarnings; bool DoSuppressDevWarnings; + std::string GeneratorPlatform; std::string GeneratorToolset; ///! read in a cmake list file to initialize the cache @@ -467,6 +476,7 @@ private: {"-U <globbing_expr>", "Remove matching entries from CMake cache."}, \ {"-G <generator-name>", "Specify a build system generator."},\ {"-T <toolset-name>", "Specify toolset name if supported by generator."}, \ + {"-A <platform-name>", "Specify platform name if supported by generator."}, \ {"-Wno-dev", "Suppress developer warnings."},\ {"-Wdev", "Enable developer warnings."} diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 9f9f6bb..61b175e 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -42,6 +42,18 @@ static const char * cmDocumentationUsage[][2] = {0, " cmake [options] <path-to-source>\n" " cmake [options] <path-to-existing-build>"}, + {0, + "Specify a source directory to (re-)generate a build system for " + "it in the current working directory. Specify an existing build " + "directory to re-generate its build system."}, + {0,0} +}; + +//---------------------------------------------------------------------------- +static const char * cmDocumentationUsageNote[][2] = +{ + {0, + "Run 'cmake --help' for more information."}, {0,0} }; @@ -163,7 +175,7 @@ static void cmakemainProgressCallback(const char *m, float prog, int main(int ac, char const* const* av) { - setlocale(LC_ALL, ""); + setlocale(LC_CTYPE, ""); cmsys::Encoding::CommandLineArguments args = cmsys::Encoding::CommandLineArguments::Main(ac, av); ac = args.argc(); @@ -223,6 +235,10 @@ int do_cmake(int ac, char const* const* av) doc.SetName("cmake"); doc.SetSection("Name",cmDocumentationName); doc.SetSection("Usage",cmDocumentationUsage); + if ( ac == 1 ) + { + doc.AppendSection("Usage",cmDocumentationUsageNote); + } doc.AppendSection("Generators",generators); doc.PrependSection("Options",cmDocumentationOptions); diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 9aee975..a0c67e0 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -61,6 +61,8 @@ void CMakeCommandUsage(const char* program) << " echo [string]... - displays arguments as text\n" << " echo_append [string]... - displays arguments as text but no new " "line\n" + << " env [--unset=NAME]... [NAME=VALUE]... COMMAND [ARG]...\n" + << " - run command in a modified environment\n" << " environment - display the current environment\n" << " make_directory dir - create a directory\n" << " md5sum file1 [...] - compute md5sum of files\n" @@ -190,6 +192,55 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) return 0; } + else if (args[1] == "env" ) + { + std::vector<std::string>::const_iterator ai = args.begin() + 2; + std::vector<std::string>::const_iterator ae = args.end(); + for(; ai != ae; ++ai) + { + std::string const& a = *ai; + if(cmHasLiteralPrefix(a, "--unset=")) + { + // Unset environment variable. + cmSystemTools::UnPutEnv(a.c_str() + 8); + } + else if(!a.empty() && a[0] == '-') + { + // Environment variable and command names cannot start in '-', + // so this must be an unknown option. + std::cerr << "cmake -E env: unknown option '" << a << "'" + << std::endl; + return 1; + } + else if(a.find("=") != a.npos) + { + // Set environment variable. + cmSystemTools::PutEnv(a.c_str()); + } + else + { + // This is the beginning of the command. + break; + } + } + + if(ai == ae) + { + std::cerr << "cmake -E env: no command given" << std::endl; + return 1; + } + + // Execute command from remaining arguments. + std::vector<std::string> cmd(ai, ae); + int retval; + if(cmSystemTools::RunSingleCommand( + cmd, 0, &retval, NULL, cmSystemTools::OUTPUT_PASSTHROUGH)) + { + return retval; + } + return 1; + } + #if defined(CMAKE_BUILD_WITH_CMAKE) // Command to create a symbolic link. Fails on platforms not // supporting them. diff --git a/Source/cmparseMSBuildXML.py b/Source/cmparseMSBuildXML.py index d1b61ef..056a0db 100755 --- a/Source/cmparseMSBuildXML.py +++ b/Source/cmparseMSBuildXML.py @@ -12,6 +12,9 @@ # "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/cl.xml" # "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/lib.xml" # "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/link.xml" +# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V140/1033/cl.xml" +# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V140/1033/lib.xml" +# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V140/1033/link.xml" # # BoolProperty <Name>true|false</Name> # simple example: diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 167e348..fb97af6 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -48,7 +48,7 @@ static const char * cmDocumentationOptions[][2] = {"--output-on-failure", "Output anything outputted by the test program " "if the test should fail."}, {"-F", "Enable failover."}, - {"-j <jobs>, --parallel <jobs>", "Run the tests in parallel using the" + {"-j <jobs>, --parallel <jobs>", "Run the tests in parallel using the " "given number of jobs."}, {"-Q,--quiet", "Make ctest quiet."}, {"-O <file>, --output-log <file>", "Output to log file"}, @@ -86,6 +86,7 @@ static const char * cmDocumentationOptions[][2] = {"--build-two-config", "Run CMake twice"}, {"--build-exe-dir", "Specify the directory for the executable."}, {"--build-generator", "Specify the generator to use."}, + {"--build-generator-platform", "Specify the generator-specific platform."}, {"--build-generator-toolset", "Specify the generator-specific toolset."}, {"--build-project", "Specify the name of the project to build."}, {"--build-makeprogram", "Specify the make program to use."}, @@ -98,7 +99,7 @@ static const char * cmDocumentationOptions[][2] = {"--test-timeout", "The time limit in seconds, internal use only."}, {"--tomorrow-tag", "Nightly or experimental starts with next day tag."}, {"--ctest-config", "The configuration file used to initialize CTest state " - "when submitting dashboards."}, + "when submitting dashboards."}, {"--overwrite", "Overwrite CTest configuration option."}, {"--extra-submit <file>[;<file>]", "Submit extra files to the dashboard."}, {"--force-new-ctest-process", "Run child CTest instances as new processes"}, @@ -116,7 +117,7 @@ static const char * cmDocumentationOptions[][2] = // this is a test driver program for cmCTest. int main (int argc, char const* const* argv) { - setlocale(LC_ALL, ""); + setlocale(LC_CTYPE, ""); cmsys::Encoding::CommandLineArguments encoding_args = cmsys::Encoding::CommandLineArguments::Main(argc, argv); diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index 5e6a226..8ca4360 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -1171,10 +1171,9 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_CXX_TEST_SRCS}) SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY LABELS ${KWSYS_LABELS_EXE}) TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_NAMESPACE}) - SET(TEST_SYSTEMTOOLS_BIN_FILE - "${CMAKE_CURRENT_SOURCE_DIR}/testSystemTools.bin") - SET(TEST_SYSTEMTOOLS_SRC_FILE - "${CMAKE_CURRENT_SOURCE_DIR}/testSystemTools.cxx") + + SET(TEST_SYSTEMTOOLS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + SET(TEST_SYSTEMTOOLS_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") CONFIGURE_FILE( ${PROJECT_SOURCE_DIR}/testSystemTools.h.in ${PROJECT_BINARY_DIR}/testSystemTools.h) diff --git a/Source/kwsys/CPU.h.in b/Source/kwsys/CPU.h.in index 2e1a584..626914b 100644 --- a/Source/kwsys/CPU.h.in +++ b/Source/kwsys/CPU.h.in @@ -80,6 +80,10 @@ #elif defined(__mips) || defined(__mips__) || defined(__MIPS__) # define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG +/* OpenRISC 1000 */ +#elif defined(__or1k__) +# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG + /* RS/6000 */ #elif defined(__THW_RS600) || defined(_IBMR2) || defined(_POWER) # define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx index d54e607..741bcba 100644 --- a/Source/kwsys/Directory.cxx +++ b/Source/kwsys/Directory.cxx @@ -103,7 +103,7 @@ void Directory::Clear() namespace KWSYS_NAMESPACE { -bool Directory::Load(const char* name) +bool Directory::Load(const kwsys_stl::string& name) { this->Clear(); #if _MSC_VER < 1300 @@ -112,16 +112,25 @@ bool Directory::Load(const char* name) intptr_t srchHandle; #endif char* buf; - size_t n = strlen(name); - if ( name[n - 1] == '/' ) + size_t n = name.size(); + if ( *name.rbegin() == '/' || *name.rbegin() == '\\' ) { buf = new char[n + 1 + 1]; - sprintf(buf, "%s*", name); + sprintf(buf, "%s*", name.c_str()); } else { + // Make sure the slashes in the wildcard suffix are consistent with the + // rest of the path buf = new char[n + 2 + 1]; - sprintf(buf, "%s/*", name); + if ( name.find('\\') != name.npos ) + { + sprintf(buf, "%s\\*", name.c_str()); + } + else + { + sprintf(buf, "%s/*", name.c_str()); + } } struct _wfinddata_t data; // data of current file @@ -144,7 +153,7 @@ bool Directory::Load(const char* name) return _findclose(srchHandle) != -1; } -unsigned long Directory::GetNumberOfFilesInDirectory(const char* name) +unsigned long Directory::GetNumberOfFilesInDirectory(const kwsys_stl::string& name) { #if _MSC_VER < 1300 long srchHandle; @@ -152,16 +161,16 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const char* name) intptr_t srchHandle; #endif char* buf; - size_t n = strlen(name); - if ( name[n - 1] == '/' ) + size_t n = name.size(); + if ( *name.rbegin() == '/' ) { buf = new char[n + 1 + 1]; - sprintf(buf, "%s*", name); + sprintf(buf, "%s*", name.c_str()); } else { buf = new char[n + 2 + 1]; - sprintf(buf, "%s/*", name); + sprintf(buf, "%s/*", name.c_str()); } struct _wfinddata_t data; // data of current file @@ -206,15 +215,11 @@ p=1992&sid=f16167f51964f1a68fe5041b8eb213b6 namespace KWSYS_NAMESPACE { -bool Directory::Load(const char* name) +bool Directory::Load(const kwsys_stl::string& name) { this->Clear(); - if (!name) - { - return 0; - } - DIR* dir = opendir(name); + DIR* dir = opendir(name.c_str()); if (!dir) { @@ -230,14 +235,9 @@ bool Directory::Load(const char* name) return 1; } -unsigned long Directory::GetNumberOfFilesInDirectory(const char* name) +unsigned long Directory::GetNumberOfFilesInDirectory(const kwsys_stl::string& name) { - DIR* dir = opendir(name); - - if (!dir) - { - return 0; - } + DIR* dir = opendir(name.c_str()); unsigned long count = 0; for (dirent* d = readdir(dir); d; d = readdir(dir) ) diff --git a/Source/kwsys/Directory.hxx.in b/Source/kwsys/Directory.hxx.in index 05217c4..0acb191 100644 --- a/Source/kwsys/Directory.hxx.in +++ b/Source/kwsys/Directory.hxx.in @@ -13,6 +13,13 @@ #define @KWSYS_NAMESPACE@_Directory_hxx #include <@KWSYS_NAMESPACE@/Configure.h> +#include <@KWSYS_NAMESPACE@/stl/string> + +/* Define these macros temporarily to keep the code readable. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# define kwsys_stl @KWSYS_NAMESPACE@_stl +# define kwsys_ios @KWSYS_NAMESPACE@_ios +#endif namespace @KWSYS_NAMESPACE@ { @@ -38,7 +45,7 @@ public: * in that directory. 0 is returned if the directory can not be * opened, 1 if it is opened. */ - bool Load(const char*); + bool Load(const kwsys_stl::string&); /** * Return the number of files in the current directory. @@ -49,7 +56,7 @@ public: * Return the number of files in the specified directory. * A higher performance static method. */ - static unsigned long GetNumberOfFilesInDirectory(const char*); + static unsigned long GetNumberOfFilesInDirectory(const kwsys_stl::string&); /** * Return the file at the given index, the indexing is 0 based @@ -77,4 +84,10 @@ private: } // namespace @KWSYS_NAMESPACE@ +/* Undefine temporary macros. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# undef kwsys_stl +# undef kwsys_ios +#endif + #endif diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx index 8569b0e..0916d2e 100644 --- a/Source/kwsys/Glob.cxx +++ b/Source/kwsys/Glob.cxx @@ -218,7 +218,7 @@ void Glob::RecurseDirectory(kwsys_stl::string::size_type start, const kwsys_stl::string& dir) { kwsys::Directory d; - if ( !d.Load(dir.c_str()) ) + if ( !d.Load(dir) ) { return; } @@ -257,8 +257,8 @@ void Glob::RecurseDirectory(kwsys_stl::string::size_type start, fullname = dir + "/" + fname; } - bool isDir = kwsys::SystemTools::FileIsDirectory(realname.c_str()); - bool isSymLink = kwsys::SystemTools::FileIsSymlink(realname.c_str()); + bool isDir = kwsys::SystemTools::FileIsDirectory(realname); + bool isSymLink = kwsys::SystemTools::FileIsSymlink(realname); if ( isDir && (!isSymLink || this->RecurseThroughSymlinks) ) { @@ -297,7 +297,7 @@ void Glob::ProcessDirectory(kwsys_stl::string::size_type start, } kwsys::Directory d; - if ( !d.Load(dir.c_str()) ) + if ( !d.Load(dir) ) { return; } @@ -342,12 +342,12 @@ void Glob::ProcessDirectory(kwsys_stl::string::size_type start, //kwsys_ios::cout << "Full name: " << fullname << kwsys_ios::endl; if ( !last && - !kwsys::SystemTools::FileIsDirectory(realname.c_str()) ) + !kwsys::SystemTools::FileIsDirectory(realname) ) { continue; } - if ( this->Internals->Expressions[start].find(fname.c_str()) ) + if ( this->Internals->Expressions[start].find(fname) ) { if ( last ) { @@ -371,7 +371,7 @@ bool Glob::FindFiles(const kwsys_stl::string& inexpr) this->Internals->Expressions.clear(); this->Internals->Files.clear(); - if ( !kwsys::SystemTools::FileIsFullPath(expr.c_str()) ) + if ( !kwsys::SystemTools::FileIsFullPath(expr) ) { expr = kwsys::SystemTools::GetCurrentWorkingDirectory(); expr += "/" + inexpr; diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index 241e295..ca9d424 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -68,6 +68,7 @@ do. #include <signal.h> /* sigaction */ #include <dirent.h> /* DIR, dirent */ #include <ctype.h> /* isspace */ +#include <assert.h> /* assert */ #if defined(__VMS) # define KWSYSPE_VMS_NONBLOCK , O_NONBLOCK @@ -450,6 +451,7 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) } for(i=0; i < n; ++i) { + assert(command[i]); /* Quiet Clang scan-build. */ newCommands[cp->NumberOfCommands][i] = strdup(command[i]); if(!newCommands[cp->NumberOfCommands][i]) { diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index c8ec754..ef71f26 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -36,6 +36,9 @@ a UNIX-style select system call. #pragma warning (push, 1) #endif #include <windows.h> /* Windows API */ +#if defined(_MSC_VER) && _MSC_VER >= 1800 +# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx +#endif #include <string.h> /* strlen, strdup */ #include <stdio.h> /* sprintf */ #include <io.h> /* _unlink */ @@ -335,7 +338,14 @@ kwsysProcess* kwsysProcess_New(void) windows. */ ZeroMemory(&osv, sizeof(osv)); osv.dwOSVersionInfoSize = sizeof(osv); +#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx +# pragma warning (push) +# pragma warning (disable:4996) +#endif GetVersionEx(&osv); +#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx +# pragma warning (pop) +#endif if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { /* Win9x no longer supported. */ @@ -2370,7 +2380,14 @@ static kwsysProcess_List* kwsysProcess_List_New(void) /* Select an implementation. */ ZeroMemory(&osv, sizeof(osv)); osv.dwOSVersionInfoSize = sizeof(osv); +#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx +# pragma warning (push) +# pragma warning (disable:4996) +#endif GetVersionEx(&osv); +#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx +# pragma warning (pop) +#endif self->NT4 = (osv.dwPlatformId == VER_PLATFORM_WIN32_NT && osv.dwMajorVersion < 5)? 1:0; diff --git a/Source/kwsys/SharedForward.h.in b/Source/kwsys/SharedForward.h.in index dd4d462..7ff29b4 100644 --- a/Source/kwsys/SharedForward.h.in +++ b/Source/kwsys/SharedForward.h.in @@ -512,7 +512,7 @@ static void kwsys_shared_forward_execvp(const char* cmd, /* Invoke the child process. */ #if defined(_MSC_VER) _execvp(cmd, argv); -#elif defined(__MINGW32__) +#elif defined(__MINGW32__) && !defined(__MINGW64__) execvp(cmd, argv); #else execvp(cmd, (char* const*)argv); diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index 6544098..84b5f39 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -60,6 +60,9 @@ #if defined(_WIN32) # include <windows.h> +# if defined(_MSC_VER) && _MSC_VER >= 1800 +# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx +# endif # include <errno.h> # if defined(KWSYS_SYS_HAS_PSAPI) # include <psapi.h> @@ -3696,7 +3699,10 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable) // install ours struct sigaction sa; sa.sa_sigaction=(SigAction)StacktraceSignalHandler; - sa.sa_flags=SA_SIGINFO|SA_RESTART|SA_RESETHAND; + sa.sa_flags=SA_SIGINFO|SA_RESETHAND; +# ifdef SA_RESTART + sa.sa_flags|=SA_RESTART; +# endif sigemptyset(&sa.sa_mask); sigaction(SIGABRT,&sa,0); @@ -3783,7 +3789,7 @@ bool SystemInformationImplementation::QueryLinuxMemory() return false; } - if( unameInfo.release!=0 && strlen(unameInfo.release)>=3 ) + if( strlen(unameInfo.release)>=3 ) { // release looks like "2.6.3-15mdk-i686-up-4GB" char majorChar=unameInfo.release[0]; @@ -5060,6 +5066,10 @@ bool SystemInformationImplementation::QueryOSInformation() // Try calling GetVersionEx using the OSVERSIONINFOEX structure. ZeroMemory (&osvi, sizeof (OSVERSIONINFOEXW)); osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); +#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx +# pragma warning (push) +# pragma warning (disable:4996) +#endif bOsVersionInfoEx = GetVersionExW ((OSVERSIONINFOW*)&osvi); if (!bOsVersionInfoEx) { @@ -5069,6 +5079,9 @@ bool SystemInformationImplementation::QueryOSInformation() return false; } } +#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx +# pragma warning (pop) +#endif switch (osvi.dwPlatformId) { diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 704cbbc..b1221e3 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -82,6 +82,9 @@ # ifndef INVALID_FILE_ATTRIBUTES # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) # endif +# if defined(_MSC_VER) && _MSC_VER >= 1800 +# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx +# endif #elif defined (__CYGWIN__) # include <windows.h> # undef _WIN32 @@ -187,17 +190,34 @@ static inline char *realpath(const char *path, char *resolved_path) } #endif +#ifdef _WIN32 +static time_t windows_filetime_to_posix_time(const FILETIME& ft) +{ + LARGE_INTEGER date; + date.HighPart = ft.dwHighDateTime; + date.LowPart = ft.dwLowDateTime; + + // removes the diff between 1970 and 1601 + date.QuadPart -= ((LONGLONG)(369 * 365 + 89) * 24 * 3600 * 10000000); + + // converts back from 100-nanoseconds to seconds + return date.QuadPart / 10000000; +} +#endif + #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__)) #include <wctype.h> -inline int Mkdir(const char* dir) +inline int Mkdir(const kwsys_stl::string& dir) { - return _wmkdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str()); + return _wmkdir( + KWSYS_NAMESPACE::SystemTools::ConvertToWindowsExtendedPath(dir).c_str()); } -inline int Rmdir(const char* dir) +inline int Rmdir(const kwsys_stl::string& dir) { - return _wrmdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str()); + return _wrmdir( + KWSYS_NAMESPACE::SystemTools::ConvertToWindowsExtendedPath(dir).c_str()); } inline const char* Getcwd(char* buf, unsigned int len) { @@ -215,15 +235,15 @@ inline const char* Getcwd(char* buf, unsigned int len) } return 0; } -inline int Chdir(const char* dir) +inline int Chdir(const kwsys_stl::string& dir) { #if defined(__BORLANDC__) - return chdir(dir); + return chdir(dir.c_str()); #else return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str()); #endif } -inline void Realpath(const char *path, kwsys_stl::string & resolved_path) +inline void Realpath(const kwsys_stl::string& path, kwsys_stl::string & resolved_path) { kwsys_stl::wstring tmp = KWSYS_NAMESPACE::Encoding::ToWide(path); wchar_t *ptemp; @@ -243,28 +263,28 @@ inline void Realpath(const char *path, kwsys_stl::string & resolved_path) #include <sys/types.h> #include <fcntl.h> #include <unistd.h> -inline int Mkdir(const char* dir) +inline int Mkdir(const kwsys_stl::string& dir) { - return mkdir(dir, 00777); + return mkdir(dir.c_str(), 00777); } -inline int Rmdir(const char* dir) +inline int Rmdir(const kwsys_stl::string& dir) { - return rmdir(dir); + return rmdir(dir.c_str()); } inline const char* Getcwd(char* buf, unsigned int len) { return getcwd(buf, len); } -inline int Chdir(const char* dir) +inline int Chdir(const kwsys_stl::string& dir) { - return chdir(dir); + return chdir(dir.c_str()); } -inline void Realpath(const char *path, kwsys_stl::string & resolved_path) +inline void Realpath(const kwsys_stl::string& path, kwsys_stl::string & resolved_path) { char resolved_name[KWSYS_SYSTEMTOOLS_MAXPATH]; - char *ret = realpath(path, resolved_name); + char *ret = realpath(path.c_str(), resolved_name); if(ret) { resolved_path = ret; @@ -317,9 +337,9 @@ class SystemToolsTranslationMap : void SystemTools::GetPath(kwsys_stl::vector<kwsys_stl::string>& path, const char* env) { #if defined(_WIN32) && !defined(__CYGWIN__) - const char* pathSep = ";"; + const char pathSep = ';'; #else - const char* pathSep = ":"; + const char pathSep = ':'; #endif if(!env) { @@ -334,7 +354,7 @@ void SystemTools::GetPath(kwsys_stl::vector<kwsys_stl::string>& path, const char kwsys_stl::string pathEnv = cpathEnv; // A hack to make the below algorithm work. - if(!pathEnv.empty() && pathEnv[pathEnv.length()-1] != pathSep[0]) + if(!pathEnv.empty() && *pathEnv.rbegin() != pathSep) { pathEnv += pathSep; } @@ -606,13 +626,13 @@ const char* SystemTools::GetExecutableExtension() #endif } -FILE* SystemTools::Fopen(const char* file, const char* mode) +FILE* SystemTools::Fopen(const kwsys_stl::string& file, const char* mode) { #ifdef _WIN32 - return _wfopen(Encoding::ToWide(file).c_str(), + return _wfopen(SystemTools::ConvertToWindowsExtendedPath(file).c_str(), Encoding::ToWide(mode).c_str()); #else - return fopen(file, mode); + return fopen(file.c_str(), mode); #endif } @@ -622,15 +642,20 @@ bool SystemTools::MakeDirectory(const char* path) { return false; } + return SystemTools::MakeDirectory(kwsys_stl::string(path)); +} + +bool SystemTools::MakeDirectory(const kwsys_stl::string& path) +{ if(SystemTools::FileExists(path)) { return SystemTools::FileIsDirectory(path); } - kwsys_stl::string dir = path; - if(dir.empty()) + if(path.empty()) { return false; } + kwsys_stl::string dir = path; SystemTools::ConvertToUnixSlashes(dir); kwsys_stl::string::size_type pos = 0; @@ -638,11 +663,11 @@ bool SystemTools::MakeDirectory(const char* path) while((pos = dir.find('/', pos)) != kwsys_stl::string::npos) { topdir = dir.substr(0, pos); - Mkdir(topdir.c_str()); + Mkdir(topdir); pos++; } topdir = dir; - if(Mkdir(topdir.c_str()) != 0) + if(Mkdir(topdir) != 0) { // There is a bug in the Borland Run time library which makes MKDIR // return EACCES when it should return EEXISTS @@ -1004,7 +1029,7 @@ bool SystemTools::DeleteRegistryValue(const char *, KeyWOW64) } #endif -bool SystemTools::SameFile(const char* file1, const char* file2) +bool SystemTools::SameFile(const kwsys_stl::string& file1, const kwsys_stl::string& file2) { #ifdef _WIN32 HANDLE hFile1, hFile2; @@ -1049,7 +1074,7 @@ bool SystemTools::SameFile(const char* file1, const char* file2) fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow); #else struct stat fileStat1, fileStat2; - if (stat(file1, &fileStat1) == 0 && stat(file2, &fileStat2) == 0) + if (stat(file1.c_str(), &fileStat1) == 0 && stat(file2.c_str(), &fileStat2) == 0) { // see if the files are the same file // check the device inode and size @@ -1068,23 +1093,34 @@ bool SystemTools::SameFile(const char* file1, const char* file2) //---------------------------------------------------------------------------- bool SystemTools::FileExists(const char* filename) { - if(!(filename && *filename)) + if(!filename) + { + return false; + } + return SystemTools::FileExists(kwsys_stl::string(filename)); +} + +//---------------------------------------------------------------------------- +bool SystemTools::FileExists(const kwsys_stl::string& filename) +{ + if(filename.empty()) { return false; } #if defined(__CYGWIN__) // Convert filename to native windows path if possible. char winpath[MAX_PATH]; - if(SystemTools::PathCygwinToWin32(filename, winpath)) + if(SystemTools::PathCygwinToWin32(filename.c_str(), winpath)) { return (GetFileAttributesA(winpath) != INVALID_FILE_ATTRIBUTES); } - return access(filename, R_OK) == 0; + return access(filename.c_str(), R_OK) == 0; #elif defined(_WIN32) - return (GetFileAttributesW(Encoding::ToWide(filename).c_str()) + return (GetFileAttributesW( + SystemTools::ConvertToWindowsExtendedPath(filename).c_str()) != INVALID_FILE_ATTRIBUTES); #else - return access(filename, R_OK) == 0; + return access(filename.c_str(), R_OK) == 0; #endif } @@ -1101,6 +1137,18 @@ bool SystemTools::FileExists(const char* filename, bool isFile) } //---------------------------------------------------------------------------- +bool SystemTools::FileExists(const kwsys_stl::string& filename, bool isFile) +{ + if(SystemTools::FileExists(filename)) + { + // If isFile is set return not FileIsDirectory, + // so this will only be true if it is a file + return !isFile || !SystemTools::FileIsDirectory(filename); + } + return false; +} + +//---------------------------------------------------------------------------- #ifdef __CYGWIN__ bool SystemTools::PathCygwinToWin32(const char *path, char *win32_path) { @@ -1124,7 +1172,7 @@ bool SystemTools::PathCygwinToWin32(const char *path, char *win32_path) } #endif -bool SystemTools::Touch(const char* filename, bool create) +bool SystemTools::Touch(const kwsys_stl::string& filename, bool create) { if(create && !SystemTools::FileExists(filename)) { @@ -1137,10 +1185,11 @@ bool SystemTools::Touch(const char* filename, bool create) return false; } #if defined(_WIN32) && !defined(__CYGWIN__) - HANDLE h = CreateFileW(Encoding::ToWide(filename).c_str(), - FILE_WRITE_ATTRIBUTES, - FILE_SHARE_WRITE, 0, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, 0); + HANDLE h = CreateFileW( + SystemTools::ConvertToWindowsExtendedPath(filename).c_str(), + FILE_WRITE_ATTRIBUTES, + FILE_SHARE_WRITE, 0, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, 0); if(!h) { return false; @@ -1155,13 +1204,13 @@ bool SystemTools::Touch(const char* filename, bool create) CloseHandle(h); #elif KWSYS_CXX_HAS_UTIMENSAT struct timespec times[2] = {{0,UTIME_OMIT},{0,UTIME_NOW}}; - if(utimensat(AT_FDCWD, filename, times, 0) < 0) + if(utimensat(AT_FDCWD, filename.c_str(), times, 0) < 0) { return false; } #else struct stat st; - if(stat(filename, &st) < 0) + if(stat(filename.c_str(), &st) < 0) { return false; } @@ -1177,13 +1226,13 @@ bool SystemTools::Touch(const char* filename, bool create) # endif mtime }; - if(utimes(filename, times) < 0) + if(utimes(filename.c_str(), times) < 0) { return false; } # else struct utimbuf times = {st.st_atime, mtime.tv_sec}; - if(utime(filename, ×) < 0) + if(utime(filename.c_str(), ×) < 0) { return false; } @@ -1192,7 +1241,8 @@ bool SystemTools::Touch(const char* filename, bool create) return true; } -bool SystemTools::FileTimeCompare(const char* f1, const char* f2, +bool SystemTools::FileTimeCompare(const kwsys_stl::string& f1, + const kwsys_stl::string& f2, int* result) { // Default to same time. @@ -1200,12 +1250,12 @@ bool SystemTools::FileTimeCompare(const char* f1, const char* f2, #if !defined(_WIN32) || defined(__CYGWIN__) // POSIX version. Use stat function to get file modification time. struct stat s1; - if(stat(f1, &s1) != 0) + if(stat(f1.c_str(), &s1) != 0) { return false; } struct stat s2; - if(stat(f2, &s2) != 0) + if(stat(f2.c_str(), &s2) != 0) { return false; } @@ -1242,13 +1292,15 @@ bool SystemTools::FileTimeCompare(const char* f1, const char* f2, // Windows version. Get the modification time from extended file attributes. WIN32_FILE_ATTRIBUTE_DATA f1d; WIN32_FILE_ATTRIBUTE_DATA f2d; - if(!GetFileAttributesExW(Encoding::ToWide(f1).c_str(), - GetFileExInfoStandard, &f1d)) + if(!GetFileAttributesExW( + SystemTools::ConvertToWindowsExtendedPath(f1).c_str(), + GetFileExInfoStandard, &f1d)) { return false; } - if(!GetFileAttributesExW(Encoding::ToWide(f2).c_str(), - GetFileExInfoStandard, &f2d)) + if(!GetFileAttributesExW( + SystemTools::ConvertToWindowsExtendedPath(f2).c_str(), + GetFileExInfoStandard, &f2d)) { return false; } @@ -1514,6 +1566,17 @@ bool SystemTools::StringStartsWith(const char* str1, const char* str2) return len1 >= len2 && !strncmp(str1, str2, len2) ? true : false; } +// Returns if string starts with another string +bool SystemTools::StringStartsWith(const kwsys_stl::string& str1, const char* str2) +{ + if (!str2) + { + return false; + } + size_t len1 = str1.size(), len2 = strlen(str2); + return len1 >= len2 && !strncmp(str1.c_str(), str2, len2) ? true : false; +} + // Returns if string ends with another string bool SystemTools::StringEndsWith(const char* str1, const char* str2) { @@ -1525,6 +1588,17 @@ bool SystemTools::StringEndsWith(const char* str1, const char* str2) return len1 >= len2 && !strncmp(str1 + (len1 - len2), str2, len2) ? true : false; } +// Returns if string ends with another string +bool SystemTools::StringEndsWith(const kwsys_stl::string& str1, const char* str2) +{ + if (!str2) + { + return false; + } + size_t len1 = str1.size(), len2 = strlen(str2); + return len1 >= len2 && !strncmp(str1.c_str() + (len1 - len2), str2, len2) ? true : false; +} + // Returns a pointer to the last occurence of str2 in str1 const char* SystemTools::FindLastString(const char* str1, const char* str2) { @@ -1594,7 +1668,7 @@ kwsys_stl::string SystemTools::CropString(const kwsys_stl::string& s, } //---------------------------------------------------------------------------- -kwsys_stl::vector<kwsys::String> SystemTools::SplitString(const char* p, char sep, bool isPath) +kwsys_stl::vector<kwsys::String> SystemTools::SplitString(const kwsys_stl::string& p, char sep, bool isPath) { kwsys_stl::string path = p; kwsys_stl::vector<kwsys::String> paths; @@ -1830,8 +1904,73 @@ void SystemTools::ConvertToUnixSlashes(kwsys_stl::string& path) } } +#ifdef _WIN32 +// Convert local paths to UNC style paths +kwsys_stl::wstring +SystemTools::ConvertToWindowsExtendedPath(const kwsys_stl::string &source) +{ + kwsys_stl::wstring wsource = Encoding::ToWide(source); + + // Resolve any relative paths + DWORD wfull_len; + + /* The +3 is a workaround for a bug in some versions of GetFullPathNameW that + * won't return a large enough buffer size if the input is too small */ + wfull_len = GetFullPathNameW(wsource.c_str(), 0, NULL, NULL) + 3; + kwsys_stl::vector<wchar_t> wfull(wfull_len); + GetFullPathNameW(wsource.c_str(), wfull_len, &wfull[0], NULL); + + /* This should get the correct size without any extra padding from the + * previous size workaround. */ + wfull_len = static_cast<DWORD>(wcslen(&wfull[0])); + + if(wfull_len >= 2 && isalpha(wfull[0]) && wfull[1] == L':') + { /* C:\Foo\bar\FooBar.txt */ + return L"\\\\?\\" + kwsys_stl::wstring(&wfull[0]); + } + else if(wfull_len >= 2 && wfull[0] == L'\\' && wfull[1] == L'\\') + { /* Starts with \\ */ + if(wfull_len >= 4 && wfull[2] == L'?' && wfull[3] == L'\\') + { /* Starts with \\?\ */ + if(wfull_len >= 8 && wfull[4] == L'U' && wfull[5] == L'N' && + wfull[6] == L'C' && wfull[7] == L'\\') + { /* \\?\UNC\Foo\bar\FooBar.txt */ + return kwsys_stl::wstring(&wfull[0]); + } + else if(wfull_len >= 6 && isalpha(wfull[4]) && wfull[5] == L':') + { /* \\?\C:\Foo\bar\FooBar.txt */ + return kwsys_stl::wstring(&wfull[0]); + } + else if(wfull_len >= 5) + { /* \\?\Foo\bar\FooBar.txt */ + return L"\\\\?\\UNC\\" + kwsys_stl::wstring(&wfull[4]); + } + } + else if(wfull_len >= 4 && wfull[2] == L'.' && wfull[3] == L'\\') + { /* Starts with \\.\ a device name */ + if(wfull_len >= 6 && isalpha(wfull[4]) && wfull[5] == L':') + { /* \\.\C:\Foo\bar\FooBar.txt */ + return L"\\\\?\\" + kwsys_stl::wstring(&wfull[4]); + } + else if(wfull_len >= 5) + { /* \\.\Foo\bar\ Device name is left unchanged */ + return kwsys_stl::wstring(&wfull[0]); + } + } + else if(wfull_len >= 3) + { /* \\Foo\bar\FooBar.txt */ + return L"\\\\?\\UNC\\" + kwsys_stl::wstring(&wfull[2]); + } + } + + // If this case has been reached, then the path is invalid. Leave it + // unchanged + return Encoding::ToWide(source); +} +#endif + // change // to /, and escape any spaces in the path -kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path) +kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const kwsys_stl::string& path) { kwsys_stl::string ret = path; @@ -1861,7 +2000,7 @@ kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path) return ret; } -kwsys_stl::string SystemTools::ConvertToOutputPath(const char* path) +kwsys_stl::string SystemTools::ConvertToOutputPath(const kwsys_stl::string& path) { #if defined(_WIN32) && !defined(__CYGWIN__) return SystemTools::ConvertToWindowsOutputPath(path); @@ -1871,13 +2010,12 @@ kwsys_stl::string SystemTools::ConvertToOutputPath(const char* path) } // remove double slashes not at the start -kwsys_stl::string SystemTools::ConvertToWindowsOutputPath(const char* path) +kwsys_stl::string SystemTools::ConvertToWindowsOutputPath(const kwsys_stl::string& path) { kwsys_stl::string ret; // make it big enough for all of path and double quotes - ret.reserve(strlen(path)+3); + ret.reserve(path.size()+3); // put path into the string - ret.assign(path); ret = path; kwsys_stl::string::size_type pos = 0; // first convert all of the slashes @@ -1919,8 +2057,8 @@ kwsys_stl::string SystemTools::ConvertToWindowsOutputPath(const char* path) return ret; } -bool SystemTools::CopyFileIfDifferent(const char* source, - const char* destination) +bool SystemTools::CopyFileIfDifferent(const kwsys_stl::string& source, + const kwsys_stl::string& destination) { // special check for a destination that is a directory // FilesDiffer does not handle file to directory compare @@ -1931,7 +2069,7 @@ bool SystemTools::CopyFileIfDifferent(const char* source, new_destination += '/'; kwsys_stl::string source_name = source; new_destination += SystemTools::GetFilenameName(source_name); - if(SystemTools::FilesDiffer(source, new_destination.c_str())) + if(SystemTools::FilesDiffer(source, new_destination)) { return SystemTools::CopyFileAlways(source, destination); } @@ -1954,23 +2092,25 @@ bool SystemTools::CopyFileIfDifferent(const char* source, #define KWSYS_ST_BUFFER 4096 -bool SystemTools::FilesDiffer(const char* source, - const char* destination) +bool SystemTools::FilesDiffer(const kwsys_stl::string& source, + const kwsys_stl::string& destination) { #if defined(_WIN32) WIN32_FILE_ATTRIBUTE_DATA statSource; - if (GetFileAttributesExW(Encoding::ToWide(source).c_str(), - GetFileExInfoStandard, - &statSource) == 0) + if (GetFileAttributesExW( + SystemTools::ConvertToWindowsExtendedPath(source).c_str(), + GetFileExInfoStandard, + &statSource) == 0) { return true; } WIN32_FILE_ATTRIBUTE_DATA statDestination; - if (GetFileAttributesExW(Encoding::ToWide(destination).c_str(), - GetFileExInfoStandard, - &statDestination) == 0) + if (GetFileAttributesExW( + SystemTools::ConvertToWindowsExtendedPath(destination).c_str(), + GetFileExInfoStandard, + &statDestination) == 0) { return true; } @@ -1991,13 +2131,13 @@ bool SystemTools::FilesDiffer(const char* source, #else struct stat statSource; - if (stat(source, &statSource) != 0) + if (stat(source.c_str(), &statSource) != 0) { return true; } struct stat statDestination; - if (stat(destination, &statDestination) != 0) + if (stat(destination.c_str(), &statDestination) != 0) { return true; } @@ -2015,15 +2155,15 @@ bool SystemTools::FilesDiffer(const char* source, #endif #if defined(_WIN32) - kwsys::ifstream finSource(source, + kwsys::ifstream finSource(source.c_str(), (kwsys_ios::ios::binary | kwsys_ios::ios::in)); - kwsys::ifstream finDestination(destination, + kwsys::ifstream finDestination(destination.c_str(), (kwsys_ios::ios::binary | kwsys_ios::ios::in)); #else - kwsys::ifstream finSource(source); - kwsys::ifstream finDestination(destination); + kwsys::ifstream finSource(source.c_str()); + kwsys::ifstream finDestination(destination.c_str()); #endif if(!finSource || !finDestination) { @@ -2068,7 +2208,7 @@ bool SystemTools::FilesDiffer(const char* source, /** * Copy a file named by "source" to the file named by "destination". */ -bool SystemTools::CopyFileAlways(const char* source, const char* destination) +bool SystemTools::CopyFileAlways(const kwsys_stl::string& source, const kwsys_stl::string& destination) { // If files are the same do not copy if ( SystemTools::SameFile(source, destination) ) @@ -2084,31 +2224,33 @@ bool SystemTools::CopyFileAlways(const char* source, const char* destination) // If destination is a directory, try to create a file with the same // name as the source in that directory. - kwsys_stl::string new_destination; + kwsys_stl::string real_destination = destination; + kwsys_stl::string destination_dir; if(SystemTools::FileExists(destination) && SystemTools::FileIsDirectory(destination)) { - new_destination = destination; - SystemTools::ConvertToUnixSlashes(new_destination); - new_destination += '/'; + destination_dir = real_destination; + SystemTools::ConvertToUnixSlashes(real_destination); + real_destination += '/'; kwsys_stl::string source_name = source; - new_destination += SystemTools::GetFilenameName(source_name); - destination = new_destination.c_str(); + real_destination += SystemTools::GetFilenameName(source_name); + } + else + { + destination_dir = SystemTools::GetFilenamePath(destination); } // Create destination directory - kwsys_stl::string destination_dir = destination; - destination_dir = SystemTools::GetFilenamePath(destination_dir); - SystemTools::MakeDirectory(destination_dir.c_str()); + SystemTools::MakeDirectory(destination_dir); // Open files #if defined(_WIN32) || defined(__CYGWIN__) - kwsys::ifstream fin(source, + kwsys::ifstream fin(source.c_str(), kwsys_ios::ios::binary | kwsys_ios::ios::in); #else - kwsys::ifstream fin(source); + kwsys::ifstream fin(source.c_str()); #endif if(!fin) { @@ -2119,13 +2261,13 @@ bool SystemTools::CopyFileAlways(const char* source, const char* destination) // can be written to. // If the remove fails continue so that files in read only directories // that do not allow file removal can be modified. - SystemTools::RemoveFile(destination); + SystemTools::RemoveFile(real_destination); #if defined(_WIN32) || defined(__CYGWIN__) - kwsys::ofstream fout(destination, + kwsys::ofstream fout(real_destination.c_str(), kwsys_ios::ios::binary | kwsys_ios::ios::out | kwsys_ios::ios::trunc); #else - kwsys::ofstream fout(destination, + kwsys::ofstream fout(real_destination.c_str(), kwsys_ios::ios::out | kwsys_ios::ios::trunc); #endif if(!fout) @@ -2161,7 +2303,7 @@ bool SystemTools::CopyFileAlways(const char* source, const char* destination) } if ( perms ) { - if ( !SystemTools::SetPermissions(destination, perm) ) + if ( !SystemTools::SetPermissions(real_destination, perm) ) { return false; } @@ -2170,7 +2312,7 @@ bool SystemTools::CopyFileAlways(const char* source, const char* destination) } //---------------------------------------------------------------------------- -bool SystemTools::CopyAFile(const char* source, const char* destination, +bool SystemTools::CopyAFile(const kwsys_stl::string& source, const kwsys_stl::string& destination, bool always) { if(always) @@ -2187,11 +2329,16 @@ bool SystemTools::CopyAFile(const char* source, const char* destination, * Copy a directory content from "source" directory to the directory named by * "destination". */ -bool SystemTools::CopyADirectory(const char* source, const char* destination, +bool SystemTools::CopyADirectory(const kwsys_stl::string& source, const kwsys_stl::string& destination, bool always) { Directory dir; +#ifdef _WIN32 + dir.Load(Encoding::ToNarrow( + SystemTools::ConvertToWindowsExtendedPath(source))); +#else dir.Load(source); +#endif size_t fileNum; if ( !SystemTools::MakeDirectory(destination) ) { @@ -2205,13 +2352,13 @@ bool SystemTools::CopyADirectory(const char* source, const char* destination, kwsys_stl::string fullPath = source; fullPath += "/"; fullPath += dir.GetFile(static_cast<unsigned long>(fileNum)); - if(SystemTools::FileIsDirectory(fullPath.c_str())) + if(SystemTools::FileIsDirectory(fullPath)) { kwsys_stl::string fullDestPath = destination; fullDestPath += "/"; fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum)); - if (!SystemTools::CopyADirectory(fullPath.c_str(), - fullDestPath.c_str(), + if (!SystemTools::CopyADirectory(fullPath, + fullDestPath, always)) { return false; @@ -2219,7 +2366,7 @@ bool SystemTools::CopyADirectory(const char* source, const char* destination, } else { - if(!SystemTools::CopyAFile(fullPath.c_str(), destination, always)) + if(!SystemTools::CopyAFile(fullPath, destination, always)) { return false; } @@ -2234,15 +2381,28 @@ bool SystemTools::CopyADirectory(const char* source, const char* destination, // return size of file; also returns zero if no file exists unsigned long SystemTools::FileLength(const char* filename) { - struct stat fs; - if (stat(filename, &fs) != 0) + unsigned long length = 0; +#ifdef _WIN32 + WIN32_FILE_ATTRIBUTE_DATA fs; + if (GetFileAttributesExW( + SystemTools::ConvertToWindowsExtendedPath(filename).c_str(), + GetFileExInfoStandard, &fs) != 0) { - return 0; + /* To support the full 64-bit file size, use fs.nFileSizeHigh + * and fs.nFileSizeLow to construct the 64 bit size + + length = ((__int64)fs.nFileSizeHigh << 32) + fs.nFileSizeLow; + */ + length = static_cast<unsigned long>(fs.nFileSizeLow); } - else +#else + struct stat fs; + if (stat(filename, &fs) == 0) { - return static_cast<unsigned long>(fs.st_size); + length = static_cast<unsigned long>(fs.st_size); } +#endif + return length; } int SystemTools::Strucmp(const char *s1, const char *s2) @@ -2259,31 +2419,49 @@ int SystemTools::Strucmp(const char *s1, const char *s2) } // return file's modified time -long int SystemTools::ModifiedTime(const char* filename) +long int SystemTools::ModifiedTime(const kwsys_stl::string& filename) { - struct stat fs; - if (stat(filename, &fs) != 0) + long int mt = 0; +#ifdef _WIN32 + WIN32_FILE_ATTRIBUTE_DATA fs; + if (GetFileAttributesExW( + SystemTools::ConvertToWindowsExtendedPath(filename).c_str(), + GetFileExInfoStandard, + &fs) != 0) { - return 0; + mt = windows_filetime_to_posix_time(fs.ftLastWriteTime); } - else +#else + struct stat fs; + if (stat(filename.c_str(), &fs) == 0) { - return static_cast<long int>(fs.st_mtime); + mt = static_cast<long int>(fs.st_mtime); } +#endif + return mt; } // return file's creation time -long int SystemTools::CreationTime(const char* filename) +long int SystemTools::CreationTime(const kwsys_stl::string& filename) { - struct stat fs; - if (stat(filename, &fs) != 0) + long int ct = 0; +#ifdef _WIN32 + WIN32_FILE_ATTRIBUTE_DATA fs; + if (GetFileAttributesExW( + SystemTools::ConvertToWindowsExtendedPath(filename).c_str(), + GetFileExInfoStandard, + &fs) != 0) { - return 0; + ct = windows_filetime_to_posix_time(fs.ftCreationTime); } - else +#else + struct stat fs; + if (stat(filename.c_str(), &fs) == 0) { - return fs.st_ctime >= 0 ? static_cast<long int>(fs.st_ctime) : 0; + ct = fs.st_ctime >= 0 ? static_cast<long int>(fs.st_ctime) : 0; } +#endif + return ct; } bool SystemTools::ConvertDateMacroString(const char *str, time_t *tmt) @@ -2394,7 +2572,7 @@ kwsys_stl::string SystemTools::GetLastSystemError() return strerror(e); } -bool SystemTools::RemoveFile(const char* source) +bool SystemTools::RemoveFile(const kwsys_stl::string& source) { #ifdef _WIN32 mode_t mode; @@ -2406,9 +2584,10 @@ bool SystemTools::RemoveFile(const char* source) SystemTools::SetPermissions(source, S_IWRITE); #endif #ifdef _WIN32 - bool res = _wunlink(Encoding::ToWide(source).c_str()) != 0 ? false : true; + bool res = + _wunlink(SystemTools::ConvertToWindowsExtendedPath(source).c_str()) == 0; #else - bool res = unlink(source) != 0 ? false : true; + bool res = unlink(source.c_str()) != 0 ? false : true; #endif #ifdef _WIN32 if ( !res ) @@ -2419,7 +2598,7 @@ bool SystemTools::RemoveFile(const char* source) return res; } -bool SystemTools::RemoveADirectory(const char* source) +bool SystemTools::RemoveADirectory(const kwsys_stl::string& source) { // Add write permission to the directory so we can modify its // content to remove files and directories from it. @@ -2435,7 +2614,12 @@ bool SystemTools::RemoveADirectory(const char* source) } Directory dir; +#ifdef _WIN32 + dir.Load(Encoding::ToNarrow( + SystemTools::ConvertToWindowsExtendedPath(source))); +#else dir.Load(source); +#endif size_t fileNum; for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) { @@ -2445,17 +2629,17 @@ bool SystemTools::RemoveADirectory(const char* source) kwsys_stl::string fullPath = source; fullPath += "/"; fullPath += dir.GetFile(static_cast<unsigned long>(fileNum)); - if(SystemTools::FileIsDirectory(fullPath.c_str()) && - !SystemTools::FileIsSymlink(fullPath.c_str())) + if(SystemTools::FileIsDirectory(fullPath) && + !SystemTools::FileIsSymlink(fullPath)) { - if (!SystemTools::RemoveADirectory(fullPath.c_str())) + if (!SystemTools::RemoveADirectory(fullPath)) { return false; } } else { - if(!SystemTools::RemoveFile(fullPath.c_str())) + if(!SystemTools::RemoveFile(fullPath)) { return false; } @@ -2517,7 +2701,7 @@ kwsys_stl::string SystemTools { tryPath = *p; tryPath += name; - if(SystemTools::FileExists(tryPath.c_str())) + if(SystemTools::FileExists(tryPath)) { return tryPath; } @@ -2537,7 +2721,7 @@ kwsys_stl::string SystemTools bool no_system_path) { kwsys_stl::string tryPath = SystemTools::FindName(name, userPaths, no_system_path); - if(tryPath != "" && !SystemTools::FileIsDirectory(tryPath.c_str())) + if(!tryPath.empty() && !SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -2556,7 +2740,7 @@ kwsys_stl::string SystemTools bool no_system_path) { kwsys_stl::string tryPath = SystemTools::FindName(name, userPaths, no_system_path); - if(tryPath != "" && SystemTools::FileIsDirectory(tryPath.c_str())) + if(!tryPath.empty() && SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -2578,7 +2762,14 @@ kwsys_stl::string SystemTools::FindProgram( { return ""; } - kwsys_stl::string name = nameIn; + return SystemTools::FindProgram(kwsys_stl::string(nameIn), userPaths, no_system_path); +} + +kwsys_stl::string SystemTools::FindProgram( + const kwsys_stl::string& name, + const kwsys_stl::vector<kwsys_stl::string>& userPaths, + bool no_system_path) +{ kwsys_stl::vector<kwsys_stl::string> extensions; #if defined (_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) bool hasExtension = false; @@ -2603,16 +2794,16 @@ kwsys_stl::string SystemTools::FindProgram( { tryPath = name; tryPath += *i; - if(SystemTools::FileExists(tryPath.c_str()) && - !SystemTools::FileIsDirectory(tryPath.c_str())) + if(SystemTools::FileExists(tryPath) && + !SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } } // now try just the name tryPath = name; - if(SystemTools::FileExists(tryPath.c_str()) && - !SystemTools::FileIsDirectory(tryPath.c_str())) + if(SystemTools::FileExists(tryPath) && + !SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -2658,8 +2849,8 @@ kwsys_stl::string SystemTools::FindProgram( tryPath = *p; tryPath += name; tryPath += *ext; - if(SystemTools::FileExists(tryPath.c_str()) && - !SystemTools::FileIsDirectory(tryPath.c_str())) + if(SystemTools::FileExists(tryPath) && + !SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -2667,8 +2858,8 @@ kwsys_stl::string SystemTools::FindProgram( // now try it without them tryPath = *p; tryPath += name; - if(SystemTools::FileExists(tryPath.c_str()) && - !SystemTools::FileIsDirectory(tryPath.c_str())) + if(SystemTools::FileExists(tryPath) && + !SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -2686,7 +2877,7 @@ kwsys_stl::string SystemTools::FindProgram( it != names.end() ; ++it) { // Try to find the program. - kwsys_stl::string result = SystemTools::FindProgram(it->c_str(), + kwsys_stl::string result = SystemTools::FindProgram(*it, path, noSystemPath); if ( !result.empty() ) @@ -2703,7 +2894,7 @@ kwsys_stl::string SystemTools::FindProgram( * found. Otherwise, the empty string is returned. */ kwsys_stl::string SystemTools -::FindLibrary(const char* name, +::FindLibrary(const kwsys_stl::string& name, const kwsys_stl::vector<kwsys_stl::string>& userPaths) { // See if the executable exists as written. @@ -2744,8 +2935,8 @@ kwsys_stl::string SystemTools tryPath = *p; tryPath += name; tryPath += ".framework"; - if(SystemTools::FileExists(tryPath.c_str()) - && SystemTools::FileIsDirectory(tryPath.c_str())) + if(SystemTools::FileExists(tryPath) + && SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -2754,8 +2945,8 @@ kwsys_stl::string SystemTools tryPath = *p; tryPath += name; tryPath += ".lib"; - if(SystemTools::FileExists(tryPath.c_str()) - && !SystemTools::FileIsDirectory(tryPath.c_str())) + if(SystemTools::FileExists(tryPath) + && !SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -2764,8 +2955,8 @@ kwsys_stl::string SystemTools tryPath += "lib"; tryPath += name; tryPath += ".so"; - if(SystemTools::FileExists(tryPath.c_str()) - && !SystemTools::FileIsDirectory(tryPath.c_str())) + if(SystemTools::FileExists(tryPath) + && !SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -2773,8 +2964,8 @@ kwsys_stl::string SystemTools tryPath += "lib"; tryPath += name; tryPath += ".a"; - if(SystemTools::FileExists(tryPath.c_str()) - && !SystemTools::FileIsDirectory(tryPath.c_str())) + if(SystemTools::FileExists(tryPath) + && !SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -2782,8 +2973,8 @@ kwsys_stl::string SystemTools tryPath += "lib"; tryPath += name; tryPath += ".sl"; - if(SystemTools::FileExists(tryPath.c_str()) - && !SystemTools::FileIsDirectory(tryPath.c_str())) + if(SystemTools::FileExists(tryPath) + && !SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -2791,8 +2982,8 @@ kwsys_stl::string SystemTools tryPath += "lib"; tryPath += name; tryPath += ".dylib"; - if(SystemTools::FileExists(tryPath.c_str()) - && !SystemTools::FileIsDirectory(tryPath.c_str())) + if(SystemTools::FileExists(tryPath) + && !SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -2800,8 +2991,8 @@ kwsys_stl::string SystemTools tryPath += "lib"; tryPath += name; tryPath += ".dll"; - if(SystemTools::FileExists(tryPath.c_str()) - && !SystemTools::FileIsDirectory(tryPath.c_str())) + if(SystemTools::FileExists(tryPath) + && !SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -2812,32 +3003,33 @@ kwsys_stl::string SystemTools return ""; } -kwsys_stl::string SystemTools::GetRealPath(const char* path) +kwsys_stl::string SystemTools::GetRealPath(const kwsys_stl::string& path) { kwsys_stl::string ret; Realpath(path, ret); return ret; } -bool SystemTools::FileIsDirectory(const char* name) +bool SystemTools::FileIsDirectory(const kwsys_stl::string& inName) { - if (!*name) + if (inName.empty()) { return false; } - size_t length = strlen(name); + size_t length = inName.size(); + const char* name = inName.c_str(); // Remove any trailing slash from the name except in a root component. char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH]; std::string string_buffer; size_t last = length-1; if(last > 0 && (name[last] == '/' || name[last] == '\\') - && strcmp(name, "/") !=0 && name[last-1] != ':') + && strcmp(name, "/") != 0 && name[last-1] != ':') { - if(last < sizeof(local_buffer)) + if (last < sizeof(local_buffer)) { memcpy(local_buffer, name, last); - local_buffer[last] = 0; + local_buffer[last] = '\0'; name = local_buffer; } else @@ -2849,7 +3041,8 @@ bool SystemTools::FileIsDirectory(const char* name) // Now check the file node type. #if defined( _WIN32 ) - DWORD attr = GetFileAttributesW(Encoding::ToWide(name).c_str()); + DWORD attr = GetFileAttributesW( + SystemTools::ConvertToWindowsExtendedPath(name).c_str()); if (attr != INVALID_FILE_ATTRIBUTES) { return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; @@ -2866,14 +3059,14 @@ bool SystemTools::FileIsDirectory(const char* name) } } -bool SystemTools::FileIsSymlink(const char* name) +bool SystemTools::FileIsSymlink(const kwsys_stl::string& name) { #if defined( _WIN32 ) (void)name; return false; #else struct stat fs; - if(lstat(name, &fs) == 0) + if(lstat(name.c_str(), &fs) == 0) { return S_ISLNK(fs.st_mode); } @@ -2922,7 +3115,7 @@ bool SystemTools::ReadSymlink(const char* newName, } #endif -int SystemTools::ChangeDirectory(const char *dir) +int SystemTools::ChangeDirectory(const kwsys_stl::string& dir) { return Chdir(dir); } @@ -2959,7 +3152,7 @@ bool SystemTools::SplitProgramPath(const char* in_name, file = ""; SystemTools::ConvertToUnixSlashes(dir); - if(!SystemTools::FileIsDirectory(dir.c_str())) + if(!SystemTools::FileIsDirectory(dir)) { kwsys_stl::string::size_type slashPos = dir.rfind("/"); if(slashPos != kwsys_stl::string::npos) @@ -2973,7 +3166,7 @@ bool SystemTools::SplitProgramPath(const char* in_name, dir = ""; } } - if(!(dir == "") && !SystemTools::FileIsDirectory(dir.c_str())) + if(!(dir.empty()) && !SystemTools::FileIsDirectory(dir)) { kwsys_stl::string oldDir = in_name; SystemTools::ConvertToUnixSlashes(oldDir); @@ -2994,8 +3187,8 @@ bool SystemTools::FindProgramPath(const char* argv0, kwsys_stl::string self = argv0 ? argv0 : ""; failures.push_back(self); SystemTools::ConvertToUnixSlashes(self); - self = SystemTools::FindProgram(self.c_str()); - if(!SystemTools::FileExists(self.c_str())) + self = SystemTools::FindProgram(self); + if(!SystemTools::FileExists(self)) { if(buildDir) { @@ -3013,7 +3206,7 @@ bool SystemTools::FindProgramPath(const char* argv0, } if(installPrefix) { - if(!SystemTools::FileExists(self.c_str())) + if(!SystemTools::FileExists(self)) { failures.push_back(self); self = installPrefix; @@ -3021,7 +3214,7 @@ bool SystemTools::FindProgramPath(const char* argv0, self += exeName; } } - if(!SystemTools::FileExists(self.c_str())) + if(!SystemTools::FileExists(self)) { failures.push_back(self); kwsys_ios::ostringstream msg; @@ -3062,12 +3255,12 @@ void SystemTools::AddTranslationPath(const kwsys_stl::string& a, const kwsys_stl SystemTools::ConvertToUnixSlashes(path_b); // First check this is a directory path, since we don't want the table to // grow too fat - if( SystemTools::FileIsDirectory( path_a.c_str() ) ) + if( SystemTools::FileIsDirectory( path_a ) ) { // Make sure the path is a full path and does not contain no '..' // Ken--the following code is incorrect. .. can be in a valid path // for example /home/martink/MyHubba...Hubba/Src - if( SystemTools::FileIsFullPath(path_b.c_str()) && path_b.find("..") + if( SystemTools::FileIsFullPath(path_b) && path_b.find("..") == kwsys_stl::string::npos ) { // Before inserting make sure path ends with '/' @@ -3224,7 +3417,7 @@ kwsys_stl::string SystemTools::CollapseFullPath(const kwsys_stl::string& in_path } // compute the relative path from here to there -kwsys_stl::string SystemTools::RelativePath(const char* local, const char* remote) +kwsys_stl::string SystemTools::RelativePath(const kwsys_stl::string& local, const kwsys_stl::string& remote) { if(!SystemTools::FileIsFullPath(local)) { @@ -3235,9 +3428,12 @@ kwsys_stl::string SystemTools::RelativePath(const char* local, const char* remot return ""; } + kwsys_stl::string l = SystemTools::CollapseFullPath(local); + kwsys_stl::string r = SystemTools::CollapseFullPath(remote); + // split up both paths into arrays of strings using / as a separator - kwsys_stl::vector<kwsys::String> localSplit = SystemTools::SplitString(local, '/', true); - kwsys_stl::vector<kwsys::String> remoteSplit = SystemTools::SplitString(remote, '/', true); + kwsys_stl::vector<kwsys::String> localSplit = SystemTools::SplitString(l, '/', true); + kwsys_stl::vector<kwsys::String> remoteSplit = SystemTools::SplitString(r, '/', true); kwsys_stl::vector<kwsys::String> commonPath; // store shared parts of path in this array kwsys_stl::vector<kwsys::String> finalPath; // store the final relative path here // count up how many matching directory names there are from the start @@ -3343,6 +3539,16 @@ static int GetCasePathName(const kwsys_stl::string & pathIn, kwsys_stl::string test_str = casePath; test_str += path_components[idx]; + // If path component contains wildcards, we skip matching + // because these filenames are not allowed on windows, + // and we do not want to match a different file. + if(path_components[idx].find('*') != kwsys_stl::string::npos || + path_components[idx].find('?') != kwsys_stl::string::npos) + { + casePath = ""; + return 0; + } + WIN32_FIND_DATAW findData; HANDLE hFind = ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), &findData); @@ -3614,7 +3820,7 @@ bool SystemTools::ComparePath(const kwsys_stl::string& c1, const kwsys_stl::stri } //---------------------------------------------------------------------------- -bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& lines, char separator) +bool SystemTools::Split(const kwsys_stl::string& str, kwsys_stl::vector<kwsys_stl::string>& lines, char separator) { kwsys_stl::string data(str); kwsys_stl::string::size_type lpos = 0; @@ -3638,7 +3844,7 @@ bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& l } //---------------------------------------------------------------------------- -bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& lines) +bool SystemTools::Split(const kwsys_stl::string& str, kwsys_stl::vector<kwsys_stl::string>& lines) { kwsys_stl::string data(str); kwsys_stl::string::size_type lpos = 0; @@ -3931,7 +4137,7 @@ bool SystemTools::LocateFileInDir(const char *filename, } temp += filename_base; - if (SystemTools::FileExists(temp.c_str())) + if (SystemTools::FileExists(temp)) { res = true; filename_found = temp; @@ -3980,9 +4186,18 @@ bool SystemTools::LocateFileInDir(const char *filename, return res; } +bool SystemTools::FileIsFullPath(const kwsys_stl::string& in_name) +{ + return SystemTools::FileIsFullPath(in_name.c_str(), in_name.size()); +} + bool SystemTools::FileIsFullPath(const char* in_name) { - size_t len = strlen(in_name); + return SystemTools::FileIsFullPath(in_name, in_name[0] ? (in_name[1] ? 2 : 1) : 0); +} + +bool SystemTools::FileIsFullPath(const char* in_name, size_t len) +{ #if defined(_WIN32) || defined(__CYGWIN__) // On Windows, the name must be at least two characters long. if(len < 2) @@ -4041,7 +4256,7 @@ bool SystemTools::GetShortPath(const kwsys_stl::string& path, kwsys_stl::string& kwsys_stl::wstring wtempPath = Encoding::ToWide(tempPath); kwsys_stl::vector<wchar_t> buffer(wtempPath.size()+1); buffer[0] = 0; - ret = GetShortPathNameW(Encoding::ToWide(tempPath).c_str(), + ret = GetShortPathNameW(wtempPath.c_str(), &buffer[0], static_cast<DWORD>(wtempPath.size())); if(buffer[0] == 0 || ret > wtempPath.size()) @@ -4091,7 +4306,7 @@ void SystemTools::SplitProgramFromArgs(const char* path, { kwsys_stl::string tryProg = dir.substr(0, spacePos); // See if the file exists - if(SystemTools::FileExists(tryProg.c_str())) + if(SystemTools::FileExists(tryProg)) { program = tryProg; // remove trailing spaces from program @@ -4105,7 +4320,7 @@ void SystemTools::SplitProgramFromArgs(const char* path, return; } // Now try and find the program in the path - findProg = SystemTools::FindProgram(tryProg.c_str(), e); + findProg = SystemTools::FindProgram(tryProg, e); if(!findProg.empty()) { program = findProg; @@ -4277,9 +4492,14 @@ bool SystemTools::GetPermissions(const char* file, mode_t& mode) { return false; } + return SystemTools::GetPermissions(kwsys_stl::string(file), mode); +} +bool SystemTools::GetPermissions(const kwsys_stl::string& file, mode_t& mode) +{ #if defined(_WIN32) - DWORD attr = GetFileAttributesW(Encoding::ToWide(file).c_str()); + DWORD attr = GetFileAttributesW( + SystemTools::ConvertToWindowsExtendedPath(file).c_str()); if(attr == INVALID_FILE_ATTRIBUTES) { return false; @@ -4301,7 +4521,8 @@ bool SystemTools::GetPermissions(const char* file, mode_t& mode) { mode |= S_IFREG; } - const char* ext = strrchr(file, '.'); + size_t dotPos = file.rfind('.'); + const char* ext = dotPos == file.npos ? 0 : (file.c_str() + dotPos); if(ext && (Strucmp(ext, ".exe") == 0 || Strucmp(ext, ".com") == 0 || Strucmp(ext, ".cmd") == 0 || @@ -4311,7 +4532,7 @@ bool SystemTools::GetPermissions(const char* file, mode_t& mode) } #else struct stat st; - if ( stat(file, &st) < 0 ) + if ( stat(file.c_str(), &st) < 0 ) { return false; } @@ -4326,14 +4547,20 @@ bool SystemTools::SetPermissions(const char* file, mode_t mode) { return false; } + return SystemTools::SetPermissions(kwsys_stl::string(file), mode); +} + +bool SystemTools::SetPermissions(const kwsys_stl::string& file, mode_t mode) +{ if ( !SystemTools::FileExists(file) ) { return false; } #ifdef _WIN32 - if ( _wchmod(Encoding::ToWide(file).c_str(), mode) < 0 ) + if ( _wchmod(SystemTools::ConvertToWindowsExtendedPath(file).c_str(), + mode) < 0 ) #else - if ( chmod(file, mode) < 0 ) + if ( chmod(file.c_str(), mode) < 0 ) #endif { return false; @@ -4342,7 +4569,7 @@ bool SystemTools::SetPermissions(const char* file, mode_t mode) return true; } -kwsys_stl::string SystemTools::GetParentDirectory(const char* fileOrDir) +kwsys_stl::string SystemTools::GetParentDirectory(const kwsys_stl::string& fileOrDir) { return SystemTools::GetFilenamePath(fileOrDir); } @@ -4389,111 +4616,6 @@ void SystemTools::Delay(unsigned int msec) #endif } -void SystemTools::ConvertWindowsCommandLineToUnixArguments( - const char *cmd_line, int *argc, char ***argv) -{ - if (!cmd_line || !argc || !argv) - { - return; - } - - // A space delimites an argument except when it is inside a quote - - (*argc) = 1; - - size_t cmd_line_len = strlen(cmd_line); - - size_t i; - for (i = 0; i < cmd_line_len; i++) - { - while (isspace(cmd_line[i]) && i < cmd_line_len) - { - i++; - } - if (i < cmd_line_len) - { - if (cmd_line[i] == '\"') - { - i++; - while (cmd_line[i] != '\"' && i < cmd_line_len) - { - i++; - } - (*argc)++; - } - else - { - while (!isspace(cmd_line[i]) && i < cmd_line_len) - { - i++; - } - (*argc)++; - } - } - } - - (*argv) = new char* [(*argc) + 1]; - (*argv)[(*argc)] = NULL; - - // Set the first arg to be the exec name - - (*argv)[0] = new char [1024]; -#ifdef _WIN32 - wchar_t tmp[1024]; - ::GetModuleFileNameW(0, tmp, 1024); - strcpy((*argv)[0], Encoding::ToNarrow(tmp).c_str()); -#else - (*argv)[0][0] = '\0'; -#endif - - // Allocate the others - - int j; - for (j = 1; j < (*argc); j++) - { - (*argv)[j] = new char [cmd_line_len + 10]; - } - - // Grab the args - - size_t pos; - int argc_idx = 1; - - for (i = 0; i < cmd_line_len; i++) - { - while (isspace(cmd_line[i]) && i < cmd_line_len) - { - i++; - } - if (i < cmd_line_len) - { - if (cmd_line[i] == '\"') - { - i++; - pos = i; - while (cmd_line[i] != '\"' && i < cmd_line_len) - { - i++; - } - memcpy((*argv)[argc_idx], &cmd_line[pos], i - pos); - (*argv)[argc_idx][i - pos] = '\0'; - argc_idx++; - } - else - { - pos = i; - while (!isspace(cmd_line[i]) && i < cmd_line_len) - { - i++; - } - memcpy((*argv)[argc_idx], &cmd_line[pos], i - pos); - (*argv)[argc_idx][i - pos] = '\0'; - argc_idx++; - } - } - } - } - kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion() { kwsys_stl::string res; @@ -4510,6 +4632,10 @@ kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion() ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXA)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); +#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx +# pragma warning (push) +# pragma warning (disable:4996) +#endif bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi); if (!bOsVersionInfoEx) { @@ -4519,6 +4645,9 @@ kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion() return 0; } } +#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx +# pragma warning (pop) +#endif switch (osvi.dwPlatformId) { diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index fb55848..e88bc8f 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -158,7 +158,9 @@ public: * Returns true if str1 starts (respectively ends) with str2 */ static bool StringStartsWith(const char* str1, const char* str2); + static bool StringStartsWith(const kwsys_stl::string& str1, const char* str2); static bool StringEndsWith(const char* str1, const char* str2); + static bool StringEndsWith(const kwsys_stl::string& str1, const char* str2); /** * Returns a pointer to the last occurence of str2 in str1 @@ -183,7 +185,7 @@ public: s starts with a / then the first element of the returned array will be /, so /foo/bar will be [/, foo, bar] */ - static kwsys_stl::vector<String> SplitString(const char* s, char separator = '/', + static kwsys_stl::vector<String> SplitString(const kwsys_stl::string& s, char separator = '/', bool isPath = false); /** * Perform a case-independent string comparison @@ -201,8 +203,8 @@ public: * Split a string on its newlines into multiple lines * Return false only if the last line stored had no newline */ - static bool Split(const char* s, kwsys_stl::vector<kwsys_stl::string>& l); - static bool Split(const char* s, kwsys_stl::vector<kwsys_stl::string>& l, char separator); + static bool Split(const kwsys_stl::string& s, kwsys_stl::vector<kwsys_stl::string>& l); + static bool Split(const kwsys_stl::string& s, kwsys_stl::vector<kwsys_stl::string>& l, char separator); /** * Return string with space added between capitalized words @@ -249,18 +251,29 @@ public: * Replace Windows file system slashes with Unix-style slashes. */ static void ConvertToUnixSlashes(kwsys_stl::string& path); - + +#ifdef _WIN32 + /** + * Convert the path to an extended length path to avoid MAX_PATH length + * limitations on Windows. If the input is a local path the result will be + * prefixed with \\?\; if the input is instead a network path, the result + * will be prefixed with \\?\UNC\. All output will also be converted to + * absolute paths with Windows-style backslashes. + **/ + static kwsys_stl::wstring ConvertToWindowsExtendedPath(const kwsys_stl::string&); +#endif + /** * For windows this calls ConvertToWindowsOutputPath and for unix * it calls ConvertToUnixOutputPath */ - static kwsys_stl::string ConvertToOutputPath(const char*); + static kwsys_stl::string ConvertToOutputPath(const kwsys_stl::string&); /** * Convert the path to a string that can be used in a unix makefile. * double slashes are removed, and spaces are escaped. */ - static kwsys_stl::string ConvertToUnixOutputPath(const char*); + static kwsys_stl::string ConvertToUnixOutputPath(const kwsys_stl::string&); /** * Convert the path to string that can be used in a windows project or @@ -268,7 +281,7 @@ public: * the string, the slashes are converted to windows style backslashes, and * if there are spaces in the string it is double quoted. */ - static kwsys_stl::string ConvertToWindowsOutputPath(const char*); + static kwsys_stl::string ConvertToWindowsOutputPath(const kwsys_stl::string&); /** * Return true if a file exists in the current directory. @@ -277,7 +290,9 @@ public: * if it is a file or a directory. */ static bool FileExists(const char* filename, bool isFile); + static bool FileExists(const kwsys_stl::string& filename, bool isFile); static bool FileExists(const char* filename); + static bool FileExists(const kwsys_stl::string& filename); /** * Converts Cygwin path to Win32 path. Uses dictionary container for @@ -296,7 +311,7 @@ public: /** Change the modification time or create a file */ - static bool Touch(const char* filename, bool create); + static bool Touch(const kwsys_stl::string& filename, bool create); /** * Compare file modification times. @@ -304,7 +319,8 @@ public: * When true is returned, result has -1, 0, +1 for * f1 older, same, or newer than f2. */ - static bool FileTimeCompare(const char* f1, const char* f2, + static bool FileTimeCompare(const kwsys_stl::string& f1, + const kwsys_stl::string& f2, int* result); /** @@ -366,7 +382,7 @@ public: * the event of an error (non-existent path, permissions issue, * etc.) the original path is returned. */ - static kwsys_stl::string GetRealPath(const char* path); + static kwsys_stl::string GetRealPath(const kwsys_stl::string& path); /** * Split a path name into its root component and the rest of the @@ -459,6 +475,7 @@ public: /** * Return whether the path represents a full path (not relative) */ + static bool FileIsFullPath(const kwsys_stl::string&); static bool FileIsFullPath(const char*); /** @@ -482,7 +499,7 @@ public: /** * Get the parent directory of the directory or file */ - static kwsys_stl::string GetParentDirectory(const char* fileOrDir); + static kwsys_stl::string GetParentDirectory(const kwsys_stl::string& fileOrDir); /** * Check if the given file or directory is in subdirectory of dir @@ -497,7 +514,7 @@ public: /** * Open a file considering unicode. */ - static FILE* Fopen(const char* file, const char* mode); + static FILE* Fopen(const kwsys_stl::string& file, const char* mode); /** * Make a new directory if it is not there. This function @@ -505,35 +522,36 @@ public: * prior to calling this function. */ static bool MakeDirectory(const char* path); + static bool MakeDirectory(const kwsys_stl::string& path); /** * Copy the source file to the destination file only * if the two files differ. */ - static bool CopyFileIfDifferent(const char* source, - const char* destination); + static bool CopyFileIfDifferent(const kwsys_stl::string& source, + const kwsys_stl::string& destination); /** * Compare the contents of two files. Return true if different */ - static bool FilesDiffer(const char* source, const char* destination); + static bool FilesDiffer(const kwsys_stl::string& source, const kwsys_stl::string& destination); /** * Return true if the two files are the same file */ - static bool SameFile(const char* file1, const char* file2); + static bool SameFile(const kwsys_stl::string& file1, const kwsys_stl::string& file2); /** * Copy a file. */ - static bool CopyFileAlways(const char* source, const char* destination); + static bool CopyFileAlways(const kwsys_stl::string& source, const kwsys_stl::string& destination); /** * Copy a file. If the "always" argument is true the file is always * copied. If it is false, the file is copied only if it is new or * has changed. */ - static bool CopyAFile(const char* source, const char* destination, + static bool CopyAFile(const kwsys_stl::string& source, const kwsys_stl::string& destination, bool always = true); /** @@ -542,18 +560,18 @@ public: * always copied. If it is false, only files that have changed or * are new are copied. */ - static bool CopyADirectory(const char* source, const char* destination, + static bool CopyADirectory(const kwsys_stl::string& source, const kwsys_stl::string& destination, bool always = true); /** * Remove a file */ - static bool RemoveFile(const char* source); + static bool RemoveFile(const kwsys_stl::string& source); /** * Remove a directory */ - static bool RemoveADirectory(const char* source); + static bool RemoveADirectory(const kwsys_stl::string& source); /** * Get the maximum full file path length @@ -583,12 +601,17 @@ public: */ static kwsys_stl::string FindProgram( const char* name, - const kwsys_stl::vector<kwsys_stl::string>& path = + const kwsys_stl::vector<kwsys_stl::string>& path = + kwsys_stl::vector<kwsys_stl::string>(), + bool no_system_path = false); + static kwsys_stl::string FindProgram( + const kwsys_stl::string& name, + const kwsys_stl::vector<kwsys_stl::string>& path = kwsys_stl::vector<kwsys_stl::string>(), bool no_system_path = false); static kwsys_stl::string FindProgram( const kwsys_stl::vector<kwsys_stl::string>& names, - const kwsys_stl::vector<kwsys_stl::string>& path = + const kwsys_stl::vector<kwsys_stl::string>& path = kwsys_stl::vector<kwsys_stl::string>(), bool no_system_path = false); @@ -596,18 +619,18 @@ public: * Find a library in the system PATH, with optional extra paths */ static kwsys_stl::string FindLibrary( - const char* name, + const kwsys_stl::string& name, const kwsys_stl::vector<kwsys_stl::string>& path); /** * Return true if the file is a directory */ - static bool FileIsDirectory(const char* name); + static bool FileIsDirectory(const kwsys_stl::string& name); /** * Return true if the file is a symlink */ - static bool FileIsSymlink(const char* name); + static bool FileIsSymlink(const kwsys_stl::string& name); /** * Return true if the file has a given signature (first set of bytes) @@ -675,17 +698,17 @@ public: /a/b/c/d to /a/b/c1/d1 -> ../../c1/d1 from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp */ - static kwsys_stl::string RelativePath(const char* local, const char* remote); + static kwsys_stl::string RelativePath(const kwsys_stl::string& local, const kwsys_stl::string& remote); /** * Return file's modified time */ - static long int ModifiedTime(const char* filename); + static long int ModifiedTime(const kwsys_stl::string& filename); /** * Return file's creation time (Win32: works only for NTFS, not FAT) */ - static long int CreationTime(const char* filename); + static long int CreationTime(const kwsys_stl::string& filename); #if defined( _MSC_VER ) typedef unsigned short mode_t; @@ -695,7 +718,9 @@ public: * Get and set permissions of the file. */ static bool GetPermissions(const char* file, mode_t& mode); + static bool GetPermissions(const kwsys_stl::string& file, mode_t& mode); static bool SetPermissions(const char* file, mode_t mode); + static bool SetPermissions(const kwsys_stl::string& file, mode_t mode); /** ----------------------------------------------------------------- * Time Manipulation Routines @@ -782,7 +807,7 @@ public: /** * Change directory to the directory specified */ - static int ChangeDirectory(const char* dir); + static int ChangeDirectory(const kwsys_stl::string& dir); /** * Get the result of strerror(errno) @@ -831,15 +856,6 @@ public: */ static kwsys_stl::string GetOperatingSystemNameAndVersion(); - /** - * Convert windows-style arguments given as a command-line string - * into more traditional argc/argv arguments. - * Note that argv[0] will be assigned the executable name using - * the GetModuleFileName() function. - */ - static void ConvertWindowsCommandLineToUnixArguments( - const char *cmd_line, int *argc, char ***argv); - /** ----------------------------------------------------------------- * URL Manipulation Routines * ----------------------------------------------------------------- @@ -890,6 +906,11 @@ private: } /** + * Actual implementation of FileIsFullPath. + */ + static bool FileIsFullPath(const char*, size_t); + + /** * Find a filename (file or directory) in the system PATH, with * optional extra paths. */ diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c index 6d7ec41..e13003f 100644 --- a/Source/kwsys/Terminal.c +++ b/Source/kwsys/Terminal.c @@ -104,11 +104,11 @@ void kwsysTerminal_cfprintf(int color, FILE* stream, const char* format, ...) } /*--------------------------------------------------------------------------*/ -/* Detect cases when a stream is definately not interactive. */ +/* Detect cases when a stream is definitely not interactive. */ #if !defined(KWSYS_TERMINAL_ISATTY_WORKS) static int kwsysTerminalStreamIsNotInteractive(FILE* stream) { - /* The given stream is definately not interactive if it is a regular + /* The given stream is definitely not interactive if it is a regular file. */ struct stat stream_stat; if(fstat(fileno(stream), &stream_stat) == 0) @@ -212,7 +212,7 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100, (void)default_tty; return isatty(fileno(stream))? 1:0; #else - /* Check for cases in which the stream is definately not a tty. */ + /* Check for cases in which the stream is definitely not a tty. */ if(kwsysTerminalStreamIsNotInteractive(stream)) { return 0; diff --git a/Source/kwsys/kwsysPlatformTests.cmake b/Source/kwsys/kwsysPlatformTests.cmake index f9ee254..16bc969 100644 --- a/Source/kwsys/kwsysPlatformTests.cmake +++ b/Source/kwsys/kwsysPlatformTests.cmake @@ -13,7 +13,7 @@ SET(KWSYS_PLATFORM_TEST_FILE_C kwsysPlatformTestsC.c) SET(KWSYS_PLATFORM_TEST_FILE_CXX kwsysPlatformTestsCXX.cxx) MACRO(KWSYS_PLATFORM_TEST lang var description invert) - IF("${var}_COMPILED" MATCHES "^${var}_COMPILED$") + IF(NOT DEFINED ${var}_COMPILED) MESSAGE(STATUS "${description}") TRY_COMPILE(${var}_COMPILED ${CMAKE_CURRENT_BINARY_DIR} @@ -43,7 +43,7 @@ MACRO(KWSYS_PLATFORM_TEST lang var description invert) MESSAGE(STATUS "${description} - no") ENDIF(${var}_COMPILED) ENDIF(${invert} MATCHES INVERT) - ENDIF("${var}_COMPILED" MATCHES "^${var}_COMPILED$") + ENDIF() IF(${invert} MATCHES INVERT) IF(${var}_COMPILED) SET(${var} 0) @@ -60,7 +60,7 @@ MACRO(KWSYS_PLATFORM_TEST lang var description invert) ENDMACRO(KWSYS_PLATFORM_TEST) MACRO(KWSYS_PLATFORM_TEST_RUN lang var description invert) - IF("${var}" MATCHES "^${var}$") + IF(NOT DEFINED ${var}) MESSAGE(STATUS "${description}") TRY_RUN(${var} ${var}_COMPILED ${CMAKE_CURRENT_BINARY_DIR} @@ -107,7 +107,7 @@ MACRO(KWSYS_PLATFORM_TEST_RUN lang var description invert) MESSAGE(STATUS "${description} - failed to compile") ENDIF(${var}_COMPILED) ENDIF(${invert} MATCHES INVERT) - ENDIF("${var}" MATCHES "^${var}$") + ENDIF() IF(${invert} MATCHES INVERT) IF(${var}_COMPILED) diff --git a/Source/kwsys/testCommandLineArguments1.cxx b/Source/kwsys/testCommandLineArguments1.cxx index 3b84c38..b65c37f 100644 --- a/Source/kwsys/testCommandLineArguments1.cxx +++ b/Source/kwsys/testCommandLineArguments1.cxx @@ -21,6 +21,7 @@ # include "kwsys_ios_iostream.h.in" #endif +#include <assert.h> /* assert */ #include <string.h> /* strcmp */ int testCommandLineArguments1(int argc, char* argv[]) @@ -83,6 +84,7 @@ int testCommandLineArguments1(int argc, char* argv[]) } for ( cc = 0; cc < newArgc; ++ cc ) { + assert(newArgv[cc]); /* Quiet Clang scan-build. */ kwsys_ios::cout << "Unused argument[" << cc << "] = [" << newArgv[cc] << "]" << kwsys_ios::endl; if ( cc >= 9 ) diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx index 1bff707..58adb84 100644 --- a/Source/kwsys/testDynamicLoader.cxx +++ b/Source/kwsys/testDynamicLoader.cxx @@ -108,7 +108,7 @@ int testDynamicLoader(int argc, char *argv[]) // Make sure that inexistent lib is giving correct result res += TestDynamicLoader("azerty_", "foo_bar",0,0,0); // Make sure that random binary file cannot be assimilated as dylib - res += TestDynamicLoader(TEST_SYSTEMTOOLS_BIN_FILE, "wp",0,0,0); + res += TestDynamicLoader(TEST_SYSTEMTOOLS_SOURCE_DIR "/testSystemTools.bin", "wp",0,0,0); #endif #ifdef __linux__ diff --git a/Source/kwsys/testProcess.c b/Source/kwsys/testProcess.c index 6d5eb71..47c3fb0 100644 --- a/Source/kwsys/testProcess.c +++ b/Source/kwsys/testProcess.c @@ -11,13 +11,16 @@ ============================================================================*/ #include "kwsysPrivate.h" #include KWSYS_HEADER(Process.h) +#include KWSYS_HEADER(Encoding.h) /* Work-around CMake dependency scanning limitation. This must duplicate the above list of headers. */ #if 0 # include "Process.h.in" +# include "Encoding.h.in" #endif +#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -102,6 +105,7 @@ static int test4(int argc, const char* argv[]) fprintf(stderr, "Output before crash on stderr from crash test.\n"); fflush(stdout); fflush(stderr); + assert(invalidAddress); /* Quiet Clang scan-build. */ /* Provoke deliberate crash by writing to the invalid address. */ *invalidAddress = 0; fprintf(stdout, "Output after crash on stdout from crash test.\n"); @@ -393,6 +397,19 @@ int runChild(const char* cmd[], int state, int exception, int value, int main(int argc, const char* argv[]) { int n = 0; + +#ifdef _WIN32 + int i; + char new_args[10][_MAX_PATH]; + LPWSTR* w_av = CommandLineToArgvW(GetCommandLineW(), &argc); + for(i=0; i<argc; i++) + { + kwsysEncoding_wcstombs(new_args[i], w_av[i], _MAX_PATH); + argv[i] = new_args[i]; + } + LocalFree(w_av); +#endif + #if 0 { HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index 69825a8..b41532b 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -98,32 +98,124 @@ static bool CheckEscapeChars(kwsys_stl::string input, static bool CheckFileOperations() { bool res = true; - - if (kwsys::SystemTools::DetectFileType(TEST_SYSTEMTOOLS_BIN_FILE) != + const kwsys_stl::string testBinFile(TEST_SYSTEMTOOLS_SOURCE_DIR + "/testSystemTools.bin"); + const kwsys_stl::string testTxtFile(TEST_SYSTEMTOOLS_SOURCE_DIR + "/testSystemTools.cxx"); + const kwsys_stl::string testNewDir(TEST_SYSTEMTOOLS_BINARY_DIR + "/testSystemToolsNewDir"); + const kwsys_stl::string testNewFile(testNewDir + "/testNewFile.txt"); + + if (kwsys::SystemTools::DetectFileType(testBinFile.c_str()) != kwsys::SystemTools::FileTypeBinary) { kwsys_ios::cerr << "Problem with DetectFileType - failed to detect type of: " - << TEST_SYSTEMTOOLS_BIN_FILE << kwsys_ios::endl; + << testBinFile << kwsys_ios::endl; res = false; } - if (kwsys::SystemTools::DetectFileType(TEST_SYSTEMTOOLS_SRC_FILE) != + if (kwsys::SystemTools::DetectFileType(testTxtFile.c_str()) != kwsys::SystemTools::FileTypeText) { kwsys_ios::cerr << "Problem with DetectFileType - failed to detect type of: " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << testTxtFile << kwsys_ios::endl; res = false; } - - if (kwsys::SystemTools::FileLength(TEST_SYSTEMTOOLS_BIN_FILE) != 766) + + if (kwsys::SystemTools::FileLength(testBinFile.c_str()) != 766) { kwsys_ios::cerr << "Problem with FileLength - incorrect length for: " - << TEST_SYSTEMTOOLS_BIN_FILE << kwsys_ios::endl; - res = false; + << testBinFile << kwsys_ios::endl; + res = false; + } + + if (!kwsys::SystemTools::MakeDirectory(testNewDir)) + { + kwsys_ios::cerr + << "Problem with MakeDirectory for: " + << testNewDir << kwsys_ios::endl; + res = false; + } + + if (!kwsys::SystemTools::Touch(testNewFile.c_str(), true)) + { + kwsys_ios::cerr + << "Problem with Touch for: " + << testNewFile << kwsys_ios::endl; + res = false; + } + + if (!kwsys::SystemTools::RemoveFile(testNewFile)) + { + kwsys_ios::cerr + << "Problem with RemoveFile: " + << testNewFile << kwsys_ios::endl; + res = false; + } + + kwsys::SystemTools::Touch(testNewFile.c_str(), true); + if (!kwsys::SystemTools::RemoveADirectory(testNewDir)) + { + kwsys_ios::cerr + << "Problem with RemoveADirectory for: " + << testNewDir << kwsys_ios::endl; + res = false; + } + +#ifdef KWSYS_TEST_SYSTEMTOOLS_LONG_PATHS + // Perform the same file and directory creation and deletion tests but + // with paths > 256 characters in length. + + const kwsys_stl::string testNewLongDir( + TEST_SYSTEMTOOLS_BINARY_DIR "/" + "012345678901234567890123456789012345678901234567890123456789" + "012345678901234567890123456789012345678901234567890123456789" + "012345678901234567890123456789012345678901234567890123456789" + "012345678901234567890123456789012345678901234567890123456789" + "01234567890123"); + const kwsys_stl::string testNewLongFile(testNewLongDir + "/" + "012345678901234567890123456789012345678901234567890123456789" + "012345678901234567890123456789012345678901234567890123456789" + "012345678901234567890123456789012345678901234567890123456789" + "012345678901234567890123456789012345678901234567890123456789" + "0123456789.txt"); + + if (!kwsys::SystemTools::MakeDirectory(testNewLongDir)) + { + kwsys_ios::cerr + << "Problem with MakeDirectory for: " + << testNewLongDir << kwsys_ios::endl; + res = false; + } + + if (!kwsys::SystemTools::Touch(testNewLongFile.c_str(), true)) + { + kwsys_ios::cerr + << "Problem with Touch for: " + << testNewLongFile << kwsys_ios::endl; + res = false; + } + + if (!kwsys::SystemTools::RemoveFile(testNewLongFile)) + { + kwsys_ios::cerr + << "Problem with RemoveFile: " + << testNewLongFile << kwsys_ios::endl; + res = false; + } + + kwsys::SystemTools::Touch(testNewLongFile.c_str(), true); + if (!kwsys::SystemTools::RemoveADirectory(testNewLongDir)) + { + kwsys_ios::cerr + << "Problem with RemoveADirectory for: " + << testNewLongDir << kwsys_ios::endl; + res = false; } +#endif return res; } @@ -138,7 +230,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with CapitalizedWords " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << '"' << test << '"' << kwsys_ios::endl; res = false; } @@ -148,7 +240,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with UnCapitalizedWords " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << '"' << test << '"' << kwsys_ios::endl; res = false; } @@ -158,7 +250,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with AddSpaceBetweenCapitalizedWords " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << '"' << test << '"' << kwsys_ios::endl; res = false; } @@ -168,7 +260,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with AppendStrings " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << "\"Mary Had A\" \" Little Lamb.\"" << kwsys_ios::endl; res = false; } delete [] cres; @@ -179,7 +271,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with AppendStrings " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << "\"Mary Had\" \" A \" \"Little Lamb.\"" << kwsys_ios::endl; res = false; } delete [] cres; @@ -188,7 +280,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with CountChar " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << "\"Mary Had A Little Lamb.\"" << kwsys_ios::endl; res = false; } @@ -198,7 +290,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with RemoveChars " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << "\"Mary Had A Little Lamb.\"" << kwsys_ios::endl; res = false; } delete [] cres; @@ -209,7 +301,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with RemoveCharsButUpperHex " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << "\"Mary Had A Little Lamb.\"" << kwsys_ios::endl; res = false; } delete [] cres; @@ -221,7 +313,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with ReplaceChars " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << "\"Mary Had A Little Lamb.\"" << kwsys_ios::endl; res = false; } delete [] cres2; @@ -231,7 +323,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with StringStartsWith " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << "\"Mary Had A Little Lamb.\"" << kwsys_ios::endl; res = false; } @@ -240,7 +332,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with StringEndsWith " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << "\"Mary Had A Little Lamb.\"" << kwsys_ios::endl; res = false; } @@ -249,7 +341,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with DuplicateString " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << "\"Mary Had A Little Lamb.\"" << kwsys_ios::endl; res = false; } delete [] cres; @@ -260,7 +352,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with CropString " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; + << "\"Mary Had A Little Lamb.\"" << kwsys_ios::endl; res = false; } @@ -271,16 +363,124 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with Split " - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; - res = false; + << "\"Mary Had A Little Lamb.\"" << kwsys_ios::endl; + res = false; + } + +#ifdef _WIN32 + if (kwsys::SystemTools::ConvertToWindowsExtendedPath + ("L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") != + L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") + { + kwsys_ios::cerr + << "Problem with ConvertToWindowsExtendedPath " + << "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"" + << kwsys_ios::endl; + res = false; + } + + if (kwsys::SystemTools::ConvertToWindowsExtendedPath + ("L:/Local Mojo/Hex Power Pack/Iffy Voodoo") != + L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") + { + kwsys_ios::cerr + << "Problem with ConvertToWindowsExtendedPath " + << "\"L:/Local Mojo/Hex Power Pack/Iffy Voodoo\"" + << kwsys_ios::endl; + res = false; + } + + if (kwsys::SystemTools::ConvertToWindowsExtendedPath + ("\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") != + L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") + { + kwsys_ios::cerr + << "Problem with ConvertToWindowsExtendedPath " + << "\"\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"" + << kwsys_ios::endl; + res = false; + } + + if (kwsys::SystemTools::ConvertToWindowsExtendedPath + ("//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo") != + L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") + { + kwsys_ios::cerr + << "Problem with ConvertToWindowsExtendedPath " + << "\"//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo\"" + << kwsys_ios::endl; + res = false; } + if (kwsys::SystemTools::ConvertToWindowsExtendedPath("//") != + L"//") + { + kwsys_ios::cerr + << "Problem with ConvertToWindowsExtendedPath " + << "\"//\"" + << kwsys_ios::endl; + res = false; + } + + if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\") != + L"\\\\.\\") + { + kwsys_ios::cerr + << "Problem with ConvertToWindowsExtendedPath " + << "\"\\\\.\\\"" + << kwsys_ios::endl; + res = false; + } + + if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\X") != + L"\\\\.\\X") + { + kwsys_ios::cerr + << "Problem with ConvertToWindowsExtendedPath " + << "\"\\\\.\\X\"" + << kwsys_ios::endl; + res = false; + } + + if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\X:") != + L"\\\\?\\X:") + { + kwsys_ios::cerr + << "Problem with ConvertToWindowsExtendedPath " + << "\"\\\\.\\X:\"" + << kwsys_ios::endl; + res = false; + } + + if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\X:\\") != + L"\\\\?\\X:\\") + { + kwsys_ios::cerr + << "Problem with ConvertToWindowsExtendedPath " + << "\"\\\\.\\X:\\\"" + << kwsys_ios::endl; + res = false; + } + + if (kwsys::SystemTools::ConvertToWindowsExtendedPath("NUL") != + L"\\\\.\\NUL") + { + kwsys_ios::cerr + << "Problem with ConvertToWindowsExtendedPath " + << "\"NUL\"" + << kwsys_ios::endl; + res = false; + } + +#endif + if (kwsys::SystemTools::ConvertToWindowsOutputPath ("L://Local Mojo/Hex Power Pack/Iffy Voodoo") != "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"") { kwsys_ios::cerr << "Problem with ConvertToWindowsOutputPath " + << "\"L://Local Mojo/Hex Power Pack/Iffy Voodoo\"" << kwsys_ios::endl; res = false; } @@ -291,6 +491,7 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with ConvertToWindowsOutputPath " + << "\"//grayson/Local Mojo/Hex Power Pack/Iffy Voodoo\"" << kwsys_ios::endl; res = false; } @@ -301,29 +502,11 @@ static bool CheckStringOperations() { kwsys_ios::cerr << "Problem with ConvertToUnixOutputPath " + << "\"//Local Mojo/Hex Power Pack/Iffy Voodoo\"" << kwsys_ios::endl; res = false; } - int targc; - char **targv; - kwsys::SystemTools::ConvertWindowsCommandLineToUnixArguments - ("\"Local Mojo\\Voodoo.asp\" -CastHex \"D:\\My Secret Mojo\\Voodoo.mp3\"", &targc, &targv); - if (targc != 4 || strcmp(targv[1],"Local Mojo\\Voodoo.asp") || - strcmp(targv[2],"-CastHex") || - strcmp(targv[3],"D:\\My Secret Mojo\\Voodoo.mp3")) - { - kwsys_ios::cerr - << "Problem with ConvertWindowsCommandLineToUnixArguments" - << TEST_SYSTEMTOOLS_SRC_FILE << kwsys_ios::endl; - res = false; - } - for (;targc >=0; --targc) - { - delete [] targv[targc]; - } - delete [] targv; - return res; } @@ -379,6 +562,55 @@ static bool CheckEnvironmentOperations() return res; } + +static bool CheckRelativePath( + const kwsys_stl::string& local, + const kwsys_stl::string& remote, + const kwsys_stl::string& expected) +{ + kwsys_stl::string result = kwsys::SystemTools::RelativePath(local, remote); + if(expected != result) + { + kwsys_ios::cerr << "RelativePath(" << local << ", " << remote + << ") yielded " << result << " instead of " << expected << kwsys_ios::endl; + return false; + } + return true; +} + +static bool CheckRelativePaths() +{ + bool res = true; + res &= CheckRelativePath("/usr/share", "/bin/bash", "../../bin/bash"); + res &= CheckRelativePath("/usr/./share/", "/bin/bash", "../../bin/bash"); + res &= CheckRelativePath("/usr//share/", "/bin/bash", "../../bin/bash"); + res &= CheckRelativePath("/usr/share/../bin/", "/bin/bash", "../../bin/bash"); + res &= CheckRelativePath("/usr/share", "/usr/share//bin", "bin"); + return res; +} + +static bool CheckCollapsePath( + const kwsys_stl::string& path, + const kwsys_stl::string& expected) +{ + kwsys_stl::string result = kwsys::SystemTools::CollapseFullPath(path); + if(expected != result) + { + kwsys_ios::cerr << "CollapseFullPath(" << path + << ") yielded " << result << " instead of " << expected << kwsys_ios::endl; + return false; + } + return true; +} + +static bool CheckCollapsePath() +{ + bool res = true; + res &= CheckCollapsePath("/usr/share/*", "/usr/share/*"); + res &= CheckCollapsePath("C:/Windows/*", "C:/Windows/*"); + return res; +} + //---------------------------------------------------------------------------- int testSystemTools(int, char*[]) { @@ -410,5 +642,9 @@ int testSystemTools(int, char*[]) res &= CheckEnvironmentOperations(); + res &= CheckRelativePaths(); + + res &= CheckCollapsePath(); + return res ? 0 : 1; } diff --git a/Source/kwsys/testSystemTools.h.in b/Source/kwsys/testSystemTools.h.in index 4b94bb6..66f0f72 100644 --- a/Source/kwsys/testSystemTools.h.in +++ b/Source/kwsys/testSystemTools.h.in @@ -14,7 +14,8 @@ #define EXECUTABLE_OUTPUT_PATH "@CMAKE_CURRENT_BINARY_DIR@" -#define TEST_SYSTEMTOOLS_BIN_FILE "@TEST_SYSTEMTOOLS_BIN_FILE@" -#define TEST_SYSTEMTOOLS_SRC_FILE "@TEST_SYSTEMTOOLS_SRC_FILE@" +#define TEST_SYSTEMTOOLS_SOURCE_DIR "@TEST_SYSTEMTOOLS_SOURCE_DIR@" +#define TEST_SYSTEMTOOLS_BINARY_DIR "@TEST_SYSTEMTOOLS_BINARY_DIR@" +#cmakedefine KWSYS_TEST_SYSTEMTOOLS_LONG_PATHS #endif |