Nix
在NixOS和macOS之间搭建统一的个人全局开发环境
相关信息
本文由AI翻译,可能存在翻译不准确、不自然的情况。
大约六个月前,在室友的推荐下,我将 PC 切换到了 NixOS。当时正好是我把 Ubuntu 桌面环境彻底搞砸了,无法恢复的时机。
NixOS 是一个基于 Nix 包管理器的 Linux 发行版,它支持声明式配置和可重现构建。
我很快发现 NixOS 在管理包和配置方面非常方便且强大,因此我决定让它成为我 PC 上唯一的操作系统。随着我越来越熟悉 Nix 的功能,我意识到也可以在运行 macOS 的 MacBook 上安装 Nix。这样一来,我就可以在 NixOS 桌面和 macOS 笔记本之间实现几乎无缝的开发体验,通过:
- 使用 Nix 在两个系统上设置相同的全局开发环境,例如特定的 Python 解释器或 Java 编译器版本。
- 在两个系统上定义共享的 shell 环境(如 zsh),从而轻松重用 shell 脚本、变量和别名。
我想要实现的目标
我需要一个解决方案,能够:
- 确保跨平台包版本完全相同。
- 将整个开发栈以代码形式声明,便于复制。
- 支持高级并行计算设置,包括 OpenCL、OpenMP 和 MPI。
- 允许针对特定平台的配置调整。
我的设置架构
为了实现这种整合,我以模块化方式构建了 Nix 配置。以下是目录结构的概述:
nix/
├── home-manager/
│ ├── shared/
│ │ └── programming.nix # 跨平台包
│ ├── linux/
│ │ └── home.nix # Linux 特定配置
│ └── darwin/
│ └── home.nix # macOS 特定配置
├── nixos/
│ └── configuration.nix # NixOS 系统配置
├── nix-darwin/
│ └── configuration.nix # macOS 系统配置
└── flake.nix # 主配置入口点
这种结构将共享元素集中起来,同时允许操作系统特定的调整。
共享编程环境
我的设置核心是 programming.nix
文件,它定义了跨平台一致的开发工具。这确保了从编译器到库的一切版本都相同。
# 跨平台编程环境包
{ config, pkgs, ... }:
{
home.packages = with pkgs; [
# 开发工具
git
wget
curl
# 编程语言和运行时
nodejs
typescript
(python3.withPackages (ps: with ps; [
numpy
pandas
scipy
matplotlib
scikit-learn
jupyterlab
]))
# Java 开发
jdk21
maven
gradle
# C/C++ 开发
gcc
cmake
gdb
lldb
pkg-config
# 并行编程栈
mpi
llvmPackages.openmp
opencl-headers
opencl-clhpp
ocl-icd
clinfo
# 文档和文本处理
pandoc
typst
# 开发环境
docker
];
home.sessionVariables = {
JAVA_HOME = "${pkgs.jdk21}";
CC = "${pkgs.gcc}/bin/gcc";
CXX = "${pkgs.gcc}/bin/g++";
};
}
此配置引入了各种编程任务所需的基本工具,包括用于数据科学和机器学习的强大 Python 设置、用于后端开发的 Java 工具,以及并行计算组件。
在 macOS 上整合 Homebrew 与 Nix
虽然 Nix 处理了我大部分命令行工具,但我依赖 Homebrew 来管理 GUI 应用程序和某些 Nix 中不可用的 macOS 特定包。为了保持一切声明式,我使用 nix-darwin 中的 homebrew
模块将 Homebrew 直接整合到 Nix 配置中。
# macOS 的 Homebrew 配置
{ config, pkgs, ... }:
{
# Homebrew 声明式配置
homebrew = {
enable = true;
# 应用安装偏好
onActivation = {
autoUpdate = true; # 更新 Homebrew 本身
upgrade = true; # 将所有包升级到最新版本
cleanup = "zap"; # 卸载未在配置中列出的包
# 额外的更新选项(可选)
extraFlags = [
"--verbose" # 在更新期间显示详细输出
];
};
# 全局 Homebrew 设置
global = {
brewfile = true; # 使用 Brewfile 进行管理
lockfiles = false; # 不创建锁文件
};
# 来自 brew 列表的 GUI 应用程序
casks = [
# 云存储和同步
"baidunetdisk"
"google-drive"
"nutstore"
# 学习和教育
"eudic"
"pdf-expert"
# 浏览器和网络客户端
"firefox"
"google-chrome"
"bilibili"
# 开发工具
"github"
"jetbrains-toolbox"
"visual-studio-code"
"cursor"
"kate"
# macUI
#"sketchybar" see home manager
"font-hack-nerd-font"
# 设计和生产力
"canva"
"figma"
"obsidian"
"typora"
# 通信
"qq"
"wechat"
"whatsapp"
"microsoft-teams"
"telegram-desktop"
# AI 和生产力
"chatgpt"
"cherry-studio"
# 网络和系统工具
"clash-verge-rev"
#"stats"
# 办公和生产力
"zoom"
"slack"
"microsoft-auto-update"
# 游戏和娱乐
"steam"
# 学术和研究
"zotero"
# 统计计算和分析
"r"
"rstudio"
# 文档准备
"mactex" # 完整的 MacTeX 发行版,包括 TeXLive
];
# Formulae(命令行工具) - 目前保持为空,因为大多数由 nix 处理
brews = [
# AI 和 ML 工具现在由 nixpkgs 处理
];
# Mac App Store 应用(如果有)
masApps = {
# 示例: "Xcode" = 497799835;
};
};
}
这种方法让我的 macOS 设置保持干净且可重现。Homebrew 处理图形应用,而 Nix 管理其余部分,一切都以代码形式定义。
益处与挑战
这种整合设置彻底改变了我的工作流程。在桌面和笔记本之间切换感觉毫不费力,一致的环境减少了设置时间和调试麻烦。
话虽如此,也存在挑战:有些包需要平台特定的调整,初始设置对 Nix 新手来说可能很陡峭。但一旦配置好,益处远远超过努力。
如果你正在探索类似的跨平台开发设置,我推荐从 Nix flakes 开始,以获得更好的模块化。欢迎根据你的需求进行调整!