Background

Today, I resumed a rust project of mine after a long time. In order to check my last working code, I ran cargo run . But it refused to run with error message:



...."-Wl,-Bdynamic" "-l" "dl" "-l" "rt" "-l" "pthread" "-l" "pthread" "-l" "gcc_s" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util" "-l" "util" = note: /usr/bin/ld: cannot find Scrt1.o: No such file or directory collect2: error: ld returned 1 exit status

Linker Issues!

ld is used to link libraries. So, the error was not in the code but in the linking phase. I googled the error and the solution was to have build-essential package installed. But the package was already installed on my machine (it is one of the first packages I install on any development machine).

Some more googling revealed that cargo uses the system cc linker to link to the C runtime. Running which cc gave me $HOME/anaconda3/bin/cc . This cc is part of my Anaconda root environment. (Anaconda is a package manager for scientific computing packages. It is a convenient way for installing multiple versions of packages in different environments).

On Linux, the linker knows where to find the required libraries using the shared library cache. I ran ldconfig -v to refresh it and then try again. Same error!

It is possible to explicitly list directories to include using LD_LIBRARY_PATH environment variable. I tried setting the LD_LIBRARY_PATH to point to the required directory and then run cargo as LD_LIBRARY_PATH=DIR cargo build -v . But it gave the same error.

I thought that cargo must be setting the linker value somewhere, so instead let me try directly compiling with rustc . Even that gave the same error. With this, I eliminated the possibility of some environment variable only affecting cargo .

More googling!

Further searching for the error with "rust" added showed me results of people having trouble cross-compiling. From this, I learned that cargo has different targets i.e different instruction sets (e,g x86-64, arm, x86, mips), different OSs (e.g linux, windows, freebsd) and different C runtimes (e.g glibc, musl, msvc). The Rust documentation on cargo mentioned that this is called a target triple. The Cargo book mentioned that you can direct cargo to explicitly use a particular linker using RUSTFLAGS environment variable.

Since I am only building for my machine, I had to find out the exact value of the target. Rust gives an exhaustive list of all supported targets by running rustc --print target-list . My target was x86_64-unknown-linux-gnu .

It is possible to pass a linker to cargo explicitly as RUSTFLAGS="-C linker=x86_64-unknown-linux-gnu" cargo build -v . It worked!

I do not want to do this every time I run cargo . The Cargo book says that cargo uses a global config file in $HOME/.cargo/config .

I added the following to the file:



# Specify which linker to use for this target [target.x86_64-unknown-linux-gnu] linker = "x86_64-linux-gnu-gcc"