-
Notifications
You must be signed in to change notification settings - Fork 85
Expand file tree
/
Copy pathinside_sdk_container_lib.sh
More file actions
456 lines (397 loc) · 13 KB
/
inside_sdk_container_lib.sh
File metadata and controls
456 lines (397 loc) · 13 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
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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
#!/bin/bash
if [[ -z ${__INSIDE_SDK_CONTAINER_LIB_SH_INCLUDED__:-} ]]; then
__INSIDE_SDK_CONTAINER_LIB_SH_INCLUDED__=x
source "$(dirname "${BASH_SOURCE[0]}")/util.sh"
# Invokes emerge to get a report about built packages for a given
# metapackage in the given root that has a portage configuration.
#
# Params:
#
# 1 - root filesystem with the portage config
# @ - packages and metapackages to get the deps from
function emerge_pretend() {
local root
root=${1}; shift
# Probably a bunch of those flags are not necessary, but I'm not
# touching it - they seem to be working. :)
local -a emerge_opts=(
--config-root="${root}"
--root="${root}"
--sysroot="${root}"
--pretend
--columns
--nospinner
--oneshot
--color n
--emptytree
--verbose
--verbose-conflicts
--verbose-slot-rebuilds y
--changed-deps y
--changed-deps-report y
--changed-slot y
--changed-use
--newuse
--complete-graph y
--deep
--rebuild-if-new-slot y
--rebuild-if-unbuilt y
--with-bdeps y
--dynamic-deps y
--update
--ignore-built-slot-operator-deps y
--selective n
--keep-going y
)
local rv
rv=0
emerge "${emerge_opts[@]}" "${@}" || rv=${?}
if [[ ${rv} -ne 0 ]]; then
echo "WARNING: emerge exited with status ${rv}" >&2
fi
}
# Gets package list for SDK.
function package_info_for_sdk() {
local root
root='/'
ignore_crossdev_stuff "${root}"
# stage4 build of SDK builds coreos-devel/sdk-depends, fsscript
# pulls in cross toolchains with crossdev (which we have just
# ignored) and dev-lang/rust
emerge_pretend "${root}" coreos-devel/sdk-depends dev-lang/rust
revert_crossdev_stuff "${root}"
}
# Gets package list for board of a given architecture.
#
# Params:
#
# 1 - architecture
function package_info_for_board() {
local arch
arch=${1}; shift
local root
root="/build/${arch}-usr"
# Ignore crossdev stuff in both SDK root and board root - emerge
# may query SDK stuff for the board packages.
ignore_crossdev_stuff /
ignore_crossdev_stuff "${root}"
emerge_pretend "${root}" coreos-devel/board-packages
revert_crossdev_stuff "${root}"
revert_crossdev_stuff /
}
# Set the directory where the emerge output and the results of
# processing it will be stored. EO stands for "emerge output"
#
# Params:
#
# 1 - directory path
function set_eo() {
local dir=${1}; shift
# rest are architectures
declare -g EGENCACHE_W="${dir}/egencache-warnings"
declare -g SDK_EO="${dir}/sdk-emerge-output"
declare -g SDK_EO_F="${SDK_EO}-filtered"
declare -g SDK_EO_W="${SDK_EO}-warnings"
declare -g SDK_EO_J="${SDK_EO}-junk"
local arch
local board_eo
for arch; do
board_eo=${dir}/${arch}-board-emerge-output
declare -g "${arch^^}_BOARD_EO=${board_eo}"
declare -g "${arch^^}_BOARD_EO_F=${board_eo}-filtered"
declare -g "${arch^^}_BOARD_EO_W=${board_eo}-warnings"
declare -g "${arch^^}_BOARD_EO_J=${board_eo}-junk"
done
}
# JSON output would be more verbose, but probably would not require
# these abominations below. But, alas, emerge doesn't have that yet.
# status package name version slot repo target (opt) keyvals size
# |--------------| |----------| |#-g1-----------#--#-g2-#| |--|-g------| |-g----------#-#-g-----| |---|
# [ebuild R ~] virtual/rust [1.71.1:0/llvm-16::coreos] to /some/root USE="-rustfmt" FOO="bar" 0 KiB
#
# Actually, there can also be another "version slot repo" part between
# the first "version slot repo" and "target" part.
STATUS_RE='\[[^]]*]' # 0 groups
PACKAGE_NAME_RE='[^[:space:]]*' # 0 groups
VER_SLOT_REPO_RE='\[\([^]]\+\)::\([^]]\+\)]' # 2 groups
TARGET_RE='to[[:space:]]\+\([^[:space:]]\)\+' # 1 group
KEYVALS_RE='\([[:space:]]*[A-Za-z0-9_]*="[^"]*"\)*' # 1 group (but containing only the last pair!)
SIZE_RE='[[:digit:]]\+[[:space:]]*[[:alpha:]]*B' # 0 groups
SPACES_RE='[[:space:]]\+' # 0 groups
NONSPACES_RE='[^[:space:]]\+' # 0 groups
NONSPACES_WITH_COLON_RE='[^[:space:]]*:' # 0 groups
FULL_LINE_RE='^'"${STATUS_RE}${SPACES_RE}${PACKAGE_NAME_RE}"'\('"${SPACES_RE}${VER_SLOT_REPO_RE}"'\)\{1,2\}\('"${SPACES_RE}${TARGET_RE}"'\)\?\('"${SPACES_RE}${KEYVALS_RE}"'\)*'"${SPACES_RE}${SIZE_RE}"'$'
# Filters sdk reports to get the package information.
function filter_sdk_eo() {
cat "${SDK_EO}" | xgrep -e "${FULL_LINE_RE}"
}
# Filters board reports for a given arch to get the package
# information.
#
# Params:
#
# 1 - architecture
function filter_board_eo() {
local arch name
arch=${1}; shift
name=${arch^^}_BOARD_EO
# Replace ${arch}-usr in the output with a generic word BOARD.
cat "${!name}" | \
xgrep -e "${FULL_LINE_RE}" | \
sed -e "s#/build/${arch}-usr/#/build/BOARD/#"
}
# Filters sdk reports to get anything but the package information
# (i.e. junk).
function junk_sdk_eo() {
cat "${SDK_EO}" | xgrep -v -e "${FULL_LINE_RE}"
}
# Filters board reports to get anything but the package information
# (i.e. junk).
function junk_board_eo() {
local arch name
arch=${1}; shift
name=${arch^^}_BOARD_EO
cat "${!name}" | xgrep -v -e "${FULL_LINE_RE}"
}
# More regexp-like abominations follow.
# There may also be a line like:
#
# [blocks B ] <dev-util/gdbus-codegen-2.76.4 ("<dev-util/gdbus-codegen-2.76.4" is soft blocking dev-libs/glib-2.76.4)
#
# But currently we don't care about those - they land in junk.
SLOT_INFO_SED_FILTERS=(
# if there is no slot information in version, add :0
#
# assumption here is that version is a second word
-e "/^${NONSPACES_RE}${SPACES_RE}${NONSPACES_WITH_COLON_RE}/ ! s/^\(${NONSPACES_RE}${SPACES_RE}${NONSPACES_RE}\)/\1:0/"
)
PKG_VER_SLOT_SED_FILTERS=(
# from line like:
#
# [ebuild R ~] virtual/rust [1.71.1:0/llvm-16::coreos] USE="-rustfmt" 0 KiB
#
# extract package name, version and optionally a slot if it exists, the result would be:
#
# virtual/rust 1.71.1:0/llvm-16
-e "s/^${STATUS_RE}${SPACES_RE}\(${PACKAGE_NAME_RE}\)${SPACES_RE}${VER_SLOT_REPO_RE}.*/\1 \2/"
"${SLOT_INFO_SED_FILTERS[@]}"
)
PKG_VER_SLOT_KV_SED_FILTERS=(
# from line like:
#
# [ebuild R ~] virtual/rust [1.71.1:0/llvm-16::coreos] USE="-rustfmt" 0 KiB
#
# extract package name, version, optionally a slot if it exists and key value pairs if any, the result would be:
#
# virtual/rust 1.71.1:0/llvm-16 USE="-rustfmt"
-e "s/${STATUS_RE}${SPACES_RE}\(${PACKAGE_NAME_RE}\)${SPACES_RE}${VER_SLOT_REPO_RE}\(${SPACES_RE}${VER_SLOT_REPO_RE}\)\?\(${SPACES_RE}${TARGET_RE}\)\?${SPACES_RE}\(${KEYVALS_RE}\)${SPACES_RE}${SIZE_RE}\$/\1 \2 \9/"
"${SLOT_INFO_SED_FILTERS[@]}"
)
PKG_REPO_SED_FILTERS=(
# from line like:
#
# [ebuild R ~] virtual/rust [1.71.1:0/llvm-16::coreos] USE="-rustfmt" 0 KiB
#
# extract package name and repo, the result would be:
#
# virtual/rust coreos
-e "s/^${STATUS_RE}${SPACES_RE}\(${PACKAGE_NAME_RE}\)${SPACES_RE}${VER_SLOT_REPO_RE}${SPACES_RE}.*/\1 \3/"
)
# Applies some sed filter over the SDK emerge output. Results are
# printed.
#
# Params:
#
# @ - parameters passed to sed
function packages_for_sdk() {
cat "${SDK_EO_F}" | sed "${@}" | sort
}
# Applies some sed filter over the board emerge output. Results are
# printed.
#
# Params:
#
# @ - parameters passed to sed
function packages_for_board() {
local arch=${1}; shift
# rest goes to sed
local name=${arch^^}_BOARD_EO_F
sed "${@}" "${!name}" | sort
}
# Prints package name, slot and version information for SDK.
function versions_sdk() {
local -a sed_opts
sed_opts=(
"${PKG_VER_SLOT_SED_FILTERS[@]}"
)
packages_for_sdk "${sed_opts[@]}"
}
# Prints package name, slot, version and key-values information for
# SDK. Key-values may be something like USE="foo bar -baz".
function versions_sdk_with_key_values() {
local -a sed_opts
sed_opts=(
"${PKG_VER_SLOT_KV_SED_FILTERS[@]}"
)
packages_for_sdk "${sed_opts[@]}"
}
# Prints package name, slot and version information for board.
function versions_board() {
local arch=${1}; shift
local -a sed_opts
sed_opts=(
-e '/to \/build\/BOARD\// ! d'
"${PKG_VER_SLOT_SED_FILTERS[@]}"
)
packages_for_board "${arch}" "${sed_opts[@]}"
}
# Prints package name, slot, version and key-values information for
# build dependencies of board. Key-values may be something like
# USE="foo bar -baz".
function board_bdeps() {
local arch=${1}; shift
local -a sed_opts
sed_opts=(
-e '/to \/build\/BOARD\// d'
"${PKG_VER_SLOT_KV_SED_FILTERS[@]}"
)
packages_for_board "${arch}" "${sed_opts[@]}"
}
# Print package name and source repository names information for SDK.
function package_sources_sdk() {
local -a sed_opts
sed_opts=(
"${PKG_REPO_SED_FILTERS[@]}"
)
packages_for_sdk "${sed_opts[@]}"
}
# Print package name and source repository names information for
# board.
function package_sources_board() {
local arch=${1}; shift
local -a sed_opts
sed_opts=(
"${PKG_REPO_SED_FILTERS[@]}"
)
packages_for_board "${arch}" "${sed_opts[@]}"
}
# Checks if no errors were produced by emerge when generating
# reports. It is assumed that emerge will print a line with "ERROR" in
# it to denote a failure.
function ensure_no_errors() {
local -a files=( "${SDK_EO_W}" )
local arch name
for arch; do
name=${arch^^}_BOARD_EO_W
files+=( "${!name}" )
done
if grep --quiet --fixed-strings 'ERROR' "${files[@]}"; then
fail "there are errors in emerge output warnings files"
fi
}
# Stores a path to a package.provided file inside the given root
# filesystem portage configuration. Mostly used to ignore
# cross-toolchains.
#
# Params:
#
# 1 - path to root filesystem with the portage configuration
# 2 - name of a variable where the path will be stored
function get_provided_file() {
local root path_var_name
root=${1}; shift
path_var_name=${1}; shift
local -n path_ref="${path_var_name}"
path_ref="${root}/etc/portage/profile/package.provided/ignore_cross_packages"
}
# Marks packages coming from crossdev repo as provided at a very high
# version. We do this, because updating their native counterparts will
# cause emerge to complain that cross-<triplet>/<package> is masked
# (like for sys-libs/glibc and cross-x86_64-cros-linux-gnu/glibc),
# because it has no keywords. In theory, we could try updating
# <ROOT>/etc/portage/package.mask/cross-<triplet> file created by the
# crossdev tool to unmask the new version, but it's an unnecessary
# hassle - native and cross package are supposed to be the same ebuild
# anyway, so update information about cross package is redundant.
#
# Params:
#
# 1 - root directory
# 2 - ID of the crossdev repository (optional, defaults to x-crossdev)
function ignore_crossdev_stuff() {
local root crossdev_repo_id
root=${1}; shift
crossdev_repo_id=${1:-x-crossdev}; shift || :
local crossdev_repo_path
crossdev_repo_path=$(portageq get_repo_path "${root}" "${crossdev_repo_id}")
local ics_path ics_dir
get_provided_file "${root}" ics_path
dirname_out "${ics_path}" ics_dir
sudo mkdir -p "${ics_dir}"
env --chdir="${crossdev_repo_path}" find . -type l | \
cut -d/ -f2-3 | \
sed -e 's/$/-9999/' | \
sudo tee "${ics_path}" >/dev/null
}
# Reverts effects of the ignore_crossdev_stuff function.
#
# Params:
#
# 1 - root directory
function revert_crossdev_stuff() {
local root
root=${1}; shift
local ics_path ics_dir
get_provided_file "${root}" ics_path
dirname_out "${ics_path}" ics_dir
sudo rm -f "${ics_path}"
if dir_is_empty "${ics_dir}"; then
sudo rmdir "${ics_dir}"
fi
}
# Checks if the expected reports were generated by emerge.
function ensure_valid_reports() {
local -a files=( "${SDK_EO_F}" )
local arch name
for arch; do
name=${arch^^}_BOARD_EO_F
files+=( "${!name}" )
done
local file
for file in "${files[@]}"; do
if [[ ! -s ${file} ]]; then
fail "report files are missing or are empty"
fi
done
}
# Drops the empty warning files in given directory.
#
# Params:
#
# 1 - path to the directory
function clean_empty_warning_files() {
local dir
dir=${1}; shift
local file
for file in "${dir}/"*'-warnings'; do
if [[ ! -s ${file} ]]; then
rm -f "${file}"
fi
done
}
function generate_cache_for() {
local repo=${1}; shift
local -i gcf_num_proc
local load_avg
get_num_proc gcf_num_proc
load_avg=$(bc <<< "${gcf_num_proc} * 0.75")
egencache --repo "${repo}" --jobs="${gcf_num_proc}" --load-average="${load_avg}" --update
}
function copy_cache_to_reports() {
local repo=${1}; shift
local reports_dir=${1}; shift
local repo_dir
repo_dir=$(portageq get_repo_path / "${repo}")
cp -a "${repo_dir}/metadata/md5-cache" "${reports_dir}/${repo}-cache"
}
fi