wingtk / gvsbuild

GTK stack for Windows
GNU General Public License v2.0
447 stars 168 forks source link

librsvg unresolved external symbols #961

Closed danyeaw closed 1 year ago

danyeaw commented 1 year ago

I first noticed this when I was trying to upgrade librsvg to version 2.56.1, but it is also now failing the CI.

I posted an issue upstream as well here: https://gitlab.gnome.org/GNOME/librsvg/-/issues/968

code-affinity commented 1 year ago

I'm having this problem too. I am unable to build any version of gvsbuild because of it.

Following your link to the librsvg issue, the librsvg maintainer was initially unable to reproduce the problem with Rust 1.68.2, but after upgrading to Rust 1.70.0 they reproduced the problem. Since then, it looks like they have made a series of commits to allow librsvg to be built with a specific version of the Rust compiler. Then they changed the continuous integration settings for librsvg to build with Rust 1.69.0. But I think that would not help me when building from gvsbuild.

I don't see anything in the gvsbuild release history identifying changes to the rust version. I guess my librsvg build is just using whatever version of Rust that gvsbuild decided to install. So I can't solve this problem by reverting to an older version of gvsbuild, even though older versions would otherwise work fine for me.

Is there a way for me to tell gvsbuild to use Rust 1.69.0? gvsbuild build --help indicates that this subcommand has a --cargo-opts command line option, but I don't see an equivalent option for rustup.

I thought gvsbuild might be willing to use a system-installed rust, but I already have rust 1.60 installed. gvsbuild downloaded and installed rust 1.70 anyway.

danyeaw commented 1 year ago

Hi @code-affinity. We use rust-up to install Rust, which always installs the latest version. So, the fix we need to figure out is to install Rust some other way (so it is pinned on a version) or configure rust-up to stay on 1.69.0 somehow.

The code is in the tools.py module.

code-affinity commented 1 year ago

Thank you @danyeaw. Just to confirm, is there no option for gvsbuild to use a system-installed rust?

danyeaw commented 1 year ago

@code-affinity No, there currently is not. I guess that is the 3rd alternative, make the rust configurable or require the user to install rust themselves.

code-affinity commented 1 year ago

I hope the tone of this comment does not seem accusatory; I only want to strengthen the case for allowing the rust version to be configured or pinned. I see in the related librsvg issue that you have already offered to work on that, so perhaps I am preaching to the choir.

Our application depends on librsvg, built by gvsbuild. But there is no version of gvsbuild that we can build successfully anymore, so we can no longer build our application. There was nothing we could have done to predict or avoid this situation. When Rust 1.70 was published on 6/1/2023 with whatever regression caused librsvg issue 968, we were doomed.

Normally, we would decide to upgrade our dependent libraries or build tools only after an evaluation period in which we would hopefully discover problems before we committed to the upgrade. If we discovered a show-stopper build issue like this one, we would simply not upgrade. But even if we discovered such an issue too late (after we had already upgraded), we would have the (admittedly unpleasant) recourse of reverting to an older version. But that approach is only possible if we have control over the versions.

By using gvsbuild to satisfy our librsvg dependency on the Windows platform, we have relinquished some of that ability, since gvsbuild provides a curated set of interrelated libraries and versions, presumably compatible with each other. But since gvsbuild also obtains some of its own build tools (like the rust compiler), this introduces a new set of compatibility requirements that must be factored into that curation. Application developers either need some control over which build tool versions are selected, or the build tool versions need to be curated by gvsbuild maintainers like the library versions are.

Allowing application developers to configure the build tool versions implies other features that seem much more ambitious than the curated approach that gvsbuild already uses for the libraries it supports. For example, Conan allows for configuration of both library dependency versions and build tool dependency versions. (For example, it would be able to represent "You can only build librsvg with Rust 1.69 or earlier.") But these features are supported by conflict detection and resolution algorithms. If Conan can't automatically resolve the conflicts, further mechanisms are provided for the application developer to manually resolve the conflict with overrides.

That makes me wonder; surely any of the build tools obtained by gvsbuild also have the potential to introduce show-stopper issues like this one. Reviewing tools.py... It looks like all of the other build tools that gvsbuild obtains (like cmake, meson, ninja) are pinned to specific versions. If I understand that code correctly, as with the rust compiler, gvsbuild does not use system-installed cmake, meson, ninja, etc. either.

danyeaw commented 1 year ago

Hey @code-affinity this will be fixed soon, it was a pretty straightforward update to include a version number in the rustup default toolchain target. I'll merge the fix and release a new version once the CI passes.

Wow, that was a very long post. I know you are frustrated that things broke, but please remember this is an open source project. If you want to improve it, we welcome your contributions. If you don't like how fast we are fixing things in our free time, you can fork the project and fix it yourself. You could also sponsor me or the other project members if this is some type of critical infrastructure for you.

I would also recommend caching the successfully built librsvg in your CI pipeline for your application. This is what we do in https://github.com/gaphor/gaphor and other projects using gvsbuild. Once you have a successful build using the latest version of gvsbuild, cache it so that you don't need to build it again until a new version of librsvg is released.

code-affinity commented 1 year ago

@danyeaw, thank you very much for the prompt fix.

Please don't take the length of my previous comment as a sign of frustration or making demands. I think by writing, so much of that note was me processing what was different about this situation than the usual effects of a problem being found in a library. I am sorry that I discouraged you. As I wrote in the librsvg issue comments, I highly value gvsbuild and really appreciate your work and the work of the other gvsbuild contributors.

Reading the review comments from @pbor for your pull request, it seems that the points I was trying to make in my comment are not self-evident, so I think it was worth the hour or so it took to compose it. I was not doing so out of frustration; I sincerely thought I was contributing to the project.

Regarding your suggestion of caching the build output, coincidentally I was in the process of incorporating Conan into our application's build process when this issue arose. I had just successfully built a Conan package for librsvg for the first time the day before Rust 1.70 was published, but I got a few details wrong so it isn't quite usable yet. Once I'm able to build gvsbuild again, librsvg and other dependent libraries will be stored as Conan packages in our local Conan repository. I think that would protect against problems like this one.

I have other commitments all day today, but tomorrow I will try to create an issue on the Rust issue tracker, following Chun-wei Fan's hints to reproduce the problem without gvsbuild.