cameron314 / readerwriterqueue

A fast single-producer, single-consumer lock-free queue for C++

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Fails to build on MacOS if using C++17 and deployment target < 10.14

szarvas opened this issue · comments

Prior to 981a1d3 I could use XCode with the following settings

  • macOS Deployment Target: 10.11
  • C++ Language Dialect: C++17

Since 981a1d3 I get the following compile error:
"Aligned allocation function of type 'void *(std::size_t, std::align_val_t)' is only available on macOS 10.14 or newer"

The error can be triggered by e.g.
auto queue = new moodycamel::ReaderWriterQueue<int>();

I can still successfully build the readerwriterqueue related files if I

  1. either drop C++17 dialect to C++14,
  2. or change deployment target to 10.14

Neither is ideal, so right now my best option is to stick to prior 981a1d3.

I don't fully understand why the allocation function requirement goes away when switching back to C++14, but I thought it could be used to still support macOS 10.11 and C++17 in the future commits.

Might be a compiler bug. Thanks for reporting, I'll commit a workaround soon.

OK, I understand the error better now. It seems C++17 introduced a new new operator that accepts an alignment specifier for over-aligned types (like ReaderWriterQueue). For macOS, the implementation of this operator seems to depend on an allocation function in a shared library (libcxx?) that for some reason is not up to date in older macOS versions.

Before C++17, such over-aligned types would simply not be aligned when allocated on the heap; this generates warnings on MSVC, for example.

In short, C++17 is incompatible with older versions of macOS, and the alignment of this queue causes an accidental dependence on a C++17 feature.

I can remove the alignment specifier but it was useful (even when not aligned in pre-C++17 heap allocations) to force padding to a multiple of 64 and at the very least document a suggested alignment. Instead, I will remove the alignment just for C++17 on macOS :-)

Let me know if this fixes your issue (I don't have a Mac on which to reproduce).

Sure, thank you for the speedy response. I'll check it out tomorrow.

It fixes the issue in the original project, where I've encountered it, but TARGET_OS_MAC doesn't seem to be defined in simple console projects. It seems to be a part of TargetConditionals.h, so that needs to be included first.

I think this conditional could be used:
#if defined (__APPLE__) && defined (__MACH__) && __cplusplus >= 201703L

which seems to work in console projects too. The __MACH__ definition distinguishes between MacOS and iOS. It's only available in the first. I have no idea whether iOS is affected by this.

I tried to find a macro that could be used to detect whether the deployment target is >= 10.14, sadly I couldn't find any. I'm sorry this optimization has to be disabled for the entirety of MacOS, but I don't see another way right now.

I'm still asking around about this, I'll get back shortly.

Okay, I actually found something, for which you need to include CoreFoundation.h, which is really old so this is probably not a problem.

I have tested the following conditional definitions successfully in my projects.

#if defined (__APPLE__) && defined (__MACH__) && __cplusplus >= 201703L

// This is required to find out what deployment target we are using
#include <CoreFoundation/CoreFoundation.h>

#if !(defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_14)
// C++17 new(size_t, align_val_t) is not backwards-compatible with older versions of macOS, so we can't support over-alignment in this case
#define MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE
#endif

#endif

#ifndef MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE
#define MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE AE_ALIGN(MOODYCAMEL_CACHE_LINE_SIZE)
#endif

I wouldn't be surprised if it was broken on iOS too, but since you've found the exact code to check the version I'll use that for now. Better to be more specific when possible. Thanks!