1package xcaddy
2
3import (
4	"encoding/json"
5	"os/exec"
6)
7
8// Compile contains parameters for compilation.
9type Compile struct {
10	Platform
11	Cgo bool `json:"cgo,omitempty"`
12}
13
14// CgoEnabled returns "1" if c.Cgo is true, "0" otherwise.
15// This is used for setting the CGO_ENABLED env variable.
16func (c Compile) CgoEnabled() string {
17	if c.Cgo {
18		return "1"
19	}
20	return "0"
21}
22
23// Platform represents a build target.
24type Platform struct {
25	OS   string `json:"os,omitempty"`
26	Arch string `json:"arch,omitempty"`
27	ARM  string `json:"arm,omitempty"`
28}
29
30// SupportedPlatforms runs `go tool dist list` to make
31// a list of possible build targets.
32func SupportedPlatforms() ([]Compile, error) {
33	out, err := exec.Command("go", "tool", "dist", "list", "-json").Output()
34	if err != nil {
35		return nil, err
36	}
37	var dists []dist
38	err = json.Unmarshal(out, &dists)
39	if err != nil {
40		return nil, err
41	}
42
43	// translate from the go command's output structure
44	// to our own user-facing structure
45	var compiles []Compile
46	for _, d := range dists {
47		comp := d.toCompile()
48		if d.GOARCH == "arm" {
49			if d.GOOS == "linux" {
50				// only linux supports ARMv5; see https://github.com/golang/go/issues/18418
51				comp.ARM = "5"
52				compiles = append(compiles, comp)
53			}
54			comp.ARM = "6"
55			compiles = append(compiles, comp)
56			comp.ARM = "7"
57			compiles = append(compiles, comp)
58		} else {
59			compiles = append(compiles, comp)
60		}
61	}
62
63	return compiles, nil
64}
65
66// dist is the structure that fits the output
67// of the `go tool dist list -json` command.
68type dist struct {
69	GOOS         string `json:"GOOS"`
70	GOARCH       string `json:"GOARCH"`
71	CgoSupported bool   `json:"CgoSupported"`
72}
73
74func (d dist) toCompile() Compile {
75	return Compile{
76		Platform: Platform{
77			OS:   d.GOOS,
78			Arch: d.GOARCH,
79		},
80		Cgo: d.CgoSupported,
81	}
82}
83