Goノートの詳細Goのコンパイル実行フロー
4393 ワード
前の記事では、Golangの異なるシステムでのインストールについて説明し、古典的なHello Worldのケースを完了しました.このプロセスでは,ソースコードのコンパイルから実行までのプロセス全体を完了するgo runコマンドを用いた.
今日はこの過程を詳しく紹介します.簡単に理解すると、go runはgo build+実行に等価である.
buildコマンドの概要
一時ディレクトリ、mkdir-p&dollarを作成します.WORK/b001/; 依存情報を検索し、cat>$WORK/b001/importcfg << ...; ソースコードコンパイル、/usr/local/go/pkg/tool/darwin_amd64/compile ...; リンクライブラリファイルを収集する、cat>$WORK/b 001/importcfg.link << ...; 実行可能ファイルを生成、/usr/local/go/pkg/tool/darwin_amd64/link -o ...; 実行可能ファイルを移動し、mv$WORK/b 001/exe/a.out hello;
このように説明すると、buildの流れがはっきりします.c/c++の開発に詳しい友人であれば、この過程は見覚えがあるように見えます.もちろん、c/c++に比べて、前処理のステップも多くなります.
次に、前のフローチャートを最適化します.
buildプロセスを2つの部分に細分化し、compileとlink、すなわちコンパイルとリンクします.ここでは2つの重要なコマンド、complieとlinkを使用します.これらはgo toolに属するサブコマンドです.
runの流れを話して
今日はこの過程を詳しく紹介します.簡単に理解すると、go runはgo build+実行に等価である.
buildコマンドの概要
Golangでは、buildプロシージャは主にgo buildによって実行されます.ソースコードのコンパイルと実行可能ファイルの生成が完了しました.
go build受信パラメータは.goファイルまたはディレクトリは、デフォルトでは現在のディレクトリのすべてをコンパイルする.goファイル.mainパケットの下で実行すると、対応する実行可能ファイルが生成され、非mainパケットの下では、生成されたライブラリファイルがキャッシュディレクトリの下に配置され、作業ディレクトリの下で新しいファイルが生成されません.
新しいhelloケース
コンパイルプロセスを正式に紹介する前に、Hello Worldのケースを再プレゼンテーションし、helloを新規作成します.goファイル、コードは以下の通りです.package main
import "fmt"
func main() {
fmt.Println("Hello World")
}
go build helloを実行します.go,ディレクトリの下で実行可能ファイルhelloを生成する.ハローを実行し、ハローワールドを出力します.
ビルドオプションの説明
コンパイルプロセスのプレゼンテーションには、go buildが提供するいくつかのオプションの協力が必要です.go help buildの表示を実行します.次のようになります.$ go help build
...
-n
-x , -n
-work , 。 , 。
...
これらのオプションはgo runコマンドにも適用されます.shコマンドオプションと似ていると思うかどうかは、コンピュータの多くの知識が通じていることがわかります.
印刷実行プロセス
-nオプションを使用して、コマンドが実行されない場合、go buildの実行プロセスを次のように表示します.$ go build -n hello.go
#
# command-line-arguments
#
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
# import config
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a
packagefile runtime=/usr/local/go/pkg/darwin_amd64/runtime.a
EOF
cd /Users/polo/Public/Work/go/src/study/basic/hello
/usr/local/go/pkg/tool/darwin_amd64/compile -o $WORK/b001/_pkg_.a -trimpath $WORK/b001 -p main -complete -buildid fVbBEz0nTJc3r6VxU5ye/fVbBEz0nTJc3r6VxU5ye -goversion go1.11.1 -D _/Users/polo/Public/Work/go/src/study/basic/hello -importcfg $WORK/b001/importcfg -pack -c=4 ./hello.go
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/_pkg_.a # internal
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile command-line-arguments=$WORK/b001/_pkg_.a
...
packagefile internal/race=/usr/local/go/pkg/darwin_amd64/internal/race.a
EOF
mkdir -p $WORK/b001/exe/
cd .
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -buildmode=exe -buildid=P1Y_fbNXAEG6zEEGqFsM/fVbBEz0nTJc3r6VxU5ye/fVbBEz0nTJc3r6VxU5ye/P1Y_fbNXAEG6zEEGqFsM -extld=clang $WORK/b001/_pkg_.a
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/exe/a.out # internal
mv $WORK/b001/exe/a.out hello
プロセスは混乱しているように見えますが、よく見ると、主にいくつかの部分から構成されています.
コンパイルプロセスを正式に紹介する前に、Hello Worldのケースを再プレゼンテーションし、helloを新規作成します.goファイル、コードは以下の通りです.
package main
import "fmt"
func main() {
fmt.Println("Hello World")
}
go build helloを実行します.go,ディレクトリの下で実行可能ファイルhelloを生成する.ハローを実行し、ハローワールドを出力します.
ビルドオプションの説明
コンパイルプロセスのプレゼンテーションには、go buildが提供するいくつかのオプションの協力が必要です.go help buildの表示を実行します.次のようになります.$ go help build
...
-n
-x , -n
-work , 。 , 。
...
これらのオプションはgo runコマンドにも適用されます.shコマンドオプションと似ていると思うかどうかは、コンピュータの多くの知識が通じていることがわかります.
印刷実行プロセス
-nオプションを使用して、コマンドが実行されない場合、go buildの実行プロセスを次のように表示します.$ go build -n hello.go
#
# command-line-arguments
#
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
# import config
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a
packagefile runtime=/usr/local/go/pkg/darwin_amd64/runtime.a
EOF
cd /Users/polo/Public/Work/go/src/study/basic/hello
/usr/local/go/pkg/tool/darwin_amd64/compile -o $WORK/b001/_pkg_.a -trimpath $WORK/b001 -p main -complete -buildid fVbBEz0nTJc3r6VxU5ye/fVbBEz0nTJc3r6VxU5ye -goversion go1.11.1 -D _/Users/polo/Public/Work/go/src/study/basic/hello -importcfg $WORK/b001/importcfg -pack -c=4 ./hello.go
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/_pkg_.a # internal
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile command-line-arguments=$WORK/b001/_pkg_.a
...
packagefile internal/race=/usr/local/go/pkg/darwin_amd64/internal/race.a
EOF
mkdir -p $WORK/b001/exe/
cd .
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -buildmode=exe -buildid=P1Y_fbNXAEG6zEEGqFsM/fVbBEz0nTJc3r6VxU5ye/fVbBEz0nTJc3r6VxU5ye/P1Y_fbNXAEG6zEEGqFsM -extld=clang $WORK/b001/_pkg_.a
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/exe/a.out # internal
mv $WORK/b001/exe/a.out hello
プロセスは混乱しているように見えますが、よく見ると、主にいくつかの部分から構成されています.
$ go help build
...
-n
-x , -n
-work , 。 , 。
...
-nオプションを使用して、コマンドが実行されない場合、go buildの実行プロセスを次のように表示します.
$ go build -n hello.go
#
# command-line-arguments
#
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
# import config
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a
packagefile runtime=/usr/local/go/pkg/darwin_amd64/runtime.a
EOF
cd /Users/polo/Public/Work/go/src/study/basic/hello
/usr/local/go/pkg/tool/darwin_amd64/compile -o $WORK/b001/_pkg_.a -trimpath $WORK/b001 -p main -complete -buildid fVbBEz0nTJc3r6VxU5ye/fVbBEz0nTJc3r6VxU5ye -goversion go1.11.1 -D _/Users/polo/Public/Work/go/src/study/basic/hello -importcfg $WORK/b001/importcfg -pack -c=4 ./hello.go
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/_pkg_.a # internal
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile command-line-arguments=$WORK/b001/_pkg_.a
...
packagefile internal/race=/usr/local/go/pkg/darwin_amd64/internal/race.a
EOF
mkdir -p $WORK/b001/exe/
cd .
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -buildmode=exe -buildid=P1Y_fbNXAEG6zEEGqFsM/fVbBEz0nTJc3r6VxU5ye/fVbBEz0nTJc3r6VxU5ye/P1Y_fbNXAEG6zEEGqFsM -extld=clang $WORK/b001/_pkg_.a
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/exe/a.out # internal
mv $WORK/b001/exe/a.out hello
プロセスは混乱しているように見えますが、よく見ると、主にいくつかの部分から構成されています.
このように説明すると、buildの流れがはっきりします.c/c++の開発に詳しい友人であれば、この過程は見覚えがあるように見えます.もちろん、c/c++に比べて、前処理のステップも多くなります.
次に、前のフローチャートを最適化します.
buildプロセスを2つの部分に細分化し、compileとlink、すなわちコンパイルとリンクします.ここでは2つの重要なコマンド、complieとlinkを使用します.これらはgo toolに属するサブコマンドです.
runの流れを話して
buildプロセスを理解するとrunはよく理解できます.go run-x helloを使います.go実行プロセスを次のように表示します....
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/hello -importcfg $WORK/b001/importcfg.link -s -w -buildmode=exe -buildid=fveq2guPMmsyv8t4cV_M/xYBkVZeN1BHy2ygmstrB/pWJerx2-jOU98BpvIFO6/fveq2guPMmsyv8t4cV_M -extld=clang $WORK/b001/_pkg_.a
$WORK/b001/exe/hello
Hello World
最後のセクションではbuildとは異なり、linkでhelloファイルを生成した後、現在のディレクトリに移動するのではなく、$WORK/b 001/exe/helloでプログラムを実行しました.コンパイルを加えて、次のフローチャートを描きます.
これでrunのプロセス全体が明らかになります.
--workで実行可能ファイルを保持する
では、この一時的に生成された実行可能ファイルを手に入れることができますか?デフォルトではだめです.go runでは最後に一時ディレクトリが削除されます.--workを使用してこのディレクトリを保持できます.プレゼンテーションの手順は次のとおりです.$ go run -x --work hello.go
WORK=/var/folders/bw/8yw8h4yj2vb6mxtb6t8t41f00000gn/T/go-build149627400
...
$WORK/b001/exe/hello
Hello World
一時ディレクトリパスWORKを印刷し、mvコマンドでrunで生成したhelloファイルを現在のディレクトリにコピーできます.以下に示します.$ mv /var/folders/bw/8yw8h4yj2vb6mxtb6t8t41f00000gn/T/go-build149627400b001/exe/hello hello
helloを実行して、私たちが予想したのと同じかどうかを確認することができます.
まとめ
この記事ではgo runからGolangのコンパイル実行プロセスを引き出します.buildが提供するいくつかのデバッグオプションを用いて,プロセスの逐次分解を実現し,最終的にコンパイル実行プロセス全体の各段階を比較的詳細に紹介した.
...
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/hello -importcfg $WORK/b001/importcfg.link -s -w -buildmode=exe -buildid=fveq2guPMmsyv8t4cV_M/xYBkVZeN1BHy2ygmstrB/pWJerx2-jOU98BpvIFO6/fveq2guPMmsyv8t4cV_M -extld=clang $WORK/b001/_pkg_.a
$WORK/b001/exe/hello
Hello World
では、この一時的に生成された実行可能ファイルを手に入れることができますか?デフォルトではだめです.go runでは最後に一時ディレクトリが削除されます.--workを使用してこのディレクトリを保持できます.プレゼンテーションの手順は次のとおりです.
$ go run -x --work hello.go
WORK=/var/folders/bw/8yw8h4yj2vb6mxtb6t8t41f00000gn/T/go-build149627400
...
$WORK/b001/exe/hello
Hello World
一時ディレクトリパスWORKを印刷し、mvコマンドでrunで生成したhelloファイルを現在のディレクトリにコピーできます.以下に示します.
$ mv /var/folders/bw/8yw8h4yj2vb6mxtb6t8t41f00000gn/T/go-build149627400b001/exe/hello hello
helloを実行して、私たちが予想したのと同じかどうかを確認することができます.