Rust is a new project from the Apache Foundation; in short, it is a modern functional programming language, with performance expected to be roughly on par with C++.
Whether a language is practical depends on more than the language itself. Of course, a language that feels great to write may be a thousand times better than one with awful syntax, but that is not the only criterion. A good toolchain, a healthy community environment, and other factors can make a language seem much more promising—or disappointing.
Rust uses Cargo as its build environment, and it is the default once you’ve installed Rust.
Much of the time, code can be reused, and good project organization makes things much easier. At this point, Cargo looks like a very nice tool—though sometimes it still leaves something to be desired.
For Rust, Cargo is roughly what cmake + make are to C. We place a Cargo.toml file in the project root and fill it with the configuration we want. Then Cargo can automatically download dependencies and compile the project. We can also use it to publish our own crates, and so on. In short, it is an integrated tool that handles a lot of things.
The goal of this article is to introduce how to write a library, publish a dependency, and use one.
First, let’s prepare a library
[github_widget repo="yuikns/r"]
The directory structure looks roughly like this:
$ tree
.
├── Cargo.toml
├── LICENSE
├── README.md
├── src
│ ├── lib.rs
│ └── utils
│ └── mod.rs
└── test
└── test.rsThe contents of lib.rs are:
#![crate_name = "r"]
#![deny(warnings)]
#[allow(dead_code)]
pub mod utils;The meaning is simple. The first few lines are declarations. Because it is a library, you may expose methods that are not actually used internally, so allow(dead_code) is used to suppress that warning. Then the utils package is exposed.
Under utils there is a mod.rs whose content is a hello world:
pub fn it_works() {
println!("it works! a voice comes from r::utils::it_works")
}Note that both the mod and the function it_works that I want to expose are marked pub; anything in between that is not pub will not be reachable from outside.
Then write the configuration in the project root. The most basic configuration is:
[package]
name = "r"
version = "0.0.1"
authors = ["Yu Jing <yu@example.com>"]Then you can run
cargo buildOnce it compiles, a toy library is ready.
After that, we can reference it in several ways, including:
- local reference
<li>GitHub reference</li>
<li>crates public registry reference</li>
A local reference needs no special explanation—just keep the files around. A GitHub reference requires pushing the project to GitHub. To reference from the crates public registry, you need to register an account on crates and obtain a token before you can publish.
The first two require no special steps; only crates needs a little attention.
First, we need to create an account at crates—you can actually just link through GitHub, which is very simple.
Then, at the URL https://crates.io/me, you can see an API key belonging to this account.
Run locally
cargo login your_api_keyand that’s it.
Essentially, this just writes a line containing the token in ~/.cargo/config.
[registry]
token = "your_api_key"Then, following the steps on this page, edit your Cargo.toml, and run the command
cargo publishOne thing to note: crates do not support deletion or modification. Once you push one up, that package stays online permanently. You cannot push again with the same version number to overwrite it. You can only use the yank command to prevent it from being downloaded any further
cargo yank --vers 0.0.1
cargo yank --vers 0.0.1 --undoNext, we need to create a project to call it.
[github_widget repo="yuikns/rs"]
This project is a simple example. Its content is as follows:
$ tree
.
├── Cargo.lock
├── Cargo.toml
├── LICENSE
└── src
└── main.rsCalling it is very straightforward
extern crate r;
use r::utils::it_works;
fn main() {
it_works();
}The configuration is also simple. In addition to the usual [package] section, you need to add a [dependencies] section.
.toml is a hybrid between .ini and .json, giving us a lot of freedom in how we write it.
We need to depend on the external library r.
If we're depending on a local file, we need the "path" parameter
[dependencies]
r = {path="../r"}path can be either a relative or an absolute path.
We can also write it like this:
[dependencies.r]
path="../r"It means the same thing.
If we're depending on git, we need at least a .git URL, and optionally a SHA1. The trailing .git on GitHub is optional.
[dependencies.r]
git = "https://github.com/yuikns/r"[dependencies]
r = { git = "https://github.com/yuikns/r.git", rev = "0dc4ef" }Both of the above forms are valid.
If we've published it to crates, things become even simpler
[dependencies]
r="0.0.1"You just need a version number.
Comments · 2