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

Config requirements for LLVM bindings #14376

Open
straight-shoota opened this issue Mar 20, 2024 · 3 comments
Open

Config requirements for LLVM bindings #14376

straight-shoota opened this issue Mar 20, 2024 · 3 comments
Labels
platform:unix platform:windows Windows support based on the MSVC toolchain / Win32 API status:discussion topic:stdlib:llvm

Comments

@straight-shoota
Copy link
Member

straight-shoota commented Mar 20, 2024

The bindings for libllvm have some specific requirements for discovering LLVM configuration. The details differ between Unix and Windows, but either way they expect a specific setup and the availability of llvm-config or llvm_VERSION (the latter is only provided for the packaged libllvm in the Crystal package on Windows).
This all works for the most common use cases. But there are serious challenges for more advanced use cases such as cross-compiling, targeting a non-default LLVM version, or just doing semantic analysis without codegen.

For example, when cross-compiling the LLVM bindings from a Unix-like system to Windows, compilation fails due to missing llvm_VERSION file:

$ make crystal target=x86_64-windows-mscv
Using /home/linuxbrew/.linuxbrew/bin/llvm-config [version=17.0.6]
CRYSTAL_CONFIG_BUILD_COMMIT="b11be6a74" CRYSTAL_CONFIG_PATH='$ORIGIN/../share/crystal/src' SOURCE_DATE_EPOCH="1710852755" CC="/home/linuxbrew/.linuxbrew/bin/gcc-13 -fuse-ld=lld" CRYSTAL_CONFIG_LIBRARY_PATH='$ORIGIN/../lib/crystal' ./bin/crystal build -D strict_multi_assign -D preview_overload_order --cross-compile --target x86_64-windows-mscv -Dwithout_interpreter  -o .build/crystal src/compiler/crystal.cr -D without_openssl -D without_zlib -D use_pcre2
Showing last frame. Use --error-trace for full trace.

In src/llvm/lib_llvm.cr:9:10

 9 | {% raise "Cannot determine LLVM configuration; ensure the file `llvm_VERSION` exists under `CRYSTAL_LIBRARY_PATH`" %}
        ^----
Error: Cannot determine LLVM configuration; ensure the file `llvm_VERSION` exists under `CRYSTAL_LIBRARY_PATH`

It's not possible to explicitly set $LLVM_VERSION or $LLVM_CONFIG, they'll just get ignored.

$LLVM_CONFIG of course could only work if an approriate llvm-config is available. Cross-compiling from Windows to Unix, this wouldn't be the case, for example.

I think this should all work without special requirements and I can't see a reason why it couldn't be possible to pass in all the necessary information explicitly.

We should also consider what information is really needed for the llvm bindings. llvm_VERSION currently provides the version, build targets and ldflags. On Unix-like sytems, the same information is retrieved from llvm-config
As far as I can see, only the LLVM version is strictly required. We need it in order to target the correct API version.
Build targets could assume just the current target if no other information is available.
Linker flags are potentially irrelevant when cross-compiling, so it shouldn't be a show-stopper if they're missing. You can always provide them on the command line explicitly.

So I think we should make it that the LLVM bindings work (for both Unix and Windows) when only $LLVM_VERSION is provided and neither llvm_VERSION nor llvm-config are available.

@HertzDevil
Copy link
Contributor

For the record, this also applies to other libraries that require the version to be determined at build time, e.g. Boehm GC and OpenSSL

@ysbaddaden
Copy link
Contributor

I'd love to be able to specify the library version for EVERY external library, not just LLVM. That would make cross compilation of any app much easier!

@straight-shoota
Copy link
Member Author

straight-shoota commented Oct 16, 2024

Yes, that would be the ideal solution in a next step. This issue in particular focuses on libllvm bindings because they literally break when llvm-config (Unix) or llvm_VERSION (Windows) are missing and there's no way to prevent that.
Other library bindings like libgc and libssl use pkg-config to look up the version1 and have a somewhat reasonable ( #14254) fallback if version info is not available.

Footnotes

  1. libssl actually has some more complex discovery because it needs to discern between OpenSSL and LibreSSL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platform:unix platform:windows Windows support based on the MSVC toolchain / Win32 API status:discussion topic:stdlib:llvm
Projects
Status: Todo
Development

No branches or pull requests

3 participants