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

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

このコミットは、Goランタイムのビルドプロセスをより「ビルドフレンドリー」にするための重要な変更を導入しています。具体的には、オペレーティングシステム(OS)やアーキテクチャ(CPU)に特化したファイルを、それぞれの専用ディレクトリからメインのsrc/pkg/runtimeディレクトリに統合し、ファイル名をfoo_os.cfoo_os_arch.cのように変更しています。これにより、Goツールがビルド時にGOOS_darwinGOARCH_amd64といったプリプロセッサマクロを定義することで、適切なファイルが自動的に選択されるようになります。

コミット

commit 851f30136d79c9bb752ab56d3991bb3180a5aa5b
Author: Russ Cox <rsc@golang.org>
Date:   Fri Dec 16 15:33:58 2011 -0500

    runtime: make more build-friendly
    
    Collapse the arch,os-specific directories into the main directory
    by renaming xxx/foo.c to foo_xxx.c, and so on.
    
    There are no substantial edits here, except to the Makefile.
    The assumption is that the Go tool will #define GOOS_darwin
    and GOARCH_amd64 and will make any file named something
    like signals_darwin.h available as signals_GOOS.h during the
    build.  This replaces what used to be done with -I$(GOOS).
    
    There is still work to be done to make runtime build with
    standard tools, but this is a big step.  After this we will have
    to write a script to generate all the generated files so they
    can be checked in (instead of generated during the build).
    
    R=r, iant, r, lucio.dere
    CC=golang-dev
    https://golang.org/cl/5490053

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

https://github.com/golang/go/commit/851f30136d79c9bb752ab56d3991bb3180a5aa5b

元コミット内容

runtime: make more build-friendly

Collapse the arch,os-specific directories into the main directory
by renaming xxx/foo.c to foo_xxx.c, and so on.

There are no substantial edits here, except to the Makefile.
The assumption is that the Go tool will #define GOOS_darwin
and GOARCH_amd64 and will make any file named something
like signals_darwin.h available as signals_GOOS.h during the
build.  This replaces what used to be done with -I$(GOOS).

There is still work to be done to make runtime build with
standard tools, but this is a big step.  After this we will have
to write a script to generate all the generated files so they
can be checked in (instead of generated during the build).

R=r, iant, r, lucio.dere
CC=golang-dev
https://golang.org/cl/5490053

変更の背景

このコミットの主な背景は、Goランタイムのビルドシステムの複雑性を軽減し、より標準的なビルドツールとの互換性を高めることにありました。当時のGoのビルドプロセスでは、OSやアーキテクチャに特化したファイルがsrc/pkg/runtime以下のdarwin/linux/386/amd64/といったサブディレクトリに分散していました。これらのファイルをビルドに含めるためには、Makefile内で-Iフラグを使って適切なインクルードパスを指定する必要がありました。

このアプローチにはいくつかの課題がありました。

  1. Makefileの複雑性: 各OS/アーキテクチャの組み合わせに対して、複雑なインクルードパスの管理が必要となり、Makefileが肥大化し、理解や保守が困難になっていました。
  2. 標準ツールとの非互換性: -Iフラグに依存するビルド方法は、Go独自のビルドシステムに強く結びついており、一般的なC/C++コンパイラやビルドツール(例: gccclangmakeの標準的な動作)との連携を難しくしていました。GoのランタイムはC言語やアセンブリ言語で書かれた部分が多く、これらのファイルをビルドする際には、GoのビルドシステムがCコンパイラを呼び出す必要がありました。
  3. 可読性と発見性: 特定のOSやアーキテクチャに依存するファイルが、そのOS/アーキテクチャ名のサブディレクトリに隠れてしまうため、コードベース全体の構造を把握しにくく、関連するファイルを見つけにくいという問題がありました。

このコミットは、これらの課題を解決し、Goランタイムのビルドプロセスをよりシンプルで、将来的にGoツールチェインがより深く統合できるような基盤を築くことを目的としています。

前提知識の解説

このコミットを理解するためには、以下の概念が重要です。

  1. Goのビルドシステム (go tool): Go言語には、ソースコードのコンパイル、パッケージの管理、テストの実行など、開発プロセス全体を管理するgoコマンド(Goツール)があります。初期のGoでは、ランタイムのビルドにはMakefileが使われていましたが、徐々にgo toolがその役割を担うようになっていきました。go toolは、Goのソースファイルだけでなく、Cやアセンブリ言語で書かれたファイルも適切にコンパイルしてリンクする能力を持っています。
  2. GOOSGOARCH: Goのビルド環境において、GOOSはターゲットとなるオペレーティングシステム(例: linux, windows, darwinなど)を、GOARCHはターゲットとなるCPUアーキテクチャ(例: amd64, 386, armなど)をそれぞれ定義する環境変数です。Goツールはこれらの値に基づいて、ビルドするコードパスを決定します。
  3. プリプロセッサマクロ (#define): C言語やC++において、プリプロセッサマクロはコンパイル前にソースコードを変換するためのディレクティブです。#defineは、特定のシンボルを定義し、そのシンボルがコード内で使用されている箇所を置換したり、#ifdef#ifndefといった条件付きコンパイルディレクティブと組み合わせて、特定のコードブロックをコンパイルに含めるか除外するかを制御したりするために使われます。
  4. 条件付きコンパイル: プリプロセッサマクロと#ifdef#ifndef#ifなどのディレクティブを組み合わせることで、コンパイル時に特定の条件(例: 特定のOSやアーキテクチャ向けであるか)に基づいてコードのコンパイルを切り替えることができます。これにより、単一のソースファイルで複数のプラットフォームに対応するコードを記述することが可能になります。
  5. ファイル名の慣習 (Goにおけるビルドタグ): Go言語では、ファイル名に特定のサフィックスを付けることで、そのファイルがどのOSやアーキテクチャ、あるいはビルドタグ(build tag)に特化しているかをGoツールに伝える慣習があります。例えば、foo_linux.goはLinux専用のファイル、foo_amd64.goはAMD64アーキテクチャ専用のファイル、foo_linux_amd64.goはLinuxかつAMD64専用のファイルとして扱われます。このコミットは、C言語やアセンブリ言語のファイルに対しても同様の慣習を導入しようとしています。

技術的詳細

このコミットの核心は、Goランタイム内のOS/アーキテクチャ固有のCおよびアセンブリ言語ファイルの管理方法を根本的に変更した点にあります。

変更前のアプローチ: 以前は、src/pkg/runtimeディレクトリの下に、darwin/linux/386/amd64/といったサブディレクトリが存在し、それぞれのプラットフォームに特化したファイル(例: src/pkg/runtime/darwin/mem.csrc/pkg/runtime/386/asm.s)が格納されていました。Makefileは、これらのサブディレクトリを-Iフラグを使ってインクルードパスに追加することで、コンパイラが適切なファイルを見つけられるようにしていました。

変更後のアプローチ: このコミットでは、以下の2つの主要な変更が行われました。

  1. ファイル名の変更とディレクトリの統合:

    • xxx/foo.cのようなパスにあったファイルは、foo_xxx.cのようにファイル名自体にOSやアーキテクチャの識別子を含む形にリネームされ、src/pkg/runtimeのメインディレクトリに移動されました。
    • 例: src/pkg/runtime/darwin/mem.csrc/pkg/runtime/mem_darwin.c に、src/pkg/runtime/386/asm.ssrc/pkg/runtime/asm_386.s に変更されました。
    • これにより、OS/アーキテクチャ固有のファイルが単一のディレクトリに集約され、ファイルシステム上の構造がフラットになりました。
  2. プリプロセッサマクロによる条件付きコンパイルへの移行:

    • コミットメッセージにあるように、「Goツールが#define GOOS_darwinGOARCH_amd64を定義する」という仮定が導入されました。これは、GoツールがCコンパイラを呼び出す際に、現在のビルドターゲット(GOOSGOARCH)に対応するプリプロセッサマクロを自動的に定義することを意味します。
    • 例えば、GOOS=windowsかつGOARCH=amd64でビルドする場合、GoツールはCコンパイラに-DGOOS_windows -DGOARCH_amd64のようなフラグを渡します。
    • これにより、Cソースコード内では、#ifdef GOOS_windows#ifdef GOARCH_amd64といったディレクティブを使って、特定のOSやアーキテクチャに依存するコードブロックを条件付きでコンパイルできるようになります。
    • また、#includeディレクティブも変更され、#include "arch.h"のような汎用的なインクルードから、#include "arch_GOARCH.h"のように、Goツールが定義するマクロを利用して適切なヘッダファイルを選択する形になりました。これにより、コンパイラはリネームされたヘッダファイル(例: arch_amd64.h)を直接参照できるようになります。

Makefileの変更: この変更に伴い、src/pkg/runtime/Makefileが大幅に修正されました。

  • 以前の-I$(GOOS) -I$(GOARCH) -I$(GOOS)/$(GOARCH)といったインクルードパスの指定が削除されました。これは、ファイル名にOS/アーキテクチャ情報が含まれるようになったため、特定のディレクトリをインクルードする必要がなくなったためです。
  • CFLAGS-DGOOS_$(GOOS) -DGOARCH_$(GOARCH)が追加されました。これにより、GoツールがCコンパイラを呼び出す際に、GOOSGOARCHに対応するプリプロセッサマクロが定義されるようになります。
  • OFILES(オブジェクトファイル)のリストが、新しいファイル名(例: asm_$(GOARCH).$Omem_$(GOOS).$O)を反映するように更新されました。
  • ヘッダファイルの生成ルールも変更され、$(GOARCH)/asm.hのようなパスではなく、asm_$(GOARCH).hのような新しいファイル名に対応するように修正されました。特に、AUTOHFILESという変数が導入され、arch_GOARCH.hos_GOOS.hsignals_GOOS.hdefs_GOOS_GOARCH.hといった自動生成されるヘッダファイルのパターンが定義されました。これらのファイルは、対応するOS/アーキテクチャ固有のヘッダファイルをコピーすることで生成されます。

この変更は、GoのビルドシステムがC/アセンブリ言語ファイルを扱う方法における重要な進化を示しています。将来的には、go toolがこれらのファイルを直接管理し、Makefileへの依存を減らすための布石となりました。

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

このコミットでは、主にファイルのリネームとMakefileの変更が中心ですが、C言語ソースコード内の#includeディレクティブも変更されています。

ファイルのリネーム例:

  • src/pkg/runtime/386/arch.h -> src/pkg/runtime/arch_386.h
  • src/pkg/runtime/amd64/asm.s -> src/pkg/runtime/asm_amd64.s
  • src/pkg/runtime/linux/defs.go -> src/pkg/runtime/defs_linux.go
  • src/pkg/runtime/darwin/mem.c -> src/pkg/runtime/mem_darwin.c
  • src/pkg/runtime/windows/386/signal.c -> src/pkg/runtime/signal_windows_386.c

#includeディレクティブの変更例:

  • src/pkg/runtime/cgocall.c
    • 変更前: #include "arch.h"
    • 変更後: #include "arch_GOARCH.h"
  • src/pkg/runtime/windows/386/callback.c
    • 変更前: #include "defs.h"#include "os.h"
    • 変更後: #include "defs_GOOS_GOARCH.h"#include "os_GOOS.h"
  • src/pkg/runtime/stack.h
    • 変更前: #ifdef __WINDOWS__
    • 変更後: #ifdef GOOS_windows

Makefileの変更例:

  • CFLAGSの変更:
    • 変更前: CFLAGS=-I$(GOOS) -I$(GOARCH) -I$(GOOS)/$(GOARCH) -FVw $(CFLAGS_$(GOARCH)) $(CFLAGS_$(GOOS))
    • 変更後: CFLAGS+=-DGOOS_$(GOOS) -DGOARCH_$(GOARCH) (既存のCFLAGSに追加)
  • OFILES_windowsの変更:
    • 変更前: callback.$Osyscall.$O
    • 変更後: callback_windows_$(GOARCH).$Osyscall_windows.$O
  • OFILESの変更:
    • 変更前: asm.$Oatomic.$Oclosure.$Omem.$Omemmove.$Ort0.$Osignal.$Osys.$Othread.$Otraceback.$O
    • 変更後: asm_$(GOARCH).$Oatomic_$(GOARCH).$Oclosure_$(GOARCH).$Omem_$(GOOS).$Omemmove_$(GOARCH).$Ort0_$(GOOS)_$(GOARCH).$Osignal_$(GOOS)_$(GOARCH).$Osys_$(GOOS)_$(GOARCH).$Othread_$(GOOS).$Otraceback_$(GOARCH).$O
  • HFILESの変更:
    • 変更前: $(GOARCH)/asm.h$(GOOS)/os.h$(GOOS)/signals.h$(GOOS)/$(GOARCH)/defs.h
    • 変更後: $(AUTOHFILES) (新しい自動生成ヘッダファイル群)

コアとなるコードの解説

このコミットのコアとなる変更は、Goランタイムのビルドにおけるプラットフォーム固有のファイルの扱いを、ディレクトリ構造による分離から、ファイル名とプリプロセッサマクロによる条件付きコンパイルへと移行させた点にあります。

  1. ファイル名の変更とディレクトリ統合の意図:

    • 以前のディレクトリ構造(例: src/pkg/runtime/darwin/mem.c)は、ファイルがどのプラットフォームに属するかを明確にしていましたが、ビルドシステムにとっては、適切なファイルをインクルードするために複雑なパス管理が必要でした。
    • ファイル名をmem_darwin.cのように変更し、すべてのファイルを単一のsrc/pkg/runtimeディレクトリに集約することで、ファイルシステム上の構造がシンプルになります。これにより、Goツールがファイルをスキャンする際に、特定のサブディレクトリを探索する必要がなくなり、ビルドプロセスの効率化と簡素化が図られます。
    • この命名規則は、Go言語のソースファイル(例: foo_linux.go)で既に採用されていた慣習を、Cやアセンブリ言語のファイルにも拡張したものです。これにより、Goプロジェクト全体で一貫したプラットフォーム固有ファイルの識別方法が確立されます。
  2. プリプロセッサマクロへの移行の意図:

    • Makefileから-Iフラグによるインクルードパスの指定を削除し、代わりにCFLAGS-DGOOS_$(GOOS) -DGOARCH_$(GOARCH)を追加したことは、ビルドの柔軟性を高める上で非常に重要です。
    • これにより、Cコンパイラはビルド時にGOOS_windowsGOARCH_amd64といったマクロが定義されているかどうかを直接チェックできるようになります。Cソースコード内で#ifdef GOOS_windowsのような条件付きコンパイルを使用することで、GoツールがCコンパイラに渡すフラグに基づいて、適切なプラットフォーム固有のコードブロックがコンパイルされるようになります。
    • これは、GoツールがC/アセンブリ言語ファイルのビルドをより細かく制御できるようになることを意味します。将来的には、Makefileのような外部のビルドスクリプトに依存することなく、Goツール自身がランタイムのビルドプロセス全体を管理できるようになるための重要なステップです。
    • #include "arch_GOARCH.h"のような変更は、コンパイル時にGOARCHの値(例: amd64)が展開され、結果的に#include "arch_amd64.h"となることを意図しています。これにより、Goツールが定義する環境変数に基づいて、適切なヘッダファイルが動的に選択されるようになります。

このコミットは、Goの初期段階におけるビルドシステムの成熟に向けた大きな一歩であり、Goツールチェインがランタイムのビルドをより深く統合し、クロスコンパイルなどの機能を実現するための基盤を強化しました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント (Goのビルドシステム、GOOS/GOARCH、ビルドタグに関する情報)
  • C言語のプリプロセッサに関する一般的な情報
  • Goの初期のソースコードとビルドプロセスの歴史に関するコミュニティの議論 (Stack Overflow, Go mailing listsなど)
  • Goのcmd/goパッケージの進化に関する情報 (GoツールがどのようにC/アセンブリファイルを扱うようになったか)