Dov
Dov

Reputation: 16166

How to call os_log_error from High Sierra (10.13)

I've been using Apple's Unified Logging System, which was working perfectly on macOS 10.12. But now when I target the 10.13 SDK (and run on 10.12), os_log_error gives me a SIGABRT and I get this error logged to the output console:

dyld: Symbol not found: __os_log_error_impl
  Referenced from: /Users/dfrankel/Library/Developer/Xcode/DerivedData/UnrarKit-dlssapvyjlrhkufjcxzwiiojfals/Build/Products/Debug/UnrarKit.framework/Versions/A/UnrarKit (which was built for Mac OS X 10.13)
  Expected in: /usr/lib/libSystem.B.dylib

I'm getting this in my unit tests whenever os_log_error and os_log_fault are called, but the other os_log* macros all run fine.

I tried manually adding libSystem.B.tbd to the framework target, and also to the unit test target, which didn't make a difference.

Upvotes: 1

Views: 827

Answers (1)

Dov
Dov

Reputation: 16166

The os_log_error and os_log_fault macros both changed in the 10.13 SDK to have more complicated behavior. The others were left alone. I pasted the updated macro below, for reference.

#if OS_LOG_TARGET_HAS_10_13_FEATURES
#define os_log_error(log, format, ...) __extension__({ \
    os_log_t _log_tmp = (log); \
    os_log_type_t _type_tmp = OS_LOG_TYPE_ERROR; \
    if (os_log_type_enabled(_log_tmp, _type_tmp)) { \
        OS_LOG_CALL_WITH_FORMAT(_os_log_error_impl, \
                (&__dso_handle, _log_tmp, _type_tmp), format, ##__VA_ARGS__); \
    } \
})
#else
#define os_log_error(log, format, ...) \
        os_log_with_type(log, OS_LOG_TYPE_ERROR, format, ##__VA_ARGS__)
#endif // OS_LOG_TARGET_HAS_10_13_FEATURES

Since my target is a framework, It's possible targets may use it from older OSes, so the only way around this that I could see is to do a runtime check of the OS version, and then conditionally select which macro to call.

BOOL isAtLeast10_13SDK;

#define MyLogError(format, ...) \
    if (isAtLeast10_13SDK) os_log_error(my_log, format, ##__VA_ARGS__); \
    else os_log_with_type(my_log, OS_LOG_TYPE_ERROR, format, ##__VA_ARGS__);
#define MyLogFault(format, ...) \
    if (isAtLeast10_13SDK) os_log_fault(my_log, format, ##__VA_ARGS__); \
    else os_log_with_type(my_log, OS_LOG_TYPE_FAULT, format, ##__VA_ARGS__);

+ (void)initialize {
        NSOperatingSystemVersion minVersion;
#if TARGET_OS_IPHONE
        minVersion.majorVersion = 11;
        minVersion.minorVersion = 0;
        minVersion.patchVersion = 0;
#else
        minVersion.majorVersion = 10;
        minVersion.minorVersion = 13;
        minVersion.patchVersion = 0;
#endif
        isAtLeast10_13SDK = [[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:minVersion];
}

Upvotes: 2

Related Questions