Cargo autogenerated code: not work except main.rs.in

I tried to use cargo code generation as described cargo study code generation, it works in such case:

[package]
name = "hello_world"
build = "build.rs"

where build.rs contains:

    let src = Path::new("src/main.rs.in");
    let dst = Path::new(&env::var("OUT_DIR").unwrap()).join("main.rs");

    registry.expand("hello_world", &src, &dst).unwrap();

all works fine, cargo found and compile generated main.rs.

But when I try library instead of binary:
[package]
name = "hello_world"
build = "build.rs"

[lib]
name = "test"
crate-type = ["cdylib"]

and replace main.rs.in with lib.rs.in compilation failed,
the problem is that cargo not search lib.rs in "target" directory,

why so and how can I fix this?

Hm, I would say that the first case should not work as well. The basic rule is that you can't generate main.rs or lib.rs files directly because cargo needs them to determine possible builds commands before executing the build script. Here is the recent discussion of this phenomenon: build.rs won't run if lib.rs if missing · Issue #3208 · rust-lang/cargo · GitHub.

So perhaps you need a hand written lib.rs like this:

include!(concat!(env!("OUT_DIR"), "/lib.rs"));

and a build script like this:

let out_dir = env::var_os("OUT_DIR").unwrap();
let dst = Path::new(&out_dir).join("lib.rs");