Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Add support for Mac Catalyst #168

Open
TolikPylypchuk opened this issue Jul 1, 2023 · 8 comments
Open

[Feature Request] Add support for Mac Catalyst #168

TolikPylypchuk opened this issue Jul 1, 2023 · 8 comments
Assignees
Milestone

Comments

@TolikPylypchuk
Copy link
Contributor

TolikPylypchuk commented Jul 1, 2023

Would it be possible to compile libuiohook for Mac Catalyst in addition to macOS? I've tried to fiddle with CMake, but didn't achieve much with it. I don't know if it's even possible to support Mac Catalyst without changes to the code.

I'm asking for this because one of the most popular UI frameworks for .NET - MAUI - uses Mac Catalyst to run apps on macOS (it doesn't provide a way to run apps as normal macOS apps). Several people have asked me to add support for MAUI on macOS to my libuiohook wrapper for .NET, and I don't know how to make it work as I don't have experience with CMake.

@TolikPylypchuk
Copy link
Contributor Author

TolikPylypchuk commented Jul 7, 2023

I've managed to add support for Mac Catalyst in my fork, but I feel that it's full of hacks. Nevertheless it works. You can check out this commit in my fork.

This is how it can be built:

export CC=clang
export CFLAGS='-O2 -g -target arm64-apple-ios13.1-macabi -miphoneos-version-min=13.1 -fembed-bitcode'

cmake -B ./build \
  -G "Unix Makefiles" \
  -D CMAKE_INSTALL_PREFIX=./dist/darwin/catalyst \
  -D CMAKE_VERBOSE_MAKEFILE=true \
  -D CMAKE_OSX_ARCHITECTURES='arm64' \
  -D BUILD_SHARED_LIBS=ON \
  -D MAC_CATALYST=ON \
  -D USE_APPLICATION_SERVICES=OFF \
  -D USE_IOKIT=OFF \
  -D USE_APPKIT=OFF \
  -D USE_EPOCH_TIME=ON

cmake --build ${{github.workspace}}/build \
  --parallel 2 \
  --config RelWithDebInfo \
  --clean-first

cmake --install ${{github.workspace}}/build --config RelWithDebInfo

This will build the arm64 version - the x86_64 can be built the same way basically, just changing arm64 to x86_64.

@kwhat
Copy link
Owner

kwhat commented Apr 20, 2024

I just dug thought your changes. It looks pretty doable. I have some questions:

I guess the first thing I am trying to figure out is what is "Mac Catalyst" and why does it require the library be compiled differently for use with it? I don't know much about Apples ecosystem so this is just so I can figure out why we are doing this.

Looking though your changes, I would prefer not to have the MAC_CATALYST define for enabling this. I don't think its really needed based on what I see in the commit you linked. We can just drop the #include <Carbon/Carbon.h> as everything else in there has been deprecated for years and in typical fashion, no replacement API was ever provided. I think everything you have below in the input_help.h will cover the need for Carbon.h.

I am not sure where kVK_RightCommand is usually defined. I think it was missing from the older headers which is why I added it here, but if its now magically provided we can just do something like the following:

#ifndef kVK_RightCommand
#define kVK_RightCommand 0x36
#endif

I am trying to figure out why you removed the following. It shouldn't have any effect on Catalyst support.

#if __MAC_OS_X_VERSION_MAX_ALLOWED <= 1050
typedef void* dispatch_queue_t;
#endif

The last bit is the difference in build flags:

if(MAC_CATALYST)
    add_compile_definitions(uiohook PRIVATE MAC_CATALYST)
    find_library(CORE_FOUNDATION CoreFoundation REQUIRED)
    target_include_directories(uiohook PRIVATE "${CORE_FOUNDATION}")
    target_link_libraries(uiohook "${CORE_FOUNDATION}")
    find_library(CORE_GRAPHICS CoreGraphics REQUIRED)
    target_include_directories(uiohook PRIVATE "${CORE_GRAPHICS}")
    target_link_libraries(uiohook "${CORE_GRAPHICS}")
else()
    set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15")
    find_package(Threads REQUIRED)
    target_link_libraries(uiohook "${CMAKE_THREAD_LIBS_INIT}")

    find_library(CARBON Carbon REQUIRED)
    target_include_directories(uiohook PRIVATE "${CARBON}")
    target_link_libraries(uiohook "${CARBON}")
endif()

Changing CMAKE_OSX_DEPLOYMENT_TARGET should probably happen on the command-line at build time. I think you can override it with something like -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15. This library still officially supports 10.5 and will probably still build for 10.4.

I am guessing that we need to look for CoreFoundation in the MAC_CATALYST enabled build because it gets sucked in by Carbon normally. If we pull in the HIToolbox stuff into input_helper.h I think we can just use the CoreFoundation library. I am guessing all of the above also applies to CoreGraphics.

How did we get away with dropping support for Threads? I think pthreads are still required for some mutex locking in input_hook.c to get the key typed chars.

If you would like to open a PR, please do so and we can get this merged into 1.3.

@kwhat kwhat added this to the 1.3 milestone Apr 20, 2024
@TolikPylypchuk
Copy link
Contributor Author

Mac Catalyst is a macOS system which enables running apps for iOS and iPadOS on macOS. As I've said, MAUI - a cross-platform UI framework for .NET - uses Mac Catalyst for macOS apps, so that's why SharpHook needs to support it.

Apps and libraries must be compiled for iOS in order to work on Mac Catalyst, that's why we need a different build of libuiohook. Since Carbon.h is not available on iOS, I needed to make adjustments.

Regarding macOS version support, Mac Catalyst itself appeared in version 10.15, so if we're building for Mac Catalyst, we're automatically building for 10.15+. Mac Catalyst versions correspond with iOS versions, and the earliest supported iOS version is 13.1. I've decided to drop support for versions of macOS older than 10.15 in my fork, because .NET itself doesn't officially support them. That's why I've removed some definitions from headers. Obviously, they should be kept if you want to support 10.5.

Regarding Threads, CoreFoundation etc. - I just hacked around to make it compile, I'm sure there are ways to make it better. As far as I remember, Threads was not available for Mac Catalyst, but I'm not sure. But I tested it, and it works (maybe, it's now open to some race conditions, I don't know to be honest).

And regarding CMAKE_OSX_DEPLOYMENT_TARGET - same thing, I just hacked around to make it work, I'm really not proficient in cmake at all, so if there are better ways to do that, I just didn't know.

I can make a PR with these changes, but I'm sure I didn't implement it in the best way possible (or even in a good way), so if you can improve on it, it would be awesome.

@kwhat kwhat self-assigned this Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
@kwhat
Copy link
Owner

kwhat commented Apr 24, 2024

Well, I understand what you did, but I cant seem to get it to compile. I keep seeing this warning clang: warning: using sysroot for 'iPhoneOS' but targeting 'MacOSX' which doesn't really make sense to me. We are manually specifying the target and it's clearly iOS.

kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 24, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
@kwhat
Copy link
Owner

kwhat commented Apr 25, 2024

Okey, so I think this is as good as it will get and I hope it works. I need you to do some testing because I have no idea how to use the output of this build. Ideally we should be able to do something like this, however, CMake does not support building for catalyst and it doesn't look like that support is showing up anytime soon.

export CC=clang
export CFLAGS='-O2'
cmake -B ./build \
        -G "Unix Makefiles" \
        -D CMAKE_INSTALL_PREFIX=./dist/ios/arm64 \
        -D CMAKE_VERBOSE_MAKEFILE=true \
        -D CMAKE_SYSTEM_NAME=iOS \
        -D CMAKE_OSX_SYSROOT=`xcrun --sdk macosx --show-sdk-path` \
        -D CMAKE_OSX_ARCHITECTURES=arm64 \
        -D CMAKE_OSX_DEPLOYMENT_TARGET=13.1 \
        -D BUILD_SHARED_LIBS=ON \
        -D USE_APPLICATION_SERVICES=OFF \
        -D USE_IOKIT=OFF \
        -D USE_APPKIT=OFF \
        -D BUILD_DEMO=OFF

The main issue is that the system name is required to be iOS which is how cmake converts CMAKE_OSX_DEPLOYMENT_TARGET=13.1 into the -miphoneos-version-min=13.1 argument, but if we set that it complains that the -isysroot specified with CMAKE_OSX_SYSROOT=xcrun --sdk macosx --show-sdk-path is not an iPhone SDK. If we try and compile with the iPhone SDK we get a bunch of errors becaues things like CGEventRef are not defined for iOS. If you try to build with CMAKE_SYSTEM_NAME=Darwin you get the correct macOS SDK, but you then get -mmacosx-version-min=13.1 which is also not correct. The only way I can get this to somewhat work correctly is by using the -target you provided.

kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
kwhat added a commit that referenced this issue Apr 25, 2024
@TolikPylypchuk
Copy link
Contributor Author

Sorry for not answering earlier, I see that you've tinkered with it quite a lot. I'll test my fork with this configuration and let you know whether it works in the next couple days.

When I first tried building libuiohook for Mac Catalyst, I tried creating an app in XCode in Objective-C, target Mac Catalyst, and link libuiohook to it, but it got nowhere since I don't know anything about Apple toolchains or Objective-C. Maybe, you'll have more luck if you try that.

@TolikPylypchuk
Copy link
Contributor Author

TolikPylypchuk commented May 5, 2024

I've just tested a build of libuiohook for Mac Catalyst, and everything seems to work fine. I've tested global hooks, input simulation, and mouse properties.

I've used this configuration from the latest commit on your branch:

cmake -B ./build \
        -G "Unix Makefiles" \
        -D CMAKE_INSTALL_PREFIX=./dist/catalyst/arm64 \
        -D CMAKE_VERBOSE_MAKEFILE=true \
        -D BUILD_SHARED_LIBS=ON \
        -D BUILD_DEMO=ON \
        -D USE_APPLICATION_SERVICES=OFF \
        -D USE_IOKIT=OFF \
        -D USE_APPKIT=OFF \
        -D BUILD_DEMO=OFF

This configuration works great.

But the configuration from your last comment doesn't work, it gives out this error:

CMake Error at /opt/homebrew/Cellar/cmake/3.29.2/share/cmake/Modules/Platform/iOS-Initialize.cmake:4 (message):
  
  /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk
  is not an iOS SDK
Call Stack (most recent call first):
  /opt/homebrew/Cellar/cmake/3.29.2/share/cmake/Modules/CMakeSystemSpecificInitialize.cmake:34 (include)
  CMakeLists.txt:20 (project)

kwhat added a commit that referenced this issue May 6, 2024
kwhat added a commit that referenced this issue May 7, 2024
kwhat added a commit that referenced this issue May 7, 2024
kwhat added a commit that referenced this issue May 7, 2024
kwhat added a commit that referenced this issue May 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants