diff --git a/cmake/SfizzConfig.cmake b/cmake/SfizzConfig.cmake index 715144a9d..9d134fe90 100644 --- a/cmake/SfizzConfig.cmake +++ b/cmake/SfizzConfig.cmake @@ -1,6 +1,7 @@ include(CMakeDependentOption) include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) +include(CheckCXXSourceCompiles) include(GNUWarnings) set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard to be used") @@ -52,7 +53,30 @@ endif() # Set macOS compatibility level if(APPLE) - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9") +endif() + +# If using C++17, check if aligned-new has runtime support on the platform; +# on macOS, this depends on the deployment target. +if(CMAKE_CXX_STANDARD LESS 17) + # not necessary on older C++, it will call ordinary new and delete + set(SFIZZ_IMPLEMENT_CXX17_ALIGNED_NEW_SUPPORT FALSE) +else() + check_cxx_source_compiles(" +struct Test { alignas(1024) int z; }; +int main() { new Test; return 0; } +" SFIZZ_HAVE_CXX17_ALIGNED_NEW) + # if support is absent, sfizz will provide a substitute implementation + if(SFIZZ_HAVE_CXX17_ALIGNED_NEW) + set(SFIZZ_IMPLEMENT_CXX17_ALIGNED_NEW_SUPPORT FALSE) + else() + # on macOS, this mandatory flag tells that allocation functions are user-provided + check_cxx_compiler_flag("-faligned-allocation" SFIZZ_HAVE_CXXFLAG_FALIGNED_ALLOCATION) + if(SFIZZ_HAVE_CXXFLAG_FALIGNED_ALLOCATION) + add_compile_options("$<$:-faligned-allocation>") + endif() + set(SFIZZ_IMPLEMENT_CXX17_ALIGNED_NEW_SUPPORT TRUE) + endif() endif() # Do not define macros `min` and `max` diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 555d8af61..13f17efd3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -193,7 +193,8 @@ set(SFIZZ_SOURCES sfizz/effects/impl/ResonantStringAVX.cpp sfizz/effects/impl/ResonantArray.cpp sfizz/effects/impl/ResonantArraySSE.cpp - sfizz/effects/impl/ResonantArrayAVX.cpp) + sfizz/effects/impl/ResonantArrayAVX.cpp + sfizz/utility/c++17/AlignedMemorySupport.cpp) include(SfizzSIMDSourceFiles) sfizz_add_simd_sources(SFIZZ_SOURCES ".") @@ -303,6 +304,9 @@ endif() if(SFIZZ_RELEASE_ASSERTS) target_compile_definitions(sfizz_internal PUBLIC "SFIZZ_ENABLE_RELEASE_ASSERT=1") endif() +if(SFIZZ_IMPLEMENT_CXX17_ALIGNED_NEW_SUPPORT) + target_compile_definitions(sfizz_internal PRIVATE "SFIZZ_IMPLEMENT_CXX17_ALIGNED_NEW_SUPPORT=1") +endif() sfizz_enable_fast_math(sfizz_internal) # Check that sfizz and cmake-side definitions are matching diff --git a/src/sfizz/utility/c++17/AlignedMemorySupport.cpp b/src/sfizz/utility/c++17/AlignedMemorySupport.cpp new file mode 100644 index 000000000..834f207f0 --- /dev/null +++ b/src/sfizz/utility/c++17/AlignedMemorySupport.cpp @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BSD-2-Clause + +// This code is part of the sfizz library and is licensed under a BSD 2-clause +// license. You should have receive a LICENSE.md file along with the code. +// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz + +#if defined(SFIZZ_IMPLEMENT_CXX17_ALIGNED_NEW_SUPPORT) +#include +#if defined(_WIN32) +# include +#else +# include +#endif + +void* operator new(std::size_t count, std::align_val_t al, const std::nothrow_t&) noexcept +{ + void *ptr; +#if defined(_WIN32) + ptr = ::_aligned_malloc(count, static_cast(al)); +#else + if (::posix_memalign(&ptr, static_cast(al), count) != 0) + ptr = nullptr; +#endif + return ptr; +} + +void operator delete(void* ptr, std::align_val_t, const std::nothrow_t&) noexcept +{ +#if defined(_WIN32) + ::_aligned_free(ptr); +#else + ::free(ptr); +#endif +} + +//------------------------------------------------------------------------------ + +void* operator new(std::size_t count, std::align_val_t al) +{ + void *ptr = operator new(count, al, std::nothrow); + if (!ptr) + throw std::bad_alloc(); + return ptr; +} + +void operator delete(void* ptr, std::align_val_t al) noexcept +{ + operator delete(ptr, al, std::nothrow); +} + +//------------------------------------------------------------------------------ + +void* operator new[](std::size_t count, std::align_val_t al) +{ + return operator new(count, al); +} + +void* operator new[](std::size_t count, std::align_val_t al, const std::nothrow_t& tag) noexcept +{ + return operator new(count, al, tag); +} + +void operator delete[](void* ptr, std::align_val_t al) noexcept +{ + operator delete(ptr, al); +} + +void operator delete[](void* ptr, std::align_val_t al, const std::nothrow_t& tag) noexcept +{ + operator delete(ptr, al, tag); +} + + +#endif // defined(SFIZZ_IMPLEMENT_CXX17_ALIGNED_NEW_SUPPORT) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9ae219dbd..fa7084584 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -56,6 +56,10 @@ set(SFIZZ_TEST_SOURCES add_executable(sfizz_tests ${SFIZZ_TEST_SOURCES}) target_link_libraries(sfizz_tests PRIVATE sfizz::internal sfizz::static sfizz::spin_mutex sfizz::jsl sfizz::filesystem) +if(APPLE AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS "10.12") + # workaround for incomplete C++17 runtime on macOS + target_compile_definitions(sfizz_tests PRIVATE "CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS") +endif() sfizz_enable_lto_if_needed(sfizz_tests) sfizz_enable_fast_math(sfizz_tests) catch_discover_tests(sfizz_tests)