How do you import macros in submodules in Rust?
Asked Answered
G

3

34

I have the following directory structure

  • /main.rs
  • /lib.rs
  • /tutorial/mod.rs
  • /tutorial/foo.rs

In foo.rs I need to use a macro from the glium library, implement_vertex!. If I put #[macro_use] extern crate glium; at the head of foo.rs, I get a error: an `extern crate` loading macros must be at the crate root. I also get a error: macro undefined: 'implement_vertex!'

There is also a lib.rs that is the crate root of the tutorial modules. I needed to put #[macro_use] there. Does this create 2 crate roots if I have both main.rs and lib.rs?

What is the correct way to import macros in a submodule?

Goodly answered 26/8, 2016 at 23:32 Comment(2)
Without actual code, this can only be solved by blind guessing. All we need is the structure, where it's being imported, and where it's being used.Glassco
How do you compile (cargo build)? Have you modified your Cargo.toml? In what file is the line mod tutorial;? In what file is the line mod foo;? Without this information, we can only guess how your module tree looks like, as @Glassco already said.Roughcast
S
24

Macros are handled early enough in the compilation stage that order matters. You, like I, probably were getting nice and used to Rust magicking away the need to care about the order of your use and crate statements.

Move your #[macro_use] extern crate glium; statement to the top of your lib.rs and/or main.rs file as needed.

Solferino answered 9/9, 2016 at 15:40 Comment(0)
R
11

Do it just like the compiler told you:

an `extern crate` loading macros must be at the crate root

Put the #[macro_use] extern crate glium; in the crate root, which is main.rs in your case. Make sure the extern crate statement is before your mod statements, otherwise the modules won't be able to access the imported macros.

You can then use the macro in your submodule.

Roughcast answered 26/8, 2016 at 23:40 Comment(7)
yeah, that's the first thing I tried. It didn't work. I still get error: macro undefined: 'implement_vertex!'Goodly
Make sure the extern crate statement is before your mod statements, otherwise the mods won't be able to access the imported macros.Laxity
I'm getting the same error but for tests/common.rs. So what is analogous to src/main.rs or src/lib.rs for the test directory?Darien
@Nawaz curios to know how did you solve this issue incase of tests directory?Nebulize
@VijaySali Usually, every .rs file in tests/ is compiled as its own little binary crate with your main library as dependency. So you would have to add the #[macro_use] extern crate glium; at the top of every file. If you add your tests manually in Cargo.toml via [[test]], then those are you crate roots.Roughcast
@VijaySali: As Lukas explained in the comment above, the solution is to add extern crate stuff; to each of your tests/<each-file>.rs. Also, note that if you want to defined a common set of functions to be used in each of your tests file, then dont define that common file as tests/common.rs as that'll be considered yet another test file instead by Cargo. Define tests/common/mod.rs instead. Then you can add extern crate common to your test files.Darien
"Make sure the extern crate statement is before your mod statements ..." actually did the trick for me. Thanks!Dysart
J
6

I figured out my original problem. It turns out there are 2 Cargo roots? I have both a lib.rs and a main.rs. It turns out the correct place to put the #[macro_use] was in lib.rs.

Juliettejulina answered 26/8, 2016 at 23:32 Comment(1)
Thanks - this helped me out too trying to import riker-testkit Putting this comment here for others: Drop this in your lib.rs: ` #[macro_use] \n extern crate riker_testkit; `Kishke

© 2022 - 2024 — McMap. All rights reserved.