diff --git a/fmus/gain/CMakeLists.txt b/fmus/gain/CMakeLists.txt index 1ae28d1..84cc091 100644 --- a/fmus/gain/CMakeLists.txt +++ b/fmus/gain/CMakeLists.txt @@ -9,6 +9,9 @@ project(${FMU_NAME}) if(WIN32) set(FMU_PLATFORM win) set(FMU_SO_SUFFIX ".dll") +elseif(APPLE) + set(FMU_PLATFORM darwin) + set(FMU_SO_SUFFIX ".dylib") elseif(UNIX) set(FMU_PLATFORM linux) set(FMU_SO_SUFFIX ".so") diff --git a/fmus/sinusGenerator/CMakeLists.txt b/fmus/sinusGenerator/CMakeLists.txt index 3ae058c..072a4ad 100644 --- a/fmus/sinusGenerator/CMakeLists.txt +++ b/fmus/sinusGenerator/CMakeLists.txt @@ -9,6 +9,9 @@ project(${FMU_NAME}) if(WIN32) set(FMU_PLATFORM win) set(FMU_SO_SUFFIX ".dll") +elseif(APPLE) + set(FMU_PLATFORM darwin) + set(FMU_SO_SUFFIX ".dylib") elseif(UNIX) set(FMU_PLATFORM linux) set(FMU_SO_SUFFIX ".so") diff --git a/fmus/vectorSum/CMakeLists.txt b/fmus/vectorSum/CMakeLists.txt index 0979314..8b20887 100644 --- a/fmus/vectorSum/CMakeLists.txt +++ b/fmus/vectorSum/CMakeLists.txt @@ -9,6 +9,9 @@ project(${FMU_NAME}) if(WIN32) set(FMU_PLATFORM win) set(FMU_SO_SUFFIX ".dll") +elseif(APPLE) + set(FMU_PLATFORM darwin) + set(FMU_SO_SUFFIX ".dylib") elseif(UNIX) set(FMU_PLATFORM linux) set(FMU_SO_SUFFIX ".so") diff --git a/libs/util/CMakeLists.txt b/libs/util/CMakeLists.txt index e8254b8..72f06de 100644 --- a/libs/util/CMakeLists.txt +++ b/libs/util/CMakeLists.txt @@ -28,10 +28,10 @@ if(WIN32) ) else() set(UTIL_PLATFORM_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/src/linux/libs.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/linux/os.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/linux/paths.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/linux/string.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/unix/libs.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/unix/os.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/unix/paths.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/unix/string.c" ) endif() diff --git a/libs/util/src/linux/libs.c b/libs/util/src/unix/libs.c similarity index 87% rename from libs/util/src/linux/libs.c rename to libs/util/src/unix/libs.c index efe7c2c..89733af 100644 --- a/libs/util/src/linux/libs.c +++ b/libs/util/src/unix/libs.c @@ -31,13 +31,20 @@ static McxStatus __mcx_dll_load(DllHandle * handle, const char * dllPath, int fl return RETURN_OK; } - McxStatus mcx_dll_load(DllHandle * handle, const char * dllPath) { +#if(__APPLE__) + return __mcx_dll_load(handle, dllPath, RTLD_LAZY|RTLD_LOCAL); +#else return __mcx_dll_load(handle, dllPath, RTLD_LAZY|RTLD_LOCAL|RTLD_DEEPBIND); +#endif } McxStatus mcx_dll_load_global(DllHandle * handle, const char * dllPath) { +#if(__APPLE__) + return __mcx_dll_load(handle, dllPath, RTLD_LAZY|RTLD_GLOBAL); +#else return __mcx_dll_load(handle, dllPath, RTLD_LAZY|RTLD_GLOBAL|RTLD_DEEPBIND); +#endif } void * mcx_dll_get_function(DllHandle dllHandle, const char* functionName) { @@ -55,4 +62,4 @@ void mcx_dll_free(DllHandle dllHandle) #ifdef __cplusplus } /* closing brace for extern "C" */ -#endif /* __cplusplus */ \ No newline at end of file +#endif /* __cplusplus */ diff --git a/libs/util/src/linux/os.c b/libs/util/src/unix/os.c similarity index 100% rename from libs/util/src/linux/os.c rename to libs/util/src/unix/os.c diff --git a/libs/util/src/linux/paths.c b/libs/util/src/unix/paths.c similarity index 100% rename from libs/util/src/linux/paths.c rename to libs/util/src/unix/paths.c diff --git a/libs/util/src/linux/string.c b/libs/util/src/unix/string.c similarity index 100% rename from libs/util/src/linux/string.c rename to libs/util/src/unix/string.c diff --git a/mcx/CMakeLists.txt b/mcx/CMakeLists.txt index 3d6957c..5d93ce5 100644 --- a/mcx/CMakeLists.txt +++ b/mcx/CMakeLists.txt @@ -20,7 +20,7 @@ target_link_libraries(${EXECUTABLE_NAME} PRIVATE mcx_common) source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/" PREFIX "Source Files" FILES ${MCX_EXE_SOURCES}) -if(UNIX) +if(UNIX AND NOT APPLE) set_target_properties(${EXECUTABLE_NAME} PROPERTIES LINK_OPTIONS -Wl,--exclude-libs,ALL) endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2de6bcc..732cb75 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,7 +43,7 @@ file(GLOB UTIL_HEADERS "util/*.h") if(WIN32) file(GLOB UTIL_SRC "util/win/*.c" "util/*.c" "util/common/*.c") else() - file(GLOB UTIL_SRC "util/linux/*.c" "util/*.c" "util/common/*.c") + file(GLOB UTIL_SRC "util/unix/*.c" "util/*.c" "util/common/*.c") endif() @@ -94,7 +94,7 @@ target_compile_definitions( ) -if(UNIX) +if(UNIX AND NOT APPLE) set_target_properties(mcx_common PROPERTIES LINK_OPTIONS -Wl,--exclude-libs,ALL) endif() diff --git a/src/objects/ObjectContainer.c b/src/objects/ObjectContainer.c index 610d724..58f2db7 100644 --- a/src/objects/ObjectContainer.c +++ b/src/objects/ObjectContainer.c @@ -82,8 +82,14 @@ typedef struct { void * arg; } StrCmpCtx; -static int ObjectContainerElementCmp(const void * first, const void * second, void * ctx) { - StrCmpCtx * data = (StrCmpCtx *)ctx; +#if(__APPLE__) +static int ObjectContainerElementCmp(void *ctx, const void *first, + const void *second) { +#else +static int ObjectContainerElementCmp(const void * first, const void * second, + void * ctx) { +#endif + StrCmpCtx *data = (StrCmpCtx *)ctx; ObjectContainerElement * firstElement = (ObjectContainerElement *) first; ObjectContainerElement * secondElement = (ObjectContainerElement *) second; diff --git a/src/util/linux/stdlib.c b/src/util/linux/stdlib.c deleted file mode 100644 index ef36f9f..0000000 --- a/src/util/linux/stdlib.c +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2020 AVL List GmbH and others - * - * This program and the accompanying materials are made available under the - * terms of the Apache Software License 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -#include "CentralParts.h" - -#include "util/stdlib.h" - -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - - -void mcx_sort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg) { - qsort_r(base, nmemb, size, compar, arg); -} - - -#ifdef __cplusplus -} /* closing brace for extern "C" */ -#endif /* __cplusplus */ \ No newline at end of file diff --git a/src/util/mutex.h b/src/util/mutex.h index fbaea8e..41960c2 100644 --- a/src/util/mutex.h +++ b/src/util/mutex.h @@ -11,8 +11,11 @@ #ifndef MCX_UTIL_MUTEX_H #define MCX_UTIL_MUTEX_H -#include "CentralParts.h" +#if(__APPLE__) +#include "sys/types.h" +#endif +#include "CentralParts.h" #if defined (ENABLE_MT) #ifdef __cplusplus diff --git a/src/util/stdlib.h b/src/util/stdlib.h index 52332c2..55a1764 100644 --- a/src/util/stdlib.h +++ b/src/util/stdlib.h @@ -32,8 +32,14 @@ extern "C" { * is the context passed to mcx_sort. * @param arg context for the compar function */ -void mcx_sort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg); +#if(__APPLE__) +void mcx_sort(void *base, size_t nmemb, size_t size, + int (*compar)(void *, const void *, const void *), void *arg); +#else +void mcx_sort(void *base, size_t nmemb, size_t size, + int (*compar)(const void *, const void *, void *), void *arg); +#endif int mcx_natural_sort_cmp(const char * left, const char * right); /** diff --git a/src/util/threads.h b/src/util/threads.h index 8bf9d1e..d8ffc34 100644 --- a/src/util/threads.h +++ b/src/util/threads.h @@ -21,6 +21,10 @@ extern "C" { #include +#if(__APPLE__) +#include +#endif + #if defined(OS_WINDOWS) #define _WINSOCKAPI_ // stops windows.h including winsock.h #include diff --git a/src/util/linux/events.c b/src/util/unix/events.c similarity index 100% rename from src/util/linux/events.c rename to src/util/unix/events.c diff --git a/src/util/linux/mutex.c b/src/util/unix/mutex.c similarity index 100% rename from src/util/linux/mutex.c rename to src/util/unix/mutex.c diff --git a/src/util/linux/signals.c b/src/util/unix/signals.c similarity index 100% rename from src/util/linux/signals.c rename to src/util/unix/signals.c diff --git a/src/util/linux/socket.c b/src/util/unix/socket.c similarity index 100% rename from src/util/linux/socket.c rename to src/util/unix/socket.c diff --git a/src/util/unix/stdlib.c b/src/util/unix/stdlib.c new file mode 100644 index 0000000..69d7068 --- /dev/null +++ b/src/util/unix/stdlib.c @@ -0,0 +1,43 @@ +/******************************************************************************** + * Copyright (c) 2020 AVL List GmbH and others + * + * This program and the accompanying materials are made available under the + * terms of the Apache Software License 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#include "CentralParts.h" + +#include "util/stdlib.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#if (__APPLE__) +void mcx_sort(void *base, size_t nmemb, size_t size, + int (*compar)(void *, const void *, const void *), void *arg) { + // FreeBSD added qsort_r in Sept 2002, but with a poor interface. In + // 2008 GNU fixed the interface and decided the compatibility breakage + // was worth it following ISO. Linux is GNU. OS X is a mish-mash of many + // things, but for C it follows BSD. As a result, we have difference in + // the non-standard qsort_r function. + // See https://stackoverflow.com/a/39561369 for details. + qsort_r(base, nmemb, size, arg, compar); +} +#else +void mcx_sort(void *base, size_t nmemb, size_t size, + int (*compar)(const void *, const void *, void *), void *arg) { + qsort_r(base, nmemb, size, compar, arg); +} +#endif + + +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif /* __cplusplus */ \ No newline at end of file diff --git a/src/util/linux/threads.c b/src/util/unix/threads.c similarity index 55% rename from src/util/linux/threads.c rename to src/util/unix/threads.c index 434cad1..2c9f6aa 100644 --- a/src/util/linux/threads.c +++ b/src/util/unix/threads.c @@ -44,6 +44,66 @@ int mcx_thread_join(McxThread handle, long * ret) { return pthread_join(handle, (void * *) ret); } +struct args { + int joined; + pthread_t td; + pthread_mutex_t mtx; + pthread_cond_t cond; + void **res; +}; + +static void *waiter(void *ap) +{ + struct args *args = ap; + pthread_join(args->td, args->res); + pthread_mutex_lock(&args->mtx); + args->joined = 1; + pthread_mutex_unlock(&args->mtx); + pthread_cond_signal(&args->cond); + return 0; +} + +// Portable implementation of `pthread_timedjoin_np()`. Inspired +// and copied from https://stackoverflow.com/a/11552244. As this +// implementation is more costly than `pthread_timedjoin_np()`, +// we only use this portable version for Apple platforms. +int pthread_timedjoin_p(pthread_t td, void **res, struct timespec *ts) +{ + pthread_t tmp; + int ret; + struct args args = { .td = td, .res = res }; + + pthread_mutex_init(&args.mtx, 0); + pthread_cond_init(&args.cond, 0); + pthread_mutex_lock(&args.mtx); + + ret = pthread_create(&tmp, 0, waiter, &args); + if (!ret) { + do { + ret = pthread_cond_timedwait(&args.cond, &args.mtx, ts); + } while (!args.joined && ret != ETIMEDOUT); + } + + pthread_mutex_unlock(&args.mtx); + + pthread_cancel(tmp); + pthread_join(tmp, 0); + + pthread_cond_destroy(&args.cond); + pthread_mutex_destroy(&args.mtx); + + return args.joined ? 0 : ret; +} + +int pthread_timedjoin(pthread_t handle, void **ret, struct timespec *time) +{ +#if(__APPLE__) + return pthread_timedjoin_p(handle, ret, time); +#else + return pthread_timedjoin_np(handle, ret, time); +#endif +} + int mcx_thread_join_with_timeout(McxThread handle, long * ret, int secs) { struct timespec time; int status = 0; @@ -53,7 +113,7 @@ int mcx_thread_join_with_timeout(McxThread handle, long * ret, int secs) { time.tv_sec += secs; - status = pthread_timedjoin_np(handle, (void * *) ret, &time); + status = pthread_timedjoin(handle, (void * *) ret, &time); if (status) { const char * cause = NULL; @@ -79,4 +139,4 @@ int mcx_thread_join_with_timeout(McxThread handle, long * ret, int secs) { } /* closing brace for extern "C" */ #endif /* __cplusplus */ -#endif // ENABLE_MT \ No newline at end of file +#endif // ENABLE_MT diff --git a/src/util/linux/time.c b/src/util/unix/time.c similarity index 100% rename from src/util/linux/time.c rename to src/util/unix/time.c