How do I change the default rustc / Cargo linker? - rust

I would like to make rustc use lld as a linker instead of ld in a particular crate. So I create .cargo/config in my project directory with the following:
[target.x86_64-unknown-linux-gnu]
linker = "ld.lld"
Which leads to linker errors:
$ cargo build
...
= note: ld.lld: error: unable to find library -ldl
ld.lld: error: unable to find library -lrt
ld.lld: error: unable to find library -lpthread
ld.lld: error: unable to find library -lgcc_s
ld.lld: error: unable to find library -lc
ld.lld: error: unable to find library -lm
ld.lld: error: unable to find library -lrt
ld.lld: error: unable to find library -lpthread
ld.lld: error: unable to find library -lutil
ld.lld: error: unable to find library -lutil
Same thing with rust-lld. If I set linker = "ld" (which should be the default, right?), I just get
= note: ld: cannot find -lgcc_s
I tried to resolve all the missing libraries manually (with -C link-arg=--library-path=/usr/lib/x86_64-linux-gnu and the like), but it only lead to wrong linkage and a segfaulting binary.
Interestingly enough, if I replace /usr/bin/ld with a symlink to /usr/bin/ld.lld, it works great (no errors, and from the compiled binary I see that it was indeed linked with lld). However, I don't want to make lld my system-wide linker, I just want to use it in a particular Rust crate.
So what is the proper way to change the default rustc linker?

Thanks to #Jmb comment, I found a solution. Turns out that the default linker that rustc uses is actually cc (which makes sense - it supplies all the needed defaults to compile/link C code, which also work for Rust). We can pass an argument to cc to make it link with lld:
[target.x86_64-unknown-linux-gnu]
rustflags = [
"-C", "link-arg=-fuse-ld=lld",
]
Now cargo build links with lld.

Adding this to Cargo.toml or .cargo/config.toml (in the project) forces using lld
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "link-arg=-fuse-ld=lld"]
[target.x86_64-pc-windows-gnu]
rustflags = ["-C", "link-arg=-fuse-ld=lld"]
[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "linker=clang", "-C", "link-arg=-fuse-ld=lld"]
For more information see this:
https://github.com/rust-lang/rust/issues/71515
You can remove "-C", "linker=clang" on Linux, if you have Gcc 9 or newer installed

This also works and is what I think #Jmb actually asked.
rustflags = [
"-C", "linker=clang-12", # change the version as needed
]

Related

Linking Rust to LLVM API in Cargo.toml

I'm using a library that wraps the LLVM-C API (inkwell) so I need to link my Rust binary to the LLVM library. If I export the following rust flags with:
export RUSTFLAGS=-lLLVM-12 -lm -ldl -lc -lpthread -lutil -lgcc_s -C link-args=-L/usr/lib/llvm/12/lib64
Then compilation runs fine.
If I then insert these lines into my Cargo.toml file for the project however:
[build]
rustflags = ["-lLLVM-12", "-lm","-ldl","-lc","-lpthread","-lutil","-lgcc_s", "-C", "link-args=-L/usr/lib/llvm/12/lib64"]
Then I get linking errors against LLVM-C functions.
Why does this work with an environment variable but not in my cargo config file? Am I msiconfiguring cargo in some way?
According to Cargo documentation, rustflags property is documented via .cargo/config.toml, not Cargo.toml.

Compiling binary using dynamic libraries

I have 20 shared objects files, and I want to use one function from the let`s say "a.so"
but my problem is that a.so is linked to other libraries.
When i compile my main i get the following error:
/usr/bin/ld: warning: b.so, needed by /home/test/lib/a.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: c.so, needed by /home/test/lib/a.so, not found (try using -rpath or -rpath-link)
How can i compile my main that i would be able to use the function in a.so ?
I have tried to use this method: gcc -L. -WL, -rpath,. main.c -l{libraryName} -o main
but i get the following error:
gcc: error: unrecognized command line option ‘-WL,’; did you mean ‘-Wa,’?
gcc: error: unrecognized command line option ‘-rpath,.’
When i compile my main i get the following error:
There are two mistakes in above statement:
you get a warning, not an error, and
you get it when you link your program, not when you compile it.
How can i compile my main that i would be able to use the function in a.so ?
Like so:
gcc -L. -Wl,-rpath=. main.c -l{libraryName} -o main
P.S. In general, it's a bad practice to have -rpath as a relative path, because the program will not work if you invoke it from a different directory. A better solution is to use absolute -rpath instead:
gcc -L/home/test/lib -Wl,-rpath=/home/test/lib main.c -l{libraryName} -o main

Linker is unable to locate curl_global_init

I am compiling a C++ application on Ubuntu 18.04.
The linker is unable to pickup the required functions from the library or it is not locating the right library
I have libcurl.so located at /usr/local/lib
nm -D lists all the functions I need with T prefix. Yet when I compile as follows
g++ -std=c++17 -lcurl tz.o main.o
I get
/usr/bin/ld: tz.o: in function 'date::curl_global()':
tz.cpp:(.text+0x9aef): undefined reference to 'curl_global_init'
I tried installing openssl-dev. No joy. So I uninstalled it.
try
g++ -std=c++17 tz.o main.o -lcurl
instead... g++ is shit in some ways, like argument ordering. (all i did was to make -lcurl the last argument instead of argument #3)

Linking error: DSO missing from command line

I am rather new to Linux (using Ubuntu 14.04 LTS 64bit), coming from Windows, and am attempting to port over an existing CUDA project of mine.
When linking via
/usr/local/cuda/bin/nvcc -arch=compute_30 -code=sm_30,compute_30 -o Main.o Display.o FileUtil.o Timer.o NeuralNetwork.o -L/usr/lib -L/usr/local/lib -L/usr/lib/x86_64-linux-gnu -L/usr/local/cuda/lib64 -lGLEW -lglfw3 -lGL -lGLU -lcuda -lcudart
I encounter the following error:
/usr/bin/ld: /usr/local/lib/libglfw3.a(x11_clipboard.c.o): undefined reference to symbol 'XConvertSelection'
//usr/lib/x86_64-linux-gnu/libX11.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make: *** [CUDANN] Error 1
The answer seems closely related to the solutions in this post (Strange linking error: DSO missing from command line), though given my inexperience with Linux I was unable to adapt them to my own problem.
Any ideas on what the problem could be?
Here is the full output during compilation: https://gist.github.com/wbolden/857eddd11e4dcb915c02
And here is my attempt at a Makefile:
https://gist.github.com/wbolden/135033daae04ed0d8cf3
Hopefully this will be of help to those, like me, who are new to Linux and don't find anything related to Linux to be particularly obvious.
As noted by talonmies, I am not able to link indirectly and as such need to specify any additional libraries required by the libraries I am using. That is to say, if I link library A, which requires libraries B and C, I need to link all three libraries for the program to link correctly.
To find what other libraries were needed I used the pkg-config command, for which I found a guide here. Running pkg-config --print-requires --print-requires-private glfw3 gave the following output, which is the list of packages required by glfw3.
x11
xrandr
xi
xxf86vm
gl
I was then able to find what libraries I needed to include by running pkg-config --libs, followed by the name of the library. For example, pkg-config --libs x11 yielded -lX11.
Note: you can pass multiple items to pkg-config as input, so running
pkg-config --libs $(pkg-config --print-requires --print-requires-private glfw3)
will print out all the additional libraries you need to link (-lX11 -lXrandr -lXi -lXxf86vm -lGL).
My program now links successfully, I hope this helpful to anyone with a similar problem.
Your linker need X11 library,You need to specify -lX11 to linker
Try
/usr/local/cuda/bin/nvcc -arch=compute_30 -code=sm_30,compute_30 -o Main.o Display.o FileUtil.o Timer.o NeuralNetwork.o -L/usr/lib -L/usr/local/lib -L/usr/lib/x86_64-linux-gnu -L/usr/local/cuda/lib64 -lGLEW -lglfw3 -lGL -lGLU -lcuda -lcudart -lX11
Try to add -pthread at the end of the library list (command line) in the Makefile.
It worked for me.
Use the following commands to fix the issue:
FLAGS=-lX11 ./configure --prefix=/usr --disable-static
make
make install

linux linker: '-lpng' inhibits '-lz'?

On ubuntu-13.04, I got an error when building an executable from shared libraries, using GCC-4.7.3 provided by the linux distribution.
I guess the problem is between libpng and zlib (the former uses the latter), but I don't know why.
First, my command is:
$ gfortran -o test_muesli_config_fml test_muesli_config_fml.o -fopenmp
-Wl,--rpath,/usr/local/lib/muesli /usr/local/lib/muesli/libfml.so -lstdc++
-Wl,--rpath,/usr/lib /usr/lib/liblapack.so -Wl,--rpath,/usr/lib /usr/lib/libblas.so
-lpng -lz -lpthread -lreadline -lhistory
which gives the following error:
/usr/local/lib/muesli/libfml.so: undefined reference to `gzwrite'
/usr/local/lib/muesli/libfml.so: undefined reference to `gzopen'
/usr/local/lib/muesli/libfml.so: undefined reference to `gzclose'
/usr/local/lib/muesli/libfml.so: undefined reference to `gzread'
collect2: error: ld returned 1 exit status
But note that -lz is present. After that, I added the linker option --trace-symbol= in order to get more information:
$ gfortran -o test_muesli_config_fml test_muesli_config_fml.o -fopenmp
-Wl,--rpath,/usr/local/lib/muesli /usr/local/lib/muesli/libfml.so -lstdc++
-Wl,--rpath,/usr/lib /usr/lib/liblapack.so -Wl,--rpath,/usr/lib /usr/lib/libblas.so
-lpng -lz -lpthread -lreadline -lhistory -Wl,--trace-symbol=gzwrite
which in turn gives the results:
/usr/local/lib/muesli/libfml.so: reference to gzwrite
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libz.so: definition of gzwrite
/usr/local/lib/muesli/libfml.so: undefined reference to `gzwrite'
/usr/local/lib/muesli/libfml.so: undefined reference to `gzopen'
/usr/local/lib/muesli/libfml.so: undefined reference to `gzclose'
/usr/local/lib/muesli/libfml.so: undefined reference to `gzread'
collect2: error: ld returned 1 exit status
so, gzwrite is found in libz.so but the linker don't use it!
By chance, I thought to remove the -lpng option (actually, the libpng library is not used) and my problem is solved! Why?
Secondly, I compile my whole code with another version of GCC-4.7.3 (compiled by myself -- I am used to test many versions of the compiler), and the error didn't occur, even using both -lpng and -lz!
Any idea?
In addition, a different try with another program (which USE libpng) leads to a successful build.
Edited on 2013-10-08
I'm pretty sure now that it is a bug in ubuntu-13.04: I've tried two other linux distros (Fedora 16 -- Ubuntu-10.04) and the linker behavior is standard, not as described above in the first part of my message.
I plan to report this problem on ubuntu community. Regards.
Edited on 2013-10-09
The bug has been reported to https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1237270
Two possible fixes (until ubuntu doesn't repair itself):
Try to compile in libpng.a and libz.a as a static library (it can be only a temporary solution, because static libs are evil in most cases).
Recompile libpng from the original source, and compile libz.a as static herein.

Resources