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

import (
	"path/filepath"
	"slices"
	"strings"
)

var (
	_cmakeEarly = H("cmake-early")

	_cmake = H("cmake")
	_ninja = H("ninja")
)

// CMakeHelper builds and tests a CMake project with specified CACHE entries.
type CMakeHelper struct {
	// Path elements joined with source.
	Append []string

	// Use the bootstrap minimal [MakeHelper] CMake.
	Early bool

	// Value of CMAKE_BUILD_TYPE. The zero value is equivalent to "Release".
	BuildType string
	// CMake CACHE entries.
	Cache []KV
	// Runs after install.
	Script string

	// Replaces the default test command.
	Test string
	// Whether to skip running tests.
	SkipTest bool

	// Whether to generate Makefile instead.
	Make bool
}

var _ Helper = new(CMakeHelper)

// tools returns the cmake handle alongside either ninja or make.
func (attr *CMakeHelper) tools(Toolchain) P {
	h := _cmake
	if attr != nil && attr.Early {
		h = _cmakeEarly
	}

	if attr != nil && attr.Make {
		return P{h, _make}
	}
	return P{h, _ninja}
}

// inputs is a noop.
func (*CMakeHelper) inputs() P { return nil }

// wantsChmod returns false.
func (*CMakeHelper) wantsChmod() bool { return false }

// wantsWrite returns false.
func (*CMakeHelper) wantsWrite() bool { return false }

// scriptEarly returns the zero value.
func (*CMakeHelper) scriptEarly() string { return "" }

// wantsDir returns a hardcoded, deterministic pathname.
func (*CMakeHelper) wantsDir() (string, bool) { return "/cure/", true }

// script generates the cure script.
func (attr *CMakeHelper) script(t Toolchain, name string) string {
	if attr == nil {
		attr = new(CMakeHelper)
	}
	target := t.triple()

	generate := "Ninja"
	test := "ninja " + jobsFlagE + " " + loadFlagE + " test"
	if attr.Make {
		generate = "'Unix Makefiles'"
		test = "make " + jobsFlagE + " " + loadFlagE + " test"
	}
	if attr.Test != "" {
		test = attr.Test
	}

	script := attr.Script
	if !attr.SkipTest && t.opts&OptSkipCheck == 0 {
		script += "\n" + test
	}

	cache := make([]KV, 1, 1+len(attr.Cache))
	cache[0] = KV{"CMAKE_BUILD_TYPE", "Release"}
	if attr.BuildType != "" {
		cache[0][1] = attr.BuildType
	}
	cache = append(cache, attr.Cache...)

	var cross string
	if t.cross() {
		cross = `
	-DCMAKE_SYSTEM_NAME=Linux \
	-DCMAKE_SYSROOT=/system/` + t.arch + ` \
	-DCMAKE_C_COMPILER=/system/bin/clang \
	-DCMAKE_CXX_COMPILER=/system/bin/clang++ \
	-DCMAKE_ASM_COMPILER=/system/bin/clang \`
	}

	return `
cmake -G ` + generate + ` \
	-Wno-author -Wno-unused-cli \` + cross + `
	-DCMAKE_C_COMPILER_TARGET='` + target + `' \
	-DCMAKE_C_FLAGS='--target=` + target + `' \
	-DCMAKE_CXX_COMPILER_TARGET='` + target + `' \
	-DCMAKE_CXX_FLAGS='--target=` + target + `' \
	-DCMAKE_ASM_COMPILER_TARGET='` + target + `' \
	-DCMAKE_ASM_FLAGS='--target=` + target + `' \
	-DCMAKE_INSTALL_LIBDIR=lib \
	` + strings.Join(slices.Collect(func(yield func(string) bool) {
		for _, v := range cache {
			if !yield("-D" + v[0] + "=" + v[1]) {
				return
			}
		}
	}), " \\\n\t") + ` \
	-DCMAKE_INSTALL_PREFIX=/system \
	'/usr/src/` + name + `/` + filepath.Join(attr.Append...) + `'
cmake --build . --parallel=` + jobsE + ` -- ` + loadFlagE + `
DESTDIR=/work cmake --install .
` + script
}