I try to follow the steps from this guide and install Crystal using brew on linux.
For this command brew install crystal-lang --with-llvm I get Error: invalid option: --with-llvm.
And if I use this one brew install crystal-lang it installs fine, although for the next step on hello world program I get this error.
I can reproduce a similar issue on an empty ubuntu image with homebrew installed:
$ docker run --rm homebrew/ubuntu22.04
# brew install crystal
# crystal run 'puts %(hello world)'
/home/linuxbrew/.cache/crystal/crystal-run-eval.tmp: error while loading shared libraries: libgc.so.1: cannot open shared object file: No such file or directory
In your case, there is probably a libgc.so.1 available in your path, but itâs not from homebrew and an older version missing the GC_get_my_stackbottom symbol.
A workaround is to specify the homebrew lib directory explicitly:
Probably the homebrew formula should configure CRYSTAL_LIBRARY_RPATH to point to homebrewâs lib directory. That should bake the lookup paths into the binary so it can find them even if homebrewâs lib directory is not in ldâs lookup path.
Thanks for taking a look on this
Not sure if itâs related, but I see the different LLVM version bundled into the snap package.
15.0.7 instead of 17.0.6
If delay-loading is removed on Windows, that would mean deprecating CRYSTAL_LIBRARY_RPATH on Linux too. On the other hand I donât know if a better solution exists (CRYSTAL_CONFIG_BUILD_OPTSâŚ?)
Yeah I think weâll need a feature to configure RPATH. And keeping the existing config variable should be good.
I went to see how runtim linking for binaries compiled with GCC from homebrew work. That should have the same need to find the libraries in homebrew lib.
$ brew install gcc
$ cat << EOF > test.c
unsigned GC_get_version(void);
int main() {
GC_get_version();
return 0;
}
EOF
$ gcc-13 test.c -o test -lgc
$ readelf -a test | grep -i linuxbrew
[Requesting program interpreter: /home/linuxbrew/.linuxbrew/lib/ld.so]
0x000000000000001d (RUNPATH) Library runpath: [/home/linuxbrew/.linuxbrew/lib/gcc/current:/home/linuxbrew/.linuxbrew/lib]
And indeed, the runpath is configured accordingly.
It seems the GCC formular is essentially doing the same thing as my RPATH patch: configure an implicit rpath that points to the homebrew lib dir for all produced binaries.
Additionally, in binaries built by GCC, the program interpreter als points to ld.so from homebrew. Not sure whatâs the specific purpose of that, though. Rpath is sufficient for library discovery. But I guess it generally makes sense to use homebrewâs linker as well.
I donât think thereâs a way to configure that in Crystal.
Maybe via forwarding --link-flags�
So as long as Crystal is using Brewâs linker, isnât there no need for us to explicitly use Brewâs directories as the RUNPATH? A similar thing happens on Termux and Crystal doesnât need this config variable over there
So this has exactly the same result as the C binary. No need for explicit runpath configuration.
However, there is currently no way to configure the compilerâs default linker. I suppose it should be pretty straightforward to introduce CRYSTAL_CONFIG_CC, though.
This would require adding gcc as a dependency of the Crystal formula. Currently it is not a dependency. Crystal just uses the default cc, which may come from a system package.
Iâm also curious if the brew install crystal-lang --with-llvm should be fixed as well. I donât see the --with-llvm option inside brew package. Is it obsolete for the current version?
Once again, I am not sure if we should do anything to RPATH from the compiler itself, since we know that is broken on Windows. Can you simply set CRYSTAL_CONFIG_CC="cc -Wl,-rpath,..."?
I suppose we could do that as well.
I explicitly made two separate PRs so we can merge only one or both.
In the current situation with CRYSTAL_LIBRARY_RPATH it makes sense to have a config value for that as well. But we can discuss the future of RPATH separately.
A probable cause for this issue is when pkg-config is from homebrew and and cc is not. (please let me know if you have this issue but this is not the case) pkg-config reports homebrew lib paths, so cc will pick up the libraries from homebrew while linking even when it doesnât know anything about homebrew itself.
But it does not configure rpath to include the homebrew lib dir (which gcc from homebrew does). So the system loader will only see the system libraries. If thereâs a discrepancy between homebrew and system libs, thatâs where it crashes.
So, a trivial resultion would also be to ensure you have both cc and pkg-config either installed from homebrew, or both not installed from homebrew. (in the latter case you might experience issues with linking libraries installed via homebrew)