自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

透過一個編譯報錯,總結(jié)兩個Go程序編譯的重要知識

開發(fā) 后端
最近調(diào)研了一下某個做 APM 的廠商的 Go 探針程序,說是引入一個包,全程不用再修改其他代碼就能在項目里引入探針。

[[437512]]

本文轉(zhuǎn)載自微信公眾號「網(wǎng)管叨bi叨」,作者網(wǎng)管。轉(zhuǎn)載本文請聯(lián)系網(wǎng)管叨bi叨公眾號。

最近調(diào)研了一下某個做 APM 的廠商的 Go 探針程序,說是引入一個包,全程不用再修改其他代碼就能在項目里引入探針。沒想到在剛引入包試著構(gòu)建了一下就翻車了。

  1. main.go:10:2: build constraints exclude all Go files in /xxx/github.com/xxx/agnet/xxxx 

編譯器編譯的時候直接排除了某個包下的所有文件,啥意思呢?就是這個包下沒有能在當(dāng)前構(gòu)建環(huán)境下構(gòu)建的 Go 文件。猜測應(yīng)該是這個包源碼的構(gòu)建標(biāo)簽上聲明了不允許在Mac 環(huán)境下構(gòu)建。打開源碼看了看,確實(shí)是,所有文件的構(gòu)建標(biāo)簽都是這么聲明的。

  1. // +build linux 
  2. // +build amd64 

這個叫做條件編譯,或者約束編譯。那想在Mac下編譯linux上才能運(yùn)行的執(zhí)行文件該怎么辦呢?Go 里邊還支持一個特性叫做交叉編譯,就是干跨平臺編譯這個事兒的。具體怎么用呢,比如這個例子里是需要在Mac環(huán)境下編譯能在Linux系統(tǒng)amd64架構(gòu)下運(yùn)行的執(zhí)行文件,就得醬嬸進(jìn)行編譯:

  1. CGO_ENABLED=0  GOOS=linux  GOARCH=amd64  go build main.go 

不過我后來想研究下為啥不讓在 Mac 上編譯,看了看這個包的探針是用CGO實(shí)現(xiàn)的調(diào)用了linux系統(tǒng)下的一個C語言實(shí)現(xiàn)的工具命令??吹竭@我已經(jīng)不想繼續(xù)研究這個包了,那么為了讓此篇文章水的不那么明顯:),接下來咱們就把Go語言的交叉編譯和條件編譯這兩個知識點(diǎn)再復(fù)習(xí)一遍吧。

交叉編譯

交叉編譯是用來在一個平臺上生成另一個平臺的可執(zhí)行程序。Go 的命令集是原生支持交叉編譯的,使用方法也很簡單,比如上面已經(jīng)演示過的

  1. CGO_ENABLED=0  GOOS=linux  GOARCH=amd64  go build main.go 

參數(shù)說明

  • CGO_ENABLED : CGO 表示golang中的工具,CGO_ENABLED 表示CGO禁用,交叉編譯中不能使用CGO的
  • GOOS: 目標(biāo)平臺
    • mac 對應(yīng) darwin
    • linux 對應(yīng) linux
    • windows 對應(yīng) windows
  • GOARCH :目標(biāo)平臺的體系架構(gòu)【386,amd64,arm】, 目前市面上的個人電腦一般都是amd64架構(gòu)的
    • 386 也稱 x86 對應(yīng) 32位操作系統(tǒng)
    • amd64 也稱 x64 對應(yīng) 64位操作系統(tǒng)
    • arm 這種架構(gòu)一般用于嵌入式開發(fā)。比如 Android , IOS , Win mobile , TIZEN 等

了解完這幾個參數(shù)后,我們在看下Mac、Linux、Windows這三個平臺上執(zhí)行交叉編譯的例子,Windows的因為家境貧寒,條件不允許我沒有試過,命令網(wǎng)上找的,如果有錯誤還請同學(xué)們在評論里留言幫我改正一下。

Mac 下編譯, Linux 或者 Windows 的可執(zhí)行程序

  1. # linux可執(zhí)行程序 
  2. CGO_ENABLED=0  GOOS=linux  GOARCH=amd64  go build main.go 
  3. # Windows 可執(zhí)行程序 
  4. CGO_ENABLED=0 GOOS=windows  GOARCH=amd64  go  build  main.go 

Linux 下編譯 , Mac 或者 Windows 下去執(zhí)行

  1. # Mac 平臺可執(zhí)行程序 
  2. CGO_ENABLED=0 GOOS=darwin  GOARCH=amd64  go build main.go 
  3. # Windows可執(zhí)行程序 
  4. CGO_ENABLED=0 GOOS=windows  GOARCH=amd64  go build main.go 

Windows 下執(zhí)行 , Mac 或 Linux 下去執(zhí)行

需要寫一個批處理程序,在里面去設(shè)置,因為windows 下的 terminal 不支持shell , 這跟 Mac 和 Linux下的有點(diǎn)不同

  1. # Mac 下執(zhí)行 
  2. SET  CGO_ENABLED=0 
  3. SET GOOS=darwin 
  4. SET GOARCH=amd64 
  5. go build main.go 
  6.  
  7. # Linux 去執(zhí)行 
  8. SET CGO_ENABLED=0 
  9. SET GOOS=linux 
  10. SET GOARCH=amd64 
  11. go build main.go 

條件編譯

交叉編譯只是為了能在一個平臺上編譯出其他平臺可運(yùn)行的程序,Go 作為一個跨平臺的語言,它提供的類庫勢必也是跨平臺的,比如說程序的系統(tǒng)調(diào)用相關(guān)的功能,能根據(jù)所處環(huán)境選擇對應(yīng)的源碼進(jìn)行編譯。讓編譯器只對滿足條件的代碼進(jìn)行編譯,將不滿足條件的代碼舍棄,這就是另外一個概念叫---條件編譯。

在 Go 中,也稱之為Build Constraints 編譯約束,添加編譯約束的方式有2種分別:

  • 編譯標(biāo)簽(build tag)
  • 文件后綴

編譯標(biāo)簽

編譯標(biāo)簽是一種通過在源碼文件頂部添加注釋,來決定文件是否參與編譯的約束方式。其格式如下:

 

  1. // +build <tags> 

注意:// +build的下一行必須是空行,否則會被解析為包注釋。

  1. // +build linux 
  2.  
  3. // main package comment 
  4. package main 

tags說明:

  • 以空格分開表示 AND
  • 以逗號分開表示 OR
  • !表示 NOT

標(biāo)簽可以指定為以下內(nèi)容:

  • 操作系統(tǒng),環(huán)境變量中GOOS的值,如:linux、darwin、windows等等。
  • 操作系統(tǒng)的架構(gòu),環(huán)境變量中GOARCH的值,如:arch64、x86、i386等等。
  • 使用的編譯器,gc或者gccgo。
  • 是否開啟CGO,cgo。
  • golang版本號:比如Go Version 1.1為go1.1,Go Version 1.12版本為go1.12,以此類推。
  • 其它自定義標(biāo)簽,通過go build -tags指定的值。

例如,編譯條件為(linux AND 386) OR (darwin AND (NOT cgo))

  1. // +build linux,386 darwin,!cgo 

另外一個文件可以有多個編譯約束,比如條件為(linux OR darwin) AND amd64

  1. // +build linux darwin 
  2. // +build amd64 

也可以使用ignore標(biāo)簽將一個文件從編譯中排除。

  1. // +build ignore 

文件后綴

除了編譯標(biāo)簽,第二種添加編譯約束的方法是通過源碼文件的文件名實(shí)現(xiàn)的,這種方案比構(gòu)造標(biāo)簽方案更簡單。編譯器也會根據(jù)文件后綴來自動選擇編譯文件:

  1. $filename_$GOOS.go 
  2. $filename_$GOARCH.go 
  3. $filename_$GOOS_$GOARCH.go 
  • $filename: 源文件名稱。
  • $GOOS: 表示操作系統(tǒng),從環(huán)境變量中獲取。
  • $GOARCH: 表示系統(tǒng)架構(gòu),從環(huán)境變量中獲取。

后綴的順序記住不要顛倒,后綴中同時出現(xiàn)系統(tǒng)和架構(gòu)名時,需要保持$filename_$GOOS_$GOARCH.go的順序。

在 Go 的每個內(nèi)置庫里都有很多以不同系統(tǒng)名結(jié)尾的文件。下面是Go的os內(nèi)置庫源代碼的部分截圖:

文件后綴添加編譯約束

兩種添加編譯限制的方式該如何選擇

構(gòu)建標(biāo)簽和文件名后綴在功能上是重疊的。比如,一個名為mypkg_linux.go的文件,再包含構(gòu)建標(biāo)簽// +build linux會顯得多余。

通常來說,當(dāng)只有一個特定平臺需要指定時,我們選擇文件名后綴的方式。比如:

  1. mypkg_linux.go         // 只在 linux 系統(tǒng)編譯 
  2. mypkg_windows_amd64.go // 只在 windows amd 64位 平臺編譯 

相反,如果你的文件需要指定給多個平臺或體系架構(gòu)使用,或者你需要排除某個特定平臺時,我們選擇構(gòu)建標(biāo)簽的方式。比如:

  1. // 在所有類unix平臺編譯 
  2. // +build darwin dragonfly freebsd linux netbsd openbsd 
  3.  
  4. // 在非Windows平臺編譯 
  5. // +build !windows 

一個編譯器報錯,居然水了一篇文章....啊...(咳嗽聲)引出來的交叉編譯和條件編譯(編譯約束)這兩個非常重要的知識點(diǎn),其實(shí)這兩個知識點(diǎn)在很早之前我也寫過篇文章,這次相當(dāng)于從實(shí)際遇到問題帶出從頭開始再分析一遍,希望大家能喜歡。

參考鏈接

http://www.oskip.com/post/golang/golang-build/

https://juejin.cn/post/6844903944808824845

https://mp.weixin.qq.com/s/Ys8o4arwIFYB6DPCdiGNNQ

 

責(zé)任編輯:武曉燕 來源: 網(wǎng)管叨bi叨
相關(guān)推薦

2021-12-16 16:20:57

GoWebSocketLinux

2020-11-13 07:16:09

線程互斥鎖死循環(huán)

2009-08-14 00:55:21

C#程序編譯

2017-10-24 17:03:48

Linux驅(qū)動程序編譯

2016-11-08 18:53:08

編譯器

2021-05-26 07:53:58

Linux運(yùn)維Linux系統(tǒng)

2011-06-24 13:38:32

QT 編譯 安裝

2012-01-18 11:02:37

Tomcat

2021-06-25 10:38:05

JavaScript編譯器前端開發(fā)

2023-07-25 15:17:38

Linux操作系統(tǒng)開發(fā)

2009-12-03 11:10:32

SMONARCHOracle

2012-10-19 14:14:51

Ubuntu 12.1

2013-07-05 10:52:07

程序員結(jié)對編程

2015-02-05 09:54:13

程序員

2010-07-25 14:31:54

Telnet程序

2020-01-06 09:53:29

程序員

2010-02-25 16:45:13

WCF應(yīng)用技巧

2010-03-23 10:47:46

python代碼

2013-10-11 09:32:33

TD-LTELTE FDD4G

2020-10-26 08:19:53

算法隊列
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號