This guide outlines the standard procedure for compiling and publishing a Rust library crate to the central registry.
Configuring the Package Manifest
The initial step involves modifying the Cargo.toml file to define metadata and build parameters. The configuration below illustrates the essential fields required for a valid release:
[package]
name = "net_scanner"
version = "0.2.0"
edition = "2021"
description = "A utility for scanning and analyzing network ports."
license = "MIT OR Apache-2.0"
[dependencies]
[profile.dev]
opt-level = 0
[profile.release]
opt-level = 3
The [package] section mandates a unique name (names are allocated on a first-come, first-served basis), a semantic version, the Rust edition, a short description, and a license identifier (typically using SPDX identifiers). The [profile] sections dictate optimization levels: opt-level = 0 speeds up compilation for development, whereas opt-level = 3 maximizes runtime performance for release builds at the cost of increased compile time.
Annotating Code with Documentation
Rust supports specific syntax for generating documentation via rustdoc. Documentation comments can be applied using /// for item-specific docs or //! for module-level (crate) docs. These comments support standard Markdown. You can preview the generated HTML documentation locally by running:
cargo doc --open
Example documentation implementation:
//! # Network Scanner
//!
//! This library provides tools to perform asynchronous port scans.
/// Holds the configuration parameters for the scanning operation.
#[derive(Debug)]
pub struct ScanConfig {
/// The target IP address or hostname.
pub target: String,
/// The range of ports to scan (e.g., "1-1000").
pub port_range: String,
/// Enables verbose logging during the scan.
pub verbose: bool,
}
/// Initiates the network scan based on the provided configuration.
///
/// # Arguments
///
/// * `cfg` - A reference to the ScanConfig struct.
///
/// # Returns
///
/// A result containing a vector of open ports or an error string.
///
/// # Example
///
/// ```no_run
/// let config = ScanConfig {
/// target: String::from("127.0.0.1"),
/// port_range: String::from("80-443"),
/// verbose: false,
/// };
/// let ports = run_scan(&config);
/// ```
pub fn run_scan(cfg: &ScanConfig) -> Result<vec>, String> {
// Implementation logic here
Ok(vec![])
}
</vec>
Registry Account and API Tokens
To publish, you must register an account on crates.io. Authentication is typically handled via a GitHub account or email verification. Once logged in, navigate to "Account Settings" and select "API Tokens" to generate a new token. You should configure the token's scope and expiration based on your needs. Additionally, ensure your email address is verified in you're profile settings, as the registry rejects uploads from unverified accounts.
Compiling the Release Build
Although the publish command compiles the crate automatical, it is advisable to perform a release build locally beforehand to catch errors early:
cargo build --release
Authenticating with Cargo
Save your API token locally to authorize Cargo for publishing operations:
cargo login <your-api-token-here>
Publishing to the Registry
Use the following command to package and upload your library to crates.io:
cargo publish
If the package name or version number is already taken by another crate, the process will fail. Unlike some other package managers, Crates.io enforces version immutability; you cannot overwrite an existing version. You must increment the version in Cargo.toml to release an update.
Managing Published Versions
If a critical bug is discovered post-release, you can "yank" the version. This marks the version as such in the registry, preventing new projects from using it as a dependency, though existing dependents will continue to download it.
cargo yank --vers 0.2.0
To revert this action and restore the version as available for new projects:
cargo yank --vers 0.2.0 --undo
For advanced options, such as publishing to alternative registries, refer to the help documentation via cargo help publish.