aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/rosa/make.go
blob: ecec3a5d7ccd7ff57e75836bc75c2ce37a6a4747 (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
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
package rosa

import (
	"slices"
	"strings"

	"hakurei.app/internal/pkg"
)

func (t Toolchain) newMake() (pkg.Artifact, string) {
	const (
		version  = "4.4.1"
		checksum = "YS_B07ZcAy9PbaK5_vKGj64SrxO2VMpnMKfc9I0Q9IC1rn0RwOH7802pJoj2Mq4a"
	)
	return t.New("make-"+version, TEarly, nil, nil, nil, `
cd "$(mktemp -d)"
/usr/src/make/configure \
	--prefix=/system \
	--build="${ROSA_TRIPLE}" \
	--disable-dependency-tracking
./build.sh
./make DESTDIR=/work install
`, pkg.Path(AbsUsrSrc.Append("make"), false, newTar(
		"https://ftpmirror.gnu.org/gnu/make/make-"+version+".tar.gz",
		checksum,
		pkg.TarGzip,
	))), version
}
func init() {
	artifactsM[Make] = Metadata{
		f: Toolchain.newMake,

		Name:        "make",
		Description: "a tool which controls the generation of executables and other non-source files",
		Website:     "https://www.gnu.org/software/make/",

		ID: 1877,
	}
}

// MakeHelper is the [Make] build system helper.
type MakeHelper struct {
	// Do not include default extras.
	OmitDefaults bool

	// Command to generate the build system.
	Generate string
	// Runs before make.
	ScriptMakeEarly string
	// Runs before check.
	ScriptCheckEarly string
	// Runs after install.
	Script string

	// Remain in current directory.
	InPlace bool

	// Whether to skip running the configure script.
	SkipConfigure bool
	// Alternative name for the configure script.
	ConfigureName string
	// Flags passed to the configure script.
	Configure []KV
	// Host target triple, zero value is equivalent to the Rosa OS triple.
	Host string
	// Target triple, zero value is equivalent to the Rosa OS triple.
	Build string

	// Extra make targets.
	Make []string
	// Whether to skip the check target.
	SkipCheck bool
	// Name of the check target, zero value is equivalent to "check".
	Check []string
	// Replaces the default install command.
	Install string
}

var _ Helper = new(MakeHelper)

// extra returns make and other optional dependencies.
func (attr *MakeHelper) extra(flag int) P {
	extra := P{Make}
	if (attr == nil || !attr.OmitDefaults) && flag&TEarly == 0 {
		extra = append(extra,
			Gawk,
			Coreutils,
		)
	}
	return extra
}

// wantsChmod returns whether the build system needs to be generated.
func (attr *MakeHelper) wantsChmod() bool {
	return attr != nil && attr.Generate != ""
}

// wantsWrite is equivalent to wantsChmod.
func (attr *MakeHelper) wantsWrite() bool { return attr.wantsChmod() }

// scriptEarly returns the optional build system generation segment.
func (attr *MakeHelper) scriptEarly() string {
	if attr == nil {
		return ""
	}

	generate := attr.Generate
	if len(generate) > 0 && generate[len(generate)-1] != '\n' {
		generate += "\n"
	}
	return generate
}

// createDir returns false.
func (*MakeHelper) createDir() bool { return false }

// wantsDir requests a new directory in TMPDIR, or omits the cd statement if InPlace.
func (attr *MakeHelper) wantsDir() string {
	if attr != nil && attr.InPlace {
		return helperInPlace
	}
	return `"$(mktemp -d)"`
}

// script generates the cure script.
func (attr *MakeHelper) script(name string) string {
	if attr == nil {
		attr = new(MakeHelper)
	}

	var configure string
	if !attr.SkipConfigure {
		configure = attr.ConfigureName
		if configure == "" {
			configure += `/usr/src/` + name + `/configure \
	--prefix=/system`

			host := `"${ROSA_TRIPLE}"`
			if attr.Host != "" {
				host = attr.Host
			}
			if attr.Host != `""` {
				configure += ` \
	--host=` + host
			}

			build := `"${ROSA_TRIPLE}"`
			if attr.Build != "" {
				build = attr.Build
			}
			if attr.Build != `""` {
				configure += ` \
	--build=` + build
			}
		}

		if len(attr.Configure) > 0 {
			const sep = " \\\n\t"
			configure += sep + strings.Join(
				slices.Collect(func(yield func(string) bool) {
					for _, v := range attr.Configure {
						s := v[0]
						if v[0] != "" &&
							v[0][0] >= 'a' &&
							v[0][0] <= 'z' {
							s = "--" + s
						} else if len(v[0]) > 1 &&
							v[0][0] == 'D' &&
							v[0][1] >= 'a' &&
							v[0][1] <= 'z' {
							s = "-" + s
						}
						if v[1] != "" {
							if v[0] != "" {
								s += "="
							}
							s += v[1]
						}
						if !yield(s) {
							return
						}
					}
				}),
				sep,
			)
		}
	}

	scriptMake := `
make \
	` + jobsFlagE
	if len(attr.Make) > 0 {
		scriptMake += " \\\n\t" + strings.Join(attr.Make, " \\\n\t")
	}
	scriptMake += "\n"

	if !attr.SkipCheck {
		scriptMake += attr.ScriptCheckEarly + `make \
	` + jobsFlagE + ` \
	`
		if len(attr.Check) > 0 {
			scriptMake += strings.Join(attr.Check, " \\\n\t")
		} else {
			scriptMake += "check"
		}
		scriptMake += "\n"
	}

	scriptInstall := attr.Install
	if scriptInstall == "" {
		scriptInstall = "make DESTDIR=/work install"
	}
	scriptInstall += "\n"

	return configure +
		attr.ScriptMakeEarly +
		scriptMake +
		scriptInstall +
		attr.Script
}