Metal-cpp undefined symbol?

lil Abi
3 min readSep 6, 2022

What the heck is “_NSBundleResourceRequestLowDiskSpaceNotification”?

If you are running on an earlier version of MacOS and trying to build an application using the Metal-cpp library, chances are that your build will probably fail. But what exactly is going on?

The Problem

linker output error

The image above displays output debug build information; informing the programmer that the linker has failed to find a definition for the following declaration: “_NSBundleResourceRequestLowDiskSpaceNotification”. Locating the declaration for the missing symbol was tricky at first since it was hidden behind a macro 😒.

Macro Statement
Macro Definition
_NS_PRIVATE_DEF_CONST(NS::NotificationName,BundleResouceRequestLowDiskNotification);

is a macro that fully expands into:

extern "C" __attribute__((visibility("default"))) NS::NotificationName const NSBundleResourceRequestLowDiskSpaceNotification __attribute__((weak_import));NS::NotificationName const NS::BundleResourceRequestLowDiskSpaceNotification = (nullptr != NSBundleResourceRequestLowDiskSpaceNotification) ? NS::BundleResourceRequestLowDiskSpaceNotification : nullptr;

Looks like a mess. But what is even the purpose of this macro? And what is it trying to even accomplish overall?

First we need to take a step back and understand WHY this error is even occurring in the first place. A quick search in the Metal documentation with the keyword, “NSBundleResourceRequestLowDiskSpaceNotification”, explains that this is global variable that notifies if the amount of disk space is getting low. The documentation also shows that this feature is not available on macOS (may be available if you have Mac Catalyst installed). The version of macOS my system is currently running is 10.14.6 (the holy era of macOS, LONG LIVE OSX 🖖). Since this variable does not exist on my system, the extern declaration of “NSBundleResourceRequestLowDiskSpaceNotification” will not be able to link to the definition since it doesn’t exist in the linked libraries (Foundation framework). And since the definition cannot be found, “NS::BundleResourceRequestLowDiskSpaceNotification” needs to be set to nullptr. What this macro basically does is that it finds the location of the object that “NSBundleResourceRequestLowDiskSpaceNotification” is linked too and assigns it to “NS::NSBundleResourceRequestLowDiskSpaceNotification” so the notification can be polled.

The Solution

The easy way to fix this problem is to copy the macro “_NS_PRIVATE_DEF_CONST” rename it to “_NS_PRIVATE_DEF_CONST_LEGACY” and add a nullptr initialization.

Like below:

This method works for any missing symbol that is similar to the error above. Just remember to check for nullptrs in your code!

Thanks for reading!

--

--