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

Distribute Linux Binaries for .NET Core on NuGet #312

Closed
mattleibow opened this issue Jun 8, 2017 · 45 comments
Closed

Distribute Linux Binaries for .NET Core on NuGet #312

mattleibow opened this issue Jun 8, 2017 · 45 comments

Comments

@mattleibow
Copy link
Contributor

mattleibow commented Jun 8, 2017

For most users of the common linux distros (Ubuntu, Debian, Red Hat, OpenSUSE, etc) it may be possible to distribute a binary in the NuGet package.

There are some limitations and reason why this is not such a good idea, but this is just an issue to track this thought.

Just want to link the main, but old, linux issue: #90


To make life easier for everyone, I moved code around and added a new target to the GN files. Now, the native libSkiaSharp build is done with GN and ninja directly: https://github.com/mono/SkiaSharp/wiki/Building-on-Linux

@kekekeks
Copy link
Contributor

kekekeks commented Jun 8, 2017

For people looking for prebuilt binaries: there is a prebuilt nuget package maintained by AvaloniaUI team. Despite the name it only contains libSkiaSharp.so. For docker images provided by microsoft you need to install libfontconfig1 package via apt-get.


Regarding providing prebuilt binaries in official package:

Please, link libstdc++ statically and use something with sufficiently old GLIBC as your build machine. This will allow to produce a single binary for almost every modern distro.

Ubuntu 14.04 is a good candidate for that since it has GLIBC 2.19 and modern compiler toolchain available from official repositories

@andrii-litvinov
Copy link

@kekekeks, I am trying to use this package with .NET Core 2.0 in linux in a container based on https://hub.docker.com/r/microsoft/aspnetcore/ and get runtime exception

System.TypeInitializationException: The type initializer for 'SkiaSharp.SKImageInfo' threw an exception. ---> System.DllNotFoundException: Unable to load DLL 'libSkiaSharp': The specified module or one of its dependencies could not be found.

though I can see the file in the output folder runtimes\linux-x64\native\libSkiaSharp.so . I am new to linux and not sure where to look for a solution. Do you know what I might be doing wrong? Or do you have any manual on how to use it? I have only installed the package.

@kekekeks
Copy link
Contributor

Try to use self-contained deployment, something like:

dotnet restore -r debian.8-x64
dotnet publish -r debian.8-x64 -o publish-dir

It should properly pack all dependencies for you.

You can also use microsoft/dotnet:2.0-runtime-deps-jessie as your base docker image in that case.

@andrii-litvinov
Copy link

@kekekeks thank you for your response! I have tried different docker packages and different runtime configurations like debian.8-x64 and linux-x64. I can see libSkiaSharp.so in startup folder, but still get same exception. Probably I should wait for official support on Linux.

@kekekeks
Copy link
Contributor

Check if you have all dependencies in your docker image. You can find them using lddtree libSkiaSharp.so. You image probably doesn't have libfontconfig1 package installed.

You can also try /lib/ld-linux.so.2 --verify ./libSkiaSharp.so or this simple utility to check for loader errors.

@andrii-litvinov
Copy link

@kekekeks I run ldd libSkiaSharp.so because it looks like that my image does not have lddtree. And it indeed says that it cannot find it: libfontconfig.so.1 => not found.

@andrii-litvinov
Copy link

andrii-litvinov commented Sep 25, 2017

I have done RUN apt-get update && apt-get install -y libfontconfig1 in my Dockerfile and and it worked 😄, thanks for the hints!

mattleibow added a commit that referenced this issue Sep 28, 2017
@Myszax
Copy link

Myszax commented Nov 22, 2017

@kekekeks
Copy link
Contributor

Do you need any particular feature of the recent SkiaSharp? It's kinda troublesome to build portable Linux binaries, so we avoid updating it unless it's really required.

@Myszax
Copy link

Myszax commented Nov 22, 2017

No, it was just a question.
I've download libSkiaSharp.so from 1.59.2 release and it works,
Anyway I am working on mono, still need to migrate to .NET Core.

@DanWBR
Copy link

DanWBR commented Nov 28, 2017

What about a native library for Raspberry Pi (Raspbian)? Any news on the Linux ARM front?

@kekekeks
Copy link
Contributor

You need to build it manually. I think @mterwoord had some success with ARM

@mterwoord
Copy link

See https://github.com/terwoord/skiasharp-raspberry for my script.
I think, it currently only requires debian-based operating system. The script currently is hardcoded at (at least) one spot t o a specific base directory (/home/matthijs/skiasharp-raspberry).

PR's are welcome!

@DanWBR
Copy link

DanWBR commented Nov 29, 2017

@mterwoord thanks for the information. So this is a cross-compilation, right? Would it be possible to compile skia/skiasharp on an actual Raspberry Pi? Did you try it?

@mterwoord
Copy link

This is cross-compilation, correct. I think I tried it, but the google tooling isn't available on arm.
Why would you want to compile on the actual pi?

@DanWBR
Copy link

DanWBR commented Nov 29, 2017

@mterwoord nothing special, just out of curiosity. It is actually much easier and faster on an Ubuntu VM for me...

@mterwoord
Copy link

That's my whole point.. ;)
If you have improvements for my script, please make PR! Thanks! :)

@DanWBR
Copy link

DanWBR commented Nov 29, 2017

@mterwoord it seems I need something on the 'rpi' directory. Could you add instructions on your readme file on how to configure your 'skiasharp-raspberry' base directory?

@mterwoord
Copy link

Edit build.sh, fix the BASE_DIR.
then run build.sh, possibly as admin (due to chroot usage)

@DanWBR
Copy link

DanWBR commented Nov 29, 2017

Ok, this wont' work with an empty base directory. I think you need to describe what goes on your base directory. An empty one won't work, obviously:

+ export BASE_DIR=/home/parallels/Desktop/skia-rasp/skiasharp-raspberry
 + BASE_DIR=/home/parallels/Desktop/skia-rasp/skiasharp-raspberry
 + export BUILD_DIR=/home/parallels/Desktop/skia-rasp/skiasharp-raspberry/build
 + BUILD_DIR=/home/parallels/Desktop/skia-rasp/skiasharp-raspberry/build
 + export RPI_ROOT=/home/parallels/Desktop/skia-rasp/skiasharp-raspberry/rpi
 + RPI_ROOT=/home/parallels/Desktop/skia-rasp/skiasharp-raspberry/rpi
 + true
 + rm -Rf /home/parallels/Desktop/skia-rasp/skiasharp-raspberry/rpi
 + mkdir -p /home/parallels/Desktop/skia-rasp/skiasharp-raspberry/rpi
 + cd /home/parallels/Desktop/skia-rasp/skiasharp-raspberry/rpi
 + qemu-debootstrap --foreign --arch armhf jessie /home/parallels/Desktop/skia-rasp/skiasharp-raspberry/rpi http://ftp.debian.org/debian
 ./build.sh: line 17: qemu-debootstrap: command not found
 + chroot /home/parallels/Desktop/skia-rasp/skiasharp-raspberry/rpi apt -q -y --force-yes install build-essential
 chroot: failed to run command ‘apt’: No such file or directory
 + chroot /home/parallels/Desktop/skia-rasp/skiasharp-raspberry/rpi apt -q -y --force-yes install gcc-multilib g++-multilib
 chroot: failed to run command ‘apt’: No such file or directory
 + chroot /home/parallels/Desktop/skia-rasp/skiasharp-raspberry/rpi apt -q -y --force-yes install 
 libstdc++-4.8-dev
 chroot: failed to run command ‘apt’: No such file or directory
 + chroot /home/parallels/Desktop/skia-rasp/skiasharp-raspberry/rpi apt -q -y --force-yes install 
libfontconfig1-dev
 chroot: failed to run command ‘apt’: No such file or directory
 + true
 + rm -Rf /home/parallels/Desktop/skia-rasp/skiasharp-raspberry/build
 + mkdir -p /home/parallels/Desktop/skia-rasp/skiasharp-raspberry/build
 + cd /home/parallels/Desktop/skia-rasp/skiasharp-raspberry/build
 + git clone https://github.com/mono/SkiaSharp.git skia
 Cloning into 'skia'...

@mterwoord
Copy link

Start off with installing qemu-debootstrap.

@DanWBR
Copy link

DanWBR commented Nov 29, 2017

I've already installed all the prerequisites as per your README file.

@mterwoord
Copy link

Well, my readme may be out of date. qemu-debootstrap isn't installed as it seems.

@DanWBR
Copy link

DanWBR commented Nov 29, 2017

Ok, you need to add 'qemu-user-static' as a prerequisite, qemu-debootstrap is on it (ubuntu 16.04). I also had to install 'apt'. Couldn't you add the install commands of all prerequisites to the script itself?

@mterwoord
Copy link

Could you make a PR for that please? :)

@toburger
Copy link

toburger commented Nov 30, 2017

When I run the chroot line
sudo chroot $RPI_ROOT apt -q -y --force-yes install build-essential
I get the following error:
chroot: failed to run command ‘apt’: No such file or directory

note: apt is installed on my system

Don't know if this is relevant: the preceding qemu-debootstrap runs successfully, but at the beginning it shows the following message
W: Cannot check Release signature; keyring file not available /usr/share/keyrings/debian-archive-keyring.gpg

@toburger
Copy link

Got it working with ubuntu 17.10 on a separate VM (WSL didn't work).
For those who are insterested in a pre built binary: https://github.com/toburger/skiasharp-raspberry/releases/tag/arm

@DanWBR
Copy link

DanWBR commented Nov 30, 2017

@mterwoord @toburger I was also able to compile the library successfully. I modified the script a little bit and will make a PR soon. I found it strange that the compiled library is a 32-bit one, I thought that Raspbian was a 64-bit OS...

@mterwoord
Copy link

mterwoord commented Nov 30, 2017 via email

@DanWBR
Copy link

DanWBR commented Nov 30, 2017

@mterwoord nothing special, I just thought that raspbian was 64-bit and was unconsciously expecting a 64-bit library.

@DanWBR
Copy link

DanWBR commented Nov 30, 2017

@mterwoord I've submitted a PR, please take a look.

@migueldeicaza
Copy link
Contributor

For Linux, I suggest that we package/distribute independently the unmanaged bits using the proper system packaging tool, and not try to solve the problem with NuGet.

Details here: #365

@DanWBR
Copy link

DanWBR commented Dec 3, 2017

I've tested the arm native library with my rasp 2, it worked on Ubuntu MATE normally. On Raspbian Stretch, it seems that the g++4.8-multilib library is missing from the default apt-get repository. I didn't try to find one and went back to Ubuntu.

@mterwoord
Copy link

Curious, what behavior do you see on raspbian?

@DanWBR
Copy link

DanWBR commented Dec 4, 2017

@mterwoord nevermind, I was putting an unnecessary dependency on g++4.8-multilib, which doesn't exist on Raspbian. The library worked fine on it too once I removed the dependency.

@mattleibow
Copy link
Contributor Author

mattleibow commented Feb 21, 2018

Just asking this question in multiple places:

Right now I have a x64 build for Linux that was compiled on Ubuntu 14.04. I am thinking of adding a few more to help the average dev use SkiaSharp without having to build their own. What other distros or CPUs would be helpful?

Leave a comment on this issue and track progress: #453

@kekekeks
Copy link
Contributor

As long as you are linking libfreetype and libstdc++ statically, that x64 library should work across all modern glibc-based distros.

@mattleibow
Copy link
Contributor Author

mattleibow commented Feb 21, 2018

@kekekeks Thanks for your continual support. I hope to get the best out for everyone.

I created an issue to help track requests and implementations: #453

@mattleibow
Copy link
Contributor Author

To make life easier for everyone, I moved code around and added a new target to the GN files. Now, the native libSkiaSharp build is done with GN and ninja directly: https://github.com/mono/SkiaSharp/wiki/Building-on-Linux

@mattleibow
Copy link
Contributor Author

mattleibow commented Oct 6, 2018

All right folks, I have been doing some work and I think I am able to meet you in the middle of "we don't really support Linux as it is not a priority" and "using Linux is a real pain because of X". Let me know what you think of this:

I have created a new package SkiaSharp.NativeAssets.Linux that will be going out with v1.68.0 that I would like to try. It will just contain the various Linux binaries that I have built and tested on. Right now, this is just going to be the binary I build on Ubuntu 16.04 amd64. I have done some testing and it appears to work on several distros (Ubuntu 14, OpenSUSe and CentOS), so I am going to put it in the linux-x64 runtime folder. (This may not work on alpine just yet - haven't tested - but I can always add a more specific build when I can.)

The overall result of this is that you will do everything as usual, but in the "app" part of the solution, just add the package. You should not release a NuGet to nuget.org that depends on this directly as you will then force all your uses to use my binary.

An example of a use case where a separate package is useful is this:

  • Matthew builds SkiaSharp and a binary for Ubuntu 16.
  • John builds an Ubuntu app and includes the SkiaSharp and SkiaSharp.NativeAssets.Linux packages. John is very happy.
  • Janet builds an Alpine app and includes SkiaSharp and her custom build of libSkiaSharp.so. Janet is not as happy as John. Janet has SKILLZ and can build for Alpine.
  • Joe is a great guy. Joe likes community. Joe likes Alpine Linux. Joe builds libSkiaSharp.so for Alpine. Joe creates a new NuGet package (JoesCodes.SkiaSharp.NativeAssets.Alpine) that just contains the Alpine binary.
  • Jane is also building for Alpine. Jane uses the JoesCodes.SkiaSharp.NativeAssets.Alpine package. Jane is happy.
  • Matthew has a look at JoesCodes.SkiaSharp.NativeAssets.Alpine and sees 1 million downloads! Matthew is blown away. Matthew knows everyone is using Alpine. Matthew has a chat to Big Boss: "We NEED Alpine". Big Boss has a look. Big Boss agrees. Matthew builds for Alpine and adds it to the SkiaSharp.NativeAssets.Linux package. Everyone is happy.
  • Janet and Jane now have options: use "official" or use "community". Janet is very happy. Jane is very happy.
    • Janet is Matthew's friend. Janet decides to use SkiaSharp.NativeAssets.Linux. Janet and Matthew are happy.
    • Jane is happy with JoesCodes.SkiaSharp.NativeAssets.Alpine. Jane is Joe's friend. Jane does not change.
  • Joe also has options: keep independent and free, or, update JoesCodes.SkiaSharp.NativeAssets.Alpine to be an empty shell package with a dependency.
    • Joe decides to update to depend on Matthew.
      • Janet updates. Janet is happy.
      • Jane updates. Jane gets the new package that gets Matthew's build. Jane is happy.
    • Joe stays free and builds the next version.
      • Janet updates. Janet is happy.
      • Jane updates. Jane gets Joe's new package. Jane is happy.

(Hope you folks like my story about Matthew and the Big Boss working to make life better for John, Janet, Joe and Jane. I had fun.)

@mattleibow mattleibow added this to the v1.68.0-preview milestone Oct 6, 2018
@mattleibow
Copy link
Contributor Author

Closing this as it is going out. Although it just has a single debian-based binary, more can be added if there is a demand. Since .NET Core is on Alpine, that will be the next build most likely.

To request a particular build of Linux to be included in the NuGet, just add a vote/comment to this issue and I will make sure to keep adding the most popular ones to the package: #453

If there are any issues with the new Linux bits, just open a new issue and let me know.

@ghost ghost locked as resolved and limited conversation to collaborators Aug 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

8 participants