Create installer script
This commit is contained in:
parent
d0237f2ac6
commit
f1d2738491
183
Dockerfile
183
Dockerfile
|
@ -1,9 +1,9 @@
|
|||
ARG USER_NAME=keil
|
||||
FROM scottyhardy/docker-wine:devel-8.4
|
||||
ARG USER_NAME
|
||||
ARG KEIL_URL=https://armkeil.blob.core.windows.net/eval/MDK537.EXE
|
||||
ARG PACK_URL=https://ennis.zhaw.ch/pack/InES.CTBoard14_DFP.4.0.3.pack
|
||||
ARG DEBUG=0
|
||||
ARG KEIL_URL=
|
||||
ARG PACK_URL=
|
||||
ARG DEBUG=
|
||||
|
||||
RUN \
|
||||
apt-get update \
|
||||
|
@ -27,182 +27,11 @@ RUN \
|
|||
&& rm -rf /var/lib/apt/lists/
|
||||
|
||||
RUN pip install pyocd
|
||||
COPY ./install-keil.sh .
|
||||
|
||||
RUN \
|
||||
installerExtension=".exe"; \
|
||||
installer="$(mktemp --suffix="$installerExtension")"; \
|
||||
installerName="$(basename "$installer" | sed "s/$installerExtension$//")"; \
|
||||
export DISPLAY=:90; \
|
||||
mkdir -p --mode=777 /tmp/.X11-unix; \
|
||||
# Create job for waiting for Xvfb to start
|
||||
watchStarting="$(mktemp)"; \
|
||||
{ 2>&1 inotifywait -e create /tmp/.X11-unix/ > /dev/null; } | { sed -u -e "/^Watches established.\$/e rm \"$watchStarting\""; } & \
|
||||
displayResolver="$!"; \
|
||||
while [ -f "$watchStarting" ]; do true; done; \
|
||||
{ \
|
||||
# Improve arguments for screenshots
|
||||
ARGS="$([ $DEBUG -eq 1 ] && echo "-screen 0 640x480x24 -dpi 192" || echo "")"; \
|
||||
Xvfb "${DISPLAY}" ${ARGS} & \
|
||||
}; \
|
||||
displayPID="$!"; \
|
||||
rm "$installer"; \
|
||||
wget "${KEIL_URL}" --progress=bar:force:noscroll -O "$installer"; \
|
||||
[ "$DEBUG" -eq 1 ] && { \
|
||||
apt-get update; \
|
||||
apt-get install -y \
|
||||
build-essential \
|
||||
imagemagick; \
|
||||
rm -rf /var/lib/apt/lists; \
|
||||
TIV="$(mktemp)"; \
|
||||
logDir="logs"; \
|
||||
screenDir="$logDir/screens"; \
|
||||
git clone https://github.com/stefanhaustein/TerminalImageViewer.git && \
|
||||
cd TerminalImageViewer/src/main/cpp && \
|
||||
make && \
|
||||
apt-get remove -y build-essential && \
|
||||
apt-get autoremove -y && \
|
||||
mv tiv "$TIV" && \
|
||||
cd - && \
|
||||
rm -rf TerminalImageViewer; \
|
||||
mkdir -p "$logDir"; \
|
||||
mkdir -p "$screenDir"; \
|
||||
} || true; \
|
||||
printHeading() { \
|
||||
local heading; \
|
||||
heading="====================================================="; \
|
||||
echo "$heading"; \
|
||||
[ -z "$1" ] && cat || echo "$1"; \
|
||||
echo "$heading"; \
|
||||
}; \
|
||||
# Run actual Keil uVision installer
|
||||
install_keil() { \
|
||||
try="$1"; \
|
||||
logFile="$(mktemp)"; \
|
||||
printHeading "Starting ARM Keil installation"; \
|
||||
# Run installer asynchronously
|
||||
{ \
|
||||
{ \
|
||||
local exitCode; \
|
||||
exitCodeFile="$(mktemp)"; \
|
||||
{ \
|
||||
2>&1 WINEDEBUG=+all,trace-all,warn-all /usr/bin/entrypoint wine "$installer" --batch-install; \
|
||||
echo "$?" > "$exitCodeFile"; \
|
||||
} \
|
||||
# Write output to a log file when debugging
|
||||
| { [ "$DEBUG" -eq 1 ] && tee "$logFile" || cat; } \
|
||||
# Pipe stdout and stderr to `handle_output` function
|
||||
| handle_output; \
|
||||
outputHandlerCode="$?"; \
|
||||
exitCode="$(cat "$exitCodeFile")"; \
|
||||
rm "$exitCodeFile"; \
|
||||
bash -c "exit $([ "$outputHandlerCode" -ne 0 ] && echo "$outputHandlerCode" || echo "$exitCode")"; \
|
||||
} & \
|
||||
}; \
|
||||
pid="$!"; \
|
||||
# Continuously display screenshots and iteration number
|
||||
[ "$DEBUG" -eq 1 ] \
|
||||
&& { \
|
||||
{ \
|
||||
x=0; \
|
||||
maxCount=120; \
|
||||
while ps -p "$pid" > /dev/null && [ "$x" -ne "$maxCount" ]; do \
|
||||
# Create screenshot and print it to the console
|
||||
fileName="$screenDir/install-try$try-$x.png"; \
|
||||
import -window root "$fileName"; \
|
||||
"$TIV" -w 10000 -h 10000 "$fileName"; \
|
||||
x="$(expr "$x" + 1)"; \
|
||||
echo "Frame #$x"; \
|
||||
sleep 1; \
|
||||
done; \
|
||||
# Kill installer after timeout indicated by `maxCount`
|
||||
[ "$x" -eq "$maxCount" ] && { kill_installer; mv "$logFile" "$logDir/timeout-try$try.log"; }; \
|
||||
} & \
|
||||
}; \
|
||||
wait "$pid"; \
|
||||
exitCode="$?"; \
|
||||
# Rename log file according to the state of the installer
|
||||
[ "$DEBUG" -eq 1 ] \
|
||||
&& [ -f "$logFile" ] \
|
||||
&& { \
|
||||
# Move logs to location based on exit code
|
||||
[ "$exitCode" -eq 0 ] && mv "$logFile" "$logDir/success-try$try.log"; \
|
||||
[ "$exitCode" -eq 42 ] && mv "$logFile" "$logDir/timeout-handled-try$try.log"; \
|
||||
[ "$exitCode" -ne 0 ] && mv "$logFile" "$logDir/fail-try$try.log"; \
|
||||
}; \
|
||||
{ \
|
||||
[ "$exitCode" -ne 0 ] && { \
|
||||
[ "$exitCode" -eq 42 ] && echo "The installation Got Stuck" || \
|
||||
echo "The Installation Failed"; \
|
||||
} || \
|
||||
echo "The Installation Was Successful"; \
|
||||
echo "Installation Process Exited With Code $exitCode"; \
|
||||
} | printHeading; \
|
||||
return "$exitCode"; \
|
||||
}; \
|
||||
# Handle console output of Keil uVision installer
|
||||
handle_output() { \
|
||||
# A pattern that is supposed to indicates that wine got stuck
|
||||
pattern="fixme:win:NtUserLockWindowUpdate ((nil))"; \
|
||||
# The amount of times the pattern should occur for the process to be considered stuck
|
||||
patternCount=2; \
|
||||
sed \
|
||||
-u \
|
||||
# Handle multiple occurrences of $pattern
|
||||
-e "/$pattern/{ x; s/^x\{$(expr $patternCount - 1)\}$/\0/; x; t stuck; x; s/^\(x*\)$/\1x/; x; };" \
|
||||
# Return to start
|
||||
-e "b;" \
|
||||
# Branch "stuck": delete output and exit with code 42
|
||||
-e ":stuck q42;" \
|
||||
# Branch "end": exit with code 0
|
||||
-e ":end q;"; \
|
||||
exitCode="$?"; \
|
||||
# Kill installer if it got stuck (according to console output)
|
||||
[ "$exitCode" -eq 42 ] && kill_installer; \
|
||||
# Use `sed`s exit code if non-zero
|
||||
[ "$exitCode" -ne 0 ] && exit "$exitCode" || \
|
||||
# Return true otherwise
|
||||
true; \
|
||||
}; \
|
||||
kill_installer() { \
|
||||
pkill -9 "$installerName" > /dev/null 2>&1; \
|
||||
}; \
|
||||
# Wait for Xvfb to start
|
||||
wait "$displayResolver"; \
|
||||
y=0; \
|
||||
while ! \
|
||||
install_keil \
|
||||
"$y" \
|
||||
; \
|
||||
do \
|
||||
printHeading "Restarting Installation"; \
|
||||
# Increase counter
|
||||
y="$(expr "$y" + 1)"; \
|
||||
done && \
|
||||
kill -9 "$displayPID" > /dev/null 2>&1; \
|
||||
# Cleanup Unnecessary Files
|
||||
rm -f "$TIV"; \
|
||||
rm -rf "$(/usr/bin/entrypoint winepath 'C:\Keil_v5')/Backup."*; \
|
||||
rm "$installer"; \
|
||||
rm -f /tmp/.X*-lock; \
|
||||
[ "$DEBUG" -eq 1 ] && { \
|
||||
apt-get remove -y imagemagick; \
|
||||
apt-get autoremove -y; \
|
||||
} || true
|
||||
|
||||
RUN \
|
||||
keilConfig="$(/usr/bin/entrypoint winepath 'C:\Keil_v5\TOOLS.INI')" && \
|
||||
winAppData="$(/usr/bin/entrypoint wine cmd.exe /c 'echo %LOCALAPPDATA%' | tr -d '\r' | sed 's/\\/\\\\/g')" && \
|
||||
packDir="$winAppData"'\Arm\Packs' && \
|
||||
sed -i '/^RTEPATH=/d' "$keilConfig" && \
|
||||
echo 'RTEPATH="'"$packDir"'"' | sed -i '/\[UV2\]/ r /dev/stdin' "$keilConfig"
|
||||
|
||||
RUN \
|
||||
wget "${PACK_URL}" --progress=bar:force:noscroll --no-check-certificate -O InES.pack; \
|
||||
/usr/bin/entrypoint xvfb-run wine 'C:\Keil_v5\UV4\PackUnzip.exe' --embedded --agree-license InES.pack & \
|
||||
pid="$!"; \
|
||||
wait "$pid"; \
|
||||
rm InES.pack; \
|
||||
rm -f /tmp/.X*-lock;
|
||||
./install-keil.sh && \
|
||||
rm ./install-keil.sh
|
||||
|
||||
RUN \
|
||||
apt-get update && \
|
||||
|
|
230
install-keil.sh
Executable file
230
install-keil.sh
Executable file
|
@ -0,0 +1,230 @@
|
|||
#!/bin/bash
|
||||
export DEBUG="${DEBUG:-0}";
|
||||
export KEIL_URL="${KEIL_URL:-https://armkeil.blob.core.windows.net/eval/MDK537.EXE}";
|
||||
export PACK_URL="${PACK_URL:-https://ennis.zhaw.ch/pack/InES.CTBoard14_DFP.4.0.3.pack}";
|
||||
|
||||
installerExtension=".exe";
|
||||
installer="$(mktemp --suffix="$installerExtension")";
|
||||
installerName="$(basename "$installer" | sed "s/$installerExtension$//")";
|
||||
|
||||
export DISPLAY=:90;
|
||||
mkdir -p --mode=777 /tmp/.X11-unix;
|
||||
|
||||
# Create a job for waiting for Xvfb to start
|
||||
watchStarting="$(mktemp)";
|
||||
{ 2>&1 inotifywait -e create /tmp/.X11-unix/; } | { sed -u -e "/^Watches established.$/e rm \"$watchStarting\""; } &
|
||||
displayResolver="$!";
|
||||
|
||||
# Wait for `inotifywait` to start
|
||||
while [ -f "$watchStarting" ]; do sleep 0.5; done;
|
||||
|
||||
{
|
||||
# Improve arguments for screenshots
|
||||
ARGS="$([ "$DEBUG" -eq 1 ] && echo "-screen 0 640x480x24 -dpi 192" || echo "")";
|
||||
Xvfb "${DISPLAY}" ${ARGS} &
|
||||
};
|
||||
|
||||
displayPID="$!";
|
||||
wget ${KEIL_URL} --progress=bar:force:noscroll -O "$installer";
|
||||
|
||||
# Preparations for Debug Logs
|
||||
if [ "$DEBUG" -eq 1 ]
|
||||
then
|
||||
dir="$(mktemp -d)";
|
||||
TIV="$(mktemp)";
|
||||
logDir="log";
|
||||
screenDir="$logDir/screens";
|
||||
git clone https://github.com/stefanhaustein/TerminalImageViewer.git "$dir";
|
||||
git checkout "v1.1.1";
|
||||
cd "$dir/src/main/cpp";
|
||||
make;
|
||||
mv tiv "$TIV";
|
||||
cd -;
|
||||
rm -rf "$dir";
|
||||
mkdir -p "$logDir";
|
||||
mkdir -p "$screenDir";
|
||||
fi
|
||||
|
||||
function printHeading() {
|
||||
local heading;
|
||||
heading="=====================================================";
|
||||
echo "$heading";
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
cat;
|
||||
else
|
||||
echo "$1";
|
||||
fi;
|
||||
|
||||
echo "$heading";
|
||||
}
|
||||
|
||||
function kill_installer() {
|
||||
pkill -9 "$installerName" > /dev/null 2>&1;
|
||||
}
|
||||
|
||||
function handle_output() {
|
||||
# Pattern that is supposed to indicate that wine got stuck
|
||||
pattern="fixme:win:NtUserLockWindowUpdate ((nil))";
|
||||
# The number of occurences of the pattern which have to occur to assume wine got stuck
|
||||
patternCount=2;
|
||||
|
||||
sed \
|
||||
-u \
|
||||
`# Handle the pattern and the chosen pattern count` \
|
||||
-e "/$pattern/{ x; s/^x\{$(expr "$patternCount" - 1)\}$/\0/; x; t stuck; x; s/^\(x*\)$/\1x/; x; };" \
|
||||
`# Return to start` \
|
||||
-e "b;" \
|
||||
`# Branch "stuck": delete output and exit with code 42` \
|
||||
-e ":stuck q42;" \
|
||||
`# Branch "end": exit with code 0` \
|
||||
-e ":end q;";
|
||||
|
||||
exitCode="$?";
|
||||
|
||||
# Kill installer if it got stuck (based on the console output and the pattern)
|
||||
if [ "$exitCode" -ne 0 ]
|
||||
then
|
||||
kill_installer;
|
||||
return "$exitCode";
|
||||
fi;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Install Keil uVision
|
||||
function install_keil() {
|
||||
try="$1";
|
||||
logFile="$(mktemp)";
|
||||
printHeading "Starting ARM Keil Installation";
|
||||
|
||||
# Run installer asynchronously
|
||||
{
|
||||
{
|
||||
local exitCode;
|
||||
exitCodeFile="$(mktemp)";
|
||||
|
||||
{
|
||||
2>&1 WINEDEBUG=+all,trace-all,warn-all wine "$installer" --batch-install;
|
||||
echo "$?" > "$exitCodeFile";
|
||||
} | \
|
||||
# Write output to a log file when debugging
|
||||
{ [ "$DEBUG" -eq 1 ] && { tee "$logFile"; } || cat; } | \
|
||||
# Pipe stdout and stderr to `handle_output` function
|
||||
handle_output;
|
||||
|
||||
outputHandlerCode="$?";
|
||||
exitCode="$(cat "$exitCodeFile")";
|
||||
rm "$exitCodeFile";
|
||||
|
||||
if [ "$outputHandlerCode" -ne 0 ]
|
||||
then
|
||||
exitCode="$outputHandlerCode";
|
||||
fi;
|
||||
|
||||
bash -c "exit $exitCode";
|
||||
} &
|
||||
};
|
||||
|
||||
pid="$!";
|
||||
|
||||
# Continuously display screenshots and iteration number when debugging
|
||||
if [ "$DEBUG" -eq 1 ]
|
||||
then
|
||||
{
|
||||
{
|
||||
x=0;
|
||||
maxCount=120;
|
||||
|
||||
while ps -p "$pid" > /dev/null && [ "$x" -ne "$maxCount" ]
|
||||
do
|
||||
# Create screenshot and print it to the console
|
||||
fileName="$screenDir/install-try$try-$x.png";
|
||||
import -window root "$fileName";
|
||||
"$TIV" -w 10000 -h 10000 "$fileName";
|
||||
x="$(expr "$x" + 1)";
|
||||
echo "Frame #$x";
|
||||
sleep 1;
|
||||
done;
|
||||
|
||||
# Kill the installer once `maxCount` has been reached
|
||||
if [ "$x" -eq "$maxCount" ]
|
||||
then
|
||||
kill_installer;
|
||||
mv "$logFile" "./$logDir/log-timeout-try$try.log";
|
||||
fi;
|
||||
} &
|
||||
};
|
||||
fi;
|
||||
|
||||
wait "$pid";
|
||||
exitCode="$?";
|
||||
|
||||
if [ "$DEBUG" -eq 1 ] && [ -f "$logFile" ]
|
||||
then
|
||||
if [ $exitCode -eq 0 ]
|
||||
then
|
||||
mv "$logFile" "./$logDir/success-try$try.log";
|
||||
elif [ $exitCode -eq 42 ]
|
||||
then
|
||||
mv "$logFile" "./$logDir/timeout-handled-try$try.log";
|
||||
else
|
||||
mv "$logFile" "./$logDir§/fail-try$try.txt";
|
||||
fi;
|
||||
fi;
|
||||
|
||||
{
|
||||
if [ $exitCode -ne 0 ]
|
||||
then
|
||||
if [ $exitCode -eq 42 ]
|
||||
then
|
||||
echo "The Installation Got Stuck";
|
||||
else
|
||||
echo "The Installation Failed";
|
||||
fi;
|
||||
else
|
||||
echo "The Installation Was Successul";
|
||||
fi;
|
||||
|
||||
echo "The Installation Process Exited With Code $exitCode";
|
||||
} | printHeading;
|
||||
|
||||
return "$exitCode";
|
||||
}
|
||||
|
||||
# Wait for Xvfb to start
|
||||
wait "$displayResolver";
|
||||
|
||||
y=0;
|
||||
|
||||
while ! install_keil "$y"
|
||||
do
|
||||
printHeading "Restarting Installation";
|
||||
y="$(expr "$y" + 1)";
|
||||
done;
|
||||
|
||||
kill -9 "$displayPID" > /dev/null 2>&1;
|
||||
|
||||
# Delete unfinished installations
|
||||
rm -rf "$(winepath 'C:\Keil_v5')/Backup."*;
|
||||
rm "$installer";
|
||||
rm -rf /tmp/.X*-lock;
|
||||
|
||||
# Fix incorrect `RTEPATH` setting
|
||||
keilConfig="$(winepath 'C:\Keil_v5\TOOLS.INI')";
|
||||
winAppData="$(wine cmd.exe /c 'echo %LOCALAPPDATA%' | tr -d '\r' | sed 's/\\/\\\\/g')";
|
||||
packDir="$winAppData"'\Arm\Packs';
|
||||
sed -i '/^RTEPATH=/d' "$keilConfig";
|
||||
echo 'RTEPATH="'"$packDir"'"' | sed -i '/\[UV2\]/ r /dev/stdin' "$keilConfig";
|
||||
|
||||
# Install additional package
|
||||
if [ ! -z "$PACK_URL" ]
|
||||
then
|
||||
packFile="$(mktemp)";
|
||||
wget "${PACK_URL}" --progress=bar:force:noscroll --no-check-certificate -O "$packFile";
|
||||
xvfb-run wine "C:\Keil_v5\UV4\PackUnzip.exe" --embedded --agree-license "$packFile" &
|
||||
pid="$!"; \
|
||||
wait "$pid"; \
|
||||
rm "$packFile";
|
||||
fi;
|
Loading…
Reference in a new issue