Add a script for compiling projects
This commit is contained in:
parent
c7d0734c5d
commit
bf5d0c1dfe
3 changed files with 238 additions and 0 deletions
3
.dockerignore
Normal file
3
.dockerignore
Normal file
|
@ -0,0 +1,3 @@
|
|||
Dockerfile
|
||||
LICENSE
|
||||
README.md
|
|
@ -183,4 +183,7 @@ RUN \
|
|||
RUN ln -s /usr/bin/gdb-multiarch /usr/bin/arm-none-eabi-gdb
|
||||
RUN echo "${USER_NAME} ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/keil
|
||||
|
||||
COPY ./compile.sh /bin/st-compile
|
||||
RUN chmod a+x /bin/st-compile
|
||||
|
||||
ENV USER_NAME=${USER_NAME}
|
||||
|
|
232
compile.sh
Normal file
232
compile.sh
Normal file
|
@ -0,0 +1,232 @@
|
|||
#!/bin/bash
|
||||
projectPattern="*.uvprojx";
|
||||
|
||||
function handle_status() {
|
||||
if [ $1 -ne 0 ]; then
|
||||
echo "Error: $2 (status code: $1)";
|
||||
exit $1;
|
||||
fi
|
||||
}
|
||||
|
||||
function regex_escape() {
|
||||
echo "$1" | sed "s/[^\^]/[&]/g; s/\^/\0/g";
|
||||
}
|
||||
|
||||
function normalize_path() {
|
||||
echo "$1" | sed "s/\\\\/\\//g";
|
||||
}
|
||||
|
||||
function getTargetXPath() {
|
||||
index="$1";
|
||||
echo -n "Project/Targets/Target";
|
||||
|
||||
if [ ! -z "$index" ]
|
||||
then
|
||||
echo -n "[$index]";
|
||||
fi;
|
||||
|
||||
echo "";
|
||||
}
|
||||
|
||||
function getFileXPath() {
|
||||
index="$1";
|
||||
echo "$(echo -n "$(getTargetXPath "$index")")/Groups/Group/Files/File/FilePath";
|
||||
}
|
||||
|
||||
function getOptionPath() {
|
||||
index="$1";
|
||||
echo "$(echo -n "$(getTargetXPath "$index")")/TargetOption/TargetCommonOption";
|
||||
}
|
||||
|
||||
function find_files() {
|
||||
local -n files=$1;
|
||||
arguments=("${@:2}");
|
||||
readarray -d '' files < <(find "${arguments[@]}" -print0);
|
||||
return;
|
||||
}
|
||||
|
||||
function find_project() {
|
||||
file="$1";
|
||||
currentDir="$(dirname "$file")";
|
||||
find_files projectFiles "$currentDir" -name "$projectPattern";
|
||||
|
||||
while true;
|
||||
do
|
||||
for projectFile in "${projectFiles[@]}"
|
||||
do
|
||||
if containsFile "$file" "$projectFile"
|
||||
then
|
||||
echo "$projectFile";
|
||||
return;
|
||||
fi;
|
||||
done;
|
||||
|
||||
if [ "$currentDir" != "/" ];
|
||||
then
|
||||
currentDir="$(dirname "$currentDir")";
|
||||
find_files projectFiles "$currentDir" -maxdepth 1 -name "$projectPattern";
|
||||
else
|
||||
break;
|
||||
fi;
|
||||
done;
|
||||
}
|
||||
|
||||
function containsFile() {
|
||||
local i;
|
||||
file="$1";
|
||||
projectFile="$2";
|
||||
targetIndex="$3";
|
||||
xpath="$(getFileXPath "$targetIndex")";
|
||||
|
||||
relativePath="$(realpath --relative-to "$(dirname "$projectFile")" "$(dirname "$file")")";
|
||||
filePattern="$(regex_escape "$(basename "$file")")";
|
||||
|
||||
while [ "$relativePath" != "." ];
|
||||
do
|
||||
filePattern="$(regex_escape "$(basename "$relativePath")")"'[/\\\\]'"$filePattern";
|
||||
relativePath="$(dirname "$relativePath")";
|
||||
done;
|
||||
|
||||
fileCount="$(xmlstarlet select --template --copy-of "count($xpath)" "$projectFile")";
|
||||
|
||||
for i in $(seq 1 $fileCount)
|
||||
do
|
||||
currentFileName="$(xmlstarlet select --template --match "($xpath)[$i]" --value-of . "$projectFile")";
|
||||
currentFileName="$(normalize_path "$currentFileName")";
|
||||
currentFileName="$(realpath --relative-to=. -m "$currentFileName")";
|
||||
|
||||
if echo "$currentFileName" | grep "^$filePattern$" > /dev/null
|
||||
then
|
||||
true;
|
||||
return;
|
||||
fi;
|
||||
done;
|
||||
|
||||
false;
|
||||
}
|
||||
|
||||
function chooseTarget() {
|
||||
local i;
|
||||
projectFile="$1";
|
||||
file="$2";
|
||||
targetCandidates=();
|
||||
targetCount="$(xmlstarlet select --template --copy-of "count($(getTargetXPath))" "$projectFile")";
|
||||
|
||||
if [ $targetCount -gt 0 ]
|
||||
then
|
||||
for i in $(seq 1 $targetCount)
|
||||
do
|
||||
if containsFile "$file" "$projectFile" "$i"
|
||||
then
|
||||
targetCandidates+=("$i");
|
||||
fi;
|
||||
done;
|
||||
|
||||
if [ "${#targetCandidates[@]}" = 0 ]
|
||||
then
|
||||
targetCandidates=($(seq 1 "$targetCount"));
|
||||
fi;
|
||||
|
||||
while [ ! "${#targetCandidates[@]}" = 1 ]
|
||||
do
|
||||
|
||||
echo "Which Target Would You Like to Build?";
|
||||
|
||||
for j in $(seq 1 "${#targetCandidates[@]}")
|
||||
do
|
||||
index="${targetCandidates["$(expr $j - 1)"]}";
|
||||
targetName="$(xmlstarlet select --template --match "$(getTargetXPath "$index")/TargetName" --value-of . "$projectFile")";
|
||||
echo "$(printf "%${#targetCount}s" "$index"): \"$targetName\"";
|
||||
done;
|
||||
read -p "Enter your choice: " choice;
|
||||
|
||||
if [ $choice -gt 0 ] && [ $choice -le "${#targetCandidates[@]}" ]
|
||||
then
|
||||
targetCandidates=("${targetCandidates[$(expr $choice - 1)]}");
|
||||
fi;
|
||||
done;
|
||||
|
||||
return "${targetCandidates[0]}";
|
||||
else
|
||||
handle_status 1 "The current project '$projectFile' doesn't contain any targets!";
|
||||
fi;
|
||||
}
|
||||
|
||||
fileName="$(realpath "$1")";
|
||||
|
||||
if [[ "$fileName" =~ \.uvprojx$ ]]
|
||||
then
|
||||
projectFile="$fileName";
|
||||
else
|
||||
projectFile="$(find_project "$fileName")";
|
||||
fi
|
||||
|
||||
if [ ! -z "$projectFile" ];
|
||||
then
|
||||
projectRoot="$(dirname "$projectFile")";
|
||||
cd "$projectRoot";
|
||||
tempFile="$(mktemp)";
|
||||
cp -f "$projectFile" "$tempFile";
|
||||
|
||||
chooseTarget "$projectFile" "$fileName";
|
||||
targetIndex="$?";
|
||||
|
||||
targetPath="$(getTargetXPath "$targetIndex")";
|
||||
optionPath="$(getOptionPath "$targetIndex")";
|
||||
|
||||
fileCount="$(xmlstarlet select --template --copy-of "count($(getFileXPath))" "$projectFile")";
|
||||
targetName="$(xmlstarlet select --template --match "$targetPath/TargetName" --value-of . "$projectFile")";
|
||||
buildPath="$(xmlstarlet select --template --match "$optionPath/OutputDirectory" --value-of . "$projectFile")";
|
||||
outputName="$(xmlstarlet select --template --match "$optionPath/OutputName" --value-of . "$projectFile")";
|
||||
buildPath="$(normalize_path "$buildPath")";
|
||||
outputName="$(normalize_path "$outputName")";
|
||||
|
||||
echo "Building Target \"$targetName\"";
|
||||
echo "";
|
||||
|
||||
for i in $(seq 1 $fileCount)
|
||||
do
|
||||
xpath="($(getFileXPath))[$i]"
|
||||
currentFileName="$(xmlstarlet select --template --match "$xpath" --value-of . "$projectFile")";
|
||||
currentFileName="$(normalize_path "$currentFileName")";
|
||||
xmlstarlet edit --inplace --update "$xpath" --value "$currentFileName" "$projectFile";
|
||||
done;
|
||||
|
||||
logFile="$(mktemp)";
|
||||
|
||||
xvfb-run bash -c "dwm & wine \"C:\Keil_v5\UV4\UV4.exe\" -j0 -b \"$projectFile\" -t \"$targetName\" -l \"$logFile\"" > /dev/null 2>&1;
|
||||
mv -f "$tempFile" "$projectFile";
|
||||
|
||||
errorPattern="\(.*\)\(([[:digit:]]\+): \(warning\|note\|error\): \([A-Z0-9]\+: \)\?.*\)$";
|
||||
|
||||
sed -i \
|
||||
-e "/$errorPattern/{" \
|
||||
-e "h; s/$errorPattern/realpath \"\1\"/;" \
|
||||
-e "x; s/$errorPattern/\2/; x;" \
|
||||
-e "e" \
|
||||
-e "G; s/\n//;" \
|
||||
-e "}" "$logFile";
|
||||
|
||||
cat "$logFile";
|
||||
|
||||
if grep -q " 0 Error(s)" "$logFile";
|
||||
then
|
||||
outputName="$(realpath "$projectRoot/$buildPath/$outputName")";
|
||||
outputFile="$outputName.axf";
|
||||
echo "The File Has Been Built to \`$outputFile\`.";
|
||||
pyocd list | {
|
||||
grep '^No available' &&
|
||||
{
|
||||
echo "Skpping flash."
|
||||
} ||
|
||||
{
|
||||
pyocd flash --target stm32f439xi "$outputFile";
|
||||
handle_status $? "Flashing failed";
|
||||
};
|
||||
};
|
||||
else
|
||||
handle_status 1 "The project could not be built!";
|
||||
fi;
|
||||
else
|
||||
handle_status 1 "No project file for \`${fileName}\` could be found."
|
||||
fi;
|
Loading…
Reference in a new issue