热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

rust放置木箱转向_Rust包管理器Cargo入门

使用Cargo构建程序到目前为止,一切都很顺利。现在你已经有了一个包,可构建一个二进制文件(也称为可执行文件)。在此之前,进入包目录&#x

使用 Cargo 构建程序

到目前为止,一切都很顺利。现在你已经有了一个包,可构建一个二进制文件(也称为可执行文件)。在此之前,进入包目录:

$ cd hello_opensource/

你可以使用 Cargo 的build命令来构建包。注意消息说它正在“编译”你的程序:

$ cargo build

Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)

Finished dev [unoptimized + debuginfo] target(s) in 0.38s

运行build命令后,检查项目目录发生了什么:

$ tree .

.

├── Cargo.lock

├── Cargo.toml

├── src

│ └── main.rs

└── target

└── debug

├── build

├── deps

│ ├── hello_opensource-147b8a0f466515dd

│ └── hello_opensource-147b8a0f466515dd.d

├── examples

├── hello_opensource

├── hello_opensource.d

└── incremental

└── hello_opensource-3pouh4i8ttpvz

├── s-fkmhjmt8tj-x962ep-1hivstog8wvf

│ ├── 1r37g6m45p8rx66m.o

│ ├── 2469ykny0eqo592v.o

│ ├── 2g5i2x8ie8zed30i.o

│ ├── 2yrvd7azhgjog6zy.o

│ ├── 3g9rrdr4hyk76jtd.o

│ ├── dep-graph.bin

│ ├── query-cache.bin

│ ├── work-products.bin

│ └── wqif2s56aj0qtct.o

└── s-fkmhjmt8tj-x962ep.lock

9 directories, 17 files

哇!编译过程产生了许多中间文件。另外,你的二进制文件将以与软件包相同的名称保存在./target/debug目录中。

使用 Cargo 运行你的应用程序

现在你的二进制文件已经构建好了,使用 Cargo 的run命令运行它。如预期的那样,它将在屏幕上打印Hello, world!。

$ cargo run

Finished dev [unoptimized + debuginfo] target(s) in 0.01s

Running `target/debug/hello_opensource`

Hello, world!

或者,你可以直接运行二进制文件,该文件位于:

$ ls -l ./target/debug/hello_opensource

-rwxr-xr-x. 2 root root 2655552 Feb 13 14:19 ./target/debug/hello_opensource

如预期的那样,它产生相同的结果:

$ ./target/debug/hello_opensource

Hello, world!

假设你需要重建包,并丢弃早期编译过程创建的所有二进制文件和中间文件。Cargo 提供了一个方便的clean选项来删除所有中间文件,但源代码和其他必需文件除外:

$ cargo clean

$ tree .

.

├── Cargo.lock

├── Cargo.toml

└── src

└── main.rs

1 directory, 3 files

对程序进行一些更改,然后再次运行以查看其工作方式。例如,下面这个较小的更改将Opensource添加到Hello, world!字符串中:

$ cat src/main.rs

fn main() {

println!("Hello, Opensource world!");

}

现在,构建该程序并再次运行它。这次,你会在屏幕上看到Hello, Opensource world!:

$ cargo build

Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)

Finished dev [unoptimized + debuginfo] target(s) in 0.39s

$ cargo run

Finished dev [unoptimized + debuginfo] target(s) in 0.01s

Running `target/debug/hello_opensource`

Hello, Opensource world!

使用 Cargo 添加依赖项

Cargo 允许你添加程序需要运行的依赖项。使用 Cargo 添加依赖项非常容易。每个 Rust 包都包含一个Cargo.toml文件,其中包含一个依赖关系列表(默认为空)。用你喜欢的文本编辑器打开该文件,找到[dependencies]部分,然后添加要包含在包中的库。例如,将rand库添加为依赖项:

$ cat Cargo.toml

[package]

name = "hello_opensource"

version = "0.1.0"

authors = ["test user "]

edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

rand = "0.3.14"

试试构建你的包,看看会发生什么。

$ cargo build

Updating crates.io index

Compiling libc v0.2.66

Compiling rand v0.4.6

Compiling rand v0.3.23

Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)

Finished dev [unoptimized + debuginfo] target(s) in 4.48s

现在,Cargo 会联系Crates.io(这是 Rust 用于存储 crate(或包)的中央仓库),并下载和编译rand。但是,等等 ——libc包是怎么回事?你没有要安装 libc 啊。是的,rand包依赖于libc包;因此,Cargo 也会下载并编译libc。

库的新版本会不断涌现,而 Cargo 提供了一种使用update命令更新其所有依赖关系的简便方法:

cargo update

你还可以选择使用-p标志跟上包名称来更新特定的库:

cargo update -p rand

使用单个命令进行编译和运行

到目前为止,每当对程序进行更改时,都先使用了build之后是run。有一个更简单的方法:你可以直接使用run命令,该命令会在内部进行编译并运行该程序。要查看其工作原理,请首先清理你的软件包目录:

$ cargo clean

$ tree .

.

├── Cargo.lock

├── Cargo.toml

└── src

└── main.rs

1 directory, 3 files

现在执行run。输出信息表明它已进行编译,然后运行了该程序,这意味着你不需要每次都显式地运行build:

$ cargo run

Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)

Finished dev [unoptimized + debuginfo] target(s) in 0.41s

Running `target/debug/hello_opensource`

Hello, world!

在开发过程中检查代码

在开发程序时,你经常会经历多次迭代。你需要确保你的程序没有编码错误并且可以正常编译。你不需要负担在每次编译时生成二进制文件的开销。Cargo 为你提供了一个check选项,该选项可以编译代码,但跳过了生成可执行文件的最后一步。首先在包目录中运行cargo clean:

$ tree .

.

├── Cargo.lock

├── Cargo.toml

└── src

└── main.rs

1 directory, 3 files

现在运行check命令,查看对目录进行了哪些更改:

$ cargo check

Checking hello_opensource v0.1.0 (/opensource/hello_opensource)

Finished dev [unoptimized + debuginfo] target(s) in 0.18s

该输出显示,即使在编译过程中创建了中间文件,但没有创建最终的二进制文件或可执行文件。这样可以节省一些时间,如果该包包含了数千行代码,这非常重要:

$ tree .

.

├── Cargo.lock

├── Cargo.toml

├── src

│ └── main.rs

└── target

└── debug

├── build

├── deps

│ ├── hello_opensource-842d9a06b2b6a19b.d

│ └── libhello_opensource-842d9a06b2b6a19b.rmeta

├── examples

└── incremental

└── hello_opensource-1m3f8arxhgo1u

├── s-fkmhw18fjk-542o8d-18nukzzq7hpxe

│ ├── dep-graph.bin

│ ├── query-cache.bin

│ └── work-products.bin

└── s-fkmhw18fjk-542o8d.lock

9 directories, 9 files

要查看你是否真的节省了时间,请对build和check命令进行计时并进行比较。首先,计时build命令:

$ time cargo build

Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)

Finished dev [unoptimized + debuginfo] target(s) in 0.40s

real 0m0.416s

user 0m0.251s

sys 0m0.199s

在运行check命令之前清理目录:

$ cargo clean

计时check命令:

$ time cargo check

Checking hello_opensource v0.1.0 (/opensource/hello_opensource)

Finished dev [unoptimized + debuginfo] target(s) in 0.15s

real 0m0.166s

user 0m0.086s

sys 0m0.081s

显然,check命令要快得多。

建立外部 Rust 包

到目前为止,你所做的这些都可以应用于你从互联网上获得的任何 Rust crate。你只需要下载或克隆存储库,移至包文件夹,然后运行build命令,就可以了:

git clone

cd

cargo build

使用 Cargo 构建优化的 Rust 程序

到目前为止,你已经多次运行build,但是你注意到它的输出了吗?不用担心,再次构建它并密切注意:

$ cargo build

Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)

Finished dev [unoptimized + debuginfo] target(s) in 0.36s

看到了每次编译后的[unoptimized + debuginfo]文本了吗?这意味着 Cargo 生成的二进制文件包含大量调试信息,并且未针对执行进行优化。开发人员经常经历开发的多次迭代,并且需要此调试信息进行分析。同样,性能并不是开发软件时的近期目标。因此,对于现在而言是没问题的。

但是,一旦准备好发布软件,就不再需要这些调试信息。而是需要对其进行优化以获得最佳性能。在开发的最后阶段,可以将--release标志与build一起使用。仔细看,编译后,你应该会看到[optimized]文本:

$ cargo build --release

Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)

Finished release [optimized] target(s) in 0.29s

如果愿意,你可以通过这种练习来了解运行优化软件与未优化软件时节省的时间。

使用 Cargo 创建库还是二进制文件

任何软件程序都可以粗略地分类为独立二进制文件或库。一个独立二进制文件也许即使是当做外部库使用的,自身也是可以运行的。但是,作为一个库,是可以被另一个独立二进制文件所利用的。到目前为止,你在本教程中构建的所有程序都是独立二进制文件,因为这是 Cargo 的默认设置。 要创建一个库,请添加--lib选项:

$ cargo new --lib libhello

Created library `libhello` package

这次,Cargo 不会创建main.rs文件,而是创建一个lib.rs文件。 你的库的代码应该是这样的:

$ tree .

.

└── libhello

├── Cargo.toml

└── src

└── lib.rs

2 directories, 2 files

Cargo 就是这样的,不要奇怪,它在你的新库文件中添加了一些代码。通过移至包目录并查看文件来查找添加的内容。默认情况下,Cargo 在库文件中放置一个测试函数。

使用 Cargo 运行测试

Rust 为单元测试和集成测试提供了一流的支持,而 Cargo 允许你执行以下任何测试:

$ cd libhello/

$ cat src/lib.rs

#[cfg(test)]

mod tests {

#[test]

fn it_works() {

assert_eq!(2 + 2, 4);

}

}

Cargo 有一个方便的test命令,可以运行代码中存在的任何测试。尝试默认运行 Cargo 在库代码中放入的测试:

$ cargo test

Compiling libhello v0.1.0 (/opensource/libhello)

Finished test [unoptimized + debuginfo] target(s) in 0.55s

Running target/debug/deps/libhello-d52e35bb47939653

running 1 test

test tests::it_works ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

Doc-tests libhello

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

深入了解 Cargo 内部

你可能有兴趣了解在运行一个 Cargo 命令时它底下发生了什么。毕竟,在许多方面,Cargo 只是个封装器。要了解它在做什么,你可以将-v选项与任何 Cargo 命令一起使用,以将详细信息输出到屏幕。

这是使用-v选项运行build和clean的几个例子。

在build命令中,你可以看到这些给定的命令行选项触发了底层的rustc(Rust 编译器):

$ cargo build -v

Compiling hello_opensource v0.1.0 (/opensource/hello_opensource)

Running `rustc --edition=2018 --crate-name hello_opensource src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=147b8a0f466515dd -C extra-filename=-147b8a0f466515dd --out-dir /opensource/hello_opensource/target/debug/deps -C incremental=/opensource/hello_opensource/target/debug/incremental -L dependency=/opensource/hello_opensource/target/debug/deps`

Finished dev [unoptimized + debuginfo] target(s) in 0.36s

而clean命令表明它只是删除了包含中间文件和二进制文件的目录:

$ cargo clean -v

Removing /opensource/hello_opensource/target

不要让你的技能生锈

要扩展你的技能,请尝试使用 Rust 和 Cargo 编写并运行一个稍微复杂的程序。很简单就可以做到:例如,尝试列出当前目录中的所有文件(可以用 9 行代码完成),或者尝试自己回显输入。小型的实践应用程序可帮助你熟悉语法以及编写和测试代码的过程。

本文为刚起步的 Rust 程序员提供了大量信息,以使他们可以开始入门 Cargo。但是,当你开始处理更大、更复杂的程序时,你需要对 Cargo 有更深入的了解。当你准备好迎接更多内容时,请下载并阅读 Rust 团队编写的开源的《Cargo 手册》,看看你可以创造什么!



推荐阅读
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • Spring框架《一》简介
    Spring框架《一》1.Spring概述1.1简介1.2Spring模板二、IOC容器和Bean1.IOC和DI简介2.三种通过类型获取bean3.给bean的属性赋值3.1依赖 ... [详细]
  • node.jsurlsearchparamsAPI哎哎哎 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • CentOS7.8下编译muduo库找不到Boost库报错的解决方法
    本文介绍了在CentOS7.8下编译muduo库时出现找不到Boost库报错的问题,并提供了解决方法。文章详细介绍了从Github上下载muduo和muduo-tutorial源代码的步骤,并指导如何编译muduo库。最后,作者提供了陈硕老师的Github链接和muduo库的简介。 ... [详细]
  • PHP反射API的功能和用途详解
    本文详细介绍了PHP反射API的功能和用途,包括动态获取信息和调用对象方法的功能,以及自动加载插件、生成文档、扩充PHP语言等用途。通过反射API,可以获取类的元数据,创建类的实例,调用方法,传递参数,动态调用类的静态方法等。PHP反射API是一种内建的OOP技术扩展,通过使用Reflection、ReflectionClass和ReflectionMethod等类,可以帮助我们分析其他类、接口、方法、属性和扩展。 ... [详细]
author-avatar
平凡的如果爱166
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有