Problems porting std to custom OS, builtins missing

I'm trying to port the std library to a custom OS. I found this guide on the net which I'm trying to follow.

The guide works quite well until you are supposed to compile the standard library. Then I get the following errors.

cargo build --target armv7a-unknown-myos-eabi -Zbinary-dep-depinfo --release --features "panic-unwind compiler-builtins-c compiler-builtins-mem" --manifest-path "library/test/Cargo.toml"
   Compiling cc v1.0.76
   Compiling core v0.0.0 (...\rust\library\core)
   Compiling libc v0.2.138
   Compiling std v0.0.0 (...\rust\library\std)
error: cannot find a built-in macro with name `derive_const`
    --> library\core\src\macros\mod.rs:1465:5
     |
1465 | /     pub macro derive_const($item:item) {
1466 | |         /* compiler built-in */
1467 | |     }
     | |_____^

error: cannot find a built-in macro with name `alloc_error_handler`
    --> library\core\src\macros\mod.rs:1523:5
     |
1523 | /     pub macro alloc_error_handler($item:item) {
1524 | |         /* compiler built-in */
1525 | |     }
     | |_____^

error: cannot find a built-in macro with name `type_ascribe`
    --> library\core\src\macros\mod.rs:1557:5
     |
1557 | /     pub macro type_ascribe($expr:expr, $ty:ty) {
1558 | |         /* compiler built-in */
1559 | |     }
     | |_____^

   Compiling compiler_builtins v0.1.85
   Compiling unwind v0.0.0 (...\rust\library\unwind)
error: attributes starting with `rustc` are reserved for use by the `rustc` compiler
  --> library\core\src\ptr\metadata.rs:53:28
   |
53 | #[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
   |                            ^^^^^^^^^^^^^^^^^^^^^^^^

Obviously it cannot find built in macros. I'm guessing here but one observation is that in the guide the standard library seems to be compiled to the same as the host CPU architecture (x86-64). In this case the built-in macros are already there. In my case I compile on an x86 but the target architecture is ARM. Do you need to do something extra with the compiler when you have new target CPU architecture or is just a library that needs to be compiled correctly?

Another observation that is not brought up in the guide is the actual extra code required in order to support a new OS. That might perhaps been omitted to limit the scope. However, when you have a new OS, I've seen that you have a library/std/src/sys/unsupported directory which essentially stubs for all the OS supports to be filled in. Are you supposed to be copying the unsupported directory to library/std/src/sys/myos, and the continue to "fill in the blanks" from there? Will the build system automatically use the "myos" directory based on the information from the target triple or target.json file?

Built-in macros are part of the compiler itself. They are not like proc macros in that they need to be compiled for the host separately. Are you using the standard library from the exact same commit as rustc was built? We don't support mixing different versions of rustc and the standard library as their api boundary is unstable and constantly changes.

Adding support for a new target is a matter of adding a target spec to rustc (or using an external json file describing the target) and porting the standard library. If you are using an external json file to describe the target you don't need to recompile rustc.

If something is unsupported by your OS (or you haven't implemented it yet) you are supposed to use eg #[path = "../unsupported/foo.rs"] pub mod foo; to include it for your target. No need to copy it. To pick up your implementation you need to add a case for your OS to the first cfg_if! invocation at library/std/src/sys/mod.rs. In you case you could use #[cfg(target_os = "myos")] as condition if you set the os field in the target spec to "myos".

The compiler is the normal latest stable updated with rustup. The source is a pull from the master branch so the API versions might be different.

When it comes to the built-in macros I didn't quite follow the answer. When it comes the built-in macros, are they generic for all CPU targets or do they need to have compiled support into the rustc compiler for every CPU target? There is bit confusion about the "built-in" word as it also is mentioned as a library "compiler_builtins" which seems to be compiler-rt. As far as I know compiler-rt needs to built for the specific CPU target that I wish to support, which is ARM in this case. Is this even supported by the build system?

So in practice, in order for this to work I need to compile the entire rust toolchain from the source I pulled from scratch to begin with?

Yeah, that isn't going to work. If you install the rust-src rustup component you can find the right source for the current rustc version in $(rustc --print sysroot)/lib/rustlib/src/rust.

They are generic.

compiler-builtins is entirely unrelated to built-in macros. compiler-builtins is a dependency of libstd, so building libstd will automatically build compiler-builtins too.

With your help I got further but the build still doesn't go through. Depending what channel you use you end up with different message.

On the stable channel (with BOOTSTRAP=1) I get this error

cargo build -Zbuild-std --target armv7a-unknown-myos-eabi
   Compiling std v0.0.0 (...\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std)
error: `sys_common::once::generic::Once::new` is not yet stable as a const fn
  --> src\sync\once.rs:70:23
   |
70 |         Once { inner: sys::Once::new() }
   |                       ^^^^^^^^^^^^^^^^
   |
   = help: const-stable functions can only call other const-stable functions

error: could not compile `std` due to previous error

On the nightly channel, I instead get this error

cargo build -Zbuild-std --target armv7a-unknown-myos-eabi
   Compiling rustc-std-workspace-core v1.0.0
   Compiling rustc-std-workspace-alloc v1.0.0
error[E0658]: use of unstable library feature 'restricted_std'
  |
  = help: add `#![feature(restricted_std)]` to the crate attributes to enable

For more information about this error, try `rustc --explain E0658`.
error: could not compile `rustc-std-workspace-core` due to previous error
warning: build failed, waiting for other jobs to finish...
error: could not compile `rustc-std-workspace-alloc` due to previous error

Adding #![feature(restricted_std)] in lib.rs in rustc-std-workspace-alloc or rustc-std-workspace-core doesn't seem to do any difference.

For the nightly error add your OS to the if condition in library/std/build.rs. That should fix this error.

Unfortunately it doesn't. Regardless I get the same error if I add an entry to my OS or not. It is kind of bizarre that it visits both if else statements.

In library/std/build.rs I added some extra lines.

println!("cargo:rerun-if-changed=build.rs");
    let target = env::var("TARGET").expect("TARGET was not set");
	println!("You should really see this, target {}", target); // Extra print so that I know it comes from this file
    if target.contains("freebsd") {
        if env::var("RUST_STD_FREEBSD_12_ABI").is_ok() {
            println!("cargo:rustc-cfg=freebsd12");
        }

...

        || target.contains("solid")
        || target.contains("nintendo-3ds")
		|| target.contains("myos")
    {
		compile_error!("Problem here ---------------1");
        // These platforms don't have any special requirements.
    } else {

...
      // - uefi (x86_64-unknown-uefi, i686-unknown-uefi)
        // - JSON targets
        // - Any new targets that have not been explicitly added above.
        println!("cargo:rustc-cfg=feature=\"restricted-std\"");
		compile_error!("Problem here  --------------------2");
    }

When I'm then running the build both paths are visited

 Running `...\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\target\debug\build\unwind-b6ed4bcc92250225\build-script-build`
error: Problem here ---------------1
  --> build.rs:37:3
   |
37 |         compile_error!("Problem here ---------------1");
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: Problem here  --------------------2
  --> build.rs:52:3
   |
52 |         compile_error!("Problem here  --------------------2");
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0635]: unknown feature `restricted_std`
 --> ...\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\rustc-std-workspace-core\lib.rs:1:12
  |
1 | #![feature(restricted_std)]
  |            ^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0635`.
error: could not compile `rustc-std-workspace-core` due to previous error

Also sometimes, it seems like any change in build.rs doesn't trigger the rebuild, for example if I do a slight change in the output text I see the old text. However, when I change the compiler_error macros is always trigger correctly. The build seems to be in lib\rustlib\src\rust\library\std\target but deleting this doesn't make any difference.

compile_error!() will give an error at compile time when used. Even if it isn't reached at runtime it will still fail with an error. You should use panic!() instead if you want to know which code is executed.

Try removing these again.