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

x/mobile: enable building frameworks for Catalyst #36856

Closed
losh11 opened this issue Jan 29, 2020 · 32 comments
Closed

x/mobile: enable building frameworks for Catalyst #36856

losh11 opened this issue Jan 29, 2020 · 32 comments
Labels
FrozenDueToAge help wanted mobile Android, iOS, and x/mobile NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@losh11
Copy link

losh11 commented Jan 29, 2020

As of macOS 10.15, users can build iPad apps to run on macOS using Catalyst. However if you build a framework using gomobile, even though the framework has support for x86_64, Xcode will display an error.

To fix this, all you need to do is target clang for the macOS sdk & add a cflag with -target x86_64-apple-ios13.0-macabi. Fully tested example below.

Gomobile should support specifying a target catalyst. In x/mobile/cmd/gomobile/env.go, add a new case "catalyst" for function envInit which looks like this:

case "catalyst":
    clang, cflags, err = envClang('macosx')
    cflags += " -target x86_64-apple-ios13.0-macabi"
@gopherbot gopherbot added this to the Unreleased milestone Jan 29, 2020
@gopherbot gopherbot added the mobile Android, iOS, and x/mobile label Jan 29, 2020
@losh11
Copy link
Author

losh11 commented Feb 1, 2020

@hyangah if y'all are okay with this, I can implement?

@agnivade
Copy link
Contributor

agnivade commented Feb 2, 2020

All yours !

@cagedmantis cagedmantis added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Feb 6, 2020
@damiandizeo
Copy link

@losh11 added a new case "catalyst" for function envInit , but when I do 'gomobile bind' and create the .framework, Xcode still displaying error in when building on macOS Catalyst. Am I missing something ?

@losh11
Copy link
Author

losh11 commented Mar 24, 2020

@damiandizeo I'm not able to check exactly what you've done without a full set of diffs. This likely means your framework is not build for x86_64h as required by catalyst.

@damiandizeo
Copy link

@losh11 thanks, adding the cflag '-target x86_64-apple-ios13.0-macabi', was able to compile the framework and now runs under Mac Catalyst

@losh11
Copy link
Author

losh11 commented Mar 25, 2020

Great to hear @damiandizeo, if you or anyone else has time to implement this, that would be awesome. Unfortunately I no longer have the time to do this myself.

dpwiese added a commit to dpwiese/mobile that referenced this issue Apr 1, 2020
See: golang/go#36856

As of macOS 10.15 target catalyst can be used to build an iPad app to run on macOS. Existing .Framework built with gomobile produces the following error when targetting catalyst:

```
error: Building for Mac Catalyst, but the linked framework 'Sample.framework' was built for iOS + iOS Simulator. You may need to restrict the platforms for which this framework should be linked in the target editor, or replace it with an XCFramework that supports both platforms. (in target 'MySampleApp' from project 'MySampleApp')
```

This commit adds a case for catalyst (although architecture is just amd64) when configuring the environment for each architecture, providing the flags needed to enable the built .Framework to be used with catalyst.
@dpwiese
Copy link

dpwiese commented Apr 1, 2020

I looked at this quickly last night, and had a bit of trouble coming up with a solution as elegant as I had hoped. The environment is configured in envInit() for each architecture in allArchs. Support for catalyst needs to provide an additional configuring, but for the existing amd64 architecture. I don't think it makes sense to add catalyst to allArchs as a new architecture, as it is not. Treating it as such seems like a poor choice, and furthermore would require many changes throughout to support it if added as a new "architecture".

Rather, when setting up the environment in envInit() I've simply included it as an additional case alongside the existing true architectures. I've opened a (draft) PR with the current proposed solution here: golang/mobile#45

Feedback is appreciated, after which I'll mark ready for review. 🚀

@gopherbot
Copy link

Change https://golang.org/cl/310949 mentions this issue: mobile: support macOS and Catalyst

@hajimehoshi
Copy link
Member

@hyangah Could you take a look at the PR? I've already looked and this seems overall good to me.

@losh11
Copy link
Author

losh11 commented Jul 10, 2021

Awesome thanks for merging guys! I wonder if there's now interest for adding support for Windows? Not very familiar with Windows libraries.

@hajimehoshi
Copy link
Member

hajimehoshi commented Jul 13, 2021

After this change, I found that some of my libraries cannot be built with gomobile. For example, the library uses UIKit, but this build fails with 'macos' target:

# github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal
/Users/hajimehoshi/ebiten/internal/graphicsdriver/metal/view_ios.go:23:10: fatal error: 'UIKit/UIKit.h' file not found
 #import <UIKit/UIKit.h>
         ^~~~~~~~~~~~~~~
1 error generated.

I'm not sure the convention of Catalyst. Is this a usual thing? Would it be fine to add an option to select targets, or would it be better to fix my code?

EDIT: My current understanding is that I should fix my code with #if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR. For macOS Catalyst, Go's build tags are darwin and ios but libraries available are macOS.

@ydnar
Copy link

ydnar commented Jul 13, 2021

Maybe we should add build tags for macos and catalyst?

Edit: UIKit is available in maccatalyst target. Have you tried building for maccatalyst?

@hajimehoshi
Copy link
Member

hajimehoshi commented Jul 13, 2021

Maybe we should add build tags for macos and catalyst?

I think we should stop using ios build tag for macos and catalyst, and this might require Go change (#42100).

CC @hyangah @aclements @rsc

@hajimehoshi
Copy link
Member

hajimehoshi commented Jul 13, 2021

Edit: UIKit is available in maccatalyst target. Have you tried building for maccatalyst?

I tried the targets "macos" and "catalyst" one by one by modifying gomobile and both failed with the same error: UIKit.h is not found

@ydnar
Copy link

ydnar commented Jul 13, 2021

Edit: UIKit is available in maccatalyst target. Have you tried building for maccatalyst?

I tried the targets "macos" and "catalyst" one by one by modifying gomobile and both failed with the same error: UIKit.h is not found

I can take a look. Do you have a project or branch I can check out?

@hajimehoshi
Copy link
Member

Thanks, but it's a little complicated: I'm using ebitenmobile that wraps gomobile, so this might not be a good project for testing...

Would it be possible to add a test that just uses UIKit?

@hajimehoshi
Copy link
Member

Just in case, what I am currently doing is

  1. Modify go.mod in github.com/hajimehoshi/go-inovation, which is a testing mobile game in Go so that github.com/hajimehoshi/ebiten/v2@deb5f6f180156160ae76f8296c95abb997073a44 is used
  2. Run go run github.com/hajimehoshi/ebiten/v2/cmd/ebitenmobile bind -target ios -o ./mobile/ios/Mobile.xcframework ./mobile in go-inovation project.

@ydnar
Copy link

ydnar commented Jul 13, 2021

EDIT: My current understanding is that I should fix my code with #if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR. For macOS Catalyst, Go's build tags are darwin and ios but libraries available are macOS.

I’d try this.

  • Right now, there’s no flags in the current gomobile to not build for macOS in addition to macCatalyst.
  • It might be worth considering changing the ios target to darwin and add another flag to control which sub-targets get built (ios, iphonesimulator, macos, catalyst).

@ydnar
Copy link

ydnar commented Jul 13, 2021

@hajimehoshi I think I’m getting close with a fix for gomobile that implements additional build tags so Go code can discriminate between macos, ios, and catalyst targets.

Edit: you can see the WIP branch here:

golang/mobile@golang:master...ydnar:goos-ios

@hajimehoshi
Copy link
Member

hajimehoshi commented Jul 14, 2021

Thanks!

  • Gomobile specifies ios as a build tag for backward compatibility, but perhaps, we no longer need to add it explicitly, as long as GOOS=ios.
  • Adding build tags like macos, catalyst, simulator might be controversial. In your change, is it possible to have two build tags macos and ios enabled at the same time? (If not, we don't need macos since this can be represented as !ios)
    • EDIT: It looks like it's possible. I'm not sure this makes sense...

@ydnar
Copy link

ydnar commented Jul 14, 2021

Thanks!

  • Gomobile specifies ios as a build tag for backward compatibility, but perhaps, we no longer need to add it explicitly, as long as GOOS=ios.

  • Adding build tags like macos, catalyst, simulator might be controversial. In your change, is it possible to have two build tags macos and ios enabled at the same time? (If not, we don't need macos since this can be represented as !ios)

    • EDIT: It looks like it's possible. I'm not sure this makes sense...

The macos build tag is pretty useful.

I just landed a commit that expands the gomobile -target arg to accept Apple/darwin-specific targets like macos and catalyst. If ios is specified it will expand to ios,simulator, and compile for the appropriate architectures (arm64 and amd64).

You can get fancy and specify multiple targets which will be compiled into a single XCFramework like this:

-target ios/arm64,simulator/amd64,simulator/arm64,catalyst/amd64,catalyst/arm64

TODO: add consistent build tags for each platform, specific to that platform and GOOS.

@hajimehoshi
Copy link
Member

The macos build tag is pretty useful.

Hmm, I'm not sure it'd be appropriate when GOOS is ios and at the same time a build tag macos exists. In your case, ios and !ios are enough to distinguish iOS and macOS, if they are exclusive.

@ydnar
Copy link

ydnar commented Jul 14, 2021

The macos build tag is pretty useful.

Hmm, I'm not sure it'd be appropriate when GOOS is ios and at the same time a build tag macos exists. In your case, ios and !ios are enough to distinguish iOS and macOS, if they are exclusive.

They’re not exclusive. catalyst implies both macos and ios.

Edit: I’m open to being convinced otherwise! Making the gl package successfully build and compile inspired this work to clean it up.

Is there a macOS gobot build for the mobile repo?

@hajimehoshi
Copy link
Member

hajimehoshi commented Jul 14, 2021

They’re not exclusive. catalyst implies both macos and ios.

So another question is, would it make sense to make them exclusive? In Catalyst, should we think the environment is macOS and iOS at the same time?

@ydnar
Copy link

ydnar commented Jul 14, 2021

They’re not exclusive. catalyst implies both macos and ios.

So another question is, would it make sense to make them exclusive? In Catalyst, should we think the environment is macOS and iOS at the same time?

I suppose macCatalyst could imply the build tags macos and maccatalyst but !ios. Let me see if I can get that to work.

@hajimehoshi
Copy link
Member

I suppose macCatalyst could imply the build tags macos and maccatalyst but !ios. Let me see if I can get that to work.

IIUC, on Catalyst, TARGET_OS_IPHONE is 0. Then, !ios seems to make sense. I might be wrong as I'm not so familiar with Catalyst.

@networkimprov
Copy link

@hajimehoshi can you reopen this issue? The previous CL closed it automatically.

@hajimehoshi hajimehoshi reopened this Jul 22, 2021
@ydnar
Copy link

ydnar commented Jul 22, 2021

@hajimehoshi does ebitenmobile build with the new branch?

@hajimehoshi
Copy link
Member

@hajimehoshi does ebitenmobile build with the new branch?

ebitenmobile is a wrapper of gomobile, not a fork.

@ydnar
Copy link

ydnar commented Jul 22, 2021

  1. Modify go.mod in github.com/hajimehoshi/go-inovation, which is a testing mobile game in Go so that github.com/hajimehoshi/ebiten/v2@deb5f6f180156160ae76f8296c95abb997073a44 is used
  2. Run go run github.com/hajimehoshi/ebiten/v2/cmd/ebitenmobile bind -target ios -o ./mobile/ios/Mobile.xcframework ./mobile in go-inovation project.

@hajimehoshi so I got this ^ to mostly work. I had to add an additional cflag -DGLES_SILENCE_DEPRECATION (because of -Werror).

However, it stopped here: https://github.com/hajimehoshi/ebiten/blob/f1fc6fe3e8819d06c651620e8b30d95faf612de0/cmd/ebitenmobile/main.go#L226

2021/07/22 08:15:30 open ios/mobile/ios/Mobile.xcframework/Versions/A/Headers/MobileEbitenViewController.h: no such file or directory
exit status 1

Presumably because it’s trying to manipulate a .framework instead of an .xcframework. Seems like a quick iteration of the directories in Mobile.xcframework will produce 1 or more Mobile.framework directories that can be modified.

The EBITENMOBILE_GOMOBILE var came in handy:

EBITENMOBILE_GOMOBILE=../gomobile go run github.com/hajimehoshi/ebiten/v2/cmd/ebitenmobile bind -target ios -o ./mobile/ios/Mobile.xcframework ./mobile

@hajimehoshi
Copy link
Member

Yeah MobileEbitenViewController.h is inserted by ebitenmobile after .framework is generated by gomobile, then your guess seems correct. Thank you for testing!

@ydnar
Copy link

ydnar commented Sep 18, 2021

@losh11 This is fixed in golang/mobile@6d8ad35e (golang/mobile#70).

@losh11 losh11 closed this as completed Sep 24, 2021
@golang golang locked and limited conversation to collaborators Sep 24, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge help wanted mobile Android, iOS, and x/mobile NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
10 participants