Showing posts with label Cgo. Show all posts
Showing posts with label Cgo. Show all posts

Monday, August 21, 2023

[Golang] 實現跨平台編譯的CGO交叉編譯:解鎖Go語言開發的更多可能

實現跨平台編譯的CGO交叉編譯:解鎖Go語言開發的更多可能

在現代軟體開發中,跨平台支援已經成為一個重要的議題。不同的平台可能需要不同的二進位檔案格式或庫,這導致了開發者需要在多個平台上進行編譯。如果你使用的是Go語言,你有幸可以利用CGO交叉編譯來實現這一點。

CGO交叉編譯的基本概念

在沒有使用CGO的情況下,Go語言的交叉編譯非常簡單,只需使用少量的參數即可完成。以下是一個例子:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build

在這個命令中,我們使用了CGO_ENABLED=0來關閉CGO,然後通過GOOS和GOARCH來指定目標平台為Linux,架構為amd64。這樣我們就可以在不使用CGO的情況下進行編譯。

另外,我們還可以使用-ldflags選項來添加一些編譯選項,例如去除調試信息、靜態編譯等。以下是一個帶有這些選項的例子:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-s -w --extldflags "-static -fpic"' main.go

CGO的挑戰與解決辦法

然而,當我們需要使用CGO進行交叉編譯時,情況就變得複雜了。CGO(C Go調用)允許Go語言調用C函數,但這對於交叉編譯來說可能是一個障礙,因為不同的平台可能有不同的C庫。

在這種情況下,我們需要關閉CGO,並使用專門的編譯器和選項。以下是一個示例,展示了如何使用CGO進行交叉編譯:

CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC=x86_64-linux-musl-gcc CGO_LDFLAGS="-static" go build -a -v

在這個命令中,我們將CGO_ENABLED設置為1,以啟用CGO。然後,我們通過CC環境變數指定GCC編譯器,並使用CGO_LDFLAGS來指定CGO部分的編譯為靜態編譯。這樣我們就可以實現帶有CGO的交叉編譯。

跨平台編譯工具的應用

如果你是在macOS平台上進行開發,你可以通過一個名為musl-cross的工具來簡化交叉編譯的過程。以下是如何使用這個工具的步驟:

  1. 通過Homebrew安裝musl-cross工具:
brew install FiloSottile/musl-cross/musl-cross
  1. 安裝成功後,你可以使用musl-cross工具來實現交叉編譯。只需在編譯命令中指定編譯器和參數即可:
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC=x86_64-linux-musl-gcc CGO_LDFLAGS="-static" go build -a -v

結語

CGO交叉編譯是一個強大的工具,使得Go語言開發者能夠在不同的平台上進行開發和部署。無論是對於沒有CGO的純Go項目,還是帶有CGO的項目,我們都可以透過適當的參數和工具,輕鬆實現跨平台編譯的目標。這種靈活性為我們的開發帶來了更多可能性,使得我們能夠更方便地在不同的環境中進行測試和部署。

參考資料:

[Go語言涉及CGO的交叉編譯(跨平台編譯)解決辦法]
[FiloSottile/musl-cross - GitHub Repository] (https://github.com/FiloSottile/musl-cross)

Friday, May 27, 2022

[Golang] Golang with Cgo 動態連結(dynamic linking) 函式庫範例與筆記 in Linux environment

之前曾經動手實作並測試Golang with Cgo 動態連結(dynamic linking) 與 靜態連結(static linking)函式庫範例用在Windows環境,相關內容整理在這篇:

[Golang] Golang with Cgo 動態連結(dynamic linking) 與 靜態連結(static linking)函式庫範例與筆記 in Windows environment

最近看到一篇 "最简单的cgo示例",既簡單且完整的示範了Golang with Cgo 動態連結(dynamic linking) 函式庫範例在Linux環境,個人將其改寫並放到github上: 

Thursday, November 25, 2021

[xgo] The first phase of hacking xgo

 xgo is a great Go CGO cross compiler that can help users to build the application written in Golang to multi-platforms at the same time. 

For more information in details, please check out these URLs:

https://github.com/karalabe/xgo
https://www.jianshu.com/p/a6047d3f976e

But, without any further study, we probably cannot understand how it works well. So here I just give some information about it. I will use my Github repository as the example:

# Install xgo
go get github.com/karalabe/xgo
$ git clone https://github.com/teyenliu/win-shared-example
$ cd win-shared-example

# Use xgo to cross-compile to windows/amd64
xgo -targets windows/amd64 github.com/teyenliu/win-shared-example


Then, we finish the cross-compilation for my application
And actually, xgo, this tool, is based on its prebuilt docker image: "karalabe/xgo-latest" to complete the cross-compilation task. We can check the dockerhub for it as well: https://hub.docker.com/r/karalabe/xgo-latest/builds

So, we can directly run this Docker Image to cross-compile my application based on my case as follows:

$ docker run --rm -v /home/liudanny/git/xgo:/build \
-v /home/liudanny/.xgo-cache:/deps-cache:ro \
-e REPO_REMOTE= \
-e REPO_BRANCH= \
-e PACK= \
-e DEPS= \
-e ARGS= \
-e OUT= \
-e FLAG_V=false \
-e FLAG_X=false \
-e FLAG_RACE=false \
-e FLAG_TAGS= \
-e FLAG_LDFLAGS= \
-e FLAG_BUILDMODE=default \
-e TARGETS=windows/amd64 \
-e EXT_GOPATH= \
karalabe/xgo-latest \
github.com/teyenliu/win-shared-example


Furthermore, we can directly run xgo's build.sh to cross-compile my application in the host instead of in in the container:

$ sudo su
# set Golang path
export PATH=$PATH:/usr/local/go/bin
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin

# rm /deps in advance
rm -rf /deps

# run build.sh
env GO111MODULE=off \
env REPO_REMOTE= \
env REPO_BRANCH= \
env PACK= \
env DEPS= \
env ARGS= \
env OUT= \
env FLAG_V=false \
env FLAG_X=false \
env FLAG_RACE=false \
env FLAG_TAGS= \
env FLAG_LDFLAGS= \
env FLAG_BUILDMODE=default \
env TARGETS=windows/amd64 \
env EXT_GOPATH= \
env BUILD_DEPS=/home/liudanny/git/xgo/docker/base/build_deps.sh \
env BOOTSTRAP_REPO=/home/liudanny/git/xgo/docker/base/bootstrap_repo.sh \
env BOOTSTRAP_PURE=/home/liudanny/git/xgo/docker/base/bootstrap_pure.sh \
env BOOTSTRAP=/home/liudanny/git/xgo/docker/base/bootstrap.sh \
env PATH=/usr/local/go/bin:$PATH \
./build.sh github.com/teyenliu/win-shared-example

Reference:
Golang 交叉编译
Golang交叉编译各个平台的二进制文件
Fyne Cross Compile


The following commands are not succesful to work for cross-compilation
$ CGO_ENABLED=1 CXX="x86_64-w64-mingw32-g++" CXX_FOR_TARGET="x86_64-w64-mingw32-g++" CC="x86_64-w64-mingw32-gcc" CC_FOR_TARGET="x86_64-w64-mingw32-gcc" GOOS=windows GOARCH=amd64 \
go build -ldflags -v -x -installsuffix cgo -o example.exe main.go

$ GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc go build -ldflags -v -x -installsuffix cgo -o example.exe main.go


Friday, November 19, 2021

[Golang] Golang with Cgo 動態連結(dynamic linking) 與 靜態連結(static linking)函式庫範例與筆記 in Windows environment

This post is focusd on how to do dynamic/static linking using Golang with cgo on Windows environment. If you want to see it on Linux environment, please check out another post: 

[Golang] Golang with Cgo 動態連結(dynamic linking) 函式庫範例與筆記 in Linux environment

First of all, thanks to someone who had posted several useful articles describing how to do dynamic linking and static linking using Golang(Go) with Cgo in Windows environment as follows:

P.S: For using this example on Linux environment, you should deal with the build process for the static and dynamic libraries.

在 Windows 環境建置動態連結函式庫 (Dynamic-link library),使用 MinGW gcc/g++ 以及 CodeBlock

Go with Cgo 靜態連結 (static linking) 函式庫建置範例與筆記
Go with Cgo 動態連結 (dynamic linking) 函式庫建置範例與筆記