EimaMei / Silicon

An alternative, purely C-focused wrapper to Apple's Cocoa API for OS X app development and basic iOS programming. Requires little to no Objective-C knowledge to use.
Other
19 stars 2 forks source link

Good idea but cannot build #6

Closed g40 closed 11 months ago

g40 commented 11 months ago

Any thoughts on this? It's a good idea and building on the previous work gets a big tick.

I'd like to see if up and running. N.B. Only tried building for MacOSX.

Thanks for listening.

Sonoma 14.1.1
XCode 15.0.1
% clang --version
Apple clang version 15.0.0 (clang-1500.0.40.1)
Target: arm64-apple-darwin23.1.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Running make runExamples 2>&1 | tee out.log results in a good number of errors, as shown below:

clang -O2 -std=c99 -I"include" -Wno-deprecated-declarations  source/mac/NSGeometry.m -c -o build/NSGeometry.o
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:33:
include/Silicon/mac/types.h:56:15: error: typedef redefinition with different types ('char *' vs 'NSString *')
typedef char* NSNotificationName; /* Note: originally this was NSString* */
              ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSNotification.h:7:19: note: previous definition is here
typedef NSString *NSNotificationName NS_TYPED_EXTENSIBLE_ENUM;
                  ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:33:
include/Silicon/mac/types.h:59:17: error: redefinition of 'NSAutoreleasePool' as different kind of symbol
mac_type_define(NSAutoreleasePool);
                ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSAutoreleasePool.h:10:12: note: previous definition is here
@interface NSAutoreleasePool : NSObject {
           ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:33:
include/Silicon/mac/types.h:61:17: error: redefinition of 'NSView' as different kind of symbol
mac_type_define(NSView);
                ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks/PrintCore.framework/Headers/PDEPluginInterface.h:28:8: note: previous definition is here
@class NSView;
       ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:33:
include/Silicon/mac/types.h:64:17: error: redefinition of 'NSNotification' as different kind of symbol
mac_type_define(NSNotification);
                ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSNotificationQueue.h:8:8: note: previous definition is here
@class NSNotification, NSNotificationCenter, NSArray<ObjectType>, NSString;
       ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:33:
include/Silicon/mac/types.h:68:17: error: redefinition of 'NSFileManager' as different kind of symbol
mac_type_define(NSFileManager);
                ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSFileManager.h:96:12: note: previous definition is here
@interface NSFileManager : NSObject
           ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:33:
include/Silicon/mac/types.h:69:17: error: redefinition of 'NSProcessInfo' as different kind of symbol
mac_type_define(NSProcessInfo);
                ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSProcessInfo.h:29:12: note: previous definition is here
@interface NSProcessInfo : NSObject {
           ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:33:
include/Silicon/mac/types.h:76:17: error: redefinition of 'NSImage' as different kind of symbol
mac_type_define(NSImage);
                ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSUserNotification.h:8:112: note: previous definition is here
@class NSString, NSDictionary<KeyType, ObjectType>, NSArray<ObjectType>, NSDateComponents, NSDate, NSTimeZone, NSImage, NSAttributedString, NSUserNotificationAction;
                                                                                                               ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:34:
In file included from include/Silicon/mac/enums.h:40:
include/Silicon/mac/headers/NSPathUtilities.h:14:29: error: redefinition of 'NSSearchPathDirectory'
typedef NS_ENUM(NSUInteger, NSSearchPathDirectory) {
                            ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSPathUtilities.h:61:29: note: previous definition is here
typedef NS_ENUM(NSUInteger, NSSearchPathDirectory) {
                            ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:34:
In file included from include/Silicon/mac/enums.h:40:
include/Silicon/mac/headers/NSPathUtilities.h:15:5: error: redefinition of enumerator 'NSApplicationDirectory'
    NSApplicationDirectory = 1,             // supported applications (Applications)
    ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSPathUtilities.h:62:5: note: previous definition is here
    NSApplicationDirectory = 1,             // supported applications (Applications)
    ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:34:
In file included from include/Silicon/mac/enums.h:40:
include/Silicon/mac/headers/NSPathUtilities.h:16:5: error: redefinition of enumerator 'NSDemoApplicationDirectory'
    NSDemoApplicationDirectory,             // unsupported applications, demonstration versions (Demos)
    ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSPathUtilities.h:63:5: note: previous definition is here
    NSDemoApplicationDirectory,             // unsupported applications, demonstration versions (Demos)
    ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:34:
In file included from include/Silicon/mac/enums.h:40:
include/Silicon/mac/headers/NSPathUtilities.h:17:5: error: redefinition of enumerator 'NSDeveloperApplicationDirectory'
    NSDeveloperApplicationDirectory,        // developer applications (Developer/Applications). DEPRECATED - there is no one single Developer directory.
    ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSPathUtilities.h:64:5: note: previous definition is here
    NSDeveloperApplicationDirectory,        // developer applications (Developer/Applications). DEPRECATED - there is no one single Developer directory.
    ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:34:
In file included from include/Silicon/mac/enums.h:40:
include/Silicon/mac/headers/NSPathUtilities.h:18:5: error: redefinition of enumerator 'NSAdminApplicationDirectory'
    NSAdminApplicationDirectory,            // system and network administration applications (Administration)
    ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSPathUtilities.h:65:5: note: previous definition is here
    NSAdminApplicationDirectory,            // system and network administration applications (Administration)
    ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:34:
In file included from include/Silicon/mac/enums.h:40:
include/Silicon/mac/headers/NSPathUtilities.h:19:5: error: redefinition of enumerator 'NSLibraryDirectory'
    NSLibraryDirectory,                     // various documentation, support, and configuration files, resources (Library)
    ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSPathUtilities.h:66:5: note: previous definition is here
    NSLibraryDirectory,                     // various documentation, support, and configuration files, resources (Library)
    ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:34:
In file included from include/Silicon/mac/enums.h:40:
include/Silicon/mac/headers/NSPathUtilities.h:20:5: error: redefinition of enumerator 'NSDeveloperDirectory'
    NSDeveloperDirectory,                   // developer resources (Developer) DEPRECATED - there is no one single Developer directory.
    ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSPathUtilities.h:67:5: note: previous definition is here
    NSDeveloperDirectory,                   // developer resources (Developer) DEPRECATED - there is no one single Developer directory.
    ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:34:
In file included from include/Silicon/mac/enums.h:40:
include/Silicon/mac/headers/NSPathUtilities.h:21:5: error: redefinition of enumerator 'NSUserDirectory'
    NSUserDirectory,                        // user home directories (Users)
    ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSPathUtilities.h:68:5: note: previous definition is here
    NSUserDirectory,                        // user home directories (Users)
    ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:34:
In file included from include/Silicon/mac/enums.h:40:
include/Silicon/mac/headers/NSPathUtilities.h:22:5: error: redefinition of enumerator 'NSDocumentationDirectory'
    NSDocumentationDirectory,               // documentation (Documentation)
    ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSPathUtilities.h:69:5: note: previous definition is here
    NSDocumentationDirectory,               // documentation (Documentation)
    ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:34:
In file included from include/Silicon/mac/enums.h:40:
include/Silicon/mac/headers/NSPathUtilities.h:23:5: error: redefinition of enumerator 'NSDocumentDirectory'
    NSDocumentDirectory,                    // documents (Documents)
    ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSPathUtilities.h:70:5: note: previous definition is here
    NSDocumentDirectory,                    // documents (Documents)
    ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:34:
In file included from include/Silicon/mac/enums.h:40:
include/Silicon/mac/headers/NSPathUtilities.h:24:5: error: redefinition of enumerator 'NSCoreServiceDirectory'
    NSCoreServiceDirectory,                 // location of CoreServices directory (System/Library/CoreServices)
    ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSPathUtilities.h:71:5: note: previous definition is here
    NSCoreServiceDirectory,                 // location of CoreServices directory (System/Library/CoreServices)
    ^
In file included from source/mac/NSGeometry.m:9:
In file included from include/Silicon/silicon.h:53:
In file included from include/Silicon/mac/silicon.h:34:
In file included from include/Silicon/mac/enums.h:40:
include/Silicon/mac/headers/NSPathUtilities.h:25:5: error: redefinition of enumerator 'NSAutosavedInformationDirectory'
    NSAutosavedInformationDirectory API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)) = 11,   // location of autosaved documents (Documents/Autosaved)
    ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSPathUtilities.h:72:5: note: previous definition is here
    NSAutosavedInformationDirectory API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)) = 11,   // location of autosaved documents (Documents/Autosaved)
    ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
make: *** [build/NSGeometry.o] Error 1
EimaMei commented 11 months ago

Unfortunately, I am not too sure why Clang complains so much about the 'redefinitions' of types and enums despite the C Silicon headers not having any Cocoa includes. Maybe removing '#include <CoreServices/CoreServices.h>' in include/silicon.h and replacing it with some other header would fix the issue, but not only do I doubt that, but I also cannot even test that out, as I am not using MacOS as my primary OS anymore. This also might be a compiler thing, where Apple's Clang auto-includes these headers, but that's going into pure speculation.

However, as an actual alternative to silicon, I recommend trying out a fork of silicon instead. It's more-or-less the same thing but single-header and 100% C, which should get rid of those errors.

g40 commented 11 months ago

Hello @EimaMei,

Thanks for the comment. The failure to compile is odd, I agree. I had found the fork and tried that too. It compiles but all of the examples crash at startup. And there is no issues page on the fork so reporting is a trifle difficult. I will pursue further and see if the cause can be fixed. @ColleagueRiley: do you have any comments? I'm building on M2 silicon/Sonoma using Clang 15.0.0

Thanks!

ColleagueRiley commented 11 months ago

I believe I used to have a similar issue as you when compiling newer versions of MacOS using [the original] Silicon. I ended up just used per-compiled binaries instead of compiling it by hand.

In terms of Silicon.h crashing, I'm not sure what the problem is.

EimaMei commented 11 months ago

Hello @EimaMei,

Thanks for the comment. The failure to compile is odd, I agree. I had found the fork and tried that too. It compiles but all of the examples crash at startup. And there is no issues page on the fork so reporting is a trifle difficult. I will pursue further and see if the cause can be fixed. @ColleagueRiley: do you have any comments? I'm building on M2 silicon/Sonoma using Clang 15.0.0

Thanks!

I’ll definitely attempt to look into it either on the following days or the weekend. As for silicon.h crashing, I’ve read awhile back that the way you declare objc_msgSend in x86-64 MacOS would crash in ARM64 MacOS due to ABI differences (sadly I cannot find that source at the moment). Either way I’ll probably have to setup docker and to debug either issue.

g40 commented 11 months ago

Hello @ColleagueRiley

Your comment re objc_msgSend is absolutely on the money. On Apple ARM64 all you need is that, and not the stret/fpret varieties. See https://stackoverflow.com/questions/24003327/objc-msgsend-macro-on-arm64 and (the slightly madcap) https://felixk15.github.io/posts/c_ocoa/

Sadly all of the examples fail in one way or another. I'll investigate further.

Silicon-h % lldb menu    
(lldb) target create "menu"
Current executable set to '/Users/jevans/src/osx/Silicon-h/menu' (arm64).
(lldb) r
Process 4607 launched: '/Users/jevans/src/osx/Silicon-h/menu' (arm64)
Process 4607 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x40)
    frame #0: 0x000000018d8c9578 libobjc.A.dylib`objc_opt_isKindOfClass + 12
libobjc.A.dylib`objc_opt_isKindOfClass:
->  0x18d8c9578 <+12>: ldr    x8, [x0]
    0x18d8c957c <+16>: and    x16, x8, #0x7ffffffffffff8
    0x18d8c9580 <+20>: mov    x17, x0
    0x18d8c9584 <+24>: movk   x17, #0x6ae1, lsl #48
Target 0: (menu) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x40)
  * frame #0: 0x000000018d8c9578 libobjc.A.dylib`objc_opt_isKindOfClass + 12
    frame #1: 0x0000000191524b98 AppKit`-[NSApplication setMainMenu:] + 96
    frame #2: 0x00000001000053cc menu`NSApplication_setMainMenu + 68
    frame #3: 0x0000000100004d80 menu`main + 468
    frame #4: 0x000000018d9010e0 dyld`start + 2360
g40 commented 11 months ago

and a picture to complement the last post (You can invoke the TUI mode by typing 'gui' at the lldb command line):

image

ColleagueRiley commented 11 months ago

I'm not too sure what the problem is, it seems like ARM likes to use objc_msgSend and not the fpret or stret varieties. But Silicon only uses objc_msgSend anyway, so I don't know how it would be causing a crash.

Silicon.h works well on x86 systems, so it's 100% something to do with ARM. It'll be kind of hard for me to figure out the problem because I don't have an computer with an ARM processor.

I think the problem could be with how I cast objc_msgSend but that's just a guess.

g40 commented 11 months ago

A couple of things worth mentioning, though perhaps not so interesting if you are only interested in a C API. Apple have a very clever C++ wrapper for Metal: https://developer.apple.com/metal/cpp/.

Some of the (many) nice features useful in this context are wrappers for SEL and ownership. So, using their string construction, the code below returns the expected result: i.e. the objc_msgSend invocation returns true, and the receiving buffer will contain "Hello World".

It is essential to cast to the correct form of function pointer prior to calling.

{
        // source string 
        NS::String* s = MTLSTR("Hello World");
        // receiving buffer    
        char buffer[512] = {0};
        //-----------------------------
        const char* sel = "getCString:maxLength:encoding:";
        SEL methodSelector = sel_registerName( sel);
        // note typedef and cast. *must* match ObjC signature.
        typedef bool (*pfn)(id,SEL,char*,unsigned long long,unsigned long long);
        // set up function pointer
        pfn p = (pfn)objc_msgSend;
        // call it. note use of metal string as argument.
        bool b = p(s,methodSelector,buffer,512,NS::UTF8StringEncoding);
        //-----------------------------
        printf("%s => %s (%s)\n",sel,(b?"true":"false"),buffer);
    }
ColleagueRiley commented 11 months ago

It looks interesting I guess, but I'd be worried about any extra performance issues that C++ brings. Cocoa already isn't that great of a API in terms of performance issues. I really wish apple would stop being weird with their products.

As for Silicon.h's crash issue, I should have a commit in the next few hours that fixes any potential casting issues. Would you be willing to test it? I'm not 100% sure if @EimaMei has an ARM device or not.

g40 commented 11 months ago

I suspect the c++ overhead is absolutely minimal. This is basically for games!

in terms of testing, yes absolutely. Let me know.

Thanks for listening.

ColleagueRiley commented 11 months ago

@g40 I believe the C++ overhead has a little bit of extra OOP to it. It seems relatively minimal though, yes.

Also, the update with the fixed casting has been committed if you want to test it.

g40 commented 11 months ago

@ColleagueRiley. Latest fails to compile. AIUI, there is no need for the fpret flavour on Apple ARM64.

Silicon-h % make
make opengl
gcc examples/graphics/opengl.c -I./ -framework Cocoa -framework OpenGL -framework CoreVideo -o opengl
In file included from examples/graphics/opengl.c:3:
./silicon.h:2151:21: error: use of undeclared identifier 'objc_msgSend_fpret'
    return (CGFloat)objc_msgSend_float(window, func);
                    ^
./silicon.h:1187:53: note: expanded from macro 'objc_msgSend_float'
#define objc_msgSend_float                      ((CGFloat (*)(id, SEL))objc_msgSend_fpret)
                                                                       ^
1 error generated.
make[1]: *** [opengl] Error 1
make: *** [example] Error 2
g40 commented 11 months ago

OK, if I edit that, the example apps compile and run. Sweet.

ColleagueRiley commented 11 months ago

@ColleagueRiley. Latest fails to compile. AIUI, there is no need for the fpret flavour on Apple ARM64.


Silicon-h % make

make opengl

gcc examples/graphics/opengl.c -I./ -framework Cocoa -framework OpenGL -framework CoreVideo -o opengl

In file included from examples/graphics/opengl.c:3:

./silicon.h:2151:21: error: use of undeclared identifier 'objc_msgSend_fpret'

    return (CGFloat)objc_msgSend_float(window, func);

                    ^

./silicon.h:1187:53: note: expanded from macro 'objc_msgSend_float'

#define objc_msgSend_float                      ((CGFloat (*)(id, SEL))objc_msgSend_fpret)

                                                                       ^

1 error generated.

make[1]: *** [opengl] Error 1

make: *** [example] Error 2

This is because I accidentally put objc_msgSend_fpret instead of abi_objc_msgSend_fpret. It's fixed now though.