-
Notifications
You must be signed in to change notification settings - Fork 899
Proposal for better way to handle native binaries, with proof of concept NuGet packages #974
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
Comments
Oh yeah, one other thing it could do is simplify the CI builds since the NuGet package restore would bring down the needed native library instead of needing to build it directly. |
/cc @ethomson |
So this seems like a reasonable approach to detaching the libgit2 libraries from the built LibGit2Sharp libraries themselves. What I don't see (and maybe I'm just not looking hard enough). Am I also able to make the LibGit2Sharp project depend on the LibGit2Sharp.NativeBinaries nuget package? So that we can get the checked in libgit2 DLLs out of the LibGit2Sharp repository? That's the big win, in my opinion. |
I think that's the general idea. One thing that we would have to properly define though is the versioning strategy for the |
Also, one minor nit, |
Yes, the LibGit2Sharp project would also be able to depend on the LibGit2Sharp.NativeBinaries package, removing the libgit2 dlls from the repo.
Yeah, I was just putting these packages together manually with NuGet Package Explorer, and didn't move that one over. The actual implementation that was generating the packages via a nuspec file would have that sorted correctly. |
The way I've set the package up right now, I'm not sure it would be super-useful on it's own, so I'm not sure it needs a separate versioning strategy. I was thinking of it as more of part of our release cycle, where we just happen to split things up into multiple packages. Would we ever want to update just the native binaries and not push out a new version of of the managed dll to use it? If not, then I think the NativeBinaries package would just have the same version as the main LibGit2Sharp package, and it would have a dependency on the exact version of the NativeBinaries package. We could always include the libgit2 commit sha in the description of the package it that would be useful. The other option I could see for the NativeBinaries package would make it just track the actual libgit2 releases, so that would only be updated when they release a new version. We could then make a prerelease package if we needed something that hadn't been released yet. However, we'd end up needing to tie our releases to theirs then, because I don't believe a non-prerelease package can depend on a prerelease package. I need to double check that to confirm, though. |
@bording We only recently started to publish pre release packages. In the past, it happened that we upgraded libgit2 without publishing LibGit2Sharp. We now leverage AppVeyor to build the packages for us on merge. We don't publish them automatically though. I wonder if we couldn't do the same thing with the libgit2 build. One thing we may plan for is that a libgit2 version may actually cause some previously passing LibGit2Sharp tests to fail. So, in order to check that a libgit2 NuGet package works, we would download it, reference it locally, run the tests. Once everything is ok, we would publish the libgit2 package. then we would open a PR on LibGit2Sharp referencing it. |
Out of curiosity, would this mean I would no longer have to explicitly copy and include the ---libgit2--- native binaries in my installer package? Maybe I'm misunderstanding something. |
I would think that we'd be able to do some sort of automation there, but it does become a bit more complicated because we need the binaries for windows, linux and mac to be included in the package. They'd probably have to be built and commited separately, and then trigger the automated package build after all the new binaries are in the repo. |
LibGit2Sharp would still need the native libgit2 binaries to work, so I guess it depends on what sort of installer package you're talking about. If you're talking about some sort of setup program or msi then you'll still need to include those the native binaries as part of that. |
@bording Oh! I didn't realize that you were after building a multi-platform package. Yes indeed, that may add some complexity ;-) Full disclosure: I'm not a *nix person. However, I was under the impression that building a "one-package-fits-all-size" for Linux would be complex (see GitTools/GitVersion#264 (comment)) from @carlosmn. |
Yes, the sample NativeBinaries package I made includes binaries for windows, linux, and mac. I was trying to make getting the needed native binaries as dead simple as possible! The package installs the binaries next to the LibGit2Sharp.dll. I tested which paths mono would look for the libraries, and, as of Mono 3.12 at least, it first looks at the directory where the requesting assembly is located, and then goes on to look at the platform-specific paths. The mono docs also mention that it will do this: http://www.mono-project.com/docs/advanced/pinvoke/dllnotfoundexception/ I didn't dig back into previous versions to see if this was something new or not. |
/cc @Therzok |
Thanks for clarifying @bording. Sorry to interupt. 👍 |
@bording You can do some runtime linker magic to make that actually work. In the current situation, looking in the current directory isn't enough. What the problem is: when you run The problem gets worse when you have relative dependencies (i.e. libssh2). How I solved this: On Mac, you can use Optionally, this could be done at libgit2's cmake level by using this guide. |
On a side note: The above solutions do not interfere with anything regarding the user's system. All binaries are shipped as-is with no extra dependency on having X installed. Preference: Once normal binaries get solved, we could also go for a route where the native binary is also shipped with |
@Therzok So are you saying that the library itself has some hardcoded path dependencies that require some special treatment? If not, them I'm a bit confused, because I tested the libraries I included in my sample package, and they definitely worked, with mono finding the library from the DllImport. |
@bording I'm saying that the runtime linker itself (not mono) will use absolute paths in resolving it. It's going to resolve the path by identity - first line in the otool/ld output - or at least, that was my last experience with using these libs. How did you use/test the binaries? If you're using something in the lines of |
That's exactly what I did! I saw how Then I used the http://www.mono-project.com/docs/advanced/pinvoke/dllnotfoundexception/ and I could see all the places that mono was looking for the library, and the first place it is looking is the directory that the referencing library is located. As that page from the docs mentions:
Everything was definitely working just like that when I was testing it out. Could this be something new in a recent mono release? Perhaps I need to go digging through the release notes... |
Then I have no issues with this and it fulfills its goal. 👍 |
@Therzok Cool, you had me worried I had missed something major in my testing this weekend! 😄 |
I think the issue I was hitting was specifically related to runtime dependencies (such as libssh2). But that's out of scope. |
Since it seems like people are cool with this, I've begun making changes here I put the example versions of those nuget packages up on myget at https://www.myget.org/F/bording-libgit2/ If you want to check out the branch so far, add that as a package source, and you'll be able to restore successfully. I'll open a PR for this with a list of what else I'm thinking needs to be done and some followup questions tomorrow! |
|
As @Therzok and I discussed above, mono doesn't have a problem loading the libgit2 lib when it's located next to LibGit2Sharp.dll. So it looks like the potential for concern would be this:
It sounds like the complication comes in with the other libgit dependencies. I wonder what the "very limited version" of libgit2 would look like? It still seems better to me to include some sort of native binary in the nuget package that at least gets people started and able to run something. We could always include a readme.txt in the package that would include instructions for building their own if they needed the extra features. Or perhaps would could include a version with the external dependencies and list those as requirements? I guessing we don't want to go down the rabbit hole of actually adding/maintaining packages to the OS package managers? |
@bording Shouldn't we also consider the processor architecture on Linux? |
Mono is 32bit only. It only supports 32bit invokes iirc. |
I've recently read something about x64 being worked on. |
There are 64bit versions of mono, but on OSX at least, you currently have to compile from source to get it. http://www.mono-project.com/docs/about-mono/supported-platforms/osx/ As far as other platforms, here is a list: http://www.mono-project.com/docs/about-mono/supported-platforms/ There are several more exotic architectures that they list as supported, but I'm not even sure where'd we get access to those to build a library! |
Taking out of the loop the dependencies, if we compile libgit2 on Ubuntu, could the produced binary be interoped as is from Mono on others distros? Sorry for the dumb question. cough Asking for a friend cough |
No idea. This is out of |
@Therzok Sorry. I didn't understand the last part of your sentence. 😖 |
So, I just spent some time chatting with a friend of mine who knows more about all of this than I do, and it sounds like for the most part the library should just work, assuming the dependent libraries are installed on the machine. He did mention a potential for a binary compatibility problem based on the version of glibc used to compile vs. the installed version on the machine. Based on that I think we could:
That seems like a reasonable approach to me, and I think it makes for a better development experience when using LibGit2Sharp on a non-windows platform. |
Assuming we want to try and get the unix binaries included, I have a way to make that work nicely inside the NuGet package, as my example NativeBinaries packages demonstrates. Even if we decide it's too much of a hassle or too problematic to include the unix binaries, I think there is still enough benefit to move forward with this for just the windows binaries at least! |
Superseded by #984 |
Looking through the issues list, one of the things I've seen come up a lot is the idea of improving how we're handling the native libgit libraries, in a way that works cross-platform, #837 and #493 for example. There has also been some talk moving the native libraries into a separate NuGet package, including some PRs that have attempted it but seem to have gotten stuck for various reasons( #896, #772).
After the change I made the current props file this weekend to keep it from copying the native binaries folder when not on windows, I started thinking about how I could leverage that into improve the above situation.
I spent some time working a proof of concept set of NuGet packages that seem to do exactly what I wanted them to:
bording/NativeBinaryNugetPackages
If you put them in a folder and set up a local package source, you can try them out. I've added them to projects in Windows, OSX Yosemite with Xamarin Studio, and Ubuntu 14.04, and everything works, with just the needed native libraries being automatically included as needed.
The way this works is that main LibGit2Sharp package just has the managed dll in it now, and nothing else. It has a dependency on what I've called LibGit2Sharp.NativeBinaries. In that package are all of the native binaries and a build\props file that conditionally adds the correct binaries based on what platform you are on.
Assuming everyone likes this approach, I'm proposing making the changes needed to go forward with this new packaging scheme.
One of the benefits I see of this is that it can simplify the main codebase, because we can just have a package dependency on the NativeBinaries package like any other managed project would. Anyone who grabs a copy of the code would just have it work in any environment!
I can also see moving all of the stuff that is currently in the repo for managing the native builds out into a separate LibGit2Sharp.NativeBinaries repo, which is where the libgit2 submodule could live along with the nuspec for building the native package.
Thoughts?
The text was updated successfully, but these errors were encountered: