How to emit LLVM-IR from Cargo - rust

How can I get cargo to emit LLVM-IR instead of a binary for my project? I know that you can use the --emit=llvm-ir flag in rustc, but I've read some Github issues that show it's impossible to pass arbitrary compiler flags to cargo.
Is there any way I can get cargo to emit LLVM-IR directly?

There is cargo rustc to pass arbitrary compiler flags through Cargo to rustc. So I think:
cargo rustc -- --emit=llvm-ir
is what you want!
This will genarate a ll file in target\debug\deps\.

EDIT: You should use Jacob's answer instead; a lot easier and less hacky.
Build the project with cargo normally but add on the -v flag to show verbose output. The command will have a result like this:
casey#casey-ubuntu:~/Documents/project$ cargo build -v
Fresh aster v0.22.1
Fresh num-traits v0.1.34
Fresh itoa v0.1.1
...
Compiling project v0.1.0 (file:///home/casey/Documents/project)
Running `rustc src/main.rs --crate-name ...`
Finished debug [unoptimized + debuginfo] target(s) in 3.54 secs
If the command produces no output, make a change somewhere in your project code to trick the compiler into rebuilding it, since it will only rebuild if it detects a change in one of the files.
Copy the rustc command from inside the ` markers on the line starting with "Running `rustc..." and append --emit=llvm-ir to it.
This will produce a .ll file in your /target/debug folder.

Related

Difference between `cargo doc` and `cargo rustdoc`

According to doc.rust-lang.org
cargo rustdoc
build[s] a package's documentation, using specified custom flags
cargo doc
build[s] a package's documentation
What is the difference between the two? From what I understand cargo rustdoc is just like cargo doc, but it allows for more lints—for instance:
#![deny(rustdoc::broken_intra_doc_links)]
Is this correct? Oddly enough, cargo rustdoc will also fail in certain situations where cargo doc doesn't. For instance
some/folder on some-branch [$!] via 🦀 v1.60.0-nightly
❯ cargo doc
Finished dev [unoptimized + debuginfo] target(s) in 0.53s
some/folder on some-branch [$!] via 🦀 v1.60.0-nightly
❯ cargo rustdoc
error: manifest path `some/folder/Cargo.toml` is a virtual manifest, but this command requires running against an actual package in this workspace
Also, cargo doc does not support adding the -D option, whereas cargo rustdoc does.
❯ cargo doc -- -D rustdoc::broken_intra_doc_links
error: Found argument '-D' which wasn't expected, or isn't valid in this context
USAGE:
cargo doc [OPTIONS]
For more information try --help
Their relationship is like between cargo build and cargo rustc: cargo doc performs all the usual work, for an entire workspace, including dependencies (by default). cargo rustdoc allows you to pass flags directly to rustdoc, and only works for a single crate.
Here is the execution code for cargo rustdoc. Here is the code for cargo doc. The only differences is that cargo rustdoc always specify to not check dependencies while cargo doc allows you to choose (by default it does, but you can specify the flag --no-deps), and that cargo rustc allows you to pass flags directly to rustdoc with the flags after the --.

When should I use the --bin option for cargo new?

What is the difference between cargo new <project_name> --bin and cargo new <project_name>?
It seems both commands make exactly the same project; all components are consistent.
I think --bin stands for "binary", but I don't know when to use this option or not.
There is no difference between cargo new and cargo new --bin. From First Steps with Cargo, emphasis mine:
To start a new package with Cargo, use cargo new:
$ cargo new hello_world
Cargo defaults to --bin to make a binary program. To make a library, we would pass --lib, instead.
Likewise, Cargo's command line help tells you the same thing. From cargo new --help, with some irrelevant lines removed:
% cargo new --help
OPTIONS:
--bin Use a binary (application) template [default]
--lib Use a library template
See also
Why does `cargo new` create a binary instead of a library?
What is the difference between library crates and normal crates in Rust?

Is it possible to override the crate-type specified in Cargo.toml from the command line when calling cargo build?

I want to generate a static library from a Rust project that I do not maintain. The project allows building a dynamic library — the Cargo.toml specifies crate-type = ["cdylib"].
Modifying the crate type in the file works, but I want to keep the unmodified original project as git submodule in my project if possible.
Is there is any flag that can be passed to the cargo build command to override this setting?
You can't override it, but you can supplement it. Use cargo rustc and pass --crate-type=staticlib directly to the compiler:
% cargo build
Compiling example v0.1.0 (/private/tmp/example)
Finished dev [unoptimized + debuginfo] target(s) in 0.31s
% find target -name '*.a'
% cargo rustc -- --crate-type=staticlib
Compiling example v0.1.0 (/private/tmp/example)
Finished dev [unoptimized + debuginfo] target(s) in 0.29s
% find target -name '*.a'
target/debug/deps/libexample.a
You can provide the crate-type, but you cannot override the one specified in your Cargo.toml:
$ cargo rustc -- --crate-type=staticlib
Compiling example v0.1.0 (/dev/tmp)
Finished dev [unoptimized + debuginfo] target(s) in 0.34s
There is an tracking issue to add a --crate-type override. In the meantime, a workaround is to use cargo-crate-type:
$ cargo install cargo-crate-type
$ cargo crate-type static
$ cargo build
Note that this command will alter your Cargo.toml
Since Rust 1.64 it is possible to override the crate-type for libraries and examples. Please note the missing -- compared to the other answers. The --crate-type flag in this answer is a cargo rustc flag, while in the other answers cargo rustc was used to pass an additional flag to rustc (as opposed to replacing the flag like cargo rustc does).
$ cargo rustc --crate-type=staticlib

Is there way to use xbuild instead of build when calling cargo-binutils commands?

I try to use binutils commands for binary of custom build target with cargo xbuild command.
However, I get an error like below message.
$ cargo nm --target i586-rust_dos.json --bin rust_dos --verbose
"cargo" "build" "--target" "i586-rust_dos.json" "--bin" "rust_dos" "--message-format=json"
Compiling rust_dos v0.1.0 (/home/soya/Documents/src/rust/prac/rust_dos)
error[E0463]: can't find crate for `core` ] 0/2
|
= note: the `i586-rust_dos-8410465322435951119` target may not be installed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0463`.
error: could not compile `rust_dos`.
To learn more, run the command again with --verbose.
error: Failed to parse crate metadata
I realized that cargo nm uses cargo build command,
so I think this error should be solved if I make cargo nm to use cargo xbuild instead of cargo build.
However, I cannot find how to do that.
Please teach me if there is a way.
To detect core crate built with cargo xbuild, I need to add sysroot flag in rustflags in .cargo/config.
example is below.
rustflags = ["--sysroot", "/full/path/to/sysroot/directory"]
There is sysroot directory in project's target directory.
If adding these flags, cargo-bintuils commands are enabled to use as far as in my environment.

How to make Travis CI work with Rust 0.12.0 and Cargo?

I am trying to make Travis CI build and test the contents of my GitHub repository, which is compatible with Rust 0.12.0 and an older Cargo:
rustc 0.12.0 (ba4081a5a 2014-10-07 13:44:41 -0700)
cargo 0.0.1-pre-nightly (861c07f 2014-10-07 23:29:57 +0000)
I have specified Rust 0.12.0 in the .travis.yml:
language: rust
rust: 0.12.0
script:
- cargo build --verbose
- cargo test --verbose
- rustdoc --test README.md -L target
- cargo doc
The issue I seem to be hitting is that Travis will pick the latest Cargo nightly:
cargo 0.0.1-pre-nightly (fd5d7a9 2014-12-25 04:28:40 +0000)
But this newer version is incompatible with Rust 0.12.0, as it is now using --emit=dep-info where it used to use --dep-info:
--dep-info [FILENAME]
Output dependency info to <filename> after compiling,
in a format suitable for use by Makefiles
This gives rustc invocation errors, as the value for is --emit is invalid:
Running `rustc src/sqlite3.rs --crate-name sqlite3 --crate-type lib -g -C metadata=1c7080eec8c6f90d -C extra-filename=-1c7080eec8c6f90d --out-dir target/deps --emit=dep-info,link -L target/deps -L target/deps -Awarnings`
...
error: unknown emission type: `dep-info`
...
Could not compile `sqlite3`.
I have been looking at other repositories for how to get around this, but it seems they either do not use Cargo with 0.12.0 (which works with Travis) or hit the same issue, like here: https://travis-ci.org/eliovir/rust-ini
I have failed to find any repository that works with Travis, rust 0.12.0 and Cargo. If I can specify the version of Cargo somewhere, I would be able to get around this, but I have failed to find a way to do so in the .travis.yml file.
Of course, with Rust 1.0 coming up, I will just wait for it, if there is no obvious solution that I have overlooked :-)
I agree that tracking nightly is probably the best bet. If there are dependencies you rely on that aren't being updated, then maybe that's a sign that they wont be updated come 1.0 time, either!
All that being said, Travis does allow you to install things before your build. This is completely untested, but you might be able to do something like
before_script:
- wget https://static.rust-lang.org/dist/rust-0.12.0-x86_64-unknown-linux-gnu.tar.gz
- tar -xvf rust-0.12.0-x86_64-unknown-linux-gnu.tar.gz
- ./rust-0.12.0-x86_64-unknown-linux-gnu/install.sh --prefix /tmp/rust-0.12/
- export PATH=$PATH:$PWD/tmp/rust-0.12/bin
- export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/tmp/rust-0.12/lib
This would download Rust 0.12, unpack and install it somewhere writable (doesn't really matter where). Then you setup env vars to point out where Rust is. Do the same to download a compatible version of Cargo.
If Travis has a "bare" language pack, that would be the best. Otherwise you could try using the Rust buildpack, or maybe just anything else (to avoid dealing with multiple rustc versions).

Resources