mirror of
https://github.com/ryan4yin/nixos-and-flakes-book.git
synced 2025-06-22 13:01:25 +02:00
feat: nix shell, nix develop & pkgs.runCommand
This commit is contained in:
parent
fb2fe1224a
commit
c098dfa2b0
@ -265,7 +265,7 @@ function themeConfigEnglish() {
|
|||||||
text: "Dev Environments on NixOS",
|
text: "Dev Environments on NixOS",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
text: "nix develop & pkgs.mkShell",
|
text: "nix shell, nix develop & pkgs.runCommand",
|
||||||
link: "/development/intro.md",
|
link: "/development/intro.md",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -455,7 +455,7 @@ function themeConfigChinese() {
|
|||||||
text: "在 NixOS 上进行开发工作",
|
text: "在 NixOS 上进行开发工作",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
text: "nix develop 与 pkgs.mkShell",
|
text: "nix shell, nix develop & pkgs.runCommand",
|
||||||
link: "/zh/development/intro.md",
|
link: "/zh/development/intro.md",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -8,8 +8,42 @@ You should NOT install the development environment of each language in the globa
|
|||||||
|
|
||||||
In the following sections, we'll introduce how the development environment works in NixOS.
|
In the following sections, we'll introduce how the development environment works in NixOS.
|
||||||
|
|
||||||
|
## Createing a Custom Shell Environment with `nix shell`
|
||||||
|
|
||||||
|
The simplest way to create a development environment is to use `nix shell`. `nix shell` will create a shell environment with the specified Nix package installed.
|
||||||
|
|
||||||
|
Here's an example:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# hello is not available
|
||||||
|
› hello
|
||||||
|
hello: command not found
|
||||||
|
|
||||||
|
# Enter an environment with the 'hello' and `cowsay` package
|
||||||
|
› nix shell nixpkgs#hello nixpkgs#cowsay
|
||||||
|
|
||||||
|
# hello is now available
|
||||||
|
› hello
|
||||||
|
Hello, world!
|
||||||
|
|
||||||
|
# ponysay is also available
|
||||||
|
› cowsay "Hello, world!"
|
||||||
|
_______
|
||||||
|
< hello >
|
||||||
|
-------
|
||||||
|
\ ^__^
|
||||||
|
\ (oo)\_______
|
||||||
|
(__)\ )\/\
|
||||||
|
||----w |
|
||||||
|
|| ||
|
||||||
|
```
|
||||||
|
|
||||||
|
`nix shell` is very useful when you just want to try out some packages or quickly create a clean environment.
|
||||||
|
|
||||||
## Creating a Development Environment
|
## Creating a Development Environment
|
||||||
|
|
||||||
|
`nix shell` is simple and easy to use, but it's not very flexible, for a more complex development environment, we need to use `pkgs.mkShell` and `nix develop`.
|
||||||
|
|
||||||
We can create a development environment using `pkgs.mkShell { ... }` and open an interactive Bash shell of this development environment using `nix develop`.
|
We can create a development environment using `pkgs.mkShell { ... }` and open an interactive Bash shell of this development environment using `nix develop`.
|
||||||
|
|
||||||
To see how `pkgs.mkShell` works, let's take a look at [its source code](https://github.com/NixOS/nixpkgs/blob/nixos-23.05/pkgs/build-support/mkshell/default.nix).
|
To see how `pkgs.mkShell` works, let's take a look at [its source code](https://github.com/NixOS/nixpkgs/blob/nixos-23.05/pkgs/build-support/mkshell/default.nix).
|
||||||
@ -112,7 +146,7 @@ Here is a `flake.nix` that defines a development environment with Node.js 18 ins
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Create an empty folder, save the above configuration as `flake.nix`, and then execute `nix develop` (or more precisely, you can use `nix develop .#default`), you will find that you have entered a nodejs 18 development environment, you can use `node` `npm` `pnpm` `yarn` and other commands. And when you just entered, `shellHook` was also executed, outputting the current version of nodejs.
|
Create an empty folder, save the above configuration as `flake.nix`, and then execute `nix develop` (or more precisely, you can use `nix develop .#default`), the current version of nodejs will be outputed, and now you can use `node` `pnpm` `yarn` seamlessly.
|
||||||
|
|
||||||
|
|
||||||
## Using zsh/fish/... instead of bash
|
## Using zsh/fish/... instead of bash
|
||||||
@ -168,6 +202,66 @@ Here is an example:
|
|||||||
With the above configuration, `nix develop` will enter the REPL environment of nushell.
|
With the above configuration, `nix develop` will enter the REPL environment of nushell.
|
||||||
|
|
||||||
|
|
||||||
|
## Creating a Development Environment with `pkgs.runCommand`
|
||||||
|
|
||||||
|
The derivation created by `pkgs.mkShell` cannot be used directly, but must be accessed via `nix develop`.
|
||||||
|
|
||||||
|
It is actually possible to create a shell wrapper containing the required packages via `pkgs.stdenv.mkDerivation`, which can then be run directly into the environment by executing the wrapper.
|
||||||
|
|
||||||
|
Using `mkDerivation` directly is a bit cumbersome, and Nixpkgs provides some simpler functions to help us create such wrappers, such as `pkgs.runCommand`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
description = "A Nix-flake-based Node.js development environment";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self , nixpkgs ,... }: let
|
||||||
|
# system should match the system you are running on
|
||||||
|
# system = "x86_64-linux";
|
||||||
|
system = "x86_64-darwin";
|
||||||
|
in {
|
||||||
|
packages."${system}".dev = let
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
overlays = [
|
||||||
|
(self: super: rec {
|
||||||
|
nodejs = super.nodejs_20;
|
||||||
|
pnpm = super.nodePackages.pnpm;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
packages = with pkgs; [
|
||||||
|
nodejs
|
||||||
|
pnpm
|
||||||
|
nushell
|
||||||
|
];
|
||||||
|
in pkgs.runCommand "dev-shell" {
|
||||||
|
# Dependencies that should exist in the runtime environment
|
||||||
|
buildInputs = packages;
|
||||||
|
# Dependencies that should only exist in the build environment
|
||||||
|
nativeBuildInputs = [ pkgs.makeWrapper ];
|
||||||
|
} ''
|
||||||
|
mkdir -p $out/bin/
|
||||||
|
ln -s ${pkgs.nushell}/bin/nu $out/bin/dev-shell
|
||||||
|
wrapProgram $out/bin/dev-shell --prefix PATH : ${pkgs.lib.makeBinPath packages}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then execute `nix run .#dev`, you will enter a nushell session, where you can use the `node` `pnpm` command normally, and the node version is 20.
|
||||||
|
|
||||||
|
Related source code:
|
||||||
|
|
||||||
|
- [pkgs/build-support/trivial-builders/default.nix - runCommand](https://github.com/NixOS/nixpkgs/blob/nixos-23.11/pkgs/build-support/trivial-builders/default.nix#L21-L49)
|
||||||
|
- [pkgs/build-support/build-support/setup-hooks/make-wrapper.sh](https://github.com/NixOS/nixpkgs/blob/nixos-23.11/pkgs/build-support/setup-hooks/make-wrapper.sh)
|
||||||
|
|
||||||
|
|
||||||
## Enter the build environment of any Nix package
|
## Enter the build environment of any Nix package
|
||||||
|
|
||||||
Now let's take a look at `nix develop`, first read the help document output by `nix develop --help`:
|
Now let's take a look at `nix develop`, first read the help document output by `nix develop --help`:
|
||||||
|
@ -13,12 +13,23 @@ The `nix shell` command allows you to enter an environment with the specified Ni
|
|||||||
› hello
|
› hello
|
||||||
hello: command not found
|
hello: command not found
|
||||||
|
|
||||||
# Enter an environment with the 'hello' package
|
# Enter an environment with the 'hello' and `cowsay` package
|
||||||
› nix shell nixpkgs#hello
|
› nix shell nixpkgs#hello nixpkgs#cowsay
|
||||||
|
|
||||||
# hello is now available
|
# hello is now available
|
||||||
› hello
|
› hello
|
||||||
Hello, world!
|
Hello, world!
|
||||||
|
|
||||||
|
# ponysay is also available
|
||||||
|
› cowsay "Hello, world!"
|
||||||
|
_______
|
||||||
|
< hello >
|
||||||
|
-------
|
||||||
|
\ ^__^
|
||||||
|
\ (oo)\_______
|
||||||
|
(__)\ )\/\
|
||||||
|
||----w |
|
||||||
|
|| ||
|
||||||
```
|
```
|
||||||
|
|
||||||
## `nix run`
|
## `nix run`
|
||||||
|
@ -10,8 +10,44 @@
|
|||||||
|
|
||||||
在本章中我们先学习一下 Nix Flakes 开发环境的实现原理,后面的章节再按使用场景介绍一些更具体的内容。
|
在本章中我们先学习一下 Nix Flakes 开发环境的实现原理,后面的章节再按使用场景介绍一些更具体的内容。
|
||||||
|
|
||||||
|
|
||||||
|
## 通过 `nix shell` 创建开发环境
|
||||||
|
|
||||||
|
在 NixOS 上,最简单的创建开发环境的方法是使用 `nix shell`,它会创建一个含有指定 Nix 包的 shell 环境。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# hello 不存在
|
||||||
|
› hello
|
||||||
|
hello: command not found
|
||||||
|
|
||||||
|
# 进入到一个含有 hello 与 cowsay 的 shell 环境
|
||||||
|
# 可以指定多个包,用空格分隔
|
||||||
|
› nix shell nixpkgs#hello nixpkgs#cowsay
|
||||||
|
|
||||||
|
# hello 可以用了
|
||||||
|
› hello
|
||||||
|
Hello, world!
|
||||||
|
|
||||||
|
# cowsay 也可以用了
|
||||||
|
› cowsay "Hello, world!"
|
||||||
|
_______
|
||||||
|
< hello >
|
||||||
|
-------
|
||||||
|
\ ^__^
|
||||||
|
\ (oo)\_______
|
||||||
|
(__)\ )\/\
|
||||||
|
||----w |
|
||||||
|
|| ||
|
||||||
|
```
|
||||||
|
|
||||||
|
`nix shell` 非常适合用于临时试用一些软件包或者快速创建一个干净的环境。
|
||||||
|
|
||||||
## 创建与使用开发环境
|
## 创建与使用开发环境
|
||||||
|
|
||||||
|
`nix shell` 用起来非常简单,但它并不够灵活,对于更复杂的开发环境管理,我们需要使用 `pkgs.mkShell` 与 `nix develop`。
|
||||||
|
|
||||||
在 Nix Flakes 中,我们可以通过 `pkgs.mkShell { ... }` 来定义一个项目环境,通过 `nix develop` 来打开一个该开发环境的交互式 Bash Shell.
|
在 Nix Flakes 中,我们可以通过 `pkgs.mkShell { ... }` 来定义一个项目环境,通过 `nix develop` 来打开一个该开发环境的交互式 Bash Shell.
|
||||||
|
|
||||||
为了更好的使用上述两个功能,我们先来看看它们的原理。
|
为了更好的使用上述两个功能,我们先来看看它们的原理。
|
||||||
@ -116,8 +152,7 @@ stdenv.mkDerivation ({
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
建个空文件夹,将上面的配置保存为 `flake.nix`,然后执行 `nix develop`(或者更精确点,可以用 `nix develop .#default`),你会发现你已经进入了一个 nodejs 18 的开发环境,可以使用 `node` `npm` `pnpm` `yarn` 等命令了。而且刚进入时,`shellHook` 也被执行了,输出了当前 nodejs 的版本。
|
建个空文件夹,将上面的配置保存为 `flake.nix`,然后执行 `nix develop`(或者更精确点,可以用 `nix develop .#default`),首先会打印出当前 nodejs 的版本,之后 `node` `pnpm` `yarn` 等命令就都能正常使用了。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 在开发环境中使用 zsh/fish 等其他 shell
|
## 在开发环境中使用 zsh/fish 等其他 shell
|
||||||
@ -171,6 +206,66 @@ stdenv.mkDerivation ({
|
|||||||
|
|
||||||
使用上面的 `flake.nix` 配置,`nix develop` 将进入一个 nodejs 18 的开发环境,同时使用 `nushell` 作为交互式 shell.
|
使用上面的 `flake.nix` 配置,`nix develop` 将进入一个 nodejs 18 的开发环境,同时使用 `nushell` 作为交互式 shell.
|
||||||
|
|
||||||
|
## 通过 `pkgs.runCommand` 创建开发环境
|
||||||
|
|
||||||
|
`pkgs.mkShell` 创建的 derivation 不能直接使用,必须通过 `nix develop` 进入到该环境中。
|
||||||
|
|
||||||
|
实际上我们也可以通过 `pkgs.stdenv.mkDerivation` 来创建一个包含所需软件包的 shell wrapper, 这样就能直接通过执行运行该 wrapper 来进入到该环境中。
|
||||||
|
|
||||||
|
直接使用 `mkDerivation` 略显繁琐,Nixpkgs 提供了一些更简单的函数来帮助我们创建这类 wrapper,比如 `pkgs.runCommand`.
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
description = "A Nix-flake-based Node.js development environment";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self , nixpkgs ,... }: let
|
||||||
|
# system should match the system you are running on
|
||||||
|
# system = "x86_64-linux";
|
||||||
|
system = "x86_64-darwin";
|
||||||
|
in {
|
||||||
|
packages."${system}".dev = let
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
overlays = [
|
||||||
|
(self: super: rec {
|
||||||
|
nodejs = super.nodejs_20;
|
||||||
|
pnpm = super.nodePackages.pnpm;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
packages = with pkgs; [
|
||||||
|
nodejs
|
||||||
|
pnpm
|
||||||
|
nushell
|
||||||
|
];
|
||||||
|
in pkgs.runCommand "dev-shell" {
|
||||||
|
# Dependencies that should exist in the runtime environment
|
||||||
|
buildInputs = packages;
|
||||||
|
# Dependencies that should only exist in the build environment
|
||||||
|
nativeBuildInputs = [ pkgs.makeWrapper ];
|
||||||
|
} ''
|
||||||
|
mkdir -p $out/bin/
|
||||||
|
ln -s ${pkgs.nushell}/bin/nu $out/bin/dev-shell
|
||||||
|
wrapProgram $out/bin/dev-shell --prefix PATH : ${pkgs.lib.makeBinPath packages}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
然后执行 `nix run .#dev`,就能进入一个 nushell session,可以在其中正常使用 `node` `pnpm` 命令,且 node 版本为 20.
|
||||||
|
|
||||||
|
相关源代码:
|
||||||
|
|
||||||
|
- [pkgs/build-support/trivial-builders/default.nix - runCommand](https://github.com/NixOS/nixpkgs/blob/nixos-23.11/pkgs/build-support/trivial-builders/default.nix#L21-L49)
|
||||||
|
- [pkgs/build-support/build-support/setup-hooks/make-wrapper.sh](https://github.com/NixOS/nixpkgs/blob/nixos-23.11/pkgs/build-support/setup-hooks/make-wrapper.sh)
|
||||||
|
|
||||||
|
|
||||||
## 进入任何 Nix 包的构建环境
|
## 进入任何 Nix 包的构建环境
|
||||||
|
|
||||||
现在再来看看 `nix develop`,先读下 `nix develop --help` 输出的帮助文档:
|
现在再来看看 `nix develop`,先读下 `nix develop --help` 输出的帮助文档:
|
||||||
@ -346,6 +441,6 @@ nix build "nixpkgs#ponysay"
|
|||||||
- [pkgs.mkShell - nixpkgs manual](https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-mkShell)
|
- [pkgs.mkShell - nixpkgs manual](https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-mkShell)
|
||||||
- [A minimal nix-shell](https://fzakaria.com/2021/08/02/a-minimal-nix-shell.html)
|
- [A minimal nix-shell](https://fzakaria.com/2021/08/02/a-minimal-nix-shell.html)
|
||||||
- [One too many shell, Clearing up with nix' shells nix shell and nix-shell - Yannik Sander](https://blog.ysndr.de/posts/guides/2021-12-01-nix-shells/)
|
- [One too many shell, Clearing up with nix' shells nix shell and nix-shell - Yannik Sander](https://blog.ysndr.de/posts/guides/2021-12-01-nix-shells/)
|
||||||
|
- [Shell Scripts - NixOS Wiki](https://nixos.wiki/wiki/Shell_Scripts)
|
||||||
|
|
||||||
[New Nix Commands]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix.html
|
[New Nix Commands]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix.html
|
||||||
|
@ -12,14 +12,28 @@
|
|||||||
› hello
|
› hello
|
||||||
hello: command not found
|
hello: command not found
|
||||||
|
|
||||||
# 进入到一个含有 hello 的 shell 环境
|
# 进入到一个含有 hello 与 cowsay 的 shell 环境
|
||||||
› nix shell nixpkgs#hello
|
# 可以指定多个包,用空格分隔
|
||||||
|
› nix shell nixpkgs#hello nixpkgs#cowsay
|
||||||
|
|
||||||
# hello 可以用了
|
# hello 可以用了
|
||||||
› hello
|
› hello
|
||||||
Hello, world!
|
Hello, world!
|
||||||
|
|
||||||
|
# cowsay 也可以用了
|
||||||
|
› cowsay "Hello, world!"
|
||||||
|
_______
|
||||||
|
< hello >
|
||||||
|
-------
|
||||||
|
\ ^__^
|
||||||
|
\ (oo)\_______
|
||||||
|
(__)\ )\/\
|
||||||
|
||----w |
|
||||||
|
|| ||
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`nix shell` 非常适合用于临时试用一些软件包或者快速创建一个干净的环境。
|
||||||
|
|
||||||
## `nix run`
|
## `nix run`
|
||||||
|
|
||||||
`nix run` 则是创建一个含有指定 Nix 包的环境,并在该环境中直接运行该 Nix 包(临时运行该程序,不将它安装到系统环境中):
|
`nix run` 则是创建一个含有指定 Nix 包的环境,并在该环境中直接运行该 Nix 包(临时运行该程序,不将它安装到系统环境中):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user