I wanted to start a Rust no_std project, so I simply created a new cargo package and wrote in main.rs the following lines:
#![feature(lang_items, start)]
#![no_std]
extern crate libc;
#[start]
fn main(_argc: isize, _argv: *const *const u8) -> isize{
1
}
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> !{
loop{}
}
#[lang = "eh_personality"] extern fn eh_personality() {}
The Cargo.toml file looks like that:
[dependencies]
libc = "0.2.71"
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
I ran cargo build and the linker printed:
LINK : error LNK2001: unresolved external symbol _mainCRTStartup
What could be the reason behind that error ?
Default build target on windows uses mscv toolchain, which includes a dynamically-linked libc. This ones is a C-runtime, which, in particularly, includes an undefined main symbol (which assumed to be defined by a programmer), therefore at linking stage the linker cannot find this missing symbol. You need explicitly specify that you don't need it via #![no_main] at the beginning of main.rs.
I also would suggest you reading A Freestanding Rust Binary which explain much more in details.
Related
If I build a Rust application using Cargo with some crate dependencies, will any code in those dependencies that is unused by my application be eliminated from the final executable?
It looks like it. I made a test lib and bin crate side by side:
// hellobin/src/main.rs
extern crate hellolib;
fn main() {
hellolib::func1();
}
For the lib:
// hellolib/src/main.rs
pub fn func1() {
println!("Hello, world!");
}
pub fn func2() {
println!("Hello, other world!");
}
Building my binary and then inspecting symbols with nm:
$ nm target/debug/helloworld | grep hello
0000000100001360 t __ZN10helloworld4main17h749f61fb726f0a10E
00000001000014b0 T __ZN8hellolib5func117hec0b5301559d46f6E
Only the used function has a symbol in the final binary.
You can compile with cargo rustc -- -C link-dead-code though and you will see both symbols are present, including the unused one:
$ nm target/debug/helloworld | grep hello
0000000100001270 t __ZN10helloworld4main17h3104b73b00fdd798E
00000001000013d0 T __ZN8hellolib5func117hec0b5301559d46f6E
0000000100001420 T __ZN8hellolib5func217hc9d0886874057b84E
I believe (but I'm not sure) that it's the linker removing the dead code, so it may have still been compiled and then removed during linking.
TL;DR: Yes, every unused function is going to be excluded.
This is actually the job of LLVM that will at least keep track of every unused function. Any unused code (as in codepaths in function not taken across the entire Application) may require LTO (Link Time Optimizations) to be activated to turn your crate into one compilation unit and give LLVM a fighting chance.
My executable Rust crate uses a native library libfoo.a which depends on a shared library libbar.so, but does not expose it at all.
My Rust FFI uses the methods from libfoo, so I defined a link attribute on my extern code::
#[link(name="foo", kind="static")]
extern "C"{
pub fn do_foo();
}
and my build.rs included from Cargo.toml using build="build.rs"
fn main() {
let libs = &[(Some("../libs/foo/1.0/"), "static=foo"), // use ../libs/foo/1.0/libfoo.a
(None, "bar")]; // use libbar.so using LD_LIBRARY_PATH
for &(ref m_path, ref lib) in libs {
if let &Some(static_path) = m_path {
println!("cargo:rustc-link-search={}", &static_path);
}
println!("cargo:rustc-link-lib={}", &lib);
}
}
which outputs
cargo:rustc-link-search=../libs/foo/1.0/
cargo:rustc-link-lib=static=foo
cargo:rustc-link-lib=bar
Theoretically, I expect Rust to link against libfoo.a and libbar.so. The problem is that rustc does not even try to acknowledge libbar.
cargo build --debug ends with
/home/author/src/foo/foo.c:21: undefined reference to 'bar_do_stuff'
collect2: error: ld returned 1 exit status
When I inspect the linker command, there is an -L ../libs/foo/1.0 argument, as well as -l foo, but there is no trace of -l bar !
If I manually add the -l bar to cc, it builds (and runs) just fine.
Could you let me know what I am missing? Should I create an FFI binding for libbar even though I don't use it in Rust and it is not exposed from libfoo's API?
The issue is a conflict between the #[link] attribute in the FFI definition and the output of the build.rs build script.
It would seem that the #[link] attribute is instructing rustc to ignore the cargo:rustc-link-* instructions.
The fix was as simple as removing the #[link] attribute.
I'm trying to use this library.
But, cargo build says this:
Compiling test v0.1.0 (file:///C:/path/to/project/test)
src\main.rs:1:1: 1:28 error: can't find crate for `jvm_assembler` [E0463]
src\main.rs:1 extern crate jvm_assembler;
^~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `test`.
To learn more, run the command again with --verbose.
My Cargo.toml is this:
[package]
name = "test"
version = "0.1.0"
authors = ["yomizu_rai"]
[dependencies]
jvm-assembler = "*"
src/main.rs is this, and there are no other sourcefiles.
extern crate jvm_assembler;
use jvm_assembler::*;
fn main() {}
I think my Cargo.toml is not wrong, and src/main.rs has no room for mistake.
Why can not rustc find jvm-assembler?
How do I resolve?
Cargo can only find crates by name if they are on crates.io. In your case you need to specify the git URL, see the section on dependencies in the Cargo documentation.
I am learning Rust, and saw a post on http://reddit.com/r/rust yesterday for Nickel. As a Node.js developer in my free time, I was interested in checking this out.
I downloaded the Rust 1.0.0-beta DMG from http://rust-lang.org.
I followed the Hello World tutorial precisely, and when I execute cargo run in my Terminal, I am receiving the following error:
Robs-MacBook-Pro:nickel-demo rob$ cargo run
Compiling nickel-demo v0.0.1 (file:///Users/rob/Workbench/nickel-demo)
src/main.rs:4:1: 4:21 error: an external crate named `nickel` has already been imported into this module [E0259]
src/main.rs:4 extern crate nickel;
^~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `nickel-demo`.
The Hello World main.rs file for the Nickel Demo looks like this:
extern crate nickel;
#[macro_use] extern crate nickel_macros;
extern crate nickel;
use nickel::Nickel;
fn main() {
let mut server = Nickel::new();
server.utilize(router! {
get "**" => |_req, _res| {
"Hello world!"
}
});
server.listen("127.0.0.1:6767");
}
As I was typing this code into my editor, I specifically thought it was weird that I was declaring extern crate nickel; twice in the file. After receiving the error I refactored the code to this:
extern crate nickel;
#[macro_use] extern crate nickel_macros;
use nickel::Nickel;
...
And I get this error:
Robs-MacBook-Pro:nickel-demo rob$ cargo run
Compiling nickel-demo v0.0.1 (file:///Users/rob/Workbench/nickel-demo)
Running `target/debug/nickel-demo`
Listening on http://127.0.0.1:6767
Ctrl-C to shutdown server
thread '<main>' panicked at 'arithmetic operation overflowed', /Users/rob/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.3.11/src/server/mod.rs:90
An unknown error occurred
The arithmetic operation overflowed bug seems to be an upstream issue. It also affects hyper which nickel depends on.
See https://github.com/seanmonstar/num_cpus/issues/2
As a temporary workaround use cargo build --release to prevent the checks altogether.
I wrote a program to parse some filenames in Rust using the standard Regex crate. The program runs fine on Linux, but when I tried to compile and run it on Windows, I get some kind of DLL error. I don't really understand what is going on with this, but it's all I have to go on.
This is the compiler version that I'm using:
F:\Coding\rust-shutterstock-deduper\target (master)
λ rustc --version
rustc 1.0.0-nightly (3ef8ff1f8 2015-02-12 00:38:24 +0000)
This is the program that I'm trying to run:
#![feature(plugin)]
#![plugin(regex_macros)]
extern crate regex_macros;
extern crate regex;
fn main() {
let x = regex!(".*");
}
And my Cargo.toml file:
[package]
name = "my_package"
version = "0.0.1"
authors = ["Nate Mara <natemara#gmail.com>"]
[dependencies]
regex = "0.1.14"
regex_macros = "0.1.8"
Are there compiler flags that I should be passing in, or do I need to run this in a special way, or... what am I doing wrong here? I'm just running with cargo run
Add #[no_link] to your code:
#![plugin(regex_macros)]
#[no_link]
extern crate regex_macros;
Right now, plugins are crates, which means they get linked in. The regex_macros crate should tell you to add no_link, but this is a temporary workaround for a Rust issue. However, it looks like this is in the process of being fixed.