proc_macro

High level abstractions with low level results are littered through out the Rust language. In this example we’ve defined serialization for the base types and then can simply automatically derive it for all objects containing those types.

#[derive(Debug, Serialize, Deserialize, PartialEq)]

struct MyStruct {

addr: EthAddress,

sig: EthSignature,

key: EthPrivateKey

}

This compiles perfectly on normal x86 targets, works perfectly too. Everything seems perfect until.

[justin@aperturescience.robot serde]$ cargo build --target mips-unknown-linux-musl

Compiling proc-macro2 v0.2.1

Compiling serde_test v1.0.27 (file:///home/justin/repos/serde/serde_test)

Compiling quote v0.4.2

error[E0463]: can't find crate for `proc_macro`

--> /home/justin/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro2-0.2.1/src/lib.rs:27:1

|

27 | extern crate proc_macro;

| ^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate error: aborting due to previous error error: Could not compile `proc-macro2`.

warning: build failed, waiting for other jobs to finish...

error: build failed

What is proc_macro and why doesn’t it exist when compiling for targets that aren’t x86? proc_macro is a compiler plugin system. Since Rust allows crates like Serde to provide syntactic sugar that gets turned into actual code the compiler structure has to accommodate code generation from a different source than itself.

When you go to compile a Rust program with #[derive(Serialize)] or some other property provided by a crate like Serde you’re building a proc_macro crate, these special crates generate a compiler plugin that’s used at compile time to build the code that #[derive(Serialize)] translates to.

So trying to crosscompile a proc_macro crate doesn’t really make any sense. You only need the plugin to generate code and all of it’s functionality is useless on the cross architecture you’re building for. Therefore Cargo just tells you that this useless version of proc_macro doesn’t exist.

This is caused by having a specific type of useless dependency. If you’ve tried to extend or define other proc macro traits you may have a extern crate quote and or extern crate syn somewhere that’s no longer needed.

This can happen if you wrote some derivations that used proc-macro functionality and then re-factored them out without removing the dependency import. Since you aren’t defining anything that actually needs a macro the compiler will let you leave off the required tag in the Cargo.toml.

Inside of this edge case you will get the above error, it can be corrected by either removing the creates quote and syn if they are no longer needed or properly defining and using a macro in the crate that imports them.

Big thanks to Manish Goregaokar for helping improve this section of the article.