Zig failed to find private framework on macOS
Zig Version
0.12.0-dev.185+49075d205
Steps to Reproduce and Observed Behavior
I have a program to use CoreBrightness like this in my build.zig:
exe.linkSystemLibrary("objc");
exe.addFrameworkPath(.{ .path = "/System/Library/PrivateFrameworks" });
exe.linkFramework("CoreBrightness");
It works on 0.12.0-dev.47+0461a64a9, but fails in latest zig.
$ zig build
zig build-exe night-shift Debug native: error: error: unable to find framework 'CoreBrightness'. searched paths:
/System/Library/PrivateFrameworks/CoreBrightness.framework/CoreBrightness.tbd
/System/Library/PrivateFrameworks/CoreBrightness.framework/CoreBrightness.dylib
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/CoreBrightness.framework/CoreBrightness.tbd
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/CoreBrightness.framework/CoreBrightness.dylib
Expected Behavior
Build successfully.
This is what I got when use otool against my program built with earlier Zig:
$ otool -L zig-out/bin/night-shift
zig-out/bin/night-shift:
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.100.3)
/System/Library/PrivateFrameworks/CoreBrightness.framework/Versions/A/CoreBrightness (compatibility version 1.0.0, current version 1.0.0)
Just hit this on 0.14.0 trying to link kperf:
exe.addSystemFrameworkPath(b.path(try std.fs.path.relativePosix(b.allocator, ".", "/System/Library/PrivateFrameworks")));
exe.linkFramework("kperf");
$ zig build
error: error: unable to find framework 'kperf'. searched paths:
/System/Library/PrivateFrameworks/kperf.framework/kperf.tbd
/System/Library/PrivateFrameworks/kperf.framework/kperf.dylib
/System/Library/PrivateFrameworks/kperf.framework/kperf
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/kperf.framework/kperf.tbd
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/kperf.framework/kperf.dylib
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/kperf.framework/kperf
Meanwhile, kperf is safe and sound:
$ ls /System/Library/PrivateFrameworks/kperf.framework
Resources Versions kperf
I'll try the good old dlopen way with std.DynLib. But I do wonder how could this break. I mean, it's a framework finding error not even a linking one.
@tensorush I finally workaround this issue like this, it seems the primary frameworks are in Xcode.app.
const macos_private_framework = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/PrivateFrameworks/";
exe.addFrameworkPath(.{ .cwd_relative = macos_private_framework });
Yeah, I was able to link, too, but with Xcode CLI:
lib.addSystemFrameworkPath(.{ .cwd_relative = "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/PrivateFrameworks" });
It's better for private frameworks SDK path to be searched by default along with the frameworks path.
Then, this issue could be closed, because this isn't really a bug, just a confusion as to what the correct private framework path is.
It's better for private frameworks SDK path to be searched by default along with the frameworks path.
I don't know exactly, and the same example written in C will compile OK using clang -F/System/Library/PrivateFrameworks ..., so it seems the clang will automatically figure out where private frameworks are.
Tbh /System/Library/PrivateFrameworks doesn't seem correct.
In case of kperf, there's a symlink to Versions/Current/kperf but there's no kperf there.
$ ls -l /System/Library/PrivateFrameworks/kperf.framework/
total 0
lrwxr-xr-x 1 root wheel 26 Feb 4 19:57 Resources -> Versions/Current/Resources
drwxr-xr-x 4 root wheel 128 Feb 4 19:57 Versions
lrwxr-xr-x 1 root wheel 22 Feb 4 19:57 kperf -> Versions/Current/kperf
$ ls -l /System/Library/PrivateFrameworks/kperf.framework/Versions/
total 0
drwxr-xr-x 4 root wheel 128 Feb 4 19:57 A
lrwxr-xr-x 1 root wheel 1 Feb 4 19:57 Current -> A
$ ls -l /System/Library/PrivateFrameworks/kperf.framework/Versions/A/
total 0
drwxr-xr-x 4 root wheel 128 Feb 4 19:57 Resources
drwxr-xr-x 3 root wheel 96 Feb 4 19:57 _CodeSignature
It is present under the native SDK path, though:
$ ls -l /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/PrivateFrameworks/kperf.framework/
total 0
drwxr-xr-x 4 root wheel 128 Mar 5 17:58 Versions
lrwxr-xr-x 1 root wheel 26 Mar 5 17:58 kperf.tbd -> Versions/Current/kperf.tbd
$ ls -l /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/PrivateFrameworks/kperf.framework/Versions
total 0
drwxr-xr-x 3 root wheel 96 Nov 21 11:05 A
lrwxr-xr-x 1 root wheel 1 Mar 5 17:58 Current -> A
$ ls -l /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/PrivateFrameworks/kperf.framework/Versions/A
total 16
-rw-r--r-- 1 root wheel 4564 Nov 10 04:06 kperf.tbd
UPD: Nevermind, kperf seems to be a special case (see kperf demo gist).