aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/rosa/cmake.go
blob: 14121609a1e86b25738edd15a4d7d6daf4b455a0 (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
package rosa

import (
	"slices"
	"strings"

	"hakurei.app/container/check"
	"hakurei.app/internal/pkg"
)

func (t Toolchain) newCMake() pkg.Artifact {
	const (
		version  = "4.2.1"
		checksum = "Y3OdbMsob6Xk2y1DCME6z4Fryb5_TkFD7knRT8dTNIRtSqbiCJyyDN9AxggN_I75"
	)
	return t.New("cmake-"+version, false, []pkg.Artifact{
		t.Load(Make),
		t.Load(KernelHeaders),
	}, nil, nil, `
# expected to be writable in the copy made during bootstrap
chmod -R +w /usr/src/cmake/Tests

cd "$(mktemp -d)"
/usr/src/cmake/bootstrap \
	--prefix=/system \
	--parallel="$(nproc)" \
	-- \
	-DCMAKE_USE_OPENSSL=OFF
make "-j$(nproc)"
make DESTDIR=/work install
`, pkg.Path(AbsUsrSrc.Append("cmake"), true,
		pkg.NewHTTPGetTar(
			nil, "https://github.com/Kitware/CMake/releases/download/"+
				"v"+version+"/cmake-"+version+".tar.gz",
			mustDecode(checksum),
			pkg.TarGzip,
		)))
}
func init() { artifactsF[CMake] = Toolchain.newCMake }

// CMakeAttr holds the project-specific attributes that will be applied to a new
// [pkg.Artifact] compiled via CMake.
type CMakeAttr struct {
	// Path elements joined with source.
	Append []string
	// Use source tree as scratch space.
	Writable bool
	// Dependencies concatenated with the build system itself.
	Extra []pkg.Artifact

	// CMake CACHE entries.
	Cache [][2]string
	// Additional environment variables.
	Env []string
	// Runs before cmake.
	ScriptEarly string
	// Runs after cmake.
	Script string

	// Override the default installation prefix [AbsSystem].
	Prefix *check.Absolute

	// Return an exclusive artifact.
	Exclusive bool
}

// NewViaCMake returns a [pkg.Artifact] for compiling and installing via CMake.
func (t Toolchain) NewViaCMake(
	name, version, variant string,
	source pkg.Artifact,
	attr *CMakeAttr,
) pkg.Artifact {
	if name == "" || version == "" || variant == "" {
		panic("names must be non-empty")
	}
	if attr == nil {
		attr = &CMakeAttr{
			Cache: [][2]string{
				{"CMAKE_BUILD_TYPE", "Release"},
			},
		}
	}
	if len(attr.Cache) == 0 {
		panic("CACHE must be non-empty")
	}

	scriptEarly := attr.ScriptEarly
	if attr.Writable {
		scriptEarly = `
chmod -R +w "${ROSA_SOURCE}"
` + scriptEarly
	}

	prefix := attr.Prefix
	if prefix == nil {
		prefix = AbsSystem
	}

	sourcePath := AbsUsrSrc.Append(name)
	return t.New(name+"-"+variant+"-"+version, attr.Exclusive, stage3Concat(t, attr.Extra,
		t.Load(CMake),
		t.Load(Ninja),
	), nil, slices.Concat([]string{
		"ROSA_SOURCE=" + sourcePath.String(),
		"ROSA_CMAKE_SOURCE=" + sourcePath.Append(attr.Append...).String(),
		"ROSA_INSTALL_PREFIX=/work" + prefix.String(),
	}, attr.Env), scriptEarly+`
mkdir /cure && cd /cure
cmake -G Ninja \
	-DCMAKE_C_COMPILER_TARGET="${ROSA_TRIPLE}" \
	-DCMAKE_CXX_COMPILER_TARGET="${ROSA_TRIPLE}" \
	-DCMAKE_ASM_COMPILER_TARGET="${ROSA_TRIPLE}" \
	`+strings.Join(slices.Collect(func(yield func(string) bool) {
		for _, v := range attr.Cache {
			if !yield("-D" + v[0] + "=" + v[1]) {
				return
			}
		}
	}), " \\\n\t")+` \
	-DCMAKE_INSTALL_PREFIX="${ROSA_INSTALL_PREFIX}" \
	"${ROSA_CMAKE_SOURCE}"
cmake --build .
cmake --install .
`+attr.Script, pkg.Path(sourcePath, attr.Writable, source))
}