diff options
Diffstat (limited to 'Source')
108 files changed, 3211 insertions, 659 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 570b7e2..17fb52d 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -188,6 +188,8 @@ set(SRCS cmExtraCodeBlocksGenerator.h cmExtraEclipseCDT4Generator.cxx cmExtraEclipseCDT4Generator.h + cmExtraKateGenerator.cxx + cmExtraKateGenerator.h cmExtraSublimeTextGenerator.cxx cmExtraSublimeTextGenerator.h cmFileTimeComparison.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 4340ad7..d507535 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 12) -set(CMake_VERSION_TWEAK 20131114) +set(CMake_VERSION_TWEAK 20131205) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 1d7681b..91701c2 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -198,6 +198,18 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() << std::endl); } + if(GetOption("CPACK_WIX_UI_REF") == 0) + { + std::string defaultRef = "WixUI_InstallDir"; + + if(Components.size()) + { + defaultRef = "WixUI_FeatureTree"; + } + + SetOption("CPACK_WIX_UI_REF", defaultRef.c_str()); + } + CollectExtensions("CPACK_WIX_EXTENSIONS", candleExtensions); CollectExtensions("CPACK_WIX_CANDLE_EXTENSIONS", candleExtensions); @@ -296,6 +308,7 @@ bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() SetOptionIfNotSet("CPACK_WIX_PROGRAM_MENU_FOLDER", GetOption("CPACK_PACKAGE_NAME")); CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER"); + CopyDefinition(includeFile, "CPACK_WIX_UI_REF"); return true; } @@ -401,40 +414,77 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() featureDefinitions.BeginElement("Feature"); featureDefinitions.AddAttribute("Id", "ProductFeature"); - featureDefinitions.AddAttribute("Title", Name); + featureDefinitions.AddAttribute("Display", "expand"); + featureDefinitions.AddAttribute("ConfigurableDirectory", "INSTALL_ROOT"); + + std::string cpackPackageName; + if(!RequireOption("CPACK_PACKAGE_NAME", cpackPackageName)) + { + return false; + } + featureDefinitions.AddAttribute("Title", cpackPackageName); + featureDefinitions.AddAttribute("Level", "1"); + + CreateFeatureHierarchy(featureDefinitions); + featureDefinitions.EndElement("Feature"); - featureDefinitions.BeginElement("FeatureRef"); - featureDefinitions.AddAttribute("Id", "ProductFeature"); + bool hasShortcuts = false; - std::vector<std::string> cpackPackageExecutablesList; - const char *cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES"); - if(cpackPackageExecutables) + shortcut_map_t globalShortcuts; + if(Components.empty()) { - cmSystemTools::ExpandListArgument(cpackPackageExecutables, - cpackPackageExecutablesList); - if(cpackPackageExecutablesList.size() % 2 != 0 ) + AddComponentsToFeature(toplevel, "ProductFeature", + directoryDefinitions, fileDefinitions, featureDefinitions, + globalShortcuts); + if(globalShortcuts.size()) + { + hasShortcuts = true; + } + } + else + { + for(std::map<std::string, cmCPackComponent>::const_iterator + i = Components.begin(); i != Components.end(); ++i) + { + cmCPackComponent const& component = i->second; + + std::string componentPath = toplevel; + componentPath += "/"; + componentPath += component.Name; + + std::string componentFeatureId = "CM_C_" + component.Name; + + shortcut_map_t featureShortcuts; + AddComponentsToFeature(componentPath, componentFeatureId, + directoryDefinitions, fileDefinitions, + featureDefinitions, featureShortcuts); + if(featureShortcuts.size()) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and " - "<text label>." << std::endl); - return false; + hasShortcuts = true; } - } - AddDirectoryAndFileDefinitons( - toplevel, "INSTALL_ROOT", - directoryDefinitions, fileDefinitions, featureDefinitions, - cpackPackageExecutablesList); + if(featureShortcuts.size()) + { + if(!CreateStartMenuShortcuts(component.Name, componentFeatureId, + featureShortcuts, fileDefinitions, featureDefinitions)) + { + return false; + } + } + } + } - if(!CreateStartMenuShortcuts( - directoryDefinitions, fileDefinitions, featureDefinitions)) + if(hasShortcuts) { + if(!CreateStartMenuShortcuts(std::string(), "ProductFeature", + globalShortcuts, fileDefinitions, featureDefinitions)) + { return false; + } } - featureDefinitions.EndElement("FeatureRef"); featureDefinitions.EndElement("Fragment"); fileDefinitions.EndElement("Fragment"); @@ -444,6 +494,12 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() } directoryDefinitions.EndElement("Directory"); + + if(hasShortcuts) + { + CreateStartMenuFolder(directoryDefinitions); + } + directoryDefinitions.EndElement("Directory"); directoryDefinitions.EndElement("Fragment"); @@ -475,16 +531,154 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() return true; } -bool cmCPackWIXGenerator::CreateStartMenuShortcuts( +bool cmCPackWIXGenerator::CreateFeatureHierarchy( + cmWIXSourceWriter& featureDefinitions) +{ + for(std::map<std::string, cmCPackComponentGroup>::const_iterator + i = ComponentGroups.begin(); i != ComponentGroups.end(); ++i) + { + cmCPackComponentGroup const& group = i->second; + if(group.ParentGroup == 0) + { + if(!EmitFeatureForComponentGroup(featureDefinitions, group)) + { + return false; + } + } + } + + for(std::map<std::string, cmCPackComponent>::const_iterator + i = Components.begin(); i != Components.end(); ++i) + { + cmCPackComponent const& component = i->second; + + if(!component.Group) + { + if(!EmitFeatureForComponent(featureDefinitions, component)) + { + return false; + } + } + } + + return true; +} + +bool cmCPackWIXGenerator::EmitFeatureForComponentGroup( + cmWIXSourceWriter& featureDefinitions, + cmCPackComponentGroup const& group) +{ + featureDefinitions.BeginElement("Feature"); + featureDefinitions.AddAttribute("Id", "CM_G_" + group.Name); + + if(group.IsExpandedByDefault) + { + featureDefinitions.AddAttribute("Display", "expand"); + } + + featureDefinitions.AddAttributeUnlessEmpty( + "Title", group.DisplayName); + + featureDefinitions.AddAttributeUnlessEmpty( + "Description", group.Description); + + for(std::vector<cmCPackComponentGroup*>::const_iterator + i = group.Subgroups.begin(); i != group.Subgroups.end(); ++i) + { + if(!EmitFeatureForComponentGroup(featureDefinitions, **i)) + { + return false; + } + } + + for(std::vector<cmCPackComponent*>::const_iterator + i = group.Components.begin(); i != group.Components.end(); ++i) + { + if(!EmitFeatureForComponent(featureDefinitions, **i)) + { + return false; + } + } + + featureDefinitions.EndElement("Feature"); + + return true; +} + +bool cmCPackWIXGenerator::EmitFeatureForComponent( + cmWIXSourceWriter& featureDefinitions, + cmCPackComponent const& component) +{ + featureDefinitions.BeginElement("Feature"); + featureDefinitions.AddAttribute("Id", "CM_C_" + component.Name); + + featureDefinitions.AddAttributeUnlessEmpty( + "Title", component.DisplayName); + + featureDefinitions.AddAttributeUnlessEmpty( + "Description", component.Description); + + if(component.IsRequired) + { + featureDefinitions.AddAttribute("Absent", "disallow"); + } + + if(component.IsHidden) + { + featureDefinitions.AddAttribute("Display", "hidden"); + } + + featureDefinitions.EndElement("Feature"); + + return true; +} + +bool cmCPackWIXGenerator::AddComponentsToFeature( + std::string const& rootPath, + std::string const& featureId, cmWIXSourceWriter& directoryDefinitions, cmWIXSourceWriter& fileDefinitions, - cmWIXSourceWriter& featureDefinitions) + cmWIXSourceWriter& featureDefinitions, + shortcut_map_t& shortcutMap) { - if(shortcutMap.empty()) + featureDefinitions.BeginElement("FeatureRef"); + featureDefinitions.AddAttribute("Id", featureId); + + std::vector<std::string> cpackPackageExecutablesList; + const char *cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES"); + if(cpackPackageExecutables) { - return true; + cmSystemTools::ExpandListArgument(cpackPackageExecutables, + cpackPackageExecutablesList); + if(cpackPackageExecutablesList.size() % 2 != 0 ) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and " + "<text label>." << std::endl); + return false; + } } + AddDirectoryAndFileDefinitons( + rootPath, "INSTALL_ROOT", + directoryDefinitions, fileDefinitions, featureDefinitions, + cpackPackageExecutablesList, shortcutMap); + + featureDefinitions.EndElement("FeatureRef"); + + return true; +} + +bool cmCPackWIXGenerator::CreateStartMenuShortcuts( + std::string const& cpackComponentName, + std::string const& featureId, + shortcut_map_t& shortcutMap, + cmWIXSourceWriter& fileDefinitions, + cmWIXSourceWriter& featureDefinitions) +{ + featureDefinitions.BeginElement("FeatureRef"); + featureDefinitions.AddAttribute("Id", featureId); + std::string cpackVendor; if(!RequireOption("CPACK_PACKAGE_VENDOR", cpackVendor)) { @@ -497,10 +691,19 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( return false; } + std::string idSuffix; + if(!cpackComponentName.empty()) + { + idSuffix += "_"; + idSuffix += cpackComponentName; + } + + std::string componentId = "CM_SHORTCUT" + idSuffix; + fileDefinitions.BeginElement("DirectoryRef"); fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); fileDefinitions.BeginElement("Component"); - fileDefinitions.AddAttribute("Id", "SHORTCUT"); + fileDefinitions.AddAttribute("Id", componentId); fileDefinitions.AddAttribute("Guid", "*"); for(shortcut_map_t::const_iterator @@ -522,10 +725,13 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( fileDefinitions.EndElement("Shortcut"); } - CreateUninstallShortcut(cpackPackageName, fileDefinitions); + if(cpackComponentName.empty()) + { + CreateUninstallShortcut(cpackPackageName, fileDefinitions); + } fileDefinitions.BeginElement("RemoveFolder"); - fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); + fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER" + idSuffix); fileDefinitions.AddAttribute("On", "uninstall"); fileDefinitions.EndElement("RemoveFolder"); @@ -535,7 +741,15 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( fileDefinitions.BeginElement("RegistryValue"); fileDefinitions.AddAttribute("Root", "HKCU"); fileDefinitions.AddAttribute("Key", registryKey); - fileDefinitions.AddAttribute("Name", "installed"); + + std::string valueName; + if(!cpackComponentName.empty()) + { + valueName = cpackComponentName + "_"; + } + valueName += "installed"; + + fileDefinitions.AddAttribute("Name", valueName); fileDefinitions.AddAttribute("Type", "integer"); fileDefinitions.AddAttribute("Value", "1"); fileDefinitions.AddAttribute("KeyPath", "yes"); @@ -545,19 +759,10 @@ bool cmCPackWIXGenerator::CreateStartMenuShortcuts( fileDefinitions.EndElement("DirectoryRef"); featureDefinitions.BeginElement("ComponentRef"); - featureDefinitions.AddAttribute("Id", "SHORTCUT"); + featureDefinitions.AddAttribute("Id", componentId); featureDefinitions.EndElement("ComponentRef"); - directoryDefinitions.BeginElement("Directory"); - directoryDefinitions.AddAttribute("Id", "ProgramMenuFolder"); - - directoryDefinitions.BeginElement("Directory"); - directoryDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); - const char *startMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); - directoryDefinitions.AddAttribute("Name", startMenuFolder); - directoryDefinitions.EndElement("Directory"); - - directoryDefinitions.EndElement("Directory"); + featureDefinitions.EndElement("FeatureRef"); return true; } @@ -628,7 +833,8 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( cmWIXSourceWriter& directoryDefinitions, cmWIXSourceWriter& fileDefinitions, cmWIXSourceWriter& featureDefinitions, - const std::vector<std::string>& packageExecutables) + const std::vector<std::string>& packageExecutables, + shortcut_map_t& shortcutMap) { cmsys::Directory dir; dir.Load(topdir.c_str()); @@ -662,7 +868,8 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( directoryDefinitions, fileDefinitions, featureDefinitions, - packageExecutables); + packageExecutables, + shortcutMap); directoryDefinitions.EndElement("Directory"); } @@ -922,3 +1129,18 @@ void cmCPackWIXGenerator::AddCustomFlags( stream << " " << QuotePath(*i); } } + +void cmCPackWIXGenerator::CreateStartMenuFolder( + cmWIXSourceWriter& directoryDefinitions) +{ + directoryDefinitions.BeginElement("Directory"); + directoryDefinitions.AddAttribute("Id", "ProgramMenuFolder"); + + directoryDefinitions.BeginElement("Directory"); + directoryDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); + const char *startMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); + directoryDefinitions.AddAttribute("Name", startMenuFolder); + directoryDefinitions.EndElement("Directory"); + + directoryDefinitions.EndElement("Directory"); +} diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h index 481a07d..84f68b6 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.h +++ b/Source/CPack/WiX/cmCPackWIXGenerator.h @@ -56,7 +56,7 @@ protected: virtual bool SupportsComponentInstallation() const { - return false; + return true; } private: @@ -79,9 +79,30 @@ private: bool CreateWiXSourceFiles(); - bool CreateStartMenuShortcuts( + bool CreateFeatureHierarchy( + cmWIXSourceWriter& featureDefinitions); + + bool EmitFeatureForComponentGroup( + cmWIXSourceWriter& featureDefinitions, + cmCPackComponentGroup const& group); + + bool EmitFeatureForComponent( + cmWIXSourceWriter& featureDefinitions, + cmCPackComponent const& component); + + bool AddComponentsToFeature( + std::string const& rootPath, + std::string const& featureId, cmWIXSourceWriter& directoryDefinitions, cmWIXSourceWriter& fileDefinitions, + cmWIXSourceWriter& featureDefinitions, + shortcut_map_t& shortcutMap); + + bool CreateStartMenuShortcuts( + std::string const& cpackComponentName, + std::string const& featureId, + shortcut_map_t& shortcutMap, + cmWIXSourceWriter& fileDefinitions, cmWIXSourceWriter& featureDefinitions); void CreateUninstallShortcut( @@ -106,7 +127,8 @@ private: cmWIXSourceWriter& directoryDefinitions, cmWIXSourceWriter& fileDefinitions, cmWIXSourceWriter& featureDefinitions, - const std::vector<std::string>& pkgExecutables); + const std::vector<std::string>& pkgExecutables, + shortcut_map_t& shortcutMap); bool RequireOption(const std::string& name, std::string& value) const; @@ -136,10 +158,11 @@ private: void AddCustomFlags( const std::string& variableName, std::ostream& stream); + void CreateStartMenuFolder(cmWIXSourceWriter& directoryDefinitions); + std::vector<std::string> wixSources; id_map_t pathToIdMap; ambiguity_map_t idAmbiguityCounter; - shortcut_map_t shortcutMap; extension_set_t candleExtensions; extension_set_t lightExtensions; diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx index 214b8ac..c8a3922 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.cxx +++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx @@ -123,6 +123,15 @@ void cmWIXSourceWriter::AddAttribute( file << " " << key << "=\"" << EscapeAttributeValue(utf8) << '"'; } +void cmWIXSourceWriter::AddAttributeUnlessEmpty( + const std::string& key, const std::string& value) +{ + if(value.size()) + { + AddAttribute(key, value); + } +} + std::string cmWIXSourceWriter::WindowsCodepageToUtf8(const std::string& value) { if(value.empty()) diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h index 0c7803c..670d4c0 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.h +++ b/Source/CPack/WiX/cmWIXSourceWriter.h @@ -40,6 +40,9 @@ public: void AddAttribute( const std::string& key, const std::string& value); + void AddAttributeUnlessEmpty( + const std::string& key, const std::string& value); + static std::string WindowsCodepageToUtf8(const std::string& value); private: diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 5475c2f..cd2fcc7 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -580,7 +580,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( * (this works at CPack time too) */ if (this->SupportsComponentInstallation() & - !(this->IsSet("CPACK_MONOLITHIC_INSTALL"))) + !(this->IsOn("CPACK_MONOLITHIC_INSTALL"))) { // Determine the installation types for this project (if provided). std::string installTypesVar = "CPACK_" @@ -1532,13 +1532,13 @@ cmCPackGenerator::GetComponent(const char *projectName, const char *name) component->DisplayName = component->Name; } component->IsHidden - = this->IsSet((macroPrefix + "_HIDDEN").c_str()); + = this->IsOn((macroPrefix + "_HIDDEN").c_str()); component->IsRequired - = this->IsSet((macroPrefix + "_REQUIRED").c_str()); + = this->IsOn((macroPrefix + "_REQUIRED").c_str()); component->IsDisabledByDefault - = this->IsSet((macroPrefix + "_DISABLED").c_str()); + = this->IsOn((macroPrefix + "_DISABLED").c_str()); component->IsDownloaded - = this->IsSet((macroPrefix + "_DOWNLOADED").c_str()) + = this->IsOn((macroPrefix + "_DOWNLOADED").c_str()) || cmSystemTools::IsOn(this->GetOption("CPACK_DOWNLOAD_ALL")); const char* archiveFile = this->GetOption((macroPrefix + @@ -1635,9 +1635,9 @@ cmCPackGenerator::GetComponentGroup(const char *projectName, const char *name) group->Description = description; } group->IsBold - = this->IsSet((macroPrefix + "_BOLD_TITLE").c_str()); + = this->IsOn((macroPrefix + "_BOLD_TITLE").c_str()); group->IsExpandedByDefault - = this->IsSet((macroPrefix + "_EXPANDED").c_str()); + = this->IsOn((macroPrefix + "_EXPANDED").c_str()); const char* parentGroupName = this->GetOption((macroPrefix + "_PARENT_GROUP").c_str()); if (parentGroupName && *parentGroupName) diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 39eeb70..e480fff 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -763,7 +763,7 @@ void cmCTestBuildHandler::GenerateXMLLaunchedFragment(std::ostream& os, bool cmCTestBuildHandler::IsLaunchedErrorFile(const char* fname) { // error-{hash}.xml - return (strncmp(fname, "error-", 6) == 0 && + return (cmHasLiteralPrefix(fname, "error-") && strcmp(fname+strlen(fname)-4, ".xml") == 0); } @@ -771,7 +771,7 @@ bool cmCTestBuildHandler::IsLaunchedErrorFile(const char* fname) bool cmCTestBuildHandler::IsLaunchedWarningFile(const char* fname) { // warning-{hash}.xml - return (strncmp(fname, "warning-", 8) == 0 && + return (cmHasLiteralPrefix(fname, "warning-") && strcmp(fname+strlen(fname)-4, ".xml") == 0); } diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index 5b34491..725f613 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -536,11 +536,11 @@ private: void DoHeaderLine() { // Look for header fields that we need. - if(strncmp(this->Line.c_str(), "commit ", 7) == 0) + if(cmHasLiteralPrefix(this->Line.c_str(), "commit ")) { this->Rev.Rev = this->Line.c_str()+7; } - else if(strncmp(this->Line.c_str(), "author ", 7) == 0) + else if(cmHasLiteralPrefix(this->Line.c_str(), "author ")) { Person author; this->ParsePerson(this->Line.c_str()+7, author); @@ -548,7 +548,7 @@ private: this->Rev.EMail = author.EMail; this->Rev.Date = this->FormatDateTime(author); } - else if(strncmp(this->Line.c_str(), "committer ", 10) == 0) + else if(cmHasLiteralPrefix(this->Line.c_str(), "committer ")) { Person committer; this->ParsePerson(this->Line.c_str()+10, committer); diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index 9831d02..8e5fd78 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -64,7 +64,8 @@ bool cmCTestLaunch::ParseArguments(int argc, const char* const* argv) DoingTargetName, DoingTargetType, DoingBuildDir, - DoingCount }; + DoingCount, + DoingFilterPrefix }; Doing doing = DoingNone; int arg0 = 0; for(int i=1; !arg0 && i < argc; ++i) @@ -98,6 +99,10 @@ bool cmCTestLaunch::ParseArguments(int argc, const char* const* argv) { doing = DoingBuildDir; } + else if(strcmp(arg, "--filter-prefix") == 0) + { + doing = DoingFilterPrefix; + } else if(doing == DoingOutput) { this->OptionOutput = arg; @@ -132,6 +137,11 @@ bool cmCTestLaunch::ParseArguments(int argc, const char* const* argv) this->OptionBuildDir = arg; doing = DoingNone; } + else if(doing == DoingFilterPrefix) + { + this->OptionFilterPrefix = arg; + doing = DoingNone; + } } // Extract the real command line. @@ -573,8 +583,15 @@ void cmCTestLaunch::DumpFileToXML(std::ostream& fxml, std::string line; const char* sep = ""; + while(cmSystemTools::GetLineFromStream(fin, line)) { + if(OptionFilterPrefix.size() && cmSystemTools::StringStartsWith( + line.c_str(), OptionFilterPrefix.c_str())) + { + continue; + } + fxml << sep << cmXMLSafe(line).Quotes(false); sep = "\n"; } diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h index 7457e83..a86a9df 100644 --- a/Source/CTest/cmCTestLaunch.h +++ b/Source/CTest/cmCTestLaunch.h @@ -45,6 +45,7 @@ private: std::string OptionTargetName; std::string OptionTargetType; std::string OptionBuildDir; + std::string OptionFilterPrefix; bool ParseArguments(int argc, const char* const* argv); // The real command line appearing after launcher arguments. diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index f1f4649..4308a4d 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -102,6 +102,13 @@ if(APPLE) MACOSX_PACKAGE_LOCATION Resources) endif() +if(CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL) + install(FILES ${CMake_SOURCE_DIR}/Licenses/LGPLv2.1.txt + DESTINATION ${CMAKE_DATA_DIR}/Licenses) + set_property(SOURCE CMakeSetupDialog.cxx + PROPERTY COMPILE_DEFINITIONS CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL) +endif() + set(CMAKE_INCLUDE_CURRENT_DIR ON) add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS}) diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index a7665c8..1903c02 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -34,6 +34,7 @@ #include "QCMakeCacheView.h" #include "AddCacheEntry.h" #include "FirstConfigure.h" +#include "cmSystemTools.h" #include "cmVersion.h" QCMakeThread::QCMakeThread(QObject* p) @@ -807,12 +808,26 @@ void CMakeSetupDialog::doDeleteCache() void CMakeSetupDialog::doAbout() { - QString msg = tr("CMake %1\n" - "Using Qt %2\n" - "www.cmake.org"); - + QString msg = tr( + "CMake %1 (cmake.org).\n" + "CMake suite maintained by Kitware, Inc. (kitware.com).\n" + "Distributed under terms of the BSD 3-Clause License.\n" + "\n" + "CMake GUI maintained by csimsoft,\n" + "built using Qt %2 (qt-project.org).\n" +#ifdef CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL + "\n" + "The Qt Toolkit is Copyright (C) Digia Plc and/or its subsidiary(-ies).\n" + "Qt is licensed under terms of the GNU LGPLv2.1, available at:\n" + " \"%3\"" +#endif + ); msg = msg.arg(cmVersion::GetCMakeVersion()); msg = msg.arg(qVersion()); +#ifdef CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL + std::string lgpl = cmSystemTools::GetCMakeRoot()+"/Licenses/LGPLv2.1.txt"; + msg = msg.arg(lgpl.c_str()); +#endif QDialog dialog; dialog.setWindowTitle(tr("About")); @@ -946,6 +961,7 @@ void CMakeSetupDialog::saveBuildPaths(const QStringList& paths) void CMakeSetupDialog::setCacheModified() { this->CacheModified = true; + this->ConfigureNeeded = true; this->enterState(ReadyConfigure); } diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index 2a683a4..ef62523 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -11,6 +11,9 @@ ============================================================================*/ #include "cmAddCustomTargetCommand.h" +#include "cmGeneratorExpression.h" +#include "cmGlobalGenerator.h" + // cmAddCustomTargetCommand bool cmAddCustomTargetCommand ::InitialPass(std::vector<std::string> const& args, @@ -22,11 +25,13 @@ bool cmAddCustomTargetCommand return false; } + std::string targetName = args[0]; + // Check the target name. - if(args[0].find_first_of("/\\") != args[0].npos) + if(targetName.find_first_of("/\\") != targetName.npos) { cmOStringStream e; - e << "called with invalid target name \"" << args[0] + e << "called with invalid target name \"" << targetName << "\". Target names may not contain a slash. " << "Use ADD_CUSTOM_COMMAND to generate files."; this->SetError(e.str().c_str()); @@ -138,16 +143,59 @@ bool cmAddCustomTargetCommand } } - std::string::size_type pos = args[0].find_first_of("#<>"); - if(pos != args[0].npos) + std::string::size_type pos = targetName.find_first_of("#<>"); + if(pos != targetName.npos) { cmOStringStream msg; - msg << "called with target name containing a \"" << args[0][pos] + msg << "called with target name containing a \"" << targetName[pos] << "\". This character is not allowed."; this->SetError(msg.str().c_str()); return false; } + // Some requirements on custom target names already exist + // and have been checked at this point. + // The following restrictions overlap but depend on policy CMP0037. + bool nameOk = cmGeneratorExpression::IsValidTargetName(targetName) && + !cmGlobalGenerator::IsReservedTarget(targetName); + if (nameOk) + { + nameOk = targetName.find(":") == std::string::npos; + } + if (!nameOk) + { + cmake::MessageType messageType = cmake::AUTHOR_WARNING; + bool issueMessage = false; + switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) + { + case cmPolicies::WARN: + issueMessage = true; + case cmPolicies::OLD: + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + issueMessage = true; + messageType = cmake::FATAL_ERROR; + } + if (issueMessage) + { + cmOStringStream e; + e << (this->Makefile->GetPolicies() + ->GetPolicyWarning(cmPolicies::CMP0037)) << "\n"; + e << "The target name \"" << targetName << + "\" is reserved or not valid for certain " + "CMake features, such as generator expressions, and may result " + "in undefined behavior."; + this->Makefile->IssueMessage(messageType, e.str().c_str()); + + if (messageType == cmake::FATAL_ERROR) + { + return false; + } + } + } + // Store the last command line finished. if(!currentLine.empty()) { @@ -158,7 +206,7 @@ bool cmAddCustomTargetCommand // Enforce name uniqueness. { std::string msg; - if(!this->Makefile->EnforceUniqueName(args[0], msg, true)) + if(!this->Makefile->EnforceUniqueName(targetName, msg, true)) { this->SetError(msg.c_str()); return false; @@ -176,7 +224,7 @@ bool cmAddCustomTargetCommand // Add the utility target to the makefile. bool escapeOldStyle = !verbatim; cmTarget* target = - this->Makefile->AddUtilityCommand(args[0].c_str(), excludeFromAll, + this->Makefile->AddUtilityCommand(targetName.c_str(), excludeFromAll, working_directory.c_str(), depends, commandLines, escapeOldStyle, comment); diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx index a93e834..a352be0 100644 --- a/Source/cmAddExecutableCommand.cxx +++ b/Source/cmAddExecutableCommand.cxx @@ -69,7 +69,9 @@ bool cmAddExecutableCommand } } - bool nameOk = cmGeneratorExpression::IsValidTargetName(exename); + bool nameOk = cmGeneratorExpression::IsValidTargetName(exename) && + !cmGlobalGenerator::IsReservedTarget(exename); + if (nameOk && !importTarget && !isAlias) { nameOk = exename.find(":") == std::string::npos; @@ -95,7 +97,8 @@ bool cmAddExecutableCommand cmOStringStream e; e << (this->Makefile->GetPolicies() ->GetPolicyWarning(cmPolicies::CMP0037)) << "\n"; - e << "The target name \"" << exename << "\" is not valid for certain " + e << "The target name \"" << exename << + "\" is reserved or not valid for certain " "CMake features, such as generator expressions, and may result " "in undefined behavior."; this->Makefile->IssueMessage(messageType, e.str().c_str()); diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index e9c5d6b..0f98f35 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -109,7 +109,9 @@ bool cmAddLibraryCommand } } - bool nameOk = cmGeneratorExpression::IsValidTargetName(libName); + bool nameOk = cmGeneratorExpression::IsValidTargetName(libName) && + !cmGlobalGenerator::IsReservedTarget(libName); + if (nameOk && !importTarget && !isAlias) { nameOk = libName.find(":") == std::string::npos; @@ -135,7 +137,8 @@ bool cmAddLibraryCommand cmOStringStream e; e << (this->Makefile->GetPolicies() ->GetPolicyWarning(cmPolicies::CMP0037)) << "\n"; - e << "The target name \"" << libName << "\" is not valid for certain " + e << "The target name \"" << libName << + "\" is reserved or not valid for certain " "CMake features, such as generator expressions, and may result " "in undefined behavior."; this->Makefile->IssueMessage(messageType, e.str().c_str()); diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index bfabc9f..125a3bf 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -1131,11 +1131,11 @@ int cmCTest::GetTestModelFromString(const char* str) return cmCTest::EXPERIMENTAL; } std::string rstr = cmSystemTools::LowerCase(str); - if ( strncmp(rstr.c_str(), "cont", 4) == 0 ) + if ( cmHasLiteralPrefix(rstr.c_str(), "cont") ) { return cmCTest::CONTINUOUS; } - if ( strncmp(rstr.c_str(), "nigh", 4) == 0 ) + if ( cmHasLiteralPrefix(rstr.c_str(), "nigh") ) { return cmCTest::NIGHTLY; } diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index d4644c3..0ef3d2e 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1901,6 +1901,12 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, } if(use_build_rpath || use_link_rpath) { + std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + const char *stagePath + = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); + const char *installPrefix + = this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); + cmSystemTools::ConvertToUnixSlashes(rootPath); std::vector<std::string> const& rdirs = this->GetRuntimeSearchPath(); for(std::vector<std::string>::const_iterator ri = rdirs.begin(); ri != rdirs.end(); ++ri) @@ -1909,9 +1915,22 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, // support or if using the link path as an rpath. if(use_build_rpath) { - if(emitted.insert(*ri).second) + std::string d = *ri; + if (!rootPath.empty() && d.find(rootPath) == 0) { - runtimeDirs.push_back(*ri); + d = d.substr(rootPath.size()); + } + else if (stagePath && *stagePath && d.find(stagePath) == 0) + { + std::string suffix = d.substr(strlen(stagePath)); + d = installPrefix; + d += "/"; + d += suffix; + cmSystemTools::ConvertToUnixSlashes(d); + } + if(emitted.insert(d).second) + { + runtimeDirs.push_back(d); } } else if(use_link_rpath) @@ -1924,9 +1943,22 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, !cmSystemTools::IsSubDirectory(ri->c_str(), topSourceDir) && !cmSystemTools::IsSubDirectory(ri->c_str(), topBinaryDir)) { - if(emitted.insert(*ri).second) + std::string d = *ri; + if (!rootPath.empty() && d.find(rootPath) == 0) + { + d = d.substr(rootPath.size()); + } + else if (stagePath && *stagePath && d.find(stagePath) == 0) + { + std::string suffix = d.substr(strlen(stagePath)); + d = installPrefix; + d += "/"; + d += suffix; + cmSystemTools::ConvertToUnixSlashes(d); + } + if(emitted.insert(d).second) { - runtimeDirs.push_back(*ri); + runtimeDirs.push_back(d); } } } diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 7fd4754..cb9e37e 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -237,7 +237,15 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) it != configs.end(); ++it) { std::vector<std::string> tlibs; - depender->GetDirectLinkLibraries(it->c_str(), tlibs, depender); + if (depender->GetType() == cmTarget::INTERFACE_LIBRARY) + { + // For INTERFACE_LIBRARY depend on the interface instead. + depender->GetInterfaceLinkLibraries(it->c_str(), tlibs, depender); + } + else + { + depender->GetDirectLinkLibraries(it->c_str(), tlibs, depender); + } // A target should not depend on itself. emitted.insert(depender->GetName()); for(std::vector<std::string>::const_iterator lib = tlibs.begin(); diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 479a699..bbfc427 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -405,6 +405,41 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) flag += this->Makefile->GetSafeDefinition("CMAKE_OSX_DEPLOYMENT_TARGET"); cmakeFlags.push_back(flag); } + if (const char *cxxDef + = this->Makefile->GetDefinition("CMAKE_CXX_COMPILER_TARGET")) + { + std::string flag="-DCMAKE_CXX_COMPILER_TARGET="; + flag += cxxDef; + cmakeFlags.push_back(flag); + } + if (const char *cDef + = this->Makefile->GetDefinition("CMAKE_C_COMPILER_TARGET")) + { + std::string flag="-DCMAKE_C_COMPILER_TARGET="; + flag += cDef; + cmakeFlags.push_back(flag); + } + if (const char *tcxxDef = this->Makefile->GetDefinition( + "CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN")) + { + std::string flag="-DCMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN="; + flag += tcxxDef; + cmakeFlags.push_back(flag); + } + if (const char *tcDef = this->Makefile->GetDefinition( + "CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN")) + { + std::string flag="-DCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN="; + flag += tcDef; + cmakeFlags.push_back(flag); + } + if (const char *rootDef + = this->Makefile->GetDefinition("CMAKE_SYSROOT")) + { + std::string flag="-DCMAKE_SYSROOT="; + flag += rootDef; + cmakeFlags.push_back(flag); + } if(this->Makefile->GetDefinition("CMAKE_POSITION_INDEPENDENT_CODE")!=0) { fprintf(fout, "set(CMAKE_POSITION_INDEPENDENT_CODE \"ON\")\n"); diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index 8029577..8576bf2 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -95,8 +95,12 @@ cmDocumentation::~cmDocumentation() //---------------------------------------------------------------------------- bool cmDocumentation::PrintVersion(std::ostream& os) { - os << this->GetNameString() << " version " - << cmVersion::GetCMakeVersion() << "\n"; + os << + this->GetNameString() << + " version " << cmVersion::GetCMakeVersion() << "\n" + "\n" + "CMake suite maintained by Kitware, Inc. (kitware.com).\n" + ; return true; } @@ -195,24 +199,27 @@ bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os) void cmDocumentation::WarnFormFromFilename( - cmDocumentation::RequestedHelpItem& request) + cmDocumentation::RequestedHelpItem& request, bool& result) { std::string ext = cmSystemTools::GetFilenameLastExtension(request.Filename); ext = cmSystemTools::UpperCase(ext); if ((ext == ".HTM") || (ext == ".HTML")) { request.HelpType = cmDocumentation::None; + result = true; cmSystemTools::Message("Warning: HTML help format no longer supported"); } else if (ext == ".DOCBOOK") { request.HelpType = cmDocumentation::None; + result = true; cmSystemTools::Message("Warning: Docbook help format no longer supported"); } // ".1" to ".9" should be manpages else if ((ext.length()==2) && (ext[1] >='1') && (ext[1]<='9')) { request.HelpType = cmDocumentation::None; + result = true; cmSystemTools::Message("Warning: Man help format no longer supported"); } } @@ -300,28 +307,28 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv, help.HelpType = cmDocumentation::OneManual; help.Argument = "cmake-properties.7"; GET_OPT_ARGUMENT(help.Filename); - this->WarnFormFromFilename(help); + this->WarnFormFromFilename(help, result); } else if(strcmp(argv[i], "--help-policies") == 0) { help.HelpType = cmDocumentation::OneManual; help.Argument = "cmake-policies.7"; GET_OPT_ARGUMENT(help.Filename); - this->WarnFormFromFilename(help); + this->WarnFormFromFilename(help, result); } else if(strcmp(argv[i], "--help-variables") == 0) { help.HelpType = cmDocumentation::OneManual; help.Argument = "cmake-variables.7"; GET_OPT_ARGUMENT(help.Filename); - this->WarnFormFromFilename(help); + this->WarnFormFromFilename(help, result); } else if(strcmp(argv[i], "--help-modules") == 0) { help.HelpType = cmDocumentation::OneManual; help.Argument = "cmake-modules.7"; GET_OPT_ARGUMENT(help.Filename); - this->WarnFormFromFilename(help); + this->WarnFormFromFilename(help, result); } else if(strcmp(argv[i], "--help-custom-modules") == 0) { @@ -335,7 +342,7 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv, help.HelpType = cmDocumentation::OneManual; help.Argument = "cmake-commands.7"; GET_OPT_ARGUMENT(help.Filename); - this->WarnFormFromFilename(help); + this->WarnFormFromFilename(help, result); } else if(strcmp(argv[i], "--help-compatcommands") == 0) { @@ -368,42 +375,42 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv, GET_OPT_ARGUMENT(help.Argument); GET_OPT_ARGUMENT(help.Filename); help.Argument = cmSystemTools::LowerCase(help.Argument); - this->WarnFormFromFilename(help); + this->WarnFormFromFilename(help, result); } else if(strcmp(argv[i], "--help-module") == 0) { help.HelpType = cmDocumentation::OneModule; GET_OPT_ARGUMENT(help.Argument); GET_OPT_ARGUMENT(help.Filename); - this->WarnFormFromFilename(help); + this->WarnFormFromFilename(help, result); } else if(strcmp(argv[i], "--help-property") == 0) { help.HelpType = cmDocumentation::OneProperty; GET_OPT_ARGUMENT(help.Argument); GET_OPT_ARGUMENT(help.Filename); - this->WarnFormFromFilename(help); + this->WarnFormFromFilename(help, result); } else if(strcmp(argv[i], "--help-policy") == 0) { help.HelpType = cmDocumentation::OnePolicy; GET_OPT_ARGUMENT(help.Argument); GET_OPT_ARGUMENT(help.Filename); - this->WarnFormFromFilename(help); + this->WarnFormFromFilename(help, result); } else if(strcmp(argv[i], "--help-variable") == 0) { help.HelpType = cmDocumentation::OneVariable; GET_OPT_ARGUMENT(help.Argument); GET_OPT_ARGUMENT(help.Filename); - this->WarnFormFromFilename(help); + this->WarnFormFromFilename(help, result); } else if(strcmp(argv[i], "--help-manual") == 0) { help.HelpType = cmDocumentation::OneManual; GET_OPT_ARGUMENT(help.Argument); GET_OPT_ARGUMENT(help.Filename); - this->WarnFormFromFilename(help); + this->WarnFormFromFilename(help, result); } else if(strcmp(argv[i], "--help-command-list") == 0) { diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index 209cc27..05c0442 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -137,7 +137,7 @@ private: std::vector<RequestedHelpItem> RequestedHelpItems; cmDocumentationFormatter Formatter; - static void WarnFormFromFilename(RequestedHelpItem& request); + static void WarnFormFromFilename(RequestedHelpItem& request, bool& result); }; #endif diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 50835e2..0d0d05b 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -77,6 +77,9 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", te, cmGeneratorExpression::BuildInterface, properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", te, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", te, properties); const bool newCMP0022Behavior = diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 86ddc3f..3f6bc2e 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -135,6 +135,14 @@ bool cmExportCommand return false; } } + else + { + cmOStringStream e; + e << "given target \"" << *currentTarget + << "\" which is not built by this project."; + this->SetError(e.str().c_str()); + return false; + } } cmGlobalGenerator *gg = this->Makefile->GetLocalGenerator() diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index fdc075e..f8b4e28 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -233,26 +233,46 @@ static bool checkInterfaceDirs(const std::string &prepro, const bool inSourceBuild = strcmp(topSourceDir, topBinaryDir) == 0; + bool hadFatalError = false; + for(std::vector<std::string>::iterator li = parts.begin(); li != parts.end(); ++li) { - if (cmGeneratorExpression::Find(*li) != std::string::npos) + size_t genexPos = cmGeneratorExpression::Find(*li); + if (genexPos == 0) { continue; } - if (strncmp(li->c_str(), "${_IMPORT_PREFIX}", 17) == 0) + cmake::MessageType messageType = cmake::FATAL_ERROR; + cmOStringStream e; + if (genexPos != std::string::npos) + { + switch (target->GetPolicyStatusCMP0041()) + { + case cmPolicies::WARN: + messageType = cmake::WARNING; + e << target->GetMakefile()->GetPolicies() + ->GetPolicyWarning(cmPolicies::CMP0041) << "\n"; + break; + case cmPolicies::OLD: + continue; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + hadFatalError = true; + break; // Issue fatal message. + } + } + if (cmHasLiteralPrefix(li->c_str(), "${_IMPORT_PREFIX}")) { continue; } if (!cmSystemTools::FileIsFullPath(li->c_str())) { - cmOStringStream e; e << "Target \"" << target->GetName() << "\" " "INTERFACE_INCLUDE_DIRECTORIES property contains relative path:\n" " \"" << *li << "\""; - target->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, - e.str().c_str()); - return false; + target->GetMakefile()->IssueMessage(messageType, e.str().c_str()); } if (isSubDirectory(li->c_str(), installDir)) { @@ -260,29 +280,44 @@ static bool checkInterfaceDirs(const std::string &prepro, } if (isSubDirectory(li->c_str(), topBinaryDir)) { - cmOStringStream e; e << "Target \"" << target->GetName() << "\" " "INTERFACE_INCLUDE_DIRECTORIES property contains path:\n" " \"" << *li << "\"\nwhich is prefixed in the build directory."; - target->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, - e.str().c_str()); - return false; + target->GetMakefile()->IssueMessage(messageType, e.str().c_str()); } if (!inSourceBuild) { if (isSubDirectory(li->c_str(), topSourceDir)) { - cmOStringStream e; e << "Target \"" << target->GetName() << "\" " "INTERFACE_INCLUDE_DIRECTORIES property contains path:\n" " \"" << *li << "\"\nwhich is prefixed in the source directory."; - target->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, - e.str().c_str()); - return false; + target->GetMakefile()->IssueMessage(messageType, e.str().c_str()); } } } - return true; + return !hadFatalError; +} + +//---------------------------------------------------------------------------- +static void prefixItems(std::string &exportDirs) +{ + std::vector<std::string> entries; + cmGeneratorExpression::Split(exportDirs, entries); + exportDirs = ""; + const char *sep = ""; + for(std::vector<std::string>::const_iterator ei = entries.begin(); + ei != entries.end(); ++ei) + { + exportDirs += sep; + sep = ";"; + if (!cmSystemTools::FileIsFullPath(ei->c_str()) + && ei->find("${_IMPORT_PREFIX}") == std::string::npos) + { + exportDirs += "${_IMPORT_PREFIX}/"; + } + exportDirs += *ei; + } } //---------------------------------------------------------------------------- @@ -301,7 +336,10 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( cmListFileBacktrace lfbt; cmGeneratorExpression ge(lfbt); - std::string dirs = tei->InterfaceIncludeDirectories; + std::string dirs = cmGeneratorExpression::Preprocess( + tei->InterfaceIncludeDirectories, + preprocessRule, + true); this->ReplaceInstallPrefix(dirs); cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs); std::string exportDirs = cge->Evaluate(target->GetMakefile(), 0, @@ -330,6 +368,8 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( return; } + prefixItems(exportDirs); + std::string includes = (input?input:""); const char* sep = input ? ";" : ""; includes += sep + exportDirs; @@ -388,14 +428,11 @@ void getCompatibleInterfaceProperties(cmTarget *target, if (!info) { - if (target->GetType() != cmTarget::INTERFACE_LIBRARY) - { - cmMakefile* mf = target->GetMakefile(); - cmOStringStream e; - e << "Exporting the target \"" << target->GetName() << "\" is not " - "allowed since its linker language cannot be determined"; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - } + cmMakefile* mf = target->GetMakefile(); + cmOStringStream e; + e << "Exporting the target \"" << target->GetName() << "\" is not " + "allowed since its linker language cannot be determined"; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } @@ -447,15 +484,18 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( getPropertyContents(target, "COMPATIBLE_INTERFACE_NUMBER_MAX", ifaceProperties); - getCompatibleInterfaceProperties(target, ifaceProperties, 0); + if (target->GetType() != cmTarget::INTERFACE_LIBRARY) + { + getCompatibleInterfaceProperties(target, ifaceProperties, 0); - std::vector<std::string> configNames; - target->GetMakefile()->GetConfigurations(configNames); + std::vector<std::string> configNames; + target->GetMakefile()->GetConfigurations(configNames); - for (std::vector<std::string>::const_iterator ci = configNames.begin(); - ci != configNames.end(); ++ci) - { - getCompatibleInterfaceProperties(target, ifaceProperties, ci->c_str()); + for (std::vector<std::string>::const_iterator ci = configNames.begin(); + ci != configNames.end(); ++ci) + { + getCompatibleInterfaceProperties(target, ifaceProperties, ci->c_str()); + } } for (std::set<std::string>::const_iterator it = ifaceProperties.begin(); diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 133944e..79e78df 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -81,10 +81,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) os << "# Compute the installation prefix relative to this file.\n" << "get_filename_component(_IMPORT_PREFIX" << " \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"; - if(strncmp(absDestS.c_str(), "/lib/", 5) == 0 || - strncmp(absDestS.c_str(), "/lib64/", 7) == 0 || - strncmp(absDestS.c_str(), "/usr/lib/", 9) == 0 || - strncmp(absDestS.c_str(), "/usr/lib64/", 11) == 0) + if(cmHasLiteralPrefix(absDestS.c_str(), "/lib/") || + cmHasLiteralPrefix(absDestS.c_str(), "/lib64/") || + cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib/") || + cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib64/")) { // Handle "/usr move" symlinks created by some Linux distros. os << @@ -140,6 +140,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) te, cmGeneratorExpression::InstallInterface, properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", + te, + cmGeneratorExpression::InstallInterface, + properties, missingTargets); const bool newCMP0022Behavior = te->GetPolicyStatusCMP0022() != cmPolicies::WARN diff --git a/Source/cmExternalMakefileProjectGenerator.cxx b/Source/cmExternalMakefileProjectGenerator.cxx index 9c965cc..0d42c35 100644 --- a/Source/cmExternalMakefileProjectGenerator.cxx +++ b/Source/cmExternalMakefileProjectGenerator.cxx @@ -13,6 +13,12 @@ #include "cmExternalMakefileProjectGenerator.h" +void cmExternalMakefileProjectGenerator +::EnableLanguage(std::vector<std::string> const&, + cmMakefile *, bool) +{ +} + std::string cmExternalMakefileProjectGenerator::CreateFullGeneratorName( const char* globalGenerator, const char* extraGenerator) diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h index 182c1a8..bce441d 100644 --- a/Source/cmExternalMakefileProjectGenerator.h +++ b/Source/cmExternalMakefileProjectGenerator.h @@ -41,6 +41,8 @@ public: /** Get the documentation entry for this generator. */ virtual void GetDocumentation(cmDocumentationEntry& entry, const char* fullName) const = 0; + virtual void EnableLanguage(std::vector<std::string> const& languages, + cmMakefile *, bool optional); ///! set the global generator which will generate the makefiles virtual void SetGlobalGenerator(cmGlobalGenerator* generator) diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 676d4ed..755b445 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -51,6 +51,29 @@ void cmExtraEclipseCDT4Generator } //---------------------------------------------------------------------------- +void cmExtraEclipseCDT4Generator +::EnableLanguage(std::vector<std::string> const& languages, + cmMakefile *, bool) +{ + for (std::vector<std::string>::const_iterator lit = languages.begin(); + lit != languages.end(); ++lit) + { + if (*lit == "CXX") + { + this->Natures.insert("org.eclipse.cdt.core.ccnature"); + } + else if (*lit == "C") + { + this->Natures.insert("org.eclipse.cdt.core.cnature"); + } + else if (*lit == "Java") + { + this->Natures.insert("org.eclipse.jdt.core.javanature"); + } + } +} + +//---------------------------------------------------------------------------- void cmExtraEclipseCDT4Generator::Generate() { const cmMakefile* mf @@ -433,13 +456,28 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() // set natures for c/c++ projects fout << "\t<natures>\n" - // TODO: ccnature only if it is c++ ??? - "\t\t<nature>org.eclipse.cdt.core.ccnature</nature>\n" "\t\t<nature>org.eclipse.cdt.make.core.makeNature</nature>\n" - "\t\t<nature>org.eclipse.cdt.make.core.ScannerConfigNature</nature>\n" - "\t\t<nature>org.eclipse.cdt.core.cnature</nature>\n" - "\t</natures>\n" - ; + "\t\t<nature>org.eclipse.cdt.make.core.ScannerConfigNature</nature>\n"; + + for (std::set<std::string>::const_iterator nit=this->Natures.begin(); + nit != this->Natures.end(); ++nit) + { + fout << "\t\t<nature>" << *nit << "</nature>\n"; + } + + if (const char *extraNaturesProp = mf->GetCMakeInstance()-> + GetProperty("ECLIPSE_EXTRA_NATURES", cmProperty::GLOBAL)) + { + std::vector<std::string> extraNatures; + cmSystemTools::ExpandListArgument(extraNaturesProp, extraNatures); + for (std::vector<std::string>::const_iterator nit = extraNatures.begin(); + nit != extraNatures.end(); ++nit) + { + fout << "\t\t<nature>" << *nit << "</nature>\n"; + } + } + + fout << "\t</natures>\n"; fout << "\t<linkedResources>\n"; // create linked resources diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h index b31cce7..9c89f85 100644 --- a/Source/cmExtraEclipseCDT4Generator.h +++ b/Source/cmExtraEclipseCDT4Generator.h @@ -41,6 +41,8 @@ public: virtual void GetDocumentation(cmDocumentationEntry& entry, const char* fullName) const; + virtual void EnableLanguage(std::vector<std::string> const& languages, + cmMakefile *, bool optional); virtual void Generate(); @@ -105,6 +107,7 @@ private: void CreateLinksForTargets(cmGeneratedFileStream& fout); std::vector<std::string> SrcLinkedResources; + std::set<std::string> Natures; std::string HomeDirectory; std::string HomeOutputDirectory; bool IsOutOfSourceBuild; diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx new file mode 100644 index 0000000..f020ddb --- /dev/null +++ b/Source/cmExtraKateGenerator.cxx @@ -0,0 +1,372 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2004-2009 Kitware, Inc. + Copyright 2004 Alexander Neundorf (neundorf@kde.org) + + 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 "cmExtraKateGenerator.h" +#include "cmGlobalUnixMakefileGenerator3.h" +#include "cmLocalUnixMakefileGenerator3.h" +#include "cmMakefile.h" +#include "cmake.h" +#include "cmSourceFile.h" +#include "cmGeneratedFileStream.h" +#include "cmTarget.h" +#include "cmSystemTools.h" +#include "cmXMLSafe.h" + +#include <cmsys/SystemTools.hxx> + +//---------------------------------------------------------------------------- +void cmExtraKateGenerator +::GetDocumentation(cmDocumentationEntry& entry, const char*) const +{ + entry.Name = this->GetName(); + entry.Brief = "Generates Kate project files."; +} + +cmExtraKateGenerator::cmExtraKateGenerator() +:cmExternalMakefileProjectGenerator() +{ +#if defined(_WIN32) + this->SupportedGlobalGenerators.push_back("MinGW Makefiles"); + this->SupportedGlobalGenerators.push_back("NMake Makefiles"); +// disable until somebody actually tests it: +// this->SupportedGlobalGenerators.push_back("MSYS Makefiles"); +#endif + this->SupportedGlobalGenerators.push_back("Ninja"); + this->SupportedGlobalGenerators.push_back("Unix Makefiles"); +} + + +void cmExtraKateGenerator::Generate() +{ + const cmMakefile* mf + = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile(); + this->ProjectName = this->GenerateProjectName(mf->GetProjectName(), + mf->GetSafeDefinition("CMAKE_BUILD_TYPE"), + this->GetPathBasename(mf->GetHomeOutputDirectory())); + this->CreateKateProjectFile(mf); + this->CreateDummyKateProjectFile(mf); +} + + +void cmExtraKateGenerator::CreateKateProjectFile(const cmMakefile* mf) const +{ + std::string filename = mf->GetHomeOutputDirectory(); + filename += "/.kateproject"; + cmGeneratedFileStream fout(filename.c_str()); + if (!fout) + { + return; + } + + std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); + std::string args = mf->GetRequiredDefinition("CMAKE_KATE_MAKE_ARGUMENTS"); + + fout << + "{\n" + "\t\"name\": \"" << this->ProjectName << "\",\n" + "\t\"directory\": \"" << mf->GetHomeDirectory() << "\",\n" + "\t\"files\": [ { " << this->GenerateFilesString(mf) << "} ],\n"; + this->WriteTargets(mf, fout); + fout << "}\n"; +} + + +void +cmExtraKateGenerator::WriteTargets(const cmMakefile* mf, + cmGeneratedFileStream& fout) const +{ + fout << + "\t\"build\": {\n" + "\t\t\"directory\": \"" << mf->GetHomeOutputDirectory() << "\",\n" + "\t\t\"default_target\": \"all\",\n" + "\t\t\"prev_target\": \"all\",\n" + "\t\t\"clean_target\": \"clean\",\n" + "\t\t\"targets\":[\n"; + + const std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); + const std::string makeArgs = mf->GetSafeDefinition( + "CMAKE_KATE_MAKE_ARGUMENTS"); + + this->AppendTarget(fout, "all", make, makeArgs, + mf->GetHomeOutputDirectory()); + this->AppendTarget(fout, "clean", make, makeArgs, + mf->GetHomeOutputDirectory()); + + // add all executable and library targets and some of the GLOBAL + // and UTILITY targets + for (std::vector<cmLocalGenerator*>::const_iterator + it = this->GlobalGenerator->GetLocalGenerators().begin(); + it != this->GlobalGenerator->GetLocalGenerators().end(); + ++it) + { + const cmTargets& targets = (*it)->GetMakefile()->GetTargets(); + cmMakefile* makefile=(*it)->GetMakefile(); + std::string currentDir = makefile->GetCurrentOutputDirectory(); + bool topLevel = (currentDir == makefile->GetHomeOutputDirectory()); + + for(cmTargets::const_iterator ti=targets.begin(); ti!=targets.end(); ++ti) + { + switch(ti->second.GetType()) + { + case cmTarget::GLOBAL_TARGET: + { + bool insertTarget = false; + // Only add the global targets from CMAKE_BINARY_DIR, + // not from the subdirs + if (topLevel) + { + insertTarget = true; + // only add the "edit_cache" target if it's not ccmake, because + // this will not work within the IDE + if (ti->first == "edit_cache") + { + const char* editCommand = makefile->GetDefinition + ("CMAKE_EDIT_COMMAND"); + if (editCommand == 0) + { + insertTarget = false; + } + else if (strstr(editCommand, "ccmake")!=NULL) + { + insertTarget = false; + } + } + } + if (insertTarget) + { + this->AppendTarget(fout, ti->first, make, makeArgs, currentDir); + } + } + break; + case cmTarget::UTILITY: + // Add all utility targets, except the Nightly/Continuous/ + // Experimental-"sub"targets as e.g. NightlyStart + if (((ti->first.find("Nightly")==0) &&(ti->first!="Nightly")) + || ((ti->first.find("Continuous")==0)&&(ti->first!="Continuous")) + || ((ti->first.find("Experimental")==0) + && (ti->first!="Experimental"))) + { + break; + } + + this->AppendTarget(fout, ti->first, make, makeArgs, currentDir); + break; + case cmTarget::EXECUTABLE: + case cmTarget::STATIC_LIBRARY: + case cmTarget::SHARED_LIBRARY: + case cmTarget::MODULE_LIBRARY: + case cmTarget::OBJECT_LIBRARY: + { + this->AppendTarget(fout, ti->first, make, makeArgs, currentDir); + std::string fastTarget = ti->first; + fastTarget += "/fast"; + this->AppendTarget(fout, fastTarget, make, makeArgs, currentDir); + + } + break; + default: + break; + } + } + + //insert rules for compiling, preprocessing and assembling individual files + std::vector<std::string> objectFileTargets; + (*it)->GetIndividualFileTargets(objectFileTargets); + for(std::vector<std::string>::const_iterator fit=objectFileTargets.begin(); + fit != objectFileTargets.end(); + ++fit) + { + this->AppendTarget(fout, *fit, make, makeArgs, currentDir); + } + } + + fout << + "\t] }\n"; +} + + +void +cmExtraKateGenerator::AppendTarget(cmGeneratedFileStream& fout, + const std::string& target, + const std::string& make, + const std::string& makeArgs, + const std::string& path) const +{ + static char JsonSep = ' '; + + fout << + "\t\t\t" << JsonSep << "{\"name\":\"" << target << "\", " + "\"build_cmd\":\"" << make << " -C " << path << " " << makeArgs << " " + << target << "\"}\n"; + + JsonSep = ','; +} + + + +void +cmExtraKateGenerator::CreateDummyKateProjectFile(const cmMakefile* mf) const +{ + std::string filename = mf->GetHomeOutputDirectory(); + filename += "/"; + filename += this->ProjectName; + filename += ".kateproject"; + cmGeneratedFileStream fout(filename.c_str()); + if (!fout) + { + return; + } + + fout << "#Generated by cmake, do not edit.\n"; +} + + +std::string +cmExtraKateGenerator::GenerateFilesString(const cmMakefile* mf) const +{ + std::string s = mf->GetHomeDirectory(); + s += "/.git"; + if(cmSystemTools::FileExists(s.c_str())) + { + return std::string("\"git\": 1 "); + } + + s = mf->GetHomeDirectory(); + s += "/.svn"; + if(cmSystemTools::FileExists(s.c_str())) + { + return std::string("\"svn\": 1 "); + } + + s = mf->GetHomeDirectory(); + s += "/"; + + std::set<std::string> files; + std::string tmp; + const std::vector<cmLocalGenerator *>& lgs = + this->GlobalGenerator->GetLocalGenerators(); + + for (std::vector<cmLocalGenerator*>::const_iterator it=lgs.begin(); + it!=lgs.end(); it++) + { + cmMakefile* makefile=(*it)->GetMakefile(); + const std::vector<std::string>& listFiles=makefile->GetListFiles(); + for (std::vector<std::string>::const_iterator lt=listFiles.begin(); + lt!=listFiles.end(); lt++) + { + tmp=*lt; + { + files.insert(tmp); + } + } + + const std::vector<cmSourceFile*>& sources = makefile->GetSourceFiles(); + for (std::vector<cmSourceFile*>::const_iterator sfIt = sources.begin(); + sfIt != sources.end(); sfIt++) + { + cmSourceFile* sf = *sfIt; + if (sf->GetPropertyAsBool("GENERATED")) + { + continue; + } + + tmp = sf->GetFullPath(); + files.insert(tmp); + } + } + + const char* sep = ""; + tmp = "\"list\": ["; + for(std::set<std::string>::const_iterator it = files.begin(); + it != files.end(); ++it) + { + tmp += sep; + tmp += " \""; + tmp += *it; + tmp += "\""; + sep = ","; + } + tmp += "] "; + + return tmp; +} + + +std::string cmExtraKateGenerator::GenerateProjectName(const std::string& name, + const std::string& type, + const std::string& path) const +{ + return name + (type.empty() ? "" : "-") + type + "@" + path; +} + + +std::string cmExtraKateGenerator::GetPathBasename(const std::string& path)const +{ + std::string outputBasename = path; + while (outputBasename.size() > 0 && + (outputBasename[outputBasename.size() - 1] == '/' || + outputBasename[outputBasename.size() - 1] == '\\')) + { + outputBasename.resize(outputBasename.size() - 1); + } + std::string::size_type loc = outputBasename.find_last_of("/\\"); + if (loc != std::string::npos) + { + outputBasename = outputBasename.substr(loc + 1); + } + + return outputBasename; +} + + +// Create the command line for building the given target using the selected +// make +std::string cmExtraKateGenerator::BuildMakeCommand(const std::string& make, + const char* makefile, const char* target) const +{ + std::string command = make; + if (strcmp(this->GlobalGenerator->GetName(), "NMake Makefiles")==0) + { + std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile); + command += " /NOLOGO /f ""; + command += makefileName; + command += "" "; + command += " VERBOSE=1 "; + command += target; + } + else if (strcmp(this->GlobalGenerator->GetName(), "MinGW Makefiles")==0) + { + // no escaping of spaces in this case, see + // http://public.kitware.com/Bug/view.php?id=10014 + std::string makefileName = makefile; + command += " -f ""; + command += makefileName; + command += "" "; + command += " VERBOSE=1 "; + command += target; + } + else if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0) + { + command += " -v "; + command += target; + } + else + { + std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile); + command += " -f ""; + command += makefileName; + command += "" "; + command += " VERBOSE=1 "; + command += target; + } + return command; +} diff --git a/Source/cmExtraKateGenerator.h b/Source/cmExtraKateGenerator.h new file mode 100644 index 0000000..4979eff --- /dev/null +++ b/Source/cmExtraKateGenerator.h @@ -0,0 +1,62 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2004-2009 Kitware, Inc. + Copyright 2013 Alexander Neundorf (neundorf@kde.org) + + 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 cmExtraKateGenerator_h +#define cmExtraKateGenerator_h + +#include "cmExternalMakefileProjectGenerator.h" + +class cmLocalGenerator; +class cmMakefile; +class cmTarget; +class cmGeneratedFileStream; + +/** \class cmExtraKateGenerator + * \brief Write Kate project files for Makefile or ninja based projects + */ +class cmExtraKateGenerator : public cmExternalMakefileProjectGenerator +{ +public: + cmExtraKateGenerator(); + + virtual const char* GetName() const + { return cmExtraKateGenerator::GetActualName();} + static const char* GetActualName() { return "Kate";} + static cmExternalMakefileProjectGenerator* New() + { return new cmExtraKateGenerator; } + /** Get the documentation entry for this generator. */ + virtual void GetDocumentation(cmDocumentationEntry& entry, + const char* fullName) const; + + virtual void Generate(); +private: + void CreateKateProjectFile(const cmMakefile* mf) const; + void CreateDummyKateProjectFile(const cmMakefile* mf) const; + void WriteTargets(const cmMakefile* mf, cmGeneratedFileStream& fout) const; + void AppendTarget(cmGeneratedFileStream& fout, + const std::string& target, + const std::string& make, + const std::string& makeArgs, + const std::string& path) const; + + std::string GenerateFilesString(const cmMakefile* mf) const; + std::string GetPathBasename(const std::string& path) const; + std::string GenerateProjectName(const std::string& name, + const std::string& type, + const std::string& path) const; + std::string BuildMakeCommand(const std::string& make, + const char* makefile, const char* target) const; + + std::string ProjectName; +}; + +#endif diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index 7beeda0..e8c8da3 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -138,22 +138,36 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) { return; } + const char* sysroot = + this->Makefile->GetDefinition("CMAKE_SYSROOT"); const char* rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH"); - if((rootPath == 0) || (strlen(rootPath) == 0)) + const bool noSysroot = !sysroot || !*sysroot; + const bool noRootPath = !rootPath || !*rootPath; + if(noSysroot && noRootPath) { return; } // Construct the list of path roots with no trailing slashes. std::vector<std::string> roots; - cmSystemTools::ExpandListArgument(rootPath, roots); + if (rootPath) + { + cmSystemTools::ExpandListArgument(rootPath, roots); + } + if (sysroot) + { + roots.push_back(sysroot); + } for(std::vector<std::string>::iterator ri = roots.begin(); ri != roots.end(); ++ri) { cmSystemTools::ConvertToUnixSlashes(*ri); } + const char* stagePrefix = + this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); + // Copy the original set of unrooted paths. std::vector<std::string> unrootedPaths = paths; paths.clear(); @@ -168,7 +182,9 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) // already inside. Skip the unrooted path if it is relative to // a user home directory or is empty. std::string rootedDir; - if(cmSystemTools::IsSubDirectory(ui->c_str(), ri->c_str())) + if(cmSystemTools::IsSubDirectory(ui->c_str(), ri->c_str()) + || (stagePrefix + && cmSystemTools::IsSubDirectory(ui->c_str(), stagePrefix))) { rootedDir = *ui; } diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index f34a35b..2e66d78 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -245,7 +245,7 @@ static void prefixItems(const std::string &content, std::string &result, result += sep; sep = ";"; if (!cmSystemTools::FileIsFullPath(ei->c_str()) - && cmGeneratorExpression::Find(*ei) == std::string::npos) + && cmGeneratorExpression::Find(*ei) != 0) { result += prefix; } diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 92dc054..92f74f3 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -173,8 +173,8 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char *tgt) return (strcmp(prop, "LINK_LIBRARIES") == 0 || strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0 || strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0 - || strncmp(prop, "LINK_INTERFACE_LIBRARIES_", 25) == 0 - || strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 34) == 0) + || cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_") + || cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_")) || strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0; } @@ -200,7 +200,7 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions() const const char *prop = this->Property.c_str(); return (strcmp(prop, "COMPILE_DEFINITIONS") == 0 || strcmp(prop, "INTERFACE_COMPILE_DEFINITIONS") == 0 - || strncmp(prop, "COMPILE_DEFINITIONS_", 20) == 0); + || cmHasLiteralPrefix(prop, "COMPILE_DEFINITIONS_")); } //---------------------------------------------------------------------------- @@ -210,3 +210,11 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingCompileOptions() const return (strcmp(prop, "COMPILE_OPTIONS") == 0 || strcmp(prop, "INTERFACE_COMPILE_OPTIONS") == 0 ); } + +//---------------------------------------------------------------------------- +bool cmGeneratorExpressionDAGChecker::EvaluatingAutoUicOptions() const +{ + const char *prop = this->Property.c_str(); + return (strcmp(prop, "AUTOUIC_OPTIONS") == 0 + || strcmp(prop, "INTERFACE_AUTOUIC_OPTIONS") == 0 ); +} diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index c8594e7..fd47ad7 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -20,13 +20,15 @@ F(EvaluatingIncludeDirectories) \ F(EvaluatingSystemIncludeDirectories) \ F(EvaluatingCompileDefinitions) \ - F(EvaluatingCompileOptions) + F(EvaluatingCompileOptions) \ + F(EvaluatingAutoUicOptions) #define CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(F) \ F(INCLUDE_DIRECTORIES) \ F(SYSTEM_INCLUDE_DIRECTORIES) \ F(COMPILE_DEFINITIONS) \ - F(COMPILE_OPTIONS) + F(COMPILE_OPTIONS) \ + F(AUTOUIC_OPTIONS) //---------------------------------------------------------------------------- struct cmGeneratorExpressionDAGChecker diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 2ae5a22..0f8c4e3 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -199,6 +199,48 @@ static const struct StrEqualNode : public cmGeneratorExpressionNode } strEqualNode; //---------------------------------------------------------------------------- +static const struct LowerCaseNode : public cmGeneratorExpressionNode +{ + LowerCaseNode() {} + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return cmSystemTools::LowerCase(parameters.front()); + } +} lowerCaseNode; + +//---------------------------------------------------------------------------- +static const struct UpperCaseNode : public cmGeneratorExpressionNode +{ + UpperCaseNode() {} + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return cmSystemTools::UpperCase(parameters.front()); + } +} upperCaseNode; + +//---------------------------------------------------------------------------- +static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode +{ + MakeCIdentifierNode() {} + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return cmSystemTools::MakeCidentifier(parameters.front().c_str()); + } +} makeCIdentifierNode; + +//---------------------------------------------------------------------------- static const struct Angle_RNode : public cmGeneratorExpressionNode { Angle_RNode() {} @@ -902,8 +944,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(POPULATE_INTERFACE_PROPERTY_NAME) // Note that the above macro terminates with an else - /* else */ if (strncmp(propertyName.c_str(), - "COMPILE_DEFINITIONS_", 20) == 0) + /* else */ if (cmHasLiteralPrefix(propertyName.c_str(), + "COMPILE_DEFINITIONS_")) { interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS"; } @@ -954,7 +996,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode if (!prop) { - if (target->IsImported()) + if (target->IsImported() + || target->GetType() == cmTarget::INTERFACE_LIBRARY) { return linkedTargetsContent; } @@ -1441,6 +1484,12 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) return &targetSoNameFileDirNode; else if (identifier == "STREQUAL") return &strEqualNode; + else if (identifier == "LOWER_CASE") + return &lowerCaseNode; + else if (identifier == "UPPER_CASE") + return &upperCaseNode; + else if (identifier == "MAKE_C_IDENTIFIER") + return &makeCIdentifierNode; else if (identifier == "BOOL") return &boolNode; else if (identifier == "ANGLE-R") diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index b964f71..5a535c7 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -611,8 +611,8 @@ const char* cmGeneratorTarget::GetCreateRuleVariable() const } //---------------------------------------------------------------------------- -std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories( - const char *config) +std::vector<std::string> +cmGeneratorTarget::GetIncludeDirectories(const char *config) const { return this->Target->GetIncludeDirectories(config); } @@ -692,3 +692,14 @@ void cmGeneratorTarget::GenerateTargetManifest(const char* config) const gg->AddToManifest(config? config:"", f); } } + +bool cmStrictTargetComparison::operator()(cmTarget *t1, cmTarget *t2) const +{ + int nameResult = strcmp(t1->GetName(), t2->GetName()); + if (nameResult == 0) + { + return strcmp(t1->GetMakefile()->GetStartOutputDirectory(), + t2->GetMakefile()->GetStartOutputDirectory()) < 0; + } + return nameResult < 0; +} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 177bc25..d2b65b2 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -70,7 +70,7 @@ public: const char* GetCreateRuleVariable() const; /** Get the include directories for this target. */ - std::vector<std::string> GetIncludeDirectories(const char *config); + std::vector<std::string> GetIncludeDirectories(const char *config) const; bool IsSystemIncludeDirectory(const char *dir, const char *config) const; @@ -100,6 +100,12 @@ private: void operator=(cmGeneratorTarget const&); }; -typedef std::map<cmTarget*, cmGeneratorTarget*> cmGeneratorTargetsType; +struct cmStrictTargetComparison { + bool operator()(cmTarget *t1, cmTarget *t2) const; +}; + +typedef std::map<cmTarget*, + cmGeneratorTarget*, + cmStrictTargetComparison> cmGeneratorTargetsType; #endif diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index b11b274..e6f3d94 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -695,6 +695,11 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, { mf->ReadListFile(0,projectCompatibility.c_str()); } + // Inform any extra generator of the new language. + if (this->ExtraGenerator) + { + this->ExtraGenerator->EnableLanguage(languages, mf, false); + } if(fatalError) { @@ -1304,6 +1309,11 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() { cmTarget* t = &ti->second; + if (t->GetType() == cmTarget::INTERFACE_LIBRARY) + { + continue; + } + t->AppendBuildInterfaceIncludes(); for (std::vector<cmValueWithOrigin>::const_iterator it @@ -1456,6 +1466,10 @@ void cmGlobalGenerator::CheckLocalGenerators() for (cmTargets::iterator l = targets.begin(); l != targets.end(); l++) { + if (l->second.GetType() == cmTarget::INTERFACE_LIBRARY) + { + continue; + } const cmTarget::LinkLibraryVectorType& libs = l->second.GetOriginalLinkLibraries(); for(cmTarget::LinkLibraryVectorType::const_iterator lib = libs.begin(); @@ -1981,7 +1995,7 @@ void cmGlobalGenerator::AddAlias(const char *name, cmTarget *tgt) } //---------------------------------------------------------------------------- -bool cmGlobalGenerator::IsAlias(const char *name) +bool cmGlobalGenerator::IsAlias(const char *name) const { return this->AliasTargets.find(name) != this->AliasTargets.end(); } @@ -1989,15 +2003,16 @@ bool cmGlobalGenerator::IsAlias(const char *name) //---------------------------------------------------------------------------- cmTarget* cmGlobalGenerator::FindTarget(const char* project, const char* name, - bool excludeAliases) + bool excludeAliases) const { // if project specific if(project) { - std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project]; - for(unsigned int i = 0; i < gens->size(); ++i) + std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator + gens = this->ProjectMap.find(project); + for(unsigned int i = 0; i < gens->second.size(); ++i) { - cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name, + cmTarget* ret = (gens->second)[i]->GetMakefile()->FindTarget(name, excludeAliases); if(ret) { @@ -2010,14 +2025,14 @@ cmGlobalGenerator::FindTarget(const char* project, const char* name, { if (!excludeAliases) { - std::map<cmStdString, cmTarget*>::iterator ai + std::map<cmStdString, cmTarget*>::const_iterator ai = this->AliasTargets.find(name); if (ai != this->AliasTargets.end()) { return ai->second; } } - std::map<cmStdString,cmTarget *>::iterator i = + std::map<cmStdString,cmTarget *>::const_iterator i = this->TotalTargets.find ( name ); if ( i != this->TotalTargets.end() ) { @@ -2033,7 +2048,8 @@ cmGlobalGenerator::FindTarget(const char* project, const char* name, } //---------------------------------------------------------------------------- -bool cmGlobalGenerator::NameResolvesToFramework(const std::string& libname) +bool +cmGlobalGenerator::NameResolvesToFramework(const std::string& libname) const { if(cmSystemTools::IsPathToFramework(libname.c_str())) { @@ -2407,7 +2423,7 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget( // Store the custom command in the target. cmCustomCommand cc(0, no_outputs, no_depends, *commandLines, 0, workingDirectory); - target.GetPostBuildCommands().push_back(cc); + target.AddPostBuildCommand(cc); target.SetProperty("EchoString", message); std::vector<std::string>::iterator dit; for ( dit = depends.begin(); dit != depends.end(); ++ dit ) @@ -2479,6 +2495,37 @@ void cmGlobalGenerator::AddTarget(cmTarget* t) } } +bool cmGlobalGenerator::IsReservedTarget(std::string const& name) +{ + // The following is a list of targets reserved + // by one or more of the cmake generators. + + // Adding additional targets to this list will require a policy! + const char* reservedTargets[] = + { + "all", "ALL_BUILD", + "help", + "install", "INSTALL", + "preinstall", + "clean", + "edit_cache", + "rebuild_cache", + "test", "RUN_TESTS", + "package", "PACKAGE", + "package_source", + "ZERO_CHECK", + 0 + }; + + for(const char** reservedTarget = reservedTargets; + *reservedTarget; ++reservedTarget) + { + if(name == *reservedTarget) return true; + } + + return false; +} + void cmGlobalGenerator::SetExternalMakefileProjectGenerator( cmExternalMakefileProjectGenerator *extraGenerator) { diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 6e93609..eb720a8 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -207,14 +207,14 @@ public: ///! Find a target by name by searching the local generators. cmTarget* FindTarget(const char* project, const char* name, - bool excludeAliases = false); + bool excludeAliases = false) const; void AddAlias(const char *name, cmTarget *tgt); - bool IsAlias(const char *name); + bool IsAlias(const char *name) const; /** Determine if a name resolves to a framework on disk or a built target that is a framework. */ - bool NameResolvesToFramework(const std::string& libname); + bool NameResolvesToFramework(const std::string& libname) const; /** If check to see if the target is linked to by any other target in the project */ @@ -244,6 +244,8 @@ public: void AddTarget(cmTarget* t); + static bool IsReservedTarget(std::string const& name); + virtual const char* GetAllTargetName() const { return "ALL_BUILD"; } virtual const char* GetInstallTargetName() const { return "INSTALL"; } virtual const char* GetInstallLocalTargetName() const { return 0; } diff --git a/Source/cmGlobalKdevelopGenerator.cxx b/Source/cmGlobalKdevelopGenerator.cxx index 273d4bb..ab7db51 100644 --- a/Source/cmGlobalKdevelopGenerator.cxx +++ b/Source/cmGlobalKdevelopGenerator.cxx @@ -75,7 +75,7 @@ void cmGlobalKdevelopGenerator::Generate() { if (ti->second.GetType()==cmTarget::EXECUTABLE) { - executable = ti->second.GetProperty("LOCATION"); + executable = ti->second.GetLocation(0); break; } } diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index e1af2f9..6333873 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -471,23 +471,29 @@ cmGlobalUnixMakefileGenerator3 // The directory-level rule should depend on the target-level rules // for all targets in the directory. std::vector<std::string> depends; - for(cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin(); - l != lg->GetMakefile()->GetTargets().end(); ++l) + cmGeneratorTargetsType targets = lg->GetMakefile()->GetGeneratorTargets(); + for(cmGeneratorTargetsType::iterator l = targets.begin(); + l != targets.end(); ++l) { - if((l->second.GetType() == cmTarget::EXECUTABLE) || - (l->second.GetType() == cmTarget::STATIC_LIBRARY) || - (l->second.GetType() == cmTarget::SHARED_LIBRARY) || - (l->second.GetType() == cmTarget::MODULE_LIBRARY) || - (l->second.GetType() == cmTarget::OBJECT_LIBRARY) || - (l->second.GetType() == cmTarget::INTERFACE_LIBRARY) || - (l->second.GetType() == cmTarget::UTILITY)) + if((l->second->GetType() == cmTarget::EXECUTABLE) || + (l->second->GetType() == cmTarget::STATIC_LIBRARY) || + (l->second->GetType() == cmTarget::SHARED_LIBRARY) || + (l->second->GetType() == cmTarget::MODULE_LIBRARY) || + (l->second->GetType() == cmTarget::OBJECT_LIBRARY) || + (l->second->GetType() == cmTarget::INTERFACE_LIBRARY) || + (l->second->GetType() == cmTarget::UTILITY)) { + if(l->second->Target->IsImported()) + { + continue; + } // Add this to the list of depends rules in this directory. - if((!check_all || !l->second.GetPropertyAsBool("EXCLUDE_FROM_ALL")) && + if((!check_all || !l->second->GetPropertyAsBool("EXCLUDE_FROM_ALL")) && (!check_relink || - l->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str()))) + l->second->Target + ->NeedRelinkBeforeInstall(lg->ConfigurationName.c_str()))) { - std::string tname = lg->GetRelativeTargetDirectory(l->second); + std::string tname = lg->GetRelativeTargetDirectory(*l->second->Target); tname += "/"; tname += pass; depends.push_back(tname); @@ -632,49 +638,55 @@ cmGlobalUnixMakefileGenerator3 lg = static_cast<cmLocalUnixMakefileGenerator3 *> (this->LocalGenerators[i]); // for each target Generate the rule files for each target. - cmTargets& targets = lg->GetMakefile()->GetTargets(); - for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t) + cmGeneratorTargetsType targets = lg->GetMakefile()->GetGeneratorTargets(); + for(cmGeneratorTargetsType::iterator t = targets.begin(); + t != targets.end(); ++t) { + if(t->second->Target->IsImported()) + { + continue; + } // Don't emit the same rule twice (e.g. two targets with the same // simple name) - if(t->second.GetName() && - strlen(t->second.GetName()) && - emitted.insert(t->second.GetName()).second && + if(t->second->GetName() && + strlen(t->second->GetName()) && + emitted.insert(t->second->GetName()).second && // Handle user targets here. Global targets are handled in // the local generator on a per-directory basis. - ((t->second.GetType() == cmTarget::EXECUTABLE) || - (t->second.GetType() == cmTarget::STATIC_LIBRARY) || - (t->second.GetType() == cmTarget::SHARED_LIBRARY) || - (t->second.GetType() == cmTarget::MODULE_LIBRARY) || - (t->second.GetType() == cmTarget::OBJECT_LIBRARY) || - (t->second.GetType() == cmTarget::INTERFACE_LIBRARY) || - (t->second.GetType() == cmTarget::UTILITY))) + ((t->second->GetType() == cmTarget::EXECUTABLE) || + (t->second->GetType() == cmTarget::STATIC_LIBRARY) || + (t->second->GetType() == cmTarget::SHARED_LIBRARY) || + (t->second->GetType() == cmTarget::MODULE_LIBRARY) || + (t->second->GetType() == cmTarget::OBJECT_LIBRARY) || + (t->second->GetType() == cmTarget::INTERFACE_LIBRARY) || + (t->second->GetType() == cmTarget::UTILITY))) { // Add a rule to build the target by name. lg->WriteDivider(ruleFileStream); ruleFileStream << "# Target rules for targets named " - << t->second.GetName() << "\n\n"; + << t->second->GetName() << "\n\n"; // Write the rule. commands.clear(); std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash(); tmp += "Makefile2"; commands.push_back(lg->GetRecursiveMakeCall - (tmp.c_str(),t->second.GetName())); + (tmp.c_str(),t->second->GetName())); depends.clear(); depends.push_back("cmake_check_build_system"); lg->WriteMakeRule(ruleFileStream, "Build rule for target.", - t->second.GetName(), depends, commands, + t->second->GetName(), depends, commands, true); - if (t->second.GetType() == cmTarget::INTERFACE_LIBRARY) + if (t->second->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; } // Add a fast rule to build the target - std::string localName = lg->GetRelativeTargetDirectory(t->second); + std::string localName = + lg->GetRelativeTargetDirectory(*t->second->Target); std::string makefileName; makefileName = localName; makefileName += "/build.make"; @@ -682,7 +694,7 @@ cmGlobalUnixMakefileGenerator3 commands.clear(); std::string makeTargetName = localName; makeTargetName += "/build"; - localName = t->second.GetName(); + localName = t->second->GetName(); localName += "/fast"; commands.push_back(lg->GetRecursiveMakeCall (makefileName.c_str(), makeTargetName.c_str())); @@ -691,11 +703,12 @@ cmGlobalUnixMakefileGenerator3 // Add a local name for the rule to relink the target before // installation. - if(t->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str())) + if(t->second->Target + ->NeedRelinkBeforeInstall(lg->ConfigurationName.c_str())) { - makeTargetName = lg->GetRelativeTargetDirectory(t->second); + makeTargetName = lg->GetRelativeTargetDirectory(*t->second->Target); makeTargetName += "/preinstall"; - localName = t->second.GetName(); + localName = t->second->GetName(); localName += "/preinstall"; depends.clear(); commands.clear(); @@ -729,26 +742,31 @@ cmGlobalUnixMakefileGenerator3 depends.push_back("cmake_check_build_system"); // for each target Generate the rule files for each target. - cmTargets& targets = lg->GetMakefile()->GetTargets(); - for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t) + cmGeneratorTargetsType targets = lg->GetMakefile()->GetGeneratorTargets(); + for(cmGeneratorTargetsType::iterator t = targets.begin(); + t != targets.end(); ++t) { - if (t->second.GetName() - && strlen(t->second.GetName()) - && ((t->second.GetType() == cmTarget::EXECUTABLE) - || (t->second.GetType() == cmTarget::STATIC_LIBRARY) - || (t->second.GetType() == cmTarget::SHARED_LIBRARY) - || (t->second.GetType() == cmTarget::MODULE_LIBRARY) - || (t->second.GetType() == cmTarget::OBJECT_LIBRARY) - || (t->second.GetType() == cmTarget::INTERFACE_LIBRARY) - || (t->second.GetType() == cmTarget::UTILITY))) + if(t->second->Target->IsImported()) + { + continue; + } + if (t->second->GetName() + && strlen(t->second->GetName()) + && ((t->second->GetType() == cmTarget::EXECUTABLE) + || (t->second->GetType() == cmTarget::STATIC_LIBRARY) + || (t->second->GetType() == cmTarget::SHARED_LIBRARY) + || (t->second->GetType() == cmTarget::MODULE_LIBRARY) + || (t->second->GetType() == cmTarget::OBJECT_LIBRARY) + || (t->second->GetType() == cmTarget::INTERFACE_LIBRARY) + || (t->second->GetType() == cmTarget::UTILITY))) { std::string makefileName; // Add a rule to build the target by name. - localName = lg->GetRelativeTargetDirectory(t->second); + localName = lg->GetRelativeTargetDirectory(*t->second->Target); makefileName = localName; makefileName += "/build.make"; - bool needRequiresStep = this->NeedRequiresStep(t->second); + bool needRequiresStep = this->NeedRequiresStep(*t->second->Target); lg->WriteDivider(ruleFileStream); ruleFileStream @@ -757,7 +775,7 @@ cmGlobalUnixMakefileGenerator3 commands.clear(); - if(t->second.GetType() != cmTarget::INTERFACE_LIBRARY) + if(t->second->GetType() != cmTarget::INTERFACE_LIBRARY) { makeTargetName = localName; makeTargetName += "/depend"; @@ -793,7 +811,7 @@ cmGlobalUnixMakefileGenerator3 cmLocalGenerator::SHELL); progCmd << " "; std::vector<unsigned long>& progFiles = - this->ProgressMap[&t->second].Marks; + this->ProgressMap[t->second->Target].Marks; for (std::vector<unsigned long>::iterator i = progFiles.begin(); i != progFiles.end(); ++i) { @@ -802,14 +820,14 @@ cmGlobalUnixMakefileGenerator3 commands.push_back(progCmd.str()); } progressDir = "Built target "; - progressDir += t->first; + progressDir += t->second->GetName(); lg->AppendEcho(commands,progressDir.c_str()); } else { depends.clear(); } - this->AppendGlobalTargetDepends(depends,t->second); + this->AppendGlobalTargetDepends(depends,*t->second->Target); if(depends.empty() && this->EmptyRuleHackDepends != "") { depends.push_back(this->EmptyRuleHackDepends); @@ -818,7 +836,7 @@ cmGlobalUnixMakefileGenerator3 localName.c_str(), depends, commands, true); // add the all/all dependency - if(!this->IsExcluded(this->LocalGenerators[0], t->second)) + if(!this->IsExcluded(this->LocalGenerators[0], *t->second->Target)) { depends.clear(); depends.push_back(localName); @@ -843,7 +861,7 @@ cmGlobalUnixMakefileGenerator3 // std::set<cmTarget *> emitted; progCmd << " " - << this->CountProgressMarksInTarget(&t->second, emitted); + << this->CountProgressMarksInTarget(t->second->Target, emitted); commands.push_back(progCmd.str()); } std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash(); @@ -861,7 +879,7 @@ cmGlobalUnixMakefileGenerator3 } depends.clear(); depends.push_back("cmake_check_build_system"); - localName = lg->GetRelativeTargetDirectory(t->second); + localName = lg->GetRelativeTargetDirectory(*t->second->Target); localName += "/rule"; lg->WriteMakeRule(ruleFileStream, "Build rule for subdir invocation for target.", @@ -872,12 +890,13 @@ cmGlobalUnixMakefileGenerator3 depends.clear(); depends.push_back(localName); lg->WriteMakeRule(ruleFileStream, "Convenience name for target.", - t->second.GetName(), depends, commands, true); + t->second->GetName(), depends, commands, true); // Add rules to prepare the target for installation. - if(t->second.NeedRelinkBeforeInstall(lg->ConfigurationName.c_str())) + if(t->second->Target + ->NeedRelinkBeforeInstall(lg->ConfigurationName.c_str())) { - localName = lg->GetRelativeTargetDirectory(t->second); + localName = lg->GetRelativeTargetDirectory(*t->second->Target); localName += "/preinstall"; depends.clear(); commands.clear(); @@ -887,7 +906,7 @@ cmGlobalUnixMakefileGenerator3 "Pre-install relink rule for target.", localName.c_str(), depends, commands, true); - if(!this->IsExcluded(this->LocalGenerators[0], t->second)) + if(!this->IsExcluded(this->LocalGenerators[0], *t->second->Target)) { depends.clear(); depends.push_back(localName); @@ -898,7 +917,7 @@ cmGlobalUnixMakefileGenerator3 } // add the clean rule - localName = lg->GetRelativeTargetDirectory(t->second); + localName = lg->GetRelativeTargetDirectory(*t->second->Target); makeTargetName = localName; makeTargetName += "/clean"; depends.clear(); diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index d0fe5d9..6983ef9 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -28,7 +28,7 @@ static const char* cmVS10GenName(const char* name, std::string& genName) return 0; } const char* p = name + sizeof(vs10generatorName) - 6; - if(strncmp(p, " 2010", 5) == 0) + if(cmHasLiteralPrefix(p, " 2010")) { p += 5; } diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx index f1d7312..1f0c47a 100644 --- a/Source/cmGlobalVisualStudio11Generator.cxx +++ b/Source/cmGlobalVisualStudio11Generator.cxx @@ -23,7 +23,7 @@ static const char* cmVS11GenName(const char* name, std::string& genName) return 0; } const char* p = name + sizeof(vs11generatorName) - 6; - if(strncmp(p, " 2012", 5) == 0) + if(cmHasLiteralPrefix(p, " 2012")) { p += 5; } diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index edd5567..3074794 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -23,7 +23,7 @@ static const char* cmVS12GenName(const char* name, std::string& genName) return 0; } const char* p = name + sizeof(vs12generatorName) - 6; - if(strncmp(p, " 2013", 5) == 0) + if(cmHasLiteralPrefix(p, " 2013")) { p += 5; } diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 35d7796..25fe10b 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -335,6 +335,10 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( projectTargets.begin(); tt != projectTargets.end(); ++tt) { cmTarget* target = *tt; + if(target->GetType() == cmTarget::INTERFACE_LIBRARY) + { + continue; + } const char* expath = target->GetProperty("EXTERNAL_MSPROJECT"); if(expath) { @@ -372,6 +376,10 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( projectTargets.begin(); tt != projectTargets.end(); ++tt) { cmTarget* target = *tt; + if(target->GetType() == cmTarget::INTERFACE_LIBRARY) + { + continue; + } bool written = false; // handle external vc project files diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 69b0a7a..e4ce13f 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -442,7 +442,8 @@ bool cmGlobalVisualStudio8Generator::NeedLinkLibraryDependencies( { if(cmTarget* depTarget = this->FindTarget(0, ui->c_str())) { - if(depTarget->GetProperty("EXTERNAL_MSPROJECT")) + if(depTarget->GetType() != cmTarget::INTERFACE_LIBRARY + && depTarget->GetProperty("EXTERNAL_MSPROJECT")) { // This utility dependency names an external .vcproj target. // We use LinkLibraryDependencies="true" to link to it without diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx index 6ae8775..98ce685 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.cxx +++ b/Source/cmGlobalWatcomWMakeGenerator.cxx @@ -47,7 +47,7 @@ cmLocalGenerator *cmGlobalWatcomWMakeGenerator::CreateLocalGenerator() lg->SetDefineWindowsNULL(true); lg->SetWindowsShell(true); lg->SetWatcomWMake(true); - lg->SetMakeSilentFlag("-s -h"); + lg->SetMakeSilentFlag("-s -h -e"); lg->SetGlobalGenerator(this); lg->SetIgnoreLibPrefix(true); lg->SetPassMakeflags(false); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index be0459d..215d483 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3031,23 +3031,23 @@ cmXCodeObject* cmGlobalXCodeGenerator cmStdString curr_tgt_folder; for(std::vector<std::string>::size_type i = 0; i < tgt_folders.size();i++) { - curr_tgt_folder += tgt_folders[i]; - it = this->TargetGroup.find(curr_tgt_folder); - if(it == this->TargetGroup.end()) + if (i != 0) { - tgroup = this->CreatePBXGroup(tgroup,tgt_folders[i]); - this->TargetGroup[curr_tgt_folder] = tgroup; + curr_tgt_folder += "/"; } - else + curr_tgt_folder += tgt_folders[i]; + it = this->TargetGroup.find(curr_tgt_folder); + if(it != this->TargetGroup.end()) { tgroup = it->second; continue; } + tgroup = this->CreatePBXGroup(tgroup,tgt_folders[i]); + this->TargetGroup[curr_tgt_folder] = tgroup; if(i == 0) { this->SourcesGroupChildren->AddObject(tgroup); } - curr_tgt_folder += "/"; } } this->TargetGroup[target] = tgroup; diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index d309a2a..10578f2 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -645,7 +645,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // generators for them. bool createInstallGeneratorsForTargetFileSets = true; - if(target.IsFrameworkOnApple()) + if(target.IsFrameworkOnApple() + || target.GetType() == cmTarget::INTERFACE_LIBRARY) { createInstallGeneratorsForTargetFileSets = false; } diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx index 91ea861..236ca1f 100644 --- a/Source/cmInstallCommandArguments.cxx +++ b/Source/cmInstallCommandArguments.cxx @@ -228,11 +228,6 @@ void cmInstallCommandIncludesArgument::Parse( for ( ; it != args->end(); ++it) { std::string dir = *it; - if (!cmSystemTools::FileIsFullPath(it->c_str()) - && cmGeneratorExpression::Find(*it) == std::string::npos) - { - dir = "$<INSTALL_PREFIX>/" + dir; - } cmSystemTools::ConvertToUnixSlashes(dir); this->IncludeDirs.push_back(dir); } diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 63ec576..c3c5299 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -370,6 +370,11 @@ void cmLocalGenerator::GenerateInstallRules() prefix = "/usr/local"; } #endif + if (const char *stagingPrefix + = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX")) + { + prefix = stagingPrefix; + } // Compute the set of configurations. std::vector<std::string> configurationTypes; @@ -536,6 +541,10 @@ void cmLocalGenerator::GenerateTargetManifest() t != targets.end(); ++t) { cmGeneratorTarget& target = *t->second; + if (target.Target->GetType() == cmTarget::INTERFACE_LIBRARY) + { + continue; + } if(configNames.empty()) { target.GenerateTargetManifest(0); @@ -798,6 +807,7 @@ static const char* ruleReplaceVars[] = "CMAKE_CURRENT_BINARY_DIR", "CMAKE_RANLIB", "CMAKE_LINKER", + "CMAKE_CL_SHOWINCLUDES_PREFIX", 0 }; @@ -1043,11 +1053,38 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable, // If this is the compiler then look for the extra variable // _COMPILER_ARG1 which must be the first argument to the compiler const char* compilerArg1 = 0; + const char* compilerTarget = 0; + const char* compilerOptionTarget = 0; + const char* compilerExternalToolchain = 0; + const char* compilerOptionExternalToolchain = 0; + const char* compilerSysroot = 0; + const char* compilerOptionSysroot = 0; if(actualReplace == "CMAKE_${LANG}_COMPILER") { std::string arg1 = actualReplace + "_ARG1"; cmSystemTools::ReplaceString(arg1, "${LANG}", lang); compilerArg1 = this->Makefile->GetDefinition(arg1.c_str()); + compilerTarget + = this->Makefile->GetDefinition( + (std::string("CMAKE_") + lang + "_COMPILER_TARGET").c_str()); + compilerOptionTarget + = this->Makefile->GetDefinition( + (std::string("CMAKE_") + lang + + "_COMPILE_OPTIONS_TARGET").c_str()); + compilerExternalToolchain + = this->Makefile->GetDefinition( + (std::string("CMAKE_") + lang + + "_COMPILER_EXTERNAL_TOOLCHAIN").c_str()); + compilerOptionExternalToolchain + = this->Makefile->GetDefinition( + (std::string("CMAKE_") + lang + + "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN").c_str()); + compilerSysroot + = this->Makefile->GetDefinition("CMAKE_SYSROOT"); + compilerOptionSysroot + = this->Makefile->GetDefinition( + (std::string("CMAKE_") + lang + + "_COMPILE_OPTIONS_SYSROOT").c_str()); } if(actualReplace.find("${LANG}") != actualReplace.npos) { @@ -1068,6 +1105,24 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable, ret += " "; ret += compilerArg1; } + if (compilerTarget && compilerOptionTarget) + { + ret += " "; + ret += compilerOptionTarget; + ret += compilerTarget; + } + if (compilerExternalToolchain && compilerOptionExternalToolchain) + { + ret += " "; + ret += compilerOptionExternalToolchain; + ret += this->EscapeForShell(compilerExternalToolchain, true); + } + if (compilerSysroot && compilerOptionSysroot) + { + ret += " "; + ret += compilerOptionSysroot; + ret += this->EscapeForShell(compilerSysroot, true); + } return ret; } return replace; @@ -1462,6 +1517,8 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, return; } + std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + std::vector<std::string> implicitDirs; // Load implicit include directories for this language. std::string impDirVar = "CMAKE_"; @@ -1474,7 +1531,9 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, for(std::vector<std::string>::const_iterator i = impDirVec.begin(); i != impDirVec.end(); ++i) { - emitted.insert(*i); + std::string d = rootPath + *i; + cmSystemTools::ConvertToUnixSlashes(d); + emitted.insert(d); if (!stripImplicitInclDirs) { implicitDirs.push_back(*i); @@ -2775,6 +2834,11 @@ cmLocalGenerator cmTargets& tgts = this->Makefile->GetTargets(); for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l) { + if (l->second.GetType() == cmTarget::INTERFACE_LIBRARY) + { + continue; + } + // Include the user-specified pre-install script for this target. if(const char* preinstall = l->second.GetProperty("PRE_INSTALL_SCRIPT")) { diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 21700e9..9a89f0f 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -266,6 +266,7 @@ public: const char* Defines; const char* RuleLauncher; const char* DependencyFile; + const char* FilterPrefix; }; /** Set whether to treat conversions to SHELL as a link script shell. */ diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index f1d5e2c..cd12c9d 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -53,6 +53,8 @@ void cmLocalNinjaGenerator::Generate() { this->WriteBuildFileTop(); + this->WritePools(this->GetRulesFileStream()); + const std::string showIncludesPrefix = this->GetMakefile() ->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX"); if (!showIncludesPrefix.empty()) @@ -64,18 +66,24 @@ void cmLocalNinjaGenerator::Generate() } } - cmTargets& targets = this->GetMakefile()->GetTargets(); - for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t) + cmGeneratorTargetsType targets = this->GetMakefile()->GetGeneratorTargets(); + for(cmGeneratorTargetsType::iterator t = targets.begin(); + t != targets.end(); ++t) { - cmNinjaTargetGenerator* tg = cmNinjaTargetGenerator::New(&t->second); + if (t->second->Target->GetType() == cmTarget::INTERFACE_LIBRARY + || t->second->Target->IsImported()) + { + continue; + } + cmNinjaTargetGenerator* tg = cmNinjaTargetGenerator::New(t->second); if(tg) { tg->Generate(); // Add the target to "all" if required. if (!this->GetGlobalNinjaGenerator()->IsExcluded( this->GetGlobalNinjaGenerator()->GetLocalGenerators()[0], - t->second)) - this->GetGlobalNinjaGenerator()->AddDependencyToAll(&t->second); + *t->second->Target)) + this->GetGlobalNinjaGenerator()->AddDependencyToAll(t->second->Target); delete tg; } } @@ -195,6 +203,39 @@ void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os) cmGlobalNinjaGenerator::WriteDivider(os); } +void cmLocalNinjaGenerator::WritePools(std::ostream& os) +{ + cmGlobalNinjaGenerator::WriteDivider(os); + + const char* jobpools = this->GetCMakeInstance() + ->GetProperty("JOB_POOLS", cmProperty::GLOBAL); + if (jobpools) + { + cmGlobalNinjaGenerator::WriteComment(os, + "Pools defined by global property JOB_POOLS"); + std::vector<std::string> pools; + cmSystemTools::ExpandListArgument(jobpools, pools); + for (size_t i = 0; i < pools.size(); ++i) + { + const std::string pool = pools[i]; + const std::string::size_type eq = pool.find("="); + unsigned int jobs; + if (eq != std::string::npos && + sscanf(pool.c_str() + eq, "=%u", &jobs) == 1) + { + os << "pool " << pool.substr(0, eq) << std::endl; + os << " depth = " << jobs << std::endl; + os << std::endl; + } + else + { + cmSystemTools::Error("Invalid pool defined by property 'JOB_POOLS': ", + pool.c_str()); + } + } + } +} + void cmLocalNinjaGenerator::WriteNinjaFilesInclusion(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); @@ -287,16 +328,32 @@ std::string cmLocalNinjaGenerator::BuildCommandLine( cmOStringStream cmd; for (std::vector<std::string>::const_iterator li = cmdLines.begin(); - li != cmdLines.end(); ++li) { - if (li != cmdLines.begin()) { - cmd << " && "; + li != cmdLines.end(); ++li) #ifdef _WIN32 - } else if (cmdLines.size() > 1) { - cmd << "cmd.exe /c "; -#endif + { + if (li != cmdLines.begin()) + { + cmd << " && "; + } + else if (cmdLines.size() > 1) + { + cmd << "cmd.exe /C \""; + } + cmd << *li; + } + if (cmdLines.size() > 1) + { + cmd << "\""; } +#else + { + if (li != cmdLines.begin()) + { + cmd << " && "; + } cmd << *li; - } + } +#endif return cmd.str(); } diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 8eb63c5..ea854c6 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -112,6 +112,7 @@ private: void WriteProjectHeader(std::ostream& os); void WriteNinjaFilesInclusion(std::ostream& os); void WriteProcessedMakefile(std::ostream& os); + void WritePools(std::ostream& os); void SetConfigName(); diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 8ed8d0a..6ca386c 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -145,13 +145,19 @@ void cmLocalUnixMakefileGenerator3::Generate() this->Makefile->IsOn("CMAKE_SKIP_ASSEMBLY_SOURCE_RULES"); // Generate the rule files for each target. - cmTargets& targets = this->Makefile->GetTargets(); + cmGeneratorTargetsType targets = this->Makefile->GetGeneratorTargets(); cmGlobalUnixMakefileGenerator3* gg = static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator); - for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t) + for(cmGeneratorTargetsType::iterator t = targets.begin(); + t != targets.end(); ++t) { + if (t->second->Target->GetType() == cmTarget::INTERFACE_LIBRARY + || t->second->Target->IsImported()) + { + continue; + } cmsys::auto_ptr<cmMakefileTargetGenerator> tg( - cmMakefileTargetGenerator::New(&(t->second))); + cmMakefileTargetGenerator::New(t->second)); if (tg.get()) { tg->WriteRuleFiles(); @@ -372,22 +378,28 @@ void cmLocalUnixMakefileGenerator3 // for each target we just provide a rule to cd up to the top and do a make // on the target - cmTargets& targets = this->Makefile->GetTargets(); + cmGeneratorTargetsType targets = this->Makefile->GetGeneratorTargets(); std::string localName; - for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t) - { - if((t->second.GetType() == cmTarget::EXECUTABLE) || - (t->second.GetType() == cmTarget::STATIC_LIBRARY) || - (t->second.GetType() == cmTarget::SHARED_LIBRARY) || - (t->second.GetType() == cmTarget::MODULE_LIBRARY) || - (t->second.GetType() == cmTarget::OBJECT_LIBRARY) || - (t->second.GetType() == cmTarget::INTERFACE_LIBRARY) || - (t->second.GetType() == cmTarget::UTILITY)) + for(cmGeneratorTargetsType::iterator t = targets.begin(); + t != targets.end(); ++t) + { + if((t->second->GetType() == cmTarget::EXECUTABLE) || + (t->second->GetType() == cmTarget::STATIC_LIBRARY) || + (t->second->GetType() == cmTarget::SHARED_LIBRARY) || + (t->second->GetType() == cmTarget::MODULE_LIBRARY) || + (t->second->GetType() == cmTarget::OBJECT_LIBRARY) || + (t->second->GetType() == cmTarget::INTERFACE_LIBRARY) || + (t->second->GetType() == cmTarget::UTILITY)) { - emitted.insert(t->second.GetName()); + if (t->second->Target->IsImported()) + { + continue; + } + + emitted.insert(t->second->GetName()); // for subdirs add a rule to build this specific target by name. - localName = this->GetRelativeTargetDirectory(t->second); + localName = this->GetRelativeTargetDirectory(*t->second->Target); localName += "/rule"; commands.clear(); depends.clear(); @@ -404,22 +416,23 @@ void cmLocalUnixMakefileGenerator3 localName.c_str(), depends, commands, true); // Add a target with the canonical name (no prefix, suffix or path). - if(localName != t->second.GetName()) + if(localName != t->second->GetName()) { commands.clear(); depends.push_back(localName); this->WriteMakeRule(ruleFileStream, "Convenience name for target.", - t->second.GetName(), depends, commands, true); + t->second->GetName(), depends, commands, true); } // Add a fast rule to build the target - std::string makefileName = this->GetRelativeTargetDirectory(t->second); + std::string makefileName = + this->GetRelativeTargetDirectory(*t->second->Target); makefileName += "/build.make"; // make sure the makefile name is suitable for a makefile std::string makeTargetName = - this->GetRelativeTargetDirectory(t->second); + this->GetRelativeTargetDirectory(*t->second->Target); makeTargetName += "/build"; - localName = t->second.GetName(); + localName = t->second->GetName(); localName += "/fast"; depends.clear(); commands.clear(); @@ -433,11 +446,12 @@ void cmLocalUnixMakefileGenerator3 // Add a local name for the rule to relink the target before // installation. - if(t->second.NeedRelinkBeforeInstall(this->ConfigurationName.c_str())) + if(t->second->Target + ->NeedRelinkBeforeInstall(this->ConfigurationName.c_str())) { - makeTargetName = this->GetRelativeTargetDirectory(t->second); + makeTargetName = this->GetRelativeTargetDirectory(*t->second->Target); makeTargetName += "/preinstall"; - localName = t->second.GetName(); + localName = t->second->GetName(); localName += "/preinstall"; depends.clear(); commands.clear(); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 30c3d73..2fd1016 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -482,6 +482,8 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] = {"AssemblerListingLocation", "Fa", "ASM List Location", "", cmVS7FlagTable::UserValue}, + {"ProgramDataBaseFileName", "Fd", "Program Database File Name", "", + cmVS7FlagTable::UserValue}, // boolean flags {"BufferSecurityCheck", "GS", "Buffer security check", "TRUE", 0}, diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index ac8381c..30a1557 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -868,6 +868,10 @@ void cmMakefile::ConfigureFinalPass() for (cmTargets::iterator l = this->Targets.begin(); l != this->Targets.end(); l++) { + if (l->second.GetType() == cmTarget::INTERFACE_LIBRARY) + { + continue; + } l->second.FinishConfigure(); } } @@ -884,34 +888,61 @@ cmMakefile::AddCustomCommandToTarget(const char* target, { // Find the target to which to add the custom command. cmTargets::iterator ti = this->Targets.find(target); - if(ti != this->Targets.end()) + + if(ti == this->Targets.end()) { - if(ti->second.GetType() == cmTarget::OBJECT_LIBRARY) + cmake::MessageType messageType = cmake::AUTHOR_WARNING; + bool issueMessage = false; + switch(this->GetPolicyStatus(cmPolicies::CMP0040)) { - cmOStringStream e; - e << "Target \"" << target << "\" is an OBJECT library " - "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands."; - this->IssueMessage(cmake::FATAL_ERROR, e.str()); - return; + case cmPolicies::WARN: + issueMessage = true; + case cmPolicies::OLD: + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + issueMessage = true; + messageType = cmake::FATAL_ERROR; } - // Add the command to the appropriate build step for the target. - std::vector<std::string> no_output; - cmCustomCommand cc(this, no_output, depends, - commandLines, comment, workingDir); - cc.SetEscapeOldStyle(escapeOldStyle); - cc.SetEscapeAllowMakeVars(true); - switch(type) + + if(issueMessage) { - case cmTarget::PRE_BUILD: - ti->second.GetPreBuildCommands().push_back(cc); - break; - case cmTarget::PRE_LINK: - ti->second.GetPreLinkCommands().push_back(cc); - break; - case cmTarget::POST_BUILD: - ti->second.GetPostBuildCommands().push_back(cc); - break; + cmOStringStream e; + e << (this->GetPolicies() + ->GetPolicyWarning(cmPolicies::CMP0040)) << "\n"; + e << "The target name \"" << target << "\" is unknown in this context."; + IssueMessage(messageType, e.str().c_str()); } + + return; + } + + if(ti->second.GetType() == cmTarget::OBJECT_LIBRARY) + { + cmOStringStream e; + e << "Target \"" << target << "\" is an OBJECT library " + "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands."; + this->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + // Add the command to the appropriate build step for the target. + std::vector<std::string> no_output; + cmCustomCommand cc(this, no_output, depends, + commandLines, comment, workingDir); + cc.SetEscapeOldStyle(escapeOldStyle); + cc.SetEscapeAllowMakeVars(true); + switch(type) + { + case cmTarget::PRE_BUILD: + ti->second.AddPreBuildCommand(cc); + break; + case cmTarget::PRE_LINK: + ti->second.AddPreLinkCommand(cc); + break; + case cmTarget::POST_BUILD: + ti->second.AddPostBuildCommand(cc); + break; } } @@ -2229,6 +2260,10 @@ void cmMakefile::ExpandVariablesCMP0019() l != this->Targets.end(); ++l) { cmTarget &t = l->second; + if (t.GetType() == cmTarget::INTERFACE_LIBRARY) + { + continue; + } includeDirs = t.GetProperty("INCLUDE_DIRECTORIES"); if(mightExpandVariablesCMP0019(includeDirs)) { @@ -3822,21 +3857,19 @@ const char* cmMakefile::GetFeature(const char* feature, const char* config) return 0; } -cmTarget* cmMakefile::FindTarget(const char* name, bool excludeAliases) +cmTarget* cmMakefile::FindTarget(const char* name, bool excludeAliases) const { if (!excludeAliases) { - std::map<std::string, cmTarget*>::iterator i + std::map<std::string, cmTarget*>::const_iterator i = this->AliasTargets.find(name); if (i != this->AliasTargets.end()) { return i->second; } } - cmTargets& tgts = this->GetTargets(); - - cmTargets::iterator i = tgts.find ( name ); - if ( i != tgts.end() ) + cmTargets::iterator i = this->Targets.find( name ); + if ( i != this->Targets.end() ) { return &i->second; } @@ -4061,8 +4094,11 @@ bool cmMakefile::IsAlias(const char *name) //---------------------------------------------------------------------------- cmGeneratorTarget* cmMakefile::FindGeneratorTargetToUse(const char* name) { - cmTarget *t = this->FindTargetToUse(name); - return this->LocalGenerator->GetGlobalGenerator()->GetGeneratorTarget(t); + if (cmTarget *t = this->FindTargetToUse(name)) + { + return this->LocalGenerator->GetGlobalGenerator()->GetGeneratorTarget(t); + } + return 0; } //---------------------------------------------------------------------------- diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 76958ca..44aaa66 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -533,7 +533,7 @@ public: this->GeneratorTargets = targets; } - cmTarget* FindTarget(const char* name, bool excludeAliases = false); + cmTarget* FindTarget(const char* name, bool excludeAliases = false) const; /** Find a target to use in place of the given name. The target returned may be imported or built within the project. */ @@ -902,7 +902,7 @@ protected: std::string ProjectName; // project name // libraries, classes, and executables - cmTargets Targets; + mutable cmTargets Targets; std::map<std::string, cmTarget*> AliasTargets; cmGeneratorTargetsType GeneratorTargets; std::vector<cmSourceFile*> SourceFiles; diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index e4219a9..69fe444 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -21,15 +21,15 @@ //---------------------------------------------------------------------------- cmMakefileExecutableTargetGenerator -::cmMakefileExecutableTargetGenerator(cmTarget* target): - cmMakefileTargetGenerator(target) +::cmMakefileExecutableTargetGenerator(cmGeneratorTarget* target): + cmMakefileTargetGenerator(target->Target) { this->CustomCommandDriver = OnDepends; this->Target->GetExecutableNames( this->TargetNameOut, this->TargetNameReal, this->TargetNameImport, this->TargetNamePDB, this->ConfigName); - this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target, + this->OSXBundleGenerator = new cmOSXBundleGenerator(target, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } diff --git a/Source/cmMakefileExecutableTargetGenerator.h b/Source/cmMakefileExecutableTargetGenerator.h index 3b18166..940226b 100644 --- a/Source/cmMakefileExecutableTargetGenerator.h +++ b/Source/cmMakefileExecutableTargetGenerator.h @@ -17,7 +17,7 @@ class cmMakefileExecutableTargetGenerator: public cmMakefileTargetGenerator { public: - cmMakefileExecutableTargetGenerator(cmTarget* target); + cmMakefileExecutableTargetGenerator(cmGeneratorTarget* target); virtual ~cmMakefileExecutableTargetGenerator(); /* the main entry point for this class. Writes the Makefiles associated diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 29365a3..35818ee 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -21,15 +21,18 @@ //---------------------------------------------------------------------------- cmMakefileLibraryTargetGenerator -::cmMakefileLibraryTargetGenerator(cmTarget* target): - cmMakefileTargetGenerator(target) +::cmMakefileLibraryTargetGenerator(cmGeneratorTarget* target): + cmMakefileTargetGenerator(target->Target) { this->CustomCommandDriver = OnDepends; - this->Target->GetLibraryNames( - this->TargetNameOut, this->TargetNameSO, this->TargetNameReal, - this->TargetNameImport, this->TargetNamePDB, this->ConfigName); + if (this->Target->GetType() != cmTarget::INTERFACE_LIBRARY) + { + this->Target->GetLibraryNames( + this->TargetNameOut, this->TargetNameSO, this->TargetNameReal, + this->TargetNameImport, this->TargetNamePDB, this->ConfigName); + } - this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target, + this->OSXBundleGenerator = new cmOSXBundleGenerator(target, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } diff --git a/Source/cmMakefileLibraryTargetGenerator.h b/Source/cmMakefileLibraryTargetGenerator.h index 07f828b..1487b56 100644 --- a/Source/cmMakefileLibraryTargetGenerator.h +++ b/Source/cmMakefileLibraryTargetGenerator.h @@ -18,7 +18,7 @@ class cmMakefileLibraryTargetGenerator: public cmMakefileTargetGenerator { public: - cmMakefileLibraryTargetGenerator(cmTarget* target); + cmMakefileLibraryTargetGenerator(cmGeneratorTarget* target); virtual ~cmMakefileLibraryTargetGenerator(); /* the main entry point for this class. Writes the Makefiles associated diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 6770e10..2063a24 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -27,6 +27,7 @@ #include "cmMakefileLibraryTargetGenerator.h" #include "cmMakefileUtilityTargetGenerator.h" +#include <ctype.h> cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmTarget* target) : OSXBundleGenerator(0) @@ -62,7 +63,7 @@ cmMakefileTargetGenerator::~cmMakefileTargetGenerator() } cmMakefileTargetGenerator * -cmMakefileTargetGenerator::New(cmTarget *tgt) +cmMakefileTargetGenerator::New(cmGeneratorTarget *tgt) { cmMakefileTargetGenerator *result = 0; @@ -1694,10 +1695,42 @@ void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar, this->Makefile->GetSafeDefinition(removeFlags.c_str()); std::vector<std::string> removeList; cmSystemTools::ExpandListArgument(removeflags, removeList); + for(std::vector<std::string>::iterator i = removeList.begin(); i != removeList.end(); ++i) { - cmSystemTools::ReplaceString(linkFlags, i->c_str(), ""); + std::string tmp; + std::string::size_type lastPosition = 0; + + for(;;) + { + std::string::size_type position = linkFlags.find(*i, lastPosition); + + if(position == std::string::npos) + { + tmp += linkFlags.substr(lastPosition); + break; + } + else + { + std::string::size_type prefixLength = position - lastPosition; + tmp += linkFlags.substr(lastPosition, prefixLength); + lastPosition = position + i->length(); + + bool validFlagStart = position == 0 || + isspace(linkFlags[position - 1]); + + bool validFlagEnd = lastPosition == linkFlags.size() || + isspace(linkFlags[lastPosition]); + + if(!validFlagStart || !validFlagEnd) + { + tmp += *i; + } + } + } + + linkFlags = tmp; } } diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index ec2af1c..4f8fafa 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -38,7 +38,7 @@ public: virtual ~cmMakefileTargetGenerator(); // construct using this factory call - static cmMakefileTargetGenerator *New(cmTarget *tgt); + static cmMakefileTargetGenerator *New(cmGeneratorTarget *tgt); /* the main entry point for this class. Writes the Makefiles associated with this target */ diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 1fa4e95..7751ad9 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -20,11 +20,11 @@ //---------------------------------------------------------------------------- cmMakefileUtilityTargetGenerator -::cmMakefileUtilityTargetGenerator(cmTarget* target): - cmMakefileTargetGenerator(target) +::cmMakefileUtilityTargetGenerator(cmGeneratorTarget* target): + cmMakefileTargetGenerator(target->Target) { this->CustomCommandDriver = OnUtility; - this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target, + this->OSXBundleGenerator = new cmOSXBundleGenerator(target, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } diff --git a/Source/cmMakefileUtilityTargetGenerator.h b/Source/cmMakefileUtilityTargetGenerator.h index fc47b38..8f99300 100644 --- a/Source/cmMakefileUtilityTargetGenerator.h +++ b/Source/cmMakefileUtilityTargetGenerator.h @@ -18,7 +18,7 @@ class cmMakefileUtilityTargetGenerator: public cmMakefileTargetGenerator { public: - cmMakefileUtilityTargetGenerator(cmTarget* target); + cmMakefileUtilityTargetGenerator(cmGeneratorTarget* target); virtual ~cmMakefileUtilityTargetGenerator(); /* the main entry point for this class. Writes the Makefiles associated diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 015654b..73ba815 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -17,6 +17,7 @@ #include "cmGeneratedFileStream.h" #include "cmMakefile.h" #include "cmOSXBundleGenerator.h" +#include "cmGeneratorTarget.h" #include <assert.h> #include <algorithm> @@ -27,8 +28,8 @@ cmNinjaNormalTargetGenerator:: -cmNinjaNormalTargetGenerator(cmTarget* target) - : cmNinjaTargetGenerator(target) +cmNinjaNormalTargetGenerator(cmGeneratorTarget* target) + : cmNinjaTargetGenerator(target->Target) , TargetNameOut() , TargetNameSO() , TargetNameReal() @@ -36,15 +37,16 @@ cmNinjaNormalTargetGenerator(cmTarget* target) , TargetNamePDB() , TargetLinkLanguage(0) { - this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName()); + this->TargetLinkLanguage = target->Target + ->GetLinkerLanguage(this->GetConfigName()); if (target->GetType() == cmTarget::EXECUTABLE) - target->GetExecutableNames(this->TargetNameOut, + target->Target->GetExecutableNames(this->TargetNameOut, this->TargetNameReal, this->TargetNameImport, this->TargetNamePDB, GetLocalGenerator()->GetConfigName()); else - target->GetLibraryNames(this->TargetNameOut, + target->Target->GetLibraryNames(this->TargetNameOut, this->TargetNameSO, this->TargetNameReal, this->TargetNameImport, @@ -55,7 +57,7 @@ cmNinjaNormalTargetGenerator(cmTarget* target) { // on Windows the output dir is already needed at compile time // ensure the directory exists (OutDir test) - EnsureDirectoryExists(target->GetDirectory(this->GetConfigName())); + EnsureDirectoryExists(target->Target->GetDirectory(this->GetConfigName())); } this->OSXBundleGenerator = new cmOSXBundleGenerator(target, @@ -462,6 +464,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() linkPath, this->GetGeneratorTarget()); + this->addPoolNinjaVariable("JOB_POOL_LINK", this->GetTarget(), vars); + this->AddModuleDefinitionFlag(vars["LINK_FLAGS"]); vars["LINK_FLAGS"] = cmGlobalNinjaGenerator ::EncodeLiteral(vars["LINK_FLAGS"]); @@ -534,7 +538,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/'); } - std::vector<cmCustomCommand> *cmdLists[3] = { + const std::vector<cmCustomCommand> *cmdLists[3] = { &this->GetTarget()->GetPreBuildCommands(), &this->GetTarget()->GetPreLinkCommands(), &this->GetTarget()->GetPostBuildCommands() diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h index 284804b..c7a089c 100644 --- a/Source/cmNinjaNormalTargetGenerator.h +++ b/Source/cmNinjaNormalTargetGenerator.h @@ -21,11 +21,12 @@ class cmSourceFile; class cmOSXBundleGenerator; +class cmGeneratorTarget; class cmNinjaNormalTargetGenerator : public cmNinjaTargetGenerator { public: - cmNinjaNormalTargetGenerator(cmTarget* target); + cmNinjaNormalTargetGenerator(cmGeneratorTarget* target); ~cmNinjaNormalTargetGenerator(); void Generate(); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 26eadbe..e3c058f 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -26,7 +26,7 @@ #include <algorithm> cmNinjaTargetGenerator * -cmNinjaTargetGenerator::New(cmTarget* target) +cmNinjaTargetGenerator::New(cmGeneratorTarget* target) { switch (target->GetType()) { @@ -44,7 +44,7 @@ cmNinjaTargetGenerator::New(cmTarget* target) // We only want to process global targets that live in the home // (i.e. top-level) directory. CMake creates copies of these targets // in every directory, which we don't need. - cmMakefile *mf = target->GetMakefile(); + cmMakefile *mf = target->Target->GetMakefile(); if (strcmp(mf->GetStartDirectory(), mf->GetHomeDirectory()) == 0) return new cmNinjaUtilityTargetGenerator(target); // else fallthrough @@ -360,10 +360,11 @@ cmNinjaTargetGenerator cmMakefile* mf = this->GetMakefile(); - const bool usingMSVC = std::string("MSVC") == - (mf->GetDefinition("CMAKE_C_COMPILER_ID") ? - mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") : - mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID")); + const std::string cId = mf->GetDefinition("CMAKE_C_COMPILER_ID") + ? mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") + : mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID"); + + const bool usingMSVC = (cId == "MSVC" || cId == "Intel"); // Tell ninja dependency format so all deps can be loaded into a database std::string deptype; @@ -572,6 +573,8 @@ cmNinjaTargetGenerator ConvertToNinjaPath(objectDir.c_str()).c_str(), cmLocalGenerator::SHELL); + this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetTarget(), vars); + this->SetMsvcTargetPdbVariable(vars); if(this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS")) @@ -725,3 +728,14 @@ cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( // Add as a dependency of all target so that it gets called. this->Generator->GetGlobalGenerator()->AddDependencyToAll(output); } + +void cmNinjaTargetGenerator::addPoolNinjaVariable(const char* pool_property, + cmTarget* target, + cmNinjaVars& vars) +{ + const char* pool = target->GetProperty(pool_property); + if (pool) + { + vars["pool"] = pool; + } +} diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 1cf811a..2ce1ed7 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -30,7 +30,7 @@ class cmNinjaTargetGenerator { public: /// Create a cmNinjaTargetGenerator according to the @a target's type. - static cmNinjaTargetGenerator* New(cmTarget* target); + static cmNinjaTargetGenerator* New(cmGeneratorTarget* target); /// Build a NinjaTargetGenerator. cmNinjaTargetGenerator(cmTarget* target); @@ -136,12 +136,15 @@ protected: }; friend struct MacOSXContentGeneratorType; -protected: + MacOSXContentGeneratorType* MacOSXContentGenerator; // Properly initialized by sub-classes. cmOSXBundleGenerator* OSXBundleGenerator; std::set<cmStdString> MacContentFolders; + void addPoolNinjaVariable(const char* pool_property, + cmTarget* target, + cmNinjaVars& vars); private: cmTarget* Target; diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 755ce6e..8556565 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -18,8 +18,9 @@ #include "cmSourceFile.h" #include "cmTarget.h" -cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(cmTarget *target) - : cmNinjaTargetGenerator(target) {} +cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator( + cmGeneratorTarget *target) + : cmNinjaTargetGenerator(target->Target) {} cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() {} diff --git a/Source/cmNinjaUtilityTargetGenerator.h b/Source/cmNinjaUtilityTargetGenerator.h index 8b82ce4..add0291 100644 --- a/Source/cmNinjaUtilityTargetGenerator.h +++ b/Source/cmNinjaUtilityTargetGenerator.h @@ -21,7 +21,7 @@ class cmSourceFile; class cmNinjaUtilityTargetGenerator : public cmNinjaTargetGenerator { public: - cmNinjaUtilityTargetGenerator(cmTarget* target); + cmNinjaUtilityTargetGenerator(cmGeneratorTarget* target); ~cmNinjaUtilityTargetGenerator(); void Generate(); diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index a475c7c..9a340dc 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -18,10 +18,10 @@ //---------------------------------------------------------------------------- cmOSXBundleGenerator:: -cmOSXBundleGenerator(cmTarget* target, +cmOSXBundleGenerator(cmGeneratorTarget* target, const char* configName) - : Target(target) - , Makefile(target->GetMakefile()) + : Target(target->Target) + , Makefile(target->Target->GetMakefile()) , LocalGenerator(Makefile->GetLocalGenerator()) , ConfigName(configName) , MacContentFolders(0) diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h index ec82b9a..29b7611 100644 --- a/Source/cmOSXBundleGenerator.h +++ b/Source/cmOSXBundleGenerator.h @@ -21,11 +21,12 @@ class cmTarget; class cmMakefile; class cmLocalGenerator; +class cmGeneratorTarget; class cmOSXBundleGenerator { public: - cmOSXBundleGenerator(cmTarget* target, + cmOSXBundleGenerator(cmGeneratorTarget* target, const char* configName); // create an app bundle at a given root, and return diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index 16b2bea..5de36ed 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -32,7 +32,7 @@ void cmLBDepend::DependWalk(cmDependInformation* info) std::string line; while(cmSystemTools::GetLineFromStream(fin, line)) { - if(!strncmp(line.c_str(), "#include", 8)) + if(cmHasLiteralPrefix(line.c_str(), "#include")) { // if it is an include line then create a string class std::string currentline = line; diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 7b80d14..0b3018e 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -289,7 +289,7 @@ cmPolicies::cmPolicies() this->DefinePolicy( CMP0037, "CMP0037", - "Target names should match a validity pattern.", + "Target names should not be reserved and should match a validity pattern.", 3,0,0,0, cmPolicies::WARN); this->DefinePolicy( @@ -301,6 +301,16 @@ cmPolicies::cmPolicies() CMP0039, "CMP0039", "Utility targets may not have link dependencies.", 3,0,0,0, cmPolicies::WARN); + + this->DefinePolicy( + CMP0040, "CMP0040", + "The target in the TARGET signature of add_custom_command() must exist.", + 3,0,0,0, cmPolicies::WARN); + + this->DefinePolicy( + CMP0041, "CMP0041", + "Error on relative include with generator expression.", + 3,0,0,0, cmPolicies::WARN); } cmPolicies::~cmPolicies() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index fc239d4..245ec4b 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -88,9 +88,13 @@ public: CMP0034, ///< Disallow command: utility_source CMP0035, ///< Disallow command: variable_requires CMP0036, ///< Disallow command: build_name - CMP0037, ///< Target names should match a validity pattern. + CMP0037, ///< Target names should not be reserved and + /// should match a validity pattern. CMP0038, ///< Targets may not link directly to themselves CMP0039, ///< Utility targets may not have link dependencies + CMP0040, ///< The target in the TARGET signature of + /// add_custom_command() must exist. + CMP0041, ///< Error on relative include with generator expression /** \brief Always the last entry. * diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 36cb368..835e3b4 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -204,6 +204,11 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target) "", makefile->GetCurrentOutputDirectory()); std::vector<std::string> depends; + if (const char *autogenDepends = + target->GetProperty("AUTOGEN_TARGET_DEPENDS")) + { + cmSystemTools::ExpandListArgument(autogenDepends, depends); + } std::vector<std::string> toolNames; if (target->GetPropertyAsBool("AUTOMOC")) { @@ -257,7 +262,7 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target) workingDirectory.c_str()); cc.SetEscapeOldStyle(false); cc.SetEscapeAllowMakeVars(true); - target->GetPreBuildCommands().push_back(cc); + target->AddPreBuildCommand(cc); } else #endif @@ -360,6 +365,7 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget* target) std::map<std::string, std::string> configIncludes; std::map<std::string, std::string> configDefines; + std::map<std::string, std::string> configUicOptions; if (target->GetPropertyAsBool("AUTOMOC")) { @@ -368,7 +374,7 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget* target) } if (target->GetPropertyAsBool("AUTOUIC")) { - this->SetupAutoUicTarget(target); + this->SetupAutoUicTarget(target, configUicOptions); } if (target->GetPropertyAsBool("AUTORCC")) { @@ -383,7 +389,9 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget* target) makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), false, true, false); - if (!configDefines.empty() || !configIncludes.empty()) + if (!configDefines.empty() + || !configIncludes.empty() + || !configUicOptions.empty()) { std::ofstream infoFile(outputFile.c_str(), std::ios::app); if ( !infoFile ) @@ -414,6 +422,16 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget* target) " " << it->second << ")\n"; } } + if (!configUicOptions.empty()) + { + for (std::map<std::string, std::string>::iterator + it = configUicOptions.begin(), end = configUicOptions.end(); + it != end; ++it) + { + infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << + " " << it->second << ")\n"; + } + } } } @@ -508,7 +526,7 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget* target, config_moc_compile_defs); if (config_moc_incs != _moc_incs) { - configIncludes["_moc_incs_" + *li] = + configIncludes[*li] = cmLocalGenerator::EscapeForCMake(config_moc_incs.c_str()); if(_moc_incs.empty()) { @@ -517,7 +535,7 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget* target, } if (config_moc_compile_defs != _moc_compile_defs) { - configDefines["_moc_compile_defs_" + *li] = + configDefines[*li] = cmLocalGenerator::EscapeForCMake(config_moc_compile_defs.c_str()); if(_moc_compile_defs.empty()) { @@ -560,6 +578,7 @@ void cmQtAutoGenerators::MergeUicOptions(std::vector<std::string> &opts, "translate", "postfix", "generator", + "include", // Since Qt 5.3 "g" }; std::vector<std::string> extraOpts; @@ -595,7 +614,25 @@ void cmQtAutoGenerators::MergeUicOptions(std::vector<std::string> &opts, opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); } -void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget* target) +static void GetUicOpts(cmTarget *target, const char * config, + std::string &optString) +{ + std::vector<std::string> opts; + target->GetAutoUicOptions(opts, config); + + const char* sep = ""; + for(std::vector<std::string>::const_iterator optIt = opts.begin(); + optIt != opts.end(); + ++optIt) + { + optString += sep; + sep = ";"; + optString += *optIt; + } +} + +void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget* target, + std::map<std::string, std::string> &configUicOptions) { cmMakefile *makefile = target->GetMakefile(); @@ -644,10 +681,30 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget* target) const char *qtVersion = makefile->GetDefinition("_target_qt_version"); - if (const char* opts = target->GetProperty("AUTOUIC_OPTIONS")) + std::string _uic_opts; + std::vector<std::string> configs; + const char *config = makefile->GetConfigurations(configs); + GetUicOpts(target, config, _uic_opts); + + if (!_uic_opts.empty()) { - makefile->AddDefinition("_uic_target_options", - cmLocalGenerator::EscapeForCMake(opts).c_str()); + _uic_opts = cmLocalGenerator::EscapeForCMake(_uic_opts.c_str()); + makefile->AddDefinition("_uic_target_options", _uic_opts.c_str()); + } + for (std::vector<std::string>::const_iterator li = configs.begin(); + li != configs.end(); ++li) + { + std::string config_uic_opts; + GetUicOpts(target, li->c_str(), config_uic_opts); + if (config_uic_opts != _uic_opts) + { + configUicOptions[*li] = + cmLocalGenerator::EscapeForCMake(config_uic_opts.c_str()); + if(_uic_opts.empty()) + { + _uic_opts = config_uic_opts; + } + } } for(std::vector<cmSourceFile*>::const_iterator fileIt = @@ -966,9 +1023,19 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(cmMakefile* makefile, { const char *uicOptionsFiles = makefile->GetSafeDefinition("AM_UIC_OPTIONS_FILES"); + std::string uicOptionsPropOrig = "AM_UIC_TARGET_OPTIONS"; + std::string uicOptionsProp = uicOptionsPropOrig; + if(config) + { + uicOptionsProp += "_"; + uicOptionsProp += config; + } const char *uicTargetOptions - = makefile->GetSafeDefinition("AM_UIC_TARGET_OPTIONS"); - cmSystemTools::ExpandListArgument(uicTargetOptions, this->UicTargetOptions); + = makefile->GetSafeDefinition(uicOptionsProp.c_str()); + cmSystemTools::ExpandListArgument( + uicTargetOptions ? uicTargetOptions + : makefile->GetSafeDefinition(includesPropOrig.c_str()), + this->UicTargetOptions); const char *uicOptionsOptions = makefile->GetSafeDefinition("AM_UIC_OPTIONS_OPTIONS"); std::vector<std::string> uicFilesVec; diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 116f174..e877f7d 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -31,7 +31,8 @@ private: const std::string &autogenTargetName, std::map<std::string, std::string> &configIncludes, std::map<std::string, std::string> &configDefines); - void SetupAutoUicTarget(cmTarget* target); + void SetupAutoUicTarget(cmTarget* target, + std::map<std::string, std::string> &configUicOptions); void SetupAutoRccTarget(cmTarget* target); cmGlobalGenerator* CreateGlobalGenerator(cmake* cm, diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx index bb193bf..36363a1 100644 --- a/Source/cmSetCommand.cxx +++ b/Source/cmSetCommand.cxx @@ -23,7 +23,7 @@ bool cmSetCommand // watch for ENV signatures const char* variable = args[0].c_str(); // VAR is always first - if (!strncmp(variable,"ENV{",4) && strlen(variable) > 5) + if (cmHasLiteralPrefix(variable, "ENV{") && strlen(variable) > 5) { // what is the variable name char *varName = new char [strlen(variable)]; diff --git a/Source/cmStandardIncludes.h b/Source/cmStandardIncludes.h index 18d017d..7369fe6 100644 --- a/Source/cmStandardIncludes.h +++ b/Source/cmStandardIncludes.h @@ -377,13 +377,31 @@ static thisClass* SafeDownCast(cmObject *c) \ return 0;\ } +inline bool cmHasLiteralPrefixImpl(const std::string &str1, + const char *str2, + size_t N) +{ + return strncmp(str1.c_str(), str2, N) == 0; +} + +inline bool cmHasLiteralPrefixImpl(const char* str1, + const char *str2, + size_t N) +{ + return strncmp(str1, str2, N) == 0; +} + #if defined(_MSC_VER) && _MSC_VER < 1300 \ - || defined(__GNUC__) && __GNUC__ < 3 + || defined(__GNUC__) && __GNUC__ < 3 \ + || defined(__BORLANDC__) #define cmArrayBegin(a) a #define cmArraySize(a) (sizeof(a)/sizeof(*a)) #define cmArrayEnd(a) a + cmArraySize(a) +#define cmHasLiteralPrefix(STR1, STR2) \ + cmHasLiteralPrefixImpl(STR1, "" STR2 "", sizeof(STR2) - 1) + #else template<typename T, size_t N> @@ -393,6 +411,12 @@ const T* cmArrayEnd(const T (&a)[N]) { return a + N; } template<typename T, size_t N> size_t cmArraySize(const T (&)[N]) { return N; } +template<typename T, size_t N> +bool cmHasLiteralPrefix(T str1, const char (&str2)[N]) +{ + return cmHasLiteralPrefixImpl(str1, str2, N - 1); +} + #endif struct cmStrCmp { @@ -404,6 +428,12 @@ struct cmStrCmp { return strcmp(input, m_test) == 0; } + // For use with binary_search + bool operator()(const char *str1, const char *str2) + { + return strcmp(str1, str2) < 0; + } + private: const char *m_test; }; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index c9905b6..fe68a8a 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -91,8 +91,8 @@ public: } ~cmTargetInternals(); typedef cmTarget::SourceFileFlags SourceFileFlags; - std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap; - bool SourceFileFlagsConstructed; + mutable std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap; + mutable bool SourceFileFlagsConstructed; // The backtrace when the target was created. cmListFileBacktrace Backtrace; @@ -135,6 +135,7 @@ public: }; std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries; std::vector<TargetPropertyEntry*> CompileOptionsEntries; + std::vector<TargetPropertyEntry*> AutoUicOptionsEntries; std::vector<TargetPropertyEntry*> CompileDefinitionsEntries; std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries; @@ -143,11 +144,14 @@ public: mutable std::map<std::string, std::vector<TargetPropertyEntry*> > CachedLinkInterfaceCompileOptionsEntries; mutable std::map<std::string, std::vector<TargetPropertyEntry*> > + CachedLinkInterfaceAutoUicOptionsEntries; + mutable std::map<std::string, std::vector<TargetPropertyEntry*> > CachedLinkInterfaceCompileDefinitionsEntries; 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> CacheLinkInterfaceAutoUicOptionsDone; }; //---------------------------------------------------------------------------- @@ -182,6 +186,7 @@ cmTargetInternals::~cmTargetInternals() { deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries); deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries); + deleteAndClear(this->CachedLinkInterfaceAutoUicOptionsEntries); deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries); } @@ -255,32 +260,34 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->IsApple = this->Makefile->IsOn("APPLE"); // Setup default property values. - this->SetPropertyDefault("INSTALL_NAME_DIR", 0); - this->SetPropertyDefault("INSTALL_RPATH", ""); - this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF"); - this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF"); - this->SetPropertyDefault("BUILD_WITH_INSTALL_RPATH", "OFF"); - this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", 0); - this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0); - this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0); - this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0); - this->SetPropertyDefault("Fortran_FORMAT", 0); - this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0); - this->SetPropertyDefault("GNUtoMS", 0); - this->SetPropertyDefault("OSX_ARCHITECTURES", 0); - this->SetPropertyDefault("AUTOMOC", 0); - this->SetPropertyDefault("AUTOUIC", 0); - this->SetPropertyDefault("AUTORCC", 0); - this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", 0); - this->SetPropertyDefault("AUTOUIC_OPTIONS", 0); - this->SetPropertyDefault("AUTORCC_OPTIONS", 0); - this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", 0); - this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0); - this->SetPropertyDefault("WIN32_EXECUTABLE", 0); - this->SetPropertyDefault("MACOSX_BUNDLE", 0); - this->SetPropertyDefault("MACOSX_RPATH", 0); - this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", 0); - + if (this->GetType() != INTERFACE_LIBRARY) + { + this->SetPropertyDefault("INSTALL_NAME_DIR", 0); + this->SetPropertyDefault("INSTALL_RPATH", ""); + this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF"); + this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF"); + this->SetPropertyDefault("BUILD_WITH_INSTALL_RPATH", "OFF"); + this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", 0); + this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0); + this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0); + this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0); + this->SetPropertyDefault("Fortran_FORMAT", 0); + this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0); + this->SetPropertyDefault("GNUtoMS", 0); + this->SetPropertyDefault("OSX_ARCHITECTURES", 0); + this->SetPropertyDefault("AUTOMOC", 0); + this->SetPropertyDefault("AUTOUIC", 0); + this->SetPropertyDefault("AUTORCC", 0); + this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", 0); + this->SetPropertyDefault("AUTOUIC_OPTIONS", 0); + this->SetPropertyDefault("AUTORCC_OPTIONS", 0); + this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", 0); + this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0); + this->SetPropertyDefault("WIN32_EXECUTABLE", 0); + this->SetPropertyDefault("MACOSX_BUNDLE", 0); + this->SetPropertyDefault("MACOSX_RPATH", 0); + this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", 0); + } // Collect the set of configuration types. std::vector<std::string> configNames; @@ -300,6 +307,11 @@ void cmTarget::SetMakefile(cmMakefile* mf) std::string configUpper = cmSystemTools::UpperCase(*ci); for(const char** p = configProps; *p; ++p) { + if (this->TargetTypeValue == INTERFACE_LIBRARY + && strcmp(*p, "MAP_IMPORTED_CONFIG_") != 0) + { + continue; + } std::string property = *p; property += configUpper; this->SetPropertyDefault(property.c_str(), 0); @@ -311,7 +323,8 @@ void cmTarget::SetMakefile(cmMakefile* mf) // did not support this variable. Projects may still specify the // property directly. TODO: Make this depend on backwards // compatibility setting. - if(this->TargetTypeValue != cmTarget::EXECUTABLE) + if(this->TargetTypeValue != cmTarget::EXECUTABLE + && this->TargetTypeValue != cmTarget::INTERFACE_LIBRARY) { std::string property = cmSystemTools::UpperCase(*ci); property += "_POSTFIX"; @@ -352,16 +365,22 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->InsertCompileOption(*it); } - this->SetPropertyDefault("C_VISIBILITY_PRESET", 0); - this->SetPropertyDefault("CXX_VISIBILITY_PRESET", 0); - this->SetPropertyDefault("VISIBILITY_INLINES_HIDDEN", 0); + if (this->GetType() != INTERFACE_LIBRARY) + { + this->SetPropertyDefault("C_VISIBILITY_PRESET", 0); + this->SetPropertyDefault("CXX_VISIBILITY_PRESET", 0); + this->SetPropertyDefault("VISIBILITY_INLINES_HIDDEN", 0); + } if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY || this->TargetTypeValue == cmTarget::MODULE_LIBRARY) { this->SetProperty("POSITION_INDEPENDENT_CODE", "True"); } - this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0); + if (this->GetType() != INTERFACE_LIBRARY) + { + this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0); + } // Record current policies for later use. #define CAPTURE_TARGET_POLICY(POLICY) \ @@ -379,6 +398,9 @@ void cmTarget::SetMakefile(cmMakefile* mf) // so ensure that the conditions don't lead to nonsense. this->PolicyStatusCMP0022 = cmPolicies::NEW; } + + this->SetPropertyDefault("JOB_POOL_COMPILE", 0); + this->SetPropertyDefault("JOB_POOL_LINK", 0); } //---------------------------------------------------------------------------- @@ -438,7 +460,7 @@ bool cmTarget::IsExecutableWithExports() const } //---------------------------------------------------------------------------- -bool cmTarget::IsLinkable() +bool cmTarget::IsLinkable() const { return (this->GetType() == cmTarget::STATIC_LIBRARY || this->GetType() == cmTarget::SHARED_LIBRARY || @@ -560,7 +582,7 @@ cmSourceFile* cmTarget::AddSource(const char* s) //---------------------------------------------------------------------------- void cmTarget::ProcessSourceExpression(std::string const& expr) { - if(strncmp(expr.c_str(), "$<TARGET_OBJECTS:", 17) == 0 && + if(cmHasLiteralPrefix(expr.c_str(), "$<TARGET_OBJECTS:") && expr[expr.size()-1] == '>') { std::string objLibName = expr.substr(17, expr.size()-18); @@ -577,7 +599,7 @@ void cmTarget::ProcessSourceExpression(std::string const& expr) //---------------------------------------------------------------------------- struct cmTarget::SourceFileFlags -cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) +cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const { struct SourceFileFlags flags; this->ConstructSourceFileFlags(); @@ -591,7 +613,7 @@ cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) } //---------------------------------------------------------------------------- -void cmTarget::ConstructSourceFileFlags() +void cmTarget::ConstructSourceFileFlags() const { if(this->Internal->SourceFileFlagsConstructed) { @@ -769,9 +791,9 @@ void cmTarget::ClearDependencyInformation( cmMakefile& mf, } //---------------------------------------------------------------------------- -bool cmTarget::NameResolvesToFramework(const std::string& libname) +bool cmTarget::NameResolvesToFramework(const std::string& libname) const { - return this->GetMakefile()->GetLocalGenerator()->GetGlobalGenerator()-> + return this->Makefile->GetLocalGenerator()->GetGlobalGenerator()-> NameResolvesToFramework(libname); } @@ -811,7 +833,7 @@ void cmTarget::GetDirectLinkLibraries(const char *config, //---------------------------------------------------------------------------- void cmTarget::GetInterfaceLinkLibraries(const char *config, - std::vector<std::string> &libs, cmTarget *head) + std::vector<std::string> &libs, cmTarget *head) const { const char *prop = this->GetProperty("INTERFACE_LINK_LIBRARIES"); if (prop) @@ -834,7 +856,7 @@ void cmTarget::GetInterfaceLinkLibraries(const char *config, //---------------------------------------------------------------------------- std::string cmTarget::GetDebugGeneratorExpressions(const std::string &value, - cmTarget::LinkLibraryType llt) + cmTarget::LinkLibraryType llt) const { if (llt == GENERAL) { @@ -1370,12 +1392,63 @@ void cmTarget::GatherDependencies( const cmMakefile& mf, } //---------------------------------------------------------------------------- +static bool whiteListedInterfaceProperty(const char *prop) +{ + if(cmHasLiteralPrefix(prop, "INTERFACE_")) + { + 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", + "EXCLUDE_FROM_ALL", + "EXCLUDE_FROM_DEFAULT_BUILD", + "EXPORT_NAME", + "IMPORTED_LINK_INTERFACE_LANGUAGES", + "IMPORTED", + "NAME", + "TYPE", + "VERSION" + }; + + if (std::binary_search(cmArrayBegin(builtIns), + cmArrayEnd(builtIns), + prop, + cmStrCmp(prop))) + { + return true; + } + + if (cmHasLiteralPrefix(prop, "EXCLUDE_FROM_DEFAULT_BUILD_") + || cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LANGUAGES_") + || cmHasLiteralPrefix(prop, "MAP_IMPORTED_CONFIG_")) + { + return true; + } + + return false; +} + +//---------------------------------------------------------------------------- void cmTarget::SetProperty(const char* prop, const char* value) { if (!prop) { return; } + if (this->GetType() == INTERFACE_LIBRARY + && !whiteListedInterfaceProperty(prop)) + { + cmOStringStream e; + e << "INTERFACE_LIBRARY targets may only have whitelisted properties. " + "The property \"" << prop << "\" is not allowed."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return; + } + if (strcmp(prop, "NAME") == 0) { cmOStringStream e; @@ -1405,6 +1478,17 @@ void cmTarget::SetProperty(const char* prop, const char* value) new cmTargetInternals::TargetPropertyEntry(cge)); return; } + if(strcmp(prop,"AUTOUIC_OPTIONS") == 0) + { + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + deleteAndClear(this->Internal->AutoUicOptionsEntries); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); + this->Internal->AutoUicOptionsEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(cge)); + return; + } if(strcmp(prop,"COMPILE_DEFINITIONS") == 0) { cmListFileBacktrace lfbt; @@ -1445,6 +1529,15 @@ void cmTarget::AppendProperty(const char* prop, const char* value, { return; } + if (this->GetType() == INTERFACE_LIBRARY + && !whiteListedInterfaceProperty(prop)) + { + cmOStringStream e; + e << "INTERFACE_LIBRARY targets may only have whitelisted properties. " + "The property \"" << prop << "\" is not allowed."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return; + } if (strcmp(prop, "NAME") == 0) { cmOStringStream e; @@ -1470,6 +1563,15 @@ void cmTarget::AppendProperty(const char* prop, const char* value, new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); return; } + if(strcmp(prop,"AUTOUIC_OPTIONS") == 0) + { + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + this->Internal->AutoUicOptionsEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); + return; + } if(strcmp(prop,"COMPILE_DEFINITIONS") == 0) { cmListFileBacktrace lfbt; @@ -1966,6 +2068,106 @@ static void processCompileOptions(cmTarget const* tgt, } //---------------------------------------------------------------------------- +void cmTarget::GetAutoUicOptions(std::vector<std::string> &result, + const char *config) const +{ + std::set<std::string> uniqueOptions; + cmListFileBacktrace lfbt; + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "AUTOUIC_OPTIONS", 0, 0); + + std::vector<std::string> debugProperties; + const char *debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) + { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugOptions = !this->DebugCompileOptionsDone + && std::find(debugProperties.begin(), + debugProperties.end(), + "AUTOUIC_OPTIONS") + != debugProperties.end(); + + if (this->Makefile->IsGeneratingBuildSystem()) + { + this->DebugAutoUicOptionsDone = true; + } + + processCompileOptions(this, + this->Internal->AutoUicOptionsEntries, + result, + uniqueOptions, + &dagChecker, + config, + debugOptions); + + std::string configString = config ? config : ""; + if (!this->Internal->CacheLinkInterfaceAutoUicOptionsDone[configString]) + { + for (std::vector<cmValueWithOrigin>::const_iterator + it = this->Internal->LinkInterfacePropertyEntries.begin(), + end = this->Internal->LinkInterfacePropertyEntries.end(); + it != end; ++it) + { + if (!cmGeneratorExpression::IsValidTargetName(it->Value) + && cmGeneratorExpression::Find(it->Value) == std::string::npos) + { + continue; + } + { + cmGeneratorExpression ge(lfbt); + 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.c_str())) + { + continue; + } + } + std::string optionGenex = "$<TARGET_PROPERTY:" + + it->Value + ",INTERFACE_AUTOUIC_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); + + this->Internal + ->CachedLinkInterfaceAutoUicOptionsEntries[configString].push_back( + new cmTargetInternals::TargetPropertyEntry(cge, + it->Value)); + } + } + + processCompileOptions(this, + this->Internal->CachedLinkInterfaceAutoUicOptionsEntries[configString], + result, + uniqueOptions, + &dagChecker, + config, + debugOptions); + + if (!this->Makefile->IsGeneratingBuildSystem()) + { + deleteAndClear(this->Internal->CachedLinkInterfaceAutoUicOptionsEntries); + } + else + { + this->Internal->CacheLinkInterfaceAutoUicOptionsDone[configString] = true; + } +} + +//---------------------------------------------------------------------------- void cmTarget::GetCompileOptions(std::vector<std::string> &result, const char *config) const { @@ -2199,11 +2401,11 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list, void cmTarget::MaybeInvalidatePropertyCache(const char* prop) { // Wipe out maps caching information affected by this property. - if(this->IsImported() && strncmp(prop, "IMPORTED", 8) == 0) + if(this->IsImported() && cmHasLiteralPrefix(prop, "IMPORTED")) { this->Internal->ImportInfoMap.clear(); } - if(!this->IsImported() && strncmp(prop, "LINK_INTERFACE_", 15) == 0) + if(!this->IsImported() && cmHasLiteralPrefix(prop, "LINK_INTERFACE_")) { this->ClearLinkMaps(); } @@ -2276,24 +2478,24 @@ static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value, } //---------------------------------------------------------------------------- -void cmTarget::CheckProperty(const char* prop, cmMakefile* context) +void cmTarget::CheckProperty(const char* prop, cmMakefile* context) const { // Certain properties need checking. - if(strncmp(prop, "LINK_INTERFACE_LIBRARIES", 24) == 0) + if(cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES")) { if(const char* value = this->GetProperty(prop)) { cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, false); } } - if(strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES", 33) == 0) + if(cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES")) { if(const char* value = this->GetProperty(prop)) { cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true); } } - if(strncmp(prop, "INTERFACE_LINK_LIBRARIES", 24) == 0) + if(cmHasLiteralPrefix(prop, "INTERFACE_LINK_LIBRARIES")) { if(const char* value = this->GetProperty(prop)) { @@ -2382,7 +2584,7 @@ std::string cmTarget::GetDirectory(const char* config, bool implib) const } //---------------------------------------------------------------------------- -std::string cmTarget::GetPDBDirectory(const char* config) +std::string cmTarget::GetPDBDirectory(const char* config) const { if(OutputInfo const* info = this->GetOutputInfo(config)) { @@ -2453,7 +2655,7 @@ const char* cmTarget::NormalGetLocation(const char* config) const } //---------------------------------------------------------------------------- -void cmTarget::GetTargetVersion(int& major, int& minor) +void cmTarget::GetTargetVersion(int& major, int& minor) const { int patch; this->GetTargetVersion(false, major, minor, patch); @@ -2461,7 +2663,7 @@ void cmTarget::GetTargetVersion(int& major, int& minor) //---------------------------------------------------------------------------- void cmTarget::GetTargetVersion(bool soversion, - int& major, int& minor, int& patch) + int& major, int& minor, int& patch) const { // Set the default values. major = 0; @@ -2489,7 +2691,7 @@ void cmTarget::GetTargetVersion(bool soversion, } //---------------------------------------------------------------------------- -const char* cmTarget::GetFeature(const char* feature, const char* config) +const char* cmTarget::GetFeature(const char* feature, const char* config) const { if(config && *config) { @@ -2560,6 +2762,16 @@ const char *cmTarget::GetProperty(const char* prop, return 0; } + if (this->GetType() == INTERFACE_LIBRARY + && !whiteListedInterfaceProperty(prop)) + { + cmOStringStream e; + e << "INTERFACE_LIBRARY targets may only have whitelisted properties. " + "The property \"" << prop << "\" is not allowed."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return 0; + } + if (strcmp(prop, "NAME") == 0) { return this->GetName(); @@ -2595,7 +2807,7 @@ const char *cmTarget::GetProperty(const char* prop, } // Support "LOCATION_<CONFIG>". - if(strncmp(prop, "LOCATION_", 9) == 0) + if(cmHasLiteralPrefix(prop, "LOCATION_")) { if (!this->HandleLocationPropertyPolicy()) { @@ -2662,6 +2874,24 @@ const char *cmTarget::GetProperty(const char* prop, } return output.c_str(); } + if(strcmp(prop,"AUTOUIC_OPTIONS") == 0) + { + static std::string output; + output = ""; + std::string sep; + typedef cmTargetInternals::TargetPropertyEntry + TargetPropertyEntry; + for (std::vector<TargetPropertyEntry*>::const_iterator + it = this->Internal->AutoUicOptionsEntries.begin(), + end = this->Internal->AutoUicOptionsEntries.end(); + it != end; ++it) + { + output += sep; + output += (*it)->ge->GetInput(); + sep = ";"; + } + return output.c_str(); + } if(strcmp(prop,"COMPILE_DEFINITIONS") == 0) { static std::string output; @@ -3145,7 +3375,7 @@ bool cmTarget::HasMacOSXRpath(const char* config) const } //---------------------------------------------------------------------------- -bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config) +bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config) const { if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY) { @@ -3597,14 +3827,14 @@ void cmTarget::GetExecutableNames(std::string& name, } //---------------------------------------------------------------------------- -bool cmTarget::HasImplibGNUtoMS() +bool cmTarget::HasImplibGNUtoMS() const { return this->HasImportLibrary() && this->GetPropertyAsBool("GNUtoMS"); } //---------------------------------------------------------------------------- bool cmTarget::GetImplibGNUtoMS(std::string const& gnuName, - std::string& out, const char* newExt) + std::string& out, const char* newExt) const { if(this->HasImplibGNUtoMS() && gnuName.size() > 6 && gnuName.substr(gnuName.size()-6) == ".dll.a") @@ -3976,7 +4206,7 @@ bool cmTarget::ComputePDBOutputDir(const char* config, std::string& out) const } //---------------------------------------------------------------------------- -bool cmTarget::UsesDefaultOutputDir(const char* config, bool implib) +bool cmTarget::UsesDefaultOutputDir(const char* config, bool implib) const { std::string dir; return this->ComputeOutputDir(config, implib, dir); @@ -4037,7 +4267,7 @@ std::string cmTarget::GetFrameworkVersion() const } //---------------------------------------------------------------------------- -const char* cmTarget::GetExportMacro() +const char* cmTarget::GetExportMacro() const { // Define the symbol for targets that export symbols. if(this->GetType() == cmTarget::SHARED_LIBRARY || @@ -4433,7 +4663,8 @@ bool isLinkDependentProperty(cmTarget const* tgt, const std::string &p, bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p, const char *config) const { - if (this->TargetTypeValue == OBJECT_LIBRARY) + if (this->TargetTypeValue == OBJECT_LIBRARY + || this->TargetTypeValue == INTERFACE_LIBRARY) { return false; } @@ -4446,7 +4677,8 @@ bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p, bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p, const char *config) const { - if (this->TargetTypeValue == OBJECT_LIBRARY) + if (this->TargetTypeValue == OBJECT_LIBRARY + || this->TargetTypeValue == INTERFACE_LIBRARY) { return false; } @@ -4458,7 +4690,8 @@ bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p, bool cmTarget::IsLinkInterfaceDependentNumberMinProperty(const std::string &p, const char *config) const { - if (this->TargetTypeValue == OBJECT_LIBRARY) + if (this->TargetTypeValue == OBJECT_LIBRARY + || this->TargetTypeValue == INTERFACE_LIBRARY) { return false; } @@ -4470,7 +4703,8 @@ bool cmTarget::IsLinkInterfaceDependentNumberMinProperty(const std::string &p, bool cmTarget::IsLinkInterfaceDependentNumberMaxProperty(const std::string &p, const char *config) const { - if (this->TargetTypeValue == OBJECT_LIBRARY) + if (this->TargetTypeValue == OBJECT_LIBRARY + || this->TargetTypeValue == INTERFACE_LIBRARY) { return false; } @@ -5105,34 +5339,37 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, { emitted.insert(*li); } - LinkImplementation const* impl = this->GetLinkImplementation(config, - headTarget); - for(std::vector<std::string>::const_iterator - li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) + if (this->GetType() != cmTarget::INTERFACE_LIBRARY) { - if(emitted.insert(*li).second) + LinkImplementation const* impl = this->GetLinkImplementation(config, + headTarget); + for(std::vector<std::string>::const_iterator + li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li) { - if(cmTarget* tgt = this->Makefile->FindTargetToUse(li->c_str())) + if(emitted.insert(*li).second) { - // This is a runtime dependency on another shared library. - if(tgt->GetType() == cmTarget::SHARED_LIBRARY) + if(cmTarget* tgt = this->Makefile->FindTargetToUse(li->c_str())) { - iface.SharedDeps.push_back(*li); + // This is a runtime dependency on another shared library. + if(tgt->GetType() == cmTarget::SHARED_LIBRARY) + { + iface.SharedDeps.push_back(*li); + } + } + else + { + // TODO: Recognize shared library file names. Perhaps this + // should be moved to cmComputeLinkInformation, but that creates + // a chicken-and-egg problem since this list is needed for its + // construction. } - } - else - { - // TODO: Recognize shared library file names. Perhaps this - // should be moved to cmComputeLinkInformation, but that creates - // a chicken-and-egg problem since this list is needed for its - // construction. } } - } - if(this->LinkLanguagePropagatesToDependents()) - { - // Targets using this archive need its language runtime libraries. - iface.Languages = impl->Languages; + if(this->LinkLanguagePropagatesToDependents()) + { + // Targets using this archive need its language runtime libraries. + iface.Languages = impl->Languages; + } } } } @@ -5864,6 +6101,7 @@ cmTargetInternalPointer::~cmTargetInternalPointer() { deleteAndClear(this->Pointer->IncludeDirectoriesEntries); deleteAndClear(this->Pointer->CompileOptionsEntries); + deleteAndClear(this->Pointer->AutoUicOptionsEntries); deleteAndClear(this->Pointer->CompileDefinitionsEntries); delete this->Pointer; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index b516a0a..93e8b99 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -25,7 +25,8 @@ F(CMP0008) \ F(CMP0020) \ F(CMP0021) \ - F(CMP0022) + F(CMP0022) \ + F(CMP0041) class cmake; class cmMakefile; @@ -114,12 +115,18 @@ public: /** * Get the list of the custom commands for this target */ - std::vector<cmCustomCommand> &GetPreBuildCommands() + std::vector<cmCustomCommand> const &GetPreBuildCommands() const {return this->PreBuildCommands;} - std::vector<cmCustomCommand> &GetPreLinkCommands() + std::vector<cmCustomCommand> const &GetPreLinkCommands() const {return this->PreLinkCommands;} - std::vector<cmCustomCommand> &GetPostBuildCommands() + std::vector<cmCustomCommand> const &GetPostBuildCommands() const {return this->PostBuildCommands;} + void AddPreBuildCommand(cmCustomCommand const &cmd) + {this->PreBuildCommands.push_back(cmd);} + void AddPreLinkCommand(cmCustomCommand const &cmd) + {this->PreLinkCommands.push_back(cmd);} + void AddPostBuildCommand(cmCustomCommand const &cmd) + {this->PostBuildCommands.push_back(cmd);} /** * Get the list of the source files used by this target @@ -156,7 +163,8 @@ public: /** * Get the flags for a given source file as used in this target */ - struct SourceFileFlags GetTargetSourceFileFlags(const cmSourceFile* sf); + struct SourceFileFlags + GetTargetSourceFileFlags(const cmSourceFile* sf) const; /** * Add sources to the target. @@ -179,7 +187,7 @@ public: cmTarget const* head) const; void GetInterfaceLinkLibraries(const char *config, std::vector<std::string> &, - cmTarget *head); + cmTarget *head) const; /** Compute the link type to use for the given configuration. */ LinkLibraryType ComputeLinkType(const char* config) const; @@ -190,7 +198,7 @@ public: void ClearDependencyInformation(cmMakefile& mf, const char* target); // Check to see if a library is a framework and treat it different on Mac - bool NameResolvesToFramework(const std::string& libname); + bool NameResolvesToFramework(const std::string& libname) const; void AddLinkLibrary(cmMakefile& mf, const char *target, const char* lib, LinkLibraryType llt); @@ -212,14 +220,14 @@ public: * Set the path where this target should be installed. This is relative to * INSTALL_PREFIX */ - std::string GetInstallPath() {return this->InstallPath;} + std::string GetInstallPath() const {return this->InstallPath;} void SetInstallPath(const char *name) {this->InstallPath = name;} /** * Set the path where this target (if it has a runtime part) should be * installed. This is relative to INSTALL_PREFIX */ - std::string GetRuntimeInstallPath() {return this->RuntimeInstallPath;} + std::string GetRuntimeInstallPath() const {return this->RuntimeInstallPath;} void SetRuntimeInstallPath(const char *name) { this->RuntimeInstallPath = name; } @@ -246,9 +254,9 @@ public: const char *GetProperty(const char *prop) const; const char *GetProperty(const char *prop, cmProperty::ScopeType scope) const; bool GetPropertyAsBool(const char *prop) const; - void CheckProperty(const char* prop, cmMakefile* context); + void CheckProperty(const char* prop, cmMakefile* context) const; - const char* GetFeature(const char* feature, const char* config); + const char* GetFeature(const char* feature, const char* config) const; bool IsImported() const {return this->IsImportedTarget;} @@ -330,7 +338,7 @@ public: If the configuration name is given then the generator will add its subdirectory for that configuration. Otherwise just the canonical pdb output directory is given. */ - std::string GetPDBDirectory(const char* config = 0); + std::string GetPDBDirectory(const char* config = 0) const; /** Get the location of the target in the build tree for the given configuration. This location is suitable for use as the LOCATION @@ -340,12 +348,13 @@ public: /** Get the target major and minor version numbers interpreted from the VERSION property. Version 0 is returned if the property is not set or cannot be parsed. */ - void GetTargetVersion(int& major, int& minor); + void GetTargetVersion(int& major, int& minor) const; /** Get the target major, minor, and patch version numbers interpreted from the VERSION or SOVERSION property. Version 0 is returned if the property is not set or cannot be parsed. */ - void GetTargetVersion(bool soversion, int& major, int& minor, int& patch); + void + GetTargetVersion(bool soversion, int& major, int& minor, int& patch) const; /** * Make sure the full path to all source files is known. @@ -377,7 +386,7 @@ public: /** Test for special case of a third-party shared library that has no soname at all. */ - bool IsImportedSharedLibWithoutSOName(const char* config); + bool IsImportedSharedLibWithoutSOName(const char* config) const; /** Get the full path to the target according to the settings in its makefile and the configuration type. */ @@ -399,12 +408,12 @@ public: std::string& pdbName, const char* config) const; /** Does this target have a GNU implib to convert to MS format? */ - bool HasImplibGNUtoMS(); + bool HasImplibGNUtoMS() const; /** Convert the given GNU import library name (.dll.a) to a name with a new extension (.lib or ${CMAKE_IMPORT_LIBRARY_SUFFIX}). */ bool GetImplibGNUtoMS(std::string const& gnuName, std::string& out, - const char* newExt = 0); + const char* newExt = 0) const; /** * Compute whether this target must be relinked before installing. @@ -442,7 +451,7 @@ public: /** Get the macro to define when building sources in this target. If no macro should be defined null is returned. */ - const char* GetExportMacro(); + const char* GetExportMacro() const; void GetCompileDefinitions(std::vector<std::string> &result, const char *config) const; @@ -459,10 +468,10 @@ public: bool IsExecutableWithExports() const; /** Return whether this target may be used to link another target. */ - bool IsLinkable(); + bool IsLinkable() const; /** Return whether or not the target is for a DLL platform. */ - bool IsDLLPlatform() { return this->DLLPlatform; } + bool IsDLLPlatform() const { return this->DLLPlatform; } /** Return whether or not the target has a DLL import library. */ bool HasImportLibrary() const; @@ -493,7 +502,7 @@ public: /** Return whether this target uses the default value for its output directory. */ - bool UsesDefaultOutputDir(const char* config, bool implib); + bool UsesDefaultOutputDir(const char* config, bool implib) const; /** @return the mac content directory for this target. */ std::string GetMacContentDirectory(const char* config, @@ -524,6 +533,8 @@ public: void GetCompileOptions(std::vector<std::string> &result, const char *config) const; + void GetAutoUicOptions(std::vector<std::string> &result, + const char *config) const; bool IsNullImpliedByLinkLibraries(const std::string &p) const; bool IsLinkInterfaceDependentBoolProperty(const std::string &p, @@ -546,7 +557,7 @@ public: const char *config) const; std::string GetDebugGeneratorExpressions(const std::string &value, - cmTarget::LinkLibraryType llt); + cmTarget::LinkLibraryType llt) const; void AddSystemIncludeDirectories(const std::set<cmStdString> &incs); void AddSystemIncludeDirectories(const std::vector<std::string> &incs); @@ -671,7 +682,7 @@ private: bool HaveInstallRule; std::string InstallPath; std::string RuntimeInstallPath; - std::string ExportMacro; + mutable std::string ExportMacro; std::set<cmStdString> Utilities; bool RecordDependencies; mutable cmPropertyMap Properties; @@ -681,6 +692,7 @@ private: bool IsImportedTarget; mutable bool DebugIncludesDone; mutable bool DebugCompileOptionsDone; + mutable bool DebugAutoUicOptionsDone; mutable bool DebugCompileDefinitionsDone; mutable std::set<std::string> LinkImplicitNullProperties; bool BuildInterfaceIncludesAppended; @@ -736,7 +748,7 @@ private: friend class cmTargetTraceDependencies; cmTargetInternalPointer Internal; - void ConstructSourceFileFlags(); + void ConstructSourceFileFlags() const; void ComputeVersionedName(std::string& vName, std::string const& prefix, std::string const& base, diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx index 46c9666..b567252 100644 --- a/Source/cmTargetCompileDefinitionsCommand.cxx +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -44,7 +44,7 @@ std::string cmTargetCompileDefinitionsCommand for(std::vector<std::string>::const_iterator it = content.begin(); it != content.end(); ++it) { - if (strncmp(it->c_str(), "-D", 2) == 0) + if (cmHasLiteralPrefix(it->c_str(), "-D")) { defs += sep + it->substr(2); } diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index e7b906c..913bdab 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -50,7 +50,7 @@ std::string cmTargetIncludeDirectoriesCommand it != content.end(); ++it) { if (cmSystemTools::FileIsFullPath(it->c_str()) - || cmGeneratorExpression::Find(*it) != std::string::npos) + || cmGeneratorExpression::Find(*it) == 0) { dirs += sep + *it; } diff --git a/Source/cmUnsetCommand.cxx b/Source/cmUnsetCommand.cxx index 84f3029..053cdfc 100644 --- a/Source/cmUnsetCommand.cxx +++ b/Source/cmUnsetCommand.cxx @@ -24,7 +24,7 @@ bool cmUnsetCommand::InitialPass(std::vector<std::string> const& args, const char* variable = args[0].c_str(); // unset(ENV{VAR}) - if (!strncmp(variable,"ENV{",4) && strlen(variable) > 5) + if (cmHasLiteralPrefix(variable, "ENV{") && strlen(variable) > 5) { // what is the variable name char *envVarName = new char [strlen(variable)]; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index ace1eef..10663b7 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -184,7 +184,8 @@ void cmVisualStudio10TargetGenerator::WriteString(const char* line, void cmVisualStudio10TargetGenerator::Generate() { // do not generate external ms projects - if(this->Target->GetProperty("EXTERNAL_MSPROJECT")) + if(this->Target->GetType() == cmTarget::INTERFACE_LIBRARY + || this->Target->GetProperty("EXTERNAL_MSPROJECT")) { return; } @@ -1794,7 +1795,7 @@ cmVisualStudio10TargetGenerator::WriteEvents(std::string const& configName) void cmVisualStudio10TargetGenerator::WriteEvent( const char* name, - std::vector<cmCustomCommand> & commands, + std::vector<cmCustomCommand> const& commands, std::string const& configName) { if(commands.size() == 0) @@ -1807,10 +1808,10 @@ void cmVisualStudio10TargetGenerator::WriteEvent( std::string script; const char* pre = ""; std::string comment; - for(std::vector<cmCustomCommand>::iterator i = commands.begin(); + for(std::vector<cmCustomCommand>::const_iterator i = commands.begin(); i != commands.end(); ++i) { - cmCustomCommand& command = *i; + const cmCustomCommand& command = *i; comment += pre; comment += lg->ConstructComment(command); script += pre; diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 9a480a8..d1f3d19 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -87,7 +87,8 @@ private: void AddLibraries(cmComputeLinkInformation& cli, std::string& libstring); void WriteLibOptions(std::string const& config); void WriteEvents(std::string const& configName); - void WriteEvent(const char* name, std::vector<cmCustomCommand> & commands, + void WriteEvent(const char* name, + std::vector<cmCustomCommand> const& commands, std::string const& configName); void WriteGroupSources(const char* name, ToolSources const& sources, std::vector<cmSourceGroup>& ); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index bf27c78..741e263 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -73,6 +73,7 @@ # include "cmExtraCodeBlocksGenerator.h" #endif #include "cmExtraSublimeTextGenerator.h" +#include "cmExtraKateGenerator.h" #ifdef CMAKE_USE_KDEVELOP # include "cmGlobalKdevelopGenerator.h" @@ -991,6 +992,8 @@ void cmake::AddDefaultExtraGenerators() &cmExtraCodeBlocksGenerator::New); this->AddExtraGenerator(cmExtraSublimeTextGenerator::GetActualName(), &cmExtraSublimeTextGenerator::New); + this->AddExtraGenerator(cmExtraKateGenerator::GetActualName(), + &cmExtraKateGenerator::New); #ifdef CMAKE_USE_ECLIPSE this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(), diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 6ef0579..882b072 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -273,7 +273,7 @@ int do_cmake(int ac, char** av) list_all_cached = true; list_help = true; } - else if (strncmp(av[i], "-P", strlen("-P")) == 0) + else if (cmHasLiteralPrefix(av[i], "-P")) { if ( i == ac -1 ) { @@ -287,8 +287,7 @@ int do_cmake(int ac, char** av) args.push_back(av[i]); } } - else if (strncmp(av[i], "--find-package", - strlen("--find-package")) == 0) + else if (cmHasLiteralPrefix(av[i], "--find-package")) { workingMode = cmake::FIND_PACKAGE_MODE; args.push_back(av[i]); diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index d4f464c..d3b7b5f 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1294,7 +1294,8 @@ int cmcmd::VisualStudioLinkIncremental(std::vector<std::string>& args, // to do the final link. If mt has any value other than 0 or 1090650113 // then there was some problem with the command itself and there was an // error so return the error code back out of cmake so make can report it. - if(mtRet != 1090650113) + // (when hosted on a posix system the value is 187) + if(mtRet != 1090650113 && mtRet != 187) { return mtRet; } diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index a9d89d4..3745f78 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -115,6 +115,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) SET(KWSYS_USE_Base64 1) SET(KWSYS_USE_Directory 1) SET(KWSYS_USE_DynamicLoader 1) + SET(KWSYS_USE_Encoding 1) SET(KWSYS_USE_Glob 1) SET(KWSYS_USE_MD5 1) SET(KWSYS_USE_Process 1) @@ -125,6 +126,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) SET(KWSYS_USE_FundamentalType 1) SET(KWSYS_USE_Terminal 1) SET(KWSYS_USE_IOStream 1) + SET(KWSYS_USE_FStream 1) SET(KWSYS_USE_String 1) SET(KWSYS_USE_SystemInformation 1) SET(KWSYS_USE_CPU 1) @@ -133,18 +135,32 @@ ENDIF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) # Enforce component dependencies. IF(KWSYS_USE_SystemTools) SET(KWSYS_USE_Directory 1) + SET(KWSYS_USE_FStream 1) + SET(KWSYS_USE_Encoding 1) ENDIF(KWSYS_USE_SystemTools) IF(KWSYS_USE_Glob) SET(KWSYS_USE_Directory 1) SET(KWSYS_USE_SystemTools 1) SET(KWSYS_USE_RegularExpression 1) + SET(KWSYS_USE_FStream 1) + SET(KWSYS_USE_Encoding 1) ENDIF(KWSYS_USE_Glob) IF(KWSYS_USE_Process) SET(KWSYS_USE_System 1) + SET(KWSYS_USE_Encoding 1) ENDIF(KWSYS_USE_Process) IF(KWSYS_USE_SystemInformation) SET(KWSYS_USE_Process 1) ENDIF(KWSYS_USE_SystemInformation) +IF(KWSYS_USE_System) + SET(KWSYS_USE_Encoding 1) +ENDIF(KWSYS_USE_System) +IF(KWSYS_USE_Directory) + SET(KWSYS_USE_Encoding 1) +ENDIF(KWSYS_USE_Directory) +IF(KWSYS_USE_FStream) + SET(KWSYS_USE_Encoding 1) +ENDIF(KWSYS_USE_FStream) # Setup the large file support default. IF(KWSYS_LFS_DISABLE) @@ -153,6 +169,11 @@ ELSE(KWSYS_LFS_DISABLE) SET(KWSYS_LFS_REQUESTED 1) ENDIF(KWSYS_LFS_DISABLE) +# Specify default 8 bit encoding for Windows +IF(NOT KWSYS_ENCODING_DEFAULT_CODEPAGE) + SET(KWSYS_ENCODING_DEFAULT_CODEPAGE CP_ACP) +ENDIF(NOT KWSYS_ENCODING_DEFAULT_CODEPAGE) + # Enable testing if building standalone. IF(KWSYS_STANDALONE) INCLUDE(Dart) @@ -509,6 +530,12 @@ IF(KWSYS_USE_FundamentalType) "Checking whether char is signed" DIRECT) ENDIF(KWSYS_USE_FundamentalType) +IF(KWSYS_USE_Encoding) + # Look for type size helper macros. + KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_WSTRING + "Checking whether wstring is available" DIRECT) +ENDIF(KWSYS_USE_Encoding) + IF(KWSYS_USE_IOStream) # Determine whether iostreams support long long. SET(KWSYS_PLATFORM_CXX_TEST_DEFINES @@ -864,8 +891,8 @@ SET(KWSYS_HXX_FILES Configure String # Add selected C++ classes. SET(cppclasses - Directory DynamicLoader Glob RegularExpression SystemTools - CommandLineArguments IOStream SystemInformation + Directory DynamicLoader Encoding Glob RegularExpression SystemTools + CommandLineArguments IOStream FStream SystemInformation ) FOREACH(cpp ${cppclasses}) IF(KWSYS_USE_${cpp}) @@ -881,7 +908,7 @@ ENDFOREACH(cpp) # Add selected C components. FOREACH(c - Process Base64 FundamentalType MD5 Terminal System String CPU + Process Base64 Encoding FundamentalType MD5 Terminal System String CPU ) IF(KWSYS_USE_${c}) # Use the corresponding header file. @@ -912,16 +939,24 @@ IF(KWSYS_USE_Process) ENDIF(KWSYS_USE_Process) # Add selected C sources. -FOREACH(c Base64 MD5 Terminal System String) +FOREACH(c Base64 Encoding MD5 Terminal System String) IF(KWSYS_USE_${c}) - SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ${c}.c) + IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}C.c) + LIST(APPEND KWSYS_C_SRCS ${c}C.c) + ELSE() + LIST(APPEND KWSYS_C_SRCS ${c}.c) + ENDIF() ENDIF(KWSYS_USE_${c}) ENDFOREACH(c) # Configure headers of C++ classes and construct the list of sources. FOREACH(c ${KWSYS_CLASSES}) # Add this source to the list of source files for the library. - SET(KWSYS_CXX_SRCS ${KWSYS_CXX_SRCS} ${c}.cxx) + IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}CXX.cxx) + LIST(APPEND KWSYS_CXX_SRCS ${c}CXX.cxx) + ELSEIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}.cxx) + LIST(APPEND KWSYS_CXX_SRCS ${c}.cxx) + ENDIF() # Configure the header for this class. CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${c}.hxx.in ${KWSYS_HEADER_DIR}/${c}.hxx @@ -1047,6 +1082,12 @@ IF(KWSYS_USE_String) COMPILE_FLAGS "-DKWSYS_STRING_C") ENDIF(KWSYS_USE_String) +IF(KWSYS_USE_Encoding) + # Set default 8 bit encoding in "EndcodingC.c". + SET_PROPERTY(SOURCE EncodingC.c APPEND PROPERTY COMPILE_DEFINITIONS + KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE}) +ENDIF(KWSYS_USE_Encoding) + #----------------------------------------------------------------------------- # Setup testing if not being built as part of another project. IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) @@ -1090,6 +1131,11 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) testCommandLineArguments testCommandLineArguments1 ) + IF(KWSYS_STL_HAS_WSTRING) + SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} + testEncoding + ) + ENDIF(KWSYS_STL_HAS_WSTRING) IF(KWSYS_USE_SystemInformation) SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testSystemInformation) ENDIF(KWSYS_USE_SystemInformation) diff --git a/Source/kwsys/Configure.hxx.in b/Source/kwsys/Configure.hxx.in index 716b84f..8f5ace2 100644 --- a/Source/kwsys/Configure.hxx.in +++ b/Source/kwsys/Configure.hxx.in @@ -36,6 +36,9 @@ /* Whether STL is in std namespace. */ #define @KWSYS_NAMESPACE@_STL_HAVE_STD @KWSYS_STL_HAVE_STD@ +/* Whether wstring is available. */ +#define @KWSYS_NAMESPACE@_STL_HAS_WSTRING @KWSYS_STL_HAS_WSTRING@ + /* Whether the STL string has operator<< for ostream. */ #define @KWSYS_NAMESPACE@_STL_STRING_HAVE_OSTREAM @KWSYS_STL_STRING_HAVE_OSTREAM@ @@ -170,6 +173,7 @@ # define KWSYS_STL_HAS_ALLOCATOR_TEMPLATE @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_TEMPLATE # define KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_NONTEMPLATE # define KWSYS_STL_HAS_ALLOCATOR_OBJECTS @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_OBJECTS +# define KWSYS_STL_HAS_WSTRING @KWSYS_NAMESPACE@_STL_HAS_WSTRING #endif #endif diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx index b884747..d54e607 100644 --- a/Source/kwsys/Directory.cxx +++ b/Source/kwsys/Directory.cxx @@ -14,6 +14,8 @@ #include KWSYS_HEADER(Configure.hxx) +#include KWSYS_HEADER(Encoding.hxx) + #include KWSYS_HEADER(stl/string) #include KWSYS_HEADER(stl/vector) @@ -22,6 +24,7 @@ #if 0 # include "Directory.hxx.in" # include "Configure.hxx.in" +# include "Encoding.hxx.in" # include "kwsys_stl.hxx.in" # include "kwsys_stl_string.hxx.in" # include "kwsys_stl_vector.hxx.in" @@ -120,10 +123,10 @@ bool Directory::Load(const char* name) buf = new char[n + 2 + 1]; sprintf(buf, "%s/*", name); } - struct _finddata_t data; // data of current file + struct _wfinddata_t data; // data of current file // Now put them into the file array - srchHandle = _findfirst(buf, &data); + srchHandle = _wfindfirst((wchar_t*)Encoding::ToWide(buf).c_str(), &data); delete [] buf; if ( srchHandle == -1 ) @@ -134,9 +137,9 @@ bool Directory::Load(const char* name) // Loop through names do { - this->Internal->Files.push_back(data.name); + this->Internal->Files.push_back(Encoding::ToNarrow(data.name)); } - while ( _findnext(srchHandle, &data) != -1 ); + while ( _wfindnext(srchHandle, &data) != -1 ); this->Internal->Path = name; return _findclose(srchHandle) != -1; } @@ -160,10 +163,10 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const char* name) buf = new char[n + 2 + 1]; sprintf(buf, "%s/*", name); } - struct _finddata_t data; // data of current file + struct _wfinddata_t data; // data of current file // Now put them into the file array - srchHandle = _findfirst(buf, &data); + srchHandle = _wfindfirst((wchar_t*)Encoding::ToWide(buf).c_str(), &data); delete [] buf; if ( srchHandle == -1 ) @@ -177,7 +180,7 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const char* name) { count++; } - while ( _findnext(srchHandle, &data) != -1 ); + while ( _wfindnext(srchHandle, &data) != -1 ); _findclose(srchHandle); return count; } diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx index fd83752..44cf6af 100644 --- a/Source/kwsys/DynamicLoader.cxx +++ b/Source/kwsys/DynamicLoader.cxx @@ -186,13 +186,12 @@ namespace KWSYS_NAMESPACE DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname) { DynamicLoader::LibraryHandle lh; -#ifdef UNICODE - wchar_t libn[MB_CUR_MAX]; - mbstowcs(libn, libname, MB_CUR_MAX); - lh = LoadLibrary(libn); -#else - lh = LoadLibrary(libname); -#endif + int length = MultiByteToWideChar(CP_UTF8, 0, libname, -1, NULL, 0); + wchar_t* wchars = new wchar_t[length+1]; + wchars[0] = '\0'; + MultiByteToWideChar(CP_UTF8, 0, libname, -1, wchars, length); + lh = LoadLibraryW(wchars); + delete [] wchars; return lh; } @@ -238,13 +237,7 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( #else const char *rsym = sym; #endif -#ifdef UNICODE - wchar_t wsym[MB_CUR_MAX]; - mbstowcs(wsym, rsym, MB_CUR_MAX); - result = GetProcAddress(lib, wsym); -#else result = (void*)GetProcAddress(lib, rsym); -#endif #if defined(__BORLANDC__) || defined(__WATCOMC__) delete[] rsym; #endif diff --git a/Source/kwsys/Encoding.h.in b/Source/kwsys/Encoding.h.in new file mode 100644 index 0000000..591c5a8 --- /dev/null +++ b/Source/kwsys/Encoding.h.in @@ -0,0 +1,79 @@ +/*============================================================================ + KWSys - Kitware System Library + 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 @KWSYS_NAMESPACE@_Encoding_h +#define @KWSYS_NAMESPACE@_Encoding_h + +#include <@KWSYS_NAMESPACE@/Configure.h> +#include <wchar.h> + +/* Redefine all public interface symbol names to be in the proper + namespace. These macros are used internally to kwsys only, and are + not visible to user code. Use kwsysHeaderDump.pl to reproduce + these macros after making changes to the interface. */ +#if !defined(KWSYS_NAMESPACE) +# define kwsys_ns(x) @KWSYS_NAMESPACE@##x +# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT +#endif +#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# define kwsysEncoding kwsys_ns(Encoding) +# define kwsysEncoding_mbstowcs kwsys_ns(Encoding_mbstowcs) +# define kwsysEncoding_DupToWide kwsys_ns(Encoding_DupToWide) +# define kwsysEncoding_wcstombs kwsys_ns(Encoding_wcstombs) +# define kwsysEncoding_DupToNarrow kwsys_ns(Encoding_DupToNarrow) +#endif + +#if defined(__cplusplus) +extern "C" +{ +#endif + + +/* Convert a narrow string to a wide string. + On Windows, UTF-8 is assumed, and on other platforms, + the current locale is assumed. + */ +kwsysEXPORT size_t kwsysEncoding_mbstowcs(wchar_t* dest, const char* src, size_t n); + +/* Convert a narrow string to a wide string. + This can return NULL if the conversion fails. */ +kwsysEXPORT wchar_t* kwsysEncoding_DupToWide(const char* src); + + +/* Convert a wide string to a narrow string. + On Windows, UTF-8 is assumed, and on other platforms, + the current locale is assumed. */ +kwsysEXPORT size_t kwsysEncoding_wcstombs(char* dest, const wchar_t* src, size_t n); + +/* Convert a wide string to a narrow string. + This can return NULL if the conversion fails. */ +kwsysEXPORT char* kwsysEncoding_DupToNarrow(const wchar_t* str); + + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +/* If we are building a kwsys .c or .cxx file, let it use these macros. + Otherwise, undefine them to keep the namespace clean. */ +#if !defined(KWSYS_NAMESPACE) +# undef kwsys_ns +# undef kwsysEXPORT +# if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# undef kwsysEncoding +# undef kwsysEncoding_mbstowcs +# undef kwsysEncoding_DupToWide +# undef kwsysEncoding_wcstombs +# undef kwsysEncoding_DupToNarrow +# endif +#endif + +#endif diff --git a/Source/kwsys/Encoding.hxx.in b/Source/kwsys/Encoding.hxx.in new file mode 100644 index 0000000..60a4a8e --- /dev/null +++ b/Source/kwsys/Encoding.hxx.in @@ -0,0 +1,56 @@ +/*============================================================================ + KWSys - Kitware System Library + 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 @KWSYS_NAMESPACE@_Encoding_hxx +#define @KWSYS_NAMESPACE@_Encoding_hxx + +#include <@KWSYS_NAMESPACE@/Configure.hxx> +#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 +#endif + +namespace @KWSYS_NAMESPACE@ +{ +class @KWSYS_NAMESPACE@_EXPORT Encoding +{ +public: + /** + * Convert between char and wchar_t + */ + +#if @KWSYS_NAMESPACE@_STL_HAS_WSTRING + + // Convert a narrow string to a wide string. + // On Windows, UTF-8 is assumed, and on other platforms, + // the current locale is assumed. + static kwsys_stl::wstring ToWide(const kwsys_stl::string& str); + static kwsys_stl::wstring ToWide(const char* str); + + // Convert a wide string to a narrow string. + // On Windows, UTF-8 is assumed, and on other platforms, + // the current locale is assumed. + static kwsys_stl::string ToNarrow(const kwsys_stl::wstring& str); + static kwsys_stl::string ToNarrow(const wchar_t* str); + +#endif // @KWSYS_NAMESPACE@_STL_HAS_WSTRING + +}; // class Encoding +} // namespace @KWSYS_NAMESPACE@ + +/* Undefine temporary macros. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# undef kwsys_stl +#endif + +#endif diff --git a/Source/kwsys/EncodingC.c b/Source/kwsys/EncodingC.c new file mode 100644 index 0000000..a36eecc --- /dev/null +++ b/Source/kwsys/EncodingC.c @@ -0,0 +1,79 @@ +/*============================================================================ + KWSys - Kitware System Library + 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 "kwsysPrivate.h" +#include KWSYS_HEADER(Encoding.h) + +/* Work-around CMake dependency scanning limitation. This must + duplicate the above list of headers. */ +#if 0 +# include "Encoding.h.in" +#endif + +#include <stdlib.h> + +#ifdef _WIN32 +#include <windows.h> +#endif + +size_t kwsysEncoding_mbstowcs(wchar_t* dest, const char* str, size_t n) +{ + if(str == 0) + { + return (size_t)-1; + } +#ifdef _WIN32 + return MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, + str, -1, dest, (int)n) - 1; +#else + return mbstowcs(dest, str, n); +#endif +} + +wchar_t* kwsysEncoding_DupToWide(const char* str) +{ + wchar_t* ret = NULL; + size_t length = kwsysEncoding_mbstowcs(NULL, str, 0) + 1; + if(length > 0) + { + ret = malloc((length)*sizeof(wchar_t)); + ret[0] = 0; + kwsysEncoding_mbstowcs(ret, str, length); + } + return ret; +} + +size_t kwsysEncoding_wcstombs(char* dest, const wchar_t* str, size_t n) +{ + if(str == 0) + { + return (size_t)-1; + } +#ifdef _WIN32 + return WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str, -1, + dest, (int)n, NULL, NULL) - 1; +#else + return wcstombs(dest, str, n); +#endif +} + +char* kwsysEncoding_DupToNarrow(const wchar_t* str) +{ + char* ret = NULL; + size_t length = kwsysEncoding_wcstombs(0, str, 0); + if(length > 0) + { + ret = malloc(length); + ret[0] = 0; + kwsysEncoding_wcstombs(ret, str, length); + } + return ret; +} diff --git a/Source/kwsys/EncodingCXX.cxx b/Source/kwsys/EncodingCXX.cxx new file mode 100644 index 0000000..aebc148 --- /dev/null +++ b/Source/kwsys/EncodingCXX.cxx @@ -0,0 +1,88 @@ +/*============================================================================ + KWSys - Kitware System Library + 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. +============================================================================*/ + +#ifdef __osf__ +# define _OSF_SOURCE +# define _POSIX_C_SOURCE 199506L +# define _XOPEN_SOURCE_EXTENDED +#endif + +#include "kwsysPrivate.h" +#include KWSYS_HEADER(Encoding.hxx) +#include KWSYS_HEADER(Encoding.h) +#include KWSYS_HEADER(stl/vector) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "Encoding.hxx.in" +# include "Encoding.h.in" +#endif + +#include <stdlib.h> + +#ifdef _MSC_VER +# pragma warning (disable: 4786) +#endif + +// Windows API. +#if defined(_WIN32) +# include <windows.h> +#endif + +namespace KWSYS_NAMESPACE +{ + +#if KWSYS_STL_HAS_WSTRING + +kwsys_stl::wstring Encoding::ToWide(const kwsys_stl::string& str) +{ + return ToWide(str.c_str()); +} + +kwsys_stl::string Encoding::ToNarrow(const kwsys_stl::wstring& str) +{ + return ToNarrow(str.c_str()); +} + +kwsys_stl::wstring Encoding::ToWide(const char* cstr) +{ + kwsys_stl::wstring wstr; + size_t length = kwsysEncoding_mbstowcs(0, cstr, 0) + 1; + if(length > 0) + { + kwsys_stl::vector<wchar_t> wchars(length); + if(kwsysEncoding_mbstowcs(&wchars[0], cstr, length) > 0) + { + wstr = &wchars[0]; + } + } + return wstr; +} + +kwsys_stl::string Encoding::ToNarrow(const wchar_t* wcstr) +{ + kwsys_stl::string str; + size_t length = kwsysEncoding_wcstombs(0, wcstr, 0) + 1; + if(length > 0) + { + std::vector<char> chars(length); + if(kwsysEncoding_wcstombs(&chars[0], wcstr, length) > 0) + { + str = &chars[0]; + } + } + return str; +} +#endif // KWSYS_STL_HAS_WSTRING + +} // namespace KWSYS_NAMESPACE diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in new file mode 100644 index 0000000..8170fb3 --- /dev/null +++ b/Source/kwsys/FStream.hxx.in @@ -0,0 +1,172 @@ +/*============================================================================ + KWSys - Kitware System Library + 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 @KWSYS_NAMESPACE@_FStream_hxx +#define @KWSYS_NAMESPACE@_FStream_hxx + +#include <@KWSYS_NAMESPACE@/ios/fstream> +#include <@KWSYS_NAMESPACE@/Encoding.hxx> + +namespace @KWSYS_NAMESPACE@ +{ +#if defined(_MSC_VER) && _MSC_VER >= 1400 + template<typename CharType,typename Traits> + class basic_filebuf : public std::basic_filebuf<CharType,Traits> + { + public: + typedef std::basic_filebuf<CharType,Traits> my_base_type; + basic_filebuf *open(char const *s,std::ios_base::openmode mode) + { + my_base_type::open(Encoding::ToWide(s).c_str(), mode); + return this; + } + }; + + template<typename CharType,typename Traits = std::char_traits<CharType> > + class basic_ifstream : public std::basic_istream<CharType,Traits> + { + public: + typedef basic_filebuf<CharType,Traits> internal_buffer_type; + typedef std::basic_istream<CharType,Traits> internal_stream_type; + + basic_ifstream() : internal_stream_type(new internal_buffer_type()) + { + buf_ = static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()); + } + explicit basic_ifstream(char const *file_name, + std::ios_base::openmode mode = std::ios_base::in) + : internal_stream_type(new internal_buffer_type()) + { + buf_ = static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()); + open(file_name,mode); + } + void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) + { + if(!buf_->open(file_name,mode | std::ios_base::in)) + { + this->setstate(std::ios_base::failbit); + } + else + { + this->clear(); + } + } + bool is_open() + { + return buf_->is_open(); + } + bool is_open() const + { + return buf_->is_open(); + } + void close() + { + if(!buf_->close()) + { + this->setstate(std::ios_base::failbit); + } + else + { + this->clear(); + } + } + + internal_buffer_type *rdbuf() const + { + return buf_.get(); + } + + ~basic_ifstream() + { + buf_->close(); + delete buf_; + } + + private: + internal_buffer_type* buf_; +}; + +template<typename CharType,typename Traits = std::char_traits<CharType> > +class basic_ofstream : public std::basic_ostream<CharType,Traits> +{ + public: + typedef basic_filebuf<CharType,Traits> internal_buffer_type; + typedef std::basic_ostream<CharType,Traits> internal_stream_type; + + basic_ofstream() : internal_stream_type(new internal_buffer_type()) + { + buf_ = static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()); + } + explicit basic_ofstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) : + internal_stream_type(new internal_buffer_type()) + { + buf_ = static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()); + open(file_name,mode); + } + void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) + { + if(!buf_->open(file_name,mode | std::ios_base::out)) + { + this->setstate(std::ios_base::failbit); + } + else + { + this->clear(); + } + } + bool is_open() + { + return buf_->is_open(); + } + bool is_open() const + { + return buf_->is_open(); + } + void close() + { + if(!buf_->close()) + { + this->setstate(std::ios_base::failbit); + } + else + { + this->clear(); + } + } + + internal_buffer_type *rdbuf() const + { + return buf_.get(); + } + ~basic_ofstream() + { + buf_->close(); + delete buf_; + } + + private: + internal_buffer_type* buf_; +}; + + typedef basic_ifstream<char> ifstream; + typedef basic_ofstream<char> ofstream; + +#else + using @KWSYS_NAMESPACE@_ios_namespace::basic_filebuf; + using @KWSYS_NAMESPACE@_ios_namespace::ofstream; + using @KWSYS_NAMESPACE@_ios_namespace::ifstream; +#endif + +} + + + +#endif diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index c836f9b..c8ec754 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -12,12 +12,14 @@ #include "kwsysPrivate.h" #include KWSYS_HEADER(Process.h) #include KWSYS_HEADER(System.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 "System.h.in" +# include "Encoding_c.h.in" #endif /* @@ -88,9 +90,10 @@ typedef LARGE_INTEGER kwsysProcessTime; typedef struct kwsysProcessCreateInformation_s { /* Windows child startup control data. */ - STARTUPINFO StartupInfo; + STARTUPINFOW StartupInfo; } kwsysProcessCreateInformation; + /*--------------------------------------------------------------------------*/ typedef struct kwsysProcessPipeData_s kwsysProcessPipeData; static DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd); @@ -197,14 +200,14 @@ struct kwsysProcess_s int State; /* The command lines to execute. */ - char** Commands; + wchar_t** Commands; int NumberOfCommands; /* The exit code of each command. */ DWORD* CommandExitCodes; /* The working directory for the child process. */ - char* WorkingDirectory; + wchar_t* WorkingDirectory; /* Whether to create the child as a detached process. */ int OptionDetach; @@ -299,7 +302,7 @@ struct kwsysProcess_s /* Real working directory of our own process. */ DWORD RealWorkingDirectoryLength; - char* RealWorkingDirectory; + wchar_t* RealWorkingDirectory; }; /*--------------------------------------------------------------------------*/ @@ -546,7 +549,7 @@ int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command) int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) { int newNumberOfCommands; - char** newCommands; + wchar_t** newCommands; /* Make sure we have a command to add. */ if(!cp || !command || !*command) @@ -554,9 +557,10 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) return 0; } + /* Allocate a new array for command pointers. */ newNumberOfCommands = cp->NumberOfCommands + 1; - if(!(newCommands = (char**)malloc(sizeof(char*) * newNumberOfCommands))) + if(!(newCommands = (wchar_t**)malloc(sizeof(wchar_t*) * newNumberOfCommands))) { /* Out of memory. */ return 0; @@ -585,8 +589,8 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) /* Allocate enough space for the command. We do not need an extra byte for the terminating null because we allocated a space for the first argument that we will not use. */ - newCommands[cp->NumberOfCommands] = (char*)malloc(length); - if(!newCommands[cp->NumberOfCommands]) + char* new_cmd = malloc(length); + if(!new_cmd) { /* Out of memory. */ free(newCommands); @@ -595,9 +599,13 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) /* Construct the command line in the allocated buffer. */ kwsysProcessComputeCommandLine(cp, command, - newCommands[cp->NumberOfCommands]); + new_cmd); + + newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(new_cmd); + free(new_cmd); } + /* Save the new array of commands. */ free(cp->Commands); cp->Commands = newCommands; @@ -633,22 +641,26 @@ int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir) } if(dir && dir[0]) { + wchar_t* wdir = kwsysEncoding_DupToWide(dir); /* We must convert the working directory to a full path. */ - DWORD length = GetFullPathName(dir, 0, 0, 0); + DWORD length = GetFullPathNameW(wdir, 0, 0, 0); if(length > 0) { - cp->WorkingDirectory = (char*)malloc(length); - if(!cp->WorkingDirectory) + wchar_t* work_dir = malloc(length*sizeof(wchar_t)); + if(!work_dir) { + free(wdir); return 0; } - if(!GetFullPathName(dir, length, cp->WorkingDirectory, 0)) + if(!GetFullPathNameW(wdir, length, work_dir, 0)) { - free(cp->WorkingDirectory); - cp->WorkingDirectory = 0; + free(work_dir); + free(wdir); return 0; } + cp->WorkingDirectory = work_dir; } + free(wdir); } return 1; } @@ -879,13 +891,13 @@ void kwsysProcess_Execute(kwsysProcess* cp) to make pipe file paths evaluate correctly. */ if(cp->WorkingDirectory) { - if(!GetCurrentDirectory(cp->RealWorkingDirectoryLength, + if(!GetCurrentDirectoryW(cp->RealWorkingDirectoryLength, cp->RealWorkingDirectory)) { kwsysProcessCleanup(cp, 1); return; } - SetCurrentDirectory(cp->WorkingDirectory); + SetCurrentDirectoryW(cp->WorkingDirectory); } /* Initialize startup info data. */ @@ -1003,7 +1015,7 @@ void kwsysProcess_Execute(kwsysProcess* cp) /* Restore the working directory. */ if(cp->RealWorkingDirectory) { - SetCurrentDirectory(cp->RealWorkingDirectory); + SetCurrentDirectoryW(cp->RealWorkingDirectory); free(cp->RealWorkingDirectory); cp->RealWorkingDirectory = 0; } @@ -1507,10 +1519,10 @@ int kwsysProcessInitialize(kwsysProcess* cp) /* Allocate space to save the real working directory of this process. */ if(cp->WorkingDirectory) { - cp->RealWorkingDirectoryLength = GetCurrentDirectory(0, 0); + cp->RealWorkingDirectoryLength = GetCurrentDirectoryW(0, 0); if(cp->RealWorkingDirectoryLength > 0) { - cp->RealWorkingDirectory = (char*)malloc(cp->RealWorkingDirectoryLength); + cp->RealWorkingDirectory = malloc(cp->RealWorkingDirectoryLength * sizeof(wchar_t)); if(!cp->RealWorkingDirectory) { return 0; @@ -1547,9 +1559,11 @@ int kwsysProcessCreate(kwsysProcess* cp, int index, else if(cp->PipeFileSTDIN) { /* Create a handle to read a file for stdin. */ - HANDLE fin = CreateFile(cp->PipeFileSTDIN, GENERIC_READ|GENERIC_WRITE, + wchar_t* wstdin = kwsysEncoding_DupToWide(cp->PipeFileSTDIN); + HANDLE fin = CreateFileW(wstdin, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + free(wstdin); if(fin == INVALID_HANDLE_VALUE) { return 0; @@ -1655,7 +1669,7 @@ int kwsysProcessCreate(kwsysProcess* cp, int index, /* Create the child in a suspended state so we can wait until all children have been created before running any one. */ - if(!CreateProcess(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0, + if(!CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0, 0, &si->StartupInfo, &cp->ProcessInformation[index])) { return 0; @@ -1729,6 +1743,7 @@ void kwsysProcessDestroy(kwsysProcess* cp, int event) int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name) { HANDLE fout; + wchar_t* wname; if(!name) { return 1; @@ -1738,8 +1753,10 @@ int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name) kwsysProcessCleanupHandle(phandle); /* Create a handle to write a file for the pipe. */ - fout = CreateFile(name, GENERIC_WRITE, FILE_SHARE_READ, 0, + wname = kwsysEncoding_DupToWide(name); + fout = CreateFileW(wname, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); + free(wname); if(fout == INVALID_HANDLE_VALUE) { return 0; @@ -1883,10 +1900,13 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error) { /* Format the error message. */ DWORD original = GetLastError(); - DWORD length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + wchar_t err_msg[KWSYSPE_PIPE_BUFFER_SIZE]; + DWORD length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, original, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, 0); + err_msg, KWSYSPE_PIPE_BUFFER_SIZE, 0); + WideCharToMultiByte(CP_UTF8, 0, err_msg, -1, cp->ErrorMessage, + KWSYSPE_PIPE_BUFFER_SIZE, NULL, NULL); if(length < 1) { /* FormatMessage failed. Use a default message. */ @@ -1924,7 +1944,7 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error) /* Restore the working directory. */ if(cp->RealWorkingDirectory) { - SetCurrentDirectory(cp->RealWorkingDirectory); + SetCurrentDirectoryW(cp->RealWorkingDirectory); } } @@ -2222,7 +2242,7 @@ static void kwsysProcessSetExitException(kwsysProcess* cp, int code) case STATUS_NO_MEMORY: default: cp->ExitException = kwsysProcess_Exception_Other; - sprintf(cp->ExitExceptionString, "Exit code 0x%x\n", code); + _snprintf(cp->ExitExceptionString, KWSYSPE_PIPE_BUFFER_SIZE, "Exit code 0x%x\n", code); break; } } @@ -2430,7 +2450,7 @@ static int kwsysProcess_List__New_NT4(kwsysProcess_List* self) loaded in this program. This does not actually increment the reference count to the module so we do not need to close the handle. */ - HMODULE hNT = GetModuleHandle("ntdll.dll"); + HMODULE hNT = GetModuleHandleW(L"ntdll.dll"); if(hNT) { /* Get pointers to the needed API functions. */ @@ -2534,7 +2554,7 @@ static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self) loaded in this program. This does not actually increment the reference count to the module so we do not need to close the handle. */ - HMODULE hKernel = GetModuleHandle("kernel32.dll"); + HMODULE hKernel = GetModuleHandleW(L"kernel32.dll"); if(hKernel) { self->P_CreateToolhelp32Snapshot = diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index 2672730..2f6c949 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -253,7 +253,7 @@ static bool call_cpuid(int select, int result[4]) _asm { #ifdef CPUID_AWARE_COMPILER ; we must push/pop the registers <<CPUID>> writes to, as the - ; optimiser doesn't know about <<CPUID>>, and so doesn't expect + ; optimiser does not know about <<CPUID>>, and so does not expect ; these registers to change. push eax push ebx @@ -2454,8 +2454,8 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed() if (!retrieved) { HKEY hKey = NULL; - LONG err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, - "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, + LONG err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey); if (ERROR_SUCCESS == err) @@ -2464,7 +2464,7 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed() DWORD data = 0; DWORD dwSize = sizeof(DWORD); - err = RegQueryValueEx(hKey, "~MHz", 0, + err = RegQueryValueExW(hKey, L"~MHz", 0, &dwType, (LPBYTE) &data, &dwSize); if (ERROR_SUCCESS == err) @@ -5017,19 +5017,19 @@ bool SystemInformationImplementation::QueryOSInformation() this->OSName = "Windows"; - OSVERSIONINFOEX osvi; + OSVERSIONINFOEXW osvi; BOOL bIsWindows64Bit; BOOL bOsVersionInfoEx; char operatingSystem[256]; // Try calling GetVersionEx using the OSVERSIONINFOEX structure. - ZeroMemory (&osvi, sizeof (OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); - bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi); + ZeroMemory (&osvi, sizeof (OSVERSIONINFOEXW)); + osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); + bOsVersionInfoEx = GetVersionExW ((OSVERSIONINFOW*)&osvi); if (!bOsVersionInfoEx) { - osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); - if (!GetVersionEx ((OSVERSIONINFO *) &osvi)) + osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOW); + if (!GetVersionExW((OSVERSIONINFOW*)&osvi)) { return false; } @@ -5115,19 +5115,19 @@ bool SystemInformationImplementation::QueryOSInformation() #endif // VER_NT_WORKSTATION { HKEY hKey; - char szProductType[80]; + wchar_t szProductType[80]; DWORD dwBufLen; // Query the registry to retrieve information. - RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey); - RegQueryValueEx (hKey, "ProductType", NULL, NULL, (LPBYTE) szProductType, &dwBufLen); + RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey); + RegQueryValueExW(hKey, L"ProductType", NULL, NULL, (LPBYTE) szProductType, &dwBufLen); RegCloseKey (hKey); - if (lstrcmpi ("WINNT", szProductType) == 0) + if (lstrcmpiW(L"WINNT", szProductType) == 0) { this->OSRelease += " Professional"; } - if (lstrcmpi ("LANMANNT", szProductType) == 0) + if (lstrcmpiW(L"LANMANNT", szProductType) == 0) { // Decide between Windows 2000 Advanced Server and Windows .NET Enterprise Server. if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) @@ -5139,7 +5139,7 @@ bool SystemInformationImplementation::QueryOSInformation() this->OSRelease += " Server"; } } - if (lstrcmpi ("SERVERNT", szProductType) == 0) + if (lstrcmpiW(L"SERVERNT", szProductType) == 0) { // Decide between Windows 2000 Advanced Server and Windows .NET Enterprise Server. if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) @@ -5172,7 +5172,7 @@ bool SystemInformationImplementation::QueryOSInformation() LPFNPROC DLLProc; // Load the Kernel32 DLL. - hKernelDLL = LoadLibrary ("kernel32"); + hKernelDLL = LoadLibraryW(L"kernel32"); if (hKernelDLL != NULL) { // Only XP and .NET Server support IsWOW64Process so... Load dynamically! DLLProc = (LPFNPROC) GetProcAddress (hKernelDLL, "IsWow64Process"); diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 749002d..4649f3b 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -20,6 +20,8 @@ #include KWSYS_HEADER(RegularExpression.hxx) #include KWSYS_HEADER(SystemTools.hxx) #include KWSYS_HEADER(Directory.hxx) +#include KWSYS_HEADER(FStream.hxx) +#include KWSYS_HEADER(Encoding.hxx) #include KWSYS_HEADER(ios/iostream) #include KWSYS_HEADER(ios/fstream) @@ -32,6 +34,8 @@ #if 0 # include "SystemTools.hxx.in" # include "Directory.hxx.in" +# include "FStream.hxx.in" +# include "Encoding.hxx.in" # include "kwsys_ios_iostream.h.in" # include "kwsys_ios_fstream.h.in" # include "kwsys_ios_sstream.h.in" @@ -75,6 +79,9 @@ // Windows API. #if defined(_WIN32) # include <windows.h> +# ifndef INVALID_FILE_ATTRIBUTES +# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) +# endif #elif defined (__CYGWIN__) # include <windows.h> # undef _WIN32 @@ -183,22 +190,25 @@ static inline char *realpath(const char *path, char *resolved_path) #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__)) inline int Mkdir(const char* dir) { - return _mkdir(dir); + return _wmkdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str()); } inline int Rmdir(const char* dir) { - return _rmdir(dir); + return _wrmdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str()); } inline const char* Getcwd(char* buf, unsigned int len) { - if(const char* ret = _getcwd(buf, len)) + std::vector<wchar_t> w_buf(len); + if(const wchar_t* ret = _wgetcwd(&w_buf[0], len)) { // make sure the drive letter is capital - if(strlen(buf) > 1 && buf[1] == ':') + if(wcslen(&w_buf[0]) > 1 && w_buf[1] == L':') { - buf[0] = toupper(buf[0]); + w_buf[0] = towupper(w_buf[0]); } - return ret; + std::string tmp = KWSYS_NAMESPACE::Encoding::ToNarrow(&w_buf[0]); + strcpy(buf, tmp.c_str()); + return buf; } return 0; } @@ -207,16 +217,18 @@ inline int Chdir(const char* dir) #if defined(__BORLANDC__) return chdir(dir); #else - return _chdir(dir); + return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str()); #endif } inline void Realpath(const char *path, kwsys_stl::string & resolved_path) { - char *ptemp; - char fullpath[MAX_PATH]; - if( GetFullPathName(path, sizeof(fullpath), fullpath, &ptemp) ) + kwsys_stl::wstring tmp = KWSYS_NAMESPACE::Encoding::ToWide(path); + wchar_t *ptemp; + wchar_t fullpath[MAX_PATH]; + if( GetFullPathNameW(tmp.c_str(), sizeof(fullpath)/sizeof(fullpath[0]), + fullpath, &ptemp) ) { - resolved_path = fullpath; + resolved_path = KWSYS_NAMESPACE::Encoding::ToNarrow(fullpath); KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path); } else @@ -591,6 +603,15 @@ const char* SystemTools::GetExecutableExtension() #endif } +FILE* SystemTools::Fopen(const char* file, const char* mode) +{ +#ifdef _WIN32 + return _wfopen(Encoding::ToWide(file).c_str(), + Encoding::ToWide(mode).c_str()); +#else + return fopen(file, mode); +#endif +} bool SystemTools::MakeDirectory(const char* path) { @@ -740,7 +761,7 @@ static DWORD SystemToolsMakeRegistryMode(DWORD mode, SystemTools::KeyWOW64 view) { // only add the modes when on a system that supports Wow64. - static FARPROC wow64p = GetProcAddress(GetModuleHandle("kernel32"), + static FARPROC wow64p = GetProcAddress(GetModuleHandleW(L"kernel32"), "IsWow64Process"); if(wow64p == NULL) { @@ -774,8 +795,8 @@ SystemTools::GetRegistrySubKeys(const char *key, } HKEY hKey; - if(RegOpenKeyEx(primaryKey, - second.c_str(), + if(RegOpenKeyExW(primaryKey, + Encoding::ToWide(second).c_str(), 0, SystemToolsMakeRegistryMode(KEY_READ, view), &hKey) != ERROR_SUCCESS) @@ -784,13 +805,13 @@ SystemTools::GetRegistrySubKeys(const char *key, } else { - char name[1024]; + wchar_t name[1024]; DWORD dwNameSize = sizeof(name)/sizeof(name[0]); DWORD i = 0; - while (RegEnumKey(hKey, i, name, dwNameSize) == ERROR_SUCCESS) + while (RegEnumKeyW(hKey, i, name, dwNameSize) == ERROR_SUCCESS) { - subkeys.push_back(name); + subkeys.push_back(Encoding::ToNarrow(name)); ++i; } @@ -829,8 +850,8 @@ bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value, } HKEY hKey; - if(RegOpenKeyEx(primaryKey, - second.c_str(), + if(RegOpenKeyExW(primaryKey, + Encoding::ToWide(second).c_str(), 0, SystemToolsMakeRegistryMode(KEY_READ, view), &hKey) != ERROR_SUCCESS) @@ -841,9 +862,9 @@ bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value, { DWORD dwType, dwSize; dwSize = 1023; - char data[1024]; - if(RegQueryValueEx(hKey, - (LPTSTR)valuename.c_str(), + wchar_t data[1024]; + if(RegQueryValueExW(hKey, + Encoding::ToWide(valuename).c_str(), NULL, &dwType, (BYTE *)data, @@ -851,16 +872,17 @@ bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value, { if (dwType == REG_SZ) { - value = data; + value = Encoding::ToNarrow(data); valueset = true; } else if (dwType == REG_EXPAND_SZ) { - char expanded[1024]; + wchar_t expanded[1024]; DWORD dwExpandedSize = sizeof(expanded)/sizeof(expanded[0]); - if(ExpandEnvironmentStrings(data, expanded, dwExpandedSize)) + if(ExpandEnvironmentStringsW(data, expanded, + dwExpandedSize)) { - value = expanded; + value = Encoding::ToNarrow(expanded); valueset = true; } } @@ -901,9 +923,9 @@ bool SystemTools::WriteRegistryValue(const char *key, const char *value, HKEY hKey; DWORD dwDummy; - char lpClass[] = ""; - if(RegCreateKeyEx(primaryKey, - second.c_str(), + wchar_t lpClass[] = L""; + if(RegCreateKeyExW(primaryKey, + Encoding::ToWide(second).c_str(), 0, lpClass, REG_OPTION_NON_VOLATILE, @@ -915,12 +937,13 @@ bool SystemTools::WriteRegistryValue(const char *key, const char *value, return false; } - if(RegSetValueEx(hKey, - (LPTSTR)valuename.c_str(), + std::wstring wvalue = Encoding::ToWide(value); + if(RegSetValueExW(hKey, + Encoding::ToWide(valuename).c_str(), 0, REG_SZ, - (CONST BYTE *)value, - (DWORD)(strlen(value) + 1)) == ERROR_SUCCESS) + (CONST BYTE *)wvalue.c_str(), + (DWORD)(sizeof(wchar_t) * (wvalue.size() + 1))) == ERROR_SUCCESS) { return true; } @@ -952,8 +975,8 @@ bool SystemTools::DeleteRegistryValue(const char *key, KeyWOW64 view) } HKEY hKey; - if(RegOpenKeyEx(primaryKey, - second.c_str(), + if(RegOpenKeyExW(primaryKey, + Encoding::ToWide(second).c_str(), 0, SystemToolsMakeRegistryMode(KEY_WRITE, view), &hKey) != ERROR_SUCCESS) @@ -983,7 +1006,7 @@ bool SystemTools::SameFile(const char* file1, const char* file2) #ifdef _WIN32 HANDLE hFile1, hFile2; - hFile1 = CreateFile( file1, + hFile1 = CreateFileW( Encoding::ToWide(file1).c_str(), GENERIC_READ, FILE_SHARE_READ , NULL, @@ -991,7 +1014,7 @@ bool SystemTools::SameFile(const char* file1, const char* file2) FILE_FLAG_BACKUP_SEMANTICS, NULL ); - hFile2 = CreateFile( file2, + hFile2 = CreateFileW( Encoding::ToWide(file2).c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, @@ -1040,15 +1063,6 @@ bool SystemTools::SameFile(const char* file1, const char* file2) } //---------------------------------------------------------------------------- -#if defined(_WIN32) || defined(__CYGWIN__) -static bool WindowsFileExists(const char* filename) -{ - WIN32_FILE_ATTRIBUTE_DATA fd; - return GetFileAttributesExA(filename, GetFileExInfoStandard, &fd) != 0; -} -#endif - -//---------------------------------------------------------------------------- bool SystemTools::FileExists(const char* filename) { if(!(filename && *filename)) @@ -1060,11 +1074,12 @@ bool SystemTools::FileExists(const char* filename) char winpath[MAX_PATH]; if(SystemTools::PathCygwinToWin32(filename, winpath)) { - return WindowsFileExists(winpath); + return (GetFileAttributesA(winpath) != INVALID_FILE_ATTRIBUTES); } return access(filename, R_OK) == 0; #elif defined(_WIN32) - return WindowsFileExists(filename); + return (GetFileAttributesW(Encoding::ToWide(filename).c_str()) + != INVALID_FILE_ATTRIBUTES); #else return access(filename, R_OK) == 0; #endif @@ -1107,7 +1122,7 @@ bool SystemTools::Touch(const char* filename, bool create) { if(create && !SystemTools::FileExists(filename)) { - FILE* file = fopen(filename, "a+b"); + FILE* file = Fopen(filename, "a+b"); if(file) { fclose(file); @@ -1116,7 +1131,8 @@ bool SystemTools::Touch(const char* filename, bool create) return false; } #if defined(_WIN32) && !defined(__CYGWIN__) - HANDLE h = CreateFile(filename, FILE_WRITE_ATTRIBUTES, + HANDLE h = CreateFileW(Encoding::ToWide(filename).c_str(), + FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); if(!h) @@ -1220,11 +1236,13 @@ 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(!GetFileAttributesEx(f1, GetFileExInfoStandard, &f1d)) + if(!GetFileAttributesExW(Encoding::ToWide(f1).c_str(), + GetFileExInfoStandard, &f1d)) { return false; } - if(!GetFileAttributesEx(f2, GetFileExInfoStandard, &f2d)) + if(!GetFileAttributesExW(Encoding::ToWide(f2).c_str(), + GetFileExInfoStandard, &f2d)) { return false; } @@ -1932,6 +1950,39 @@ bool SystemTools::CopyFileIfDifferent(const char* source, bool SystemTools::FilesDiffer(const char* source, const char* destination) { + +#if defined(_WIN32) + WIN32_FILE_ATTRIBUTE_DATA statSource; + if (GetFileAttributesExW(Encoding::ToWide(source).c_str(), + GetFileExInfoStandard, + &statSource) == 0) + { + return true; + } + + WIN32_FILE_ATTRIBUTE_DATA statDestination; + if (GetFileAttributesExW(Encoding::ToWide(destination).c_str(), + GetFileExInfoStandard, + &statDestination) == 0) + { + return true; + } + + if(statSource.nFileSizeHigh != statDestination.nFileSizeHigh || + statSource.nFileSizeLow != statDestination.nFileSizeLow) + { + return true; + } + + if(statSource.nFileSizeHigh == 0 && statSource.nFileSizeLow == 0) + { + return false; + } + off_t nleft = ((__int64)statSource.nFileSizeHigh << 32) + + statSource.nFileSizeLow; + +#else + struct stat statSource; if (stat(source, &statSource) != 0) { @@ -1953,15 +2004,19 @@ bool SystemTools::FilesDiffer(const char* source, { return false; } + off_t nleft = statSource.st_size; +#endif -#if defined(_WIN32) || defined(__CYGWIN__) - kwsys_ios::ifstream finSource(source, (kwsys_ios::ios::binary | - kwsys_ios::ios::in)); - kwsys_ios::ifstream finDestination(destination, (kwsys_ios::ios::binary | - kwsys_ios::ios::in)); +#if defined(_WIN32) + kwsys::ifstream finSource(source, + (kwsys_ios::ios::binary | + kwsys_ios::ios::in)); + kwsys::ifstream finDestination(destination, + (kwsys_ios::ios::binary | + kwsys_ios::ios::in)); #else - kwsys_ios::ifstream finSource(source); - kwsys_ios::ifstream finDestination(destination); + kwsys::ifstream finSource(source); + kwsys::ifstream finDestination(destination); #endif if(!finSource || !finDestination) { @@ -1971,7 +2026,6 @@ bool SystemTools::FilesDiffer(const char* source, // Compare the files a block at a time. char source_buf[KWSYS_ST_BUFFER]; char dest_buf[KWSYS_ST_BUFFER]; - off_t nleft = statSource.st_size; while(nleft > 0) { // Read a block from each file. @@ -2044,10 +2098,10 @@ bool SystemTools::CopyFileAlways(const char* source, const char* destination) // Open files #if defined(_WIN32) || defined(__CYGWIN__) - kwsys_ios::ifstream fin(source, - kwsys_ios::ios::binary | kwsys_ios::ios::in); + kwsys::ifstream fin(source, + kwsys_ios::ios::binary | kwsys_ios::ios::in); #else - kwsys_ios::ifstream fin(source); + kwsys::ifstream fin(source); #endif if(!fin) { @@ -2344,7 +2398,11 @@ bool SystemTools::RemoveFile(const char* source) /* Win32 unlink is stupid --- it fails if the file is read-only */ SystemTools::SetPermissions(source, S_IWRITE); #endif +#ifdef _WIN32 + bool res = _wunlink(Encoding::ToWide(source).c_str()) != 0 ? false : true; +#else bool res = unlink(source) != 0 ? false : true; +#endif #ifdef _WIN32 if ( !res ) { @@ -2789,12 +2847,15 @@ bool SystemTools::FileIsDirectory(const char* name) } // Now check the file node type. +#if defined( _WIN32 ) + DWORD attr = GetFileAttributesW(Encoding::ToWide(name).c_str()); + if (attr != INVALID_FILE_ATTRIBUTES) + { + return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; +#else struct stat fs; if(stat(name, &fs) == 0) { -#if defined( _WIN32 ) && !defined(__CYGWIN__) - return ((fs.st_mode & _S_IFDIR) != 0); -#else return S_ISDIR(fs.st_mode); #endif } @@ -3279,11 +3340,12 @@ static int GetCasePathName(const kwsys_stl::string & pathIn, kwsys_stl::string test_str = casePath; test_str += path_components[idx]; - WIN32_FIND_DATA findData; - HANDLE hFind = ::FindFirstFile(test_str.c_str(), &findData); + WIN32_FIND_DATAW findData; + HANDLE hFind = ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), + &findData); if (INVALID_HANDLE_VALUE != hFind) { - casePath += findData.cFileName; + casePath += Encoding::ToNarrow(findData.cFileName); ::FindClose(hFind); } else @@ -3733,8 +3795,7 @@ bool SystemTools::FileHasSignature(const char *filename, return false; } - FILE *fp; - fp = fopen(filename, "rb"); + FILE *fp = Fopen(filename, "rb"); if (!fp) { return false; @@ -3767,8 +3828,7 @@ SystemTools::DetectFileType(const char *filename, return SystemTools::FileTypeUnknown; } - FILE *fp; - fp = fopen(filename, "rb"); + FILE *fp = Fopen(filename, "rb"); if (!fp) { return SystemTools::FileTypeUnknown; @@ -3958,9 +4018,8 @@ bool SystemTools::GetShortPath(const char* path, kwsys_stl::string& shortPath) { #if defined(WIN32) && !defined(__CYGWIN__) const int size = int(strlen(path)) +1; // size of return - char *buffer = new char[size]; // create a buffer char *tempPath = new char[size]; // create a buffer - int ret; + DWORD ret; // if the path passed in has quotes around it, first remove the quotes if (path[0] == '"' && path[strlen(path)-1] == '"') @@ -3973,19 +4032,20 @@ bool SystemTools::GetShortPath(const char* path, kwsys_stl::string& shortPath) strcpy(tempPath,path); } + kwsys_stl::wstring wtempPath = Encoding::ToWide(tempPath); + kwsys_stl::vector<wchar_t> buffer(wtempPath.size()+1); buffer[0] = 0; - ret = GetShortPathName(tempPath, buffer, size); + ret = GetShortPathNameW(Encoding::ToWide(tempPath).c_str(), + &buffer[0], static_cast<DWORD>(wtempPath.size())); - if(buffer[0] == 0 || ret > size) + if(buffer[0] == 0 || ret > wtempPath.size()) { - delete [] buffer; delete [] tempPath; return false; } else { - shortPath = buffer; - delete [] buffer; + shortPath = Encoding::ToNarrow(&buffer[0]); delete [] tempPath; return true; } @@ -4212,12 +4272,45 @@ bool SystemTools::GetPermissions(const char* file, mode_t& mode) return false; } +#if defined(_WIN32) + DWORD attr = GetFileAttributesW(Encoding::ToWide(file).c_str()); + if(attr == INVALID_FILE_ATTRIBUTES) + { + return false; + } + if((attr & FILE_ATTRIBUTE_READONLY) != 0) + { + mode = (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6)); + } + else + { + mode = (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6)) | + (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6)); + } + if((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + mode |= S_IFDIR | (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6)); + } + else + { + mode |= S_IFREG; + } + const char* ext = strrchr(file, '.'); + if(ext && (Strucmp(ext, ".exe") == 0 || + Strucmp(ext, ".com") == 0 || + Strucmp(ext, ".cmd") == 0 || + Strucmp(ext, ".bat") == 0)) + { + mode |= (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6)); + } +#else struct stat st; if ( stat(file, &st) < 0 ) { return false; } mode = st.st_mode; +#endif return true; } @@ -4231,7 +4324,11 @@ bool SystemTools::SetPermissions(const char* file, mode_t mode) { return false; } +#ifdef _WIN32 + if ( _wchmod(Encoding::ToWide(file).c_str(), mode) < 0 ) +#else if ( chmod(file, mode) < 0 ) +#endif { return false; } @@ -4336,7 +4433,9 @@ void SystemTools::ConvertWindowsCommandLineToUnixArguments( (*argv)[0] = new char [1024]; #ifdef _WIN32 - ::GetModuleFileName(0, (*argv)[0], 1024); + wchar_t tmp[1024]; + ::GetModuleFileNameW(0, tmp, 1024); + strcpy((*argv)[0], Encoding::ToNarrow(tmp).c_str()); #else (*argv)[0][0] = '\0'; #endif @@ -4396,14 +4495,14 @@ kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion() #ifdef _WIN32 char buffer[256]; - OSVERSIONINFOEX osvi; + OSVERSIONINFOEXA osvi; BOOL bOsVersionInfoEx; // Try calling GetVersionEx using the OSVERSIONINFOEX structure. // If that fails, try using the OSVERSIONINFO structure. - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXA)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi); if (!bOsVersionInfoEx) @@ -4546,21 +4645,21 @@ kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion() { HKEY hKey; #define BUFSIZE 80 - char szProductType[BUFSIZE]; + wchar_t szProductType[BUFSIZE]; DWORD dwBufLen=BUFSIZE; LONG lRet; - lRet = RegOpenKeyEx( + lRet = RegOpenKeyExW( HKEY_LOCAL_MACHINE, - "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", + L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey); if (lRet != ERROR_SUCCESS) { return 0; } - lRet = RegQueryValueEx(hKey, "ProductType", NULL, NULL, - (LPBYTE) szProductType, &dwBufLen); + lRet = RegQueryValueExW(hKey, L"ProductType", NULL, NULL, + (LPBYTE) szProductType, &dwBufLen); if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE)) { @@ -4569,15 +4668,15 @@ kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion() RegCloseKey(hKey); - if (lstrcmpi("WINNT", szProductType) == 0) + if (lstrcmpiW(L"WINNT", szProductType) == 0) { res += " Workstation"; } - if (lstrcmpi("LANMANNT", szProductType) == 0) + if (lstrcmpiW(L"LANMANNT", szProductType) == 0) { res += " Server"; } - if (lstrcmpi("SERVERNT", szProductType) == 0) + if (lstrcmpiW(L"SERVERNT", szProductType) == 0) { res += " Advanced Server"; } @@ -4593,16 +4692,16 @@ kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion() // Display service pack (if any) and build number. if (osvi.dwMajorVersion == 4 && - lstrcmpi(osvi.szCSDVersion, "Service Pack 6") == 0) + lstrcmpiA(osvi.szCSDVersion, "Service Pack 6") == 0) { HKEY hKey; LONG lRet; // Test for SP6 versus SP6a. - lRet = RegOpenKeyEx( + lRet = RegOpenKeyExW( HKEY_LOCAL_MACHINE, - "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009", + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009", 0, KEY_QUERY_VALUE, &hKey); if (lRet == ERROR_SUCCESS) diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index d6dae39..9457a4e 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -24,6 +24,8 @@ // Required for va_list #include <stdarg.h> +// Required for FILE* +#include <stdio.h> #if @KWSYS_NAMESPACE@_STL_HAVE_STD && !defined(va_list) // Some compilers move va_list into the std namespace and there is no way to // tell that this has been done. Playing with things being included before or @@ -42,10 +44,6 @@ namespace @KWSYS_NAMESPACE@ } #endif // va_list -#if defined( _MSC_VER ) -typedef unsigned short mode_t; -#endif - /* Define these macros temporarily to keep the code readable. */ #if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS # define kwsys_stl @KWSYS_NAMESPACE@_stl @@ -497,6 +495,11 @@ public: */ /** + * Open a file considering unicode. + */ + static FILE* Fopen(const char* file, const char* mode); + + /** * Make a new directory if it is not there. This function * can make a full path even if none of the directories existed * prior to calling this function. @@ -684,6 +687,10 @@ public: */ static long int CreationTime(const char* filename); + #if defined( _MSC_VER ) + typedef unsigned short mode_t; + #endif + /** * Get and set permissions of the file. */ diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx index be7a09e..3f947f3 100644 --- a/Source/kwsys/kwsysPlatformTestsCXX.cxx +++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx @@ -674,3 +674,9 @@ int main() return a; } #endif + +#ifdef TEST_KWSYS_STL_HAS_WSTRING +#include <string> +void f(std ::wstring*) {} +int main() { return 0; } +#endif diff --git a/Source/kwsys/testEncoding.cxx b/Source/kwsys/testEncoding.cxx new file mode 100644 index 0000000..8e74a50 --- /dev/null +++ b/Source/kwsys/testEncoding.cxx @@ -0,0 +1,159 @@ +/*============================================================================ + KWSys - Kitware System Library + 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 "kwsysPrivate.h" + +#if defined(_MSC_VER) +# pragma warning (disable:4786) +#endif + +#include KWSYS_HEADER(Encoding.hxx) +#include KWSYS_HEADER(ios/iostream) + +#include <locale.h> + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "Encoding.hxx.in" +# include "kwsys_ios_iostream.h.in" +#endif + +//---------------------------------------------------------------------------- +static const unsigned char helloWorldStrings[][32] = +{ + // English + {'H','e','l','l','o',' ','W','o','r','l','d',0}, + // Japanese + {0xE3, 0x81, 0x93, 0xE3, 0x82, 0x93, 0xE3, 0x81, 0xAB, 0xE3, + 0x81, 0xA1, 0xE3, 0x81, 0xAF, 0xE4, 0xB8, 0x96, 0xE7, 0x95, + 0x8C, 0}, + // Arabic + {0xD9, 0x85, 0xD8, 0xB1, 0xD8, 0xAD, 0xD8, 0xA8, 0xD8, 0xA7, + 0x20, 0xD8, 0xA7, 0xD9, 0x84, 0xD8, 0xB9, 0xD8, 0xA7, 0xD9, + 0x84, 0xD9, 0x85, 0}, + // Yiddish + {0xD7, 0x94, 0xD7, 0xA2, 0xD7, 0x9C, 0xD7, 0x90, 0x20, 0xD7, + 0x95, 0xD7, 0x95, 0xD7, 0xA2, 0xD7, 0x9C, 0xD7, 0x98, 0}, + // Russian + {0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 0xB5, + 0xD1, 0x82, 0x20, 0xD0, 0xBC, 0xD0, 0xB8, 0xD1, 0x80, 0}, + // Latin + {0x4D, 0x75, 0x6E, 0x64, 0x75, 0x73, 0x20, 0x73, 0x61, 0x6C, + 0x76, 0x65, 0}, + // Swahili + {0x68, 0x75, 0x6A, 0x61, 0x6D, 0x62, 0x6F, 0x20, 0x44, 0x75, + 0x6E, 0x69, 0x61, 0}, + // Icelandic + {0x48, 0x61, 0x6C, 0x6C, 0xC3, 0xB3, 0x20, 0x68, 0x65, 0x69, + 0x6D, 0x75, 0x72, 0}, + {0} +}; + +//---------------------------------------------------------------------------- +static int testHelloWorldEncoding() +{ + int ret = 0; + for(int i=0; helloWorldStrings[i][0] != 0; i++) + { + std::string str = reinterpret_cast<const char*>(helloWorldStrings[i]); + std::cout << str << std::endl; + std::wstring wstr = kwsys::Encoding::ToWide(str); + std::string str2 = kwsys::Encoding::ToNarrow(wstr); + if(!wstr.empty() && str != str2) + { + std::cout << "converted string was different: " << str2 << std::endl; + ret++; + } + } + return ret; +} + +static int testRobustEncoding() +{ + // test that the conversion functions handle invalid + // unicode correctly/gracefully + + int ret = 0; + char cstr[] = {(char)-1, 0}; + // this conversion could fail + std::wstring wstr = kwsys::Encoding::ToWide(cstr); + + wstr = kwsys::Encoding::ToWide(NULL); + if(wstr != L"") + { + const wchar_t* wcstr = wstr.c_str(); + std::cout << "ToWide(NULL) returned"; + for(size_t i=0; i<wstr.size(); i++) + { + std::cout << " " << std::hex << (int)wcstr[i]; + } + std::cout << std::endl; + ret++; + } + wstr = kwsys::Encoding::ToWide(""); + if(wstr != L"") + { + const wchar_t* wcstr = wstr.c_str(); + std::cout << "ToWide(\"\") returned"; + for(size_t i=0; i<wstr.size(); i++) + { + std::cout << " " << std::hex << (int)wcstr[i]; + } + std::cout << std::endl; + ret++; + } + +#ifdef WIN32 + // 16 bit wchar_t - we make an invalid surrogate pair + wchar_t cwstr[] = {0xD801, 0xDA00, 0}; + // this conversion could fail + std::string win_str = kwsys::Encoding::ToNarrow(cwstr); +#endif + + std::string str = kwsys::Encoding::ToNarrow(NULL); + if(str != "") + { + std::cout << "ToNarrow(NULL) returned " << str << std::endl; + ret++; + } + + str = kwsys::Encoding::ToNarrow(L""); + if(wstr != L"") + { + std::cout << "ToNarrow(\"\") returned " << str << std::endl; + ret++; + } + + return ret; +} + + +//---------------------------------------------------------------------------- +int testEncoding(int, char*[]) +{ + const char* loc = setlocale(LC_ALL, ""); + if(loc) + { + std::cout << "Locale: " << loc << std::endl; + } + else + { + std::cout << "Locale: None" << std::endl; + } + + int ret = 0; + + ret |= testHelloWorldEncoding(); + ret |= testRobustEncoding(); + + return ret; +} |