常见编程语言版本管理与包管理
文章考虑当前机器的环境,记录一下各种语言的版本管理与包管理方法。
Python
主要使用 uv,但是更古早的 python -m venv .venv 的写法依然被兼容。
版本管理
在使用 uv 的项目里,项目级 Python 版本通常由 .python-version 和 pyproject.toml 共同表达。.python-version 给工具一个本地切换提示,pyproject.toml 里的 requires-python 则声明项目需要的 Python 版本范围。
常用版本管理的命令为:
1 | uv python install 3.11 |
uv python pin 3.11 会在项目目录写入 .python-version。之后在项目里执行 uv run、uv sync 时,uv 会按项目配置选择合适的 Python 解释器并维护虚拟环境。
包管理
uv 项目的依赖声明放在 pyproject.toml,完整解析结果放在 uv.lock。常用命令:
1 | uv sync |
uv sync 根据 pyproject.toml 和 uv.lock 创建或更新环境;uv add 修改依赖声明并更新锁文件;uv run 在项目环境里运行命令。.venv/ 是本地虚拟环境目录,不应该提交。
也有一些项目只使用 requirements.txt。这种方式更轻量,通常配合 pip 使用:
1 | python -m venv .venv |
它适合小项目、课程项目或临时脚本,但表达的信息比 pyproject.toml + uv.lock 少。
配置例子
以 /home/zxz/Data/git-remote/COMET 为例:
1 | .python-version |
其中 .python-version 写的是:
1 | 3.11 |
pyproject.toml 里声明项目需要的 Python 版本和直接依赖:
1 | [project] |
Node.js
当前博客仓库就是用了 Node.js。
版本管理
当前 Node.js 版本切换主要由 fnm 完成:
1 | fnm list |
如果项目里有 .node-version 或 .nvmrc,通常可以进入项目后执行:
1 | fnm use |
当前检查到的项目里没有 .node-version 或 .nvmrc,博客仓库实际上没有项目级固定 Node.js 版本;它使用的是当前 shell 已经选中的 node v24.15.0。
包管理
这个博客仓库使用 npm:
1 | npm install |
严格按锁文件恢复依赖时可以用:
1 | npm ci |
package.json 声明脚本、项目元数据和直接依赖;package-lock.json 锁定 npm 解析出来的完整依赖树;node_modules/ 是本地安装结果,不应该提交。
当前环境也能看到 pnpm 和 yarn 命令入口,但这个博客仓库里没有 pnpm-lock.yaml 或 yarn.lock,也没有 packageManager 字段。因此这里不展开 pnpm / Yarn 的项目配置。判断一个 Node.js 项目实际使用哪套包管理器,最可靠的线索通常还是锁文件和 package.json。
配置例子
博客仓库的 package.json 主要包含脚本和 Hexo 依赖:
1 | { |
这个仓库有 package-lock.json,所以它当前是 npm 锁文件路线。
C# / .NET
版本管理
常用版本检查命令:
1 | dotnet --version |
如果同一台机器装了多个 SDK,项目可以用 global.json 固定构建时使用的 SDK:
1 | dotnet new globaljson --sdk-version 8.0.125 |
如果没有 global.json,实际构建会按 .NET CLI 的 SDK 选择规则使用当前 dotnet 能解析到的 SDK。.NET 的版本管理至少要分清三件事:
| 概念 | 作用 | 当前例子 |
|---|---|---|
| SDK | 决定执行 dotnet build、dotnet restore、dotnet run 时使用哪套 CLI/MSBuild/编译工具链 |
8.0.125 |
| TargetFramework | 写在 .csproj 里,决定项目面向哪个目标框架,以及编译时能使用哪些 API |
net8.0、net6.0 |
| Runtime | 程序真正启动后使用的运行时实现 | Microsoft.NETCore.App 8.0.25 |
所以 global.json 用来选择 .NET SDK;TargetFramework 写在项目文件中,用来指定目标框架;reference assemblies / targeting pack 提供编译时可见的 API 接口,但它们本身不能被当作运行时实现加载。
例如某解决方案底下有三个 .csproj,其中 TargetFramework 既有 net8.0,也有 net6.0,这里并非指定 SDK 版本,而是规定了每个项目的目标框架。
在 Arch Linux 上,大致对应关系是:
| 需求 | 常见包 |
|---|---|
| 构建 .NET 8 项目 | dotnet-sdk-8.0 |
编译面向 net8.0、net6.0 的普通项目 |
dotnet-targeting-pack-8.0、dotnet-targeting-pack-6.0 |
| 编译 ASP.NET Core / Web 项目 | aspnet-targeting-pack-8.0、aspnet-targeting-pack-6.0 等 |
| 运行 framework-dependent 的 .NET 8 程序 | dotnet-runtime-8.0 |
| 运行 ASP.NET Core 程序 | aspnet-runtime-8.0、aspnet-runtime-6.0 等 |
NuGet 依赖会由 dotnet restore 自动恢复,但 SDK、Runtime、targeting pack 这类系统级组件不会被项目自动用 pacman 安装。遇到缺少目标框架或运行时的报错时,需要根据项目的 global.json、TargetFramework 和项目类型手动安装对应包。
从这里可以看出,.NET 提供了 SDK 选择机制,但是没有像其他语言一样提供不同版本 SDK / Runtime / targeting pack 的安装器。Windows 中,这部分工作应该是默认交给 Visual Studio 了。
包管理
.NET 包管理走 NuGet,依赖通常写在 .csproj 的 PackageReference 里。常用命令:
1 | dotnet restore |
当解决方案里有多个项目时,.sln 负责组织项目;.csproj 负责声明具体项目的目标框架、NuGet 包依赖和项目引用。
配置例子
可以参考的 .NET 项目是 /home/zxz/Data/git-remote/TboxWebdav,里面有:
1 | TboxWebdav.sln |
例如 TboxWebdav.Server.AspNetCore.csproj:
1 | <Project Sdk="Microsoft.NET.Sdk.Web"> |
这里有三类信息:
| 配置 | 作用 |
|---|---|
TargetFramework |
这个项目面向哪个 .NET 目标框架,例如 net8.0 |
PackageReference |
NuGet 包依赖 |
ProjectReference |
项目引用,例如这里就会引用 TboxWebdav.Server.csproj 构建出来的 .dll 文件 |
这个项目里没有看到 Directory.Packages.props 或 packages.lock.json,所以这里只记录它们的用途,不写具体配置:
| 文件 | 作用 |
|---|---|
Directory.Packages.props |
可以集中管理多个项目的 NuGet 包版本 |
packages.lock.json |
可以锁定 NuGet restore 结果 |
Java
版本管理
当前机器的 Java 版本管理目前是 Arch Linux 的系统级方案:通过系统包安装 JDK,再用 archlinux-java 查看或切换默认 Java 环境。
常用检查和切换命令:
1 | java -version |
当前只有 java-21-openjdk 这一套默认环境,因此并没有真实发生多 JDK 切换;如果以后系统里安装了多个 JDK,archlinux-java set 才会更有意义。
包管理
Java 项目的包管理通常由 Maven 或 Gradle 承担。Maven 的项目入口一般是 pom.xml,Gradle 的项目入口一般是 build.gradle 或 build.gradle.kts。
当前检查到的目录里没有 Java 项目配置,因此这里只保留概念,不写具体依赖配置。日后如果出现真实项目,可以按实际使用的 Maven 或 Gradle 补充。
配置例子
当前没有发现 pom.xml、build.gradle、build.gradle.kts 或 gradle.lockfile。这里只列出这些文件通常负责的事情:
| 文件/工具 | 作用 |
|---|---|
pom.xml |
Maven 项目配置和依赖声明 |
build.gradle(.kts) |
Gradle 项目配置和依赖声明 |
| Gradle Wrapper | 项目自带的 Gradle 版本入口 |
Rust
版本管理
Rust 这边的工具链比较完整:rustup 管工具链,cargo 管项目和依赖。
常用检查和切换命令:
1 | rustup show |
rustup default 设置全局默认工具链;rustup override set 可以在某个目录下设置局部工具链。当前参考项目里没有 rust-toolchain.toml,所以更接近“默认 stable 工具链 + 项目内 rust-version 提示”的用法。
包管理
Rust 项目的包管理由 Cargo 负责。常用命令:
1 | cargo build |
Cargo.toml 声明项目元数据、workspace 和直接依赖;Cargo.lock 锁定完整依赖树。应用项目通常应该提交 Cargo.lock,target/ 是构建产物,不应该提交。
配置例子
项目 /home/zxz/Data/git-remote/security-scan/scan 里有:
1 | Cargo.toml |
主 Cargo.toml:
1 | [package] |
migration/Cargo.toml 里还写了最低 Rust 版本:
1 | [package] |
这里的分工是:
| 文件/字段 | 作用 |
|---|---|
Cargo.toml |
项目元数据、workspace、直接依赖 |
edition |
Rust 语言 edition,例如 2024 |
rust-version |
声明 crate 需要的最低 Rust 版本 |
Cargo.lock |
锁定完整依赖树 |
rustup |
管理本地 Rust 工具链 |



