aboutsummaryrefslogtreecommitdiff
blob: c1ed935e5643a16df5fa87b5c9eabf99f519bcdb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//===- context.go - Build context utilities for llgo ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Build context utilities for llgo.
//
//===----------------------------------------------------------------------===//

package build

import (
	"errors"
	"go/build"
	"regexp"
	"strings"
)

type Context struct {
	build.Context

	// LLVM triple
	Triple string
}

// ContextFromTriple returns a new go/build.Context with GOOS and GOARCH
// configured from the given triple.
func ContextFromTriple(triple string) (*Context, error) {
	goos, goarch, err := parseTriple(triple)
	if err != nil {
		return nil, err
	}
	ctx := &Context{Context: build.Default, Triple: triple}
	ctx.GOOS = goos
	ctx.GOARCH = goarch
	ctx.BuildTags = append(ctx.BuildTags, "llgo")
	if triple == "pnacl" {
		ctx.BuildTags = append(ctx.BuildTags, "pnacl")
	}
	return ctx, nil
}

func parseTriple(triple string) (goos string, goarch string, err error) {
	if strings.ToLower(triple) == "pnacl" {
		return "nacl", "le32", nil
	}

	type REs struct{ re, out string }
	// reference: http://llvm.org/docs/doxygen/html/Triple_8cpp_source.html
	goarchREs := []REs{
		{"amd64|x86_64", "amd64"},
		{"i[3-9]86", "386"},
		{"xscale|((arm|thumb)(v.*)?)", "arm"},
	}
	goosREs := []REs{
		{"linux.*", "linux"},
		{"(darwin|macosx|ios).*", "darwin"},
		{"k?freebsd.*", "freebsd"},
		{"netbsd.*", "netbsd"},
		{"openbsd.*", "openbsd"},
	}
	match := func(list []REs, s string) string {
		for _, t := range list {
			if matched, _ := regexp.MatchString(t.re, s); matched {
				return t.out
			}
		}
		return ""
	}

	s := strings.Split(triple, "-")
	switch l := len(s); l {
	default:
		return "", "", errors.New("triple should be made up of 2, 3, or 4 parts.")
	case 2, 3: // ARCHITECTURE-(VENDOR-)OPERATING_SYSTEM
		goarch = s[0]
		goos = s[l-1]
	case 4: // ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT
		goarch = s[0]
		goos = s[2]
	}
	goarch = match(goarchREs, goarch)
	if goarch == "" {
		return "", "", errors.New("unknown architecture in triple")
	}
	goos = match(goosREs, goos)
	if goos == "" {
		return "", "", errors.New("unknown OS in triple")
	}
	return goos, goarch, nil
}