日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
go語言makefile go語言make map

Go 是怎么使用 Go 來編譯自身的

第一步:all.bash

創(chuàng)新互聯(lián)服務(wù)項目包括雷州網(wǎng)站建設(shè)、雷州網(wǎng)站制作、雷州網(wǎng)頁制作以及雷州網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,雷州網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到雷州省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

% cd $GOROOT/src

% ./all.bash

第一步有些突兀,因為 all.bash 僅僅調(diào)用了其它兩個 shell 腳本;make.bash 和 run.bash。如果你在使用 Windows 或 Plan 9,過程是一樣的,只是腳本擴展名變成了.bat 或.rc。對于本文中的其它腳本,請根據(jù)你的系統(tǒng)適當(dāng)改動。

第二步:make.bash

. ./make.bash --no-banner

main.bash 來源于 all.bash,因此調(diào)用退出將正確終止便宜進程。main.bash 有三個主要工作,第一個是驗證編譯 Go 的環(huán)境是否完整。完整性檢查在過去幾年中建立,它通常嘗試避免使用已知的破損工具或必然失敗的環(huán)境進行編譯。

第三步. cmd/dist

gcc -O2 -Wall -Werror -ggdb -o cmd/dist/dist -Icmd/dist cmd/dist/*.c

一旦可用性檢查完畢,make.bash 將編譯產(chǎn)生 cmd/dist,cmd/dist取代了之前存在于Go 1 之前的Makefile 編譯系統(tǒng)。cmd/dist用來管理少量的pkg/runtime的代碼生成。cmd/dist 是C語言編寫的程序,能夠充分利用系統(tǒng)C編譯器和頭文件來處理大部分主機系統(tǒng)平臺的檢測。cmd/dist通常用來檢測主機的操作系統(tǒng)和體系結(jié)構(gòu),即環(huán)境變量$GOHOSTOS和$GOHOSTARCH .如果是交叉編譯的話,變量 $GOOS和$GOARCH可能會由于你的設(shè)置而不同。事實上,Go 通常用作跨平臺編譯器,只不過多數(shù)情況下,主機和目標(biāo)系統(tǒng)一致而已。接下來,make.bash 調(diào)用cmd/dist 的引導(dǎo)參數(shù)的支持庫、 lib9、 libbio 和 libmach,使用編譯器套件,然后用自己的編譯器進行編譯。這些工具也是用 C 語言寫的中,但是由系統(tǒng) C 編譯器編譯產(chǎn)生。

echo "# Building compilers and Go bootstrap tool for host, $GOHOSTOS/$GOHOSTARCH."

buildall="-a"

if [ "$1" = "--no-clean" ]; then

buildall=""

fi

./cmd/dist/dist bootstrap $buildall -v # builds go_bootstrap

使用的編譯器套件 cmd/dist 編譯產(chǎn)生一個版本的gotool,go_bootstrap。但go_bootstrap并不是完整得gotool,比方說 pkg/net 就是孤立的,避免了依賴于 cgo。要編譯的文件的列表以及它們的依賴項,是由cmd/dist編譯的 ,所以十分謹慎地避免引入新的生成依賴項 到 cmd/go。

第四步:go_bootstrap

現(xiàn)在, go_bootstrap 編譯完成了,make.bash 的最后一部就是使用 go_bootstrap 完成 Go 標(biāo)準(zhǔn)庫的編譯,包括整套 gotool 的替換版。

echo "# Building packages and commands for $GOOS/$GOARCH."

"$GOTOOLDIR"/go_bootstrap install -gcflags "$GO_GCFLAGS" \

-ldflags "$GO_LDFLAGS" -v std

第五步:run.bash

現(xiàn)在,make.bash 完成了,運行回到了 all.bash,它將引用 run.bash。run.bash 的工作是編譯和測試標(biāo)準(zhǔn)庫,運行時以及語言測試套件。

bash run.bash --no-rebuild

使用 --no-rebuild 標(biāo)識是因為 make.bash 和 run.bash 可能都調(diào)用了 go install -a std,這樣可以避免重復(fù),--no-rebuild 跳過了第二個 go install。

# allow all.bash to avoid double-build of everything

rebuild=true

if [ "$1" = "--no-rebuild" ]; then

shift

else

echo '# Building packages and commands.'

time go install -a -v std

echo

fi

第六步:go test -a std

echo '# Testing packages.'

time go test std -short -timeout=$(expr 120 \* $timeout_scale)s

echo

下一步 run.bash z則是對標(biāo)準(zhǔn)庫中的所有包進行單元測試,這是使用 testing 包編寫的。由于 $GOPATH 和 $GOROOT 中的代碼存在于同一個命名空間中,我們不能使用 go test,這可能會測試 $GOPATH 中的所有包,所以將創(chuàng)建別名std來標(biāo)識標(biāo)準(zhǔn)庫中的包。由于有些測試需要很長時間,或耗用大量內(nèi)存,測試將會通過 -short 標(biāo)識將其過濾。

第七步 runtime 和 cgo 測試

run.bash的下一節(jié)將運行大量對cgo支持的平臺測試,運行一些季春測試,編譯 Go 附帶的一些雜項程序。隨著時間的推移,這份雜項程序列表已經(jīng)變長了,當(dāng)它們發(fā)現(xiàn)自己并不包含在編譯過程中時,沉默將不可避免的被打破。

第八步: go run test

(xcd ../test

unset GOMAXPROCS

time go run run.go

) || exit $?

run.bash的倒數(shù)第二步調(diào)用了$GOROOT目錄下test文件夾中的編譯器和運行時測試。這其中有描述編譯器和運行時本身的低層級測試。而子目錄 test/bugs 及 test/fixedbugs 中的測試對已知問題和已解決問題進行特別的測試。所有測試的測試驅(qū)動器是 $GOROOT/test/run.go,該程序很小,它調(diào)用test文件夾中的每個.go 文件。有些 .go 文件在首行上描述了預(yù)期的運行結(jié)果,例如,程序失敗或是放出特定的輸出隊列。

第九步go tool api

echo '# Checking API compatibility.'

go tool api -c $GOROOT/api/go1.txt,$GOROOT/api/go1.1.txt \

-next $GOROOT/api/next.txt -except $GOROOT/api/except.txt

run.bash的最后一部將調(diào)用API工具,API工具的作用是執(zhí)行 Go 1 約定;導(dǎo)出的符號,常數(shù),函數(shù),變量,類型和方法組成2012年確認的 Go 1 API。Go 1 寫在 api/go1.txt 文件,而 Go 1.1 則寫在 api/go1.1.txt文件中。另一個額外的文件,api/next.txt 描述了G 1.1自后添加到標(biāo)準(zhǔn)庫和運行時中的符號。當(dāng) Go 1.2 發(fā)布時,這個文件將會成為 Go 1.2 的約定,另一個新的 next.txt 文件也將被創(chuàng)建。這里還有一個小文件,except.txt,它包括 Go 1 約定中被批準(zhǔn)的擴展。對文件的增添總是小心翼翼的。

如何在golang 中調(diào)用c的靜態(tài)庫或者動態(tài)庫

Cgo 使得Go程序能夠調(diào)用C代碼. cgo讀入一個用特別的格式寫的Go語言源文件, 輸出Go和C程序, 使得C程序能打包到Go語言的程序包中.

舉例說明一下. 下面是一個Go語言包, 包含了兩個函數(shù) -- Random 和 Seed -- 是C語言庫中random和srandom函數(shù)的馬甲.

package rand

/*

#include stdlib.h

*/ import "C" func Random() int { return int(C.random()) } func Seed(i int) { C.srandom(C.uint(i)) }

我們來看一下這里都有什么內(nèi)容. 開始是一個包的導(dǎo)入語句.

rand包導(dǎo)入了"C"包, 但你會發(fā)現(xiàn)在Go的標(biāo)準(zhǔn)庫里沒有這個包. 那是因為C是一個"偽包", 一個為cgo引入的特殊的包名, 它是C命名空間的一個引用.

rand 包包含4個到C包的引用: 調(diào)用 C.random和C.srandom, 類型轉(zhuǎn)換 C.uint(i)還有引用語句.

Random函數(shù)調(diào)用libc中的random函數(shù), 然后回返結(jié)果. 在C中, random返回一個C類型的長整形值, cgo把它輪換為C.long. 這個值必需轉(zhuǎn)換成Go的類型, 才能在Go程序中使用. 使用一個常見的Go類型轉(zhuǎn)換:

func Random() int { return int(C.random()) }

這是一個等價的函數(shù), 使用了一個臨時變量來進行類型轉(zhuǎn)換:

func Random() int { var r C.long = C.random() return int(r) }

Seed函數(shù)則相反. 它接受一個Go語言的int類型, 轉(zhuǎn)換成C語言的unsigned int類型, 然后傳遞給C的srandom函數(shù).

func Seed(i int) { C.srandom(C.uint(i)) }

需要注意的是, cgo中的unsigned int類型寫為C.uint; cgo的文檔中有完整的類型列表.

這個例子中還有一個細節(jié)我們沒有說到, 那就是導(dǎo)入語句上面的注釋.

/*

#include stdlib.h

*/ import "C"

Cgo可以識別這個注釋, 并在編譯C語言程序的時候?qū)⑺?dāng)作一個頭文件來處理. 在這個例子中, 它只是一個include語句, 然而其實它可以是使用有效的C語言代碼. 這個注釋必需緊靠在import "C"這個語句的上面, 不能有空行, 就像是文檔注釋一樣.

Strings and things

與Go語言不同, C語言中沒有顯式的字符串類型. 字符串在C語言中是一個以0結(jié)尾的字符數(shù)組.

Go和C語言中的字符串轉(zhuǎn)換是通過C.CString, C.GoString,和C.GoStringN這些函數(shù)進行的. 這些轉(zhuǎn)換將得到字符串類型的一個副本.

下一個例子是實現(xiàn)一個Print函數(shù), 它使用C標(biāo)準(zhǔn)庫中的fputs函數(shù)把一個字符串寫到標(biāo)準(zhǔn)輸出上:

package print // #include stdio.h // #include stdlib.h import "C" import "unsafe" func Print(s string) { cs := C.CString(s) C.fputs(cs, (*C.FILE)(C.stdout)) C.free(unsafe.Pointer(cs)) }

在C程序中進行的內(nèi)存分配是不能被Go語言的內(nèi)存管理器感知的. 當(dāng)你使用C.CString創(chuàng)建一個C字符串時(或者其它類型的C語言內(nèi)存分配), 你必需記得在使用完后用C.free來釋放它.

調(diào)用C.CString將返回一個指向字符數(shù)組開始處的指錯, 所以在函數(shù)退出前我們把它轉(zhuǎn)換成一個unsafe.Pointer(Go中與C的void 等價的東西), 使用C.free來釋放分配的內(nèi)存. 一個慣用法是在分配內(nèi)存后緊跟一個defer(特別是當(dāng)這段代碼比較復(fù)雜的時候), 這樣我們就有了下面這個Print函數(shù):

func Print(s string) { cs := C.CString(s) defer C.free(unsafe.Pointer(cs)) C.fputs(cs, (*C.FILE)(C.stdout)) }

構(gòu)建 cgo 包

如果你使用goinstall, 構(gòu)建cgo包就比較容易了, 只要調(diào)用像平常一樣使用goinstall命令, 它就能自動識別這個特殊的import "C", 然后自動使用cgo來編譯這些文件.

如果你想使用Go的Makefiles來構(gòu)建, 那在CGOFILES變量中列出那些要用cgo處理的文件, 就像GOFILES變量包含一般的Go源文件一樣.

rand包的Makefile可以寫成下面這樣:

include $(GOROOT)/src/Make.inc

TARG=goblog/rand

CGOFILES=\ rand.go\ include $(GOROOT)/src/Make.pkg

然后輸入gomake開始構(gòu)建.

更多 cgo 的資源

cgo的文檔中包含了關(guān)于C偽包的更多詳細的說明, 以及構(gòu)建過程. Go代碼樹中的cgo的例子給出了更多更高級的用法.

一個簡單而又符合Go慣用法的基于cgo的包是Russ Cox寫的gosqlite. 而Go語言的網(wǎng)站上也列出了更多的的cgo包.

最后, 如果你對于cgo的內(nèi)部是怎么運作這個事情感到好奇的話, 去看看運行時包的cgocall.c文件的注釋吧.

Makefile簡介

就像dockerfile之于docker,makefile之于make.....

make命令執(zhí)行時,需要一個makefile文件,以告訴make命令需要怎么樣的去編譯和鏈接程序。

你在命令行敲一個make,會自動去尋找目錄下的makefile文件并執(zhí)行。

可能你在C程序中見到的比較多,但是其實其他語言也是可以用到。

makefile內(nèi)部是你根據(jù)makefile語法規(guī)則,自己編寫的一條條shell命令等。

target

可以是一個object file(目標(biāo)文件),也可以是一個執(zhí)行文件,還可以是一個標(biāo)簽(label)。對于標(biāo)簽這種特性,在后續(xù)的“偽目標(biāo)”章節(jié)中會有敘述。

prerequisites

生成該target所依賴的文件和/或target,沒有就不需要寫

command

該target要執(zhí)行的命令(任意的shell命令)

下面我們看一個在 golang 中的應(yīng)用例子

這里執(zhí)行的任務(wù)就是本地編譯,把得到的二進制可執(zhí)行文件用upx壓縮之后通過rsync傳到服務(wù)器,

然后重啟服務(wù)器的supervisor使程序重啟,最后刪除本地生成的可執(zhí)行文件。

這一系列的任務(wù),在makefile編寫完成之后,只需要執(zhí)行一句

make test

就可以完成一系列任務(wù),非常方便。

這里需要注意的幾個地方:

.PHONY

.PHONY: build clean tool lint help

其作用是聲明 build / clean / tool / lint / help 為偽目標(biāo),聲明為偽目標(biāo)會怎么樣呢?

聲明為偽目標(biāo)后:在執(zhí)行對應(yīng)的命令時,make 就不會去檢查是否存在 build / clean / tool / lint / help 其對應(yīng)的文件,而是每次都會運行標(biāo)簽對應(yīng)的命令

若不聲明:恰好存在對應(yīng)的文件,則 make 將會認為 xx 文件已存在,沒有重新構(gòu)建的必要了

@

如果你執(zhí)行 make 會發(fā)現(xiàn),makefile中的每條命令都被打印到shell標(biāo)準(zhǔn)輸出中,為什么?

因為make默認就是這么設(shè)置的,默認先打印每條命令再執(zhí)行,這叫 echo

在命令前加@作用就是不讓你這條命令打印到標(biāo)準(zhǔn)輸出。


本文題目:go語言makefile go語言make map
URL網(wǎng)址:http://www.dlmjj.cn/article/dosidpj.html