在NixO上运行非nixos可执行文件有哪些不同的方法?我也想看看手动方法。
在NixO上运行非nixos可执行文件有哪些不同的方法?我也想看看手动方法。
Answers:
这里有几种方法(手动方法主要用于教育目的,因为大多数时候编写适当的推导方法更好)。我根本不是专家,我也做了这份清单来学习nix,因此,如果您有更好的方法,请告诉我!
因此,主要问题是可执行文件首先调用加载程序,然后需要一些库才能工作,并且nixos将加载程序和库都放入/nix/store/
。
此列表提供了我到目前为止找到的所有方法。基本上有三个“组”:
我建议使用方法4 autoPatchelfHook
进行真实,正确的设置,如果您没有时间只想在一行中运行二进制文件,那么基于steam-run
(方法7 )。
您首先需要找到带有以下内容的加载程序file
:
$ file wolframscript
wolframscript: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.18, BuildID[sha1]=079684175aa38e3633b60544681b338c0e8831e0, stripped
装载机在这里/lib64/ld-linux-x86-64.so.2
。要找到nixos的加载程序,您可以执行以下操作:
$ ls /nix/store/*glibc*/lib/ld-linux-x86-64.so.2
/nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ld-linux-x86-64.so.2
您还需要查找以找到程序所需的库,例如ldd
:
$ ldd wolframscript
linux-vdso.so.1 (0x00007ffe8fff9000)
libpthread.so.0 => /nix/store/sw54ph775lw7b9g4hlfvpx6fmlvdy8qi-glibc-2.27/lib/libpthread.so.0 (0x00007f86aa321000)
librt.so.1 => /nix/store/sw54ph775lw7b9g4hlfvpx6fmlvdy8qi-glibc-2.27/lib/librt.so.1 (0x00007f86aa317000)
libdl.so.2 => /nix/store/sw54ph775lw7b9g4hlfvpx6fmlvdy8qi-glibc-2.27/lib/libdl.so.2 (0x00007f86aa312000)
libstdc++.so.6 => not found
libm.so.6 => /nix/store/sw54ph775lw7b9g4hlfvpx6fmlvdy8qi-glibc-2.27/lib/libm.so.6 (0x00007f86aa17c000)
libgcc_s.so.1 => /nix/store/sw54ph775lw7b9g4hlfvpx6fmlvdy8qi-glibc-2.27/lib/libgcc_s.so.1 (0x00007f86a9f66000)
libc.so.6 => /nix/store/sw54ph775lw7b9g4hlfvpx6fmlvdy8qi-glibc-2.27/lib/libc.so.6 (0x00007f86a9dae000)
/lib64/ld-linux-x86-64.so.2 => /nix/store/sw54ph775lw7b9g4hlfvpx6fmlvdy8qi-glibc-2.27/lib64/ld-linux-x86-64.so.2 (0x00007f86aa344000)
在这里,您可以看到除以外的大多数库libstdc++.so.6
。因此,让我们找到它:
$ find /nix/store -name libstdc++.so.6
/nix/store/12zhmzzhrwszdc8q3fwgifpwjkwi3mzc-gcc-7.3.0-lib/lib/libstdc++.so.6
好。现在,我们只需要运行LD_LIBRARY_PATH
配置为指向该文件的程序,然后在该文件的第一步调用我们确定的加载程序:
LD_LIBRARY_PATH=/nix/store/12zhmzzhrwszdc8q3fwgifpwjkwi3mzc-gcc-7.3.0-lib/lib/:$LD_LIBRARY_PATH /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ld-linux-x86-64.so.2 ./wolframscript
(请确保./
在脚本名称之前使用,并仅保留库的目录。如果您有多个库,只需将路径用冒号concat来使用)
安装后(使用nixenv -i
或configuration.nix
)patchelf
,您还可以直接修改可执行文件以打包好的加载程序和库。要更改加载程序,只需运行:
patchelf --set-interpreter /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ld-linux-x86-64.so.2 wolframscript
并检查:
$ patchelf --print-interpreter wolframscript
/nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ld-linux-x86-64.so.
并更改硬编码在可执行文件中的库的路径,请首先检查当前的rpath是什么(对我来说是空的):
$ patchelf --print-rpath wolframscript
并将它们附加到您之前确定的库路径中,最后用冒号分隔:
$ patchelf --set-rpath /nix/store/12zhmzzhrwszdc8q3fwgifpwjkwi3mzc-gcc-7.3.0-lib/lib/ wolframscript
$ ./wolframscript
我们可以在受skypeforlinux启发的nix派生中或多或少地复制相同的东西
此示例还提供了一种替代方法,您可以使用:
patchelf --set-interpreter ${glibc}/lib/ld-linux-x86-64.so.2 "$out/bin/wolframscript" || true
(一旦您了解“手动”方法,就应该很清楚),或者
patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" "$out/bin/wolframscript" || true
第二种方法更微妙,但是如果您运行:
$ nix-shell '<nixpkgs>' -A hello --run 'echo $NIX_CC/nix-support/dynamic-linker "->" $(cat $NIX_CC/nix-support/dynamic-linker)'
/nix/store/8zfm4i1aw4c3l5n6ay311ds6l8vd9983-gcc-wrapper-7.4.0/nix-support/dynamic-linker -> /nix/store/sw54ph775lw7b9g4hlfvpx6fmlvdy8qi-glibc-2.27/lib/ld-linux-x86-64.so.2
您将看到该文件$NIX_CC/nix-support/dynamic-linker
包含加载程序的路径ld-linux-x86-64.so.2
。
放进去derivation.nix
,这是
{ stdenv, dpkg,glibc, gcc-unwrapped }:
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";
rpath = stdenv.lib.makeLibraryPath [
gcc-unwrapped
glibc
];
# What is it for?
# + ":${stdenv.cc.cc.lib}/lib64";
src = ./WolframScript_12.0.0_LINUX64_amd64.deb;
in stdenv.mkDerivation {
name = "wolframscript-${version}";
system = "x86_64-linux";
inherit src;
nativeBuildInputs = [
];
buildInputs = [ dpkg ];
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
'';
postFixup = ''
# Why does the following works?
patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" "$out/bin/wolframscript" || true
# or
# patchelf --set-interpreter ${glibc}/lib/ld-linux-x86-64.so.2 "$out/bin/wolframscript" || true
patchelf --set-rpath ${rpath} "$out/bin/wolframscript" || true
'';
meta = with stdenv.lib; {
description = "Wolframscript";
homepage = https://www.wolfram.com/wolframscript/;
license = licenses.unfree;
maintainers = with stdenv.lib.maintainers; [ ];
platforms = [ "x86_64-linux" ];
};
}
并default.nix
投入:
{ pkgs ? import <nixpkgs> {} }:
pkgs.callPackage ./derivation.nix {}
编译并运行
nix-build
result/bin/wolframscript
以前的所有方法都需要一些工作(您需要找到可执行文件,对其进行修补...)。NixOs为我们做了一个特殊的“挂钩” autoPatchelfHook
,可以自动为您修补所有内容!您只需要在中指定它(native)BuildInputs
,然后nix 就能发挥作用。
{ 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" ];
};
}
有些软件可能很难打包,因为它们可能严重依赖FHS文件树结构,或者可能检查二进制文件是否不变。然后,您还可以使用buildFHSUserEnv为您的应用程序提供FHS文件结构(轻巧,使用名称空间)。请注意,此方法比基于修补程序的方法重,并且会增加大量的启动时间,因此请尽可能避免使用
您可以只生成外壳程序,然后手动提取归档文件并执行文件,也可以直接为FHS打包程序。首先让我们看看如何获得一个外壳。将fhs-env.nix
以下内容放入文件中(例如):
let nixpkgs = import <nixpkgs> {};
in nixpkgs.buildFHSUserEnv {
name = "fhs";
targetPkgs = pkgs: [];
multiPkgs = pkgs: [ pkgs.dpkg ];
runScript = "bash";
}
并运行:
nix-build fhs-env.nix
result/bin/fhs
然后,您将在外观更标准的linux中获得重击,并且可以运行命令来运行可执行文件,例如:
mkdir wolf_fhs/
dpkg -x WolframScript_12.0.0_LINUX64_amd64.deb wolf_fhs/
cd wolf_fhs/opt/Wolfram/WolframScript/bin/
./wolfram
如果您需要更多库/程序作为依赖项,只需将它们添加到multiPkgs
(对于所有受支持的targetPkgs
拱门)或(仅对于当前拱门)。
奖励:您还可以使用单行命令启动fhs shell,而无需创建特定文件:
nix-build -E '(import <nixpkgs> {}).buildFHSUserEnv {name = "fhs";}' && ./result/bin/fhs
来源:https : //reflexivereflection.com/posts/2015-02-28-deb-installation-nixos.html
使用buildFHSUserEnv
它可以运行许多软件,但是您将需要手动指定所有必需的库。如果您想要一个快速的解决方案,而又没有时间精确检查所需的库,则可以尝试一下steam-run
(尽管它的名称没有直接与Steam链接,而是打包了很多库),这是就像buildFHSUserEnv
预先安装了许多常见库一样(其中一些可能是非免费的steamrt
,因为其中包含一些nvidia代码,谢谢辛普森!)。要使用它,只需安装steam-run
,然后:
steam-run ./wolframscript
或者如果您想要一个完整的外壳:
steam-run bash
请注意,您可能需要添加nixpkgs.config.allowUnfree = true;
(或白名单这个特定的包),如果你想与安装它nixos-rebuild
,如果你想运行与/安装nix-shell
/ nix-env
你需要把{ allowUnfree = true; }
在~/.config/nixpkgs/config.nix
。
将包或库“覆盖”到nix-shell并不容易,但是如果要围绕脚本创建包装器,则可以手动创建包装器脚本:
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p steam-run
exec steam-run ./wolframscript "$@"
或直接以nixos派生形式编写:
{ stdenv, steam-run, writeScriptBin }:
let
src = ./opt/Wolfram/WolframScript/bin/wolframscript;
in writeScriptBin "wolf_wrapped_steam" ''
exec ${steam-run}/bin/steam-run ${src} "$@"
''
或者,如果您从.deb开始(在这里我makeWrapper
改用了):
{ stdenv, steam-run, dpkg, writeScriptBin, makeWrapper }:
stdenv.mkDerivation {
name = "wolframscript";
src = ./WolframScript_12.0.0_LINUX64_amd64.deb;
nativeBuildInputs = [
dpkg makeWrapper
];
unpackPhase = "true";
installPhase = ''
mkdir -p $out/bin
dpkg -x $src $out
cp -av $out/opt/Wolfram/WolframScript/bin/wolframscript $out/bin/.wolframscript-unwrapped
makeWrapper ${steam-run}/bin/steam-run $out/bin/wolframscript --add-flags $out/bin/.wolframscript-unwrapped
rm -rf $out/opt
'';
}
(如果您太累了,无法编写常规代码default.nix
,则可以直接运行nix-build -E "with import <nixpkgs> {}; callPackage ./derivation.nix {}"
)
去做
https://nixos.org/nixos/manual/index.html#module-services-flatpak
appimage-run:使用musescore进行测试