80

How do I include a file with the full path my_project/src/include_me.rs in main.rs?

I've checked the dependencies guide, and all of them appear to be including a binary. I've also checked "The Book", but none of the examples there end in ".rs" either.

How do I make include_me.rs compile with the rest of the project?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Seph Reed
  • 8,797
  • 11
  • 60
  • 125
  • 2
    No, I linked that above. It's only clear to you because it's familiar. Nowhere in there is an include that implies file system navigation, ie `/path/to/include.rs`. Python does a similar thing of getting rid of the extension on imports, and I personally find it non-idiomatic. It makes imports not look like they relate to a path. – Seph Reed Aug 06 '17 at 06:23
  • Not, you did not link to the section I linked to. The one I linked to has this text: *Next, let’s extract the network module into its own file using the same pattern [...] Then create a **new src/network.rs file** and enter the following*. I'm unclear which part of that section is hard to understand. – Shepmaster Aug 06 '17 at 13:15
  • 3
    It's within a few chapters. I read the whole book up to that point, and either of these two chapters seemed like where I would find my answer, but did not. – Seph Reed Aug 06 '17 at 23:11

1 Answers1

144

There are basically two (main) ways in Rust to include code from somewhere else:

1. "Including" internal code

If your include_me.rs belongs to your project, you should move it to the same folder main.rs lies in:

└── src
    ├── include_me.rs
    └── main.rs

Then you can write this in your main.rs:

mod include_me;

fn main() {
    // Call a function defined in the other file (module)
    include_me::some_function();
}

A mod declaration makes the Rust compiler look for the corresponding .rs files automatically!

So everything that belongs to your project, belongs in the same folder (or a subfolder thereof) as the folder where main.rs (or lib.rs) is lying. The files are then "included" via the module system. To read a good introduction into modules, please read the chapter on modules in the Rust book. You could also check out Rust by Example on that topic. The module system is pretty central and thus important to learning Rust.

2. "Including" external code

If your include_me.rs is something that doesn't belong to your actual project, but is rather a collection of useful things you are using in multiple projects, it should be seen as a library. To include code of such external libraries, you have to include it as an extern crate. And to make your life easier, you really want to use Cargo!

So let's prepare your include_me.rs as Cargo library project. You need the following file structure (which is automatically generated by cargo new my_library --lib):

. my_library
  ├── Cargo.toml
  └── src
      └── lib.rs

Now copy all the contents from include_me.rs into lib.rs (it is just convention to call the root file of a library project lib.rs). Let's say that the my_library folder's full path is ~/code/my_library.

Now let's prepare your main project's Cargo project. It has a similar file structure (but a main.rs instead of lib.rs, because it's a executable-project, not a library-project):

. my_project
├── Cargo.toml
└── src
    └── main.rs

To declare your dependency on my_library, you have to put this into your Cargo.toml:

[package]
name = "my_project"
version = "0.1.0"
authors = ["you"]
edition = "2018"

[dependencies]
my_library = { path = "~/code/my_library" }

You can also use relative paths ("../my_library"), but it only makes sense if you know that the two projects always stay where they are, relative to one another (like if they are both managed in the same repository).

Now you can, in your main.rs, write:

use my_library::some_function;

fn main() {
    // Call a function defined in the other file (extern crate)
    some_function();
}

If you want to upload any of those two projects, you have to interact with crates.io (or another crates registry, if your company has one), but this is another topic.

(Note: some time ago, it was necessary to write extern crate my_library; inside main.rs. This is not necessary anymore, but you might find old code with extern crate declarations.)

Any other ways?

Yes, but you shouldn't use those. There is the include!() macro which allows you to verbatim include other files, just like the #include from C-land. However, it is strongly discouraged to use this in situations where the module system would be able to solve your problem. include!() is only useful in very special situations, often linked to a more complex build system which generates code.

Lukas Kalbertodt
  • 79,749
  • 26
  • 255
  • 305
  • 7
    Thank you very much, I really appreciate it, and I think others may as well. As basic as this is, it is a necessary step for people learning alone. It may seem obvious that mod can be used to include things with or without the '.rs' extension, but to a new comer it appears to only be used for pulling files from some unknown dictionary (similar to io, or Math). Yours is the first example I have seen of a `mod` referencing a `*.rs` file anywhere, and I really appreciate you sharing this syntax. – Seph Reed Aug 06 '17 at 06:33
  • 2
    Thanks for the time you put into this answer. Very useful. – womp May 29 '19 at 01:58
  • Great answer. Thanks! Please also fix the typo in `use my_library::some_function();`. There shouldn't be a parenthesis there I believe. – Abdullah Khan Jun 27 '22 at 07:22
  • 1
    @AbdullahKhan Oh, good catch. Fixed it! – Lukas Kalbertodt Jun 27 '22 at 07:29
  • As a clarification, `mod include_me;` declares a module (defined by `./include_me.rs`). I think the OP doesn't know about Rust "modules", so when he asks "how do I include a file?", he's asking the wrong question and needs to be redirected: "You don't; you need to declare the other file as a MODULE and use it that way." – lmat - Reinstate Monica Jan 11 '23 at 15:32
  • This has to be one of the best answers I've read on this website. Clear, thorough... chefs kiss. Thanks Lukas. – codyj Jan 20 '23 at 02:02