Robmaister / SharpFont

Cross-platform FreeType bindings for .NET - Need maintainer
Other
294 stars 107 forks source link

How is the Freetype native binary installed on iOS? #102

Open corliss opened 7 years ago

corliss commented 7 years ago

How is the iOS Freetype binary located and installed? The p/invoke code previously used the path "__Internal", which I removed as part of the Portable unification checkin. But I wasn't able to locate a binary with that name either in this repo or in the Dependencies repo. So where did that come from?

We should also add support for

The SharpFont PCL will suffice, together with per-platform native freetype binaries. A single nuspec can handle this, I think, by having the correct binaries in the correct subfolders of lib.

Robmaister commented 7 years ago

Based on this link it appears as though __Internal means that it's packed into the binary which is also hosting the instance of Mono running that C# code. I believe that on iOS you're only allowed to distribute a single binary file, hence this magic string.

This StackOverflow question states that modifying the .dll.config should work, though no one was able to confirm.

I don't have an iPhone or the toolchain setup to see if this works, but I could try and see if anyone I know would be willing to run some test code for me. @manu-silicon wrote the original changes, so perhaps he has the capacity to test such a change?

The original change, #80, is supposed to work for UWP and Android as well, though perhaps it wasn't declared in the profile selected for PCL. Mac has been supported for a very long time, SharpFont.dll.config has a dllmap to a .dylib in OS X, and OpenRA currently ships with it on OS X.

corliss commented 7 years ago

it appears as though __Internal means that it's packed into the binary which is also hosting the instance of Mono running that C# code.

What causes it to be packed into the binary, since neither SharpFont nor SharpFont.Dependencies do anything to make that happen?

corliss commented 7 years ago

The original change, #80, is supposed to work for UWP and Android as well, though perhaps it wasn't declared in the profile selected for PCL. Mac has been supported for a very long time.

I think I'm starting to understand, but still some open questions. So here's a list of all supported platforms, with my understanding of how this works:

Robmaister commented 7 years ago

Windows: It appears that SharpFont.Dependencies copies the x64 or x86 version of freetype6.dll to the bin directory. The relevant line of SharpFont.Dependencies.props is:

Yep. If you're publishing your own software that is more complex, you might also distribute both versions of the dll and do a runtime selection based on the host architecture. Or select a different version of MSVC that you choose to depend on instead.

Linux & FreeBSD: SharpFont.dll.config has these lines, but how is libfreetype.so.6 installed? Or do we assume that it is preinstalled with the OS?

Downstreams will typically publish a package on a package manager, and will mark freetype as a dependency to be installed before that package will be installed. So basically yes, assume that it is installed, or enforce installation prior to running the program/game

UWP: Can't find any code related to UWP.

It should "just work" as long as the dll is included in the app package. Some MSBuild work might be handy to automate this if the <Content> tag in the .props file isn't enough.

Android: Can't find any code related to Android

Will also just work. If the dllmap to linux doesn't resolve, Mono will search for variants of the existing dll name, and I believe some version of FreeType ships with Android.

iOS: We need to add a line mapping freetype6 to __Internal for iOS, but even after that, how is the freetype binary included with the app?

I'm not 100% on the details here, but as I understand it, everything is packaged into one native binary by Xamarin. The native portion of the app essentially just bootstraps a Mono environment and hosts your C# assembly that's embedded in the binary. All your other native dependencies are supposed to be statically linked into this same binary. Mono uses the magic string "__Internal" to mean "the binary that's executing this code", since that's the one binary you're allowed to have at all.

Depending on the details, a .dll.config might not actually be included here at all, ,making this solution impossible or just really hard. I think we'll need someone with the right environment to test some of this stuff for us eventually. I'm all about killing off the iOS specific package, so if there's some way to intercept DllImports and use your iOS detection function, then that will be our backup to the .dll.config change

corliss commented 7 years ago

More questions :)

HinTak commented 7 years ago

Sigh. You guys have absolutely no idea about how Mono works.

Mono implements gdiplus, which Mono's implementation of System.Drawing and System.Windows.Forms depends on, via a whole bunch of libraries, one of which is freetype. This is on non-windows. On windows, mono uses the native microsoft's gdiplus so mono does not depends on freetype through gdiplus; but gtk# depends on gtk and gtk depends on cairo which in turn depends on freetype.

So anything that has a GUI with mono basically can assume freetype is present, except mono on windows with winforms.

HinTak commented 7 years ago

You are right, Xamarin.Mac does not need or ship freetype.

You want to know whether freetype can be assumed to be around, I gave you the answer: gtk# on all platforms and winforms on non-windows.

HinTak commented 7 years ago

FWIW, mono is not a variant of microsoft CLR, although microsoft now owns xamarin. There are distinct differences (and different bugs) between mono's implemention of various CLR libraries vs Microsoft's.

HinTak commented 7 years ago

? Xamarin uses microsoft CLR? The last time I checked (around Christmas?) , netcore was still essentially windows only...

Robmaister commented 7 years ago

UWP: So the desktop binaries are used here? That doesn't make sense, because UWP has different file APIs, and supports other processors such as ARM.

Yup, freetype makes little use of CRT/Win32 calls. The most would be opening a file to read it's contents. If that doesn't work because of the sandboxing, there's a Face constructor that accepts a byte array.

For ARM, it looks like the solution is to simply build an ARM version of freetype and use that, like how OpenCV does it among others: https://blogs.msdn.microsoft.com/lucian/2015/11/27/opencv-building-uwp-binaries/

iOS: I understand about the Mono environment, but how does it know about FreeType at all? Or is FreeType always included for all apps by Mono/Xamarin?

Part of the build process for a Xamarin app is to statically link freetype into the final binary, and you'd have to build freetype yourself for that currently.

I suppose UWP ARM and iOS builds of freetype would be helpful in this case

corliss commented 7 years ago

This is where I wish github markdown supported tables :)

Can we agree on this goal: the user only needs to include the SharpFont and SharpFont.Dependencies nuget, and never has to worry about native binaries. That is, the nugets take care of installing them if needed. Given that, here's a summary so far:

All told, that is quite a lot of work. But we'll get there. :) And along with that - HarfBuzz!

corliss commented 7 years ago

FYI I will open separate issues for each platform, intended to be closed only when each platform is fully verified.

Robmaister commented 7 years ago

@HinTak

Sigh. You guys have absolutely no idea about how Mono works.

Chill with the condescending tone, please. No, we don't all know everything about Mono, but I'd like to at least keep the discussions constructive.

Mono implements gdiplus, which Mono's implementation of System.Drawing and System.Windows.Forms depends on, via a whole bunch of libraries, one of which is freetype. This is on non-windows. On windows, mono uses the native microsoft's gdiplus so mono does not depends on freetype through gdiplus; but gtk# depends on gtk and gtk depends on cairo which in turn depends on freetype.

You want to know whether freetype can be assumed to be around, I gave you the answer: gtk# on all platforms and winforms on non-windows.

Not all distributions of Mono have to include libgdiplus or cairo. One example would be Unity3D.

FWIW, mono is not a variant of microsoft CLR, although microsoft now owns xamarin. There are distinct differences (and different bugs) between mono's implemention of various CLR libraries vs Microsoft's.

Yup, it's a rewrite of the runtime back when the CLR was only "open" in that the spec was published as an ECMA and ISO standard and everything else was closed source. I'm aware that they are separate runtimes.

? Xamarin uses microsoft CLR? The last time I checked (around Christmas?) , netcore was still essentially windows only...

That's not what I said, Mono can be embedded into a native executable and I believe this was what Xamarin did in order to bypass restrictions on iOS apps. Unity3D does this as well, which is how C# scripts can be hosted inside their C++ engine.

.NET Core SDK is currently available for Windows, OS X, and Linux as well: https://www.microsoft.com/net/download/core

If you are running on Linux or OS X, though, SharpFont won't work as they're still trying to figure out DLL mapping: https://github.com/dotnet/coreclr/issues/930

Robmaister commented 7 years ago

@corliss

Can we agree on this goal: the user only needs to include the SharpFont and SharpFont.Dependencies nuget, and never has to worry about native binaries. That is, the nugets take care of installing them if needed. Given that, here's a summary so far:

Yes, this should be the goal.

  • UWP: x64 and x86: Same builds as desktop. Issues with files. (Note: a byte array is sub-optimal when dealing with lots of fonts - fonts can get quite large. I believe that Freetype uses memory mapped files when that option is available.) TODO: ARM

I believe FreeType also has a system of loading fonts from a file stream, haven't taken the time to look into the feasibility of making that interop properly with C# streams.

  • Android: preinstalled. Need to test this (or has this been tested already?)

Definitely still needs a test, hopefully it's just hanging around /usr/lib or something.

  • Mac: Already supported, uses the freetype that is preinstalled in the OS.

I misspoke/forgot - only older versions of OS X distributed freetype.6.dylib, so now we depend on the copy distributed with the default Mono package. /Library/Frameworks/Mono.framework/Libraries/libfreetype.6.dylib

  • iOS: May need an entry in SharpFont.dll.config. Need to test whether iOS has a preinstalled freetype binary, if not will need to ship one.

Be prepared for a mapping to __Internal to not work, we may have to bring back SharpFont.iOS for now with just the single #define to change the DLL path, or find some crazy hack around it.

corliss commented 7 years ago

Be prepared for a mapping to __Internal to not work, we may have to bring back SharpFont.iOS for now with just the single #define to change the DLL path, or find some crazy hack around it.

In that case, is it possible to get help re: iOS? Just in terms of understanding where it currently finds the library. There are many threads on the internet of people wanting to build FreeType for iOS, which leads me to believe that it does not come preinstalled on the system.

Robmaister commented 7 years ago

Yeah, it's not pre-installed as far as I know, the user must download, build, and link it themselves. I tried to explain this earlier, probably a bit poorly:

Part of the build process for a Xamarin app is to statically link freetype into the final binary, and you'd have to build freetype yourself for that currently.