mirror of
https://github.com/chromebrew/chromebrew.git
synced 2026-01-06 22:24:12 -05:00
156 lines
5.2 KiB
Bash
Executable File
156 lines
5.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# getrealdeps for Chromebrew version 1.1
|
|
# Author: Satadru Pramanik (satmandu) satadru at gmail dot com
|
|
# set -x
|
|
# export PS4='+(${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
|
|
pkg="${1%.rb}"
|
|
|
|
# Exit quickly if an invalid package name is given.
|
|
[[ ( -z "$pkg" ) || ( "$pkg" == *"#"* ) ]] && exit 1
|
|
|
|
if [ -z "${NOCOLORS}" ]; then
|
|
RED='\e[1;91m'; # Use Light Red for errors.
|
|
YELLOW='\e[1;33m'; # Use Yellow for informational messages.
|
|
GREEN='\e[1;32m'; # Use Green for success messages.
|
|
BLUE='\e[1;34m'; # Use Blue for intrafunction messages.
|
|
GRAY='\e[0;37m'; # Use Gray for program output.
|
|
MAGENTA='\e[1;35m';
|
|
RESET='\e[0m'
|
|
else
|
|
RED='';
|
|
YELLOW='';
|
|
GREEN='';
|
|
BLUE='';
|
|
GRAY='';
|
|
MAGENTA='';
|
|
RESET=''
|
|
fi
|
|
|
|
# Simplify colors and print errors to stderr (2).
|
|
echo_error() { echo -e "${RED}${*}${RESET}" >&2; }
|
|
echo_info() { echo -e "${YELLOW}${*}${RESET}" >&1; }
|
|
echo_success() { echo -e "${GREEN}${*}${RESET}" >&1; }
|
|
echo_intra() { echo -e "${BLUE}${*}${RESET}" >&1; }
|
|
echo_out() { echo -e "${GRAY}${*}${RESET}" >&1; }
|
|
echo_other() { echo -e "${MAGENTA}${*}${RESET}" >&2; }
|
|
|
|
# Install jq if a functional local copy does not exist.
|
|
if ! jq --version &> /dev/null; then
|
|
crew install jq
|
|
fi
|
|
|
|
: "${CREW_PREFIX:=$(crew const CREW_PREFIX | cut -d= -f2)}"
|
|
: "${CREW_LIB_PREFIX:=$(crew const CREW_LIB_PREFIX | cut -d= -f2)}"
|
|
|
|
# Package needs to be installed for package filelist to be populated.
|
|
if ! [[ $(jq --arg key "${pkg}" -e '.installed_packages[] | select(.name == $key )' "${CREW_PREFIX}"/etc/crew/device.json) ]]; then
|
|
crew install "${pkg}"
|
|
fi
|
|
|
|
if ! [[ -f "${CREW_PREFIX}/etc/crew/meta/${pkg}.filelist" ]]; then
|
|
echo_error "Package $pkg either does not exist or does not contain any libraries."
|
|
exit 1
|
|
fi
|
|
|
|
# Speed up grep
|
|
export LC_ALL=C
|
|
|
|
# Install grep if a functional local copy does not exist.
|
|
if grep --version &> /dev/null; then
|
|
GREP="grep"
|
|
else
|
|
crew install grep
|
|
GREP="${CREW_PREFIX}/bin/grep"
|
|
fi
|
|
|
|
# Install mawk if a functional local copy of awk does not exist.
|
|
if ! awk -W version &> /dev/null; then
|
|
crew install mawk
|
|
fi
|
|
|
|
# Which packages have a needed library in CREW_LIB_PREFIX
|
|
# This is a subset of what crew whatprovides gives
|
|
whatprovidesfxn() {
|
|
pkgdepslcl="${1}"
|
|
# Handle patchelf inserted full library paths.
|
|
if [[ "${pkgdepslcl}" == *"${CREW_LIB_PREFIX}"* ]]; then
|
|
filelcl=$($GREP --exclude "${pkg}.filelist" --exclude={"${CREW_PREFIX}/etc/crew/meta/\*_build.filelist"} "${pkgdepslcl}$" "${CREW_PREFIX}"/etc/crew/meta/*.filelist)
|
|
else
|
|
filelcl=$($GREP --exclude "${pkg}.filelist" --exclude={"${CREW_PREFIX}/etc/crew/meta/\*_build.filelist"} "^${CREW_LIB_PREFIX}.*${pkgdepslcl}$" "${CREW_PREFIX}"/etc/crew/meta/*.filelist)
|
|
fi
|
|
packagelcl=$(echo "$filelcl" | \
|
|
sed 's/.filelist.*//g' | sed 's:.*/::' | awk '!x[$0]++' | sed s/://g)
|
|
echo "$packagelcl"
|
|
}
|
|
|
|
# What files does a package provide
|
|
crewfilesfxn() {
|
|
pkgname="${1}"
|
|
files=$(< "${CREW_PREFIX}"/etc/crew/meta/"${pkgname}".filelist)
|
|
echo "$files"
|
|
}
|
|
|
|
pkgfiles=$(crewfilesfxn "${pkg}")
|
|
# Use readelf to determine library dependencies, as
|
|
# this doesn't almost run a program like using ldd would.
|
|
rm -rf /tmp/deps/"${pkg}"
|
|
pkgdeps=$(unset lines ; for i in $pkgfiles ; \
|
|
do \
|
|
[[ -f "${i}" ]] || continue
|
|
read -r -n 4 exec_header_bytes < "${i}"
|
|
[[ "$exec_header_bytes" == $'\x7FELF' ]] || continue
|
|
[[ $i = *_tkinter* ]] && continue # Carveout for Python3
|
|
# Expand upx compressed binaries if in a container environment
|
|
# since otherwise we cannot figure out their dependencies.
|
|
[[ -f "/.dockerenv" ]] && upx -d "${i}" &> /dev/null
|
|
mkdir -p /tmp/deps/"${pkg}"/
|
|
# shellcheck disable=SC2030,SC2046
|
|
lines+=$(echo ; readelf -d "$i" 2>/dev/null | $GREP NEEDED | awk '{print $5}' \
|
|
| sed 's/\[//g' | sed 's/\]//g' | awk '!x[$0]++' | tee /tmp/deps/"${pkg}"/$(basename "$i") ; echo ) ; \
|
|
done ; \
|
|
echo "$lines" | tr " " "\n" \
|
|
| awk 'NF' | awk '!x[$0]++')
|
|
|
|
# Remove duplicates.
|
|
pkgdeps="$(awk 'NF' <<< "${pkgdeps}" | awk '!x[$0]++')"
|
|
|
|
# Figure out which Chromebrew packages provide the relevant deps.
|
|
# shellcheck disable=SC2031
|
|
pkgdeps=$(unset lines; for j in $pkgdeps ; \
|
|
do lines+=$(echo ; whatprovidesfxn "$j"); done ; \
|
|
echo "$lines" | tr " " "\n" | awk '!x[$0]++')
|
|
|
|
# Remove original package from list.
|
|
pkgdeps=$(tr " " "\n" <<< "$pkgdeps" | sed "/${pkg}/d" | sort -u )
|
|
# Replace glibc_build packages with glibc
|
|
pkgdeps=$(tr " " "\n" <<< "$pkgdeps" | sed 's/glibc_build.*/glibc/' | sort -u )
|
|
# Replace glibc_lib* packages with glibc_lib
|
|
pkgdeps=$(tr " " "\n" <<< "$pkgdeps" | sed 's/glibc_lib.*/glibc_lib/' | sort -u )
|
|
|
|
# Note which dependencies are missing, but ignore :build lines, since
|
|
# build depenencies may still be runtime dependencies.
|
|
missingpkgdeps=$(
|
|
for i in $pkgdeps
|
|
do
|
|
$GREP -v ":build" "${CREW_PREFIX}"/lib/crew/packages/"${pkg}".rb | $GREP -q "depends_on '$i'" || echo "$i"
|
|
done
|
|
)
|
|
echo_info "\nPackage ${pkg} has runtime library dependencies on these packages:"
|
|
echo -e "${RESET}"
|
|
for i in $pkgdeps
|
|
do
|
|
echo_intra " depends_on '$i' # R"
|
|
done
|
|
echo -e "${RESET}"
|
|
|
|
# If there are no missing deps, no warning is needed.
|
|
if [ -n "${missingpkgdeps}" ]; then
|
|
echo_error "\nPackage file ${pkg}.rb is missing these runtime library dependencies:"
|
|
echo -e "${RESET}"
|
|
for i in $missingpkgdeps
|
|
do
|
|
echo_other " depends_on '$i' # R"
|
|
done
|
|
fi
|
|
echo -e "${RESET}"
|