oneclick / rubyinstaller2

MSYS2 based RubyInstaller for Windows
https://rubyinstaller.org
BSD 3-Clause "New" or "Revised" License
644 stars 248 forks source link

ABI compatibility probem with RubyInstaller 3.3.1-1 release. #385

Closed mcorino closed 1 month ago

mcorino commented 1 month ago

What problems are you experiencing?

I was under the impression ABI compatibility should be maintained between Ruby releases based on major+minor version but I have a problem loading a native extension built with the RIDK from the RubyInstaller 3.3.0-1-x64 release in an environment with RubyInstaller 3.3.1-1-x64 release.

Is this a known/expected problem?

larskanis commented 1 month ago

This is right, all major+minor equal versions should be ABI compatible. So extensions built on 3.3.0-1-x64 or 3.3.1-1-x64 should be exchangeable. I don't know of any incompatibilities.

What is the error you get?

mcorino commented 1 month ago

I get a LoadError on loading the extension .so.I installed both 3.3.0 and 3.3.1 fresh and only installed my gem (wxruby3) and next tried to load my extension. On 3.3.0 this works, on 3.3.1 a LoadError.On 29 May 2024 21:31, Lars Kanis @.***> wrote: This is right, all major+minor equal versions should be ABI compatible. So extensions built on 3.3.0-1-x64 or 3.3.1-1-x64 should be exchangeable. I don't know of any incompatibilities. What is the error you get?

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you authored the thread.Message ID: @.***>

mcorino commented 1 month ago

In both cases the gem installation downloads the same prebuilt binary release package which was built using RubyInstaller 3.3.0-1.

mcorino commented 1 month ago

@larskanis I looked some more into this and found the problem. It's not so much a question of ABI incompatbility as it is ABI incompleteness.

The Ruby 3.3.1-1 release is (at least) missing the expat library. My native extension libraries built with the 3.3.0-1 release linked with the libexpat-1.dll which is included in that release and than failed because that library is missing from 3.3.1-1. Copying the library from the 3.3.0-1 installation to the 3.3.1-1 installation (/ucrt64/bin) made my extensions function properly again with the 3.3.1-1 installation. I did not check in detail but a quick check shows that the ucrt64/bin folder of the 3.3.0-1 installation contains 94 files and the same folder of the 3.3.1-1 installation only 71 files. So it seems there may be more items missing from the 3.3.1-1 release.

Would it possible to release a 3.3.1-2 release shortly with all the missing items added (and the 3.3.1-1 release removed) so we get proper ABI compatibility back?

larskanis commented 1 month ago

Would it possible to release a 3.3.1-2 release shortly with all the missing items added (and the 3.3.1-1 release removed) so we get proper ABI compatibility back?

No. libexpat is not a dependency of ruby, that's why it is not distributed with it. Maybe it was part of some older rubyinstaller-devkit release, due to some dependency of some other library, but the gem in question has to make sure on its own, that the library is available. Usually it can be solved by installing a pacman package like so:

ridk exec pacman -S mingw-w64-ucrt-x86_64-expat

To automate this it's possible to add the dependency to the gemspec like so: https://github.com/oneclick/rubyinstaller2/wiki/For-gem-developers#user-content-msys2-library-dependency

mcorino commented 1 month ago

Ah, I wasn't aware that, apparently , the installation of the RIDK could not be relied on other than the availability of the compiler suite.

I'll work on adding pacman library dependencies to my gem spec.

mcorino commented 1 month ago

@larskanis I have looked into installing extra pacman packages to alleviate the missing libexpat in the 3.3.1-1 installation but unfortunately this does not work.

The libexpat library installed through the MSYS2 pacman tool installs fine and is installed under msys64\usr\{include|lib|bin} but the library is unfortunately not installed with the standard name libexpat-1.dll but rather with the name msys-expat-1.dll. As the 3.3.0-1 built extension was linked to libexpat-1.dll it still does not work under 3.3.1-1. And now comes the kicker. Even when explicitly installing the libexpat-devel package in the 3.3.0-1 installation (which adds the msys-expat-1 lib there as well) I still cannot build a compatible extension because the standard included expat lib (headers & libraries) is installed under msys64\ucrt64 and it turns out that the compiler and linker will find and use anything installed under msys64\ucrt64 before a similar package installed under msys64\usr.

There is a serious problem here that seems unsolvable. Any package standard installed by RubyInstaller because of being a ruby or (standard lib) dependency gets installed in msys64\ucrt64 it seems and will overrule any similar package (header & link library) installed through pacman. If such a standard package has a differently named shared library than a pacman installed shared library there is no ABI compatibility possible for a native extension if a release update removes the standard package like it does in the case of the 3.3.1-1 update.

This problem would be smaller (although still potentially there) if the dependency libs pulled in by ruby or it's standard libs used the same naming scheme as pacman installed packages. Why is that not so?

larskanis commented 1 month ago

Did you install libexpat through the above mentioned package?

ridk exec pacman -S mingw-w64-ucrt-x86_64-expat

Installing packages without the mingw prefix will not solve this problem. They are used internally only in MSYS2.

mcorino commented 1 month ago

Ahhh, bugger, I overlooked that one. Thanks for straightening me out. I now get the full picture (more at least) and will continue from here.