{ stdenv, dpkg, glibc, gcc-unwrapped, autoPatchelfHook }:
let
# Please keep the version x.y.0.z and do not update to x.y.76.z because the
# source of the latter disappears much faster.
version = "12.0.0";
src = ./WolframScript_12.0.0_LINUX64_amd64.deb;
in stdenv.mkDerivation {
name = "wolframscript-${version}";
system = "x86_64-linux";
inherit src;
# Required for compilation
nativeBuildInputs = [
autoPatchelfHook # Automatically setup the loader, and do the magic
dpkg
];
# Required at running time
buildInputs = [
glibc
gcc-unwrapped
];
unpackPhase = "true";
# Extract and copy executable in $out/bin
installPhase = ''
mkdir -p $out
dpkg -x $src $out
cp -av $out/opt/Wolfram/WolframScript/* $out
rm -rf $out/opt
'';
meta = with stdenv.lib; {
description = "Wolframscript";
homepage = https://www.wolfram.com/wolframscript/;
license = licenses.mit;
maintainers = with stdenv.lib.maintainers; [ ];
platforms = [ "x86_64-linux" ];
};
}
If you do not want to spawn a sandbox as we did for steam-run (in sandboxes it's impossible to run setuid apps, sandboxes can't be nested, poor integration with the system packages included direnv), you can recreate the missing loader system-wide by putting in your configuration.nix:
programs.nix-ld.enable = true;
You can see that the file is now present:
$ ls /lib64/
ld-linux-x86-64.so.2
However it is still impossible to run binaries as the new ld-linux-x86-64.so.2 file only redirects to the loader in NIX_LD (this way multiple programs can use different loaders while being on the same system):
$ ./blender
cannot execute ./blender: NIX_LD or NIX_LD_x86_64-linux is not set
To locally create this environment variable, you can do something like:
Note that (contrary to steam-run) nix-ld does not come with any library by default but you can add your own or use tools to do that automatically, see below. You can also get inspired by the list of libraries that steam-run packs here: https://github.com/NixOS/nixpkgs/blob/master/pkgs/games/steam/fhsenv.nix Here is for example the file I'm using for now, it is enough to run blender:
# Automatically creates a loader in /lib/* to avoid patching stuff
programs.nix-ld.enable = true;
environment.variables = {
NIX_LD_LIBRARY_PATH = with pkgs; lib.makeLibraryPath [
stdenv.cc.cc
openssl
xorg.libXcomposite
xorg.libXtst
xorg.libXrandr
xorg.libXext
xorg.libX11
xorg.libXfixes
libGL
libva
pipewire.lib
xorg.libxcb
xorg.libXdamage
xorg.libxshmfence
xorg.libXxf86vm
libelf
# Required
glib
gtk2
bzip2
# Without these it silently fails
xorg.libXinerama
xorg.libXcursor
xorg.libXrender
xorg.libXScrnSaver
xorg.libXi
xorg.libSM
xorg.libICE
gnome2.GConf
nspr
nss
cups
libcap
SDL2
libusb1
dbus-glib
ffmpeg
# Only libraries are needed from those two
libudev0-shim
# Verified games requirements
xorg.libXt
xorg.libXmu
libogg
libvorbis
SDL
SDL2_image
glew110
libidn
tbb
# Other things from runtime
flac
freeglut
libjpeg
libpng
libpng12
libsamplerate
libmikmod
libtheora
libtiff
pixman
speex
SDL_image
SDL_ttf
SDL_mixer
SDL2_ttf
SDL2_mixer
libappindicator-gtk2
libdbusmenu-gtk2
libindicator-gtk2
libcaca
libcanberra
libgcrypt
libvpx
librsvg
xorg.libXft
libvdpau
gnome2.pango
cairo
atk
gdk-pixbuf
fontconfig
freetype
dbus
alsaLib
expat
];
NIX_LD = lib.fileContents "${pkgs.stdenv.cc}/nix-support/dynamic-linker";
};
You can also find the name of the libraries, see above nix-index. You can also use nix-alien-ld or nix-autobahn to automatically find and load the libraries for you. Note that if you don't have the right libraries you will get an error like
$ ./blender
./blender: error while loading shared libraries: libX11.so.6: cannot open shared object file: No such file or directory
You can see at once all the libraries that are not yet available using:
$ LD_LIBRARY_PATH=$NIX_LD_LIBRARY_PATH ldd turtl
libpangocairo-1.0.so.0 => /nix/store/n9h110ffps25rdkkim5k802p3p5w476m-pango-1.50.6/lib/libpangocairo-1.0.so.0 (0x00007f02feb83000)
libatk-1.0.so.0 => not found
…
Method 9) nix-alien
nix-alien automatically builds a FHS with the appropriates libraries. If you have flake enabled (otherwise just add replace nix run with nix --extra-experimental-features "nix-command flakes" run) you can simply run it this way (nix-alien is not yet packaged in 2022)
nix run github:thiagokokada/nix-alien -- yourprogram
It will then automatically find the library using nix-index, asking you some questions when it is not sure (this is cached).
Note that programs that rely on openGl need to use nixGl to run (this certainly apply to other methods here):
nix run --impure github:guibou/nixGL --override-input nixpkgs nixpkgs/nixos-21.11 -- nix run github:thiagokokada/nix-alien -- blender
Note that you may need to change the version of nixos-21.11 to ensure that the version of openGl matches your program.
Note that you can also see the automatically generated file (the path is given the first time the program is run):
$ cat /home/leo/.cache/nix-alien/87a5d119-f810-5222-9b47-4809257c60ec/fhs-env/default.nix
{ pkgs ? import <nixpkgs> { } }:
let
inherit (pkgs) buildFHSUserEnv;
in
buildFHSUserEnv {
name = "blender-fhs";
targetPkgs = p: with p; [
xorg.libX11.out
xorg.libXfixes.out
xorg.libXi.out
xorg.libXrender.out
xorg.libXxf86vm.out
xorg_sys_opengl.out
];
runScript = "/tmp/blender-3.2.2-linux-x64/blender";
}
See also the other version working with nix-ld and nix-autobahn.
Method 9) Using containers/Docker (heavier)
TODO
Note that the project distrobox allows you to simply create new containers tightly integrated with the host installing any distribution you want.
精简版
又快又脏:确保
steam-run
已安装(奇怪的名字,它与蒸汽无关),例如nix-shell -p steam-run
,然后:这是一个更长更详细的解释,以及各种方法,通常不那么脏。自创建此答案以来,已经开发了 steam-run 的其他替代方案,请参见例如 nix-ld (基本上在 中重新创建缺少的加载程序
/lib
)和nix-alien / nix-autobahn,它们也会自动尝试添加缺少的库。最后,您可以使用distrobox,它在与主机紧密集成的 docker/podman 容器中为您提供任何分发。长版
这里有几种方法(手动方法主要用于教育目的,因为大多数情况下编写适当的推导更好)。我根本不是专家,我做这个列表也是为了学习 nix,所以如果你有更好的方法,请告诉我!
所以主要问题是可执行文件首先调用一个加载器,然后需要一些库才能工作,而 nixos 将加载器和库都放在
/nix/store/
.这个列表给出了我迄今为止找到的所有方法。基本上有三个“组”:
我建议使用方法 4
autoPatchelfHook
进行真实、正确的设置,如果您没有时间并且只想在一行中运行二进制文件,您可能会对基于steam-run
(方法 7 )。方法1)脏手动方法,无补丁
您需要首先找到加载程序,例如
file
:装载机在这里
/lib64/ld-linux-x86-64.so.2
。要查找 nixos 的加载程序,您可以执行以下操作:您还需要找到程序所需的库,例如使用
ldd
orLD_DEBUG=libs
:在这里,您会看到除了
libstdc++.so.6
. 所以让我们找到他们!找到它们的第一个快速而肮脏的方法是检查它们是否已经存在于您的系统中:如果该库尚未安装,您肯定会更喜欢使用更复杂的
nix-index
程序在更大的数据库中搜索这些文件(感谢 hydra)。为此,首先安装nix-index
并生成数据库(这只是第一次需要,但可能需要几分钟才能运行):(您也可以使用
nix-index-update
from nix-alien自动从nix-index-database下载缓存)然后,要搜索一个库,您可以执行以下操作(注意--top-level
删除一些条目):然后,您可以为这个快速而肮脏的示例安装这些库(稍后我们将看到更好的解决方案)。
好的。现在,我们只需要运行程序,并将
LD_LIBRARY_PATH
配置指向该文件(另请参见makeLibraryPath
在派生中生成该字符串),并调用我们在第一步确定的对该文件的加载程序:(确保
./
在脚本名称之前使用,并且只保留库的目录。如果您有多个库,只需使用冒号连接路径)方法2)脏手动方法,有补丁
安装后(with
nixenv -i
or in yourconfiguration.nix
)patchelf
,您也可以直接修改可执行文件以打包好的加载器和库。要更改加载程序,只需运行:并检查:
并更改可执行文件中硬编码的库的路径,首先检查当前的 rpath 是什么(对我来说是空的):
并将它们附加到您之前确定的库路径中,最终用冒号分隔:
方法 3) 在 nix 派生中打补丁
我们可以在受skypeforlinux启发的 nix 派生中复制或多或少相同的东西
此示例还提供了一种替代方法,您可以使用:
(一旦你理解了“手动”方法,这应该很清楚),或者
第二种方法有点微妙,但如果你运行:
您将看到该文件
$NIX_CC/nix-support/dynamic-linker
包含 loader 的路径ld-linux-x86-64.so.2
。放进去
derivation.nix
,这是并
default.nix
说:编译并运行
方法4)使用autoPatchElf:更简单
所有以前的方法都需要一些工作(您需要找到可执行文件,修补它们......)。NixOs 为我们做了一个特殊的“钩子”
autoPatchelfHook
,它会自动为您修补所有内容!您只需要在 中指定它(native)BuildInputs
,然后 nix 就可以了。方法5)使用FHS模拟经典的linux shell,手动执行文件
某些软件可能很难以这种方式打包,因为它们可能严重依赖FHS文件树结构,或者可能会检查二进制文件是否未更改。然后,您还可以使用buildFHSUserEnv为您的应用程序提供 FHS 文件结构(轻量级,使用命名空间)。请注意,此方法比基于补丁的方法更重,并且会增加大量启动时间,因此请尽可能避免使用
您可以只生成一个 shell,然后手动提取存档并执行文件,或者直接为 FHS 打包您的程序。让我们先看看如何获得一个shell。将以下内容放入文件(例如
fhs-env.nix
)中:并运行:
然后,您将在外观更标准的 linux 中获得 bash,并且可以运行命令来运行可执行文件,例如:
如果您需要更多库/程序作为依赖项,只需将它们添加到
multiPkgs
(对于所有受支持的拱门)或targetPkgs
(仅对于当前拱门)。奖励:您还可以使用单行命令启动 fhs shell,而无需创建特定文件:
方法6)使用FHS模拟经典的linux shell,将里面的文件打包
来源:https ://reflexivereflection.com/posts/2015-02-28-deb-installation-nixos.html
方法 7) 蒸汽运行
您可以运行许多软件,
buildFHSUserEnv
但您需要手动指定所有必需的库。如果您想要一个快速的解决方案并且您没有时间精确检查所需的库是什么,您可能想尝试steam-run
(尽管名称,它没有直接与 steam 链接,并且只是打包了很多库),即就像buildFHSUserEnv
预装了很多通用库一样(其中一些可能是非免费的,比如steamrt
包含一些 nvidia 代码,谢谢辛普森!)。要使用它,只需安装steam-run
,然后:或者如果你想要一个完整的外壳:
请注意,如果您想使用 安装它,并且如果您想使用/运行/安装它,您可能需要添加
nixpkgs.config.allowUnfree = true;
(或将此特定包列入白名单),您需要放入.nixos-rebuild
nix-shell
nix-env
{ allowUnfree = true; }
~/.config/nixpkgs/config.nix
将包或库“覆盖”到 nix-shell 并不容易,但如果你想为你的脚本创建一个包装器,你可以手动创建一个包装器脚本:
或直接将其写在 nixos 派生中:
或者如果你从 .deb 开始(我在这里使用
makeWrapper
):(如果平时写太累
default.nix
,可以直接跑nix-build -E "with import <nixpkgs> {}; callPackage ./derivation.nix {}"
)方法 8) 使用
nix-ld
If you do not want to spawn a sandbox as we did for steam-run (in sandboxes it's impossible to run setuid apps, sandboxes can't be nested, poor integration with the system packages included direnv), you can recreate the missing loader system-wide by putting in your
configuration.nix
:You can see that the file is now present:
However it is still impossible to run binaries as the new
ld-linux-x86-64.so.2
file only redirects to the loader inNIX_LD
(this way multiple programs can use different loaders while being on the same system):To locally create this environment variable, you can do something like:
or system-wide using:
Note that you need to restart your X11 session everytime you change this file or do:
Note that (contrary to
steam-run
)nix-ld
does not come with any library by default but you can add your own or use tools to do that automatically, see below. You can also get inspired by the list of libraries that steam-run packs here: https://github.com/NixOS/nixpkgs/blob/master/pkgs/games/steam/fhsenv.nix Here is for example the file I'm using for now, it is enough to run blender:You can also find the name of the libraries, see above
nix-index
. You can also use nix-alien-ld or nix-autobahn to automatically find and load the libraries for you. Note that if you don't have the right libraries you will get an error likeYou can see at once all the libraries that are not yet available using:
Method 9) nix-alien
nix-alien automatically builds a FHS with the appropriates libraries. If you have flake enabled (otherwise just add replace
nix run
withnix --extra-experimental-features "nix-command flakes" run
) you can simply run it this way (nix-alien is not yet packaged in 2022)It will then automatically find the library using nix-index, asking you some questions when it is not sure (this is cached).
Note that programs that rely on openGl need to use nixGl to run (this certainly apply to other methods here):
Note that you may need to change the version of
nixos-21.11
to ensure that the version of openGl matches your program.Note that you can also see the automatically generated file (the path is given the first time the program is run):
See also the other version working with nix-ld and nix-autobahn.
Method 9) Using containers/Docker (heavier)
TODO
Note that the project distrobox allows you to simply create new containers tightly integrated with the host installing any distribution you want.
Method 10) Rely on flatpack/appimage
https://nixos.org/nixos/manual/index.html#module-services-flatpak
appimage-run : To test with, ex, musescore
Sources or examples
Also, for people wanting to get started in packaging, I wrote recently a similar tutorial here.