Introduction: Why a Local Crate is Not a Luxury, But a Necessity
\n\nImagine: you are writing a Rust library for parsing configuration files. It's still raw, not ready for publication on crates.io, but you already want to test it in a real project — an Actix web server or a CLI utility. What to do? Copy the code? Create a monorepo? No, in Rust there is an elegant solution for this — a local unpublished crate.
The question "How to use a local unpublished crate?" has gathered thousands of views on Stack Overflow. This is no coincidence: every Rust developer sooner or later faces the need to connect their own crate that hasn't been released yet. In this article, we will cover all the methods — from simply specifying a path to working with Git dependencies and workspaces. Let's go!
\n\nWhat is an Unpublished Crate and Why Do You Need It?
\n\nAn unpublished crate is a Rust package that exists only on your local disk or in a private repository. It is not uploaded to crates.io and is not available to other developers (unless you give them access to the files).
Typical use cases:
\n- \n
- Developing a library in parallel with the main project \n
- Refactoring: extracting part of the code into a separate crate \n
- Private corporate libraries that cannot be published \n
- Testing dependencies before publication \n
The main advantage is that you have full control over the code and can make changes instantly without waiting for publication on crates.io.
\n\nMethod 1: Path Dependency — The Simplest and Fastest
\n\nThis is the basic method, suitable when both projects (the dependency and the dependent) are on your computer.
\n\nProject Structure
\n\nLet's say you have the following folder structure:
\n\nmy_project/\n├── my_lib/ # unpublished crate\n│ ├── Cargo.toml\n│ └── src/\n│ └── lib.rs\n└── my_app/ # main project\n ├── Cargo.toml\n └── src/\n └── main.rs\n\nStep 1: Create the my_lib Library
\n\nInside my_lib/Cargo.toml:
[package]\nname = "my_lib"\nversion = "0.1.0"\nedition = "2021"\n\n[dependencies]\n\nIn my_lib/src/lib.rs, let's write a simple function:
pub fn greet(name: &str) -> String {\n format!("Hello, {}! This is a local crate.", name)\n}\n\nStep 2: Connect my_lib in my_app via path
\n\nIn my_app/Cargo.toml, add the [dependencies] section:
[package]\nname = "my_app"\nversion = "0.1.0"\nedition = "2021"\n\n[dependencies]\nmy_lib = { path = "../my_lib" }\n\nNote: the path is specified relative to the main project's Cargo.toml file. If the library is in a different directory, specify an absolute or relative path.
Step 3: Use the Crate in Code
\n\nIn my_app/src/main.rs:
use my_lib::greet;\n\nfn main() {\n let message = greet("Alexey");\n println!("{}", message);\n}\n\nRun: cargo run — and you will see the output: "Hello, Alexey! This is a local crate."
Important! Any changes in my_lib will be automatically picked up the next time you build my_app. No need to reinstall or update versions.
Method 2: Git Dependencies — For Team Collaboration
\n\nIf you work in a team or store code in Git, it's better to use Git dependencies. This is convenient when the crate is in a separate repository (even a private one).
\n\nSetup
\n\nSuppose your unpublished crate my_lib is in the repository https://github.com/yourname/my_lib.git