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

wip: support using an existing clang installation #374

Closed
wants to merge 2 commits into from

Conversation

nolange
Copy link
Contributor

@nolange nolange commented Oct 21, 2023

add an option --host-clang which will skip building llvm, and instead provide symlinks and wrappers for clang and llvm tools.

Currently the clang version is detected, but it does not affect the llvm version that will be downloaded and used.

The functionality is so far only tested on debian 12 with a backported clang-17 from experimental. Unfortunately the default version is still clang-14.
To install the default clang for debian 12:

apt-get install git clang cmake ca-certificates ninja-build make llvm python3 libunwind-14-dev lld python3-distutils

There exist still some issues I would want to resolve to make this a working "addon" using the system clang.

  • scripts should be adapted instead of needing symlinks or additional wrappers in bin
    for building llvm-mingw it doesnt matter much, but the final installation should be leaner.
  • testing the toolchain with more than just simple projects
  • Fitting the version of llvm to clang (or proving that those stay compatible?)

@nolange nolange marked this pull request as draft October 21, 2023 01:12
@mstorsjo
Copy link
Owner

  • Fitting the version of llvm to clang (or proving that those stay compatible?)

This varies quite a bit among the components:

  • compiler-rt builtins; could maybe in theory depend on the version of the compiler, but in practice I'm not aware of any relevant changes in the last many versions
  • compiler-rt sanitizers; also could depend on the compiler version, probably with more potential for changes happening, but also here, I'm not directly aware of any breaking points (but I haven't followed that interface very closely)
  • libcxx has a policy, where they support being built with either of the latest two major versions of Clang, but not further than that. IIRC this is acted on quite diligently, by dropping cases for handling older versions of Clang. (The other way around; building an older libcxx with a newer version of Clang might or might not work, but I believe that's not the relevant case here.)
  • libcxxabi is kinda closely tied to libcxx, but doesn't usually do anything tricky wrt the compiler
  • libunwind has a pretty stable ABI and shouldn't really be tied to the version of the compiler, and doesn't have any tricky code that requires a very modern compiler
  • libopenmp is developed very closely in lockstep with Clang, where code is added in Clang/LLVM at the same time as in libopenmp (and its tests). IIRC the interface between Clang and the library is standardized though, so if you disregard libopenmp's tests, I believe a newer libopenmp should just provide more things that an older Clang just won't use (but all the testcases of the newer libopenmp wouldn't pass with an older Clang)

@nephatrine
Copy link

I have been testing @nolange's fork with --host-llvm (now --host-clang) and it's working well for me. It might not be needed, but I do specify LLVM_VERSION manually to be the tracking branch for the LLVM major version matching the system prior to building to be safer.

I've only tested with these configurations and and I'm not building anything really complicated (but not just toy examples either) so it's not conclusive or anything, but I haven't had any issues:

  • Debian bookworm with LLVM 14 (needs --disable-cfguard specified)
  • Debian bookworm with LLVM 16 from LLVM apt as system default clang/lld/etc.
  • Ubuntu jammy with LLVM 16 from LLVM apt as system default clang/lld/etc.

I had hacked together my own much less elegant solution previously based on #59 using the same LLVM_VERSION strategy and had never encountered any compatibility problems with just the major version number matching the system llvm/clang version.

@mstorsjo
Copy link
Owner

I have been testing @nolange's fork with --host-llvm (now --host-clang) and it's working well for me. It might not be needed, but I do specify LLVM_VERSION manually to be the tracking branch for the LLVM major version matching the system prior to building to be safer.

Right - that avoids potential compatibility issues between the prebuilt clang/llvm and the runtimes - but it comes at the cost of risk of mismatches between the build scripts and the expectations in them, vs what works for the sources at the time.

During the years, there's been quite a few different changes and cleanups in how the runtimes (in particular, libunwind+libcxxabi+libcxx) are built and configured. The build scripts generally should work with either the pinned version (the latest release or RC of LLVM) and the latest version from git (which is tested in nightly builds). But whenever I update the build scripts, if e.g. latest LLVM sources requires changing something, or if it allows making things cleaner/neater, I take that into use whenever I can (after updating the pinned version).

A couple recent examples:

  • 6b87253, "build-openmp: Build the OpenMP library on all architectures", which only works since LLVM 16.x
  • 6b9e0b1, "build-libcxx: Build both static and shared libc++ in one single cmake build", which only works as intended since LLVM 15.x
  • 7b1d05f, "build-libcxx: Build libunwind+libcxxabi+libcxx with one single cmake build", which probably only works since LLVM 14.x
  • 14db168, "wrappers: Use --{start,end}-no-unused-arguments instead of -Qunused-arguments", requiring LLVM 14.x
  • 13e065b, "build-libcxx: Don't manually install libunwind.dll", which requires LLVM 13.x

(There were lots of refactorings around the build of libcxx around 2020-2022, but I think the dust has mostly settled by now. But even still, things evolve all the time.)

So going forward, if we'd have this functionality merged to be able to build with a prebuilt LLVM (sorry I haven't had time to actually look at the changes in the branch yet), the safest thing would probably be to check out a contempory version of llvm-mingw, matching the prebuilt LLVM/Clang (possibly overriding MINGW_W64_VERSION to get a fresh version of those files), to have build scripts getting a version of LLVM that they expect.

@nolange
Copy link
Contributor Author

nolange commented Oct 25, 2023

@mstorsjo thanks for the explanation

I think ideally the compiler-rt builtins could be provided by the system clang, they only depend on mingw headers (and there likely some basic stuff like stddef.h).
The compiler-rt sanitizers seem way more complicated and obviously depend on the C++ library and the flavor of the runtime. If those are installed by the system clang then those should use the system mingw libraries - so its not really an option.

Picking the current supported LLVM version seems to be the most sane to me, but some options would be nice in the future:

  • Pick the fitting LLVM version

  • Provide the sources by other means

    On debian for example, you could easily prepare the fitting LLVM version with all debian-specific patches, just would need an option to tell the scripts to use those sources instead of getting them via git.

Hope I will find some time next week

build-compiler-rt.sh Outdated Show resolved Hide resolved
build-all.sh Outdated Show resolved Hide resolved
build-all.sh Outdated Show resolved Hide resolved
install-wrappers.sh Outdated Show resolved Hide resolved
install-wrappers.sh Show resolved Hide resolved
# link the header directory, prevent modification
ln -snf $resdir/include $PREFIX$clangres/include

# Note: clang will detect the "InstalledDir" based on the path that was used to invoke the tools
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate on this comment? In principle, won't this odd/unexpected feature essentially mean that the whole wrapper script that you generate below wouldn't be necessary? It would be good to make the comment clearer, to indicate that while this behaviour exists, we choose not to rely on it, because of reasons X and Y (which reasons?), and instead use a wrapper script. I guess the "This might still have some hidden effects" comments is that, somewhat, i.e. we could do that but choose not to since we don't know what implications it might have?

Just spelling it out a bit more explicitly would be helpful at least.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The note is primary to myself, precisely because I dont know and cant explain if this might be an issue.

%  clang -v                
Debian clang version 17.0.2 (1~exp1)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/12
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/12
Candidate multilib: .;@m64
Selected multilib: .;@m64

vs.

%  /usr/lib/llvm-17/bin/clang -v
Debian clang version 17.0.2 (1~exp1)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/lib/llvm-17/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Candidate multilib: .;@m64
Selected multilib: .;@m64

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left this open - anything to do here?
Its the way it is because I dont know better

install-wrappers.sh Show resolved Hide resolved
install-wrappers.sh Show resolved Hide resolved
@nolange
Copy link
Contributor Author

nolange commented Nov 10, 2023

Bwt. I managed to build via CI, but I am not used to Github: https://github.com/nolange/llvm-mingw/tree/wip

Some pointers there? probably should copy or parameterize linux+asserts and try compiling ffmpeg?

@mstorsjo
Copy link
Owner

Some pointers there? probably should copy or parameterize linux+asserts and try compiling ffmpeg?

Hmm. It's probably easy to tweak some of the existing jobs to test this; not sure what the best way as a permanent place in the build graph would be...

Most of the github actions build pipeline is built on one job producing a relocatable package, which is packed up and transferred to the next job, where it's unpacked and used. For a toolchain that is built to use the distro clang, that is much less of a redistributable package - although it practically works as long as both steps have e.g. the same version of Clang installed.

Just building it and running run-tests.sh (possibly with e.g. RUN_I686=false RUN_X86_64=false set, to tell it not to try to use wine to execute the built executables) should be enough to test using many of the tools; see the linux-cross-aarch64 job for an example of that. Building ffmpeg probably would test more, but I'm not sure if it's strictly necessary to weed out issues with it? If it's kept to just testing with run-tests.sh, it would all fit within one standalone job and doesn't need to duplicate parts of the other jobs.

add an option --host-clang which will skip building llvm,
and instead provide symlinks and wrappers for clang and
llvm tools.

Currently the clang version is detected, but it does not
affect the llvm version that will be downloaded and used.
@nolange
Copy link
Contributor Author

nolange commented Jan 16, 2024

Should've addressed all open points. some CI integration is in another branch: https://github.com/nolange/llvm-mingw/tree/wip

@nolange nolange marked this pull request as ready for review January 16, 2024 21:14
@mstorsjo
Copy link
Owner

Should've addressed all open points. some CI integration is in another branch: https://github.com/nolange/llvm-mingw/tree/wip

Thanks! I think this looks good at this point.

I tried doing a different kind of testing for it, by doing a build within docker, which allows controlling more exactly what files are available and what aren't, and a manual job that one can trigger to test building this within GHA, see https://github.com/mstorsjo/llvm-mingw/commits/system-clang.

If you don't mind, I think I'll go ahead and merge it with this kind of testing setup in the near future.

@nolange
Copy link
Contributor Author

nolange commented Feb 25, 2024

@mstorsjo: I certainly don't mind if this finds its way upstream, its self-contained enough so that changes can be done in future MRs.

@mstorsjo
Copy link
Owner

@mstorsjo: I certainly don't mind if this finds its way upstream, its self-contained enough so that changes can be done in future MRs.

Ok, I've merged those patches now then, so I guess this PR can be closed.

@nolange
Copy link
Contributor Author

nolange commented Feb 26, 2024

You could've just... you know... accepted the PR?

@nolange nolange closed this Feb 26, 2024
@mstorsjo
Copy link
Owner

You could've just... you know... accepted the PR?

Oh, right, indeed, sorry about that.

At some point I considered if I wanted to tune some of the commits before merging, but I guess I could have done that by pushing to your branch and then merging the PR as well. Anyway, thanks for the contribution!

@nolange nolange deleted the system-clang branch March 12, 2024 09:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants