Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
zengxs committed Nov 21, 2024
0 parents commit d7b628e
Show file tree
Hide file tree
Showing 14 changed files with 659 additions and 0 deletions.
27 changes: 27 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.go]
indent_style = tab

[Makefile]
indent_style = tab

[*.json]
indent_size = 2

[*.{yml,yaml}]
indent_size = 2
29 changes: 29 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Build
on:
push:
pull_request:

jobs:
cross-build:
runs-on: ubuntu-latest
env:
# Our script only installs the dependencies automatically if it's running inside Docker.
# GitHub Actions is not running inside Docker, so we need to set this environment variable
# to allow the automatic installation of the dependencies.
ALLOW_OUTSIDE_DOCKER: "1"
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.23.3"
- name: Build
run: |
go mod vendor
make all
- name: Test
run: ./dist/linux-amd64/demo --database-url=sqlite://./test.sqlite3
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
path: dist
63 changes: 63 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon?
![iI]con[_a-zA-Z0-9]

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk


### Go ###
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
go.work
go.work.sum

# env file
.env


### Project ###
/vendor/
/dist/
.zig-cache/
*.sqlite3
92 changes: 92 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
SOURCES := $(shell find . -name '*.go')
MAIN_PACKAGE_PATH := .

ZIG := $(CURDIR)/scripts/helpers/zig.sh
ZIG_CC := $(ZIG) cc -w
ZIG_CXX := $(ZIG) c++ -w

LIPO := $(CURDIR)/scripts/helpers/lipo.sh

LINUX_GOFLAGS := --ldflags '-linkmode external -w' -tags 'sqlite_json,sqlite_foreign_keys,sqlite_fts5'
LINUX_GLIBC_VERSION := 2.17

DARWIN_GOFLAGS = --ldflags '-linkmode external -w' -tags 'sqlite_json,sqlite_foreign_keys,sqlite_fts5'
DARWIN_SDKROOT = $(shell bash $(CURDIR)/scripts/find-darwin-sdkroot.sh)
DARWIN_ZIG_FLAGS = \
-I$(DARWIN_SDKROOT)/usr/include \
-L$(DARWIN_SDKROOT)/usr/lib \
-F$(DARWIN_SDKROOT)/System/Library/Frameworks

WINDOWS_GOFLAGS := -tags 'sqlite_json,sqlite_foreign_keys,sqlite_fts5'

# Always use build with cgo enabled
export CGO_ENABLED = 1


.PHONY: all
all: linux macos windows

.PHONY: clean
clean:
rm -rf dist

.PHONY: linux
linux: dist/linux-amd64/demo dist/linux-arm64/demo

dist/linux-amd64/demo: $(SOURCES)
$(eval export CC = $(ZIG_CC) --target=x86_64-linux-gnu.$(LINUX_GLIBC_VERSION))
$(eval export CXX = $(ZIG_CXX) --target=x86_64-linux-gnu.$(LINUX_GLIBC_VERSION))
$(eval export GOOS = linux)
$(eval export GOARCH = amd64)
@echo CC="$(CC)" CXX="$(CXX)" GOOS="$(GOOS)" GOARCH="$(GOARCH)"
go build $(LINUX_GOFLAGS) -o $@ $(MAIN_PACKAGE_PATH)

dist/linux-arm64/demo: $(SOURCES)
$(eval export CC = $(ZIG_CC) --target=aarch64-linux-gnu.$(LINUX_GLIBC_VERSION))
$(eval export CXX = $(ZIG_CXX) --target=aarch64-linux-gnu.$(LINUX_GLIBC_VERSION))
$(eval export GOOS = linux)
$(eval export GOARCH = arm64)
@echo CC="$(CC)" CXX="$(CXX)" GOOS="$(GOOS)" GOARCH="$(GOARCH)"
go build $(LINUX_GOFLAGS) -o $@ $(MAIN_PACKAGE_PATH)

.PHONY: macos
macos: dist/darwin/demo

dist/darwin/demo: dist/darwin-arm64/demo dist/darwin-amd64/demo
mkdir -p $(dir $@)
$(LIPO) -output $@ -create $^

dist/darwin-amd64/demo: $(SOURCES)
$(eval export CC = $(ZIG_CC) --target=x86_64-macos $(DARWIN_ZIG_FLAGS))
$(eval export CXX = $(ZIG_CXX) --target=x86_64-macos $(DARWIN_ZIG_FLAGS))
$(eval export GOOS = darwin)
$(eval export GOARCH = amd64)
@echo CC="$(CC)" CXX="$(CXX)" GOOS="$(GOOS)" GOARCH="$(GOARCH)"
go build $(DARWIN_GOFLAGS) -o $@ $(MAIN_PACKAGE_PATH)

dist/darwin-arm64/demo: $(SOURCES)
$(eval export CC = $(ZIG_CC) --target=aarch64-macos $(DARWIN_ZIG_FLAGS))
$(eval export CXX = $(ZIG_CXX) --target=aarch64-macos $(DARWIN_ZIG_FLAGS))
$(eval export GOOS = darwin)
$(eval export GOARCH = arm64)
@echo CC="$(CC)" CXX="$(CXX)" GOOS="$(GOOS)" GOARCH="$(GOARCH)"
go build $(DARWIN_GOFLAGS) -o $@ $(MAIN_PACKAGE_PATH)

.PHONY: windows
windows: dist/windows-amd64/demo.exe dist/windows-arm64/demo.exe

dist/windows-amd64/demo.exe: $(SOURCES)
$(eval export CC = $(ZIG_CC) --target=x86_64-windows-gnu)
$(eval export CXX = $(ZIG_CXX) --target=x86_64-windows-gnu)
$(eval export GOOS = windows)
$(eval export GOARCH = amd64)
@echo CC="$(CC)" CXX="$(CXX)" GOOS="$(GOOS)" GOARCH="$(GOARCH)"
go build $(WINDOWS_GOFLAGS) -o $@ $(MAIN_PACKAGE_PATH)

dist/windows-arm64/demo.exe: $(SOURCES)
$(eval export CC = $(ZIG_CC) --target=aarch64-windows-gnu)
$(eval export CXX = $(ZIG_CXX) --target=aarch64-windows-gnu)
$(eval export GOOS = windows)
$(eval export GOARCH = arm64)
@echo CC="$(CC)" CXX="$(CXX)" GOOS="$(GOOS)" GOARCH="$(GOARCH)"
go build $(WINDOWS_GOFLAGS) -o $@ $(MAIN_PACKAGE_PATH)
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# cross-cgo

This is a simple example of how to cross-compile a Go program that uses CGO.

## Overview

Most of the time, cross-compiling a Go program is as simple as setting the
`GOOS` and `GOARCH` environment variables. However, when you use CGO, things
get a bit more complicated. This is because CGO uses the C compiler and
linker to build the Go program, and these tools are platform-specific.

This example shows how to cross-compile a Go program that uses CGO. It uses
official golang Docker image to build the program for different platforms:

- Linux (amd64, arm64)
- Windows (amd64, arm64)
- macOS (amd64, arm64, universal2)

The cross-compilation has been tested on macOS and Linux. It should work on
Windows as well, but I haven't tested it.

The main dependencies is **zig** (as C compiler and linker) and
**MacOSX SDK** (for macOS target). The build script will download and install
these dependencies automatically.

The example program is a simple Go program that uses SQLite via CGO.
You can run the program with the following command:

```bash
# build for all platforms
make all
# run the program (choose the correct binary for your platform, e.g. linux-amd64)
./dist/linux-amd64/demo --database-url sqlite3://./test.sqlite3
```

## Issues

Zig version must be 0.14.0 or later due to this issue: https://github.com/ziglang/zig/issues/20243

Cross-compiling for macOS on other platforms must add `-w` flag to `ldflags` to avoid
DWARF generation error. (`dsymutil` is not available on other platforms).

Error occurs: `error: unable to create compilation: AccessDenied`. Run
`go mod vendor` to keep the dependencies in the project can fix this issue
(I don't know why).

Glibc version: you can specify the glibc version for Linux build by setting
`LINUX_GLIBC_VERSION` in Makefile, default is 2.17 (CentOS 7 compatible).
35 changes: 35 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module cross-cgo

go 1.23.3

require (
github.com/joho/godotenv v1.5.1
github.com/urfave/cli/v2 v2.27.5
github.com/xo/dburl v0.23.2
go.uber.org/fx v1.23.0
go.uber.org/zap v1.27.0
gorm.io/driver/mysql v1.5.7
gorm.io/driver/postgres v1.5.10
gorm.io/driver/sqlite v1.5.6
gorm.io/gorm v1.25.12
)

require (
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.5.5 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
go.uber.org/dig v1.18.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
)
69 changes: 69 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/xo/dburl v0.23.2 h1:Fl88cvayrgE56JA/sqhNMLljCW/b7RmG1mMkKMZUFgA=
github.com/xo/dburl v0.23.2/go.mod h1:uazlaAQxj4gkshhfuuYyvwCBouOmNnG2aDxTCFZpmL4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
go.uber.org/dig v1.18.0 h1:imUL1UiY0Mg4bqbFfsRQO5G4CGRBec/ZujWTvSVp3pw=
go.uber.org/dig v1.18.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
go.uber.org/fx v1.23.0 h1:lIr/gYWQGfTwGcSXWXu4vP5Ws6iqnNEIY+F/aFzCKTg=
go.uber.org/fx v1.23.0/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/driver/postgres v1.5.10 h1:7Lggqempgy496c0WfHXsYWxk3Th+ZcW66/21QhVFdeE=
gorm.io/driver/postgres v1.5.10/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE=
gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
Loading

0 comments on commit d7b628e

Please sign in to comment.