summaryrefslogtreecommitdiff
path: root/eclass/crystal-utils.eclass
blob: a1819472d28f36eceb48d86695b8b1d18ec1b59f (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
# Copyright 2022-2026 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

# @ECLASS: crystal-utils.eclass
# @MAINTAINER:
# Anna <cyber+gentoo@sysrq.in>
# @AUTHOR:
# Anna <cyber+gentoo@sysrq.in>
# @SUPPORTED_EAPIS: 8 9
# @BLURB: utility functions for Crystal packages
# @DESCRIPTION:
# A utility eclass providing functions to invoke Crystal.
#
# This eclass does not set any metadata variables nor export any phase, so it
# can be inherited safely.
#
# All helper functions die on failure and support being called via 'nonfatal'.

case ${EAPI} in
	8) inherit edo ;;
	9) ;;
	*) die "${ECLASS}: EAPI ${EAPI} unsupported."
esac

if [[ ! ${_CRYSTAL_UTILS_ECLASS} ]]; then
_CRYSTAL_UTILS_ECLASS=1

inherit flag-o-matic multiprocessing

# @ECLASS_VARIABLE: CRYSTAL_MAX_VER
# @DEFAULT_UNSET
# @PRE_INHERIT
# @DESCRIPTION:
# Highest Crystal version supported by the package. If unset, no upper bound
# is assumed.

# @ECLASS_VARIABLE: CRYSTAL_MIN_VER
# @PRE_INHERIT
# @DESCRIPTION:
# Lowest Crystal version supported by the package.
: "${CRYSTAL_MIN_VER:=1.16.3}"

# @ECLASS_VARIABLE: CRYSTAL_DEPS
# @OUTPUT_VARIABLE
# @DESCRIPTION:
# This is an eclass-generated Crystal dependency string.
CRYSTAL_DEPS="
	|| (
		>=dev-lang/crystal-${CRYSTAL_MIN_VER}
		>=dev-lang/crystal-bin-${CRYSTAL_MIN_VER}
	)
${CRYSTAL_MAX_VER:+\
	|| (
		<=dev-lang/crystal-${CRYSTAL_MAX_VER}-r9999
		<=dev-lang/crystal-bin-${CRYSTAL_MAX_VER}-r9999
	)
}"

# @ECLASS_VARIABLE: SHARDS_DEPS
# @OUTPUT_VARIABLE
# @DESCRIPTION:
# This is an eclass-generated Shards dependency string.
SHARDS_DEPS="
	|| (
		dev-util/shards
		dev-lang/crystal-bin
	)
"

# @ECLASS_VARIABLE: CRYSTAL_DEFINES
# @DEFAULT_UNSET
# @DESCRIPTION:
# List of compile-time defines.  Used by 'crystal build' and 'crystal docs'.

# @FUNCTION: _crystal_get_colors_opt
# @INTERNAL
# @RETURN: "--no-color" if colors should be disabled, empty string otherwise
_crystal_get_colors_opt() {
	if [[ ${NOCOLOR} == "true" || ${NOCOLOR} == "yes" ]]; then
		echo "--no-color"
	fi
}

# @FUNCTION: _crystal_get_debug_opt
# @INTERNAL
# @RETURN: "--debug" if USE=debug, "--no-debug" otherwise
_crystal_get_debug_opt() {
	if has debug ${IUSE} && use debug; then
		echo "--debug"
	else
		echo "--no-debug"
	fi
}

# @FUNCTION: crystal_configure
# @DESCRIPTION:
# Set Crystal environment variables to match user settings.
#
# Passes arguments to Crystal by reading from an optionally pre-defined local
# mycrystalargs bash array.
#
# Must be run or ecrystal/eshards will fail.
crystal_configure() {
	debug-print-function ${FUNCNAME} "${@}"

	# avoid possible sandbox violation
	export CRYSTAL_CACHE_DIR="${T}/crystal"
	export SHARDS_CACHE_PATH="${T}/shards"

	[[ -z ${mycrystalargs} ]] && local -a mycrystalargs=()
	local mycrystalargstype=$(declare -p mycrystalargs 2>&-)
	if [[ "${mycrystalargstype}" != "declare -a mycrystalargs="* ]]; then
		die "mycrystalargs must be declared as array"
	fi

	local args=(
		--link-flags="\"${LDFLAGS}\""
		--error-trace
		--release
		--progress
		$(_crystal_get_debug_opt)
		$(_crystal_get_colors_opt)
		$(is-flagq -mcpu && echo "--mcpu=$(get-flag mcpu)")
		$(is-flagq -mcmodel && echo "--mcmodel=$(get-flag mcmodel)")
		# TODO: --mattr
		"${CRYSTAL_DEFINES[@]}"
		"${mycrystalargs[@]}"
	)

	export CRYSTAL_OPTS="${args[@]}"

	_CRYSTAL_CONFIGURE_HAS_RUN=1
}

# @FUNCTION: ecrystal
# @USAGE: [<args>...]
# @DESCRIPTION:
# Call crystal, passing supplied arguments.
ecrystal() {
	debug-print-function ${FUNCNAME} "${@}"

	[[ ${_CRYSTAL_CONFIGURE_HAS_RUN} ]] || \
		die "${FUNCNAME}: crystal_configure has not been run"

	mkdir -p "${CRYSTAL_CACHE_DIR}" || die "Creating Crystal cache dir failed"
	edo crystal "${@}"
}

# @FUNCTION: eshards
# @USAGE: [<args>...]
# @DESCRIPTION:
# Call shards, passing the standard set of options, then supplied arguments.
eshards() {
	debug-print-function ${FUNCNAME} "${@}"

	[[ ${_CRYSTAL_CONFIGURE_HAS_RUN} ]] || \
		die "${FUNCNAME}: crystal_configure has not been run"

	mkdir -p "${CRYSTAL_CACHE_DIR}" || die "Creating Crystal cache dir failed"
	mkdir -p "${SHARDS_CACHE_PATH}" || die "Creating Shards cache dir failed"

	local args=(
		--local
		--without-development
		$(_crystal_get_colors_opt)
	)

	edo shards "${args[@]}" "${@}"
}

# @FUNCTION: crystal_build
# @USAGE: <args>...
# @DESCRIPTION:
# Function for building a target.  All arguments are passed to crystal.
crystal_build() {
	local build_args=(
		--threads=$(get_makeopts_jobs)
		--verbose
	)

	ecrystal build "${build_args[@]}" "${@}"
}

# @FUNCTION: crystal_spec
# @USAGE: [<args>...]
# @DESCRIPTION:
# Function for running tests.  All arguments are passed to crystal.
crystal_spec() {
	ecrystal spec --verbose "${@}" || die -n "Tests failed"
}

fi