[Solved] "Hello World" no_std build problem

I'm trying to get the following no_std "Hello World" application to build:

#![feature(lang_items, start)]
#![no_std]

extern crate libc;

#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
    // Since we are passing a C string the final null character is mandatory
    const HELLO: &'static str = "Hello, world!\n\0";
    unsafe {
        libc::printf(HELLO.as_ptr() as *const _);
    }
    0
}

#[lang = "eh_personality"]
extern "C" fn eh_personality() {}
#[lang = "panic_fmt"]
extern "C" fn panic_fmt() -> ! {
    loop {}
}
$ rustc +nightly --version
rustc 1.32.0-nightly (4a45578bc 2018-12-07)
$ cargo +nightly build
...
error[E0522]: definition of an unknown language item: `panic_fmt`
  --> src/main.rs:18:1
   |
18 | #[lang = "panic_fmt"]
   | ^^^^^^^^^^^^^^^^^^^^^ definition of unknown language item `panic_fmt`

error: `#[panic_handler]` function required, but not found

Does anyone have a link I could follow to read about what is needed on the panic side of things now?

Is nightly still required to build this kind of application, or is there a way to do this on stable?

1 Like

https://github.com/intermezzOS/kernel/blob/master/src/panic.rs

IIRC overloading start may not be stable? You should be able to just use main though.

You don't need nightly features anymore:

#![no_std]
#![no_main]

extern crate libc;

#[no_mangle]
pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> isize {
    // Since we are passing a C string the final null character is mandatory
    const HELLO: &'static str = "Hello, world!\n\0";
    unsafe {
        libc::printf(HELLO.as_ptr() as *const _);
    }
    0
}

#[panic_handler]
fn my_panic(_info: &core::panic::PanicInfo) -> ! {
    loop {}
}
4 Likes

Thanks for the info about panic_fmt. I'm still only able to build on nightly due to:

error: language item required, but not found: `eh_personality`

The following does work on nightly though:

#![feature(lang_items)]
#![no_std]
#![no_main]

extern crate libc;

#[no_mangle]
pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> isize {
    // Since we are passing a C string the final null character is mandatory
    const HELLO: &'static str = "Hello, world!\n\0";
    unsafe {
        libc::printf(HELLO.as_ptr() as *const _);
    }
    0
}

#[panic_handler]
fn my_panic(_info: &core::panic::PanicInfo) -> ! {
    loop {}
}

#[lang = "eh_personality"]
extern "C" fn eh_personality() {}

Unless someone knows about how to work around this lang item on stable?

I believe if you disable stack unwinding it will fix that:

[profile.dev]
panic = "abort"

[profile.release]
panic = "abort"
9 Likes

That was it! I was using panic = 'abort' in profile.release, but not profile.dev but testing the build in debug mode.

Thanks all! :+1:

1 Like