あなたの最初の派生

あなたの最初の派生

nixプログラムをパッケージ化するための簡単な派生を作成し、それをnixpkgsに含めるためのPRを生成するにはどうすればよいですか?

(簡単な説明がないので、こう書いてください。)

ベストアンサー1

注:この答えは完全ではありませんが、すでに良い出発点になります。後でより多くの言語固有のコンテンツを追加する予定です(または各言語の質問を作成し、この回答も...「合理的に」「短くする」こともできます)。

以下はいくつかの参考資料です。

  • マニュアルのクイックスタート:詳細はこちらで説明します。
  • ニックスの丸薬(特にセクション6):素晴らしいですが、ボトムアップアプローチをとります。まず、私が混乱しているnixのすべての内部を説明します。おそらく、最初の派生物を作成するためにすべてを学ぶ必要はありません。ここではトップダウンアプローチを採用し、ほとんどのユーザーが直接使用したい機能を提供し、その後の動作を説明します。
  • 出荷書類ビーチ標準環境これは非常に良いですが、情報が多く(不完全な)例がほとんど含まれていません。
  • その他私の答えただし、事前にコンパイルされたバイナリをビルドする場合のみ。

あなたの最初の派生

一般人の観点からは、派生はプログラム構築の秘訣です。調理するときに材料をケーキに組み合わせるには、いくつかの材料(ニクスのソースと依存関係とも呼ばれます)といくつかの手順(手順とも呼ばれます)が必要です。

シンプルなCプログラム

私が想像できる最も簡単なCプログラムである簡単な例から始めましょう。program.c目的のフォルダのファイルに書き込むことができます(この例では)。

#include <stdio.h>

int main() {
   printf("Hello, World!\n");
   return 0;
}

誘導

それからnixにこのプログラムをコンパイルする方法を教えてください。したがって、ファイルを作成しますderivation.nix

{ stdenv }:
stdenv.mkDerivation rec {
  name = "program-${version}";
  version = "1.0";

  src = ./.;

  nativeBuildInputs = [ ];
  buildInputs = [ ];

  buildPhase = ''
    gcc program.c -o myprogram
  '';

  installPhase = ''
    mkdir -p $out/bin
    cp myprogram $out/bin
  '';
}

これは、入力が依存関係(ケーキの「成分」、stdenvここでは有用なユーティリティ)であり、次のおかげで派生物を出力する機能を説明しますstdenv.mkDerivationこのプロセスがすべてのコンパイル済みファイルを含むフォルダを出力すると想像できます。。私はmkDerivationいくつかの情報を提供しました:

  • ソース:ここのソースは現在のフォルダにありますが、後で見てみましょうが、ネットワークからソースをインポートすることもできます。
  • nativeBuildInputsプログラムのコンパイルに必要な依存関係(デフォルトでgccは常に含まれているため、ここでは何も指定する必要はありません)
  • buildInputsプログラムを実行するために必要な依存関係(通常はここにライブラリを置きます)
  • buildPhaseプログラム構築ガイドライン(bashスクリプト)このステップが開始されると、ソースコードを含むフォルダにドロップされます。
  • installPhaseプログラムを「インストール」する方法を説明する指示(下記参照)

実際、より多くのステップ(ソースの解凍、パッチ、構成...)がありますが、この例では必要ありません。

何をしますかinstallPhase

インストール段階では、最終実行可能ファイル/ライブラリ/アセット/...がどこにあるべきかを教えてくれます。一般的なLinux環境では、バイナリは通常/bin/usr/binまたは/usr/local/bin、ライブラリ、または/libアセット/lib64にコピーされます/share。すべてのプログラムがそのアイテムを同じ場所に配置すると、すぐに混乱する可能性があります。

Nixでは、すべてのプログラムは同様の/nix/store/someUniqueHash-programName-versionパス(このパスの値はに設定されています)に独自のフォルダを持ち、バイナリは一般的なLinuxフォルダ階層を再現してライブラリにアセットに移動します。したがって、ファイルをどこに置くべきかわからない場合は、通常のLinuxディストリビューションでファイルをどこに置くべきかを確認し、パスの前に追加する必要があります(いくつかの例外はありますが、もはや理由がないので代わりに使用します)。フォルダ)。多くのビルドシステム(cmake ...)には、プログラムをインストールする場所を示す変数があります。 : 通常、これは、または等のバイナリをインストールすることです。この場合、通常は一般的なコンパイルコマンドを簡単に設定して実行できます。プログラムをインストールすると、Nixはインストールされたソフトウェアファイルへのリンクを正しく生成します。たとえば、NixO では、グローバルにインストールされたバイナリがリンクされます。$outinstallPhase$out/bin$out/lib$out/share$out/$out/bin$out/usr/local/binlocalPREFIXPREFIX//usr/localPREFIX/binPREFIX=$out/run/current-system/sw/bin

$ ls /run/current-system/sw/bin -al | grep firefox
lrwxrwxrwx 1 root root   70 janv.  1  1970 firefox -> /nix/store/152drilm2qhjimzfx8mch0hmqvr27p29-firefox-99.0.1/bin/firefox

したがって、この例では、インストール段階でフォルダを作成し、コピー段階$out/binで取得したバイナリをコピーするだけです。これがまさに私たちがすることです!

どうやって試すことができますか?

これを試みるには、依存関係をどこから取得するかを指定する必要があります(同様にケーキを調理するときは、まずお気に入りの農家を訪問して卵を購入する必要があります)。したがって、以下を含む別のファイルを作成します(そのファイルが最初に検索されるため、default.nixここで名前が重要です)。nix

{ pkgs ? import <nixpkgs> {} }:
pkgs.callPackage ./derivation.nix {}

ここでは、デフォルトでnixにチャネルを使用して<nixpkgs>依存関係を取得するように指示すると、callPackage正しく入力されますderivation.nix

だから、ちょうど実行

$ nix-build

最後に、派生フォルダresultにリンクされた新しいフォルダが必要です。$out

$ ls -al | grep result
lrwxrwxrwx  1 leo  users  55 sept. 13 20:59 result -> /nix/store/xi0hx472hzykl6xjw0hnmh0zjyp6sc52-program-1.0

その後、次のようにバイナリを実行できます。

$ ./result/bin/myprogram
Hello, World!

おめでとうございます。最初の派生を完了しました!

以下では、より複雑なアプリケーションをパッケージ化する方法を見てみましょう。しかし、その前にパッケージをインストールしてnixpkgsに貢献する方法を見てみましょう。

私のシステムにインストールできますか?

もちろん、このフォークを取り付けることもできます。ファイルをコピーし(default.nix必要でない場合)、インストールされている/etc/nixosパッケージのリストを次に変更します。

environment.systemPackages = with pkgs; [
  (callPackage ./derivation.nix {})
]

ここに!

コマンド型を使用してすべてのシステムにインストールすることもできます。

$ nix-env -i -f default.nix

私の派生物をnixpkgsにどのように提出しますか?

nixpkgsプロジェクトのすべてのパッケージ式は、次の場所にあります。https://github.com/NixOS/nixpkgsそこに独自のパッケージを追加できます!これを行うには、まずフォーク(プール要求を実行)してリポジトリを複製します。次に、コピーして、derivation.nixプログラムの名前であるプログラムの適用範囲pkgs/CATEGORY/PACKAGE/default.nixに応じて適切に選択します。CATEGORYPACKAGE

もちろん、nixpkgsリポジトリにはプログラムのソースコードは含まれていないため、外部ソースを指すようにソースプロパティを変更する必要があります(下記参照)。

次に、nixpkgsで利用可能なすべてのプログラムのリストを見つけたので、pkgs/top-level/all-packages.nix次の行を追加する必要があります。

  myprogram = callPackage ../CATEGORY/PACKAGE { };

このファイルでは(プログラムはアルファベット順にソートされています)。テストするには、リポジトリのルートに移動して次を呼び出します。

$ nix-build -A myprogram

resultプログラムをコンパイルし、以前と同じようにテストするフォルダを作成する必要があります。

ジョブが完了したら、ジョブをコミットしてプルリクエストとして送信してください。

gitを初めて使用する場合、または詳細について知りたい場合は、この投稿が好きです。https://discourse.nixos.org/t/how-to-find-needed-librarys-for-lined-source-bin-applications/39118/43?u=tobiasbora

ソースがオンラインであればどうでしょうか?

ほとんどの場合、オンラインでホストされているソースをダウンロードしようとします。問題ありません。srcたとえば、githubからダウンロードする場合は、属性を変更するだけです(getterリストを参照)。ここ):

{ stdenv, lib, fetchFromGitHub }:
stdenv.mkDerivation rec {
  name = "program-${version}";
  version = "1.0";

  # For https://github.com/myuser/myexample
  src = fetchFromGitHub {
    owner = "myuser";
    repo = "myexample";
    rev = "v${version}"; # If there is a release like v1.0, otherwise put the commit directly 
    sha256 = ""; # <-- dummy hash: after the first compilation this line will give an error and the correct hash. Replace lib.fakeSha256 with "givenhash". Or use nix-prefetch-git. On older nix, this might fail, use sha256 = lib.fakeSha256; instead.
  };

  buildPhase = ''
    gcc program.c -o myprogram
  '';

  installPhase = ''
    mkdir -p $out/bin
    cp myprogram $out/bin
  '';
}

この行を自分のハッシュに変更する必要がありますsha256(ダウンロードしたファイルが正しいことを確認する必要があります)。lib.fakeSha256はダミーハッシュなので、最初にコンパイルするとハッシュが間違っているというエラーが発生しますtruehash。したがって、ハッシュをこの値に置き換えます(同様のツールがありますが、nix-prefetch-git使用しないことを認識する必要があります)。警告:すでにキャッシュ内にある他のプログラムのハッシュを使用するとエラーは発生しませんが、他のパッケージのソースが大幅にスパイクされます!

また、nixは自動的にソースコードに対して正しい操作を実行しようとします。特にダウンロードしたzipファイルを自動的に解凍することに注意してください。

  src = fetchurl {
    url = "http://example.org/libfoo-source-${version}.tar.bz2";
    sha256 = "0x2g1jqygyr5wiwg4ma1nd7w4ydpy82z9gkcv8vh2v8dn3y58v5m";
  };

図書館の利用方法

次に、ライブラリ(この例ではncurses)を使用してプログラムをもう少し複雑にしましょう。私たちはncurseshello-worldプログラムを使用します:

#include <ncurses.h>

int main(int argc, char ** argv)
{
    initscr(); // init screen and sets up screen
    printw("Hello World"); // print to screen
    refresh(); // refreshes the screen
    getch(); // pause the screen output
    endwin(); // deallocates memory and ends ncurses
    return 0;
}

上記のようにこのプログラムを直接コンパイルするとエラーが発生します。

program.c:1:10: fatal error: ncurses.h: No such file or directory

これは、ncursesを依存関係として追加しなかったために予想される現象です。これを行うには、スペースで区切られたリストにbuildInputsライブラリを追加しますncurses(入力依存関係の最初の行にも追加する必要があります)。これにより、buildInputsコンパイラはプログラムのバイナリからヘッダーファイルを取得します。利用可能なサブディレクトリinclude...そしてコンパイルコマンドを更新します-lncurses

{ stdenv, ncurses }:
stdenv.mkDerivation rec {
  name = "program-${version}";
  version = "1.0";

  src = ./.;

  buildInputs = [
    ncurses
  ];

  buildPhase = ''
    gcc -lncurses program.c -o myprogram
  '';

  installPhase = ''
    mkdir -p $out/bin
    cp myprogram $out/bin
  '';
}

前のようにプログラムをコンパイルして実行すれば終わりです!

プログラムのデバッグ、パート1:nix-shell

nix-buildnix-buildコンパイルをキャッシュしないため、asを使用してプログラムをデバッグすることは時々迷惑になることがあります。失敗するたびに、次回最初からコンパイルを開始します(これは再現性を確保するために必要です)。しかし、実際にこれは少し面倒かもしれません... nix-shellこの問題を解決するために作られました。上記のファイルをコンパイルするためにコマンドを実行すると、gccgccライブラリとncursesライブラリがグローバルにインストールされないため、直接失敗します(たとえば、複数のプロジェクトで同じライブラリの異なるバージョンを使用できるようにする機能です)。このプログラムをインストールするシェルを作成するには、次のコマンドを実行すると、nix-shell自動的にプログラムの依存関係を確認します。

$ nix-shell
$ gcc -lncurses program.c -o myprogram
$ ./myprogram

後でもう少し高度な使い方を見てみましょうnix-shell

基本ステップとフックを使用して時間を節約

多くのプログラムは以下を使用して簡単にコンパイルされるため、プログラムをコンパイルする方法は通常同じです。

$ ./configure --prefix=$out
$ make
$ make install

したがって、nixはデフォルトで上記のコマンドを試みます(パッチ、テストなどをもっと試してください)。これが、nixpkgsの多くのプログラムが実際に書くのに何のステップも必要としない理由です。

ほとんどのステップは実際に設定可能です。たとえば、ステップの特定の部分を有効/無効にし、makeFlags = [ "PREFIX=$(out)" ];makefileにフラグを追加するなど、いくつかのパラメータを指定できます。これらのステップの完全な文書が提供されます。マニュアルに、より具体的にこのゾーン。実際に実行している内容を確認するには、genericBuildファイルの機能を確認してください。pkgs/stdenv/generic/setup.shファイルに上記の基本ステップは、派生としてオーバーライドされない限り呼び出されます。nix-shell後で見てみましょうが、使用されているコードを直接読むこともできます。

これらの基本ステップは依存関係によって上書きされることもあります。たとえば、プログラムが cmake を使用している場合、追加するとcmakecmake を使用するように設定手順が自動的に調整されますnativeBuildInputs = [ cmake ];(これはマニュアルに従って設定することもできます)。ここ)。 scons、ninja、mesonでも同様の動作が発生します。より一般的には、 nix はビルドプロセスを修正するために特定のステップの前後に実行される複数の「フック」を定義します。それらを含めるだけnativeBuildInputsで十分です。ほとんどのフックが文書化されています。ここ、現在位置:

  • autoPatchelfHooknixで使用できるように(通常は排他的)バイナリを自動的にパッチします(他の回答も参照してください)ここ)

たとえば、次のように(ncurse)プログラムでCMakeを使用できます。CMakeLists.txtプログラムをコンパイルするための一般的なcmakeルールを含むファイルを作成します。

cmake_minimum_required(VERSION 3.10)

# set the project name
project(myprogram)

# Configure curses as a dependency
find_package(Curses REQUIRED)
include_directories(${CURSES_INCLUDE_DIR})

# add the executable
add_executable(myprogram program.c)

# Link the curses library
target_link_libraries(myprogram ${CURSES_LIBRARIES})

# Explains how to install the program
install(TARGETS myprogram DESTINATION bin)

これで、以下を大幅に簡素化できますderivation.nix

{ stdenv, ncurses, cmake }:
stdenv.mkDerivation rec {
  name = "program-${version}";
  version = "1.0";

  src = ./.;

  buildInputs = [
    ncurses
    cmake
  ];

}

nix-shellとnix内部を使用したプログラムのデバッグ:パート2

注:このセクションは残りの部分を理解するために必要ではないため、スキップできます。

nix-shell上記では、キャッシュを活用してコンパイル時間を節約するために必要なすべての依存関係を持つシェルに入れる方法を見てきました。もちろん、このシェルでは通常のコマンドを実行して以前と同じようにプログラムをコンパイルできますが、時にはnix Builderが実行するのとまったく同じコマンドを実行する方が良い場合があります。

これはnixの内部についてもっと学ぶ機会でもあります。ニックスの丸薬詳しくはこちらをご覧くださいウィキペディアに行く)。フォークを書くと、nixは.drvパッケージの構築方法を単純なjson形式で記述するファイルをフォークします。

ファイルを表示するには、次を実行できます。

$ nix-shell
# (or "nix-shell -A myprogram" if you run it from nixpkgs)
$ nix show-derivation $(nix-instantiate | sed 's/!.*//')
{
  "/nix/store/4ja3vvab4wswalczr7k0lw17dxb69nf7-program-1.0.drv": {
    "outputs": {
      "out": {
        "path": "/nix/store/qv8s0lm7w0az90xjc90dy7rvjqmic9zz-program-1.0"
      }
    },
    "inputSrcs": [
      "/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh",
      "/nix/store/zrpp5wmrq39ylqy73pbk3plvw5sx59vh-example"
    ],
    "inputDrvs": {
      "/nix/store/1av43alhcb8a894sz2cnnf9aldfdyb0h-stdenv-linux.drv": [
        "out"
      ],
      "/nix/store/6pj63b323pn53gpw3l5kdh1rly55aj15-bash-5.1-p16.drv": [
        "out"
      ],
      "/nix/store/p6y4zvhi9vjg8h7hli0ix9jxkl225ahk-ncurses-6.3-p20220507.drv": [
        "dev"
      ],
      "/nix/store/w6jf92i16rghx0jr4ix33snq4d237l8i-cmake-3.24.0.drv": [
        "out"
      ]
    },
    "system": "x86_64-linux",
    "builder": "/nix/store/1b9p07z77phvv2hf6gm9f28syp39f1ag-bash-5.1-p16/bin/bash",
    "args": [
      "-e",
      "/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"
    ],
    "env": {
      "buildInputs": "/nix/store/kn8gbpi8bfxkzg6slyskz4y0d2pkl0xk-ncurses-6.3-p20220507-dev /nix/store/xjg2fzw513iig1cghd4mvcq5fh2cyv4y-cmake-3.24.0",
      "builder": "/nix/store/1b9p07z77phvv2hf6gm9f28syp39f1ag-bash-5.1-p16/bin/bash",
      "cmakeFlags": "",
      "configureFlags": "",
      "depsBuildBuild": "",
      "depsBuildBuildPropagated": "",
      "depsBuildTarget": "",
      "depsBuildTargetPropagated": "",
      "depsHostHost": "",
      "depsHostHostPropagated": "",
      "depsTargetTarget": "",
      "depsTargetTargetPropagated": "",
      "doCheck": "",
      "doInstallCheck": "",
      "mesonFlags": "",
      "name": "program-1.0",
      "nativeBuildInputs": "",
      "out": "/nix/store/qv8s0lm7w0az90xjc90dy7rvjqmic9zz-program-1.0",
      "outputs": "out",
      "patches": "",
      "propagatedBuildInputs": "",
      "propagatedNativeBuildInputs": "",
      "src": "/nix/store/zrpp5wmrq39ylqy73pbk3plvw5sx59vh-example",
      "stdenv": "/nix/store/bj5n3k01mq8bysw0rcdm7jxvhc620pd3-stdenv-linux",
      "strictDeps": "",
      "system": "x86_64-linux",
      "version": "1.0"
    }
  }
}

"out": …正確な出力は重要ではありませんが、いくつかの重要な部分があります。まず、フォークは出力フォルダ、ソースと依存関係、ビルド中に利用可能ないくつかの環境変数、およびnix-shellの自動入力を指定します。次の理由で正しく設定しましたnix-shell

$ echo $out
/nix/store/qv8s0lm7w0az90xjc90dy7rvjqmic9zz-program-1.0

さらに重要なことは次のとおりです。

    "builder": "/nix/store/1b9p07z77phvv2hf6gm9f28syp39f1ag-bash-5.1-p16/bin/bash",
    "args": [
      "-e",
      "/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"
    ],

これは、出力を生成するためにnixが単に引数を使用してビルダーを実行することを意味します/nix/store/…/bin/bash(ここではbashインタプリタだけです)。-e /nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh

このファイルはとても簡単です。

$ cat /nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh
source $stdenv/setup
genericBuild

入力したら

$ cat $stdenv/setup

あなたはそれがまったく同じであることがわかります。pkgs/stdenv/generic/setup.sh基本ステップのファイルを整理してください!

したがってnix-shell、次の方法を使用してすべての手順を一度に実行できます(別の$outフォルダを作成すると読み取り専用モードでは書き込みできません/nix/store)。

cd empty_directory # important to make sure "source" folder is not existing, otherwise you get an error like "unpacker appears to have produced no directories". Sources will be unpacked in a subdirectory, and it must be removed every time you restart the download process (otherwise we get the above error).
export out=/tmp/out # Create a temporary folder to put the output of the derivation
set -x # Optional: to display all the command lines, useful to debug sometimes
source $stdenv/setup # In order to load the default phase of the derivation
set +e # Do not quit the shell on error/Ctrl-C ($stdenv/setup adds a "set -e")
genericBuild # start the build process.

最後の行を次に置き換えて、実行する複数のステップを指定することもできます。

phases="buildPhase" genericBuild

ステップのリストを取得するには、次のようにします。

echo "$phases"

空の場合はデフォルトです。

$ typeset -f genericBuild | grep 'phases='
phases="${prePhases:-} unpackPhase patchPhase ${preConfigurePhases:-}             configurePhase ${preBuildPhases:-} buildPhase checkPhase             ${preInstallPhases:-} installPhase ${preFixupPhases:-} fixupPhase installCheckPhase             ${preDistPhases:-} distPhase ${postPhases:-}"

他の言語をカプセル化

上記のガイドラインは確かに多くの言語と状況に適用されますが、一部の言語は環境変数と依存関係の面で独自の要件を処理するためのいくつかの追加ツールを提供しています(たとえば、pipPython依存関係をインストールするために実際に使用することはできません)))。このページに既存の言語をすべてリストするのは難しいかもしれないので、従うべきいくつかの一般的な提案は次のとおりです。

  • これnixpkgs マニュアル基本的に各言語のセクションがあるので、通常は良い出発点になります。
  • これニックスウィキ場合によっては、特定の言語に関する追加情報が含まれます。役に立つことを確認してください
  • これnixpkgs リポジトリ何千ものプログラムが含まれています。以前にパッケージ化しようとしたのと同じプログラムを誰かがパッケージ化したはずです。インスピレーションを得るには、rgオンライン検索(時々いくつかの項目が欠けているように見える)を使用するか、ローカルコピーで検索(より良い方法はgrep)を使用して、使用したいツールを含むフォークを見つけます。

ただし、簡単に説明するために頻繁に発生する可能性のある状況を以下に示します。

(しばしば独占)バイナリをパッケージ化する方法

私はかなり広い答えをしましたここ。もちろん、ソリューション4(autoPatchElf)または5-6(buildFHSUserEnv)に興味があります$out/bin。それをプログラムを呼び出すリンクやスクリプトに入れてください。autoPatchelfHooknativeBuildInputs$out/opt$out/bin$out/opt

シェルスクリプトをパッケージ化する方法

このファイルを考えてみましょうmyshellscript.sh

#!/usr/bin/bash

echo "Hello, world"

ただ使用

{ stdenv }:
stdenv.mkDerivation rec {
  name = "program-${version}";
  version = "1.0";

  src = ./.;

  installPhase = ''
    mkdir -p $out/bin
    cp myshellscript.sh $out/bin
    chmod +x $out/bin/myshellscript.sh # not needed if the file is already executable
  '';
}

patchShebangsAutobashスクリプトはフックによって自動的にパッチされます。デフォルトでは修理フェーズに表示されます。

シンプルなビルダーを使用してこの派生物をさらに小さくする方法を学びましょう。

ラッパーまたは実行可能ファイルを追加する方法

たとえば、パッケージが機能するにはいくつかの実行可能ファイルが必要であるとしますcowsay。なぜなら、nixは、美しく説明されているように、競合を制限するためにパッケージ間で「ステルス」(純度とも呼ばれる)を維持しようとしているからです。ここ(おそらくプログラムごとに異なるバージョンが必要になる場合があります。)環境変数に「使用可能」であるとはcowsay想定できません。したがって、プログラムを呼び出す前にこの変数を追加する必要があります。これは、実際のプログラムを呼び出す前に(必要に応じてより多くの環境変数も含む)、設定されているいわゆる「ラッパー」で元のプログラムを置き換えることによって行われます。cowsay$PATHcowsay$PATH

簡単なbashスクリプトのためにこのステップをより簡単にするためのツールを後で見ていきますが、ラッパーは多くの状況で役に立ち、今の使い方を学ぶことは確かに時間の無駄ではありません。

それでは、このスクリプトをパッケージ化してみましょうmyshellscript.sh

#!/usr/bin/bash

cowsay "My first wrapper!"

これを使用してくださいderivation.nix

{ lib, stdenv, cowsay, makeBinaryWrapper}:
stdenv.mkDerivation rec {
  name = "program-${version}";
  version = "1.0";

  src = ./.;
  nativeBuildInputs = [
    makeBinaryWrapper # You can also use makeWrapper to use a bash wrapper, but this won't be compatible with MacOs that expects binary loaders
  ];
  buildInputs = [
    cowsay
  ];

  installPhase = ''
    mkdir -p $out/bin
    cp myshellscript.sh $out/bin
    chmod +x $out/bin/myshellscript.sh
    wrapProgram $out/bin/myshellscript.sh \
      --prefix PATH : ${lib.makeBinPath [ cowsay ]}
  '';
}

入力を追加した方法cowsayと、以下を使用してラッパーを作成した方法を確認してください。

    wrapProgram $out/bin/myshellscript.sh \
      --prefix PATH : ${lib.makeBinPath [ cowsay ]}
  '';

cowsayパスに追加します。nix-build(通常のファイルを忘れずに)これはバイナリファイルであることがわかります(とにかく読むことができます)...このファイルが正確に何をしているのかdefault.nixを確認するのは難しいので、代わりに使用したいかもしれません。使用中ですが、「セキュリティ」の理由からMacOでは動作しません。ここでは、次の内容を読むことができます。./result/bin/myshellscript.shlessmakeWrappermakeBinWrapper

$ cat result/bin/myshellscript.sh
#! /nix/store/1b9p07z77phvv2hf6gm9f28syp39f1ag-bash-5.1-p16/bin/bash -e
PATH=${PATH:+':'$PATH':'}
PATH=${PATH/':''/nix/store/mrl0n0kphz0xwvv8qbk2xyz2x1pr2f76-cowsay-3.04/bin'':'/':'}
PATH='/nix/store/mrl0n0kphz0xwvv8qbk2xyz2x1pr2f76-cowsay-3.04/bin'$PATH
PATH=${PATH#':'}
PATH=${PATH%':'}
export PATH
exec -a "$0" "/nix/store/xrz4cv51nd8n1bawfw5i6vd4yizzmajb-program-1.0/bin/.myshellscript.sh-wrapped"  "$@" 

このコードは少し複雑ですが、基本的にCowsayのバイナリをパスの先頭に追加してから、ツールが移動したシェルファイルを実行すること$out/bin/.myshellscript.sh-wrappedですwrapProgram

今テストしてみる時間です。

$ ./result/bin/myshellscript.sh
 ___________________ 
< My first wrapper! >
 ------------------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

いいね!ラッパーを修正するためのさまざまなオプションがあります。ここ

シンプルなビルダーのおかげで、派生が短くなりました。

時々、セットアップステップ、ラッパーなどを書くのは少し面倒です。したがって、シンプルなビルダーは、より簡単な機能でstdenv.mkDerivationラップするように作成されました。stdenv.mkDerivation彼らは文書化されていますマニュアルに。私たちはこれらすべてを扱うわけではありません(それらのいくつかは新しいファイル、スクリプト、マージフォークを生成するために使用されます...)。ただし、これを使用してコードの実行を簡素化しますcowsay

このようにして、我々は単にこの派生を使用することができます:

{ lib, stdenv, cowsay, writeShellApplication }:
writeShellApplication {
  name = "mycowsay";

  runtimeInputs = [ cowsay ];

  text = ''
    cowsay "My first wrapper!"
  '';
}

$out/bin/mycowsay適切な$PATHベースを使用してbashスクリプトを生成しますruntimeInputs。以前のように外部ファイルにスクリプトを作成する場合は、次のことができます。

text = builtins.readFile ./myshellscript.sh;

Pythonスクリプトをパッケージ化する方法

TODO、関連トピックを表示:

  • 単一スクリプトの場合は、次を使用できます。https://stackoverflow.com/questions/43837691/how-to-package-a-single-python-script-with-nix
  • buildPythonPackage完全なPythonアプリケーションおよび/またはモジュールの場合はもちろん使用し(余分なmkDerivation費用はほとんどありません)、適切なファイルを作成したいと思います。setup.py私が追加したものをご覧ください。ウィキペディアで
  • Pythonを呼び出すことができるbashスクリプトもパッケージ化する場合は、次のようにラップすることをお勧めします。
  postFixup = ''
    wrapProgram "$out/bin/mssql-cli" \
      --prefix PYTHONPATH : "$PYTHONPATH"
  '';

内部、バイナリbuildPythonPackage(スクリプトではない)しなければならない(テスト)自動梱包。 (あまり好きではありませんが、wrapPythonProgramsバイナリでしか機能しないと思って作りました。この問題)

GTKアプリケーションをパッケージ化する方法

太陽

QTアプリケーションをパッケージ化する方法

太陽

おすすめ記事