-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrule.go
More file actions
171 lines (150 loc) · 3.46 KB
/
Copy pathrule.go
File metadata and controls
171 lines (150 loc) · 3.46 KB
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package makefile
import (
"fmt"
"sort"
"strings"
)
//Rule is a Makefile rule
type Rule struct {
Name Text
Deps []Text
Command []*Command
Attr RuleAttributes
}
//AddDep adds a dependency to the Rule
func (r *Rule) AddDep(dep Text) *Rule {
if r.Deps == nil {
r.Deps = []Text{dep}
} else {
r.Deps = append(r.Deps, dep)
}
return r
}
//AddCmd adds an existing Command to a rule
func (r *Rule) AddCmd(c *Command) *Rule {
if r.Command == nil {
r.Command = []*Command{c}
} else {
r.Command = append(r.Command, c)
}
return r
}
//NewCmd creates a new Command and adds it to the rule
func (r *Rule) NewCmd(base string) *Command {
c := NewCmd(RawText(base))
r.AddCmd(c)
return c
}
//RuleAttributes is a struct containing the attributes of a Rule
type RuleAttributes struct {
OneShell bool //goes in front of rule as .ONESHELL:
Phony bool
Shell Text //shell to use, goes in deps as SHELL:=path
}
//Phony configures a Rule to be phony
func (r *Rule) Phony() *Rule {
r.Attr.Phony = true
return r
}
//OneShell configures a Rule to be built with one shell
func (r *Rule) OneShell() *Rule {
r.Attr.OneShell = true
return r
}
//SetShell configures a Rule to use the specified shell
func (r *Rule) SetShell(sh Text) *Rule {
r.Attr.Shell = sh
return r
}
//Print prunts a piece of Text
func (r *Rule) Print(txt Text) *Rule {
r.NewCmd("echo").AddArg(txt).SetNoPrint()
return r
}
//Command is a command in a rule/shell substitution
type Command struct {
Base Text //base is the program to invoke (e.g. gcc)
Args []Text
Env map[ShellVar]Text
NoPrint bool
}
func (c *Command) envString() string {
estrs := make([]string, len(c.Env))
i := 0
for n, v := range c.Env {
err := n.CheckValid()
if err != nil {
panic(err)
}
estrs[i] = fmt.Sprintf("%s=%s", n, v.Convert())
i++
}
sort.Strings(estrs)
return strings.Join(estrs, " ")
}
//String returns the command as a string
//NOTE: may panic
func (c *Command) String() string {
str := c.Base.Convert()
if len(c.Env) != 0 {
str = c.envString() + " " + str
}
if len(c.Args) != 0 {
astrs := make([]string, len(c.Args))
for i, v := range c.Args {
astrs[i] = v.Convert()
}
str = str + " " + strings.Join(astrs, " ")
}
if c.NoPrint {
str = "@" + str
}
return str
}
//NewCmd returns a command using base as the Base and args as arguments
func NewCmd(base Text) *Command {
return &Command{Base: base}
}
//AddArg adds an arg to a command
func (c *Command) AddArg(arg Text) *Command {
if c.Args == nil {
c.Args = []Text{arg}
} else {
c.Args = append(c.Args, arg)
}
return c
}
//AddArgSlice adds a slice of arguments to a command
func (c *Command) AddArgSlice(args []Text) *Command {
if c.Args == nil {
c.Args = args
} else {
c.Args = append(c.Args, args...)
}
return c
}
//SetNoPrint sets the NoPrint to true on a command
func (c *Command) SetNoPrint() *Command {
c.NoPrint = true
return c
}
//SetEnv sets an environment variable for the Command
func (c *Command) SetEnv(v ShellVar, val Text) *Command {
if c.Env == nil {
c.Env = make(map[ShellVar]Text)
}
c.Env[v] = val
return c
}
//Sub returns a shell substitution (Text) which substitutes in this command
func (c *Command) Sub() ShellSub {
return ShellSub{Cmd: c}
}
//ShellSub substitutes the output of a command
type ShellSub struct {
Cmd *Command
}
//Convert formats the ShellSub as a shell substitution
func (ss ShellSub) Convert() string {
return fmt.Sprintf("$(shell %s)", strings.TrimPrefix(ss.Cmd.String(), "@"))
}