讲动人的故事,写懂人的代码
1.6 Cargo.lock:确保构建稳定可靠
“看!”席双嘉一边指着屏幕一边说,“终端窗口提示符的颜色,从绿变黄了。这就意味着代码在上次提交后有点变化。”
赵可菲:“但是我们只是运行了程序,代码应该没动呀。”
席双嘉敲了下git status -uall
,这样就能显示出所有未被git跟踪的文件。
屏幕上出现了一个名叫Cargo.lock的文件。
代码语言:javascript复制 zkf@mbp ~/dicey_temperatures ↱ main git status -uall
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
Untracked files:
(use "git add <file>..." to include in what will be committed)
Cargo.lock
nothing added to commit but untracked files present (use "git add" to track)
席双嘉:“看,只要一运行cargo run
,Cargo.lock文件就被自动创建出来了嘛。”
他随便点开了这个文件。
代码语言:javascript复制# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "hello_world_rust"
version = "0.1.0"
赵可菲:“嘿,这个文件需要提交到版本库吗?”
贾克强:“对的,Cargo.lock文件得提交到版本库,让我们的构建更稳定和可靠。”
“就像咱们程序员最怕的那种情况,明明在自己这儿代码运行得好好的,但怎么在测试环境就犯傻了。”
“许多时候,这就是因为开发环境和测试环境不一致。”
“也就是说,虽然构建的是同一份代码,但由于构建环境差异,开发环境能跑的包,在测试环境再构建后就跑不通了。“
”这是因为,构建环境的差异,让这两个包本身就不一样。”
“Cargo.lock文件就是为了解决这个问题。”
“当你运行 cargo build
时,Cargo 会查看一下 Cargo.toml
文件,看看哪个版本的依赖项最合适。”
“然后它会把这些版本写入 Cargo.lock
文件。一旦有了这个文件,Cargo 会忽略所有的更新,只参考这个文件。”
“除非你想更新。那就得用 cargo update
。”
“这个机制就保证了我们构建的包,无论过多久或是谁去构建,都是一致的,保护我们的项目不被新版本的依赖项带来的问题影响。”
赵可菲:“但我们并没有运行cargo build
命令呀。”
贾克强:“哈哈!你刚才运行的cargo run
命令呀。“
”它会先执行cargo build
来编译你的项目。如果编译成功,cargo run
接着就会运行编译后的二进制文件。”
贾克强话音未落,席双嘉已经把Cargo.lock文件提交到版本库了。
1.6.1 定义Rust项目元数据与依赖项的Cargo.toml文件
席双嘉指着屏幕问:“这个Cargo.toml
文件,和Cargo.lock
到底有啥不一样啊?”
[package]
name = "hello_world_rust"
version = "0.1.0"
edition = "2021"
[dependencies]
贾克强:“在Rust中,Cargo.toml
和Cargo.lock
就像项目的左右手,他们在Rust项目的构建和依赖管理中非常关键。”
“Cargo.toml
就像是我们的地图,它定义了项目的基本信息、依赖和配置。”
“你看这个文件,就像是个菜单,分成两个部分。“
”[package]就像是我们的门牌号,写着项目的名称、版本、作者等。“
”[dependencies]就像是我们的购物清单,列出了项目需要的所有依赖和版本。“
“Cargo.toml
需要我们手动编辑,开发者通过它来告诉项目我们需要什么依赖和配置。”
“Cargo.lock
就像是自动更新的购物清单。它是由Cargo自动创建和管理的,用来记录项目实际使用的所有依赖和版本。“
“每当我们运行cargo build
、cargo update
等命令时,Cargo会读取Cargo.toml
,就像查看我们的购物清单,然后更新Cargo.lock
。”
“对于库(library)项目,通常我们不需要把Cargo.lock
提交到版本控制系统(比如Git),因为库的用户会根据他们自己的Cargo.toml
生成他们需要的Cargo.lock
。”
“但对于可执行程序(binary)项目,我们通常会提交Cargo.lock
,这样可以确保所有的开发者和部署环境都使用相同的依赖版本。”
“咱们的Hello world就是个可执行程序,所以别忘了把Cargo.lock
提交到Git哦。“
1.6.2 Java世界如何确保构建稳定可靠
赵可菲笑着说:“在Java的世界里,要实现类似Rust中Cargo.lock
的功能,我们得靠Maven和Gradle这两大神器了。”
“Maven就是通过pom.xml
文件来管理项目的依赖。“
”要锁定依赖版本,保证我们构建的东西能稳稳地运行,Maven通常会在<dependencyManagement>
里头指定依赖的具体版本,或者用Maven Enforcer插件之类的外部工具。“
”虽然Maven没有直接类似于Cargo.lock
的文件,但我们可以在pom.xml
中明确所有版本,并利用<dependencyManagement>
来锁定它们。”
“此外,Maven的发行版和快照机制,也能分别帮我们管理稳定构建和开发构建。”
“然后是Gradle,它通过build.gradle
文件来配置依赖。”
“和Maven一样,Gradle原来并不会自动产生锁文件,不过我们可以通过依赖约束等策略来达到类似的效果。”
“从Gradle 4.8版本开始,Gradle引入了依赖锁文件的概念,允许开发者明确锁定版本。”
“只要运行gradle dependencies --write-locks
命令,Gradle就会生成一个锁文件,这个文件会固定依赖的版本,这在功能上就像Rust的Cargo.lock
一样,保证了不同环境和时间下构建结果的一致性。”
1.6.3 C 世界如何确保构建稳定可靠
席双嘉:“在C 的世界里,我们也有类似Rust中的Cargo.lock机制,就是用Conan这个工具。”
“Conan,这可是专门为C 量身打造的包管理器哦,它能帮我们处理所有的依赖和版本控制问题,让项目构建得稳稳当当。”
“用Conan的话,它会给我们生成一个叫做conan.lock
的文件,这个玩意儿和Rust的Cargo.lock
差不多。”
“这个conan.lock
文件的作用就是把项目依赖的版本给锁定住,这样无论在哪个环境下构建,依赖都能保持一致。”
“这样一来,就能避免因为依赖版本不同,在开发、测试和生产环境中出现的那些麻烦事儿。”
“虽然CMake本身并没有内建的生成锁文件的功能,但它可以找Conan这样的包管理器作为搭子,通过Conan来管理依赖和版本,也就能间接实现锁定机制了。”
“在CMake的项目里,你可以在CMakeLists.txt
文件中包含Conan的配置,然后通过链接Conan管理的库来构建应用程序。”
(未完待续)
如果喜欢这篇文章,别忘了给文章点个赞,好鼓励我继续写哦~