「パッケージにパッチを適用」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(Kusakata がページ「ABS でパッチを適用」を「パッケージにパッチを適用」に移動しました)
(英語版と同期, --strip ではなく -p (よく使われると思われる) で例示した)
(他の1人の利用者による、間の1版が非表示)
1行目: 1行目:
 
[[Category:パッケージ管理]]
 
[[Category:パッケージ管理]]
[[en:Patching in ABS]]
+
[[en:Patching packages]]
 
{{Related articles start}}
 
{{Related articles start}}
 
{{Related|ABS}}
 
{{Related|ABS}}
{{Related|SVN から PKGBUILD を取得}}
 
 
{{Related articles end}}
 
{{Related articles end}}
このドキュメントでは [[ABS]] を使ってパッケージにパッチを作成したり適用する手順を説明します。
+
このドキュメントでは [[Arch Build System]] (ABS) を使ってパッケージにパッチを作成したり適用する手順を説明します。
  +
  +
[[Wikipedia:ja:パッチ|パッチ]] にはファイルにおけるとある行の変更が複数記されています。ソースコードの変更を自動化するのに主に用いられます。
   
 
== パッチの作成 ==
 
== パッチの作成 ==
   
  +
パッチには特定のファイル、あるいは複数のファイルの変更行が含まれています。ソースコードの変更を自動化するときにパッチは使われます。
別の場所から入手したパッチを使う場合 (例: Linux カーネルのパッチをダウンロードした場合)、下のセクションに飛んでください。ただしソースコードや Makefile、設定ファイルなどを編集する必要がある場合、パッチを作成できるようにならなければなりません。
 
   
{{Note|ファイル内か二行程度しか必要がないときは (例: Makefile)、{{ic|sed}} を用するが簡単だと思われます。}}
+
{{Note|特定の行更すだけであれば、{{ic|sed}} を代わりに使用するとい手もあります。}}
   
  +
{{ic|diff}} ツールは行毎にファイルを比較します。ツールの出力を保存することでパッチを作成できます (例: {{ic|diff --unified --recursive --text foo bar > patch}})。ディレクトリを指定すると {{ic|diff}} はディレクトリに含まれているファイルを比較します。
パッケージのパッチを作成するときは、パッケージのコピーを2つ作成して、新しいコピーを編集し、2つのファイルの差分を作成します。Arch Linux パッケージを作成する場合、以下の手順に従うことでパッチが作成できます:
 
   
  +
# パッケージをビルド済みの場合は {{ic|src}} ディレクトリを削除してください。
# ファイルのダウンロード先を {{ic|PKGBUILD}} の source 配列に追加してください。もちろん、既存の PKGBUILD を編集する場合、必要ありません。
 
  +
# {{ic|makepkg --nobuild}} を実行してください。{{ic|PKGBUILD}} に記述されたソースファイルがダウンロード・展開されます。
# ダミーの (空の、あるいは {{ic|echo}} コマンドだけしか存在しない) build() 関数を作成してください。既存の {{ic|PKGBUILD}} を修正する場合、build 関数の大部分をコメントアウトしてください。{{ic|makepkg}} を複数回実行することになるため、壊れたパッケージをビルドするのに時間を費やすのは無駄です。
 
  +
# {{ic|src}} ディレクトリに展開されたディレクトリのコピーを2つ作成してください。ひとつは元のまま取っておくコピーで、もうひとつは変更を加えるコピーです。ここでは {{ic|package.orig}} と {{ic|package.new}} と呼称します。
# {{ic|makepkg -o}} を実行してください。編集する必要があるソースファイルが {{ic|src}} ディレクトリにダウンロードされます。
 
  +
# {{ic|package.new}} ディレクトリのファイルに必要な変更を加えてください。
# {{ic|src}} ディレクトリに移動してください。通常の場合、ダウンロードした圧縮ファイルから解凍されたファイルが含まれたディレクトリが存在します (ファイルしかない場合もありますが、差分は複数のファイルを処理できます)。ディレクトリのコピーを2つ作成してください。片方のコピーには手を入れず makepkg で操作しません。もう片方のコピーからパッチを作成します。2つのコピーには {{ic|package.pristine}} と {{ic|package.new}} などと名前を付けます。
 
  +
# {{ic|diff --unified --recursive --text package.orig package.new --color}} を実行してパッチがどのように出来るか確認してください。
# {{ic|package.new}} ディレクトリに移動してください。編集する必要があるファイルを全て編集します。必要な変更はパッチで何をするかによります。Makefile のパスを修正する、あるいはソースのエラーを修正する (例えば、{{ic|gcc 3.4}} でコンパイルできるようにする) などです。無論、{{ic|package.new}} ディレクトリのサブディレクトリにあるファイルを編集することもできます。{{ic|package.new}} ディレクトリに大量のファイルを作成するコマンドを実行しないように気をつけてください。プログラムをコンパイルして変更が問題ないかを確認してはいけません。コンパイルを実行してしまうと、無用なファイルがパッチの中に入ってしまいます。代わりに、手動で {{ic|patch}} コマンドを使用するか {{ic|PKGBUILD}} (下を参照) でディレクトリの別のコピー (先に作成した pristine ディレクトリではありません) にパッチを適用して、そこから変更を適用してください。
 
# {{ic|src}} ディレクトリに戻ってください。
+
# {{ic|diff --unified --recursive --text package.orig package.new > package.patch}} を実行してパッチを作成してください。
# {{ic|diff -aur package.pristine package.new}} を実行してください。unified 形式の diff フォーマット全ての変更が出力されます。ファイル開いてパッ問題ないことを確認することができます。
+
# {{ic|package.orig}} ディレクトリに移動して {{ic|patch -p1 < ../package.patch}} でパッチ適用してください。{{ic|makepkg --noextract --install}} で変更を加えたパッケージビルド・インストールできることを確認ます。
  +
# {{ic|diff -aur package.pristine package.new > package.patch}} を実行して全ての変更を {{ic|package.patch}} という名前のファイルにまとめてください。これが patch で使用するファイルになります。元のディレクトリのコピーに変更を適用して、上手くパッチが機能することを確認できます。また、パッチに無駄な情報が含まれていないことも確認すると良いでしょう。例えば、ファイル内のタブがパッチによってスペースに変換されるのは望ましくありません (テキストエディタが行ったことが原因です)。パッチはテキストエディタを使って編集することができます。あるいは万全を期して (diff ファイルに誤りを入れないように)、元のファイルを編集してから再度パッチを作成してもかまいません。
 
  +
{{Note|[[Git]] で {{ic|git diff}} または {{ic|git format-patch}} を使ってパッチを作成することもできます [https://stackoverflow.com/questions/6658313/generate-a-git-patch-for-a-specific-commit]。}}
  +
  +
{{ic|diff}} について、さらなる詳細は {{man|1|diff}} や {{man|1|git-diff}} を参照してください。
   
 
== パッチの適用 ==
 
== パッチの適用 ==
28行目: 32行目:
 
このセクションでは自分で作成した、あるいはインターネットからダウンロードしてきたパッチを {{ic|PKGBUILD}} の {{ic|prepare()}} 関数で適用する方法を説明します。以下の手順に従ってください:
 
このセクションでは自分で作成した、あるいはインターネットからダウンロードしてきたパッチを {{ic|PKGBUILD}} の {{ic|prepare()}} 関数で適用する方法を説明します。以下の手順に従ってください:
   
# {{ic|PKGBUILD}} の {{ic|source}} 配列にパッチファイルのエントリを追加してください。元のソース url とは空白で区切られます。ファイルがオンライン上に存在する場合、完全な URL を記入すれば {{ic|src}} ディレクトリに自動的にダウンロード・配置されます。パッチを自分で作成した場合、あるいはインターネット上からパッチを取得できない場合、{{ic|PKGBUILD}} ファイルと同じディレクトリにパッチファイルを置いて、source 配列にファイルの名前を追加してください。ファイルが {{ic|src}} ディレクトリにコピーされるようになります。{{ic|PKGBUILD}} を再配布する場合、{{ic|PKGBUILD}} とパッチを一緒にする必要があります。
+
# {{ic|PKGBUILD}} の {{ic|source}} 配列にパッチファイルのエントリを追加してください。元のソース url とは空白で区切られます。ファイルがオンライン上に存在する場合、完全な URL を記入すれば {{ic|src}} ディレクトリに自動的にダウンロード・配置されます。パッチを自分で作成した場合、あるいはインターネット上からパッチを取得できない場合、{{ic|PKGBUILD}} ファイルと同じディレクトリにパッチファイルを置いて、{{ic|source}} 配列にファイルの名前を追加してください。ファイルが {{ic|src}} ディレクトリにコピーされるようになります。{{ic|PKGBUILD}} を再配布する場合、{{ic|PKGBUILD}} とパッチを一緒にする必要があります。
# 次に {{ic|updpkgsums}} を使用して {{ic|md5sums}} 配列を更新してください。あるいは手動で {{ic|md5sums}} 配列にエントリを追加してください。{{ic|md5sum}} ツールを使うことでパッチのチェックサムを生成できます。
+
# 次に、パッケー {{Pkg|pacman-contrib}} に含まれる {{ic|updpkgsums}} を使用して {{ic|md5sums}} 配列を更新してください。あるいは手動で {{ic|md5sums}} 配列にエントリを追加してください。{{ic|md5sum}} ツールを使うことでパッチのチェックサムを生成できます。
 
# {{ic|PKGBUILD}} の中に {{ic|prepare()}} 関数を(存在しない場合)作成してください。
 
# {{ic|PKGBUILD}} の中に {{ic|prepare()}} 関数を(存在しない場合)作成してください。
 
# まずはパッチをあてる必要があるディレクトリに移動します (移動を行うのは {{ic|prepare()}} 関数の中で、ターミナルではありません。パッチの適用を自動化します)。{{ic|cd $srcdir/$pkgname-$pkgver}} などとすることでディレクトリを移動できます。{{ic|$pkgname-$pkgver}} はダウンロードされたソースファイルが展開されたときによく作られるディレクトリの名前ですが、必ずしもこの名前になるとは限りません。
 
# まずはパッチをあてる必要があるディレクトリに移動します (移動を行うのは {{ic|prepare()}} 関数の中で、ターミナルではありません。パッチの適用を自動化します)。{{ic|cd $srcdir/$pkgname-$pkgver}} などとすることでディレクトリを移動できます。{{ic|$pkgname-$pkgver}} はダウンロードされたソースファイルが展開されたときによく作られるディレクトリの名前ですが、必ずしもこの名前になるとは限りません。
# ディレクトリの中からパッチを適用してください。{{ic|prepare()}} 関数に以下を追加するだけです ({{ic|pkgname.patch}} は差分が含まれているファイルの名前に置き換えてください。パッチファイルは {{ic|PKGBUILD}} の {{ic|source}} 配列に追加したので自動的に {{ic|src}} ディレクトリにコピーされています):{{bc|patch -p1 <pkgname.patch}}
+
# ディレクトリの中からパッチを適用してください。{{ic|prepare()}} 関数に以下を追加するだけです ({{ic|''pkgname''.patch}} は差分が含まれているファイルの名前に置き換えてください。パッチファイルは {{ic|PKGBUILD}} の {{ic|source}} 配列に追加したので自動的に {{ic|src}} ディレクトリにコピーされています):{{bc|patch -p1 -i ''pkgname''.patch}}
   
 
::prepare 関数の例:{{bc|<nowiki>
 
::prepare 関数の例:{{bc|<nowiki>
 
prepare() {
 
prepare() {
 
cd $pkgname-$pkgver
 
cd $pkgname-$pkgver
patch -Np1 <../eject.patch
+
patch -Np1 -i "${srcdir}/eject.patch"
 
}
 
}
 
</nowiki>}}
 
</nowiki>}}
   
(ターミナルから) {{ic|makepkg}} を実行してください。全てが上手くいっていれば、パッチが自動的に適用されて、新しいパッケージにはパッチに含まれている変更が追加されているはずです。そうならない場合、patch の {{ic|-p}} オプションを使って実験を行ってみてください。詳しくは {{ic|man patch}} を読んでください。
+
(ターミナルから) {{ic|makepkg}} を実行してください。全てが上手くいっていれば、パッチが自動的に適用されて、新しいパッケージにはパッチに含まれている変更が追加されているはずです。そうならない場合、patch の {{ic|-p}} オプションを使って実験を行ってみてください ({{ic|--dry-run}} や {{ic|--reverse}} や {{ic|--verbose}} などのオプションが有用でしょう)。詳しくは {{man|1|patch}} を読んでください。
   
 
基本的には次のようになっています。{{ic|myversion/}} のファイルにパッチを適用する diff ファイルが作成された場合、diff ファイルは {{ic|myversion/file}} に適用されます。({{ic|PKGBUILD}} で cd した) {{ic|yourversion/}} ディレクトリの中から実行する場合、ファイルにパッチが適用されるときに、{{ic|myversion/}} の部分は省いて {{ic|file}} ファイルに適用されるようにしなくてはなりません。{{ic|-p1}} でパスからディレクトリが一つ削除されます。しかしながら、開発者が {{ic|myfiles/myversion}} にパッチを適用した場合、ディレクトリを二つ削除する必要があるので、{{ic|-p2}} を使います。
 
基本的には次のようになっています。{{ic|myversion/}} のファイルにパッチを適用する diff ファイルが作成された場合、diff ファイルは {{ic|myversion/file}} に適用されます。({{ic|PKGBUILD}} で cd した) {{ic|yourversion/}} ディレクトリの中から実行する場合、ファイルにパッチが適用されるときに、{{ic|myversion/}} の部分は省いて {{ic|file}} ファイルに適用されるようにしなくてはなりません。{{ic|-p1}} でパスからディレクトリが一つ削除されます。しかしながら、開発者が {{ic|myfiles/myversion}} にパッチを適用した場合、ディレクトリを二つ削除する必要があるので、{{ic|-p2}} を使います。
   
-p オプションを指定しなかった場合、全てのディレクトリ構造が取り除かれます。全てのファイルがベースディレクトリに存在する場合はそれで ok ですが、パッチを作成したのが {{ic|myversion/}} で編集したファイルが {{ic|myversion/src/file}} の場合、{{ic|yourversion}} の中から {{ic|-p}} オプションを付けずにパッチを実行したときに、{{ic|yourversion/file}} という名前のファイルにパッチが適用されてしまいます。
+
{{ic|-p}} オプションを指定しなかった場合、全てのディレクトリ構造が取り除かれます。全てのファイルがベースディレクトリに存在する場合はそれで ok ですが、パッチを作成したのが {{ic|myversion/}} で編集したファイルが {{ic|myversion/src/file}} の場合、{{ic|yourversion}} の中から {{ic|-p}} オプションを付けずにパッチを実行したときに、{{ic|yourversion/file}} という名前のファイルにパッチが適用されてしまいます。
   
 
ほとんどの開発者はパッチを適用するディレクトリの親ディレクトリからパッチを作成するので、通常は {{ic|-p1}} が正しくなります。
 
ほとんどの開発者はパッチを適用するディレクトリの親ディレクトリからパッチを作成するので、通常は {{ic|-p1}} が正しくなります。
  +
  +
== quilt を使う ==
  +
  +
多数のパッチを管理する場合、{{Pkg|quilt}} を使うことでパッチの適用や更新、パッチをあてたファイルのリバートなどが楽になります。{{Pkg|quilt}} は [https://wiki.debian.org/UsingQuilt Debian] でパッチを管理するのに使われています。基本的な使用方法は [http://www.shakthimaan.com/downloads/glv/quilt-tutorial/quilt-doc.pdf Using Quilt] を見てください。
   
 
== 参照 ==
 
== 参照 ==
   
* http://www.kegel.com/academy/opensource.html — Useful information on patching files
+
* http://www.kegel.com/academy/opensource.html — パッチの適用に関する有用な情報
* http://patch-tracker.debian.org/
 
* http://gentoo-portage.com/
 
* http://packages.gentoo.org/
 
* http://pkgs.fedoraproject.org/cgit/
 

2019年6月8日 (土) 16:27時点における版

関連記事

このドキュメントでは Arch Build System (ABS) を使ってパッケージにパッチを作成したり適用する手順を説明します。

パッチ にはファイルにおけるとある行の変更が複数記されています。ソースコードの変更を自動化するのに主に用いられます。

パッチの作成

パッチには特定のファイル、あるいは複数のファイルの変更行が含まれています。ソースコードの変更を自動化するときにパッチは使われます。

ノート: 特定の行を変更するだけであれば、sed を代わりに使用するという手もあります。

diff ツールは行毎にファイルを比較します。ツールの出力を保存することでパッチを作成できます (例: diff --unified --recursive --text foo bar > patch)。ディレクトリを指定すると diff はディレクトリに含まれているファイルを比較します。

  1. パッケージをビルド済みの場合は src ディレクトリを削除してください。
  2. makepkg --nobuild を実行してください。PKGBUILD に記述されたソースファイルがダウンロード・展開されます。
  3. src ディレクトリに展開されたディレクトリのコピーを2つ作成してください。ひとつは元のまま取っておくコピーで、もうひとつは変更を加えるコピーです。ここでは package.origpackage.new と呼称します。
  4. package.new ディレクトリのファイルに必要な変更を加えてください。
  5. diff --unified --recursive --text package.orig package.new --color を実行してパッチがどのように出来るか確認してください。
  6. diff --unified --recursive --text package.orig package.new > package.patch を実行してパッチを作成してください。
  7. package.orig ディレクトリに移動して patch -p1 < ../package.patch でパッチを適用してください。makepkg --noextract --install で変更を加えたパッケージがビルド・インストールできることを確認します。
ノート: Gitgit diff または git format-patch を使ってパッチを作成することもできます [1]

diff について、さらなる詳細は diff(1)git-diff(1) を参照してください。

パッチの適用

このセクションでは自分で作成した、あるいはインターネットからダウンロードしてきたパッチを PKGBUILDprepare() 関数で適用する方法を説明します。以下の手順に従ってください:

  1. PKGBUILDsource 配列にパッチファイルのエントリを追加してください。元のソース url とは空白で区切られます。ファイルがオンライン上に存在する場合、完全な URL を記入すれば src ディレクトリに自動的にダウンロード・配置されます。パッチを自分で作成した場合、あるいはインターネット上からパッチを取得できない場合、PKGBUILD ファイルと同じディレクトリにパッチファイルを置いて、source 配列にファイルの名前を追加してください。ファイルが src ディレクトリにコピーされるようになります。PKGBUILD を再配布する場合、PKGBUILD とパッチを一緒にする必要があります。
  2. 次に、パッケー pacman-contrib に含まれる updpkgsums を使用して md5sums 配列を更新してください。あるいは手動で md5sums 配列にエントリを追加してください。md5sum ツールを使うことでパッチのチェックサムを生成できます。
  3. PKGBUILD の中に prepare() 関数を(存在しない場合)作成してください。
  4. まずはパッチをあてる必要があるディレクトリに移動します (移動を行うのは prepare() 関数の中で、ターミナルではありません。パッチの適用を自動化します)。cd $srcdir/$pkgname-$pkgver などとすることでディレクトリを移動できます。$pkgname-$pkgver はダウンロードされたソースファイルが展開されたときによく作られるディレクトリの名前ですが、必ずしもこの名前になるとは限りません。
  5. ディレクトリの中からパッチを適用してください。prepare() 関数に以下を追加するだけです (pkgname.patch は差分が含まれているファイルの名前に置き換えてください。パッチファイルは PKGBUILDsource 配列に追加したので自動的に src ディレクトリにコピーされています):
    patch -p1 -i pkgname.patch
prepare 関数の例:
prepare() {
 cd $pkgname-$pkgver
 patch -Np1 -i "${srcdir}/eject.patch"
}

(ターミナルから) makepkg を実行してください。全てが上手くいっていれば、パッチが自動的に適用されて、新しいパッケージにはパッチに含まれている変更が追加されているはずです。そうならない場合、patch の -p オプションを使って実験を行ってみてください (--dry-run--reverse--verbose などのオプションが有用でしょう)。詳しくは patch(1) を読んでください。

基本的には次のようになっています。myversion/ のファイルにパッチを適用する diff ファイルが作成された場合、diff ファイルは myversion/file に適用されます。(PKGBUILD で cd した) yourversion/ ディレクトリの中から実行する場合、ファイルにパッチが適用されるときに、myversion/ の部分は省いて file ファイルに適用されるようにしなくてはなりません。-p1 でパスからディレクトリが一つ削除されます。しかしながら、開発者が myfiles/myversion にパッチを適用した場合、ディレクトリを二つ削除する必要があるので、-p2 を使います。

-p オプションを指定しなかった場合、全てのディレクトリ構造が取り除かれます。全てのファイルがベースディレクトリに存在する場合はそれで ok ですが、パッチを作成したのが myversion/ で編集したファイルが myversion/src/file の場合、yourversion の中から -p オプションを付けずにパッチを実行したときに、yourversion/file という名前のファイルにパッチが適用されてしまいます。

ほとんどの開発者はパッチを適用するディレクトリの親ディレクトリからパッチを作成するので、通常は -p1 が正しくなります。

quilt を使う

多数のパッチを管理する場合、quilt を使うことでパッチの適用や更新、パッチをあてたファイルのリバートなどが楽になります。quiltDebian でパッチを管理するのに使われています。基本的な使用方法は Using Quilt を見てください。

参照