Rust 开发命令行工具(中)(三)

简介: Rust 开发命令行工具(中)(三)

3. 打包并发布 Rust 项目

经过,我们通过单元测试黑盒测试后,我们确认,我们的项目已经功能完备了。是骡子是马拉出来遛遛现在是打包和发布的时候了!

下面我们看看发布Rust的几种方式。

最快:cargo publish

使用cargo发布应用程序是最简单的方法。我们还记得我们如何将外部依赖项添加到项目中吗?cargo会从其默认的包管理器crates.io下载它们。借助cargo publish,我们也可以将crate发布到crates.io。这适用于所有crate,包括具有二进制目标的crate

crate发布到crates.io相当简单:

  1. 如果尚未创建crates.io帐户,需要创建一个帐户。目前,可以通过在GitHub上授权来完成

image.png

  1. 本地计算机上,登录cargo登录,为此,我们需要到crates.io帐户页面,创建一个新令牌,然后运行cargo login <your-new-token>

image.png

image.png

  1. 确认Cargo.toml信息,确保我们已添加了必要的元数据
[package]
name = "f789"
version = "0.1.0"
authors = ["Your Name <your@email.com>"]
license = "MIT OR Apache-2.0"
description = "文件搜索工具"
readme = "README.md"
homepage = "https://github.com/you/f789"
repository = "https://github.com/you/f789"
keywords = ["cli", "search"]
categories = ["command-line-utilities"]
  1. 使用cargo publish进行发布

image.png

  1. 发布成功后,就可以在crates.io中查看

image.png

  1. 如果你是首次在crates.io发布,你需要验证一下邮箱

image.png

如果想了解可以在cargo发布指南中了解更多信息。

如何从crates.io安装二进制文件

我们已经了解了如何将crate发布到crates.io,我们可能想知道如何安装它。与库不同,cargo会在运行cargo build(或类似的命令)时为我们下载和编译库,我们需要明确告诉它要安装二进制文件。

使用cargo install <crate-name>可以实现这一点。默认情况下,它会下载crate,编译其中包含的所有二进制目标(以release模式进行,所以可能需要一些时间),并将它们复制到~/.cargo/bin/目录中。

还可以从git存储库安装crate,仅安装crate的特定二进制文件,并指定替代目录以进行安装。

何时使用它

cargo install是一种安装二进制crate的简单方法。对于Rust开发人员来说非常方便,但有一些重要的缺点:由于它总是从头开始编译我们的源代码,因此使用我们的工具的用户需要在其计算机上安装Rustcargo和项目所需的所有其他系统依赖项。编译大型Rust代码库可能也需要一些时间。

使用cargo install f789按照

image.png

安装成功,并默认存储到/Users/xxx/.cargo/bin

image.png

我们现在可以随意打开一个命令行,并且按照我们之前代码逻辑,f789 front text.txt就可以查看运行结果了。

image.png


大家可以忽略上面截图中git部分的。我为了省事,直接在源代码的目录中,进行了上述的操作。其实上述操作可以在任何终端中运行。

分发二进制文件

Rust是一种编译为本机代码的语言,并默认情况下静态链接所有依赖项。当我们在包含名为f789的二进制文件的项目上运行cargo build时,我们将得到一个名为f789的二进制文件。

  • 使用cargo build,它将位于target/debug/f789
  • 当我们运行cargo build --release时,它将位于target/release/f789

这意味着,我们可以将这个文件发送给与我们运行相同操作系统的人,他们就可以运行它。

它解决了cargo install的两个缺点:用户的计算机上不需要安装Rust,并且不是需要一分钟才能编译,他们可以立即运行二进制文件。

因此,正如我们所看到的,cargo build已经为我们构建了二进制文件。唯一的问题是,默认情况下,这些二进制文件不能保证在所有有趣的平台上运行。如果我们在Windows计算机上运行cargo build,我们不会得到默认情况下在Mac上运行的二进制文件。

在 CI 上构建二进制版本

如果我们的工具是开源的并托管在GitHub上,那么设置免费的CI(持续集成)服务(如Travis CI)非常容易。这基本上是在虚拟机中每次我们推送更改到我们的存储库时运行设置命令。这些命令是什么以及它们运行在哪种类型的机器上是可配置的。

我们还可以使用此功能构建二进制文件并将其上传到GitHub

  • 首先,我们运行cargo build --release并将二进制文件上传到某个位置
  • 其次,我们仍然需要确保我们构建的二进制文件与尽可能多的系统兼容。
  • 例如,在Linux上,我们可以编译而不是为当前系统编译,而是为x86_64-unknown-linux-musl目标编译,以避免依赖默认系统库。
  • macOS上,我们可以将MACOSX_DEPLOYMENT_TARGET设置为10.7,只依赖于版本10.7及更早版本中存在的系统功能。

另一种方法是使用包含构建二进制文件所需工具的预构建(Docker)映像。这允许我们轻松地针对更多的异构平台进行定位。trust项目包含可以包含在我们的项目中的脚本以及设置的说明。它还包括使用AppVeyorWindows支持。

如果我们只想在本地设置并在自己的计算机上生成发布文件,请仍然查看trust。它在内部使用cross,它的工作方式类似于cargo,但将命令转发到Docker容器内部的cargo进程。这些映像的定义也可在cross的存储库中找到。

何时使用它

一般来说,拥有二进制发布版本是一个好主意,几乎没有任何不利因素。它不能解决用户必须手动安装和更新工具的问题,但他们可以快速获取最新的发布版本,而无需安装Rust


将应用程序放入包存储库

迄今为止,我们看到的两种方法都不是我们通常在计算机上安装软件的方式。特别是大多数操作系统上的全局软件包管理器,我们可以使用这些管理器来安装命令行工具。对用户来说:如果他们可以以与安装其他工具相同的方式安装程序,那么就无需考虑如何安装我们的程序。这些软件包管理器还允许用户在新版本可用时更新其程序。

难点在于,支持不同的系统意味着我们必须查看这些不同的系统如何工作。对于某些系统,只需向存储库添加一个文件(例如,为macOSbrew添加一个Formula文件),但对于其他系统,我们通常需要自己发送补丁并将我们的工具添加到它们的存储库中。有一些有用的工具,如cargo-bundlecargo-debcargo-aur,但描述它们的工作原理以及如何正确为这些不同的系统打包我们的工具超出了本章的范围。


代码展示

src/main.rs

use anyhow::{Context, Result};
use clap::Parser;
use std::fs::File;
use std::io::{self, BufRead};
use std::path::PathBuf;
/// 在文件中搜索模式并显示包含它的行。
#[derive(Parser)]
struct Cli {
    /// 要查找的模式
    pattern: String,
    /// 要读取的文件的路径
    path: PathBuf,
}
fn main() -> Result<()> {
    let args = Cli::parse();
    // 打开文件并创建一个 BufReader 来逐行读取
    let file = File::open(&args.path).with_context(|| format!("无法打开文件 {:?}", &args.path))?;
    let reader = io::BufReader::new(file);
    let stdout = io::stdout();
    let stdout_lock = stdout.lock();
    let handle = io::BufWriter::new(stdout_lock);
    let content = reader
        .lines()
        .collect::<io::Result<Vec<String>>>()?
        .join("\n");
    f789::find_matches(&content, &args.pattern, handle)?;
    Ok(())
}

src/lib.rs

use anyhow::Result;
use indicatif::ProgressBar;
use std::io::Write;
pub fn find_matches(content: &str, pattern: &str, mut writer: impl Write) -> Result<()> {
    let pb = ProgressBar::new(100);
    for line in content.lines() {
        do_hard_work();
        pb.println(format!("[+] 查找到了 #{:?}项", line));
        pb.inc(1);
        if line.contains(pattern) {
            writeln!(writer, "{}", line)?;
        }
    }
    Ok(())
}
fn do_hard_work() {
    std::thread::sleep(std::time::Duration::from_millis(250));
}

后记

分享是一种态度

参考资料:

  1. 用Rust 写一个命令行
  2. crates

全文完,既然看到这里了,如果觉得不错,随手点个赞和“在看”吧。

相关文章
|
1月前
|
Rust 安全 程序员
拜登:“一切非 Rust 项目均为非法”,开发界要大变天?
白宫国家网络总监办公室(ONCD,以下简称网总办)在本周一发布的报告中说道:“程序员编写代码并非没有后果,他们的⼯作⽅式于国家利益而言至关重要。”
34 1
|
2月前
|
Rust 前端开发 JavaScript
Rust在前端与全栈开发中的实践探索
随着Rust语言的日渐成熟,其应用场景已经从后端扩展到前端和全栈开发领域。本文将深入探讨Rust语言在前端与全栈开发中的实际应用案例,分析Rust语言在这些领域的优势和面临的挑战,并展望Rust未来的发展趋势。
|
4月前
|
Rust 测试技术 人机交互
Rust 开发命令行工具(中)(二)
Rust 开发命令行工具(中)(二)
|
4月前
|
存储 Rust JavaScript
Rust 开发命令行工具(中)(一)
Rust 开发命令行工具(中)(一)
|
4月前
|
存储 Rust Linux
Rust 开发命令行工具(上)(三)
Rust 开发命令行工具(上)(三)
|
4月前
|
存储 Rust Shell
Rust 开发命令行工具(上)(二)
Rust 开发命令行工具(上)(二)
|
4月前
|
存储 人工智能 Rust
Rust 开发命令行工具(上)(一)
Rust 开发命令行工具(上)(一)
|
4天前
|
Rust 安全 程序员
|
4天前
|
Rust 安全 程序员
Rust vs Go:解析两者的独特特性和适用场景
在讨论 Rust 与 Go 两种编程语言哪种更优秀时,我们将探讨它们在性能、简易性、安全性、功能、规模和并发处理等方面的比较。同时,我们看看它们有什么共同点和根本的差异。现在就来看看这个友好而公平的对比。
|
8月前
|
Rust Go C++
Rust vs Go:常用语法对比(十三)(1)
Rust vs Go:常用语法对比(十三)(1)
63 0