This repository has been archived by the owner on Feb 17, 2022. It is now read-only.
/
target.go
156 lines (137 loc) · 4.13 KB
/
target.go
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright 2018 Schibsted
package buildbuild
import (
"errors"
"path"
"strings"
)
// Targets we want to generate.
type Target struct {
Rule string // Rule to generate the target.
Sources []string // Source files, path unresolved.
Deps []string
Srcopts []string
Destdir string // Destination directory, might be an alias defined in DestLookup
Extraargs []string // Various extra arguments like "cflags = -O0"
Options map[string]bool // Various output options, notably "all" makes this a default target.
CollectAs string
IncdepsExcept map[string]bool
MultiTarget []string // A single build generating multiple targets.
}
var (
MultipleDefinedTarget = errors.New("Multiple defined target. Rename your generated intermediate files.")
)
func (desc *GeneralDesc) AddTarget(tname, rule string, srcs []string, destdir, srcdir string, extraargs []string, options map[string]bool) *Target {
var srcopts []string
for _, src := range srcs {
if opt := desc.Srcopts[src]; len(opt) > 0 {
srcopts = append(srcopts, opt...)
}
}
if desc.Targets[tname] != nil {
tname = desc.renameTarget(tname, rule, srcs)
}
eas := append([]string(nil), extraargs...)
target := &Target{
Rule: rule,
Sources: srcs,
Srcopts: srcopts,
Extraargs: eas,
Destdir: destdir,
Options: options,
IncdepsExcept: make(map[string]bool),
}
desc.Targets[tname] = target
if desc.Srcdirs == nil {
desc.Srcdirs = make(map[string]string)
}
for _, src := range srcs {
desc.Srcdirs[src] = srcdir
}
return target
}
func (desc *GeneralDesc) renameTarget(tname, rule string, srcs []string) string {
// First we have to make sure that no target has already been renamed according
// to the rules below. If there was and we have three targets with the same
// name we can't resolve that. Rename your intermediate files.
tmpname := "TMP_BUILD" + tname
if desc.Targets[tmpname] != nil {
panic(&ParseError{MultipleDefinedTarget, tname, desc.Builddesc})
}
if strings.HasPrefix(rule, "install") {
// If our rule is install, we need to rename the old target so that
// all dependencies are on us.
for idx, src := range srcs {
if src == tname {
srcs[idx] = tmpname
}
}
prevtgt := desc.Targets[tname]
desc.Targets[tmpname] = prevtgt
if len(prevtgt.MultiTarget) > 0 {
for idx, t := range prevtgt.MultiTarget {
if t == tname {
prevtgt.MultiTarget[idx] = tmpname
break
}
}
}
delete(desc.Targets, tname)
desc.Srcdirs[tmpname] = desc.Srcdirs[tname]
delete(desc.Srcdirs, tname)
desc.Deps[tmpname] = desc.Deps[tname]
delete(desc.Deps, tname)
desc.Srcopts[tmpname] = desc.Srcopts[tname]
delete(desc.Srcopts, tname)
return tname
}
if strings.HasPrefix(desc.Targets[tname].Rule, "install") {
// if the already defined rule is install, we can change our
// name since no one will depend on us having the right name.
for idx, src := range desc.Targets[tname].Sources {
if src == tname {
desc.Targets[tname].Sources[idx] = tmpname
}
}
return tmpname
}
// If neither of the targets are install, we can't handle it.
panic(&ParseError{MultipleDefinedTarget, tname, desc.Builddesc})
}
func (g *GeneralDesc) AddMultiTarget(tnames []string, tgt *Target) {
tgt.MultiTarget = tnames
for idx, tname := range tnames {
prevtgt := g.Targets[tname]
if prevtgt != nil && prevtgt != tgt {
tname = g.renameTarget(tname, tgt.Rule, tgt.Sources)
tnames[idx] = tname
}
g.Targets[tname] = tgt
}
}
func (g *GeneralDesc) AllTargets() map[string]*Target {
return g.Targets
}
var DestLookup = map[string]string{
"obj": "$objdir/",
"objdir": "$objdir/",
"dest_inc": "$incdir/",
"dest_bin": "$dest_bin/",
"dest_tool": "$buildtools/",
"dest_lib": "$libdir/",
"dest_mod": "$dest_mod/",
"destroot": "$destroot/",
"builddir": "$builddir/",
"flavorroot": "$flavorroot/",
}
func (target *Target) ResolveDest() string {
dest := target.Destdir
parts := strings.SplitN(dest, "/", 2)
first := DestLookup[parts[0]]
if first != "" {
parts[0] = first
} else {
parts = append([]string{"$destroot"}, parts...)
}
return path.Join(parts...)
}