For an executable's integration tests that originally had no lib.rs , since integration tests require use but cannot directly use main , we created a lib.rs and moved all of main 's submodules into it—essentially making main obsolete.
The strange thing is, we had a macro defined in main that was also moved to lib . Through use super::* , submodules could call the macro. But later, when we added another one, we found it couldn't be located no matter what.
After struggling for a long time, we discovered that we needed to add it in main as well—as if it was using the definition from main .
Then, as an experiment, we commented out the one in lib.rs and found it also threw an error, indicating that it was also using the one from lib.rs ...
Declarative macros don't have the same scoping mechanism as items have. By themselves they are textually scoped (i.e. can only be used in code that comes after the macro declaration) and are visible only to a module and its submodules. The #[macro_use] and #[macro_export] attributes can be used to change this. In your case, you want to #[macro_export] your macro from your library to make it visible as your_lib::your_macro in your binary. See:
that is my lib.rs; I can't call the loge macro in applications module; which in turn has its submodule, , evety submodle includes a use super::*;
the log macro can be called, I totally confused by that until I notice main.rs defined the log macro too ( in fact, lib.rs just a copy of main.rs for using in the tests)
After I add loge to main.rs, everything is OK.
And after I deleted the defination in lib.rs, another error reports, meaning both main.rs and lib.rs must contains the macros
This sounds like you are also defining the same submodules your library has in your binary crate? This would mean that both crates need to define the macros to have them visible to the submodules. I recommend splitting library and binary crates in a way that there isn't any overlap between the two and use the library to import everything that is needed in your binary.
Yes, you can't import from a binary. It still would be more idiomatic to specify your module tree only in your library and use your_lib::some_module in your binary, instead of defining mod some_module there, too, I'd say.
When you import and use your_lib::log from your tests or inside of your library? Is log defined in the library root or in some submodule, like your_lib::util? #[macro_export]always exports the macro from the library root, not from the module the macro is defined in.
I don't import the macros explicitly, I use use super::* at each module level, the macro deined in lib.rs, then use super::* in submodule A will bring the macro to module A; then use suer::* in A::B will bring it to B, then to A::C ... etc. I call the macro in some module of the tree. I think it should visible at any level; but except I deine the macro in root module of main.rs, it is invisible. But In fact, I only use lib.rs in tests, I don't know why the deination in main.rs takes effect.
But if I delete the defination in the lib.rs --- since the macro takes from main.rs, so defination in lib.rs is unecessary? --- it shows without the defination in lib.rs, the compiling fails too.
If you define module A in both lib.rs and main.rs, you'll need to define log and loge in both lib.rs and main.rs as well. Or at least have a use your_lib::{log, loge}; in main.rs. With your setup, A is compiled twice, once for your library and once for your binary. This is one of the reasons why I recommended that you should define the module tree only in your library and import it into your binary from there.