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

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

このコミットは、Go言語のビルドシステムにおけるビルドタグ(+build ディレクティブ)の適用範囲を拡張し、特定のファイルが特定の環境(OSなど)でのみコンパイルされるように制御する変更を導入しています。これにより、クロスプラットフォーム開発におけるコードの管理とビルドの効率性が向上します。

コミット

commit fd1f10966d5a3b87d051d92cd854dff8484e19c5
Author: Russ Cox <rsc@golang.org>
Date:   Thu Dec 15 13:35:59 2011 -0500

    more tags for go/build
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/5490047

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

https://github.com/golang/go/commit/fd1f10966d5a3b87d051d92cd854dff8484e19c5

元コミット内容

このコミットの元の内容は、「go/build のためのより多くのタグ」と簡潔に記述されています。これは、Goのビルドシステムがファイルをコンパイルする際に使用する条件付きコンパイルタグ(ビルドタグ)の適用を拡大したことを示唆しています。具体的には、Goソースファイルの先頭に// +build <tag>形式のコメントを追加し、特定のOS(LinuxやWindows)に特化したコードや、ビルドプロセスから除外すべきファイルを明示しています。

変更の背景

Go言語はクロスプラットフォーム開発を強力にサポートしていますが、特定のOSに依存する機能やAPIを使用する必要がある場合、そのコードが他のOSで誤ってコンパイルされないように制御する必要があります。このコミットの背景には、Goの標準ライブラリや実験的なパッケージにおいて、OS固有のコード(例: Windowsのファイルシステム通知やGUI関連のコード、Linuxのターミナル関連のコード)を適切に分離し、必要な環境でのみビルドされるようにするための仕組みを強化する目的があります。

また、godocのようなツールの一部ファイルが、特定のビルド環境(例: Google App Engine)でのみ使用されることを意図している場合、通常のビルドプロセスから除外する必要がありました。このコミットは、これらの要件を満たすために、Goのビルドタグをより広範に適用することで、ビルドの正確性と効率性を向上させています。

前提知識の解説

Goのビルドタグ(Build Constraints)

Go言語には、ソースファイルのコンパイルを条件付きで行うための「ビルド制約(Build Constraints)」または「ビルドタグ(Build Tags)」と呼ばれるメカニズムがあります。これは、Goソースファイルの先頭に// +build <tag>形式のコメントを記述することで機能します。

  • 構文: // +build <tag1> <tag2> ...
    • 複数のタグはスペースで区切られます。
    • タグは論理AND (tag1 && tag2) または論理OR (tag1 || tag2) で結合できます。
      • // +build linux darwinlinux || darwin を意味し、LinuxまたはmacOSでビルドされます。
      • // +build linux,amd64linux && amd64 を意味し、LinuxかつAMD64アーキテクチャでビルドされます。
  • 動作: go build コマンドは、ビルド時に指定された環境(OS、アーキテクチャなど)や、コマンドラインで指定されたカスタムタグに基づいて、どのファイルをコンパイルに含めるかを決定します。
  • 一般的なタグ:
    • OS名: linux, windows, darwin (macOS), freebsd, android, ios など
    • アーキテクチャ名: amd64, arm, arm64, 386 など
    • ignore: このタグが指定されたファイルは、常にビルドプロセスから除外されます。これは、テストファイルや特定の環境でのみ使用されるべきではないファイルに便利です。
  • 目的:
    • クロスプラットフォーム対応: OSやアーキテクチャに依存するコードを分離し、適切な環境でのみコンパイルされるようにする。
    • 条件付きコンパイル: 特定の機能やデバッグコードを、特定のビルド条件下でのみ含める。
    • テストの除外: テストファイルやベンチマークファイルを通常のビルドから除外する(通常はファイル名規則で対応されるが、ignoreタグも使用可能)。

mksyscall_windows.pl

mksyscall_windows.plは、Go言語の内部ツールであり、Windows APIのシステムコールをGoのコードから呼び出すためのラッパーコードを自動生成するPerlスクリプトです。Windowsのシステムプログラミングでは、C言語のヘッダーファイルで定義された関数や構造体をGoから利用するために、Goのsyscallパッケージを通じて低レベルなインターフェースを提供する必要があります。このスクリプトは、winapi.goのようなGoのソースファイルに記述されたWindows APIの定義を読み込み、それに対応するGoの関数呼び出しコード(通常はzwinapi.goのようなファイルに生成される)を生成します。

技術的詳細

このコミットは、Goのビルドタグを既存のGoソースファイルに適用し、さらにMakefileのビルドプロセスにも組み込むことで、Goプロジェクトのビルドの堅牢性を高めています。

  1. Goソースファイルへのビルドタグの追加:

    • src/cmd/godoc/appinit.go// +build ignore が追加されました。これは、appinit.goが通常のgodocのビルドプロセスではコンパイルされず、Google App Engineのような特定の環境でのみ使用されることを意図しているためです。ignoreタグは、そのファイルがGoのビルドシステムによって完全に無視されることを保証します。
    • src/pkg/exp/terminal/ 以下のファイル (terminal.go, terminal_test.go, util.go) に // +build linux が追加されました。これは、これらのファイルがLinuxシステムに特化したターミナル関連の機能を提供するため、Linux環境でのみコンパイルされるべきであることを示しています。
    • src/pkg/exp/winfsnotify/ 以下のファイル (winfsnotify.go, winfsnotify_test.go) に // +build windows が追加されました。これは、これらのファイルがWindowsのファイルシステム通知機能に特化しているため、Windows環境でのみコンパイルされるべきであることを示しています。
    • src/pkg/exp/wingui/ 以下のファイル (gui.go, winapi.go, zwinapi.go) に // +build windows が追加されました。これらはWindowsのGUI関連の機能を提供するため、Windows環境でのみコンパイルされるべきです。
  2. Makefileにおけるビルドタグの動的な追加:

    • src/pkg/exp/wingui/Makefile の変更は特に重要です。zwinapi.goファイルは、mksyscall_windows.plスクリプトによってwinapi.goから自動生成されます。このコミットでは、mksyscall_windows.plの出力に// +build windowsという行を先頭に追加するようにMakefileのコマンドが変更されました。
    • 変更前:
      zwinapi.go: winapi.go
      	$(GOROOT)/src/pkg/syscall/mksyscall_windows.pl $< \
      		| gofmt \
      		> $@
      
    • 変更後:
      zwinapi.go: winapi.go
      	(echo '// +build windows'; \
      	$(GOROOT)/src/pkg/syscall/mksyscall_windows.pl $<) \
      		| gofmt \
      		> $@
      
    • この変更により、zwinapi.goが生成されるたびに、そのファイルの先頭に// +build windowsディレクティブが自動的に挿入されるようになります。これにより、zwinapi.goも他のWindows固有のファイルと同様に、Windows環境でのみコンパイルされることが保証されます。これは、自動生成されるファイルに対してもビルド制約を適用するための洗練された方法です。

これらの変更は、Goのビルドシステムが、特定のOSや目的のために設計されたコードを、他の環境でのビルドから自動的に除外できるようにすることで、ビルドエラーの削減、ビルド時間の短縮、およびコードベースの明確な分離に貢献します。

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

このコミットにおけるコアとなるコードの変更は、主にGoソースファイルの先頭行へのビルドタグの追加と、Makefileにおける自動生成ファイルへのビルドタグの挿入ロジックの変更です。

src/cmd/godoc/appinit.go

--- a/src/cmd/godoc/appinit.go
+++ b/src/cmd/godoc/appinit.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build ignore
+
 package main
 
 // This file replaces main.go when running godoc under app-engine.

src/pkg/exp/terminal/terminal.go (および terminal_test.go, util.go も同様)

--- a/src/pkg/exp/terminal/terminal.go
+++ b/src/pkg/exp/terminal/terminal.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build linux
+
 package terminal
 
 import "io"

src/pkg/exp/winfsnotify/winfsnotify.go (および winfsnotify_test.go も同様)

--- a/src/pkg/exp/winfsnotify/winfsnotify.go
+++ b/src/pkg/exp/winfsnotify/winfsnotify.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build windows
+
 // Package winfsnotify allows the user to receive
 // file system event notifications on Windows.
 package winfsnotify

src/pkg/exp/wingui/Makefile

--- a/src/pkg/exp/wingui/Makefile
+++ b/src/pkg/exp/wingui/Makefile
@@ -18,6 +18,7 @@ GOFILES=\
 include ../../../Make.cmd
 
 zwinapi.go: winapi.go
-\t$(GOROOT)/src/pkg/syscall/mksyscall_windows.pl $< \\\
+\t(echo '// +build windows'; \\\
+\t$(GOROOT)/src/pkg/syscall/mksyscall_windows.pl $<) \\\
 \t\t| gofmt \\\
 \t\t> $@

src/pkg/exp/wingui/gui.go (および winapi.go, zwinapi.go も同様)

--- a/src/pkg/exp/wingui/gui.go
+++ b/src/pkg/exp/wingui/gui.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build windows
+
 package main
 
 import (

コアとなるコードの解説

Goソースファイルへのビルドタグ追加

各Goソースファイルの先頭に// +build <tag>形式のコメント行が追加されています。この行はGoのビルドシステムによって特別に解釈され、そのファイルがどのビルド条件下でコンパイルされるべきかを指示します。

  • // +build ignore: src/cmd/godoc/appinit.go に追加されたこのタグは、このファイルがGoの通常のビルドプロセスから完全に除外されることを意味します。これは、特定の環境(例: Google App Engine)でのみ使用される特殊なエントリポイントファイルであるため、一般的なビルドでは不要であり、コンパイルエラーや不要な依存関係を避けるために除外されます。
  • // +build linux: src/pkg/exp/terminal/ 以下のファイルに追加されたこのタグは、これらのファイルがLinuxオペレーティングシステムでのみコンパイルされるべきであることを示します。これは、ターミナル操作に関連する機能がOSに依存するため、Linux以外のシステムではコンパイルされないようにするためです。
  • // +build windows: src/pkg/exp/winfsnotify/ および src/pkg/exp/wingui/ 以下のファイルに追加されたこのタグは、これらのファイルがWindowsオペレーティングシステムでのみコンパイルされるべきであることを示します。これらはそれぞれWindowsのファイルシステム通知機能とGUI機能に特化しており、Windows以外のシステムではコンパイルされるべきではありません。

これらのタグの追加により、go buildコマンドは、現在のOS環境に基づいて適切なファイルセットのみを選択的にコンパイルするようになります。例えば、Linux環境でビルドする場合、+build windowsタグを持つファイルは無視され、+build linuxタグを持つファイルのみが考慮されます。

Makefileにおけるビルドタグの動的な挿入

src/pkg/exp/wingui/Makefileの変更は、自動生成されるGoソースファイル(zwinapi.go)に対してもビルドタグを適用するための巧妙な方法です。

zwinapi.goは、mksyscall_windows.plスクリプトがwinapi.goを処理して生成するファイルです。変更前のMakefileでは、スクリプトの出力が直接zwinapi.goにリダイレクトされていました。

変更後では、echo '// +build windows';というコマンドが追加され、その出力がmksyscall_windows.plの出力とパイプ(|)で結合され、最終的にgofmtを通してzwinapi.goに書き込まれます。

  • (echo '// +build windows'; ...): この部分が新しい変更の核心です。echoコマンドによって文字列// +build windowsが出力され、セミコロン(;)で区切られた次のコマンド(mksyscall_windows.plの実行)の出力と結合されます。これにより、mksyscall_windows.plが生成するGoコードの先頭に// +build windowsという行が挿入されることが保証されます。
  • | gofmt > $@: 結合された出力はgofmtによって整形され、最終的にzwinapi.goファイル($@はターゲットファイル名)に書き込まれます。

このMakefileの変更により、zwinapi.goが再生成されるたびに、そのファイルがWindows固有のコードであることを示すビルドタグが自動的に付与されるようになります。これにより、手動でタグを追加する手間が省け、ビルドプロセスの自動化と正確性が向上します。

全体として、このコミットはGoのビルドシステムをより効果的に活用し、クロスプラットフォーム開発におけるコードの分離と管理を改善するための重要なステップです。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語のソースコードリポジトリ
  • Gitのコミット履歴と差分表示
  • Makefileの一般的な構文と機能
  • Perlスクリプトの基本的な動作
  • Go言語におけるクロスコンパイルと条件付きコンパイルに関する一般的な知識