When developing certain types of embedded, kernel, firmware, or other system targets, projects need to supply specific linker arguments, notably -nostartfiles
to omit the standard C start function (such as _start
) and associated code.
Right now, this requires creating a .cargo/config
file, and specifying target-specific non-portable linker arguments. I'd like to create a portable way to do this, inline with the project code.
This goes hand in hand with #![no_main]
, but goes further than that, allowing writing your own entry point for a binary.
Rough proposal
Add a new top-level attribute, no_entry
. When present, Rust will omit its own entry-point code, and will pass any necessary target-specific arguments to the toolchain to omit the target's entry-point code (such as -nostartfiles
) .
Binaries built with this attribute set will typically not link unless the user supplies their own entry-point symbol.
Libraries cannot use this attribute; attempting to do so will produce a compile-time error stating that no_entry
only applies to binaries.
Future extensions
I'd like to provide an #[entry]
attribute to portably specify the entry-point symbol. The symbol itself may still be non-portable, but having #[entry]
would allow using exclusively Rust cfg
to handle portability, rather than also needing linker arguments. This would also potentially make it possible for Rust library crates to provide entry points. (This differs from #[start]
, which provides a semi-portable entry point that still has Rust code run before it.)
I'd also like to add an attribute to pass -nodefaultlibs
to the linker. Unlike no_entry
, this would typically require no_std
on many targets, as std
often depends on the C library.
However, I don't want to combine either of those with no_entry
, as I'd like to keep this proposal as simple and straightforward as possible.
Next steps
If this sounds reasonable, I'm happy to write it up as an RFC. I don't expect it to require substantial effort to implement; we should be able to have a reasonable default for each linker flavor, and then a way for targets to override that if they need extra logic.