Missing `start` lang_item when using Real-Time For the Masses - rust

I'm trying to write a multi-threaded bare-metal application for the STM32F4Discovery using the Real-Time For the Masses (RTFM) crate. I've frankensteined together a minimal application from an example for the STM32F3Discovery board and this example:
#![no_std]
extern crate cortex_m;
extern crate cortex_m_rtfm as rtfm;
extern crate cortex_m_semihosting;
extern crate panic_semihosting;
extern crate stm32f4;
use stm32f4::stm32f407;
use rtfm::app;
app! {
device: stm32f407,
}
fn init(_p: init::Peripherals) {
}
fn idle() -> ! {
loop {
rtfm::wfi();
}
}
Compilation fails with
error: requires `start` lang_item
I'm new to Rust (in fact I was hoping to learn the language with this project) and have no idea where the error might be located. Is it just that the app! macro is broken or am I missing something?

I've found a workaround in RTFM's issues on GitHub that allows to compile the code above:
import cortex-m-rt and its entry macro
#[macro_use(entry)]
extern crate cortex_m_rt as rt;
add #![no_main] to the head of the source
wrap the main function using the entry macro:
#[entry]
fn entry_wrap() -> ! {
main();
loop {}
}
I haven't tested this yet but it compiles without problems.

Related

Undefined reference to main when using Real-Time For the Masses

I'm trying to write a multi-threaded bare-metal application for the STM32F4Discovery using the Real-Time For the Masses (RTFM) crate. I've frankensteined together a minimal application from an example for the STM32F3Discovery board and this example:
#![deny(unsafe_code)]
#![no_main]
#![no_std]
extern crate cortex_m;
extern crate cortex_m_rtfm as rtfm;
extern crate cortex_m_semihosting;
extern crate panic_semihosting;
extern crate stm32f4;
use stm32f4::stm32f407;
use rtfm::app;
app! {
device: stm32f407,
}
fn init(_p: init::Peripherals) {
}
fn idle() -> ! {
loop {
rtfm::wfi();
}
}
I can get it to compile but linking with rust-lld fails with
= note: rust-lld: error: undefined symbol: main
I am confused because when I run cargo expand I do get a main function:
fn main() {
#![allow(path_statements)]
let init: fn(init::Peripherals) = init;
rtfm::atomic(unsafe { &mut rtfm::Threshold::new(0) },
|_t|
unsafe {
let _late_resources =
init(init::Peripherals{core:
::stm32f407::CorePeripherals::steal(),
device:
::stm32f407::Peripherals::steal(),});
});
let idle: fn() -> ! = idle;
idle();
}
I'm new to Rust (in fact I was hoping to learn the language with this project) and have no idea where the error might be located.
As you ask the compiler to not insert main, there is no main symbol in your program.
Rust uses symbol mangling so your main function doesn't have a symbol named main.
The answer depends on your contextm but generally this should do it:
#[no_mangle] // ensure that this symbol is called `main` in the output
pub extern fn main(argc: i32, argv: *const *const u8) -> i32 {
}
All additional information can be found here

Is there a way to import macros from an external crate during tests only, without any warnings?

I have something like:
#[macro_use] extern crate log;
pub fn do_nothing() { let _ = log::Level::Info; }
#[cfg(test)]
mod tests {
#[test]
fn test_a() { debug!("Message."); }
}
this compiles with a warning:
warning: unused `#[macro_use]` import
If I remove the macro import, and change the 1st line to:
extern crate log;
then I get the following error at compile time:
error: cannot find macro `debug!` in this scope
If I then try and import the macros only for the tests module, i.e.:
extern crate log;
pub fn do_nothing() { let _ = log::Level::Info; }
#[cfg(test)]
mod tests {
#[macro_use] extern crate log;
#[test]
fn test_a() { debug!("Message."); }
}
then I get the compiler error:
error[E0468]: an `extern crate` loading macros must be at the crate root
Is there a solution which avoids all warnings without just suppressing them?
You can use cfg_attr:
#[cfg_attr(test, macro_use)]
extern crate log;
See also:
Is it possible to conditionally derive with features?
Can I conditionally compile my Rust program for a Windows subsystem?
Run additional tests by using a feature flag to "cargo test"

Importing a crate into a const block

I'm trying to write a procedural macro that implements a #[derive()] trait for a struct. In the generated implementation code I need to use AnyMap.
To avoid multi crate imports, and based on what I read in some other crate's code (namely Serde) I put my generated code into a const _IMPL_xxx_FOR_xxx : () = { /* generated code */ }; block but it fails to compile.
I was able to replicate my issue with the following code
const BLOCK_1: () = {
extern crate anymap;
use anymap::AnyMap;
};
const BLOCK_2: () = {
extern crate anymap;
use anymap::AnyMap;
};
fn main() {
println!("foo");
}
The compile error I'm getting is the following:
error[E0432]: unresolved import `anymap::AnyMap`
--> src/main.rs:3:9
|
3 | use anymap::AnyMap;
| ^^^^^^^^^^^^^^ Maybe a missing `extern crate anymap;`?
error[E0432]: unresolved import `anymap::AnyMap`
--> src/main.rs:9:9
|
9 | use anymap::AnyMap;
| ^^^^^^^^^^^^^^ Maybe a missing `extern crate anymap;`?
Is it an issue specific to AnyMap? Would you know of any way to fix this (including maybe a different approach to generating procedural macro code if the pattern I'm using is not recommended?
I can replicate this on the playground using simply
const A: () = {
extern crate core;
use core::option::Option;
};
fn main() {}
However, it appears only the use statement is broken, and I can still use items from core, but I have to name them explicitly each time:
const A: () = {
extern crate core;
do_stuff!(core::option::Option)
};
The reason is that use statements typically assume a path relative to the root, and there is no way to explicitly name the block you are in (self refers to the current module unfortunately).
Here's a better workaround - as I said before, Rust uses self to refer to the current module, so you can just put a module in your code block and then have the use statements reference self.
In your case it would be:
const BLOCK_1: () = {
mod inner {
extern crate anymap;
use self::anymap::AnyMap;
}
};
On the specific issue of making this work for procedural macro, a suggested solution was to reexport the needed crate as part of the crate containing the derive macro (or the one containing the class I'm trying to export) using something like pub extern crate anymap and then use <my_crate>::anymap::AnyMap;

How do I use a macro defined in another crate?

I've seen a couple tutorials to create a Python module using the cpython crate but still have errors when building:
extern crate cpython;
use cpython::{PyObject, PyResult, Python, PyTuple, PyDict, ToPyObject, PythonObject};
fn add_two(py: Python, args: &PyTuple, _: Option<&PyDict>) -> PyResult<PyObject> {
match args.as_slice() {
[ref a_obj, ref b_obj] => {
let a = a_obj.extract::<i32>(py).unwrap();
let b = b_obj.extract::<i32>(py).unwrap();
let mut acc:i32 = 0;
for _ in 0..1000 {
acc += a + b;
}
Ok(acc.to_py_object(py).into_object())
},
_ => Ok(py.None())
}
}
py_module_initializer!(example, |py, module| {
try!(module.add(py, "add_two", py_fn!(add_two)));
Ok(())
});
I get:
error: macro undefined: 'py_module_initializer!'
Where do I get it? I am using Rust 1.12.
UPD
Need to add #[macro_use] (as in answers)
For other errors - see examples here
You probably need to declare cpython as follows:
#[macro_use] extern crate cpython;
To be able to use cpython's macros. You can consult the example in its docs.
You must add the #[macro_use] attribute on the extern crate declaration to ask the compiler to bring the macros exported by the crate into your crate's namespace.
#[macro_use]
extern crate cpython;

Unresolved import when calling a macro defined in an external crate

I am trying to implement a custom HTTP header using impl_header macro from hyper crate but it seems it cannot resolve the hyper::header module.
Here is my code:
#[macro_use] extern crate hyper;
use hyper::header;
struct CustomHeader;
impl_header!(CustomHeader, "value", String);
And here is the compiler error:
<hyper macros>:11:14: 11:20 error: unresolved import `header::HeaderFormat`. Maybe a missing `extern crate header`?
<hyper macros>:11 Result { use header:: HeaderFormat ; self . fmt_header ( f ) } } }
^~~~~~
<hyper macros>:1:1: 11:67 note: in expansion of impl_header!
lib.rs:4:1: 4:45 note: expansion site
error: aborting due to previous error
Could not compile `macro_issue`.
Any clue why this happens and how can I fix it?
Thank you
I agree with Renato that this is an issue with hyper, and you should file a bug (or even better a pull request!). If you'd like to work around it for now though, you can re-export header as your own:
#[macro_use]
extern crate hyper;
pub use hyper::header as header;
struct CustomHeader;
impl_header!(CustomHeader, "value", String);
fn main() {}
Unfortunately, this simply unlocks a whole new wave of errors that I'll let you figure out!

Resources