blob: 0781810caa73616252af30284aa6e7b020de9264 [file] [log] [blame]
#!/bin/bash
# Copyright 2021 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Builds debug-<board>-package-info.json which contains debug
# information of the packages available as part of a board.
# The script should be used from inside the chroot as it
# uses cros_sdk dependencies for extracting package information.
set -eu
set -o pipefail
PROG_NAME=$(basename "$0")
readonly PROG_NAME
BOARD=""
BUILD_ID=""
OUTPUT_DIR=""
TMP_DIR=""
cleanup_dir() {
if [[ -d "${TMP_DIR}" ]]; then
rm -fr "${TMP_DIR}"
fi
}
# Returns the overlay of the package name provided.
# Example:
# Input: sys-apps/systemd-248.6
# Output: portage-stable
find_overlay() {
local -r file_path=$(equery-"${BOARD}" w "${1}")
# Split the ebuild path of the package based on '/'.
IFS="/" read -r -a arr <<< "${file_path}"
# Return the overlay of the package.
# It should be the fourth element from the end.
if [[ "${#arr[@]}" -le 4 ]]; then
echo ""
else
echo "${arr[-4]}"
fi
}
# Returns the set use_flags for the package name provided.
# Example:
# Input: sys-apps/systemd-248.6
# Output: +apparmor,+audit,+cgroup-hybrid,+gcrypt,+hwdb,+kmod,+lz4,
# +networkd-wait-online,+pam,+resolvconf,+seccomp,+sysv-utils,+vanilla
find_use_flags() {
local -r use_flags=$(equery-"${BOARD}" u "${1}" | cut -f 2-3)
result=""
# Looping over the use_flags.
for val in ${use_flags}; do
# Only include the use_flags which are set.
if [[ "${val::1}" == "+" ]]; then
if [[ "${result}" == "" ]]; then
result=${val}
else
result+=",${val}"
fi
fi
done
echo "${result}"
}
write_debug_package_info() {
local -r pkg_info_file=$1
local -r output_file=$2
local -r tmp_overlay_file=$3
local -r tmp_use_flags_file=$4
while IFS= read -r line; do
# Check for empty line and comment.
[[ -z "${line}" || "${line}" =~ ^#.* ]] && continue
find_overlay "${line}" > "${tmp_overlay_file}" &
find_use_flags "${line}" > "${tmp_use_flags_file}" &
wait
overlay=$(<"${tmp_overlay_file}")
use_flags=$(<"${tmp_use_flags_file}")
output="${line}"
if [[ "${overlay}" != "" ]]; then
output+=" overlay:${overlay}"
fi
if [[ "${use_flags}" != "" ]]; then
output+=" use_flags:${use_flags}"
fi
echo "${output}" >> "${output_file}"
done < "${pkg_info_file}"
}
build_debug_package_info() {
trap cleanup_dir EXIT
echo "Generating debug-cos-package-info.json. It may take couple of minutes.."
TMP_DIR="$(mktemp -d -p /tmp package-list.XXXXXXXXXX)"
local -r pkg_deps_file="${TMP_DIR}"/pkg_deps.txt
local -r pkg_info_file="${TMP_DIR}"/pkg_info.txt
local -r debug_pkg_info_file="${TMP_DIR}"/debug_pkg_info.txt
local -r tmp_overlay_file="${TMP_DIR}"/overlay.txt
local -r tmp_use_flags_file="${TMP_DIR}"/use_flags.txt
# Generate the package dependency file.
# The generated file will contain snippet
# similar to below:
#
# {
# "acct-group/docker-0.0.1": {
# "action": "merge",
# "category": "acct-group",
# "cpes": [],
# "deps": [
# "sys-apps/baselayout-2.2-r1"
# ],
# "full_name": "acct-group/docker-0.0.1",
# "name": "docker",
# "rev_deps": [
# "app-emulation/docker-20.10.6-r5"
# ],
# "version": "0.0.1"
# }
(cros_extract_deps \
--sysroot /build/"${BOARD}" \
--format deps \
virtual/target-os \
--output-path "${pkg_deps_file}")
# Extract the package name from the
# above generated file.
# Output:
# acct-group/docker-0.0.1
( grep "full_name" <"${pkg_deps_file}" \
| awk -F '"' '{print $4}' >> "${pkg_info_file}")
write_debug_package_info \
"${pkg_info_file}" \
"${debug_pkg_info_file}" \
"${tmp_overlay_file}" \
"${tmp_use_flags_file}"
local -r script_root="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")"
sudo "${script_root}/create_pkg_info.py" \
--input="allPackages:${debug_pkg_info_file}" \
--output="${OUTPUT_DIR}/debug-${BOARD}-package-info.json" \
--build-id="${BUILD_ID}" \
--debug
cleanup_dir
trap - EXIT
}
usage() {
local exit_code="${1}"
cat <<EOF
Usage:
${PROG_NAME} -b <board> -i <build_id> -o <output_dir>
-b, --board board for which file should be created
-i, --build_id build_id to be used in the debug-<board>-package-info.json
-o, --output_dir Output directory where file will be created
Examples:
$ ${PROG_NAME} \
-b lakitu \
-i 1.0.0 \
-o /mnt/host/source/src/build/images/lakitu/1.0.0
EOF
exit "${exit_code}"
}
# Parse command line arguments.
parse_args() {
local args
if ! args=$(getopt \
--options "b:i:o:" \
--longoptions "board: build_id: output_dir:" \
-- "$@"); then
usage 1
fi
eval set -- "${args}"
while :; do
arg="${1}"
shift
case "${arg}" in
-b|--board)
BOARD="${1}"; shift ;;
-i|--build_id)
BUILD_ID="${1}"; shift ;;
-o|--output_dir)
OUTPUT_DIR="${1}"; shift ;;
--)
break ;;
*)
echo "internal error parsing arguments!"; usage 1 ;;
esac
done
if [[ -z "${BOARD}" ||
-z "${BUILD_ID}" ||
-z "${OUTPUT_DIR}" ]]; then
usage 1
fi
}
main() {
parse_args "$@"
build_debug_package_info
}
main "$@"