-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Halide doesn't build with brew-installed LLVM on OSX using Make #7055
Comments
Note: the Homebrew setup above fails in a similar way with CMake (you must specify |
Looks like https://github.com/orgs/Homebrew/discussions/3666 is the likely issue |
I haven't tried your build using
works. For
should work. |
It's good to know that exists as a workaround, but this is clearly an undue burden on downstreams. Homebrew should not break default-setting compatibility with Xcode/AppleClang. |
This is hardly a burden, because there are multiple trivial workarounds you can use that can even be encoded portably in a What is an undue burden is insisting that everyone else's builds and binaries that link to LLVM libraries should be slower in order to simplify linking with LLVM's static libraries -- which I'll note is a comparatively uncommon use-case. Most users install Homebrew LLVM for the bundled toolchain or as a dependency of another Homebrew package. Relying on static libraries isn't even portable; most distributions either don't ship them at all or ship an incomplete set. Homebrew likely would not either if it wasn't more work to just remove them. So, no, in the case of static libraries, I view seamless compatibility with Apple Clang as nice-to-have but not essential. If this affected more than the static libraries, then that would be something else, but all evidence so far suggests otherwise. |
Show the code, please. I don't think this is anywhere close to portable or trivial. |
Your own suggestion showing how to link to the shared libraries seems to require another flag ( |
You have. Linking with the shared libraries works as before. The extra configuration is required to link with the static libraries. See the error message quoted above:
I don't even know why you're linking with a static LLVM library when Note that I said only that incorporating the necessary build flags into your What is trivial are the end-user workarounds. They can do export LDFLAGS=-Wl,-lto_library,/path/to/llvm/lib/libLTO.dylib or export CFLAGS=-fuse-ld=/path/to/llvm/bin/ld64.lld
export CXXFLAGS=-fuse-ld=/path/to/llvm/bin/ld64.lld This can be simplified to export CFLAGS=-fuse-ld=lld
export CXXFLAGS=-fuse-ld=lld if export CC="$(brew --prefix llvm)/bin/clang"
export CXX="$(brew --prefix llvm)/bin/clang++" will also work fine. Setting This isn't too much of a leap above what you already require Homebrew LLVM users to do:
However, if it really is so onerous, Homebrew users can use This is not available for users who need to build Halide from a specific version/commit, but I'm guessing that these users will be able to handle needing to set an extra flag or two to get things to work. It's likely that anyone looking to do this needs a specific version of LLVM anyway, in which case what is provided by Homebrew will likely not suit. As for code samples, here is one: https://github.com/banach-space/llvm-tutor/blob/65e163b676199deaf68e76ac6f2ef26458d75429/tools/CMakeLists.txt Here's another: cmake_minimum_required(VERSION 3.10)
project(test)
set(CMAKE_CXX_STANDARD 14)
find_package(LLVM REQUIRED)
add_executable(test test.cpp)
target_include_directories(test PRIVATE ${LLVM_INCLUDE_DIR})
target_link_libraries(test LLVMCore LLVMPasses LLVMIRReader LLVMSupport)
if(APPLE)
find_library(LTO_Library LTO HINTS ${LLVM_LIBRARY_DIR})
if(LTO_Library)
set_target_properties(test PROPERTIES LINK_OPTIONS "-Wl,-lto_library,${LTO_Library}")
endif()
endif() But I imagine you can do better if you took more than the few minutes I spent putting this together. In any case, even if I am mistaken about how trivial the workarounds are: I still stand by my initial position that not requiring them to link with static libraries is only nice-to-have. |
We are not. The source of my belief is what you said here:
I am glad to know that setting
That is not what you said. Quoting you, again,
Are you arguing that encoding a "trivial workaround" portably may not itself be trivial? If so, maybe the workaround isn't so trivial in the first place...
We must have entirely different mental models of what end-users will consider "trivial".
Is isn't for our users because they might want to write cross-platform software (which LLVM and Halide both are), but on Windows, LLVM does not support shared linking, full stop. So for many users, being able to link statically isn't merely nice-to-have, it's a hard technical requirement.
The |
Of course there is a distinction between passing flags to your build and handling them generically with That said, we don't have to agree on what is and isn't trivial:
What is the error message? Is your CI cross-compiling?
Check the output of the
Only if you need the static libraries. This applies to a small enough set of users that it just doesn't outweigh the benefit to all the others. |
I'll bite... how does Meson handle this issue differently than (C)Make? |
At this point it seems clear that Homebrew is taking a direction that doesn't work well with Halide, and that direction isn't likely to change anytime soon, so I suspect that the right answer here is for Halide to find an alternate recommendation for OSX users who want to install current versions of LLVM. |
This makes sense. I apologise for the breakage. If fixing it came for free, other than the time I put into it, I'd fix it. But it doesn't. However, if there are issues beyond linking with static libraries, those will need to be fixed. Feel free to file an issue at https://github.com/Homebrew/homebrew-core/issues, if you still have users who use our build of LLVM. |
If I understand correctly, the thing that was removed was machine-code versions of llvm static libraries. Now the only versions that ship contain bitcode instead, and are useless to, e.g. gcc. Sounds like we should to change our instructions to say that if you use homebrew, you must either use homebrew llvm as your toolchain, or only use Halide as a shared library. Maybe this is silly for some reason, but why not add a homebrew llvm static library package that contains actual machine code rather than bitcode? |
Indeed this seems like a possible compromise because, after a conversation I had with Thiago Macieira, it seems that LTO static libraries can only be linked by the exact compiler build (not version) that produced them. That is, passing |
For the last few days, Meson's own internal unit test "frameworks: 15 llvm (method=config-tool link-static=True)", which attempts to find llvm (using llvm-config) and link to it statically, fails with the same error as the original bug report here. (Shared linking works fine.) So I guess the answer is that Meson handles this exactly like CMake does, and that's why Meson too is broken. But perhaps people only specifically ask for static libraries in unittests of a build system, who knows. :) |
They also ask for them pretty consistently in all sorts of deployment scenarios. Very many (a majority?) of our customers statically link LLVM's libraries to ours. Again, based on my conversation with Thiago, I think the compilers are doing the right thing by rejecting these binaries. The only toolchain with which it is reasonable to expect them to work is the exact toolchain that created them. Hacks to trick the compiler into accepting them might well lead to corrupted builds. Between Halide and Meson both having issues with this change, maybe it should yet be reconsidered... |
This would be a surprise to me, because this is essentially the mechanism by which LTO bootstrap builds on Darwin worked for years. In fact there are some hacks in LLVM's CMake scripts that are specifically designed to force host tools (e.g. Apple's Not to mention that the just-built Of course, you could be of the view that it's okay when
No, not silly at all. I quite like this idea, and will look into it. However, there may be something even better available. It appears Fedora also build their toolchain with ThinLTO, but somehow they take the bitcode inside the static archives and transform them into ELF during the build process. I don't know yet how Fedora does this, or whether it can be translated to MachO (and if so, how), but this seems to me to be the best solution here. Edit: This is how Fedora does it: https://src.fedoraproject.org/rpms/redhat-rpm-config/blob/rawhide/f/brp-llvm-compile-lto-elf It seems like doing the exact same thing on macOS should work, but I'll need a bit to experiment with it. |
Implemented in Homebrew/homebrew-core#112154. Building Halide from the tip of the main branch succeeds when LLVM is rebuilt with those changes. |
In Homebrew#106925, I enabled LTO for our LLVM build. This creates static archives that contain LLVM bitcode instead of object code. This makes the static archives more difficult to use, requiring workarounds such as https://github.com/Homebrew/homebrew-core/blob/c01f1794fc3decce04b71cae03966213fc7af34d/Formula/enzyme.rb#L30 and has caused problems for multiple downstream projects. We can fix this by converting the bitcode into object code, which is what Fedora does with their LLVM build. They also build their toolchain with LTO. Alternatively, we can disable LTO, but that foregoes significant speedups we get from enabling it. While we're here, let's add some test coverage for features that were recently enabled that we don't test. Fixes: ziglang/zig#12923 halide/Halide#7055 mesonbuild/meson#10879 Homebrew/discussions#3666
In #106925, I enabled LTO for our LLVM build. This creates static archives that contain LLVM bitcode instead of object code. This makes the static archives more difficult to use, requiring workarounds such as https://github.com/Homebrew/homebrew-core/blob/c01f1794fc3decce04b71cae03966213fc7af34d/Formula/enzyme.rb#L30 and has caused problems for multiple downstream projects. We can fix this by converting the bitcode into object code, which is what Fedora does with their LLVM build. They also build their toolchain with LTO. Alternatively, we can disable LTO, but that foregoes significant speedups we get from enabling it. While we're here, let's add some test coverage for features that were recently enabled that we don't test. Fixes: ziglang/zig#12923 halide/Halide#7055 mesonbuild/meson#10879 Homebrew/discussions#3666 Closes #112154. Signed-off-by: Sean Molenaar <1484494+SMillerDev@users.noreply.github.com> Signed-off-by: BrewTestBot <1589480+BrewTestBot@users.noreply.github.com>
Fixed, thanks @carlocab! |
A user who was trying to follow the tutorial steps on a Mac laptop reported (and I confirmed) that attempting to use a homebrew-installed version of LLVM doesn't build properly, for reasons that aren't clear.
Steps to repeat:
export LLVM_CONFIG=/path/to/brew/llvm-config
(eg/usr/local/opt/llvm/bin/llvm-config
on my system)Results on my system:
(Apparently, AArch64AsmParser.cpp.o contains LLVM bitcode, not x64 native code?)
Results on user's system:
The text was updated successfully, but these errors were encountered: