Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 13343] ファイルの概要

このコミットは、Go言語のビルドシステムにおける条件付きコンパイルディレクティブ(+buildタグ)のドキュメント内の論理式の誤りを修正するものです。具体的には、特定のプラットフォーム(LinuxまたはmacOS)とCgoが両方とも有効でない場合にファイルを含めるためのビルドタグの論理否定が誤っていた点を訂正しています。

コミット

  • コミットハッシュ: 503aa6505e26f7dadf9e115eca186c9c01ff99d9
  • 作者: Russ Cox rsc@golang.org
  • コミット日時: 2012年6月13日 水曜日 16:24:56 -0400

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/503aa6505e26f7dadf9e115eca186c9c01ff99d9

元コミット内容

go/build: fix boolean negation

!(linux&cgo | darwin&cgo)
= (!linux|!cgo) & (!darwin|!cgo)
= (!linux&!darwin) | !cgo  // new comment
≠ !linux | !darwin | !cgo  // old comment

Fixes #3726.

R=golang-dev, bsiegert
CC=golang-dev
https://golang.org/cl/6306076

変更の背景

この変更は、Go言語のビルドシステムがファイルを選択する際に使用する+buildタグの論理式に関するドキュメントの誤りを修正するために行われました。Goのビルドシステムでは、ソースファイルの先頭に// +buildディレクティブを記述することで、特定のビルド条件(例: OS、アーキテクチャ、タグ)が満たされた場合にのみそのファイルをコンパイル対象に含めることができます。

コミットメッセージに記載されているように、この修正はGoのIssue #3726に対応しています。このIssueでは、go/buildパッケージのドキュメント(doc.go)に記載されていた、特定の条件の論理否定の例が誤っていることが指摘されました。具体的には、「LinuxまたはmacOSでCgoが有効な場合」という条件の否定が、ドキュメント上では誤った形で表現されており、これが開発者の混乱を招く可能性がありました。

この誤りは、Goのビルドタグの動作を正確に理解し、適切に利用するために非常に重要です。特に、特定の環境を除外したい場合や、複数の条件を組み合わせた複雑なビルドロジックを記述する際に、論理演算の正確な理解が不可欠となります。このコミットは、ドキュメントの正確性を高め、Go開発者がビルドタグをより効果的に使用できるようにすることを目的としています。

前提知識の解説

Goのビルドタグ(Build Constraints)

Go言語では、ソースファイルの先頭に特別なコメント行を記述することで、そのファイルを特定のビルド条件に基づいて含めるか除外するかを制御できます。これを「ビルドタグ」または「ビルド制約(Build Constraints)」と呼びます。

構文は以下の通りです。 // +build tag1,tag2 tag3

  • tag1,tag2: カンマで区切られたタグは論理AND(すべてが真)として扱われます。
  • スペースで区切られたタグのグループは論理OR(いずれかが真)として扱われます。
  • タグの前に!を付けると論理NOT(否定)になります。

例:

  • // +build linux darwin: LinuxまたはmacOSの場合にビルド。
  • // +build amd64,go1.18: AMD64アーキテクチャかつGo 1.18以上の場合にビルド。
  • // +build !windows: Windows以外の場合にビルド。

これらのタグは、OS(linux, windows, darwinなど)、アーキテクチャ(amd64, arm, 386など)、Goのバージョン(go1.18など)、またはカスタムタグ(debug, releaseなど)を指定するために使用されます。

ブール論理とド・モルガンの法則

このコミットの核心は、ブール論理における論理否定の正確な適用、特に「ド・モルガンの法則」にあります。

ブール論理の基本的な演算子:

  • AND (& または &&): 両方の条件が真の場合に真。
  • OR (| または ||): どちらか一方または両方の条件が真の場合に真。
  • NOT (! または ~): 条件が真であれば偽、偽であれば真。

ド・モルガンの法則: 論理否定を分配する際に使用される重要な法則です。

  1. !(A AND B)(!A OR !B) と等価である。 例: !(linux & cgo)(!linux | !cgo) と等価。
  2. !(A OR B)(!A AND !B) と等価である。 例: !(linux | darwin)(!linux & !darwin) と等価。

この法則は、複雑な論理式を簡略化したり、その否定を正確に表現したりする際に不可欠です。

技術的詳細

コミットが修正している論理式は !(linux&cgo | darwin&cgo) です。これは、「LinuxかつCgoが有効」または「macOSかつCgoが有効」という条件の全体を否定するものです。

元のドキュメントでは、この式の否定が !linux | !darwin | !cgo と誤って記述されていました。 この誤りを修正するために、ド・モルガンの法則を段階的に適用します。

  1. 元の式: !( (linux & cgo) | (darwin & cgo) ) ここで、A = (linux & cgo)B = (darwin & cgo) とします。 式は !(A | B) の形になります。

  2. ド・モルガンの法則 (2番目) を適用: !(A | B)(!A & !B) と等価です。 したがって、!(linux & cgo) & !(darwin & cgo) となります。

  3. 各項にド・モルガンの法則 (1番目) を適用:

    • !(linux & cgo)(!linux | !cgo) と等価。
    • !(darwin & cgo)(!darwin | !cgo) と等価。
  4. 結合: これらを結合すると、(!linux | !cgo) & (!darwin | !cgo) となります。 これがコミットメッセージの2行目の式です。

  5. 分配法則による簡略化: (!linux | !cgo) & (!darwin | !cgo) を展開します。 これは X & Y の形であり、X = (!linux | !cgo)Y = (!darwin | !cgo) です。 X & Y = X&Y (!linux | !cgo) & (!darwin | !cgo) = (!linux & !darwin) | (!linux & !cgo) | (!cgo & !darwin) | (!cgo & !cgo) = (!linux & !darwin) | (!linux & !cgo) | (!cgo & !darwin) | !cgo

    ここで、(!linux & !cgo)(!cgo & !darwin)!cgo を含んでいるため、!cgo が真であればこれらの項も真になります。ブール論理の吸収律 A | (A & B) = A を考えると、!cgo が存在する場合、(!linux & !cgo)(!cgo & !darwin)!cgo に吸収されます。 したがって、最終的に (!linux & !darwin) | !cgo と簡略化されます。 これがコミットメッセージの3行目の式であり、新しいコメントで「new comment」と示されている正しい論理式です。

誤っていた !linux | !darwin | !cgo は、元の式 !(linux&cgo | darwin&cgo) とは異なる意味を持ちます。例えば、linux=true, darwin=false, cgo=true の場合を考えます。

  • 元の式: !(true&true | false&true) = !(true | false) = !true = false
  • 誤った式: !true | !false | !true = false | true | false = true 結果が異なるため、元のドキュメントの記述が誤っていたことがわかります。

この修正は、Goのビルドシステムが特定の条件を満たさないファイルを正確に除外するために、ドキュメントが正しい論理的根拠を提供することの重要性を示しています。

コアとなるコードの変更箇所

変更は src/pkg/go/build/doc.go ファイルの100行目と101行目です。

--- a/src/pkg/go/build/doc.go
+++ b/src/pkg/go/build/doc.go
@@ -100,7 +100,7 @@
 // default functionality for other systems, which in this case would
 // carry the constraint:
 //
-//	// +build !linux !darwin !cgo
+//	// +build !linux,!darwin !cgo
 //
 // Naming a file dns_windows.go will cause it to be included only when
 // building the package for Windows; similarly, math_386.s will be included

コアとなるコードの解説

変更された行は、Goのビルドタグの例を示しているドキュメントコメントの一部です。

変更前: // +build !linux !darwin !cgo

この行は、!linux (Linuxではない) OR !darwin (macOSではない) OR !cgo (Cgoではない) という論理OR条件を表しています。これは、前述の技術的詳細で説明したように、!(linux&cgo | darwin&cgo) の正しい否定ではありませんでした。Goのビルドタグの構文では、スペースで区切られたタグは論理ORとして扱われます。

変更後: // +build !linux,!darwin !cgo

この行は、(!linux AND !darwin) OR !cgo という論理条件を表しています。

  • !linux,!darwin: カンマで区切られているため、!linux!darwin の両方が真(LinuxでもmacOSでもない)という論理AND条件になります。
  • !cgo: これは独立したタググループであり、前のグループとスペースで区切られているため、論理OR条件になります。

したがって、変更後の行は「LinuxでもmacOSでもない」または「Cgoが有効でない」という条件を正確に表現しており、これは !(linux&cgo | darwin&cgo) の正しい簡略化された否定形 (!linux&!darwin) | !cgo に対応します。

この修正は、単なるコメントの変更ですが、Goのビルドタグの動作に関する公式ドキュメントの正確性を保証する上で非常に重要です。開発者がこのドキュメントを参照する際に、誤った論理式に基づいてビルドタグを記述してしまうリスクを排除します。

関連リンク

参考にした情報源リンク