diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c29e9f338..0eacbad0bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,122 +1,122 @@ cmake_minimum_required(VERSION 2.6) project(KDevPlatform) set(KDE4_BUILD_TESTS "ON" CACHE "BOOL" "Enable building of tests" FORCE ) set(CMAKE_MODULE_PATH ${KDevPlatform_SOURCE_DIR}/cmake/modules) set(KDEVPLATFORM_VERSION_MAJOR 1) set(KDEVPLATFORM_VERSION_MINOR 3) set(KDEVPLATFORM_VERSION_PATCH 1) set(KDE_MIN_VERSION "4.5.0") find_package(KDE4 4.5.0 REQUIRED) set(KDEVPLATFORM_LIB_VERSION 5.0.0) set(KDEVPLATFORM_LIB_SOVERSION 5) find_package(ZLIB REQUIRED) include (KDE4Defaults) include (MacroWriteBasicCMakeVersionFile) include (MacroLibrary) # Make sure that we're having RPATH on our installed libs, else using kdevelop # from prefixes like $HOME/kdevelop breaks # Code taken from FindKDE4Internal.cmake for KDE 4.5 list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${LIB_INSTALL_DIR}" _isSystemLibDir) if("${_isSystemLibDir}" STREQUAL "-1") set(CMAKE_INSTALL_RPATH "${LIB_INSTALL_DIR}") endif("${_isSystemLibDir}" STREQUAL "-1") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) set(KOMPARE_FOUND FALSE) #macro_optional_find_package(Kompare) macro_bool_to_01(KOMPARE_FOUND HAVE_KOMPARE) #macro_log_feature(KOMPARE_FOUND "Kompare" "KPart to view file differences." # "http://www.caffeinated.me.uk/kompare/" FALSE "" # "Required for difference checking. From KDE SDK package, KDE 4.3.61 or higher needed.") -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config-kdevplatform.h.cmake - ${CMAKE_CURRENT_BINARY_DIR}/config-kdevplatform.h ) add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS}) add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS -DQURL_NO_CAST_FROM_QSTRING) -if(CMAKE_COMPILER_IS_GNUCXX) - # TODO: Remove when LTS for g++ < 4.3 has ended. - # See also: languages/cpp/parser/parser.h - macro_ensure_version("4.3.0" "${_gcc_version}" GCC_IS_NEWER_THAN_4_3) - if (GCC_IS_NEWER_THAN_4_3) - message(STATUS "Enabling c++0x support for unordered map") - add_definitions( -std=c++0x ) # For unordered_map - else(GCC_IS_NEWER_THAN_4_3) - add_definitions( -DGXX_LT_4_3 ) - endif (GCC_IS_NEWER_THAN_4_3) -endif(CMAKE_COMPILER_IS_GNUCXX) -if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - # TODO: version check? - add_definitions( -std=c++0x ) -endif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + +# TODO: Remove when LTS for g++ < 4.3 has ended. +# See also: languages/cpp/parser/parser.h in KDevelop +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + include(CheckIncludeFileCXX) + check_include_file_cxx(unordered_map HAVE_UNORDERED_MAP) + + if(HAVE_UNORDERED_MAP) + message(STATUS "Enabling c++0x support for unordered map") + add_definitions( -std=c++0x ) + else(HAVE_UNORDERED_MAP) + check_include_file_cxx(ext/hash_map HAVE_EXT_HASH_MAP) + endif(HAVE_UNORDERED_MAP) +endif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config-kdevplatform.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/config-kdevplatform.h ) include_directories(${KDevPlatform_SOURCE_DIR} ${KDevPlatform_BINARY_DIR} ${KDE4_INCLUDES}) # Now set the usual KDEVPLATFORM_XXX_LIBRARIES variable so we can more easily move plugins around set(KDEVPLATFORM_SUBLIME_LIBRARIES sublime) set(KDEVPLATFORM_INTERFACES_LIBRARIES kdevplatforminterfaces) set(KDEVPLATFORM_LANGUAGE_LIBRARIES kdevplatformlanguage) set(KDEVPLATFORM_PROJECT_LIBRARIES kdevplatformproject) set(KDEVPLATFORM_UTIL_LIBRARIES kdevplatformutil) set(KDEVPLATFORM_OUTPUTVIEW_LIBRARIES kdevplatformoutputview) set(KDEVPLATFORM_VCS_LIBRARIES kdevplatformvcs) set(KDEVPLATFORM_SHELL_LIBRARIES kdevplatformshell) set(KDEVPLATFORM_TESTS_LIBRARIES kdevplatformtests) set(KDEVPLATFORM_DEBUGGER_LIBRARIES kdevplatformdebugger) set(KDEVPLATFORM_DOCUMENTATION_LIBRARIES kdevplatformdocumentation) add_subdirectory(sublime) add_subdirectory(interfaces) add_subdirectory(project) add_subdirectory(language) add_subdirectory(shell) add_subdirectory(util) add_subdirectory(outputview) add_subdirectory(vcs) add_subdirectory(pics) #macro_optional_add_subdirectory(doc) add_subdirectory(debugger) add_subdirectory(documentation) add_subdirectory(tests) add_subdirectory(plugins) macro_write_basic_cmake_version_file( ${KDevPlatform_BINARY_DIR}/KDevPlatformConfigVersion.cmake ${KDEVPLATFORM_VERSION_MAJOR} ${KDEVPLATFORM_VERSION_MINOR} ${KDEVPLATFORM_VERSION_PATCH} ) configure_file( "${KDevPlatform_SOURCE_DIR}/KDevPlatformConfig.cmake.in" "${KDevPlatform_BINARY_DIR}/KDevPlatformConfig.cmake" @ONLY ) configure_file( "${KDevPlatform_SOURCE_DIR}/kdevplatformversion.h.cmake" "${KDevPlatform_BINARY_DIR}/kdevplatformversion.h" @ONLY ) if(KDE4_USE_COMMON_CMAKE_PACKAGE_CONFIG_DIR) set(_kdevplatform_CONFIG_DEST "${LIB_INSTALL_DIR}/cmake/kdevplatform") else(KDE4_USE_COMMON_CMAKE_PACKAGE_CONFIG_DIR) set(_kdevplatform_CONFIG_DEST "${LIB_INSTALL_DIR}/kdevplatform") endif(KDE4_USE_COMMON_CMAKE_PACKAGE_CONFIG_DIR) install( FILES "${KDevPlatform_BINARY_DIR}/kdevplatformversion.h" DESTINATION "${INCLUDE_INSTALL_DIR}/kdevplatform" ) install( FILES "${KDevPlatform_BINARY_DIR}/KDevPlatformConfig.cmake" "${KDevPlatform_BINARY_DIR}/KDevPlatformConfigVersion.cmake" DESTINATION "${_kdevplatform_CONFIG_DEST}" ) install( EXPORT KDevPlatformTargets DESTINATION "${_kdevplatform_CONFIG_DEST}" NAMESPACE KDevPlatformImport__ FILE KDevPlatformTargets.cmake ) # Put this last, so it can use _kdevplatform_CONFIG_DEST add_subdirectory(cmake) include(CTest) # CTestCustom.cmake has to be in the CTEST_BINARY_DIR. # in the KDE build system, this is the same as CMAKE_BINARY_DIR. configure_file(${CMAKE_SOURCE_DIR}/CTestCustom.cmake ${CMAKE_BINARY_DIR}/CTestCustom.cmake) diff --git a/config-kdevplatform.h.cmake b/config-kdevplatform.h.cmake index 6737e06473..1ec2ad5a63 100644 --- a/config-kdevplatform.h.cmake +++ b/config-kdevplatform.h.cmake @@ -1,2 +1,8 @@ /* Define to 1 if you have Kompare support, 0 otherwise */ #define HAVE_KOMPARE @HAVE_KOMPARE@ + +/* Define to 1 if the unordered_map header is present, 0 otherwise */ +#define HAVE_UNORDERED_MAP @HAVE_UNORDERED_MAP@ + +/* Define to 1 if the ext/hash_map header is present, 0 otherwise */ +#define HAVE_EXT_HASH_MAP @HAVE_EXT_HASH_MAP@ diff --git a/language/editor/modificationrevision.cpp b/language/editor/modificationrevision.cpp index ac8a85213a..ee0d510dd1 100644 --- a/language/editor/modificationrevision.cpp +++ b/language/editor/modificationrevision.cpp @@ -1,178 +1,179 @@ /* Copyright 2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "config-kdevplatform.h" #include "modificationrevision.h" #include #include #include -#if defined(Q_CC_MSVC) -#include -using namespace stdext; -#elif defined GXX_LT_4_3 -#include -using namespace __gnu_cxx; -#else // C++0X +#if defined(HAVE_UNORDERED_MAP) // C++0X // TODO: Replace hash_map with unordered map when support for G++ < 4.3 has // ended. This class was added as a temporary workaround, to get rid of // hash_map related warnings for g++ >= 4.3. #include template, class _Pred = std::equal_to<_Key>, class _Alloc = std::allocator > > class hash_map : public std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> { }; +#elif defined(HAVE_EXT_HASH_MAP) +#include +using namespace __gnu_cxx; +#elif defined(Q_CC_MSVC) +#include +using namespace stdext; #endif #include "../duchain/indexedstring.h" #include "modificationrevisionset.h" #include ///@todo Listen to filesystem changes (together with the project manager) and call fileModificationCache().clear(...) when a file has changed namespace KDevelop { const int cacheModificationTimesForSeconds = 30; struct IndexedStringHash { uint operator() (const KDevelop::IndexedString& str) const { return str.hash(); } #ifdef Q_CC_MSVC bool operator() (const KDevelop::IndexedString& lhs, const KDevelop::IndexedString& rhs) const { return lhs < rhs; } enum { // parameters for hash table bucket_size = 4, // 0 < bucket_size min_buckets = 8}; // min_buckets = 2 ^^ N, 0 < N #endif }; QMutex fileModificationTimeCacheMutex(QMutex::Recursive); struct FileModificationCache { timeval m_readTime; QDateTime m_modificationTime; }; typedef hash_map FileModificationMap; FileModificationMap& fileModificationCache() { static FileModificationMap cache; return cache; } typedef hash_map OpenDocumentRevisionsMap; OpenDocumentRevisionsMap& openDocumentsRevisionMap() { static OpenDocumentRevisionsMap map; return map; } QDateTime fileModificationTimeCached( const IndexedString& fileName ) { timeval currentTime; gettimeofday(¤tTime, 0); FileModificationMap::const_iterator it = fileModificationCache().find( fileName ); if( it != fileModificationCache().end() ) { ///Use the cache for X seconds timeval age; timersub(¤tTime, &(*it).second.m_readTime, &age); if( age.tv_sec < cacheModificationTimesForSeconds ) return (*it).second.m_modificationTime; } QFileInfo fileInfo( fileName.str() ); fileModificationCache()[fileName].m_readTime = currentTime; fileModificationCache()[fileName].m_modificationTime = fileInfo.lastModified(); return fileInfo.lastModified(); } void ModificationRevision::clearModificationCache(const IndexedString& fileName) { ModificationRevisionSet::clearCache(); ///@todo Make the cache management more clever (don't clear the whole) QMutexLocker lock(&fileModificationTimeCacheMutex); FileModificationMap::iterator it = fileModificationCache().find(fileName); if(it != fileModificationCache().end()) fileModificationCache().erase(it); } ModificationRevision ModificationRevision::revisionForFile(const IndexedString& url) { QMutexLocker lock(&fileModificationTimeCacheMutex); ModificationRevision ret(fileModificationTimeCached(url)); OpenDocumentRevisionsMap::const_iterator it = openDocumentsRevisionMap().find(url); if(it != openDocumentsRevisionMap().end()) ret.revision = (*it).second; return ret; } void ModificationRevision::clearEditorRevisionForFile(const KDevelop::IndexedString& url) { ModificationRevisionSet::clearCache(); ///@todo Make the cache management more clever (don't clear the whole) QMutexLocker lock(&fileModificationTimeCacheMutex); if(openDocumentsRevisionMap().find(url) != openDocumentsRevisionMap().end()) openDocumentsRevisionMap().erase(url); } void ModificationRevision::setEditorRevisionForFile(const KDevelop::IndexedString& url, int revision) { ModificationRevisionSet::clearCache(); ///@todo Make the cache management more clever (don't clear the whole) QMutexLocker lock(&fileModificationTimeCacheMutex); openDocumentsRevisionMap().erase(url); openDocumentsRevisionMap().insert(std::make_pair(url, revision)); Q_ASSERT(revisionForFile(url).revision == revision); } ModificationRevision::ModificationRevision( const QDateTime& modTime , int revision_ ) : modificationTime(modTime.toTime_t()), revision(revision_) { } bool ModificationRevision::operator <( const ModificationRevision& rhs ) const { return modificationTime < rhs.modificationTime || (modificationTime == rhs.modificationTime && revision < rhs.revision); } bool ModificationRevision::operator ==( const ModificationRevision& rhs ) const { return modificationTime == rhs.modificationTime && revision == rhs.revision; } bool ModificationRevision::operator !=( const ModificationRevision& rhs ) const { return modificationTime != rhs.modificationTime || revision != rhs.revision; } QString ModificationRevision::toString() const { return QString("%1 (rev %2)").arg(QDateTime::fromTime_t(modificationTime).time().toString()).arg(revision); } } kdbgstream& operator<< (kdbgstream& s, const KDevelop::ModificationRevision& rev) { s << rev.toString(); return s; }