I ran into a bunch of problems to get clang_sys statically linking with binaries built via msvc on Windows
Documenting the found issues here for a future fix.
Process to get static linking on clang 18.1.7
Stage 1: cmake configuration
Configuring cmake on llvm using the generator "Visual Studio 17 2022",
requires that LLVM_ENABLE_PIC also be turned off. Otherwise, it unsets LIBCLANG_BUILD_STATIC and builds shared DLL libraries.
-DLIBCLANG_BUILD_STATIC=ON-DLLVM_ENABLE_PIC=OFF
Cmake configure command:
cmake -G "Visual Studio 17 2022" -A x64 -T host=x64 -DLLVM_TARGETS_TO_BUILD=X86 -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_PIC=OFF -S <path/to/llvm-project>/llvm -B <build_dir>
Then built the binaries in configuration RelWithDebInfo|x64.
devenv.com LLVM.sln /Build "RelWithDebInfo|x64"
Followed by cmake install command:
cmake --install <build_dir> --prefix <install_dir> --config RelWithDebInfo
Stage 3: fixing build/static.rs link() to find libraries
Problem: Could not find libclang.lib
get_clang_libraries() searches for libclang*.a. Libraries on msvc are .lib.
Fix: changed get_clang_libraries() to switch the glob based on platform.
Problem: Could not find clang.lib.
get_library_name() strips the lib prefix from the filename, turning libclang -> clang. clang.lib doesn't exist in the install libraries AFAICT. If it does, there's some configuration in cmake I don't know about, but I didn't need a clang.lib in the end.
CLANG_LIBRARIES also refers to the nonexistent clang(.a/.lib).
Fix: removed get_library_name() call in get_clang_libraries(). Replaced it so it returned the filename libclang.lib
Problem: Unresolved external symbols (huge list here)
get_library_name() wasn't returning any of the other clang libraries that were also dependencies. E.G. clangAST.lib and friends.
Fix: added logic to get_clang_libraries() so it returned libclang.lib and any clang*.lib libraries in the <install>/lib directory.
Problem: Unresolved external symbol GetFileVersionInfoSizeW + 2 more.
This is from Version.lib, from C:/Program Files (x86)/Windows Kits/10/Lib/10.0.22621.0/um/x64
Fix: Added the appropriate cargo:rustc-link-search=C:/Program Files (x86)/Windows Kits/10/Lib/10.0.22621.0/um/x64 and cargo:rustc-link-lib=static=Version printlns at the end of link().
Caveat: I just hard-coded just to see if it will work. Need to find a more generic way to find Version.lib.
complete
And now it compiles and tests succeed with static linking.
Workflow Notes:
Need to compile using cargo test --features static -vv
cargo build doesn't try to link against the library, so it false-positively succeeds building if it can find a libclang.lib. Use cargo test instead.
--features static required to build with static linking from within the clang_sys crate
-vv is "very verbose" and will emit the println outputs from build.rs and static.rs.
I ran into a bunch of problems to get clang_sys statically linking with binaries built via msvc on Windows Documenting the found issues here for a future fix.
Process to get static linking on clang 18.1.7
Stage 1: cmake configuration
Configuring cmake on llvm using the generator "Visual Studio 17 2022", requires that
LLVM_ENABLE_PIC
also be turned off. Otherwise, it unsetsLIBCLANG_BUILD_STATIC
and builds shared DLL libraries.-DLIBCLANG_BUILD_STATIC=ON
-DLLVM_ENABLE_PIC=OFF
Cmake configure command:
cmake -G "Visual Studio 17 2022" -A x64 -T host=x64 -DLLVM_TARGETS_TO_BUILD=X86 -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_PIC=OFF -S <path/to/llvm-project>/llvm -B <build_dir>
Then built the binaries in configuration
RelWithDebInfo|x64
.devenv.com LLVM.sln /Build "RelWithDebInfo|x64"
Followed by cmake install command:
cmake --install <build_dir> --prefix <install_dir> --config RelWithDebInfo
Stage 2: Environment Variables
Created
.cargo/config.toml
containingStage 3: fixing
build/static.rs link()
to find librariesProblem: Could not find libclang.lib
get_clang_libraries()
searches forlibclang*.a
. Libraries on msvc are.lib
.Fix: changed
get_clang_libraries()
to switch the glob based on platform.Problem: Could not find clang.lib.
get_library_name()
strips thelib
prefix from the filename, turninglibclang
->clang
.clang.lib
doesn't exist in the install libraries AFAICT. If it does, there's some configuration in cmake I don't know about, but I didn't need a clang.lib in the end.CLANG_LIBRARIES
also refers to the nonexistentclang(.a/.lib)
.Fix: removed
get_library_name()
call inget_clang_libraries()
. Replaced it so it returned the filenamelibclang.lib
Problem: Unresolved external symbols (huge list here)
get_library_name()
wasn't returning any of the other clang libraries that were also dependencies. E.G.clangAST.lib
and friends.Fix: added logic to
get_clang_libraries()
so it returnedlibclang.lib
and anyclang*.lib
libraries in the<install>/lib
directory.Problem: Unresolved external symbol
GetFileVersionInfoSizeW
+ 2 more.C:/Program Files (x86)/Windows Kits/10/Lib/10.0.22621.0/um/x64
Fix: Added the appropriate
cargo:rustc-link-search=C:/Program Files (x86)/Windows Kits/10/Lib/10.0.22621.0/um/x64
andcargo:rustc-link-lib=static=Version
printlns at the end oflink()
. Caveat: I just hard-coded just to see if it will work. Need to find a more generic way to findVersion.lib
.complete
And now it compiles and tests succeed with static linking.
Workflow Notes:
Need to compile using
cargo test --features static -vv
cargo build
doesn't try to link against the library, so it false-positively succeeds building if it can find a libclang.lib. Usecargo test
instead.--features static
required to build with static linking from within the clang_sys crate-vv
is "very verbose" and will emit the println outputs from build.rs and static.rs.