zig icon indicating copy to clipboard operation
zig copied to clipboard

Zig failed to find private framework on macOS

Open jiacai2050 opened this issue 2 years ago • 5 comments

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)

jiacai2050 avatar Aug 30 '23 14:08 jiacai2050

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 avatar Mar 09 '25 06:03 tensorush

@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 });

jiacai2050 avatar Mar 09 '25 08:03 jiacai2050

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.

tensorush avatar Mar 09 '25 08:03 tensorush

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.

jiacai2050 avatar Mar 10 '25 03:03 jiacai2050

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).

tensorush avatar Mar 10 '25 06:03 tensorush