You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
724 lines
19 KiB
724 lines
19 KiB
#!/usr/bin/env bash
|
|
# kaleidoscope-builder - Kaleidoscope helper tool
|
|
# Copyright (C) 2017-2018 Keyboard.io, Inc.
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify it under
|
|
# the terms of the GNU General Public License as published by the Free Software
|
|
# Foundation, version 3.
|
|
#
|
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License along with
|
|
# this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
set -e
|
|
|
|
######
|
|
###### Build and output configuration
|
|
######
|
|
|
|
absolute_filename() {
|
|
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
|
|
}
|
|
|
|
|
|
|
|
build_version () {
|
|
: "${LIB_PROPERTIES_PATH:="../.."}"
|
|
GIT_VERSION="$(cd "${SKETCH_DIR}"; if [ -d .git ]; then echo -n '-g' && git describe --abbrev=4 --dirty --always; fi)"
|
|
LIB_VERSION="$(cd "${SKETCH_DIR}"; (grep version= "${LIB_PROPERTIES_PATH}/library.properties" 2>/dev/null || echo version=0.0.0) | cut -d= -f2)${GIT_VERSION}"
|
|
}
|
|
|
|
build_paths() {
|
|
# We need that echo because we\re piping to cksum
|
|
# shellcheck disable=SC2005
|
|
SKETCH_IDENTIFIER="$(echo "${SKETCH_FILE_PATH}" | cksum | cut -d ' ' -f 1)-${SKETCH_FILE_NAME}"
|
|
: "${KALEIDOSCOPE_TEMP_PATH:=${TMPDIR:-/tmp}/kaleidoscope-${USER}}"
|
|
|
|
: "${KALEIDOSCOPE_BUILD_PATH:=${KALEIDOSCOPE_TEMP_PATH}/sketch}"
|
|
: "${KALEIDOSCOPE_OUTPUT_PATH:=${KALEIDOSCOPE_TEMP_PATH}/sketch}"
|
|
|
|
: "${SKETCH_OUTPUT_DIR:=${SKETCH_IDENTIFIER}/output}"
|
|
: "${SKETCH_BUILD_DIR:=${SKETCH_IDENTIFIER}/build}"
|
|
|
|
: "${BUILD_PATH:=${KALEIDOSCOPE_BUILD_PATH}/${SKETCH_BUILD_DIR}}"
|
|
: "${OUTPUT_PATH:=${KALEIDOSCOPE_OUTPUT_PATH}/${SKETCH_OUTPUT_DIR}}"
|
|
|
|
: "${CCACHE_WRAPPER_PATH:=${KALEIDOSCOPE_TEMP_PATH}/ccache/bin}"
|
|
: "${CORE_CACHE_PATH:=${KALEIDOSCOPE_TEMP_PATH}/arduino-cores}"
|
|
|
|
mkdir -p "$CORE_CACHE_PATH"
|
|
mkdir -p "$BUILD_PATH"
|
|
}
|
|
|
|
build_filenames () {
|
|
: "${OUTPUT_FILE_PREFIX:=${SKETCH_BASE_NAME}-${LIB_VERSION}}"
|
|
: "${HEX_FILE_PATH:=${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}.hex}"
|
|
: "${HEX_FILE_WITH_BOOTLOADER_PATH:=${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}-with-bootloader.hex}"
|
|
: "${ELF_FILE_PATH:=${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}.elf}"
|
|
: "${LIB_FILE_PATH:=${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}.a}"
|
|
}
|
|
|
|
|
|
enable_ccache () {
|
|
if [ -z "${CCACHE_NOT_SUPPORTED}" ] && [ "$(command -v ccache)" ]; then
|
|
if ! [ -d "$CCACHE_WRAPPER_PATH" ]; then
|
|
mkdir -p "$CCACHE_WRAPPER_PATH"
|
|
|
|
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}${C_COMPILER_BASENAME}" ]; then
|
|
ln -s "$(command -v ccache)" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}${C_COMPILER_BASENAME}"
|
|
fi
|
|
|
|
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}${CXX_COMPILER_BASENAME}" ]; then
|
|
ln -s "$(command -v ccache)" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}${CXX_COMPILER_BASENAME}"
|
|
fi
|
|
|
|
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}nm" ]; then
|
|
ln -s "${AVR_NM}" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}nm"
|
|
fi
|
|
|
|
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}objcopy" ]; then
|
|
ln -s "${AVR_OBJCOPY}" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}objcopy"
|
|
fi
|
|
|
|
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}ar" ]; then
|
|
ln -s "${AVR_AR}" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}ar"
|
|
fi
|
|
|
|
if ! [ -h "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}size" ]; then
|
|
ln -s "${AVR_SIZE}" "${CCACHE_WRAPPER_PATH}/${COMPILER_PREFIX}size"
|
|
fi
|
|
fi
|
|
|
|
export CCACHE_PATH=${COMPILER_PATH}/
|
|
CCACHE_ENABLE="-prefs compiler.path=${CCACHE_WRAPPER_PATH}/"
|
|
fi
|
|
}
|
|
|
|
|
|
firmware_size () {
|
|
if [ "${ARCH}" = "virtual" ]; then
|
|
echo "[Size not computed for virtual build]"
|
|
return
|
|
fi
|
|
|
|
: "${MAX_PROG_SIZE:=$(get_arduino_pref 'upload.maximum_size')}"
|
|
|
|
## This is a terrible hack, please don't hurt me. - algernon
|
|
|
|
set +e
|
|
raw_output=$("$@" 2> /dev/null)
|
|
rc=$?
|
|
set -e
|
|
|
|
if [ $rc -eq 0 ]; then
|
|
output="$(echo "${raw_output}"| grep "\\(Program\\|Data\\):" | sed -e 's,^, - ,' && echo)"
|
|
|
|
PROGSIZE="$(echo "${output}" | grep "Program:" | cut -d: -f2 | awk '{print $1}')"
|
|
|
|
PERCENT="$(echo "${PROGSIZE}" "${MAX_PROG_SIZE}" | awk "{ printf \"%02.01f\", \$1 / \$2 * 100 }")"
|
|
|
|
# we want the sed there, doing with shell builtins would be worse.
|
|
# shellcheck disable=SC2001 disable=SC1117
|
|
echo "${output}" | sed -e "s/\(Program:.*\)(\([0-9\.]*%\) Full)/\1(${PERCENT}% Full)/"
|
|
else
|
|
echo "Unable to determine image size."
|
|
fi
|
|
}
|
|
|
|
|
|
find_sketch () {
|
|
if [ -z "${SKETCH}" ]; then
|
|
echo "SKETCH needs to be set before including this file!" >&2
|
|
exit 1
|
|
fi
|
|
|
|
SKETCH_DIR="${SKETCH}"
|
|
SKETCH_BASE_NAME=$(basename "$SKETCH")
|
|
SKETCH_FILE_NAME="${SKETCH_BASE_NAME}.ino"
|
|
|
|
for path in "${SKETCH_DIR}" \
|
|
"src" \
|
|
"."; do
|
|
if [ -f "${path}/${SKETCH_FILE_NAME}" ]; then
|
|
SKETCH_DIR="${path}"
|
|
SKETCH_FILE_PATH=$(absolute_filename "${SKETCH_DIR}/${SKETCH_FILE_NAME}")
|
|
return
|
|
fi
|
|
done
|
|
echo "I couldn't find your sketch (.ino file)" >&2
|
|
exit 1
|
|
}
|
|
|
|
|
|
|
|
prompt_before_flashing () {
|
|
flashing_instructions=$(get_arduino_pref 'build.flashing_instructions')
|
|
|
|
if [ "x${flashing_instructions}x" = "xx" ]; then
|
|
flashing_instructions="If your keyboard needs you to do something to put it in flashing mode, do that now."
|
|
fi
|
|
|
|
printf '%b\n\n' "${flashing_instructions}"
|
|
echo ""
|
|
echo "When you're ready to proceed, press 'Enter'."
|
|
|
|
# We do not want to permit line continuations here. We just want a newline.
|
|
# shellcheck disable=SC2162
|
|
read
|
|
}
|
|
|
|
flash () {
|
|
compile "$@"
|
|
|
|
# Check to see if we can see a keyboard bootloader port.
|
|
# If we -can-, then we should skip over the "reset to bootloader" thing
|
|
find_bootloader_ports
|
|
if [ -z "${DEVICE_PORT_BOOTLOADER}" ]; then
|
|
prompt_before_flashing
|
|
|
|
# This is defined in the (optional) user config.
|
|
# shellcheck disable=SC2154
|
|
${preFlash_HOOKS}
|
|
|
|
# If we're -not- doing a manual reset, then try to do it automatically
|
|
if [ -z "${MANUAL_RESET}" ]; then
|
|
reset_device
|
|
sleep 2
|
|
find_bootloader_ports
|
|
# Otherwise, poll for a bootloader port.
|
|
else
|
|
wait_for_bootloader_port
|
|
fi
|
|
|
|
fi
|
|
|
|
check_bootloader_port_and_flash
|
|
|
|
# This is defined in the (optional) user config.
|
|
# shellcheck disable=SC2154
|
|
${postFlash_HOOKS}
|
|
}
|
|
|
|
wait_for_bootloader_port() {
|
|
declare -i tries
|
|
tries=15
|
|
|
|
while [ "$tries" -gt 0 ] && [ -z "${DEVICE_PORT_BOOTLOADER}" ]; do
|
|
sleep 1
|
|
printf "."
|
|
find_bootloader_ports
|
|
# the variable annotations do appear to be necessary
|
|
# shellcheck disable=SC2004
|
|
tries=$(($tries-1))
|
|
done
|
|
|
|
if [ "$tries" -gt 0 ]; then
|
|
echo "Found."
|
|
else
|
|
echo "Timed out."
|
|
fi
|
|
}
|
|
|
|
check_bootloader_port () {
|
|
if [ -z "${DEVICE_PORT_BOOTLOADER}" ]; then
|
|
echo "Unable to detect a keyboard in bootloader mode."
|
|
echo "You may need to hold a key or hit a reset button."
|
|
echo "Please check your keyboard's documentation"
|
|
return 1
|
|
fi
|
|
|
|
}
|
|
|
|
check_bootloader_port_and_flash () {
|
|
|
|
if ! check_bootloader_port; then
|
|
return 1
|
|
fi
|
|
|
|
echo "Flashing your keyboard:"
|
|
|
|
# If the flash fails, try a second time
|
|
if ! flash_over_usb; then
|
|
sleep 2
|
|
if ! flash_over_usb; then
|
|
if [ "${ARDUINO_VERBOSE}" != "-verbose" ]; then
|
|
echo "Something went wrong."
|
|
echo "You might want to try flashing again with the VERBOSE environment variable set"
|
|
fi
|
|
|
|
return 1
|
|
fi
|
|
fi
|
|
echo "Keyboard flashed successfully!"
|
|
return 0
|
|
}
|
|
|
|
flash_over_usb () {
|
|
|
|
FLASH_CMD=$(${AVRDUDE} \
|
|
-C "${AVRDUDE_CONF}" \
|
|
-p"${MCU}" \
|
|
-cavr109 \
|
|
-D \
|
|
-P "${DEVICE_PORT_BOOTLOADER}" \
|
|
-b57600 \
|
|
"-Uflash:w:${HEX_FILE_PATH}:i")
|
|
|
|
if [ "${ARDUINO_VERBOSE}" != "-verbose" ]; then
|
|
${FLASH_CMD} 2>&1 |grep -v ^avrdude | grep -v '^$' |grep -v '^ ' | grep -vi programmer
|
|
return "${PIPESTATUS[0]}"
|
|
else
|
|
${FLASH_CMD}
|
|
return $?
|
|
fi
|
|
}
|
|
|
|
flash_from_bootloader() {
|
|
compile "$@"
|
|
prompt_before_flashing
|
|
find_bootloader_ports
|
|
check_bootloader_port_and_flash
|
|
}
|
|
|
|
program() {
|
|
compile "$@"
|
|
prompt_before_flashing
|
|
flash_with_programmer
|
|
}
|
|
|
|
flash_with_programmer() {
|
|
${AVRDUDE} -v \
|
|
-C "${AVRDUDE_CONF}" \
|
|
-p"${MCU}" \
|
|
-cusbtiny \
|
|
-D \
|
|
-B 1 \
|
|
"-Uflash:w:${HEX_FILE_PATH}:i"
|
|
}
|
|
|
|
find_bootloader_path() {
|
|
BOOTLOADER_FILE=$( get_arduino_pref 'bootloader.file' )
|
|
: "${BOOTLOADER_FILE:=caterina/Caterina.hex}"
|
|
: "${BOOTLOADER_PATH:=${BOARD_HARDWARE_PATH}/keyboardio/avr/bootloaders/${BOOTLOADER_FILE}}"
|
|
}
|
|
|
|
|
|
hex_with_bootloader () {
|
|
compile
|
|
|
|
find_bootloader_path
|
|
|
|
awk '/^:00000001FF/ == 0' "${HEX_FILE_PATH}" > "${HEX_FILE_WITH_BOOTLOADER_PATH}"
|
|
echo "Using ${BOOTLOADER_PATH}"
|
|
${MD5} "${BOOTLOADER_PATH}"
|
|
cat "${BOOTLOADER_PATH}" >> "${HEX_FILE_WITH_BOOTLOADER_PATH}"
|
|
ln -sf -- "${OUTPUT_FILE_PREFIX}-with-bootloader.hex" "${OUTPUT_PATH}/${SKETCH_BASE_NAME}-latest-with-bootloader.hex"
|
|
cat <<- EOF
|
|
|
|
Combined firmware and bootloader are now at ${HEX_FILE_WITH_BOOTLOADER_PATH}
|
|
Make sure you have the bootloader version you expect.
|
|
|
|
And TEST THIS ON REAL HARDWARE BEFORE YOU GIVE IT TO ANYONE
|
|
|
|
EOF
|
|
}
|
|
|
|
build () {
|
|
compile "$@"
|
|
size "$@"
|
|
}
|
|
|
|
|
|
prepare_ccache () {
|
|
build_paths
|
|
enable_ccache
|
|
}
|
|
compile () {
|
|
find_sketch
|
|
build_version
|
|
build_paths
|
|
build_filenames
|
|
# If the hex file is older than the sketch file, or the hex file does not exist
|
|
# then rebuild. This is not as correct as letting make check our dependencies
|
|
# But it's less broken for most user use cases
|
|
# TODO(anyone): Make this suck less
|
|
if [ "${HEX_FILE_PATH}" -ot "${SKETCH_FILE_PATH}" ]; then
|
|
do_compile "$@"
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
do_compile () {
|
|
prepare_ccache
|
|
|
|
install -d "${OUTPUT_PATH}"
|
|
|
|
echo "Building ${SKETCH_FILE_PATH}"
|
|
|
|
# This is defined in the (optional) user config.
|
|
# shellcheck disable=SC2154
|
|
${compile_HOOKS}
|
|
|
|
if [ -d "${ARDUINO_LOCAL_LIB_PATH}/libraries" ]; then
|
|
# shellcheck disable=SC2089
|
|
# We want literal backslashes here, not arrays.
|
|
local_LIBS="-libraries \"${ARDUINO_LOCAL_LIB_PATH}/libraries\""
|
|
fi
|
|
|
|
ARDUINO_PACKAGES=""
|
|
if [ -d "${ARDUINO_PACKAGE_PATH}" ]; then
|
|
# shellcheck disable=SC2089
|
|
# We want literal backslashes here, not arrays.
|
|
ARDUINO_PACKAGES="-hardware \"${ARDUINO_PACKAGE_PATH}\""
|
|
fi
|
|
|
|
SAVED_BOARD="${BOARD}"
|
|
SAVED_FQBN="${FQBN}"
|
|
if [ -e "${SKETCH_DIR}/.kaleidoscope-builder.conf" ]; then
|
|
# shellcheck disable=SC1090
|
|
BOARD="$(. "${SKETCH_DIR}"/.kaleidoscope-builder.conf && echo "${BOARD}")"
|
|
# shellcheck disable=SC1090
|
|
FQBN="$(. "${SKETCH_DIR}"/.kaleidoscope-builder.conf && echo "${FQBN}")"
|
|
if [ -n "${BOARD}" ]; then
|
|
if [ -z "${ARCH}" ]; then
|
|
FQBN="keyboardio:avr:${BOARD}"
|
|
else
|
|
FQBN="keyboardio:${ARCH}:${BOARD}"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
_CMD_CXX="${CXX:-${COMPILER_PREFIX}${CXX_COMPILER_BASENAME}${COMPILER_SUFFIX}}"
|
|
_CMD_CC="${CC:-${COMPILER_PREFIX}${C_COMPILER_BASENAME}${COMPILER_SUFFIX}}"
|
|
_CMD_AR="${AR:-${COMPILER_PREFIX}${AR_BASENAME}${COMPILER_SUFFIX}}"
|
|
|
|
# SC2091: We do not care if quotes or backslashes are not respected.
|
|
# SC2086: We want word splitting.
|
|
# shellcheck disable=SC2086,SC2090
|
|
"${ARDUINO_BUILDER}" \
|
|
-compile \
|
|
${ARDUINO_PACKAGES} \
|
|
-hardware "${ARDUINO_PATH}/hardware" \
|
|
-hardware "${BOARD_HARDWARE_PATH}" \
|
|
${ARDUINO_TOOLS_FLAG:+"${ARDUINO_TOOLS_FLAG}"} ${ARDUINO_TOOLS_PARAM:+"${ARDUINO_TOOLS_PARAM}"} \
|
|
-tools "${ARDUINO_BUILDER_TOOLS_PATH}" \
|
|
-fqbn "${FQBN}" \
|
|
-libraries "." \
|
|
-libraries "${KALEIDOSCOPE_DIR}" \
|
|
-libraries "${BOARD_HARDWARE_PATH}/.." \
|
|
${local_LIBS} \
|
|
${EXTRA_BUILDER_ARGS} \
|
|
-build-cache "${CORE_CACHE_PATH}" \
|
|
-build-path "${BUILD_PATH}" \
|
|
-ide-version "${ARDUINO_IDE_VERSION}" \
|
|
-built-in-libraries "${ARDUINO_PATH}/libraries" \
|
|
-prefs "compiler.cpp.extra_flags=${ARDUINO_CFLAGS} ${LOCAL_CFLAGS}" \
|
|
-prefs "compiler.path=${COMPILER_PATH}" \
|
|
-prefs "compiler.c.cmd=${_CMD_CC}" \
|
|
-prefs "compiler.cpp.cmd=${_CMD_CXX}" \
|
|
-prefs "compiler.ar.cmd=${_CMD_AR}" \
|
|
-prefs "compiler.c.elf.cmd=${_CMD_CXX}" \
|
|
$CCACHE_ENABLE \
|
|
-warnings all \
|
|
${ARDUINO_VERBOSE} \
|
|
${ARDUINO_AVR_GCC_PREFIX_PARAM} \
|
|
"${SKETCH_FILE_PATH}"
|
|
|
|
if [ -z "${LIBONLY}" ]; then
|
|
cp "${BUILD_PATH}/${SKETCH_FILE_NAME}.hex" "${HEX_FILE_PATH}"
|
|
cp "${BUILD_PATH}/${SKETCH_FILE_NAME}.elf" "${ELF_FILE_PATH}"
|
|
ln -sf "${OUTPUT_FILE_PREFIX}.hex" "${OUTPUT_PATH}/${SKETCH_BASE_NAME}-latest.hex"
|
|
ln -sf "${OUTPUT_FILE_PREFIX}.elf" "${OUTPUT_PATH}/${SKETCH_BASE_NAME}-latest.elf"
|
|
else
|
|
cp "${BUILD_PATH}/${SKETCH_FILE_NAME}.a" "${LIB_FILE_PATH}"
|
|
ln -sf "${OUTPUT_FILE_PREFIX}.a" "${OUTPUT_PATH}/${SKETCH_BASE_NAME}-latest.a"
|
|
fi
|
|
|
|
if [ "${ARDUINO_VERBOSE}" = "-verbose" ]; then
|
|
echo "Build artifacts can be found in ${BUILD_PATH}";
|
|
fi
|
|
|
|
BOARD="${SAVED_BOARD}"
|
|
FQBN="${SAVED_FQBN}"
|
|
}
|
|
|
|
find_all_sketches () {
|
|
for plugin in ./*.ino \
|
|
$([ -d examples ] && find examples -name '*.ino') \
|
|
src/*.ino; do
|
|
if [ -d "$(dirname "${plugin}")" ] || [ -f "${plugin}" ]; then
|
|
p="$(basename "${plugin}" .ino)"
|
|
if [ "${p}" != '*' ]; then
|
|
case "${plugin}" in
|
|
examples/*/${p}/${p}.ino)
|
|
echo "${plugin}" | sed -e "s,examples/,," | sed -e "s,/${p}\\.ino,,"
|
|
;;
|
|
*)
|
|
echo "${p}"
|
|
;;
|
|
esac
|
|
fi
|
|
fi
|
|
done | sort
|
|
}
|
|
|
|
build_all () {
|
|
plugins="$(find_all_sketches)"
|
|
|
|
for plugin in ${plugins}; do
|
|
export SKETCH="${plugin}"
|
|
$0 "${plugin}" build
|
|
done
|
|
}
|
|
|
|
|
|
compile_all () {
|
|
plugins="$(find_all_sketches)"
|
|
|
|
for plugin in ${plugins}; do
|
|
export SKETCH="${plugin}"
|
|
$0 "${plugin}" compile
|
|
done
|
|
}
|
|
|
|
|
|
size () {
|
|
compile
|
|
|
|
echo "- Size: ${ELF_FILE_PATH}"
|
|
# shellcheck disable=SC2086
|
|
firmware_size "${AVR_SIZE}" ${AVR_SIZE_FLAGS} "${ELF_FILE_PATH}"
|
|
echo
|
|
}
|
|
|
|
size_map () {
|
|
compile
|
|
|
|
"${AVR_NM}" --size-sort -C -r -l -t decimal "${ELF_FILE_PATH}"
|
|
}
|
|
|
|
disassemble () {
|
|
compile
|
|
|
|
"${AVR_OBJDUMP}" -C -d "${ELF_FILE_PATH}"
|
|
}
|
|
|
|
decompile () {
|
|
disassemble
|
|
}
|
|
|
|
clean () {
|
|
find_sketch
|
|
build_paths
|
|
rm -rf -- "${OUTPUT_PATH}"
|
|
rm -rf -- "${BUILD_PATH}"
|
|
kaleidoscope_dir="$(dirname "$0")/.."
|
|
if [ -d "${kaleidoscope_dir}/testing/googletest/build" ]; then
|
|
( cd "${kaleidoscope_dir}/testing/googletest/build" &&
|
|
cmake .. &&
|
|
make clean)
|
|
fi
|
|
}
|
|
|
|
reset_device() {
|
|
find_device_port
|
|
check_device_port
|
|
reset_device_cmd
|
|
}
|
|
|
|
check_device_port () {
|
|
if [ -z "$DEVICE_PORT" ]; then
|
|
cat <<EOF >&2
|
|
|
|
I couldn't autodetect the keyboard's serial port.
|
|
|
|
If you see this message and your keyboard is connected to your computer,
|
|
it may mean that our serial port detection logic is buggy or incomplete.
|
|
In that case, please report this issue at:
|
|
https://github.com/keyboardio/Kaleidoscope
|
|
EOF
|
|
exit 1
|
|
elif echo "$DEVICE_PORT" | grep -q '[[:space:]]'; then
|
|
cat <<EOF >&2
|
|
Unexpected whitespace found in detected serial port:
|
|
|
|
$DEVICE_PORT
|
|
|
|
If you see this message, it means that our serial port
|
|
detection logic is buggy or incomplete.
|
|
|
|
Please report this issue at:
|
|
https://github.com/keyboardio/Kaleidoscope
|
|
EOF
|
|
exit 1
|
|
fi
|
|
|
|
if ! [ -w "$DEVICE_PORT" ]; then
|
|
cat <<EOF >&2
|
|
|
|
In order to update your keyboard's firmware you need to have permission
|
|
to write to its serial port $DEVICE_PORT.
|
|
|
|
It appears that you do not have this permission:
|
|
|
|
$(ls -l "$DEVICE_PORT")
|
|
|
|
This may be because you're not in the correct unix group:
|
|
|
|
$(stat -c %G "$DEVICE_PORT").
|
|
|
|
You are currently in the following groups:
|
|
|
|
$(id -Gn)
|
|
|
|
Please ensure you have followed the instructions on setting up your
|
|
account to be in the right group:
|
|
|
|
https://github.com/keyboardio/Kaleidoscope/wiki/Install-Arduino-support-on-Linux
|
|
|
|
EOF
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
|
|
usage () {
|
|
cat <<- EOF
|
|
Usage: $0 SKETCH commands...
|
|
|
|
Runs all of the commands in the context of the Sketch.
|
|
|
|
Available commands:
|
|
|
|
help
|
|
This help screen.
|
|
|
|
compile
|
|
Compiles the sketch.
|
|
|
|
size
|
|
Reports the size of the compiled sketch.
|
|
|
|
build
|
|
Runs compile and report-size.
|
|
|
|
clean
|
|
Cleans up the output directory.
|
|
|
|
size-map
|
|
Displays the size map for the sketch.
|
|
|
|
disassemble
|
|
Decompile the sketch.
|
|
|
|
reset-device
|
|
Reset the device.
|
|
|
|
flash
|
|
Flashes the firmware using avrdude.
|
|
|
|
build-all
|
|
Build all Sketches we can find.
|
|
|
|
EOF
|
|
}
|
|
|
|
help () {
|
|
usage
|
|
}
|
|
|
|
if [ $# -lt 1 ]; then
|
|
usage
|
|
exit 1
|
|
fi
|
|
|
|
## Parse the command-line
|
|
## - anything that has a =, is an env var
|
|
## - from the remaining stuff, the first one is the Library/Sketch
|
|
## - everything else are commands
|
|
##
|
|
## - if there is only one argument, that's a command
|
|
|
|
KALEIDOSCOPE_DIR="$(cd "$(dirname "$0")"/..; pwd)"
|
|
# shellcheck disable=SC2034
|
|
KALEIDOSCOPE_BIN_DIR="${KALEIDOSCOPE_DIR}/bin/"
|
|
|
|
|
|
|
|
|
|
# shellcheck disable=SC2155
|
|
export SOURCEDIR="$(pwd)"
|
|
|
|
|
|
for conf_file in \
|
|
"${HOME}/.kaleidoscope-builder.conf" \
|
|
"${SOURCEDIR}/.kaleidoscope-builder.conf" \
|
|
"${SOURCEDIR}/kaleidoscope-builder.conf" \
|
|
"${KALEIDOSCOPE_DIR}/etc/kaleidoscope-builder.conf"; do
|
|
if [ -e "${conf_file}" ]; then
|
|
# shellcheck disable=SC1090
|
|
. "${conf_file}"
|
|
fi
|
|
|
|
done
|
|
|
|
# shellcheck disable=SC1090
|
|
|
|
if [ -n "${VERBOSE}" ] && [[ "${VERBOSE}" -gt 0 ]]; then
|
|
ARDUINO_VERBOSE="-verbose"
|
|
else
|
|
ARDUINO_VERBOSE="-quiet"
|
|
fi
|
|
|
|
cmds=""
|
|
|
|
## Export vars
|
|
for i in $(seq 1 $#); do
|
|
v="$1"
|
|
shift
|
|
|
|
case "${v}" in
|
|
*=*)
|
|
# Exporting an expansion is *precisely* what we want here.
|
|
# shellcheck disable=SC2086,SC2163
|
|
export ${v}
|
|
;;
|
|
*)
|
|
cmds="${cmds} ${v}"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Word splitting is desired here.
|
|
# shellcheck disable=SC2086
|
|
set -- ${cmds}
|
|
|
|
if [ $# -eq 1 ]; then
|
|
cmd="$(echo "$1" | tr '-' '_')"
|
|
${cmd}
|
|
exit $?
|
|
fi
|
|
|
|
SKETCH="$1"
|
|
shift
|
|
|
|
if [ "${SKETCH}" = "default" ]; then
|
|
SKETCH="${DEFAULT_SKETCH}"
|
|
fi
|
|
|
|
cmds=""
|
|
|
|
# shellcheck disable=2034
|
|
for i in $(seq 1 $#); do
|
|
cmds="${cmds} $(echo "$1" | tr '-' '_')"
|
|
shift
|
|
done
|
|
|
|
for cmd in ${cmds}; do
|
|
${cmd}
|
|
done
|