怎么樣在Windows下使用Make編譯Golang程序
GNU的Make是一個(gè)又古老又強(qiáng)大的構(gòu)建工具枢步,就Makefile的語(yǔ)法而言也不算復(fù)雜,沒(méi)有特別復(fù)雜的需求的話消玄,拿來(lái)做程序構(gòu)建是一個(gè)好主意荔燎。更復(fù)雜一點(diǎn)的構(gòu)建就可以選擇Google的Bazel,但是通常的工程都沒(méi)有這么復(fù)雜的需求方庭。
在Unix厕吉、Linux、BSD械念、macOS使用Make是很方便的头朱,很自然的×浼酰可是项钮,在Windows下面卻存在著兼容性的問(wèn)題,在其他操作系統(tǒng)可以順利執(zhí)行的Makefile,在Windows卻跑不了寄纵。這體驗(yàn)很糟糕鳖敷。雖然微軟在努力解決不兼容的問(wèn)題,比如最新的PowerShell程拭,但是操作系統(tǒng)畢竟還是存在著巨大的差異定踱,要完全解決幾乎是不可能完成的任務(wù)。所以恃鞋,在Makefile多少是需要做一些適配崖媚。
安裝Make
常規(guī)的做法,大家都是使用安裝MinGW包的方法來(lái)安裝Make恤浪,但是這很繁瑣畅哑,我并不推薦,我推薦使用Choco和Scoop來(lái)安裝管理Make水由。
Choco
PowerShell安裝Choco:
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
管理員權(quán)限啟動(dòng)PowerShell荠呐,然后運(yùn)行以下命令進(jìn)行安裝:
choco install make
安裝其他有用的工具:
choco install grep awk sed touch
scoop
安裝Scoop:
irm get.scoop.sh | iex
scoop install make
安裝其他有用的工具:
scoop install grep gawk sed touch
MinGW
下載安裝MinGW:https://www.mingw-w64.org/downloads/
下載好之后,解壓砂客,把bin文件夾加入到Windows的環(huán)境變量里面泥张,使之可以全局運(yùn)行。
然后鞠值,還需要把mingw32-make.exe
文件改名成make.exe
媚创。
此方法比較繁瑣,不如使用軟件包管理器去直接安裝make還方便多了彤恶。
另钞钙,通過(guò)軟件包管理也能夠安裝mingw:
choco install mingw
scoop install mingw
Windows和Linux之間使用Make的區(qū)別
在Windows下使用Make和在Linux下面使用Make是有區(qū)別的,而這個(gè)差異性倒不是來(lái)自于Make声离,而是來(lái)自于依賴的命令芒炼。
Bash里面很多的命令,在CMD下都沒(méi)有术徊,PowerShell倒是增加了一些本刽,像:man
、ls
弧关、rm
、pwd
這些常用的倒是都已經(jīng)有了唤锉,但是差異還是有世囊,兼容性永遠(yuǎn)是個(gè)大問(wèn)題。
常用的Linux工具倒是有窿祥,像grep
株憾、awk
、sed
……都可以通過(guò)上面的軟件管理器choco、scoop安裝到嗤瞎。但是墙歪,像uname
這些平臺(tái)嚴(yán)重相關(guān)的命令是肯定沒(méi)有辦法的。
簡(jiǎn)單舉一些例子:
- 文件路徑分隔符贝奇,Windows是
\
虹菲,而Linux是/
; - Linux的
mkdir
是有-p
選項(xiàng)的,而Windows沒(méi)有掉瞳。 -
echo
的行為也跟Linux的不同毕源。
現(xiàn)在PowerShell倒是在提高與Bash的兼容性,但是畢竟系統(tǒng)差異性太大陕习,兼容性是肯定存在的霎褐,那么,怎么辦呢该镣?我們可以在Makefile里面判斷操作系統(tǒng)的版本冻璃,來(lái)做差異化處理。
簡(jiǎn)單的探測(cè)系統(tǒng)版本:
detected_OS :=
ifeq ($(OS),Windows_NT)
detected_OS := Windows
else
detected_OS := $(shell sh -c 'uname 2>/dev/null || echo Unknown')
endif
all:
@echo $(detected_OS)
使用Makefile編譯Golang程序
下面以一個(gè)簡(jiǎn)單的編譯Golang程序的Makefile來(lái)講解如何跨平臺(tái)使用Makefile進(jìn)行交叉編譯:
GOPATH=$(shell go env GOPATH)
GOARCH?=$(shell go env GOARCH)
ifeq ($(OS),Windows_NT)
IS_WINDOWS := 1
endif
BUILD_CMD = $(if $(IS_WINDOWS), \
SET CGO_ENABLED=0&SET GOOS=$(1)&SET GOARCH=$(2)&go build -o .\bin\$(1)_$(2)\$(3), \
CGO_ENABLED=0 GOOS=$(1) GOARCH=$(2) go build -o ./bin/$(1)_$(2)/$(3))
linux:
$(call BUILD_CMD,linux,$(GOARCH),test)
windows:
echo $(IS_WINDOWS)
$(call BUILD_CMD,windows,$(GOARCH),test.exe)
mac:
$(call BUILD_CMD,darwin,$(GOARCH),test)
上面這段代碼里面使用ifeq ($(OS),Windows_NT)
來(lái)判斷操作系統(tǒng)损合,得到一個(gè)IS_WINDOWS
的變量省艳。
然后,定義了一個(gè)BUILD_CMD
的函數(shù)塌忽,它調(diào)用了內(nèi)置的if
函數(shù)拍埠,它的語(yǔ)法是:
$(if <condition>,<then-part>,<else-part>)
第一個(gè)分支是走的Windows的編譯,第二個(gè)分支是走的其他操作系統(tǒng)的編譯土居。
需要注意的是:路徑分隔符枣购,參數(shù)設(shè)置前面需要加SET
,語(yǔ)句之間需要用&
間隔擦耀。