So I'm running this in powershell for my Rust project:
cargo build --target thumbv7em-none-eabihf
And it produces this error after I try to execute this command:
error: failed to parse manifest at C:\Users\PC\Downloads\Blizzard\Cargo.toml Caused by: virtual manifests must be configured with [workspace]
Here is my Cargo.toml file:
[package]
name = "my-project"
version = "0.1.0"
authors = ["runner"]
edition = "2021"
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
If it's needed, here is my rust file:
#![no_std]
#![no_main]
use core::panic::PanicInfo;
#[no_mangle]
pub extern "C" fn _start() -> ! {
loop {}
}
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
And my file path looks like this:
> Blizzard
> src
> main.rs
> Cargo.toml
How can I fix this issue? Any help is appreciated
Related
I want to build a no_std static library with rust.
I got the following:
[package]
name = "nostdlb"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
lib.rs:
#![no_std]
pub fn add(left: usize, right: usize) -> usize {
left + right
}
Despite setting the panic behaviour for both dev and release to abort cargo gives the following error:
error: `#[panic_handler]` function required, but not found
error: could not compile `nostdlb` due to previous error
I thought the panic handler is only required when there is no stack unwinding provided by std?
No, you need to write your own one. If you need just aborting, consider using the following one:
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
I also highly recommend to unmangle the function and use C calling convention if you’re going to use this symbol somewhere (not import it the library as a crate, but link it manually):
#[no_mangle]
extern fn add(right: usize, left: usize) -> usize {
right + left
}
I'm starting on a command-line tool in Rust, and hitting a wall right from the get-go. I can parse command-line arguments using StructOpt if the Opt struct is defined in main.rs, but since I want to be able to pass the Opt struct into the library code, I'm defining it in its own file so that other parts of the library know what it's all about.
Here's the version of the code that's dumping the fewest errors, although I concede that it's largely cobbled together by trying things suggested by the compiler and some random SO suggestions, so it may be completely wrong.
The build error I'm getting is:
$ cargo run
Compiling basic v0.1.0 (/home/mpalmer/src/action-validator/blobble)
error[E0433]: failed to resolve: maybe a missing crate `structopt`?
--> src/opt.rs:8:5
|
8 | /// Activate debug mode
| ^^^^^^^^^^^^^^^^^^^^^^^ not found in `structopt::clap`
|
help: consider importing this struct
|
3 | use opt::structopt::clap::Arg;
|
For more information about this error, try `rustc --explain E0433`.
error: could not compile `basic` due to previous error
$ cargo --version
cargo 1.56.0 (4ed5d137b 2021-10-04)
$ rustc --version
rustc 1.56.0 (09c42c458 2021-10-18)
(Yes, I have tried adding use opt::structopt::clap::Arg;, just in case, but the error doesn't go away and I get a warning about an unused import -- while still being told to try adding the same use that is unused, which is amusing)
Cargo.toml
[package]
name = "basic"
version = "0.1.0"
authors = ["User"]
[dependencies]
structopt = "0.3"
src/main.rs
extern crate basic;
extern crate structopt;
use basic::Opt;
use structopt::StructOpt;
fn main() {
let opt = Opt::from_args();
println!("{:#?}", opt)
}
src/lib.rs
mod opt;
pub use crate::opt::Opt;
src/opt.ts
extern crate structopt;
use self::structopt::StructOpt;
#[derive(StructOpt, Debug)]
#[structopt(name = "basic")]
pub struct Opt {
/// Activate debug mode
#[structopt(short,long)]
debug: bool,
}
Suggestions gratefully appreciated.
A working version is
Cargo.toml
[package]
name = "basic"
version = "0.1.0"
authors = ["User"]
edition = "2018"
[dependencies]
structopt = "0.3"
lib.rs
#[macro_use] extern crate structopt;
use structopt::StructOpt;
pub mod opt;
opt.rs
#[derive(StructOpt, Debug)]
#[structopt(name = "basic")]
pub struct Opt {
/// Activate debug mode
#[structopt(short,long)]
debug: bool,
}
main.rs
#[macro_use] extern crate structopt;
use structopt::StructOpt;
fn main() {
let opt = basic::opt::Opt::from_args();
println!("{:#?}", opt);
}
You need to declare use structopt::StructOpt because from_args trait must be in the scope.
I'm trying to link a Rust program with libsoundio. I'm using Windows and there's a GCC binary download available. I can link it like this if I put it in the same folder as my project:
#[link(name = ":libsoundio-1.1.0/i686/libsoundio.a")]
#[link(name = "ole32")]
extern {
fn soundio_version_string() -> *const c_char;
}
But I really want to specify #[link(name = "libsoundio")] or even #[link(name = "soundio")], and then provide a linker path somewhere else.
Where can I specify that path?
I tried the rustc-link-search suggestion as follows:
#[link(name = "libsoundio")]
#[link(name = "ole32")]
extern {
fn soundio_version_string() -> *const c_char;
}
And in .cargo/config:
[target.i686-pc-windows-gnu.libsoundio]
rustc-link-search = ["libsoundio-1.1.0/i686"]
rustc-link-lib = ["libsoundio.a"]
[target.x86_64-pc-windows-gnu.libsoundio]
rustc-link-search = ["libsoundio-1.1.0/x86_64"]
rustc-link-lib = ["libsoundio.a"]
But it still only passes "-l" "libsoundio" to gcc and fails with the same ld: cannot find -llibsoundio. Am I missing something really obvious? The docs seem to suggest this should work.
As stated in the documentation for a build script:
All the lines printed to stdout by a build script [... starting] with cargo: is interpreted directly by Cargo [...] rustc-link-search indicates the specified value should be passed to the compiler as a -L flag.
In your Cargo.toml:
[package]
name = "link-example"
version = "0.1.0"
authors = ["An Devloper <an.devloper#example.com>"]
build = "build.rs"
And your build.rs:
fn main() {
println!(r"cargo:rustc-link-search=C:\Rust\linka\libsoundio-1.1.0\i686");
}
Note that your build script can use all the power of Rust and can output different values depending on target platform (e.g. 32- and 64-bit).
Finally, your code:
extern crate libc;
use libc::c_char;
use std::ffi::CStr;
#[link(name = "soundio")]
extern {
fn soundio_version_string() -> *const c_char;
}
fn main() {
let v = unsafe { CStr::from_ptr(soundio_version_string()) };
println!("{:?}", v);
}
The proof is in the pudding:
$ cargo run
Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target\debug\linka.exe`
"1.0.3"
Ideally, you will create a soundio-sys package, using the convention for *-sys packages. That simply has a build script that links to the appropriate libraries and exposes the C methods. It will use the Cargo links key to uniquely identify the native library and prevent linking to it multiple times. Other libraries can then include this new crate and not worry about those linking details.
Another possible way is setting the RUSTFLAGS like:
RUSTFLAGS='-L my/lib/location' cargo build # or cargo run
I don't know if this is the most organized and recommended approach, but it worked for my simple project.
I found something that works OK: you can specify links in your Cargo.toml:
[package]
links = "libsoundio"
build = "build.rs"
This specifies that the project links to libsoundio. Now you can specify the search path and library name in the .cargo/config file:
[target.i686-pc-windows-gnu.libsoundio]
rustc-link-search = ["libsoundio-1.1.0/i686"]
rustc-link-lib = [":libsoundio.a"]
[target.x86_64-pc-windows-gnu.libsoundio]
rustc-link-search = ["libsoundio-1.1.0/x86_64"]
rustc-link-lib = [":libsoundio.a"]
(The : prefix tells GCC to use the actual filename and not to do all its idiotic lib-prepending and extension magic.)
You also need to create an empty build.rs:
fn main() {}
This file is never run, because the values in .cargo/config override its output, but for some reason Cargo still requires it - any time you use links = you have to have build =, even if it isn't used.
Finally in main.rs:
#[link(name = "libsoundio")]
#[link(name = "ole32")]
extern {
fn soundio_version_string() -> *const c_char;
}
I'm following the instructions from here. In the example folder, I use the first example. For some reason console says it can't find the external crate "gl". Here's what my Cargo.toml looks like.
[package]
name = "hello_world"
version = "0.0.1"
authors = [ "bob <bobbuilder#gmail.com>" ]
[dependencies.gl]
git = "https://github.com/bjz/gl-rs"
[dependencies.glfw]
git = "https://github.com/bjz/glfw-rs.git"
[build-dependencies]
gl_generator = "*"
[dependencies]
gl_common = "*"
[[bin]]
name = "hello_world"
My build.rs
extern crate gl_generator; // <-- this is your build dependency
extern crate khronos_api; // included by gl_generator
use std::os;
use std::io::File;
fn main() {
let dest = Path::new(os::getenv("OUT_DIR").unwrap());
let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();
// This generates bindsings for OpenGL ES v3.1
gl_generator::generate_bindings(gl_generator::GlobalGenerator,
gl_generator::registry::Ns::Gles2,
khronos_api::GL_XML,
vec![],
"3.1", "core", &mut file).unwrap();
}
The documentation you linked to says:
Under the [package] section, add build = "build.rs"
But I don't see that in your Cargo.toml.
I would like to make a Rust package that contains both a reusable library (where most of the program is implemented), and also an executable that uses it.
Assuming I have not confused any semantics in the Rust module system, what should my Cargo.toml file look like?
Tok:tmp doug$ du -a
8 ./Cargo.toml
8 ./src/bin.rs
8 ./src/lib.rs
16 ./src
Cargo.toml:
[package]
name = "mything"
version = "0.0.1"
authors = ["me <me#gmail.com>"]
[lib]
name = "mylib"
path = "src/lib.rs"
[[bin]]
name = "mybin"
path = "src/bin.rs"
src/lib.rs:
pub fn test() {
println!("Test");
}
src/bin.rs:
extern crate mylib; // not needed since Rust edition 2018
use mylib::test;
pub fn main() {
test();
}
Simple
Create a src/main.rs that will be used as the defacto executable. You do not need to modify your Cargo.toml and this file will be compiled to a binary of the same name as the library.
The project contents:
% tree
.
├── Cargo.toml
└── src
├── lib.rs
└── main.rs
Cargo.toml
[package]
name = "example"
version = "0.1.0"
edition = "2018"
src/lib.rs
use std::error::Error;
pub fn really_complicated_code(a: u8, b: u8) -> Result<u8, Box<dyn Error>> {
Ok(a + b)
}
src/main.rs
fn main() {
println!(
"I'm using the library: {:?}",
example::really_complicated_code(1, 2)
);
}
And execute it:
% cargo run -q
I'm using the library: Ok(3)
Flexible
If you wish to control the name of the binary or have multiple binaries, you can create multiple binary source files in src/bin and the rest of your library sources in src. You can see an example in my project. You do not need to modify your Cargo.toml at all, and each source file in src/bin will be compiled to a binary of the same name.
The project contents:
% tree
.
├── Cargo.toml
└── src
├── bin
│ └── mybin.rs
└── lib.rs
Cargo.toml
[package]
name = "example"
version = "0.1.0"
edition = "2018"
src/lib.rs
use std::error::Error;
pub fn really_complicated_code(a: u8, b: u8) -> Result<u8, Box<dyn Error>> {
Ok(a + b)
}
src/bin/mybin.rs
fn main() {
println!(
"I'm using the library: {:?}",
example::really_complicated_code(1, 2)
);
}
And execute it:
% cargo run --bin mybin -q
I'm using the library: Ok(3)
See also:
How can I specify which crate `cargo run` runs by default in the root of a Cargo workspace?
An alternate solution is to not try to cram both things into one package. For slightly larger projects with a friendly executable, I've found it very nice to use a workspace.
Here, I create a binary project that includes a library inside of it, but there are many possible ways of organizing the code:
% tree the-binary
the-binary
├── Cargo.toml
├── src
│ └── main.rs
└── the-library
├── Cargo.toml
└── src
└── lib.rs
Cargo.toml
This uses the [workspace] key and depends on the library:
[package]
name = "the-binary"
version = "0.1.0"
edition = "2018"
[workspace]
[dependencies]
the-library = { path = "the-library" }
src/main.rs
fn main() {
println!(
"I'm using the library: {:?}",
the_library::really_complicated_code(1, 2)
);
}
the-library/Cargo.toml
[package]
name = "the-library"
version = "0.1.0"
edition = "2018"
the-library/src/lib.rs
use std::error::Error;
pub fn really_complicated_code(a: u8, b: u8) -> Result<u8, Box<dyn Error>> {
Ok(a + b)
}
And execute it:
% cargo run -q
I'm using the library: Ok(3)
There are two big benefits to this scheme:
The binary can now use dependencies that only apply to it. For example, you can include lots of crates to improve the user experience, such as command line parsers or terminal formatting. None of these will "infect" the library.
The workspace prevents redundant builds of each component. If we run cargo build in both the the-library and the-binary directory, the library will not be built both times — it's shared between both projects.
You can put lib.rs and main.rs to sources folder together. There is no conflict and cargo will build both things.
To resolve documentaion conflict add to your Cargo.toml:
[[bin]]
name = "main"
doc = false