X Tutup
Skip to content

Commit a9bebff

Browse files
authored
Merge pull request cli#3383 from cli/build-env
Tweak build scripts to enable cross-compiling
2 parents bc681b9 + d437206 commit a9bebff

File tree

3 files changed

+69
-24
lines changed

3 files changed

+69
-24
lines changed

Makefile

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,27 @@ export CGO_CFLAGS
55
CGO_LDFLAGS ?= $(filter -g -L% -l% -O%,${LDFLAGS})
66
export CGO_LDFLAGS
77

8+
EXE =
9+
ifeq ($(GOOS),windows)
10+
EXE = .exe
11+
endif
12+
813
## The following tasks delegate to `script/build.go` so they can be run cross-platform.
914

10-
.PHONY: bin/gh
11-
bin/gh: script/build
12-
@script/build bin/gh
15+
.PHONY: bin/gh$(EXE)
16+
bin/gh$(EXE): script/build
17+
@script/build $@
1318

1419
script/build: script/build.go
15-
go build -o script/build script/build.go
20+
GOOS= GOARCH= GOARM= GOFLAGS= CGO_ENABLED= go build -o $@ $<
1621

1722
.PHONY: clean
1823
clean: script/build
19-
@script/build clean
24+
@script/build $@
2025

2126
.PHONY: manpages
2227
manpages: script/build
23-
@script/build manpages
28+
@script/build $@
2429

2530
# just a convenience task around `go test`
2631
.PHONY: test

docs/source.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,33 @@
2727
```
2828

2929
#### Windows
30-
```sh
30+
```pwsh
3131
# build the `bin\gh.exe` binary
32-
> go run script/build.go
32+
> go run script\build.go
3333
```
3434
There is no install step available on Windows.
3535

3636
3. Run `gh version` to check if it worked.
3737

3838
#### Windows
3939
Run `bin\gh version` to check if it worked.
40+
41+
## Cross-compiling binaries for different platforms
42+
43+
You can use any platform with Go installed to build a binary that is intended for another platform
44+
or CPU architecture. This is achieved by setting environment variables such as GOOS and GOARCH.
45+
46+
For example, to compile the `gh` binary for the 32-bit Raspberry Pi OS:
47+
```sh
48+
# on a Unix-like system:
49+
$ GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=0 make clean bin/gh
50+
```
51+
```pwsh
52+
# on Windows, pass environment variables as arguments to the build script:
53+
> go run script\build.go clean bin\gh GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=0
54+
```
55+
56+
Run `go tool dist list` to list all supported values of GOOS/GOARCH.
57+
58+
Tip: to reduce the size of the resulting binary, you can use `GO_LDFLAGS="-s -w"`. This omits
59+
symbol tables used for debugging. See the list of [supported linker flags](https://golang.org/cmd/link/).

script/build.go

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Build tasks for the GitHub CLI project.
22
//
3-
// Usage: go run script/build.go [<task>]
3+
// Usage: go run script/build.go [<tasks>...] [<env>...]
44
//
55
// Known tasks are:
66
//
@@ -65,32 +65,52 @@ var tasks = map[string]func(string) error{
6565
var self string
6666

6767
func main() {
68-
task := "bin/gh"
69-
if runtime.GOOS == "windows" {
70-
task = "bin\\gh.exe"
68+
args := os.Args[:1]
69+
for _, arg := range os.Args[1:] {
70+
if idx := strings.IndexRune(arg, '='); idx >= 0 {
71+
os.Setenv(arg[:idx], arg[idx+1:])
72+
} else {
73+
args = append(args, arg)
74+
}
7175
}
7276

73-
if len(os.Args) > 1 {
74-
task = os.Args[1]
77+
if len(args) < 2 {
78+
if isWindowsTarget() {
79+
args = append(args, filepath.Join("bin", "gh.exe"))
80+
} else {
81+
args = append(args, "bin/gh")
82+
}
7583
}
7684

77-
self = filepath.Base(os.Args[0])
85+
self = filepath.Base(args[0])
7886
if self == "build" {
7987
self = "build.go"
8088
}
8189

82-
t := tasks[normalizeTask(task)]
83-
if t == nil {
84-
fmt.Fprintf(os.Stderr, "Don't know how to build task `%s`.\n", task)
85-
os.Exit(1)
90+
for _, task := range args[1:] {
91+
t := tasks[normalizeTask(task)]
92+
if t == nil {
93+
fmt.Fprintf(os.Stderr, "Don't know how to build task `%s`.\n", task)
94+
os.Exit(1)
95+
}
96+
97+
err := t(task)
98+
if err != nil {
99+
fmt.Fprintln(os.Stderr, err)
100+
fmt.Fprintf(os.Stderr, "%s: building task `%s` failed.\n", self, task)
101+
os.Exit(1)
102+
}
86103
}
104+
}
87105

88-
err := t(task)
89-
if err != nil {
90-
fmt.Fprintln(os.Stderr, err)
91-
fmt.Fprintf(os.Stderr, "%s: building task `%s` failed.\n", self, task)
92-
os.Exit(1)
106+
func isWindowsTarget() bool {
107+
if os.Getenv("GOOS") == "windows" {
108+
return true
109+
}
110+
if runtime.GOOS == "windows" {
111+
return true
93112
}
113+
return false
94114
}
95115

96116
func version() string {

0 commit comments

Comments
 (0)
X Tutup