NixOでNixos以外の実行可能ファイルを実行するには、どのような方法がありますか?手動の方法も見たいです。
ここにいくつかの方法があります(手動による方法は、ほとんどの場合、適切な派生を書く方が良いため、ほとんどが教育目的です)。私はまったく専門家ではないので、このリストもnixを学ぶために作成したので、より良い方法がある場合は、お知らせください!
したがって、主な問題は、実行可能ファイルが最初にローダーを呼び出し、次に機能するためにいくつかのライブラリーを必要とすること、そしてnixosがローダーとライブラリーの両方を/nix/store/
に配置することです。
このリストは、これまでに見つけたすべての方法を示しています。基本的に3つの「グループ」があります。
実際に適切な設定を行うには、autoPatchelfHook
を使用した方法4をお勧めします。時間がなく、バイナリを1行で実行したい場合は、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
(スクリプト名の前に./
を使用し、ライブラリのディレクトリのみを保持するようにしてください。複数のライブラリがある場合は、パスをコロンで連結してください)
(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
この2番目の方法は少し微妙ですが、実行すると:
$ 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
以前のすべてのメソッドには少し作業が必要です(実行可能ファイルを見つけてパッチを適用する必要があります...)。 NixOは、自動的にすべてにパッチを適用する特別な「フック」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でbashを取得し、次のようなコマンドを実行して実行可能ファイルを実行できます。
mkdir wolf_fhs/
dpkg -x WolframScript_12.0.0_LINUX64_AMD64.deb wolf_fhs/
cd wolf_fhs/opt/Wolfram/WolframScript/bin/
./wolfram
依存関係としてより多くのライブラリ/プログラムが必要な場合は、それらをmultiPkgs
(サポートされているすべてのArchの場合)またはtargetPkgs
(現在のArchのみ)に追加してください。
おまけ:特定のファイルを作成せずに、1行のコマンドでfhsシェルを起動することもできます。
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
のようなものです(それらのいくつかは、いくつかのnvidiaコードをパックするsteamrt
のようにフリーではないかもしれません、simpsonに感謝します!)。これを使用するには、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 {}"
を実行できます)
TODO
https://nixos.org/nixos/manual/index.html#module-services-flatpak
appimage-run:musescoreでテストする