I have a Rust crate A that depends on another Rust crate B; both of them are STD-clean (i.e. both use #![no_std]) and there are no other dependencies. I would like to get my hands on the LLVM IR of all the code needed to statically link it together with lld.
To get the LLVM IR from just A, I am currently passing --emit=llvm-ir to cargo rustc. This results in target/debug/deps/A-someKindOfHash.ll which I can then consume -- in my case, by using Clang to link it with some C code that calls (non-mangled) Rust functions.
However, that .ll file doesn't contain all transitive dependencies, so as soon as A actually starts using functions from B, this breaks down.
How do I tell Cargo to create LLVM IR from all dependencies and put them somewhere under target/?
Related
My rust crate relies on a single C source file (whose functions aren t used for export outside the crate) using clang specific s C language extensions.
What s the syntax for not using gcc or Microsoft cl, but always forcing the use of clang inside build.rs?
There's a crate I want to use as a library for some of my own code (speedtest-rs specifically, but it doesn't really matter). However, whenever I try to use this crate, the compiler doesn't want to play nice with it.
$ cargo build
Compiling my-project v0.1.0 (/home/nick/Documents/code/my-project)
error[E0432]: unresolved import `speedtest_rs`
--> src/main.rs:1:5
|
1 | use speedtest_rs::*;
| ^^^^^^^^^^^^ use of undeclared type or module `speedtest_rs`
Looking at the Rust book, it seems like there's a distinction between a binary and library crae
The rand crate is a library crate which contains code intended to be used in other programs
Some googling has shown me that binary crates just have an extra link step, so I should be able to link against them, right? I know a lot of Rust packages have both a library and a binary in them, but what do you do when an author does not seem to follow this pattern?
Some googling has shown me that binary crates just have an extra link step, so I should be able to link against them, right?
No. It's not that simple. Plus that extra step creates an executable file rather than a library file. An executable cannot be used as a library.
I know a lot of Rust packages have both a library and a binary in them, but what do you do when an author does not seem to follow this pattern?
You can:
Ask them on GitHub to publish a library.
Fork the crate and make your own library (which you can do since it is published with the usual dual “Apache License, Version 2.0” + “MIT” license).
There isn't an automated way to use a binary crate as a library because in particular:
Rust won't generate a library.
Since the crate is missing a src/lib.rs file, nothing is exported. This is akin to have all items in that crate private. You wouldn't be able to use anything.
I am trying to link some executable (which compiled with gcc) with the library that is compiled with cargo build.
cargo generates both .a and .so libraries from the code written in Rust language.
The linkage error is:
/sharedhome/maxaxe01/mbed-cloud-client-example-internal/mbed-cloud-client/parsec-se-driver/target/debug/libparsec_tpm_direct_se_driver.a(compiler_builtins-2541f1e09df1c67d.compiler_builtins.dh9snxly-cgu.0.rcgu.o): In function `__udivti3':
/cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.25/src/int/udiv.rs:247: multiple definition of `__udivti3'
/usr/lib/gcc/x86_64-linux-gnu/7/libgcc.a(_udivdi3.o):(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
As I understand, the problem that some low level processor math function defined twice, in my libgcc and RUST system library compiler_builtins-0.1.25/src/int/udiv.rs May be somebody has some idea how to solve this?
If I link executable with library as shared object, it is successfully linked, but I need to compile with static lib! (cargo build generates both, .so and .a)
This thread ("multiple definition of `memcmp" error when linking Rust staticlib with embedded C program) does not help me.
If the two versions of the function __udivti3 are equivalent, you could try linking your program with -Wl,--allow-multiple-definition. This is obviously an ugly hack and I would be interested in getting a proper solution, but it worked for me. I was getting a similar conflict on __muloti4 between the compiler-builtins crate (part of the standard library) and a static version of LLVM libc++.
Obviously, I am assuming that using a cdylib is not an option for you and your Rust library needs to be static.
I would like to compile a Rust program/project to Wasm for use within my Python application using python-ext-wasm. The existing tutorials assume that it's for the web and suggest wasm-pack. Is there another way of just compiling Rust to Wasm without JavaScript bindings?
For example, if I have a Rust program (myproject/math.rs).
#[no_mangle]
pub extern fn sum(x: i32, y: i32) -> i32 {
x + y
}
How do I convert that into a wasm file without webpack?
How do I take an entire project (with it's library dependencies) and compile all of them to Wasm?
You can compile WebAssembly directly with cargo build --target wasm32-unknown-unknown. This is essentially what other tooling like wasm-pack and wasm-bindgen are built around, and if you don't want that (e.g. if you're not targeting JavaScript) you can just use that to compile directly to WebAssembly.
Some caveats though:
All communication between the WebAssembly module and host must happen with extern functions. This means that there's only a limited number of types that can be used, mostly primitive types (integers, floats, booleans and pointers). You won't be able to pass complex types unless you're using an additional layer of abstraction on top (which is what wasm-bindgen does).
Large parts of the standard library (including file systems and networking, for instance) is not supported by the wasm32-unknown-unknown target. If your WebAssembly host supports WASI (WebAssembly System Interface), you can use the wasm32-wasi target instead to compile a module with WASI support, which supports much more of the standard library.
I'm currently hacking my way through trying to make quasiquotes for writing Rust code inline in Haskell. I think I have the code generation work done (including things like marshaling Haskell types to and from generated Rust ones). I now have the problem of figuring out how to do all the compilation and linking from within Template Haskell. The pipeline is as follows:
The quasiquote gets parsed
Source code is generated for
a corresponding Rust function
Haskell FFI imports
the Haskell call to the imported function
The Rust code gets compiled into a static library (like rustc --crate-type=staticlib qq_function.rs -o qq_function.a)
The Haskell code gets compiled and linked against qq_function.a (and a handful of other libraries like m, c, etc.)
My issue is getting steps 3 and 4 to happen entirely within TemplateHaskell. Here is as far as I've gotten:
runIO can write out the Rust source files that I've generated
addDependentFile informs GHC that the generated Rust file is a dependency
addForeignFile regrettably does not work for automatically managing the compilation since Rust is not a supported language (this is the approach inline-c takes since C is a supported language)
runIO could be used to generate the static Rust library (and delete the Rust source file afterwards) by calling out to rustc.
What is still very much not clear to me is
how I can use Template Haskell to add libraries against which to link and
how I can use Template Haskell to clean up these generated libraries afterwards?
EDIT
I've filed a GHC feature request related to this.