Enzyme icon indicating copy to clipboard operation
Enzyme copied to clipboard

libLLVM.a doesn't exist, so fix how enzyme is linking LLVM

Open ZuseZ4 opened this issue 7 months ago • 3 comments

There are a couple of bugs in both Enzyme and LLVM, so it took me a while to figure this one out.

  1. linking against "LLVM" as a constant string only works if there's some type of libLLVM.something. We only have a libLLVM.so if we build LLVM as a dynamically linked library, which rust does e.g. for x86-64. There is no libLLVM.a equivalent otherwise, just a lot of individual archives.

  2. In theory, the right thing to fix this would be

llvm_map_components_to_libnames(llvm_libs all)
target_link_libraries(Enzyme-${LLVM_VERSION_MAJOR} ${llvm_libs})

However, "all" isn't being handled correctly, see https://github.com/llvm/llvm-project/issues/46347 It seems to be a common experience that some cmake macros are unreliable, so I was recommended to just call the llvm-config binary.

    execute_process(COMMAND ${LLVM_TOOLS_BINARY_DIR}/llvm-config --libs all
                OUTPUT_VARIABLE llvm_libraries)

Trying to also add the --ldflags fails the subsequent parsing:

CMake Error:
  Running

   '/usr/bin/ninja' '-C' '/home/manuel/prog/rust-new/build/x86_64-unknown-linux-gnu/enzyme/build' '-t' 'recompact'

  failed with:

   ninja: error: build.ninja:606: expected '=', got identifier

  -lLLVMWindowsManifest -lLLVMXRay -lLLVMLibDriver -lLLVMDlltoolDriver -lL...

                        ^ near here

so we have to add the -L somedir in yet another command.

  1. We therefore call
    set_target_properties(Enzyme-${LLVM_VERSION_MAJOR} PROPERTIES
        LINK_FLAGS "`${LLVM_TOOLS_BINARY_DIR}/llvm-config --ldflags`")

which correctly gives e.g. on my system -L/home/manuel/prog/rust-new/build/x86_64-unknown-linux-gnu/llvm/lib, where all the libLLVMSomething.a files are located.

So this still seems messy, but at least it should be more often correct than the current code. I'd be happy if someone else can fix it in upstream.

Alternative: Being more precise and only specifying llvm_map_components_to_libnames(llvm_libraries Passes) instead of trying to use all seems to work. But the recommendation seems to be the binary, so idk.

ZuseZ4 avatar May 04 '25 16:05 ZuseZ4

Also there is at least a 4th bug, but I think that one is on the rust side, where we at times pass the wrong llvm_dir (in cases like PGO builds, where we have multiple).

ZuseZ4 avatar May 04 '25 16:05 ZuseZ4

out.ll.txt

ZuseZ4 avatar May 04 '25 20:05 ZuseZ4

@wsmoses I don't understand how the julia build environment differs, especially the last commit was just a guess (since I don't know why zlib was previously commented out). However, it works. I'd probably try to again remove

        llvm_map_components_to_libnames(llvm_librariess Passes Support)
        target_link_libraries(Enzyme-${LLVM_VERSION_MAJOR} ${llvm_librariess})

once CI passed, given that I suspect that the ZLIB removal was the likely culprit for the build failure. Then, we'd be fully relying on llvm-config. Interestingly, rust CI also failed without the zlib change (even though it worked locally) https://github.com/rust-lang-ci/rust/actions/runs/14826389971/job/41620030778

Can you look into the precompilation failure? Also the Ubuntu runner got cancelled after an hour, not sure why. I didn't see any failures.

ZuseZ4 avatar May 05 '25 00:05 ZuseZ4