From c410e9182d322a8c095ef94fbadf4d8f541e6b98 Mon Sep 17 00:00:00 2001 From: Martin Doege Date: Thu, 26 Jun 2014 20:30:22 +0200 Subject: [PATCH] OS X compatibility fixes --- CMakeLists.txt | 20 ++++------ cmake/Modules/FindGettextLib.cmake | 12 ++++++ src/CMakeLists.txt | 33 +++++++++++++---- src/cguittfont/irrUString.h | 2 + src/jthread/jevent.h | 7 ++++ src/jthread/jsemaphore.h | 12 ++++++ src/jthread/pthread/jevent.cpp | 13 +++++++ src/jthread/pthread/jsemaphore.cpp | 59 ++++++++++++++++++++++++++++-- src/porting.cpp | 5 +-- src/porting.h | 26 +++++++++++-- 10 files changed, 158 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb701a076..da7e46923 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,11 +72,9 @@ if(WIN32) set(EXAMPLE_CONF_DIR ".") set(LOCALEDIR "locale") elseif(APPLE) - # Random placeholders; this isn't usually used and may not work - # See https://github.com/toabi/minetest-mac/ - set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}") - set(BINDIR "bin") - set(DOCDIR "share/doc/${PROJECT_NAME}") + set(SHAREDIR ".") + set(BINDIR "./bin") + set(DOCDIR "./doc/${PROJECT_NAME}") set(EXAMPLE_CONF_DIR ${DOCDIR}) set(LOCALEDIR "locale") elseif(UNIX) # Linux, BSD etc @@ -171,7 +169,7 @@ install(FILES "doc/menu_lua_api.txt" DESTINATION "${DOCDIR}") install(FILES "doc/mapformat.txt" DESTINATION "${DOCDIR}") install(FILES "minetest.conf.example" DESTINATION "${EXAMPLE_CONF_DIR}") -if(UNIX) +if(UNIX AND NOT APPLE) install(FILES "doc/minetest.6" "doc/minetestserver.6" DESTINATION "${MANDIR}/man6") install(FILES "misc/minetest.desktop" DESTINATION "${XDG_APPS_DIR}") install(FILES "misc/minetest.appdata.xml" DESTINATION "${APPDATADIR}") @@ -211,15 +209,13 @@ if(WIN32) # This might be needed for some installer #set(CPACK_PACKAGE_EXECUTABLES bin/minetest.exe "Minetest" bin/minetestserver.exe "Minetest Server") elseif(APPLE) - # TODO # see http://cmake.org/Wiki/CMake:CPackPackageGenerators#Bundle_.28OSX_only.29 - # set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION_STRING}-osx") - set(CPACK_PACKAGE_ICON "") + set(CPACK_PACKAGE_ICON ${CMAKE_CURRENT_SOURCE_DIR}/misc/mac/minetest-icon.icns) set(CPACK_BUNDLE_NAME ${PROJECT_NAME}) - set(CPACK_BUNDLE_ICON "") - set(CPACK_BUNDLE_PLIST "") - set(CPACK_BUNDLE_STARTUP_COMMAND "Contents/MacOS/${PROJECT_NAME}") + set(CPACK_BUNDLE_ICON ${CPACK_PACKAGE_ICON}) + set(CPACK_BUNDLE_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/misc/mac/Info.plist) + set(CPACK_BUNDLE_STARTUP_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/misc/mac/minetest-mac.sh) set(CPACK_GENERATOR "Bundle") else() set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION_STRING}-linux") diff --git a/cmake/Modules/FindGettextLib.cmake b/cmake/Modules/FindGettextLib.cmake index bc7ea367f..c6f731e04 100644 --- a/cmake/Modules/FindGettextLib.cmake +++ b/cmake/Modules/FindGettextLib.cmake @@ -16,6 +16,18 @@ FIND_PROGRAM(GETTEXT_MSGFMT PATHS "${CUSTOM_GETTEXT_PATH}/bin" DOC "path to msgfmt") +if(APPLE) + FIND_LIBRARY(GETTEXT_LIBRARY + NAMES libintl.a + PATHS "${CUSTOM_GETTEXT_PATH}/lib" + DOC "gettext *intl*.lib") + + FIND_LIBRARY(ICONV_LIBRARY + NAMES libiconv.dylib + PATHS "/usr/lib" + DOC "iconv lib") +endif(APPLE) + # modern Linux, as well as Mac, seem to not need require special linking # they do not because gettext is part of glibc # TODO check the requirements on other BSDs and older Linux diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f8aa75ea5..464070c24 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -162,7 +162,12 @@ else() endif(APPLE) endif(BUILD_CLIENT) find_package(ZLIB REQUIRED) - set(PLATFORM_LIBS -lpthread -lrt ${CMAKE_DL_LIBS}) + set(PLATFORM_LIBS -lpthread ${CMAKE_DL_LIBS}) + if(APPLE) + set(PLATFORM_LIBS "-framework CoreFoundation" ${PLATFORM_LIBS}) + else() + set(PLATFORM_LIBS -lrt ${PLATFORM_LIBS}) + endif(APPLE) #set(CLIENT_PLATFORM_LIBS -lXxf86vm) # This way Xxf86vm is found on OpenBSD too find_library(XXF86VM_LIBRARY Xxf86vm) @@ -504,7 +509,7 @@ set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin") if(BUILD_CLIENT) add_executable(${PROJECT_NAME} ${minetest_SRCS}) add_dependencies(${PROJECT_NAME} GenerateVersion) - target_link_libraries( + set(minetest_LIBS ${PROJECT_NAME} ${ZLIB_LIBRARIES} ${IRRLICHT_LIBRARY} @@ -522,6 +527,16 @@ if(BUILD_CLIENT) ${PLATFORM_LIBS} ${CLIENT_PLATFORM_LIBS} ) + if(APPLE) + target_link_libraries( + ${minetest_LIBS} + ${ICONV_LIBRARY} + ) + else() + target_link_libraries( + ${minetest_LIBS} + ) + endif() if(USE_CURL) target_link_libraries( ${PROJECT_NAME} @@ -605,7 +620,9 @@ if(MSVC) else() # Probably GCC - + if(APPLE) + SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pagezero_size 10000 -image_base 100000000" ) + endif() if(WARN_ALL) set(RELEASE_WARNING_FLAGS "-Wall") else() @@ -623,12 +640,12 @@ else() set(OTHER_FLAGS "-mthreads -fexceptions") endif() + set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${WARNING_FLAGS} ${OTHER_FLAGS} -ffast-math -Wall -pipe -funroll-loops") if(APPLE) - set(CMAKE_OSX_ARCHITECTURES i386 CACHE STRING "do not build for 64-bit" FORCE) - set(ARCH i386) - endif() - - set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${WARNING_FLAGS} ${OTHER_FLAGS} -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Os") + else() + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -fomit-frame-pointer") + endif(APPLE) set(CMAKE_CXX_FLAGS_DEBUG "-g -O1 -Wall ${WARNING_FLAGS} ${OTHER_FLAGS}") if(USE_GPROF) diff --git a/src/cguittfont/irrUString.h b/src/cguittfont/irrUString.h index 8d7a23aa4..32efaa683 100644 --- a/src/cguittfont/irrUString.h +++ b/src/cguittfont/irrUString.h @@ -45,6 +45,8 @@ #define __BYTE_ORDER 0 #define __LITTLE_ENDIAN 0 #define __BIG_ENDIAN 1 +#elif __MACH__ +#include #else #include #endif diff --git a/src/jthread/jevent.h b/src/jthread/jevent.h index d31d8e654..f97e09ca0 100644 --- a/src/jthread/jevent.h +++ b/src/jthread/jevent.h @@ -30,6 +30,11 @@ #ifdef _WIN32 #include +#elif __MACH__ +#include +#include +#include +#include #else #include #endif @@ -38,6 +43,8 @@ class Event { #ifdef _WIN32 HANDLE hEvent; +#elif __MACH__ + semaphore_t sem; #else sem_t sem; #endif diff --git a/src/jthread/jsemaphore.h b/src/jthread/jsemaphore.h index bdce2e4ae..53538da1c 100644 --- a/src/jthread/jsemaphore.h +++ b/src/jthread/jsemaphore.h @@ -24,6 +24,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #define MAX_SEMAPHORE_COUNT 1024 +#elif __MACH__ +#include +#include +#include +#include +#include +#include +#include #else #include #include @@ -44,9 +52,13 @@ public: private: #if defined(WIN32) HANDLE m_hSemaphore; +#elif __MACH__ + semaphore_t m_semaphore; #else sem_t m_semaphore; #endif + int semcount; }; + #endif /* JSEMAPHORE_H_ */ diff --git a/src/jthread/pthread/jevent.cpp b/src/jthread/pthread/jevent.cpp index 26a6fb05c..6a45a37d2 100644 --- a/src/jthread/pthread/jevent.cpp +++ b/src/jthread/pthread/jevent.cpp @@ -29,6 +29,19 @@ #define UNUSED(expr) do { (void)(expr); } while (0) +#ifdef __MACH__ +#undef sem_t +#define sem_t semaphore_t +#undef sem_init +#define sem_init(s, p, c) semaphore_create(mach_task_self(), (s), 0, (c)) +#undef sem_wait +#define sem_wait(s) semaphore_wait(*(s)) +#undef sem_post +#define sem_post(s) semaphore_signal(*(s)) +#undef sem_destroy +#define sem_destroy(s) semaphore_destroy(mach_task_self(), *(s)) +#endif + Event::Event() { int sem_init_retval = sem_init(&sem, 0, 0); assert(sem_init_retval == 0); diff --git a/src/jthread/pthread/jsemaphore.cpp b/src/jthread/pthread/jsemaphore.cpp index ee1431065..f6d7f022f 100644 --- a/src/jthread/pthread/jsemaphore.cpp +++ b/src/jthread/pthread/jsemaphore.cpp @@ -20,13 +20,33 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include "jthread/jsemaphore.h" +#ifdef __MACH__ +#include +#endif #define UNUSED(expr) do { (void)(expr); } while (0) +#ifdef __MACH__ +#undef sem_t +#undef sem_init +#undef sem_wait +#undef sem_post +#undef sem_destroy +#define sem_t semaphore_t +#define sem_init(s, p, c) semaphore_create(mach_task_self(), (s), 0, (c)) +#define sem_wait(s) semaphore_wait(*(s)) +#define sem_post(s) semaphore_signal(*(s)) +#define sem_destroy(s) semaphore_destroy(mach_task_self(), *(s)) +pthread_mutex_t semcount_mutex; +#endif + JSemaphore::JSemaphore() { int sem_init_retval = sem_init(&m_semaphore,0,0); assert(sem_init_retval == 0); UNUSED(sem_init_retval); +#ifdef __MACH__ + semcount = 0; +#endif } JSemaphore::~JSemaphore() { @@ -45,16 +65,32 @@ void JSemaphore::Post() { int sem_post_retval = sem_post(&m_semaphore); assert(sem_post_retval == 0); UNUSED(sem_post_retval); +#ifdef __MACH__ + pthread_mutex_lock(&semcount_mutex); + semcount++; + pthread_mutex_unlock(&semcount_mutex); +#endif } void JSemaphore::Wait() { int sem_wait_retval = sem_wait(&m_semaphore); assert(sem_wait_retval == 0); UNUSED(sem_wait_retval); +#ifdef __MACH__ + pthread_mutex_lock(&semcount_mutex); + semcount--; + pthread_mutex_unlock(&semcount_mutex); +#endif } bool JSemaphore::Wait(unsigned int time_ms) { +#ifdef __MACH__ + mach_timespec_t waittime; + waittime.tv_sec = time_ms / 1000; + waittime.tv_nsec = 1000000 * (time_ms % 1000); +#else struct timespec waittime; +#endif struct timeval now; if (gettimeofday(&now, NULL) == -1) { @@ -62,15 +98,26 @@ bool JSemaphore::Wait(unsigned int time_ms) { return false; } +#ifndef __MACH__ waittime.tv_nsec = ((time_ms % 1000) * 1000 * 1000) + (now.tv_usec * 1000); waittime.tv_sec = (time_ms / 1000) + (waittime.tv_nsec / (1000*1000*1000)) + now.tv_sec; waittime.tv_nsec %= 1000*1000*1000; +#endif errno = 0; - int sem_wait_retval = sem_timedwait(&m_semaphore,&waittime); +#ifdef __MACH__ + int sem_wait_retval = semaphore_timedwait(m_semaphore, waittime); +#else + int sem_wait_retval = sem_timedwait(&m_semaphore, &waittime); +#endif if (sem_wait_retval == 0) { +#ifdef __MACH__ + pthread_mutex_lock(&semcount_mutex); + semcount--; + pthread_mutex_unlock(&semcount_mutex); +#endif return true; } else { @@ -81,10 +128,14 @@ bool JSemaphore::Wait(unsigned int time_ms) { } int JSemaphore::GetValue() { - int retval = 0; - sem_getvalue(&m_semaphore,&retval); - +#ifdef __MACH__ + pthread_mutex_lock(&semcount_mutex); + retval = semcount; + pthread_mutex_unlock(&semcount_mutex); +#else + sem_getvalue(&m_semaphore, &retval); +#endif return retval; } diff --git a/src/porting.cpp b/src/porting.cpp index d1e3cdd70..3c2a5c824 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -25,10 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" -#if defined(__APPLE__) - #include - #include "CoreFoundation/CoreFoundation.h" -#elif defined(__FreeBSD__) +#if defined(__FreeBSD__) #include #include #elif defined(_WIN32) diff --git a/src/porting.h b/src/porting.h index 383d4377a..b5a5d00f2 100644 --- a/src/porting.h +++ b/src/porting.h @@ -123,6 +123,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #define PADDING(x, y) ((ALIGNOF(y) - ((uintptr_t)(x) & (ALIGNOF(y) - 1))) & (ALIGNOF(y) - 1)) +#if defined(__APPLE__) + #include + #include +#endif + namespace porting { @@ -220,9 +225,13 @@ void initIrrlicht(irr::IrrlichtDevice * ); } #else // Posix - #include - #include - +#include +#include +#ifdef __MACH__ +#include +#include +#endif + inline u32 getTimeS() { struct timeval tv; @@ -247,7 +256,18 @@ void initIrrlicht(irr::IrrlichtDevice * ); inline u32 getTimeNs() { struct timespec ts; + // from http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x +#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time + clock_serv_t cclock; + mach_timespec_t mts; + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + ts.tv_sec = mts.tv_sec; + ts.tv_nsec = mts.tv_nsec; +#else clock_gettime(CLOCK_REALTIME, &ts); +#endif return ts.tv_sec * 1000000000 + ts.tv_nsec; }