From 6f24474309d6f76343cc90d7421bec38e7086c76 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Tue, 10 Oct 2017 19:33:42 +0200 Subject: [PATCH 1/8] Replace MemoryManager implementation with rpmalloc Fixes #3865 --- .gitmodules | 3 + include/MemoryManager.h | 108 ++------------ src/3rdparty/CMakeLists.txt | 4 + src/3rdparty/rpmalloc/CMakeLists.txt | 28 ++++ src/3rdparty/rpmalloc/rpmalloc | 1 + src/CMakeLists.txt | 12 ++ src/core/MemoryManager.cpp | 204 ++++----------------------- src/core/Mixer.cpp | 1 + src/core/MixerWorkerThread.cpp | 1 + src/core/ProjectRenderer.cpp | 1 + src/core/main.cpp | 5 - 11 files changed, 92 insertions(+), 276 deletions(-) create mode 100644 .gitmodules create mode 100644 src/3rdparty/CMakeLists.txt create mode 100644 src/3rdparty/rpmalloc/CMakeLists.txt create mode 160000 src/3rdparty/rpmalloc/rpmalloc diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000000..10785ef9a9d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/3rdparty/rpmalloc/rpmalloc"] + path = src/3rdparty/rpmalloc/rpmalloc + url = https://github.com/rampantpixels/rpmalloc.git diff --git a/include/MemoryManager.h b/include/MemoryManager.h index ef6c0abbfc6..23561e4c0ac 100644 --- a/include/MemoryManager.h +++ b/include/MemoryManager.h @@ -1,6 +1,7 @@ /* - * MemoryManager.h - A lightweight, generic memory manager for LMMS + * MemoryManager.h * + * Copyright (c) 2017 Lukas W * Copyright (c) 2014 Vesa Kivimäki * Copyright (c) 2007-2014 Tobias Doerffel * @@ -26,81 +27,22 @@ #ifndef MEMORY_MANAGER_H #define MEMORY_MANAGER_H -#include -#include -#include -#include "MemoryHelper.h" -#include "export.h" - -class QReadWriteLock; - -const int MM_CHUNK_SIZE = 64; // granularity of managed memory -const int MM_INITIAL_CHUNKS = 1024 * 1024; // how many chunks to allocate at startup - TODO: make configurable -const int MM_INCREMENT_CHUNKS = 16 * 1024; // min. amount of chunks to increment at a time - -struct MemoryPool -{ - void * m_pool; - char * m_free; - size_t m_chunks; - QMutex m_mutex; - - MemoryPool() : - m_pool( NULL ), - m_free( NULL ), - m_chunks( 0 ) - {} - - MemoryPool( size_t chunks ) : - m_chunks( chunks ) - { - m_free = reinterpret_cast( MemoryHelper::alignedMalloc( chunks ) ); - memset( m_free, 1, chunks ); - } - - MemoryPool( const MemoryPool & mp ) : - m_pool( mp.m_pool ), - m_free( mp.m_free ), - m_chunks( mp.m_chunks ), - m_mutex() - {} - - MemoryPool & operator = ( const MemoryPool & mp ) - { - m_pool = mp.m_pool; - m_free = mp.m_free; - m_chunks = mp.m_chunks; - return *this; - } - - void * getChunks( int chunksNeeded ); - void releaseChunks( void * ptr, int chunks ); -}; +#include +#include -struct PtrInfo -{ - int chunks; - MemoryPool * memPool; -}; - -typedef QVector MemoryPoolVector; -typedef QHash PointerInfoMap; +#include "export.h" class EXPORT MemoryManager { public: - static bool init(); + struct ThreadGuard + { + ThreadGuard(); + ~ThreadGuard(); + }; + static void * alloc( size_t size ); static void free( void * ptr ); - static int extend( int chunks ); // returns index of created pool (for use by alloc) - static void cleanup(); - -private: - static MemoryPoolVector s_memoryPools; - static QReadWriteLock s_poolMutex; - - static PointerInfoMap s_pointerInfo; - static QMutex s_pointerMutex; }; template @@ -147,32 +89,4 @@ static void operator delete[] ( void * ptr ) \ // and just for symmetry... #define MM_FREE( ptr ) MemoryManager::free( ptr ) - - -// for debugging purposes - -#define MM_OPERATORS_DEBUG \ -public: \ -static void * operator new ( size_t size ) \ -{ \ - qDebug( "MM_OPERATORS_DEBUG: new called for %d bytes", size ); \ - return MemoryManager::alloc( size ); \ -} \ -static void * operator new[] ( size_t size ) \ -{ \ - qDebug( "MM_OPERATORS_DEBUG: new[] called for %d bytes", size ); \ - return MemoryManager::alloc( size ); \ -} \ -static void operator delete ( void * ptr ) \ -{ \ - qDebug( "MM_OPERATORS_DEBUG: delete called for %p", ptr ); \ - MemoryManager::free( ptr ); \ -} \ -static void operator delete[] ( void * ptr ) \ -{ \ - qDebug( "MM_OPERATORS_DEBUG: delete[] called for %p", ptr ); \ - MemoryManager::free( ptr ); \ -} - - #endif diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt new file mode 100644 index 00000000000..4067413e3d5 --- /dev/null +++ b/src/3rdparty/CMakeLists.txt @@ -0,0 +1,4 @@ +set(CMAKE_C_FLAGS "") +set(CMAKE_CXX_FLAGS "") + +ADD_SUBDIRECTORY(rpmalloc) diff --git a/src/3rdparty/rpmalloc/CMakeLists.txt b/src/3rdparty/rpmalloc/CMakeLists.txt new file mode 100644 index 00000000000..fb9e19cf3bc --- /dev/null +++ b/src/3rdparty/rpmalloc/CMakeLists.txt @@ -0,0 +1,28 @@ +add_library(rpmalloc STATIC + rpmalloc/rpmalloc/rpmalloc.c + rpmalloc/rpmalloc/rpmalloc.h +) + +target_include_directories(rpmalloc PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/rpmalloc/rpmalloc +) + +if (NOT LMMS_BUILD_WIN32) + target_compile_definitions(rpmalloc + PRIVATE -D_GNU_SOURCE + ) +endif() + +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + target_compile_definitions(rpmalloc + PRIVATE -DENABLE_ASSERTS -DENABLE_VALIDATE_ARGS + ) +endif() + +option(LMMS_ENABLE_MALLOC_STATS "Enables statistics for rpmalloc" OFF) + +if (LMMS_ENABLE_MALLOC_STATS) + target_compile_definitions(rpmalloc + PRIVATE -DENABLE_STATISTICS + ) +endif() diff --git a/src/3rdparty/rpmalloc/rpmalloc b/src/3rdparty/rpmalloc/rpmalloc new file mode 160000 index 00000000000..f3b2e630871 --- /dev/null +++ b/src/3rdparty/rpmalloc/rpmalloc @@ -0,0 +1 @@ +Subproject commit f3b2e630871c32288e7b501877c6d99d20171c20 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 154ff4f85ae..f50ce06d01a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,5 @@ +ADD_SUBDIRECTORY(3rdparty) + CONFIGURE_FILE("lmmsconfig.h.in" "${CMAKE_BINARY_DIR}/lmmsconfig.h") CONFIGURE_FILE("lmmsversion.h.in" "${CMAKE_BINARY_DIR}/lmmsversion.h") @@ -147,7 +149,9 @@ SET(LMMS_REQUIRED_LIBS ${SAMPLERATE_LIBRARIES} ${SNDFILE_LIBRARIES} ${EXTRA_LIBRARIES} + rpmalloc ) + # Expose required libs for tests binary SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS} PARENT_SCOPE) @@ -155,6 +159,14 @@ TARGET_LINK_LIBRARIES(lmms ${LMMS_REQUIRED_LIBS} ) +FOREACH(LIB ${LMMS_REQUIRED_LIBS}) + GET_TARGET_PROPERTY(INCLUDE_DIRS ${LIB} INTERFACE_INCLUDE_DIRECTORIES) + if (INCLUDE_DIRS) + TARGET_INCLUDE_DIRECTORIES(lmmsobjs PRIVATE ${INCLUDE_DIRS}) + ENDIF() +ENDFOREACH() + + # Required libs for debug msys builds IF(LMMS_BUILD_MSYS AND CMAKE_BUILD_TYPE STREQUAL "Debug") TARGET_LINK_LIBRARIES(lmms QtCore4 QtGui4 QtXml4) diff --git a/src/core/MemoryManager.cpp b/src/core/MemoryManager.cpp index 4196d1aacd6..6c16be0d2ed 100644 --- a/src/core/MemoryManager.cpp +++ b/src/core/MemoryManager.cpp @@ -1,8 +1,7 @@ /* - * MemoryManager.cpp - A lightweight, generic memory manager for LMMS + * MemoryManager.cpp * - * Copyright (c) 2014 Vesa Kivimäki - * Copyright (c) 2007-2014 Tobias Doerffel + * Copyright (c) 2017 Lukas W * * This file is part of LMMS - https://lmms.io * @@ -25,197 +24,54 @@ #include "MemoryManager.h" -#include +#include +#include "rpmalloc.h" -MemoryPoolVector MemoryManager::s_memoryPools; -QReadWriteLock MemoryManager::s_poolMutex; -PointerInfoMap MemoryManager::s_pointerInfo; -QMutex MemoryManager::s_pointerMutex; - - -bool MemoryManager::init() -{ - s_memoryPools.reserve( 64 ); - s_pointerInfo.reserve( 4096 ); - // construct first MemoryPool and allocate memory - MemoryPool m ( MM_INITIAL_CHUNKS ); - m.m_pool = MemoryHelper::alignedMalloc( MM_INITIAL_CHUNKS * MM_CHUNK_SIZE ); - s_memoryPools.append( m ); - return true; -} - - -void * MemoryManager::alloc( size_t size ) -{ - if( !size ) - { - return NULL; +/// Global static object handling rpmalloc intializing and finalizing +struct MemoryManagerGlobalGuard { + MemoryManagerGlobalGuard() { + rpmalloc_initialize(); } - - int requiredChunks = size / MM_CHUNK_SIZE + ( size % MM_CHUNK_SIZE > 0 ? 1 : 0 ); - - MemoryPool * mp = NULL; - void * ptr = NULL; - - MemoryPoolVector::iterator it = s_memoryPools.begin(); - - s_poolMutex.lockForRead(); - while( it != s_memoryPools.end() && !ptr ) - { - ptr = ( *it ).getChunks( requiredChunks ); - if( ptr ) - { - mp = &( *it ); - } - ++it; - } - s_poolMutex.unlock(); - - if( ptr ) - { - s_pointerMutex.lock(); - PtrInfo p; - p.chunks = requiredChunks; - p.memPool = mp; - s_pointerInfo[ptr] = p; - s_pointerMutex.unlock(); - return ptr; + ~MemoryManagerGlobalGuard() { + rpmalloc_finalize(); } +} static mm_global_guard; - // can't find enough chunks in existing pools, so - // create a new pool that is guaranteed to have enough chunks - int moreChunks = qMax( requiredChunks, MM_INCREMENT_CHUNKS ); - int i = MemoryManager::extend( moreChunks ); - mp = &s_memoryPools[i]; - ptr = s_memoryPools[i].getChunks( requiredChunks ); - if( ptr ) - { - s_pointerMutex.lock(); - PtrInfo p; - p.chunks = requiredChunks; - p.memPool = mp; - s_pointerInfo[ptr] = p; - s_pointerMutex.unlock(); - return ptr; - } - // still no luck? something is horribly wrong - qFatal( "MemoryManager.cpp: Couldn't allocate memory: %d chunks asked", requiredChunks ); - return NULL; +namespace { +static thread_local size_t thread_guard_depth; } - -void MemoryManager::free( void * ptr ) +MemoryManager::ThreadGuard::ThreadGuard() { - if( !ptr ) - { - return; // Null pointer deallocations are OK but do not need to be handled + if (thread_guard_depth++ == 0) { + rpmalloc_thread_initialize(); } - - // fetch info on the ptr and remove - s_pointerMutex.lock(); - if( ! s_pointerInfo.contains( ptr ) ) // if we have no info on ptr, fail loudly - { - qFatal( "MemoryManager: Couldn't find pointer info for pointer: %p", ptr ); - } - PtrInfo p = s_pointerInfo[ptr]; - s_pointerInfo.remove( ptr ); - s_pointerMutex.unlock(); - - p.memPool->releaseChunks( ptr, p.chunks ); -} - - -int MemoryManager::extend( int chunks ) -{ - MemoryPool m ( chunks ); - m.m_pool = MemoryHelper::alignedMalloc( chunks * MM_CHUNK_SIZE ); - - s_poolMutex.lockForWrite(); - s_memoryPools.append( m ); - int i = s_memoryPools.size() - 1; - s_poolMutex.unlock(); - - return i; } - -void MemoryManager::cleanup() +MemoryManager::ThreadGuard::~ThreadGuard() { - for( MemoryPoolVector::iterator it = s_memoryPools.begin(); it != s_memoryPools.end(); ++it ) - { - MemoryHelper::alignedFree( ( *it ).m_pool ); - MemoryHelper::alignedFree( ( *it ).m_free ); + if (--thread_guard_depth == 0) { + rpmalloc_thread_initialize(); } } +static thread_local MemoryManager::ThreadGuard local_mm_thread_guard{}; -void * MemoryPool::getChunks( int chunksNeeded ) +void* MemoryManager::alloc(size_t size) { - if( chunksNeeded > m_chunks ) // not enough chunks in this pool? - { - return NULL; - } - - m_mutex.lock(); - - // now find out if we have a long enough sequence of chunks in this pool - char last = 0; - intptr_t n = 0; - intptr_t index = -1; - bool found = false; - - for( int i = 0; i < m_chunks; ++i ) - { - if( m_free[i] ) - { - if( !last ) - { - index = i; - } - - ++n; - if( n >= chunksNeeded ) - { - found = true; - break; - } - } - else - { - n = 0; - } - - last = m_free[i]; - } - - if( found ) // if enough chunks found, return pointer to chunks - { - // set chunk flags to false so we know the chunks are in use - for( intptr_t i = 0; i < chunksNeeded; ++i ) - { - m_free[ index + i ] = 0; - } - m_mutex.unlock(); - return (char*)m_pool + ( index * MM_CHUNK_SIZE ); - } - m_mutex.unlock(); - return NULL; // out of stock, come again tomorrow! + // Reference local thread guard to ensure it is initialized. + // Compilers may optimize the instance away otherwise. + Q_UNUSED(&local_mm_thread_guard); + Q_ASSERT_X(rpmalloc_is_thread_initialized(), "MemoryManager::alloc", "Thread not initialized"); + return rpmalloc(size); } -void MemoryPool::releaseChunks( void * ptr, int chunks ) +void MemoryManager::free(void * ptr) { - m_mutex.lock(); - - intptr_t start = ( (intptr_t)ptr - (intptr_t)m_pool ) / MM_CHUNK_SIZE; - if( start < 0 ) - { - qFatal( "MemoryManager: error at releaseChunks() - corrupt pointer info?" ); - } - - memset( &m_free[ start ], 1, chunks ); - - m_mutex.unlock(); + Q_UNUSED(&local_mm_thread_guard); + Q_ASSERT_X(rpmalloc_is_thread_initialized(), "MemoryManager::free", "Thread not initialized"); + return rpfree(ptr); } diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 53cacbe6386..c99d3ab8cb5 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -36,6 +36,7 @@ #include "NotePlayHandle.h" #include "ConfigManager.h" #include "SamplePlayHandle.h" +#include "MemoryHelper.h" // platform-specific audio-interface-classes #include "AudioAlsa.h" diff --git a/src/core/MixerWorkerThread.cpp b/src/core/MixerWorkerThread.cpp index dfcc1ff6a51..e8c6bd61c08 100644 --- a/src/core/MixerWorkerThread.cpp +++ b/src/core/MixerWorkerThread.cpp @@ -153,6 +153,7 @@ void MixerWorkerThread::startAndWaitForJobs() void MixerWorkerThread::run() { + MemoryManager::ThreadGuard mmThreadGuard; Q_UNUSED(mmThreadGuard); disable_denormals(); QMutex m; diff --git a/src/core/ProjectRenderer.cpp b/src/core/ProjectRenderer.cpp index 7588401c2da..56e9c01c0a9 100644 --- a/src/core/ProjectRenderer.cpp +++ b/src/core/ProjectRenderer.cpp @@ -163,6 +163,7 @@ void ProjectRenderer::startProcessing() void ProjectRenderer::run() { + MemoryManager::ThreadGuard mmThreadGuard; Q_UNUSED(mmThreadGuard); #if 0 #ifdef LMMS_BUILD_LINUX #ifdef LMMS_HAVE_SCHED_H diff --git a/src/core/main.cpp b/src/core/main.cpp index b36ca0055c3..fc8dd5de2c8 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -57,7 +57,6 @@ #include #include "MainApplication.h" -#include "MemoryManager.h" #include "ConfigManager.h" #include "NotePlayHandle.h" #include "embed.h" @@ -203,7 +202,6 @@ void fileCheck( QString &file ) int main( int argc, char * * argv ) { // initialize memory managers - MemoryManager::init(); NotePlayHandleManager::init(); // intialize RNG @@ -930,9 +928,6 @@ int main( int argc, char * * argv ) Engine::destroy(); } - // cleanup memory managers - MemoryManager::cleanup(); - // ProjectRenderer::updateConsoleProgress() doesn't return line after render if( coreOnly ) { From 17b41780966d8c1245cceab0245070e0261fe7b8 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Tue, 10 Oct 2017 19:47:15 +0200 Subject: [PATCH 2/8] rpmalloc: Explicitly specify C11 mode --- src/3rdparty/rpmalloc/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/3rdparty/rpmalloc/CMakeLists.txt b/src/3rdparty/rpmalloc/CMakeLists.txt index fb9e19cf3bc..9efd729307c 100644 --- a/src/3rdparty/rpmalloc/CMakeLists.txt +++ b/src/3rdparty/rpmalloc/CMakeLists.txt @@ -1,3 +1,5 @@ +set(CMAKE_C_FLAGS "-std=c11") + add_library(rpmalloc STATIC rpmalloc/rpmalloc/rpmalloc.c rpmalloc/rpmalloc/rpmalloc.h From 14cde39dcd36a40828f0f3e75cf334ea5d07c1f0 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Tue, 10 Oct 2017 21:23:42 +0200 Subject: [PATCH 3/8] Fix rpmalloc compile flags, fix missing includes --- include/AutomatableModel.h | 1 + include/PluginFactory.h | 1 + src/3rdparty/rpmalloc/CMakeLists.txt | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index dd9bd7680cf..cdfdffccf62 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -25,6 +25,7 @@ #ifndef AUTOMATABLE_MODEL_H #define AUTOMATABLE_MODEL_H +#include #include #include "JournallingObject.h" diff --git a/include/PluginFactory.h b/include/PluginFactory.h index b2d0131ad89..fb3e8ea9412 100644 --- a/include/PluginFactory.h +++ b/include/PluginFactory.h @@ -28,6 +28,7 @@ #include #include +#include #include #include "export.h" diff --git a/src/3rdparty/rpmalloc/CMakeLists.txt b/src/3rdparty/rpmalloc/CMakeLists.txt index 9efd729307c..b71af279b81 100644 --- a/src/3rdparty/rpmalloc/CMakeLists.txt +++ b/src/3rdparty/rpmalloc/CMakeLists.txt @@ -17,7 +17,7 @@ endif() if (CMAKE_BUILD_TYPE STREQUAL "Debug") target_compile_definitions(rpmalloc - PRIVATE -DENABLE_ASSERTS -DENABLE_VALIDATE_ARGS + PRIVATE -DENABLE_ASSERTS=1 -DENABLE_VALIDATE_ARGS=1 ) endif() @@ -25,6 +25,6 @@ option(LMMS_ENABLE_MALLOC_STATS "Enables statistics for rpmalloc" OFF) if (LMMS_ENABLE_MALLOC_STATS) target_compile_definitions(rpmalloc - PRIVATE -DENABLE_STATISTICS + PRIVATE -DENABLE_STATISTICS=1 ) endif() From 7f5bc19523c82d0b07c9f7f4b14465edc9b922b5 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Wed, 11 Oct 2017 09:55:06 +0200 Subject: [PATCH 4/8] rpmalloc: Use develop branch for MinGW fix See https://github.com/rampantpixels/rpmalloc/issues/30 --- src/3rdparty/rpmalloc/rpmalloc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty/rpmalloc/rpmalloc b/src/3rdparty/rpmalloc/rpmalloc index f3b2e630871..70726c24486 160000 --- a/src/3rdparty/rpmalloc/rpmalloc +++ b/src/3rdparty/rpmalloc/rpmalloc @@ -1 +1 @@ -Subproject commit f3b2e630871c32288e7b501877c6d99d20171c20 +Subproject commit 70726c244860a41ee9c5c4b41eec999b5e622eed From 3ae888925c3e65d95ae5611f61774006a90a39e7 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Wed, 11 Oct 2017 10:26:05 +0200 Subject: [PATCH 5/8] Fix rpmalloc thread guard destructor --- src/core/MemoryManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/MemoryManager.cpp b/src/core/MemoryManager.cpp index 6c16be0d2ed..d0932e4f17b 100644 --- a/src/core/MemoryManager.cpp +++ b/src/core/MemoryManager.cpp @@ -53,7 +53,7 @@ MemoryManager::ThreadGuard::ThreadGuard() MemoryManager::ThreadGuard::~ThreadGuard() { if (--thread_guard_depth == 0) { - rpmalloc_thread_initialize(); + rpmalloc_thread_finalize(); } } From f7ed3fc1b7771b0e7c65151b80588dc56c3a22b6 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Wed, 11 Oct 2017 10:38:53 +0200 Subject: [PATCH 6/8] Carla: Add missing include --- plugins/carlabase/carla.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/carlabase/carla.h b/plugins/carlabase/carla.h index 59a34a76495..6431e5300de 100644 --- a/plugins/carlabase/carla.h +++ b/plugins/carlabase/carla.h @@ -25,6 +25,8 @@ #ifndef CARLA_H #define CARLA_H +#include + #include "CarlaNative.h" #include "Instrument.h" From 743a05e9bc86a0237852d917d2752bb8088c0c85 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Wed, 11 Oct 2017 10:43:52 +0200 Subject: [PATCH 7/8] rpmalloc: Actually update to latest develop --- src/3rdparty/rpmalloc/rpmalloc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty/rpmalloc/rpmalloc b/src/3rdparty/rpmalloc/rpmalloc index 70726c24486..2e0479192b8 160000 --- a/src/3rdparty/rpmalloc/rpmalloc +++ b/src/3rdparty/rpmalloc/rpmalloc @@ -1 +1 @@ -Subproject commit 70726c244860a41ee9c5c4b41eec999b5e622eed +Subproject commit 2e0479192b8dfb15e0084969fdf06208cffbfd09 From 5ae1026cd34604da06daa4c277a4f7bb28d11db2 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Wed, 11 Oct 2017 11:07:30 +0200 Subject: [PATCH 8/8] Travis: Specify OSX image for Qt5 build --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 76fc62b91f7..773aed79f6e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ matrix: - env: QT5=True TARGET_OS=win32 - env: QT5=True TARGET_OS=win64 - os: osx + osx_image: xcode8.2 env: QT5=True before_install: - . ${TRAVIS_BUILD_DIR}/.travis/${TRAVIS_OS_NAME}.${TARGET_OS}.before_install.sh