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

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

このコミットは、Go言語の初期開発段階において、src/lib/lang/ ディレクトリに Makefile を追加するものです。この Makefile は、gobuild ツールによって自動生成されることを意図しており、token パッケージと scanner パッケージのビルド、テスト、インストールに関するルールを定義しています。

コミット

commit bd4f5af1073bb36948047909aed9501f7bec2db9
Author: Robert Griesemer <gri@golang.org>
Date:   Wed Mar 4 17:16:58 2009 -0800

    - missing makefile
    
    R=r
    OCL=25714
    CL=25714

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

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

元コミット内容

このコミットの元々の内容は、src/lib/lang/ ディレクトリに不足していた Makefile を追加することです。コミットメッセージは非常に簡潔で、「- missing makefile」とだけ記されています。これは、このディレクトリのビルドプロセスを確立するために、このファイルが不可欠であったことを示唆しています。

変更の背景

Go言語の初期段階では、現在の go build コマンドのような統合されたビルドシステムはまだ存在していませんでした。代わりに、各パッケージやコンポーネントは Makefile を使用してビルドされていました。このコミットは、src/lib/lang ディレクトリ、特に token および scanner パッケージが適切にビルドされるようにするために、必要な Makefile を追加するものです。

Makefile のコメントには「DO NOT EDIT. Automatically generated by gobuild. gobuild -m >Makefile」とあり、これは gobuild というツールが Makefile を生成していたことを示しています。これは、Goのビルドシステムが進化する過程で、自動化された Makefile 生成が一時的に採用されていたことを示唆しています。

前提知識の解説

MakefileとMake

Makefile は、make ユーティリティがプログラムのコンパイルやその他のタスクを自動化するために使用するファイルです。make は、ファイルの依存関係を追跡し、変更されたファイルのみを再ビルドすることで、ビルドプロセスを効率化します。Makefile には、ターゲット(生成されるファイルや実行されるアクション)、依存関係(ターゲットを生成するために必要なファイル)、およびコマンド(ターゲットを生成するためのシェルコマンド)が記述されます。

Go言語の初期ビルドシステム

Go言語の初期は、現在の go コマンドのような統一されたツールチェインが確立されていませんでした。代わりに、C言語のコンパイラ(6g, 6c, 6a など、アーキテクチャを示す数字がプレフィックスとして付く)や、カスタムのビルドスクリプト、そして Makefile が使用されていました。この時期のGoのビルドは、C言語のプロジェクトのビルドプロセスに似ていました。

gobuild ツール

Makefile のコメントに登場する gobuild は、Go言語の初期に存在したビルドツールの一つと考えられます。これは、Goのソースコードから Makefile を自動生成する役割を担っていたようです。現在の go build コマンドがGoのビルドプロセスを完全に抽象化しているのに対し、gobuild はより低レベルな Makefile の生成を通じてビルドを管理していました。

token および scanner パッケージ

Go言語のコンパイラやツールにおいて、token パッケージと scanner パッケージは非常に基本的な役割を担っています。

  • token パッケージ: ソースコードを構成する最小単位である「トークン」(キーワード、識別子、演算子など)を定義します。
  • scanner パッケージ: ソースコードの文字列を読み込み、それをトークンのストリームに変換する字句解析器(lexer)を提供します。これはコンパイラの最初のフェーズであり、後続の構文解析(parser)の入力となります。

これらのパッケージは、Go言語のコンパイラや他のツールがGoのソースコードを理解し、処理するために不可欠な基盤コンポーネントです。

技術的詳細

この Makefile は、Go言語の初期のビルドプロセスにおける重要な側面を示しています。

  1. コンパイラとツールの指定:

    • O=6: これは、当時のGoのツールチェインが特定のアーキテクチャ(おそらく32-bit x86)をターゲットにしていたことを示唆しています。6g (Goコンパイラ), 6c (Cコンパイラ), 6a (アセンブラ), 6ar (アーカイバ) といったツールが使用されています。
    • GC=$(O)g, CC=$(O)c -w, AS=$(O)a, AR=$(O)ar: これらの変数は、Goのコンパイラ、Cコンパイラ、アセンブラ、アーカイバへのパスを定義しています。-w フラグはCコンパイラの警告を抑制しています。
  2. ビルドルール:

    • %.$O: %.go: Goソースファイル (.go) をGoオブジェクトファイル (.$O) にコンパイルするルール。$(GC) (Goコンパイラ) が使用されます。
    • %.$O: %.c: Cソースファイル (.c) をGoオブジェクトファイル (.$O) にコンパイルするルール。$(CC) (Cコンパイラ) が使用されます。
    • %.$O: %.s: アセンブリソースファイル (.s) をGoオブジェクトファイル (.$O) にアセンブルするルール。$(AS) (アセンブラ) が使用されます。
  3. パッケージの定義とビルド:

    • O1O2 変数で、token パッケージと scanner パッケージを構成するオブジェクトファイルが定義されています。
    • token.ascanner.a は、それぞれ token パッケージと scanner パッケージのアーカイブファイル(ライブラリ)です。
    • a1a2 ターゲットは、それぞれのパッケージのオブジェクトファイルをコンパイルし、$(AR) grc コマンド(Goのアーカイバ)を使ってアーカイブファイルを作成しています。grcg (Goアーカイブ), r (置換), c (作成) のオプションを意味します。
  4. クリーンアップとテスト:

    • clean ターゲットは、ビルドによって生成された中間ファイルや最終ファイルを削除します。
    • test ターゲットは、gotest コマンドを実行してテストを行います。
    • coverage ターゲットは、gotest の後に 6cov コマンドを実行してカバレッジ情報を生成します。
  5. インストール:

    • install ターゲットは、ビルドされた scanner.atoken.a$(GOROOT)/pkg/ ディレクトリにコピーします。これは、他のGoプロジェクトがこれらのパッケージをインポートして使用できるようにするためです。

この Makefile は、Go言語の初期のビルドプロセスが、C言語のビルドシステムと類似したアプローチを採用していたことを明確に示しています。各パッケージが個別の Makefile を持ち、それらが依存関係に基づいてビルドされるという、より分散されたビルドモデルでした。

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

このコミットは、src/lib/lang/Makefile という新しいファイルを追加するものです。変更はすべて追加行であり、既存のファイルの変更はありません。

--- /dev/null
+++ b/src/lib/lang/Makefile
@@ -0,0 +1,66 @@
+# Copyright 2009 The Go Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# DO NOT EDIT.  Automatically generated by gobuild.
+# gobuild -m >Makefile
+O=6
+GC=$(O)g
+CC=$(O)c -w
+AS=$(O)a
+AR=$(O)ar
+
+default: packages
+
+clean:
+	rm -f *.$O *.a $O.out
+
+test: packages
+	gotest
+
+coverage: packages
+	gotest
+	6cov -g `pwd` | grep -v '_test\\.go:'
+
+%.$O: %.go
+	$(GC) $*.go
+
+%.$O: %.c
+	$(CC) $*.c
+
+%.$O: %.s
+	$(AS) $*.s
+
+O1=\
+	token.$O\
+
+O2=\
+	scanner.$O\
+
+scanner.a: a1 a2
+token.a: a1 a2
+
+a1:	$(O1)
+	$(AR) grc token.a token.$O
+	rm -f $(O1)
+
+a2:	$(O2)
+	$(AR) grc scanner.a scanner.$O
+	rm -f $(O2)
+
+newpkg: clean
+	$(AR) grc scanner.a
+	$(AR) grc token.a
+
+$(O1): newpkg
+$(O2): a1
+
+nuke: clean
+	rm -f $(GOROOT)/pkg/scanner.a $(GOROOT)/pkg/token.a
+
+packages: scanner.a token.a
+
+install: packages
+	cp scanner.a $(GOROOT)/pkg/scanner.a
+	cp token.a $(GOROOT)/pkg/token.a

コアとなるコードの解説

この Makefile は、token および scanner パッケージのビルドプロセスを定義しています。

  • ヘッダー: Go Authorsの著作権表示と、BSDスタイルのライセンスに関する記述があります。また、「DO NOT EDIT. Automatically generated by gobuild. gobuild -m >Makefile」というコメントがあり、このファイルが gobuild ツールによって自動生成されたものであることを示しています。
  • 変数定義:
    • O=6: ビルドターゲットのアーキテクチャ(例: 6 for 32-bit x86)を示します。
    • GC, CC, AS, AR: それぞれGoコンパイラ、Cコンパイラ、アセンブラ、アーカイバのコマンドを定義しています。これらは O の値に基づいて 6g, 6c, 6a, 6ar となります。
  • デフォルトターゲット: default: packages は、make コマンドが引数なしで実行された場合に packages ターゲットが実行されることを意味します。
  • クリーンアップターゲット: clean は、ビルドによって生成されたオブジェクトファイル (.O)、アーカイブファイル (.a)、およびその他の出力ファイル ($O.out) を削除します。
  • テストターゲット: testgotest コマンドを実行してテストを実行します。coveragegotest の後に 6cov を実行してコードカバレッジを測定します。
  • 汎用ビルドルール:
    • %.$O: %.go: .go ファイルをGoコンパイラ ($(GC)) でコンパイルして .O ファイルを生成します。
    • %.$O: %.c: .c ファイルをCコンパイラ ($(CC)) でコンパイルして .O ファイルを生成します。
    • %.$O: %.s: .s ファイルをアセンブラ ($(AS)) でアセンブルして .O ファイルを生成します。
  • パッケージオブジェクトファイルリスト:
    • O1: token.$O を含み、token パッケージのオブジェクトファイルを指定します。
    • O2: scanner.$O を含み、scanner パッケージのオブジェクトファイルを指定します。
  • パッケージアーカイブターゲット:
    • scanner.a: a1 a2token.a: a1 a2: これらの行は、scanner.atoken.aa1a2 に依存していることを示していますが、これは論理的に正しくありません。おそらく scanner.aa2 に、token.aa1 に依存するという意図だったと思われます。
    • a1: token パッケージのオブジェクトファイル ($(O1)) をビルドし、それらを token.a というアーカイブファイルにまとめます。その後、中間オブジェクトファイルを削除します。
    • a2: scanner パッケージのオブジェクトファイル ($(O2)) をビルドし、それらを scanner.a というアーカイブファイルにまとめます。その後、中間オブジェクトファイルを削除します。
  • newpkg ターゲット: clean を実行した後、空の scanner.atoken.a を作成します。これは、新しいパッケージのビルドを開始する際の初期化ステップとして機能する可能性があります。
  • 依存関係:
    • $(O1): newpkg: token パッケージのオブジェクトファイルが newpkg に依存していることを示します。
    • $(O2): a1: scanner パッケージのオブジェクトファイルが a1 に依存していることを示します。これは、scannertoken に依存していることを反映している可能性があります。
  • nuke ターゲット: clean を実行した後、$(GOROOT)/pkg/ ディレクトリにある scanner.atoken.a を削除します。これは、システム全体からこれらのパッケージを完全に削除するためのものです。
  • packages ターゲット: scanner.atoken.a をビルドします。これは、このディレクトリ内のすべてのパッケージをビルドするための主要なターゲットです。
  • install ターゲット: ビルドされた scanner.atoken.a$(GOROOT)/pkg/ ディレクトリにコピーします。これにより、これらのパッケージがGoの標準ライブラリの一部として利用可能になります。

この Makefile は、Go言語の初期のビルドシステムが、C言語のプロジェクトで一般的に見られるような、明示的な依存関係とビルドルールを持つ Makefile を使用していたことを示しています。これは、現在の go build コマンドが提供する、より抽象化されたシンプルなビルド体験とは対照的です。

関連リンク

  • Go言語の初期のビルドシステムに関する議論やドキュメントは、Goの公式リポジトリの初期のコミット履歴や、Goのメーリングリストのアーカイブで確認できる可能性があります。
  • make ユーティリティの公式ドキュメント: https://www.gnu.org/software/make/manual/

参考にした情報源リンク

  • Go言語の公式リポジトリ (GitHub): https://github.com/golang/go
  • make ユーティリティに関する一般的な知識
  • Go言語の初期のビルドプロセスに関する歴史的情報(Web検索を通じて得られる可能性のある情報)
  • Go言語の token および scanner パッケージに関する一般的な知識
  • Go言語の初期のツールチェインに関する情報(6g, 6c, 6a など)