Apa metode yang berbeda untuk menjalankan non-nixos yang dapat dieksekusi di NixO? Saya juga ingin melihat metode manualnya.
Apa metode yang berbeda untuk menjalankan non-nixos yang dapat dieksekusi di NixO? Saya juga ingin melihat metode manualnya.
Jawaban:
Berikut adalah beberapa metode (yang manual kebanyakan untuk tujuan pendidikan karena sebagian besar waktu menulis derivasi yang tepat lebih baik). Saya bukan ahli sama sekali, dan saya melakukan daftar ini juga untuk mempelajari nix, jadi jika Anda memiliki metode yang lebih baik, beri tahu saya!
Jadi masalah utamanya adalah bahwa panggilan yang dapat dieksekusi terlebih dahulu loader, dan kemudian membutuhkan beberapa perpustakaan untuk bekerja, dan nixos memasukkan kedua loader dan perpustakaan /nix/store/
.
Daftar ini memberikan semua metode yang saya temukan sejauh ini. Pada dasarnya ada tiga "grup":
Saya akan merekomendasikan metode 4 dengan autoPatchelfHook
pengaturan yang nyata dan tepat, dan jika Anda tidak punya waktu dan hanya ingin menjalankan biner dalam satu baris, Anda mungkin tertarik dengan solusi cepat dan kotor berdasarkan pada steam-run
(metode 7) ).
Anda harus terlebih dahulu menemukan loader dengan misalnya 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
Di sini loadernya /lib64/ld-linux-x86-64.so.2
. Untuk menemukan pemuat nixos, Anda dapat melakukan:
$ ls /nix/store/*glibc*/lib/ld-linux-x86-64.so.2
/nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ld-linux-x86-64.so.2
Anda juga perlu menemukan untuk menemukan perpustakaan yang diperlukan oleh program Anda, misalnya dengan 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)
Di sini, Anda melihat bahwa sebagian besar perpustakaan ditemukan kecuali libstdc++.so.6
. Jadi mari kita temukan:
$ find /nix/store -name libstdc++.so.6
/nix/store/12zhmzzhrwszdc8q3fwgifpwjkwi3mzc-gcc-7.3.0-lib/lib/libstdc++.so.6
Baik. Sekarang, kita hanya perlu menjalankan program dengan LD_LIBRARY_PATH
konfigurasi untuk menunjuk ke file ini, dan memanggil loader yang kita tentukan pada langkah pertama pada file ini:
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
(pastikan untuk menggunakan ./
sebelum nama skrip, dan hanya menyimpan direktori perpustakaan. Jika Anda memiliki beberapa perpustakaan, cukup gunakan concat path dengan titik dua)
Setelah menginstal (dengan nixenv -i
atau di Anda configuration.nix
) patchelf
, Anda juga dapat secara langsung memodifikasi executable untuk mengemas loader dan library yang baik. Untuk mengubah loader, jalankan:
patchelf --set-interpreter /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ld-linux-x86-64.so.2 wolframscript
dan untuk memeriksa:
$ patchelf --print-interpreter wolframscript
/nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ld-linux-x86-64.so.
dan untuk mengubah jalur ke pustaka yang di-hardcode dalam executable, periksa terlebih dahulu apa rpath saat ini (kosong untuk saya):
$ patchelf --print-rpath wolframscript
dan menambahkannya ke jalur perpustakaan yang Anda tentukan sebelumnya, akhirnya dipisahkan dengan titik dua:
$ patchelf --set-rpath /nix/store/12zhmzzhrwszdc8q3fwgifpwjkwi3mzc-gcc-7.3.0-lib/lib/ wolframscript
$ ./wolframscript
Kita dapat mereproduksi hal yang kurang lebih sama dalam derivasi nix yang terinspirasi oleh skypeforlinux
Contoh ini juga menyajikan alternatif, bisa Anda gunakan:
patchelf --set-interpreter ${glibc}/lib/ld-linux-x86-64.so.2 "$out/bin/wolframscript" || true
(yang seharusnya cukup jelas setelah Anda memahami metode "manual"), atau
patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" "$out/bin/wolframscript" || true
Metode kedua ini sedikit lebih halus, tetapi jika Anda menjalankan:
$ 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
Anda akan melihat bahwa file tersebut $NIX_CC/nix-support/dynamic-linker
berisi path ke loader ld-linux-x86-64.so.2
.
Dimasukkan ke dalam derivation.nix
, ini
{ 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" ];
};
}
dan di tempat default.nix
:
{ pkgs ? import <nixpkgs> {} }:
pkgs.callPackage ./derivation.nix {}
Kompilasi dan jalankan bersama
nix-build
result/bin/wolframscript
Semua metode sebelumnya membutuhkan sedikit pekerjaan (Anda perlu menemukan executable, tambalan mereka ...). NixOs memberi kami "kait" khusus autoPatchelfHook
yang secara otomatis menambal segalanya untuk Anda! Anda hanya perlu menentukannya (native)BuildInputs
, dan nix melakukan keajaiban.
{ 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" ];
};
}
Beberapa sofware mungkin sulit untuk dikemas dengan cara itu karena mereka mungkin sangat bergantung pada struktur pohon file FHS , atau mungkin memeriksa bahwa biner tidak berubah. Anda kemudian dapat juga menggunakan buildFHSUserEnv untuk menyediakan struktur file FHS (ringan, menggunakan namespaces) untuk aplikasi Anda. Perhatikan bahwa metode ini lebih berat daripada metode berbasis tambalan, dan tambahkan waktu startup yang signifikan, jadi hindari jika memungkinkan
Anda bisa menelurkan shell dan kemudian secara manual mengekstrak arsip dan menjalankan file, atau langsung mengemas program Anda untuk FHS. Pertama mari kita lihat bagaimana cara mendapatkan shell. Masukkan file (katakan fhs-env.nix
) berikut ini:
let nixpkgs = import <nixpkgs> {};
in nixpkgs.buildFHSUserEnv {
name = "fhs";
targetPkgs = pkgs: [];
multiPkgs = pkgs: [ pkgs.dpkg ];
runScript = "bash";
}
dan lari:
nix-build fhs-env.nix
result/bin/fhs
Anda kemudian akan mendapatkan bash di linux yang tampak lebih standar, dan Anda dapat menjalankan perintah untuk menjalankan executable Anda, seperti:
mkdir wolf_fhs/
dpkg -x WolframScript_12.0.0_LINUX64_amd64.deb wolf_fhs/
cd wolf_fhs/opt/Wolfram/WolframScript/bin/
./wolfram
Jika Anda membutuhkan lebih banyak pustaka / program sebagai dependensi, cukup tambahkan ke multiPkgs
(untuk semua targetPkgs
lengkungan yang didukung) atau (hanya untuk lengkungan saat ini).
Bonus: Anda juga dapat meluncurkan shell fhs dengan perintah satu baris, tanpa membuat file tertentu:
nix-build -E '(import <nixpkgs> {}).buildFHSUserEnv {name = "fhs";}' && ./result/bin/fhs
sumber: https://reflexivereflection.com/posts/2015-02-02-deb-installation-nixos.html
Dengan buildFHSUserEnv
Anda dapat menjalankan banyak softwares, tetapi Anda harus menentukan secara manual semua perpustakaan yang diperlukan. Jika Anda menginginkan solusi cepat dan Anda tidak punya waktu untuk memeriksa dengan tepat perpustakaan apa yang diperlukan, Anda mungkin ingin mencoba steam-run
(terlepas dari namanya, itu tidak terhubung langsung dengan uap, dan hanya mengemas banyak perpustakaan), yang merupakan seperti buildFHSUserEnv
dengan banyak perpustakaan umum yang sudah diinstal sebelumnya (beberapa di antaranya mungkin tidak bebas seperti steamrt
itu mengemas beberapa kode nvidia, terima kasih simpson!). Untuk menggunakannya, cukup instal steam-run
, lalu:
steam-run ./wolframscript
atau jika Anda ingin shell penuh:
steam-run bash
Perhatikan bahwa Anda mungkin perlu menambahkan nixpkgs.config.allowUnfree = true;
(atau whitelist paket khusus ini ) jika Anda ingin menginstalnya dengan nixos-rebuild
, dan jika Anda ingin menjalankan / install dengan nix-shell
/ nix-env
Anda harus menempatkan { allowUnfree = true; }
di ~/.config/nixpkgs/config.nix
.
Tidaklah mudah untuk "menimpa" paket atau pustaka ke nix-shell, tetapi jika Anda ingin membuat wrapper di sekitar skrip Anda, Anda dapat membuat skrip wrapper secara manual:
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p steam-run
exec steam-run ./wolframscript "$@"
atau langsung menuliskannya di derivasi nixos:
{ stdenv, steam-run, writeScriptBin }:
let
src = ./opt/Wolfram/WolframScript/bin/wolframscript;
in writeScriptBin "wolf_wrapped_steam" ''
exec ${steam-run}/bin/steam-run ${src} "$@"
''
atau jika Anda mulai dari .deb (di sini saya menggunakan makeWrapper
sebaliknya):
{ 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
'';
}
(jika Anda terlalu lelah untuk menulis yang biasa default.nix
, Anda dapat berlari langsung nix-build -E "with import <nixpkgs> {}; callPackage ./derivation.nix {}"
)
MELAKUKAN
https://nixos.org/nixos/manual/index.html#module-services-flatpak
appimage-run: Untuk menguji dengan, ex, musescore