How to link a C library without calling one of its functions? - rust

I'd like to link with -lm. Right now, I'm doing it this way:
let _link_lm = f64::sin(3.0);
I tried putting this in .cargo/config:
[build]
rustflags = ["-C", "link-args=-lm"]
This doesn't dynamically link the library.
Also, using cargo:rustc-link-lib=m in a build script is the same as calling cargo rustc -- -lm which does not work either.
I check that the library is not linked with ldd.
It matters to link the library because this is for a JIT compiler which can call these functions by fetching them using dlsym.
How I can link to this library without calling one of its functions?

It turns out that rustc call the linker with -Wl,--as-needed, so the solution for me was to disable this option:
[build]
rustflags = ["-C", "link-arg=-Wl,--no-as-needed", "-C", "link-arg=-lm"]

Related

How to pass rustflags to artifact dependency binary?

I want to find a way to pass rustflags to artifact dependency bin.
Below is the story.
I write my toy OS currently, and using artifact dependency because this is suggested at rust-osdev/bootloader repositiory(descriptions are Booting section of this README) and I thought this is a useful way. However, I find that this way seems not to pass rustflags I attached in .cargo/config.toml in my kernel workspace like below.
[build]
target = "x86_64-unknown-none"
rustflags = ["-C", "relocation-model=static", "-C", "link-arg=-no-pie"]
[unstable]
build-std = ["core", "compiler_builtins"]
build-std-features = ["compiler-builtins-mem"]
In above config, I expect that kernel elf type is EXEC, but actually, that type is DYN, i.e. I got PIE Elf file even though I write static and no pie flags.
I tried some patterns like below.
run cargo build directly in kernel workspace directory
set invalid rustflags like link-args=hoge and run cargo build in root project directory
As a result
non pie elf (Elf type is EXEC) is created with no errors.
no errors appeared while compile even if I run cargo clean before build.
That's why, I suspect the rustflags I wrote in .cargo/config.toml does not work when its workspace is treated as binary artifact dependency.
Reproduction code is here.
If there is a way to pass rustflags, please teach me.
Add your build.rs in workspace, <project root path>/<kernel workspace name>/build.rs in my case, and put script like below in it.
fn main() {
println!("cargo:rust-link-arg=-no-pie");
}

How to add custom llvm pass into rustc

I am trying to add my llvm pass into Rustc. Rustc has one compiling option -C passes=val where we could add extra LLVM passes to run. However, as my try, this option can only accept the pass when the pass code is placed inside the LLVM code tree, but I want to add my pass out-of-tree into Rustc.
When I add my pass via this option:
RUSTFLAGS="-C passes=my-pass" cargo build
Compiler reports errors:
error: failed to run LLVM passes: unknown pass name 'my-pass'
Then I try to load my pass via -C llvm-args=-fpass-plugin=/opt/new-pass/mypass.so -C passes=my-pass in the clang way. It reports: rustc -Cllvm-args="..." with: Unknown command line argument '-fpass-plugin=/opt/new-pass/mypass.so'. Also tried to replace -fpass-plugin with other options like -load and -load-pass-plugin, but they still cannot be recognized by rustc.
How could I add my custom pass into Rustc?
I was trying to find a solution to this exact problem too. According to a rust developer on their Zulip Chat, it looks like you need to build a custom rustc with plugin support.

How do I pass the linker the -rlink argument?

I'm trying to cross compile a rust project with cross. My project depends on libcurl. The linker can find the libcurl .so but not the libraries which it depends on:
I'm running:
cross build -vv --target=arm-unknown-linux-gnueabihf
which gives me:
= note: /usr/arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: warning: libnghttp2.so.14, needed by /usr/lib/arm-linux-gnueabihf/libcurl.so, not found (try using -rpath or -rpath-link)
I've already confirmed that the library its looking for exists:
root#80a13d68ad84:/# find /usr/lib -name "libnghttp2.so.14"
/usr/lib/x86_64-linux-gnu/libnghttp2.so.14
/usr/lib/arm-linux-gnueabihf/libnghttp2.so.14
I've read about rust build scripts here, where I can add paths to the library search path, but that has not resolved the issue, this is what my build.rs looks like:
fn main() {
println!("cargo:rustc-link-search=native=/usr/lib/arm-linux-gnueabihf");
}
The error suggests using -rpath or -rpath-link, so how do I configure the rpath in rust? Or is there a different way to resolve this issue?
You might be able to specify linker arguments by using an environment variable like
RUSTFLAGS="-C link-arg=--rpath=..."
Cargo allows placing the same kind of flag in the configuration file (see here) but I'm not sure if cross has the same support for something like that.

How can I optionally pass rustc flags depending on a Cargo feature?

The program I'm writing runs much faster when the -C target-cpu=native flag is passed to rustc. I want to give users a simple, platform-independent way to enable this when compiling, so I added a Cargo feature cpu_native = [] in Cargo.toml and created this Cargo config in my project:
[target.'cfg(cpu_native)']
rustflags = ["-C", "target-cpu=native"]
However, this has no effect on my program, and passing --features cpu_native to Cargo does not even trigger a recompile. Changing to the following Cargo config does force re-compilation with faster instructions:
[build]
rustflags = ["-C", "target-cpu=native"]
However, this will compile with target-cpu=native with the default Cargo features, which was not what I wanted. From the Cargo book, what I want seems to be possible, but I don't see what I'm doing wrong.
I don't think this is supported (yet?). I enhanced Cargo to print out what config flags are checked against when resolving:
[
Name("debug_assertions"),
Name("proc_macro"),
KeyPair("target_arch", "x86_64"),
KeyPair("target_endian", "little"),
KeyPair("target_env", ""),
KeyPair("target_family", "unix"),
KeyPair("target_os", "macos"),
KeyPair("target_pointer_width", "64"),
Name("unix"),
]
[target.'cfg(cpu_native)']
This is the incorrect syntax for a Cargo feature; it would normally be cfg(feature = "cpu_native").

What does -fprofile-arcs linker option mean?

I want to have code covergage in my application, so in premake.lua I added the following:
if options["coverage"] then
tinsert(package.buildoptions, {"-fprofile-arcs", "-ftest-coverage"})
tinsert(package.links, "gcov")
end
then I ran the following command:
premake --coverage --target gnu ; make
That did not work until I added the following :
if options["coverage"] then
tinsert(package.buildoptions, {"-fprofile-arcs", "-ftest-coverage"})
tinsert(package.linkoptions, {"-fprofile-arcs"})
tinsert(package.links, "gcov")
end
Which was a solution posed on the Internet. My problem is that I found 0 documentation on this -fprofile-arcs linker flag... What does it do? and where is it documented?
This option is not given to the linker. It is interpreted by the compiler driver(gcc, g++).
When compiling, this option is just passed to the compiler (cc1, cc1plus).
When linking, the effect of the options is that the compiler driver just includes the -lgcov on the linker command line.

Resources