[インデックス 11955] ファイルの概要
このコミットは、Go言語のdebug/gosym
パッケージにおけるテストのビルドプロセスを改善し、従来のMakefileベースのシステムからGo標準のツールチェーンへと移行するものです。具体的には、テスト用のバイナリを生成するために使用されていたMakefileを削除し、Goツール(go tool 6a
とgo tool 6l
)を用いてテストコードを直接ビルドするように変更しています。これにより、Goプロジェクト全体のビルドシステムの一貫性が向上し、依存関係の管理が簡素化されます。
コミット
commit 343059930624b1e5b54fae8a092819db95b40cca
Author: David Symonds <dsymonds@golang.org>
Date: Thu Feb 16 14:47:14 2012 +1100
debug/gosym: Remove Makefile, rewrite test using go tool.
Update #2573.
R=r
CC=golang-dev
https://golang.org/cl/5656071
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/343059930624b1e5b54fae8a092819db95b40cca
元コミット内容
debug/gosym: Remove Makefile, rewrite test using go tool.
このコミットは、debug/gosym
パッケージのテストにおいて、Makefileの使用を廃止し、Goツールを用いたテストの再構築を行うものです。これはIssue #2573の更新に対応しています。
変更の背景
この変更の背景には、Goプロジェクト全体のビルドシステムの一貫性を高めるという目的があります。Go言語は、その設計思想としてシンプルなビルドプロセスを重視しており、go build
やgo test
といったコマンドを通じて、ほとんどのビルド作業を自動化しています。しかし、初期のGoプロジェクトの一部では、C言語のプロジェクトで一般的に使用されるMakefileが残存している箇所がありました。
特に、debug/gosym
パッケージのような低レベルのデバッグ情報を取り扱う部分では、アセンブリコードのコンパイルやリンクといった特殊なビルドステップが必要となる場合があり、そのためにMakefileが利用されていました。しかし、Goツールチェーンが成熟するにつれて、これらの特殊なビルドステップもGoツール自身で処理できるようになりました。
Issue #2573は、まさにこの問題、すなわちGoのテストがGoツールではなくMakefileに依存している点を指摘し、Goツールへの移行を提案していました。このコミットは、その提案に応える形で、debug/gosym
パッケージのテストビルドをGoツールに完全に移行することで、ビルドプロセスの簡素化、可搬性の向上、そしてGoエコシステム全体の一貫性強化を図っています。これにより、開発者はGoの標準的なコマンドだけでテストを実行できるようになり、異なる環境でのビルドの複雑さが軽減されます。
前提知識の解説
このコミットを理解するためには、以下の技術的な概念について理解しておく必要があります。
- Go言語のビルドシステム: Go言語は、
go build
、go run
、go test
といったコマンドを通じて、ソースコードのコンパイル、実行、テストを統合的に管理します。これらのコマンドは、Goのツールチェーン(コンパイラ、リンカ、アセンブラなど)を内部的に呼び出し、依存関係の解決やバイナリの生成を自動的に行います。 - Makefile: Makefileは、主にUnix系システムでソフトウェアのビルドプロセスを自動化するために使用されるツールです。
make
コマンドによって実行され、ファイル間の依存関係を定義し、それらを解決するためのコマンドシーケンス(レシピ)を記述します。C/C++プロジェクトなどで広く利用されています。 debug/gosym
パッケージ: Go言語の標準ライブラリの一部であり、Goバイナリに含まれるシンボルテーブル(symtab
)とプログラムカウンタ-ライン番号テーブル(pclntab
)を解析するための機能を提供します。これらのテーブルは、デバッガが実行中のプログラムのどの部分がソースコードのどの行に対応するかを特定するために使用されます。pclntab
(Program Counter Line Table): Goバイナリに埋め込まれている重要なデータ構造の一つで、プログラムカウンタ(PC)の値と、対応するソースファイルのパス、行番号、関数名などの情報をマッピングします。デバッグ情報やプロファイリングにおいて不可欠な要素です。go tool 6a
とgo tool 6l
: これらはGoの初期のツールチェーンにおけるアセンブラ(6a
)とリンカ(6l
)のコマンドです。6
は64ビットアーキテクチャ(amd64)を指し、a
はアセンブラ、l
はリンカを意味します。これらのツールは、Goのソースコードやアセンブリコードをコンパイルし、実行可能なバイナリにリンクするために使用されます。現代のGoでは、これらの低レベルツールは通常go build
などの高レベルコマンドによって抽象化されており、直接呼び出すことは稀です。- ELF (Executable and Linkable Format): Unix系システムで広く使用されている実行可能ファイル、オブジェクトファイル、共有ライブラリの標準フォーマットです。GoのバイナリもLinux上ではELF形式で生成されます。
debug/elf
パッケージは、GoからELFファイルを解析するための機能を提供します。 os/exec
パッケージ: Goプログラムから外部コマンドを実行するための機能を提供します。このコミットでは、go tool
コマンドを呼び出すために使用されています。
技術的詳細
このコミットの技術的な核心は、debug/gosym
パッケージのテストスイートが、外部のMakefileに依存することなく、Goの標準ツールチェーン(go tool
コマンド)を使用してテスト用のバイナリを生成するように変更された点にあります。
具体的な変更点は以下の通りです。
-
Makefileの削除:
src/pkg/debug/gosym/Makefile
が完全に削除されました。このMakefileは、pclinetest.s
というアセンブリファイルをコンパイルし、_test/pclinetest
というテストバイナリを生成するために使用されていました。- Makefileには、
make-pclinetest
というターゲットがあり、$(AS)
(アセンブラ)と$(LD)
(リンカ)を直接呼び出してバイナリを生成するロジックが含まれていました。この依存関係が解消されたことで、ビルドプロセスがGoツールに一元化されました。
-
アセンブリファイルの名称変更:
src/pkg/debug/gosym/pclinetest.s
がsrc/pkg/debug/gosym/pclinetest.asm
に名称変更されました。- この名称変更は、Goツールが
.s
拡張子を持つファイルをGoのアセンブリファイルとして自動的に認識し、コンパイルしようとする挙動を回避するためのものです。pclinetest.asm
は、Goツールが直接処理するのではなく、os/exec
を通じて明示的にgo tool 6a
でコンパイルされることを意図しています。これにより、Goのビルドシステムがこのファイルを通常のGoアセンブリとして扱わないようにし、テストの特殊なビルドフローを維持しています。
-
pclntab_test.go
の変更:pclntab_test.go
内のdotest()
関数が大幅に修正されました。- テストバイナリの生成ロジックの組み込み: 以前はMakefileに依存していたテストバイナリ(
pclinetest
)の生成が、dotest()
関数内で直接行われるようになりました。 os/exec
の使用:os/exec.Command
を使用して、以下のシェルコマンドが実行されます。go tool 6a pclinetest.asm && go tool 6l -E main -o /tmp/pclinetest pclinetest.6
go tool 6a pclinetest.asm
:pclinetest.asm
をアセンブルし、オブジェクトファイルpclinetest.6
を生成します。go tool 6l -E main -o /tmp/pclinetest pclinetest.6
:pclinetest.6
をリンクし、/tmp/pclinetest
という実行可能バイナリを生成します。-E main
はエントリポイントを指定し、-o
は出力ファイル名を指定します。
- 一時ディレクトリへの出力: 生成されたテストバイナリは、
os.TempDir()
で取得される一時ディレクトリに保存されるようになりました。これにより、テスト実行後の一時ファイルのクリーンアップが容易になります。 - プラットフォームチェックの強化:
runtime.GOOS
とruntime.GOARCH
を使用して、テストがLinux AMD64環境でのみ実行されるように明示的にチェックしています。これは、go tool 6a
やgo tool 6l
が特定のアーキテクチャに特化しているためです。 - ファイルパスのサフィックスチェックの変更:
TestPCLine
関数内で、file
パスのチェックがより柔軟になりました。以前はfile[len(file)-12:] != "pclinetest.s"
という厳密なサフィックスチェックを行っていましたが、!strings.HasSuffix(file, "pclinetest.s")
に変更され、より堅牢なチェックになっています。これは、pclinetest.asm
からビルドされたバイナリが、デバッグ情報上は依然として元の.s
ファイルを参照している可能性があるためです。
これらの変更により、debug/gosym
パッケージのテストは、Goの標準的なテスト実行コマンド(go test
)を通じて、完全にGoツールチェーン内で完結するようになりました。これにより、外部のビルドツールへの依存が解消され、Goプロジェクト全体のビルドとテストの自動化がさらに推進されました。
コアとなるコードの変更箇所
src/pkg/debug/gosym/Makefile
(削除)
--- a/src/pkg/debug/gosym/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.
-
-include ../../../Make.inc
-
-TARG=debug/gosym
-GOFILES=\
- pclntab.go\
- symtab.go\
-
-include ../../../Make.pkg
-
-test: make-pclinetest
-
-testshort: make-pclinetest
-
-make-pclinetest:
- @if [ "`uname`-`uname -m`\" = Linux-x86_64 -a $(GOARCH) = amd64 ]; then mkdir -p _test && $(AS) pclinetest.s && $(LD) -E main -o _test/pclinetest pclinetest.$O; fi
src/pkg/debug/gosym/pclinetest.s
から src/pkg/debug/gosym/pclinetest.asm
への名称変更
--- a/src/pkg/debug/gosym/pclinetest.s
+++ b/src/pkg/debug/gosym/pclinetest.asm
@@ -1,5 +1,3 @@
-// +build ignore
-
TEXT linefrompc(SB),7,$0 // Each byte stores its line delta
BYTE $2;
BYTE $1;
src/pkg/debug/gosym/pclntab_test.go
(変更)
--- a/src/pkg/debug/gosym/pclntab_test.go
+++ b/src/pkg/debug/gosym/pclntab_test.go
@@ -7,14 +7,31 @@ package gosym
import (
"debug/elf"
"os"
+ "os/exec"
"runtime"
+ "strings"
"testing"
)
+var pclinetestBinary string
+
func dotest() bool {
// For now, only works on ELF platforms.
- // TODO: convert to work with new go tool
- return false && runtime.GOOS == "linux" && runtime.GOARCH == "amd64"
+ if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
+ return false
+ }
+ if pclinetestBinary != "" {
+ return true
+ }
+ // This command builds pclinetest from pclinetest.asm;
+ // the resulting binary looks like it was built from pclinetest.s,
+ // but we have renamed it to keep it away from the go tool.
+ pclinetestBinary = os.TempDir() + "/pclinetest"
+ cmd := exec.Command("sh", "-c", "go tool 6a pclinetest.asm && go tool 6l -E main -o "+pclinetestBinary+" pclinetest.6")
+ if err := cmd.Run(); err != nil {
+ panic(err)
+ }
+ return true
}
func getTable(t *testing.T) *Table {
@@ -149,7 +166,7 @@ func TestPCLine(t *testing.T) {
return
}
- f, tab := crack("_test/pclinetest", t)
+ f, tab := crack(pclinetestBinary, t)
text := f.Section(".text")
textdat, err := text.Data()
if err != nil {
@@ -163,10 +180,13 @@ func TestPCLine(t *testing.T) {
file, line, fn := tab.PCToLine(pc)
off := pc - text.Addr // TODO(rsc): should not need off; bug in 8g
wantLine += int(textdat[off])
+ t.Logf("off is %d", off)
if fn == nil {
t.Errorf("failed to get line of PC %#x", pc)
- } else if len(file) < 12 || file[len(file)-12:] != "pclinetest.s" || line != wantLine || fn != sym {
- t.Errorf("expected %s:%d (%s) at PC %#x, got %s:%d (%s)", "pclinetest.s", wantLine, sym.Name, pc, file, line, fn.Name)
+ } else if !strings.HasSuffix(file, "pclinetest.s") {
+ t.Errorf("expected %s (%s) at PC %#x, got %s (%s)", "pclinetest.s", sym.Name, pc, file, fn.Name)
+ } else if line != wantLine || fn != sym {
+ t.Errorf("expected :%d (%s) at PC %#x, got :%d (%s)", wantLine, sym.Name, pc, line, fn.Name)
}
}
コアとなるコードの解説
このコミットのコアとなる変更は、src/pkg/debug/gosym/pclntab_test.go
内のdotest()
関数の実装に集約されています。
-
pclinetestBinary
変数の導入:var pclinetestBinary string
がグローバル変数として追加されました。これは、生成されたテストバイナリのパスをキャッシュするために使用されます。これにより、テストが複数回実行される場合に、毎回バイナリを再ビルドするのを防ぎ、効率を向上させます。
-
プラットフォームチェックの強化:
if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { return false }
- この行は、テストがLinuxオペレーティングシステムとAMD64アーキテクチャでのみ実行されることを保証します。これは、
go tool 6a
とgo tool 6l
が特定のプラットフォームに特化しているため、他の環境での実行を早期に終了させるためのガード句です。
- この行は、テストがLinuxオペレーティングシステムとAMD64アーキテクチャでのみ実行されることを保証します。これは、
-
テストバイナリのビルドロジック:
if pclinetestBinary != "" { return true }
pclinetestBinary
が既に設定されている場合(つまり、バイナリが既にビルドされている場合)、すぐにtrue
を返して再ビルドをスキップします。
pclinetestBinary = os.TempDir() + "/pclinetest"
- テストバイナリの出力パスを、システムの一時ディレクトリ内に設定します。これにより、テスト実行後の一時ファイルの管理が容易になります。
cmd := exec.Command("sh", "-c", "go tool 6a pclinetest.asm && go tool 6l -E main -o "+pclinetestBinary+" pclinetest.6")
- この行が、Makefileを置き換える主要な部分です。
os/exec.Command
を使用してシェルコマンドを実行します。 "sh", "-c", "..."
: シェルを介してコマンドを実行するための標準的な方法です。go tool 6a pclinetest.asm
:pclinetest.asm
というアセンブリファイルをGoのアセンブラ(6a
)でコンパイルし、pclinetest.6
というオブジェクトファイルを生成します。&&
: 前のコマンドが成功した場合にのみ、次のコマンドを実行します。go tool 6l -E main -o "+pclinetestBinary+" pclinetest.6
:pclinetest.6
オブジェクトファイルをGoのリンカ(6l
)でリンクし、pclinetestBinary
で指定されたパスに実行可能バイナリを生成します。-E main
はエントリポイントをmain
関数に設定し、-o
は出力ファイル名を指定します。
- この行が、Makefileを置き換える主要な部分です。
if err := cmd.Run(); err != nil { panic(err) }
- 構築したコマンドを実行し、エラーが発生した場合はパニックを引き起こします。これにより、テストバイナリの生成に失敗した場合にテストが続行されるのを防ぎます。
-
TestPCLine
関数内の変更:f, tab := crack(pclinetestBinary, t)
- 以前はハードコードされたパス
"_test/pclinetest"
を使用していた箇所が、pclinetestBinary
変数を使用するように変更されました。これにより、動的に生成されたバイナリのパスが正しく参照されるようになります。
- 以前はハードコードされたパス
!strings.HasSuffix(file, "pclinetest.s")
- デバッグ情報から取得したファイルパスのサフィックスチェックが、より柔軟な
strings.HasSuffix
を使用するように変更されました。これは、pclinetest.asm
からビルドされたバイナリのデバッグ情報が、元の.s
拡張子を参照している可能性があるため、より堅牢なチェックが必要とされたためです。
- デバッグ情報から取得したファイルパスのサフィックスチェックが、より柔軟な
これらの変更により、debug/gosym
パッケージのテストは、Goの標準的なツールチェーンに完全に統合され、外部のビルドシステムへの依存が解消されました。
関連リンク
- Go言語の公式ドキュメント: https://golang.org/doc/
- Goの
debug/gosym
パッケージ: https://pkg.go.dev/debug/gosym - Goの
os/exec
パッケージ: https://pkg.go.dev/os/exec - GoのIssue #2573:
cmd/go: make go test work for all packages
(このコミットが解決したIssue) - 検索しても直接的なリンクは見つかりませんでしたが、GoのIssueトラッカーで検索すると関連情報が見つかる可能性があります。
参考にした情報源リンク
- Go言語のソースコード (GitHub): https://github.com/golang/go
- Goのコードレビューシステム (Gerrit): https://golang.org/cl/5656071 (コミットメッセージに記載されているChange-ID)
- ELFファイルフォーマットに関する一般的な情報 (Wikipediaなど): https://ja.wikipedia.org/wiki/Executable_and_Linkable_Format
- Makefileに関する一般的な情報 (GNU Makeマニュアルなど): https://www.gnu.org/software/make/manual/
- Goの
go tool
コマンドに関する情報 (Goのドキュメントやブログ記事):go tool
は内部ツールであり、公式ドキュメントには詳細な説明がない場合がありますが、Goのソースコードや関連するブログ記事でその使用法が解説されていることがあります。# [インデックス 11955] ファイルの概要
このコミットは、Go言語のdebug/gosym
パッケージにおけるテストのビルドプロセスを改善し、従来のMakefileベースのシステムからGo標準のツールチェーンへと移行するものです。具体的には、テスト用のバイナリを生成するために使用されていたMakefileを削除し、Goツール(go tool 6a
とgo tool 6l
)を用いてテストコードを直接ビルドするように変更しています。これにより、Goプロジェクト全体のビルドシステムの一貫性が向上し、依存関係の管理が簡素化されます。
コミット
commit 343059930624b1e5b54fae8a092819db95b40cca
Author: David Symonds <dsymonds@golang.org>
Date: Thu Feb 16 14:47:14 2012 +1100
debug/gosym: Remove Makefile, rewrite test using go tool.
Update #2573.
R=r
CC=golang-dev
https://golang.org/cl/5656071
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/343059930624b1e5b54fae8a092819db95b40cca
元コミット内容
debug/gosym: Remove Makefile, rewrite test using go tool.
このコミットは、debug/gosym
パッケージのテストにおいて、Makefileの使用を廃止し、Goツールを用いたテストの再構築を行うものです。これはIssue #2573の更新に対応しています。
変更の背景
この変更の背景には、Goプロジェクト全体のビルドシステムの一貫性を高めるという目的があります。Go言語は、その設計思想としてシンプルなビルドプロセスを重視しており、go build
やgo test
といったコマンドを通じて、ほとんどのビルド作業を自動化しています。しかし、初期のGoプロジェクトの一部では、C言語のプロジェクトで一般的に使用されるMakefileが残存している箇所がありました。
特に、debug/gosym
パッケージのような低レベルのデバッグ情報を取り扱う部分では、アセンブリコードのコンパイルやリンクといった特殊なビルドステップが必要となる場合があり、そのためにMakefileが利用されていました。しかし、Goツールチェーンが成熟するにつれて、これらの特殊なビルドステップもGoツール自身で処理できるようになりました。
Issue #2573は、まさにこの問題、すなわちGoのテストがGoツールではなくMakefileに依存している点を指摘し、Goツールへの移行を提案していました。このコミットは、その提案に応える形で、debug/gosym
パッケージのテストビルドをGoツールに完全に移行することで、ビルドプロセスの簡素化、可搬性の向上、そしてGoエコシステム全体の一貫性強化を図っています。これにより、開発者はGoの標準的なコマンドだけでテストを実行できるようになり、異なる環境でのビルドの複雑さが軽減されます。
前提知識の解説
このコミットを理解するためには、以下の技術的な概念について理解しておく必要があります。
- Go言語のビルドシステム: Go言語は、
go build
、go run
、go test
といったコマンドを通じて、ソースコードのコンパイル、実行、テストを統合的に管理します。これらのコマンドは、Goのツールチェーン(コンパイラ、リンカ、アセンブラなど)を内部的に呼び出し、依存関係の解決やバイナリの生成を自動的に行います。 - Makefile: Makefileは、主にUnix系システムでソフトウェアのビルドプロセスを自動化するために使用されるツールです。
make
コマンドによって実行され、ファイル間の依存関係を定義し、それらを解決するためのコマンドシーケンス(レシピ)を記述します。C/C++プロジェクトなどで広く利用されています。 debug/gosym
パッケージ: Go言語の標準ライブラリの一部であり、Goバイナリに含まれるシンボルテーブル(symtab
)とプログラムカウンタ-ライン番号テーブル(pclntab
)を解析するための機能を提供します。これらのテーブルは、デバッガが実行中のプログラムのどの部分がソースコードのどの行に対応するかを特定するために使用されます。pclntab
(Program Counter Line Table): Goバイナリに埋め込まれている重要なデータ構造の一つで、プログラムカウンタ(PC)の値と、対応するソースファイルのパス、行番号、関数名などの情報をマッピングします。デバッグ情報やプロファイリングにおいて不可欠な要素です。go tool 6a
とgo tool 6l
: これらはGoの初期のツールチェーンにおけるアセンブラ(6a
)とリンカ(6l
)のコマンドです。6
は64ビットアーキテクチャ(amd64)を指し、a
はアセンブラ、l
はリンカを意味します。これらのツールは、Goのソースコードやアセンブリコードをコンパイルし、実行可能なバイナリにリンクするために使用されます。現代のGoでは、これらの低レベルツールは通常go build
などの高レベルコマンドによって抽象化されており、直接呼び出すことは稀です。- ELF (Executable and Linkable Format): Unix系システムで広く使用されている実行可能ファイル、オブジェクトファイル、共有ライブラリの標準フォーマットです。GoのバイナリもLinux上ではELF形式で生成されます。
debug/elf
パッケージは、GoからELFファイルを解析するための機能を提供します。 os/exec
パッケージ: Goプログラムから外部コマンドを実行するための機能を提供します。このコミットでは、go tool
コマンドを呼び出すために使用されています。
技術的詳細
このコミットの技術的な核心は、debug/gosym
パッケージのテストスイートが、外部のMakefileに依存することなく、Goの標準ツールチェーン(go tool
コマンド)を使用してテスト用のバイナリを生成するように変更された点にあります。
具体的な変更点は以下の通りです。
-
Makefileの削除:
src/pkg/debug/gosym/Makefile
が完全に削除されました。このMakefileは、pclinetest.s
というアセンブリファイルをコンパイルし、_test/pclinetest
というテストバイナリを生成するために使用されていました。- Makefileには、
make-pclinetest
というターゲットがあり、$(AS)
(アセンブラ)と$(LD)
(リンカ)を直接呼び出してバイナリを生成するロジックが含まれていました。この依存関係が解消されたことで、ビルドプロセスがGoツールに一元化されました。
-
アセンブリファイルの名称変更:
src/pkg/debug/gosym/pclinetest.s
がsrc/pkg/debug/gosym/pclinetest.asm
に名称変更されました。- この名称変更は、Goツールが
.s
拡張子を持つファイルをGoのアセンブリファイルとして自動的に認識し、コンパイルしようとする挙動を回避するためのものです。pclinetest.asm
は、Goツールが直接処理するのではなく、os/exec
を通じて明示的にgo tool 6a
でコンパイルされることを意図しています。これにより、Goのビルドシステムがこのファイルを通常のGoアセンブリとして扱わないようにし、テストの特殊なビルドフローを維持しています。
-
pclntab_test.go
の変更:pclntab_test.go
内のdotest()
関数が大幅に修正されました。- テストバイナリの生成ロジックの組み込み: 以前はMakefileに依存していたテストバイナリ(
pclinetest
)の生成が、dotest()
関数内で直接行われるようになりました。 os/exec
の使用:os/exec.Command
を使用して、以下のシェルコマンドが実行されます。go tool 6a pclinetest.asm && go tool 6l -E main -o /tmp/pclinetest pclinetest.6
go tool 6a pclinetest.asm
:pclinetest.asm
をアセンブルし、オブジェクトファイルpclinetest.6
を生成します。&&
: 前のコマンドが成功した場合にのみ、次のコマンドを実行します。go tool 6l -E main -o /tmp/pclinetest pclinetest.6
:pclinetest.6
をリンクし、/tmp/pclinetest
という実行可能バイナリを生成します。-E main
はエントリポイントを指定し、-o
は出力ファイル名を指定します。
- 一時ディレクトリへの出力: 生成されたテストバイナリは、
os.TempDir()
で取得される一時ディレクトリに保存されるようになりました。これにより、テスト実行後の一時ファイルのクリーンアップが容易になります。 - プラットフォームチェックの強化:
runtime.GOOS
とruntime.GOARCH
を使用して、テストがLinux AMD64環境でのみ実行されるように明示的にチェックしています。これは、go tool 6a
やgo tool 6l
が特定のアーキテクチャに特化しているためです。 - ファイルパスのサフィックスチェックの変更:
TestPCLine
関数内で、file
パスのチェックがより柔軟になりました。以前はfile[len(file)-12:] != "pclinetest.s"
という厳密なサフィックスチェックを行っていましたが、!strings.HasSuffix(file, "pclinetest.s")
に変更され、より堅牢なチェックになっています。これは、pclinetest.asm
からビルドされたバイナリが、デバッグ情報上は依然として元の.s
ファイルを参照している可能性があるためです。
これらの変更により、debug/gosym
パッケージのテストは、Goの標準的なテスト実行コマンド(go test
)を通じて、完全にGoツールチェーン内で完結するようになりました。これにより、外部のビルドツールへの依存が解消され、Goプロジェクト全体のビルドとテストの自動化がさらに推進されました。
コアとなるコードの変更箇所
src/pkg/debug/gosym/Makefile
(削除)
--- a/src/pkg/debug/gosym/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.
-
-include ../../../Make.inc
-
-TARG=debug/gosym
-GOFILES=\
- pclntab.go\
- symtab.go\
-
-include ../../../Make.pkg
-
-test: make-pclinetest
-
-testshort: make-pclinetest
-
-make-pclinetest:
- @if [ "`uname`-`uname -m`\" = Linux-x86_64 -a $(GOARCH) = amd64 ]; then mkdir -p _test && $(AS) pclinetest.s && $(LD) -E main -o _test/pclinetest pclinetest.$O; fi
src/pkg/debug/gosym/pclinetest.s
から src/pkg/debug/gosym/pclinetest.asm
への名称変更
--- a/src/pkg/debug/gosym/pclinetest.s
+++ b/src/pkg/debug/gosym/pclinetest.asm
@@ -1,5 +1,3 @@
-// +build ignore
-
TEXT linefrompc(SB),7,$0 // Each byte stores its line delta
BYTE $2;
BYTE $1;
src/pkg/debug/gosym/pclntab_test.go
(変更)
--- a/src/pkg/debug/gosym/pclntab_test.go
+++ b/src/pkg/debug/gosym/pclntab_test.go
@@ -7,14 +7,31 @@ package gosym
import (
"debug/elf"
"os"
+ "os/exec"
"runtime"
+ "strings"
"testing"
)
+var pclinetestBinary string
+
func dotest() bool {
// For now, only works on ELF platforms.
- // TODO: convert to work with new go tool
- return false && runtime.GOOS == "linux" && runtime.GOARCH == "amd64"
+ if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
+ return false
+ }
+ if pclinetestBinary != "" {
+ return true
+ }
+ // This command builds pclinetest from pclinetest.asm;
+ // the resulting binary looks like it was built from pclinetest.s,
+ // but we have renamed it to keep it away from the go tool.
+ pclinetestBinary = os.TempDir() + "/pclinetest"
+ cmd := exec.Command("sh", "-c", "go tool 6a pclinetest.asm && go tool 6l -E main -o "+pclinetestBinary+" pclinetest.6")
+ if err := cmd.Run(); err != nil {
+ panic(err)
+ }
+ return true
}
func getTable(t *testing.T) *Table {
@@ -149,7 +166,7 @@ func TestPCLine(t *testing.T) {
return
}
- f, tab := crack("_test/pclinetest", t)
+ f, tab := crack(pclinetestBinary, t)
text := f.Section(".text")
textdat, err := text.Data()
if err != nil {
@@ -163,10 +180,13 @@ func TestPCLine(t *testing.T) {
file, line, fn := tab.PCToLine(pc)
off := pc - text.Addr // TODO(rsc): should not need off; bug in 8g
wantLine += int(textdat[off])
+ t.Logf("off is %d", off)
if fn == nil {
t.Errorf("failed to get line of PC %#x", pc)
- } else if len(file) < 12 || file[len(file)-12:] != "pclinetest.s" || line != wantLine || fn != sym {
- t.Errorf("expected %s:%d (%s) at PC %#x, got %s:%d (%s)", "pclinetest.s", wantLine, sym.Name, pc, file, line, fn.Name)
+ } else if !strings.HasSuffix(file, "pclinetest.s") {
+ t.Errorf("expected %s (%s) at PC %#x, got %s (%s)", "pclinetest.s", sym.Name, pc, file, fn.Name)
+ } else if line != wantLine || fn != sym {
+ t.Errorf("expected :%d (%s) at PC %#x, got :%d (%s)", wantLine, sym.Name, pc, line, fn.Name)
}
}
コアとなるコードの解説
このコミットのコアとなる変更は、src/pkg/debug/gosym/pclntab_test.go
内のdotest()
関数の実装に集約されています。
-
pclinetestBinary
変数の導入:var pclinetestBinary string
がグローバル変数として追加されました。これは、生成されたテストバイナリのパスをキャッシュするために使用されます。これにより、テストが複数回実行される場合に、毎回バイナリを再ビルドするのを防ぎ、効率を向上させます。
-
プラットフォームチェックの強化:
if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { return false }
- この行は、テストがLinuxオペレーティングシステムとAMD64アーキテクチャでのみ実行されることを保証します。これは、
go tool 6a
とgo tool 6l
が特定のプラットフォームに特化しているため、他の環境での実行を早期に終了させるためのガード句です。
- この行は、テストがLinuxオペレーティングシステムとAMD64アーキテクチャでのみ実行されることを保証します。これは、
-
テストバイナリのビルドロジック:
if pclinetestBinary != "" { return true }
pclinetestBinary
が既に設定されている場合(つまり、バイナリが既にビルドされている場合)、すぐにtrue
を返して再ビルドをスキップします。
pclinetestBinary = os.TempDir() + "/pclinetest"
- テストバイナリの出力パスを、システムの一時ディレクトリ内に設定します。これにより、テスト実行後の一時ファイルの管理が容易になります。
cmd := exec.Command("sh", "-c", "go tool 6a pclinetest.asm && go tool 6l -E main -o "+pclinetestBinary+" pclinetest.6")
- この行が、Makefileを置き換える主要な部分です。
os/exec.Command
を使用してシェルコマンドを実行します。 "sh", "-c", "..."
: シェルを介してコマンドを実行するための標準的な方法です。go tool 6a pclinetest.asm
:pclinetest.asm
というアセンブリファイルをGoのアセンブラ(6a
)でコンパイルし、pclinetest.6
というオブジェクトファイルを生成します。&&
: 前のコマンドが成功した場合にのみ、次のコマンドを実行します。go tool 6l -E main -o "+pclinetestBinary+" pclinetest.6
:pclinetest.6
オブジェクトファイルをGoのリンカ(6l
)でリンクし、pclinetestBinary
で指定されたパスに実行可能バイナリを生成します。-E main
はエントリポイントをmain
関数に設定し、-o
は出力ファイル名を指定します。
- この行が、Makefileを置き換える主要な部分です。
if err := cmd.Run(); err != nil { panic(err) }
- 構築したコマンドを実行し、エラーが発生した場合はパニックを引き起こします。これにより、テストバイナリの生成に失敗した場合にテストが続行されるのを防ぎます。
-
TestPCLine
関数内の変更:f, tab := crack(pclinetestBinary, t)
- 以前はハードコードされたパス
"_test/pclinetest"
を使用していた箇所が、pclinetestBinary
変数を使用するように変更されました。これにより、動的に生成されたバイナリのパスが正しく参照されるようになります。
- 以前はハードコードされたパス
!strings.HasSuffix(file, "pclinetest.s")
- デバッグ情報から取得したファイルパスのサフィックスチェックが、より柔軟な
strings.HasSuffix
を使用するように変更されました。これは、pclinetest.asm
からビルドされたバイナリのデバッグ情報が、元の.s
拡張子を参照している可能性があるため、より堅牢なチェックが必要とされたためです。
- デバッグ情報から取得したファイルパスのサフィックスチェックが、より柔軟な
これらの変更により、debug/gosym
パッケージのテストは、Goの標準的なツールチェーンに完全に統合され、外部のビルドシステムへの依存が解消されました。
関連リンク
- Go言語の公式ドキュメント: https://golang.org/doc/
- Goの
debug/gosym
パッケージ: https://pkg.go.dev/debug/gosym - Goの
os/exec
パッケージ: https://pkg.go.dev/os/exec - GoのIssue #2573:
cmd/go: make go test work for all packages
(このコミットが解決したIssue) - 検索しても直接的なリンクは見つかりませんでしたが、GoのIssueトラッカーで検索すると関連情報が見つかる可能性があります。
参考にした情報源リンク
- Go言語のソースコード (GitHub): https://github.com/golang/go
- Goのコードレビューシステム (Gerrit): https://golang.org/cl/5656071 (コミットメッセージに記載されているChange-ID)
- ELFファイルフォーマットに関する一般的な情報 (Wikipediaなど): https://ja.wikipedia.org/wiki/Executable_and_Linkable_Format
- Makefileに関する一般的な情報 (GNU Makeマニュアルなど): https://www.gnu.org/software/make/manual/
- Goの
go tool
コマンドに関する情報 (Goのドキュメントやブログ記事):go tool
は内部ツールであり、公式ドキュメントには詳細な説明がない場合がありますが、Goのソースコードや関連するブログ記事でその使用法が解説されていることがあります。