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?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
jz87
  • 9,199
  • 10
  • 37
  • 42
  • 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. – DK. Aug 27 '16 at 07:12
  • 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 @DK. already said. – Lukas Kalbertodt Aug 27 '16 at 10:27

3 Answers3

23

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.

E_net4
  • 27,810
  • 13
  • 101
  • 139
John Anthony
  • 247
  • 1
  • 2
9

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.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Lukas Kalbertodt
  • 79,749
  • 26
  • 255
  • 305
  • yeah, that's the first thing I tried. It didn't work. I still get error: macro undefined: 'implement_vertex!' – jz87 Aug 27 '16 at 01:24
  • 1
    Make sure the `extern crate` statement is before your `mod` statements, otherwise the mods won't be able to access the imported macros. – durka42 Aug 27 '16 at 19:41
  • 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? – Nawaz Oct 07 '18 at 16:42
  • @Nawaz curios to know how did you solve this issue incase of tests directory? – Vijay Sali Aug 15 '20 at 18:40
  • 1
    @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. – Lukas Kalbertodt Aug 15 '20 at 19:07
  • 1
    @VijaySali: As Lukas explained in the comment above, the solution is to add `extern crate stuff;` to each of your `tests/.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. – Nawaz Aug 15 '20 at 20:56
  • "Make sure the extern crate statement is before your mod statements ..." actually did the trick for me. Thanks! – LongHike Oct 09 '20 at 06:32
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.

tdube
  • 2,453
  • 2
  • 16
  • 25
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 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; ` – JasonG Jul 16 '21 at 19:14