Port select portions of Makefile to script/build.go
This is to enable build tasks on Windows.
This commit is contained in:
parent
5e97775978
commit
39431a101d
4 changed files with 215 additions and 32 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -6,6 +6,7 @@
|
|||
/site
|
||||
.github/**/node_modules
|
||||
/CHANGELOG.md
|
||||
/script/build
|
||||
|
||||
# VS Code
|
||||
.vscode
|
||||
|
|
|
|||
42
Makefile
42
Makefile
|
|
@ -1,14 +1,3 @@
|
|||
BUILD_FILES = $(shell go list -f '{{range .GoFiles}}{{$$.Dir}}/{{.}}\
|
||||
{{end}}' ./...)
|
||||
|
||||
GH_VERSION ?= $(shell git describe --tags 2>/dev/null || git rev-parse --short HEAD)
|
||||
DATE_FMT = +%Y-%m-%d
|
||||
ifdef SOURCE_DATE_EPOCH
|
||||
BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "$(DATE_FMT)" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "$(DATE_FMT)" 2>/dev/null || date -u "$(DATE_FMT)")
|
||||
else
|
||||
BUILD_DATE ?= $(shell date "$(DATE_FMT)")
|
||||
endif
|
||||
|
||||
CGO_CPPFLAGS ?= ${CPPFLAGS}
|
||||
export CGO_CPPFLAGS
|
||||
CGO_CFLAGS ?= ${CFLAGS}
|
||||
|
|
@ -16,27 +5,29 @@ export CGO_CFLAGS
|
|||
CGO_LDFLAGS ?= $(filter -g -L% -l% -O%,${LDFLAGS})
|
||||
export CGO_LDFLAGS
|
||||
|
||||
GO_LDFLAGS := -X github.com/cli/cli/internal/build.Version=$(GH_VERSION) $(GO_LDFLAGS)
|
||||
GO_LDFLAGS := -X github.com/cli/cli/internal/build.Date=$(BUILD_DATE) $(GO_LDFLAGS)
|
||||
ifdef GH_OAUTH_CLIENT_SECRET
|
||||
GO_LDFLAGS := -X github.com/cli/cli/internal/authflow.oauthClientID=$(GH_OAUTH_CLIENT_ID) $(GO_LDFLAGS)
|
||||
GO_LDFLAGS := -X github.com/cli/cli/internal/authflow.oauthClientSecret=$(GH_OAUTH_CLIENT_SECRET) $(GO_LDFLAGS)
|
||||
endif
|
||||
.PHONY: bin/gh
|
||||
bin/gh: script/build
|
||||
@script/build bin/gh
|
||||
|
||||
bin/gh: $(BUILD_FILES)
|
||||
go build -trimpath -ldflags "${GO_LDFLAGS}" -o "$@" ./cmd/gh
|
||||
script/build: script/build.go
|
||||
go build -o script/build script/build.go
|
||||
|
||||
clean:
|
||||
rm -rf ./bin ./share
|
||||
.PHONY: clean
|
||||
clean: script/build
|
||||
@script/build clean
|
||||
|
||||
.PHONY: manpages
|
||||
manpages: script/build
|
||||
@script/build manpages
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go test ./...
|
||||
.PHONY: test
|
||||
|
||||
site:
|
||||
git clone https://github.com/github/cli.github.com.git "$@"
|
||||
|
||||
.PHONY: site-docs
|
||||
site-docs: site
|
||||
git -C site pull
|
||||
git -C site rm 'manual/gh*.md' 2>/dev/null || true
|
||||
|
|
@ -44,8 +35,8 @@ site-docs: site
|
|||
rm -f site/manual/*.bak
|
||||
git -C site add 'manual/gh*.md'
|
||||
git -C site commit -m 'update help docs' || true
|
||||
.PHONY: site-docs
|
||||
|
||||
.PHONY: site-bump
|
||||
site-bump: site-docs
|
||||
ifndef GITHUB_REF
|
||||
$(error GITHUB_REF is not set)
|
||||
|
|
@ -53,11 +44,6 @@ endif
|
|||
sed -i.bak -E 's/(assign version = )".+"/\1"$(GITHUB_REF:refs/tags/v%=%)"/' site/index.html
|
||||
rm -f site/index.html.bak
|
||||
git -C site commit -m '$(GITHUB_REF:refs/tags/v%=%)' index.html
|
||||
.PHONY: site-bump
|
||||
|
||||
.PHONY: manpages
|
||||
manpages:
|
||||
go run ./cmd/gen-docs --man-page --doc-path ./share/man/man1/
|
||||
|
||||
DESTDIR :=
|
||||
prefix := /usr/local
|
||||
|
|
|
|||
|
|
@ -22,18 +22,18 @@
|
|||
# installs to '/usr/local' by default; sudo may be required
|
||||
$ make install
|
||||
|
||||
# install to a different location
|
||||
# or, install to a different location
|
||||
$ make install prefix=/path/to/gh
|
||||
```
|
||||
|
||||
#### Windows
|
||||
```sh
|
||||
# build the binary
|
||||
> go build -o gh.exe ./cmd/gh
|
||||
# build the `bin\gh.exe` binary
|
||||
> go run script/build.go
|
||||
```
|
||||
There is no install step available on Windows.
|
||||
|
||||
3. Run `gh version` to check if it worked.
|
||||
|
||||
#### Windows
|
||||
Run `.\gh version` to check if it worked.
|
||||
Run `bin\gh version` to check if it worked.
|
||||
|
|
|
|||
196
script/build.go
Normal file
196
script/build.go
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
// Build tasks for the GitHub CLI project.
|
||||
//
|
||||
// Usage: go run script/build.go [<task>]
|
||||
//
|
||||
// Known tasks are:
|
||||
//
|
||||
// bin/gh:
|
||||
// Builds the main executable.
|
||||
// Supported environment variables:
|
||||
// - GH_VERSION: determined from source by default
|
||||
// - GH_OAUTH_CLIENT_ID
|
||||
// - GH_OAUTH_CLIENT_SECRET
|
||||
// - SOURCE_DATE_EPOCH: enables reproducible builds
|
||||
// - GO_LDFLAGS
|
||||
//
|
||||
// manpages:
|
||||
// Builds the man pages under `share/man/man1/`.
|
||||
//
|
||||
// clean:
|
||||
// Deletes all built files.
|
||||
//
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cli/safeexec"
|
||||
)
|
||||
|
||||
var tasks = map[string]func(string) error{
|
||||
"bin/gh": func(exe string) error {
|
||||
info, err := os.Stat(exe)
|
||||
if err == nil && !sourceFilesLaterThan(info.ModTime()) {
|
||||
fmt.Printf("%s: `%s` is up to date.\n", self, exe)
|
||||
return nil
|
||||
}
|
||||
|
||||
ldflags := os.Getenv("GO_LDFLAGS")
|
||||
ldflags = fmt.Sprintf("-X github.com/cli/cli/internal/build.Version=%s %s", version(), ldflags)
|
||||
ldflags = fmt.Sprintf("-X github.com/cli/cli/internal/build.Date=%s %s", date(), ldflags)
|
||||
if oauthSecret := os.Getenv("GH_OAUTH_CLIENT_SECRET"); oauthSecret != "" {
|
||||
ldflags = fmt.Sprintf("-X github.com/cli/cli/internal/authflow.oauthClientSecret=%s %s", oauthSecret, ldflags)
|
||||
ldflags = fmt.Sprintf("-X github.com/cli/cli/internal/authflow.oauthClientID=%s %s", os.Getenv("GH_OAUTH_CLIENT_ID"), ldflags)
|
||||
}
|
||||
|
||||
return run("go", "build", "-trimpath", "-ldflags", ldflags, "-o", exe, "./cmd/gh")
|
||||
},
|
||||
"manpages": func(_ string) error {
|
||||
return run("go", "run", "./cmd/gen-docs", "--man-page", "--doc-path", "./share/man/man1/")
|
||||
},
|
||||
"clean": func(_ string) error {
|
||||
return rmrf("bin", "share")
|
||||
},
|
||||
}
|
||||
|
||||
var self string
|
||||
|
||||
func main() {
|
||||
task := "bin/gh"
|
||||
if runtime.GOOS == "windows" {
|
||||
task = "bin\\gh.exe"
|
||||
}
|
||||
|
||||
if len(os.Args) > 1 {
|
||||
task = os.Args[1]
|
||||
}
|
||||
|
||||
self = filepath.Base(os.Args[0])
|
||||
if self == "build" {
|
||||
self = "build.go"
|
||||
}
|
||||
|
||||
t := tasks[normalizeTask(task)]
|
||||
if t == nil {
|
||||
fmt.Fprintf(os.Stderr, "Don't know how to build task `%s`.\n", task)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err := t(task)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
fmt.Fprintf(os.Stderr, "%s: building task `%s` failed.\n", self, task)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func version() string {
|
||||
if versionEnv := os.Getenv("GH_VERSION"); versionEnv != "" {
|
||||
return versionEnv
|
||||
}
|
||||
if desc, err := cmdOutput("git", "describe", "--tags"); err == nil {
|
||||
return desc
|
||||
}
|
||||
rev, _ := cmdOutput("git", "rev-parse", "--short", "HEAD")
|
||||
return rev
|
||||
}
|
||||
|
||||
func date() string {
|
||||
t := time.Now()
|
||||
if sourceDate := os.Getenv("SOURCE_DATE_EPOCH"); sourceDate != "" {
|
||||
if sec, err := strconv.ParseInt(sourceDate, 10, 64); err == nil {
|
||||
t = time.Unix(sec, 0)
|
||||
}
|
||||
}
|
||||
return t.Format("2006-01-02")
|
||||
}
|
||||
|
||||
func sourceFilesLaterThan(t time.Time) bool {
|
||||
foundLater := false
|
||||
_ = filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if foundLater {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if len(path) > 1 && (path[0] == '.' || path[0] == '_') {
|
||||
if info.IsDir() {
|
||||
return filepath.SkipDir
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if path == "go.mod" || path == "go.sum" || (strings.HasSuffix(path, ".go") && !strings.HasSuffix(path, "_test.go")) {
|
||||
if info.ModTime().After(t) {
|
||||
foundLater = true
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return foundLater
|
||||
}
|
||||
|
||||
func rmrf(targets ...string) error {
|
||||
args := append([]string{"rm", "-rf"}, targets...)
|
||||
announce(args...)
|
||||
for _, target := range targets {
|
||||
if err := os.RemoveAll(target); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func announce(args ...string) {
|
||||
fmt.Println(shellInspect(args))
|
||||
}
|
||||
|
||||
func run(args ...string) error {
|
||||
exe, err := safeexec.LookPath(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
announce(args...)
|
||||
cmd := exec.Command(exe, args[1:]...)
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func cmdOutput(args ...string) (string, error) {
|
||||
exe, err := safeexec.LookPath(args[0])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cmd := exec.Command(exe, args[1:]...)
|
||||
cmd.Stderr = ioutil.Discard
|
||||
out, err := cmd.Output()
|
||||
return strings.TrimSuffix(string(out), "\n"), err
|
||||
}
|
||||
|
||||
func shellInspect(args []string) string {
|
||||
fmtArgs := make([]string, len(args))
|
||||
for i, arg := range args {
|
||||
if strings.ContainsAny(arg, " \t'\"") {
|
||||
fmtArgs[i] = fmt.Sprintf("%q", arg)
|
||||
} else {
|
||||
fmtArgs[i] = arg
|
||||
}
|
||||
}
|
||||
return strings.Join(fmtArgs, " ")
|
||||
}
|
||||
|
||||
func normalizeTask(t string) string {
|
||||
return filepath.ToSlash(strings.TrimSuffix(t, ".exe"))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue