With the LLVM 15.x release wrapping up there are some issues that came up and were discussed during the release process that still don’t have a good solution. I have collected these issues and present them here now so that we have time to address them during the LLVM 16 development window:
libclang SOVERSION handling
One of the hotter debates right before the LLVM 15 window closed was how to handle libclang versioning. This was mostly discussed in this thread here that was opened by @h-vetinari. The compromise that was adopted in LLVM 15 was to make this configurable in CMake with the understanding that we should probably make a better-anchored decision before LLVM 16.
This commit was reverted in both LLVM 14 and 15 because it was not exactly clear how to handle this. @dblaikie was driving this discussion in this issue
Several runtime build issues
In LLVM 14 we switched to use runtime builds for our test script. This was reverted because check-all didn’t run the tests for the runtimes. This was fixed for LLVM 15, but later reverted on main. This discussion can be found on Phabricator here. - I think this just needs a fix from @petrhosek
LLVM 15.x initially shipped with the warning implicit-function-declaration made an error. This was reported that it broke several configure scripts in some almost invisible ways. This discussion was brought up by @mgorny and @AaronBallman
Call to action
I hope we can resurrect these threads or have an active discussion about the issues above and have them sorted out before we branch out LLVM 16.x
I might also very well have forgotten some issues - please use this thread to bring up those discussions as well.
I think another key issue with this release is the handling of the top-level cmake directory. We have received many, many, many issue reports because pretty much all subprojects depend on these cmake files now, but they are not part of the individual subproject tarballs.
The current situation is quite hostile to anyone who tries to build LLVM from the distributed tarballs and does not happen to be an expert in LLVM packaging idiosyncrasies. For the next release, we should probably go back to the scheme where the cmake directory is included in individual tarballs, to make LLVM builds “just work” again.
This was the result of many discussions in the LLVM 13/14 timeframe (including cmake changes the folder hierarchy in the subproject tarballs, which also breaks a lot of projects).
I don’t think there’s a good solution to subproject-tarballs while also having common cmake infrastructure.
libcxx has moved away from standalone builds completely AFAIU, for example.
One thing we haven’t tried yet (but I’m pretty sure it’s not a good idea, just spitballing) is to have each subproject have it’s own cmake infra that’s just a symlink to the project-level cmake folder. Those symlinks could be materialised for the tarball generation so the the subproject tarballs are more easily usable again.
The important case here: consider downstream project that requires llvm only (no other components, for example custom language frontend and some custom backend). With LLVM 15 it cannot just fetch llvm subdir and add necessary things on top / inside.
I’m not talking about fetching tarballs, but rather about importing llvm (via e.g. git subtree) into downstream repo. The top-level cmake folder should be imported as well and it might be in quite strange place.
15.0.1 and up have downgraded this back into an on-by-default warning (rather than a warning that defaults to an error), so for 15.x, I think we’re good.
For 16.x, the current behavior is that they are warnings which default to an error. My understanding is that @mgorny and others have been diligently working through the fallout and have been making good progress on fixing up things from their side. So I’m relying on distro folks to speak up if we’re still not in a good enough place to be able to leave the diagnostics as defaulting to an error, but I figured we’d see where things stand as we get closer to the branch point for 16.0.0.
Bumping this topic again so we have a less “hair-on-fire” situation when dealing with this than last time.
My preference would be to default to have a separate SOVERSION for libclang that only changes when actually necessary, along the lines of the original RFC.
This would however represent the third(!) change of default in as many LLVM releases, and I can understand that people would be reluctant to do so (though I noted already for the reversion of the default for LLVM 15 that we’d find ourselves in this situation…)
and before, situation pre-RFC
Default reverted to pre-RFC; switch available to keep RFC
The reason I left a question-mark in the table is that I think a deficiency of the original approach was to use a numbering scheme which made it look like a bug (i.e. someone forgot to bump 13->14). I think if there were a separate libclang versioning scheme that looks less like it should be 1:1 with the LLVM version (whether that’s restarting from 1, adding 1000 to LLVM version, or whatever), this would help get rid of the confusion with a separate SOVERSION, and would still let people that are affected by ABI benefit from the fact that there’s now less things to rebuild.
those that change the libclang ABI; the idea of the RFC was to reset the libclang SOVERSION to the current LLVM version whenever the ABI changes, meaning we’d continually run into the “looks like someone forgot to bump the version” issue. ↩︎
I don’t have a strong opinion as long as it can be switched to matching SOVERSION but I’d like to note that this is a dangerous default when linking to shared LLVM libraries / dylibs.
Unless I’m mistaken, the other option is “inefficient” at best (i.e. requiring you to rebuild more often), so I’m not convinced putting the users at risk is worth it. If you change the default, then at the very least you should warn if LLVM_LINK_LLVM_DYLIB is enabled along with the SOVERSION option — or perhaps we should do that anyway.
Ah, sorry, I thought I’ve already said it but I guess it was in another thread. Let’s say that a program links both to libclang.so.X and libLLVM-Y.so. Now LLVM gets upgraded — this means that a new SOVERSION of libLLVM-Z.so is installed but libclang.so.X gets replaced if it didn’t change the ABI. Effectively, the program is now linking to newlibclang.so.X and old libLLVM-Y.so, effectively getting both libLLVM-Y.so and libLLVM-Z.so loaded.
This is a real problem for many Linux distributions. LLVM makes breaking API changes with every major release, and many programs find it very hard to keep up. We have to support installing multiple LLVM versions simultaneously, and therefore we also need to be able to install different versions of libclang.so that link to a specific release of LLVM.
Are you sure about that? On Linux we use symbol versions, so the symbols would use either version LLVM_Y or LLVM_Z and thus not collide. I’m not aware of any issues with loading multiple versions of libLLVM.so into the same process. (Not anymore, it used to be an issue before we started using symbol versions in LLVM 5.)
We also got complaints about that unfortunately: see the discussion on issue 53281 after it was closed. (All LLVM 14 tarballs had the bundled cmake directory.) Seems there is no way to make everyone happy.