blob: 1654cbb2a7d3ab20df8fab673f6e6b003cd882af [file] [log] [blame]
#!/bin/bash
# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
readonly PREFIX="${HOME}/.local/hdctools"
readonly BRANCH='master'
readonly REPO=https://chromium.googlesource.com/chromiumos/third_party/hdctools
readonly PYUSBDIR="${PREFIX}/util/usb"
readonly PYUSB='v1.0.2'
readonly SERVOD_PYTHONPATH="${PREFIX}/lib/python2.7/site-packages"
readonly DEPS=(python-pexpect python-numpy python-setuptools
python-serial python-pytest tidy libftdi-dev curl gcc make
pkg-config)
FORCE=''
# Prints out a log message with the wrapper prefix.
info() {
echo "servod-wrapper: $*" >&2
}
# Prints usage tips.
usage() {
info 'Installs and runs servod (or dut-control) from hdctools.
Wrapper usage:
servod [parameters] # Runs servod, first preparing it if necessary.
servod dut [parameters] # Runs dut-control, first preparing it if necessary.
dut-control [parameters] # Same as "servod dut" (via symlink).
servod install [-f] # Just prepares (or updates) servod.
servod uninstall # Removes the prepared servod install.
'
}
# Downloads gitiles src file and decodes to stdout.
curl_src() {
curl -#f "$1?format=TEXT" | base64 -d
}
# Determine and install prereqs.
install_dependencies() {
local pkg needed=()
for pkg in "${DEPS[@]}"; do
if [[ ! -f "/usr/share/doc/${pkg}/copyright" ]]; then
needed+=("${pkg}")
fi
done
if [[ "${#needed[@]}" -gt 0 ]]; then
info "Installing prerequisite packages: ${needed[*]}"
sudo apt-get install "${needed[@]}"
fi
}
# Fetches the latest version of hdctools.
fetch_hdctools_version() {
local commit
info "Checking hdctools version (branch ${BRANCH})..."
commit="$(curl_src "${REPO}/+/${BRANCH}" \
| grep -m 1 '^tree' \
| cut -d' ' -f 2)"
printf "%s" "${BRANCH}-${commit:-unknown}"
}
# Downloads and patches hdctools.
download_hdctools() {
info "Downloading hdctools..."
curl -#f "${REPO}/+archive/${BRANCH}.tar.gz" | tar -xzm || return
# don't need warnings
echo 'HOSTOS_CWARN=' >> 'defs/c-Linux.mk'
# FIXME: improve EC Makefile so we don't need to hack out toad
sed -i 's/toad//' 'src/Makefile'
# Avoid servo_updater dependency by implementing a dummy servo_updater.
sed -i "s|import servo_updater|class servo_updater:\n FIRMWARE_PATH = '/='|g" \
'servo/drv/ec3po_servo.py'
# Use /tmp as default log directory rather than /var/log since we're not root.
sed -i "/^DEFAULT_LOG_DIR *=/s|'[^']*'|'/tmp'|" 'servo/servod.py'
}
# Grabs the latest EC3PO from the EC repo without cloning the whole thing.
download_ec3po() {
info "Downloading ec3po..."
local ec3po="${PREFIX}/util/ec3po"
mkdir -p "${ec3po}"
curl -#f 'https://chromium.googlesource.com/chromiumos/platform/ec/+archive/master/util/ec3po.tar.gz' \
| tar -xz -C "${ec3po}" || return
# Extract just the ec3po section of setup.py
# FIXME: improve the setup.py so we can call only the chunk we want
curl_src 'https://chromium.googlesource.com/chromiumos/platform/ec/+/master/setup.py' \
| awk '
/^setup\(/ && x==0 { print; x=1 }
/name=.ec3po./ { x=2 }
x==2;
/^\)/ && x==2 { exit }
' >> setup.py
if [[ ! -s 'setup.py' ]]; then
return 1
fi
}
# Grabs a pyusb that matches the chroot.
download_pyusb() {
info "Downloading pyusb ${PYUSB}..."
mkdir -p "${PYUSBDIR}"
curl -#f "https://codeload.github.com/walac/pyusb/tar.gz/${PYUSB}" \
| tar -xz -C "${PYUSBDIR}"
}
# Builds pyusb.
build_pyusb() {
mkdir -p "${SERVOD_PYTHONPATH}"
(
cd "${PYUSBDIR}"/* || return
python setup.py build || return
python setup.py install --prefix="${PREFIX}" || return
)
}
# Downloads, extracts, and compiles servod and prereqs.
prepare() {
install_dependencies || return
# Store the commit hash in VCSID so that servod --version reports something.
VCSID="$(fetch_hdctools_version)"
export VCSID
# Check version
if [[ "${VCSID%-unknown}" != "${VCSID}" ]]; then
info "Failed to determine hdctools version"
elif grep -qF "${VCSID}" "${PREFIX}/.version" 2>/dev/null; then
info "Same version already installed (${VCSID})."
if [[ -z "${FORCE}" ]]; then
info "Specify -f to reinstall."
return 0
fi
else
info "Latest hdctools is ${VCSID}"
fi
# Reset the prefix each time to ensure a clean slate.
rm -rf "${PREFIX}"
mkdir -p "${PREFIX}"
# Download and build.
(
cd "${PREFIX}"
download_hdctools || return
download_ec3po || return
download_pyusb || return
# Build and install into our own prefix.
info "Building and installing..."
build_pyusb || return
make DESTDIR="${PREFIX}" || return
python setup.py build || return
make DESTDIR="${PREFIX}" install || return
python setup.py install --prefix="${PREFIX}" || return
# For some reason, the python eggs aren't properly populated with metadata
for pkg in servo usbkm232; do
cp -vft lib/python*/site-packages/"$pkg"-*/EGG-INFO "build/$pkg.egg-info/"*
done
) || return
# Store the VCSID on success.
echo "${VCSID}" > "${PREFIX}/.version"
# Done; output usage.
info 'Finished preparing servod.'
usage
}
main() {
export LD_LIBRARY_PATH="${PREFIX}/usr/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}"
export PYTHONPATH="${SERVOD_PYTHONPATH}${PYTHONPATH+:${PYTHONPATH}}"
local cmd="${1-}"
if [[ "${cmd}" == 'uninstall' ]]; then
rm -rvf "${PREFIX}"
return
elif [[ "${cmd}" != 'install' ]]; then
if [[ -d "${SERVOD_PYTHONPATH}" ]]; then
# Also support dut-control.
local servod="servo.servod"
local base="${0##*/}"
if [[ "${base#dut}" != "${base}" || "${cmd#dut}" != "${cmd}" ]]; then
servod="servo.dut_control"
if [[ "${base#dut}" == "${base}" ]]; then
shift
fi
elif [[ "${base#servodutil}" != "${base}" || "${cmd#servodutil}" != "${cmd}" ]]; then
servod="servo.servodutil"
if [[ "${base#servodutil}" == "${base}" ]]; then
shift
fi
elif [[ "${cmd}" == '-h' || "${cmd}" == '--help' ]]; then
usage
else
info "Note: you can update servod to ToT by running $0 install"
fi
python -m "${servod}" "$@"
return
fi
elif [[ "${cmd}" == 'install' ]]; then
if [[ "${2-}" == '-f' ]]; then
FORCE=y
fi
fi
# Either an explicit or implicit install.
prepare || return
# Relaunch if this wasn't an explicit install.
if [[ "${cmd}" != 'install' ]]; then
main "$@"
fi
}
set -eu
main "$@"