mirror of
https://gitea.windcorp.ru/Wind-Corporation/Progressia.git
synced 2025-08-28 03:26:49 +03:00
Squash improve-ide-compat into main
Fixes GH-5 - cppcheck replaced with clang-tidy - clang-tidy lint warnings fixed - Reworked build tools from scratch to make IDE setup easier - Added 1.5 IDE setup guides
This commit is contained in:
@@ -1,66 +0,0 @@
|
||||
#!/bin/false
|
||||
|
||||
# Writes a message to stderr.
|
||||
# Parameters:
|
||||
# $@ - the message to display
|
||||
function error() {
|
||||
echo >&2 "`basename "$0"`: $@"
|
||||
}
|
||||
|
||||
# Writes a message to stderr and exits with code 1.
|
||||
# Parameters:
|
||||
# $@ - the message to display
|
||||
function fail() {
|
||||
error "$@"
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# Ensures that a variable with name $1 has a valid executable. If it does not,
|
||||
# this function attempts to find an executable with a name suggested in $2...$n.
|
||||
# In either way, if the variable does not end up naming an executable, fail() is
|
||||
# called.
|
||||
# Parameters:
|
||||
# $1 - name of the variable to check and modify
|
||||
# $2...$n - suggested executables (at least one)
|
||||
# $FAIL_SILENTLY - if set, don't call exit and don't print anything on failure
|
||||
function find_cmd() {
|
||||
declare -n target="$1"
|
||||
|
||||
if [ -z "${target+x}" ]; then
|
||||
for candidate in "${@:2}"; do
|
||||
if command -v "$candidate" >/dev/null; then
|
||||
target="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if ! command -v "$target" >/dev/null; then
|
||||
[ -n "${FAIL_SILENTLY+x}" ] && return 1
|
||||
fail "Command $2 is not available. Check \$PATH or set \$$1."
|
||||
fi
|
||||
|
||||
unset -n target
|
||||
return 0
|
||||
}
|
||||
|
||||
# Displays the command and then runs it.
|
||||
# Parameters:
|
||||
# $@ - the command to run
|
||||
function echo_and_run() {
|
||||
echo " > $*"
|
||||
command "$@"
|
||||
}
|
||||
|
||||
root_dir="$(dirname "$(dirname "$(realpath "${BASH_SOURCE[0]}")")")"
|
||||
source_dir="$root_dir"
|
||||
build_dir="$root_dir/build"
|
||||
tools_dir="$root_dir/tools"
|
||||
|
||||
# Load private.sh
|
||||
private_sh="$tools_dir/private.sh"
|
||||
if [ -f "$private_sh" ]; then
|
||||
[ -x "$private_sh" ] \
|
||||
|| fail 'tools/private.sh exists but it is not executable'
|
||||
source "$private_sh"
|
||||
fi
|
199
tools/build.sh
199
tools/build.sh
@@ -1,199 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
usage=\
|
||||
"Usage: build.sh [OPTIONS...]
|
||||
Build and run the game.
|
||||
|
||||
Options:
|
||||
--debug make a debug build (default)
|
||||
--release make a release build
|
||||
--build-id=ID set the build ID. Default is dev.
|
||||
--cmake-gen=ARGS pass additional arguments to pass to cmake when
|
||||
generating build files. ARGS is the ;-separated list.
|
||||
--dont-generate don't generate build instructions; use existing
|
||||
configuration if building
|
||||
--dont-build don't build; run existing binaries or generate build
|
||||
instructions only
|
||||
--debug-vulkan enable Vulkan validation layers from LunarG
|
||||
-R, --run run the game after building
|
||||
--memcheck[=ARGS] run the game using valgrind's memcheck dynamic memory
|
||||
analysis tool. Implies -R. ARGS is the ;-separated
|
||||
list of arguments to pass to valgrind/memcheck.
|
||||
|
||||
-h, --help display this help and exit
|
||||
|
||||
Environment variables:
|
||||
PARALLELISM threads to use, default is 1
|
||||
|
||||
CMAKE cmake executable
|
||||
VALGRIND valgrind executable
|
||||
|
||||
private.sh variables:
|
||||
private_cmake_gen_args array of additional arguments to pass to cmake when
|
||||
generating build files
|
||||
|
||||
See also: tools/cppcheck/use-cppcheck.sh --help
|
||||
tools/clang-format/use-clang-format.sh --help
|
||||
tools/setup.sh --help"
|
||||
|
||||
rsrc="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
|
||||
source "$rsrc/bashlib.sh"
|
||||
|
||||
|
||||
|
||||
# Parse arguments
|
||||
|
||||
build_type=Debug
|
||||
do_generate=true
|
||||
cmake_gen_args=()
|
||||
do_build=true
|
||||
|
||||
run_type=Normal
|
||||
do_run=''
|
||||
|
||||
debug_vulkan=''
|
||||
memcheck_args=()
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
-h | --help )
|
||||
echo "$usage"
|
||||
exit
|
||||
;;
|
||||
--debug )
|
||||
build_type=Debug
|
||||
;;
|
||||
--release )
|
||||
build_type=Release
|
||||
;;
|
||||
--build-id )
|
||||
fail "Option --build-id=ID requires a parameter"
|
||||
;;
|
||||
--build-id=* )
|
||||
build_id="${arg#*=}"
|
||||
;;
|
||||
--cmake-gen )
|
||||
fail "Option --cmake-gen=ARGS requires a parameter"
|
||||
;;
|
||||
--cmake-gen=* )
|
||||
readarray -t -d ';' new_cmake_gen_args <<<"${arg#*=};"
|
||||
unset new_cmake_gen_args[-1]
|
||||
cmake_gen_args+=("${new_cmake_gen_args[@]}")
|
||||
unset new_cmake_gen_args
|
||||
;;
|
||||
--debug-vulkan )
|
||||
debug_vulkan=true
|
||||
;;
|
||||
-R | --run )
|
||||
do_run=true
|
||||
;;
|
||||
--memcheck )
|
||||
do_run=true
|
||||
run_type=memcheck
|
||||
;;
|
||||
--memcheck=* )
|
||||
do_run=true
|
||||
run_type=memcheck
|
||||
readarray -t -d ';' new_memcheck_args <<<"${arg#*=};"
|
||||
unset new_memcheck_args[-1]
|
||||
memcheck_args+=("${new_memcheck_args[@]}")
|
||||
unset new_memcheck_args
|
||||
;;
|
||||
--dont-generate )
|
||||
do_generate=''
|
||||
;;
|
||||
--dont-build )
|
||||
do_build=''
|
||||
;;
|
||||
* )
|
||||
fail "Unknown option '$arg'"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$do_build" -a -z "$do_generate" -a ${#cmake_gen_args[@]} != 0 ]; then
|
||||
fail "CMake arguments are set, but no build is requested. Aborting"
|
||||
fi
|
||||
|
||||
if [ -z "$do_build" -a -z "$do_generate" -a -z "$do_run" ]; then
|
||||
fail "Nothing to do"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Generate build files
|
||||
|
||||
find_cmd CMAKE cmake
|
||||
if [ $do_generate ]; then
|
||||
|
||||
cmake_gen_managed_args=(
|
||||
-DCMAKE_BUILD_TYPE=$build_type
|
||||
-DVULKAN_ERROR_CHECKING=`[ $debug_vulkan ] && echo ON || echo OFF`
|
||||
-UBUILD_ID
|
||||
)
|
||||
|
||||
[ -n "${build_id+x}" ] && cmake_gen_managed_args+=(
|
||||
-DBUILD_ID="$build_id"
|
||||
)
|
||||
|
||||
echo_and_run "$CMAKE" \
|
||||
-B "$build_dir" \
|
||||
-S "$source_dir" \
|
||||
"${cmake_gen_managed_args[@]}" \
|
||||
"${private_cmake_gen_args[@]}" \
|
||||
"${cmake_gen_args[@]}" \
|
||||
|| fail "Could not generate build files"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Build
|
||||
|
||||
find_cmd CMAKE cmake
|
||||
if [ $do_build ]; then
|
||||
options=()
|
||||
|
||||
[ -n "${PARALLELISM+x}" ] && options+=(-j "$PARALLELISM")
|
||||
|
||||
echo_and_run "$CMAKE" \
|
||||
--build "$build_dir" \
|
||||
"${options[@]}" \
|
||||
|| fail "Build failed"
|
||||
|
||||
unset options
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Run
|
||||
|
||||
if [ $do_run ]; then
|
||||
|
||||
run_command=()
|
||||
|
||||
if [ $run_type == memcheck ]; then
|
||||
find_cmd VALGRIND valgrind
|
||||
|
||||
run_command+=(
|
||||
"$VALGRIND"
|
||||
--tool=memcheck
|
||||
--suppressions="$tools_dir"/memcheck/suppressions.supp
|
||||
"${memcheck_args[@]}"
|
||||
--
|
||||
)
|
||||
fi
|
||||
|
||||
run_command+=(
|
||||
"$build_dir/progressia"
|
||||
)
|
||||
|
||||
run_dir="$root_dir/run"
|
||||
mkdir -p "$run_dir"
|
||||
|
||||
(
|
||||
cd "$run_dir"
|
||||
echo_and_run "${run_command[@]}"
|
||||
echo "Process exited with code $?"
|
||||
)
|
||||
|
||||
fi
|
@@ -1,4 +0,0 @@
|
||||
BasedOnStyle: LLVM
|
||||
|
||||
# Use larger indentation
|
||||
IndentWidth: 4
|
@@ -1,102 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
usage=\
|
||||
"Usage: use-clang-format.sh git
|
||||
or: use-clang-format.sh files FILES...
|
||||
or: use-clang-format.sh raw ARGUMENTS...
|
||||
In the 1st form, format all files that have changed since last git commit.
|
||||
In the 2nd form, format all FILES, treating directories recursively.
|
||||
In the 3rd form, run \`clang-format --style=<style> ARGUMENTS...\`.
|
||||
|
||||
Environment variables:
|
||||
CLANG_FORMAT clang-format executable
|
||||
CLANG_FORMAT_DIFF clang-format-diff script"
|
||||
|
||||
rsrc="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
|
||||
source "$rsrc/../bashlib.sh"
|
||||
|
||||
case "$1" in
|
||||
git )
|
||||
find_cmd CLANG_FORMAT_DIFF \
|
||||
clang-format-diff-13 \
|
||||
clang-format-diff \
|
||||
clang-format-diff.py
|
||||
;;
|
||||
files | raw )
|
||||
find_cmd CLANG_FORMAT \
|
||||
clang-format-13 \
|
||||
clang-format
|
||||
;;
|
||||
-h | --help | '' )
|
||||
echo "$usage"
|
||||
exit
|
||||
;;
|
||||
* )
|
||||
fail "Unknown option '$1'"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Generate style argument
|
||||
style=''
|
||||
while IFS='' read line; do
|
||||
[ -z "$line" ] && continue
|
||||
[ "${line:0:1}" = '#' ] && continue
|
||||
[ -n "$style" ] && style+=', '
|
||||
style+="$line"
|
||||
done < "$rsrc/clang-format.yml"
|
||||
style="{$style}" # Not typo
|
||||
|
||||
case "$1" in
|
||||
git )
|
||||
unstaged_changes="`git diff --name-only`"
|
||||
if [ -n "$unstaged_changes" ]; then
|
||||
fail "Refusing to operate in git repository with unstaged changes:
|
||||
$unstaged_changes"
|
||||
fi
|
||||
|
||||
git diff -U0 --no-color --relative HEAD \
|
||||
{desktop,main}/{'*.cpp','*.h','*.inl'} \
|
||||
| command "$CLANG_FORMAT_DIFF" -p1 -style="$style" -i --verbose
|
||||
exit_code="$?"
|
||||
git add "$root_dir"
|
||||
exit "$exit_code"
|
||||
;;
|
||||
|
||||
raw )
|
||||
command "$CLANG_FORMAT" -style="$style" "$@"
|
||||
;;
|
||||
|
||||
files )
|
||||
files=()
|
||||
|
||||
for input in "${@:2}"; do
|
||||
if [ -d "$input" ]; then
|
||||
readarray -d '' current_files < <(
|
||||
find "$input" \
|
||||
\( -name '*.cpp' -o -name '*.h' -o -name '*.inl' \) \
|
||||
-type f \
|
||||
-print0 \
|
||||
)
|
||||
|
||||
[ "${#current_files[@]}" -eq 0 ] \
|
||||
&& fail "No suitable files found in directory $input"
|
||||
|
||||
files+=("${current_files[@]}")
|
||||
else
|
||||
case "$input" in
|
||||
*.cpp | *.h | *.inl )
|
||||
files+=("$input")
|
||||
;;
|
||||
* )
|
||||
error "Refusing to format file '$input': `
|
||||
`only .cpp, .h and .inl supported"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
|
||||
[ "${#files[@]}" -eq 0 ] && fail "No files to format"
|
||||
|
||||
command "$CLANG_FORMAT" -style="$style" -i --verbose "${files[@]}"
|
||||
;;
|
||||
esac
|
@@ -1,56 +0,0 @@
|
||||
# Global variables. Yikes. FIXME
|
||||
set(tools ${PROJECT_SOURCE_DIR}/tools)
|
||||
set(generated ${PROJECT_BINARY_DIR}/generated)
|
||||
set(assets_to_embed "")
|
||||
set(assets_to_embed_args "")
|
||||
|
||||
file(MAKE_DIRECTORY ${generated})
|
||||
|
||||
find_package(Vulkan COMPONENTS glslc REQUIRED)
|
||||
find_program(glslc_executable NAMES glslc HINTS Vulkan::glslc)
|
||||
set(shaders ${generated}/shaders)
|
||||
file(MAKE_DIRECTORY ${shaders})
|
||||
|
||||
# Shedules compilation of shaders
|
||||
# Adapted from https://stackoverflow.com/a/60472877/4463352
|
||||
macro(compile_shader)
|
||||
foreach(source ${ARGV})
|
||||
get_filename_component(source_basename ${source} NAME)
|
||||
set(tmp "${shaders}/${source_basename}.spv")
|
||||
add_custom_command(
|
||||
OUTPUT ${tmp}
|
||||
DEPENDS ${source}
|
||||
COMMAND ${glslc_executable}
|
||||
-o ${tmp}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${source}
|
||||
COMMENT "Compiling shader ${source}"
|
||||
)
|
||||
list(APPEND assets_to_embed_args "${tmp};as;${source_basename}.spv")
|
||||
list(APPEND assets_to_embed "${tmp}")
|
||||
unset(tmp)
|
||||
unset(source_basename)
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
compile_shader(
|
||||
desktop/graphics/shaders/shader.frag
|
||||
desktop/graphics/shaders/shader.vert
|
||||
)
|
||||
|
||||
# Generate embed files
|
||||
add_custom_command(
|
||||
OUTPUT ${generated}/embedded_resources.cpp
|
||||
${generated}/embedded_resources.h
|
||||
|
||||
COMMAND ${tools}/embed/embed.py
|
||||
--cpp ${generated}/embedded_resources.cpp
|
||||
--header ${generated}/embedded_resources.h
|
||||
--
|
||||
${assets_to_embed_args}
|
||||
|
||||
DEPENDS "${assets_to_embed}"
|
||||
${tools}/embed/embed.py
|
||||
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
COMMENT "Embedding assets"
|
||||
)
|
@@ -1,28 +0,0 @@
|
||||
# CppCheck command line arguments
|
||||
# Each line is treated as one argument, unless it is empty or it starts with #.
|
||||
#
|
||||
# Available variables:
|
||||
# ${CMAKE_SOURCE_DIR} project root
|
||||
# ${CMAKE_BINARY_DIR} CMake build directory
|
||||
|
||||
--enable=warning,style,information
|
||||
#--enable=unusedFunction # Unused functions are often OK since they are intended
|
||||
# # to be used later
|
||||
#--enable=missingInclude # Very prone to false positives; system-dependent
|
||||
--inconclusive
|
||||
|
||||
# SUPPRESSIONS
|
||||
# Warnings that are suppressed on a case-by-case basis should be suppressed
|
||||
# using inline suppressions.
|
||||
# Warnings that were decided to be generally inapplicable should be suppressed
|
||||
# using suppressions.txt.
|
||||
# Warnings that result from the way cppcheck is invoked should be suppressed
|
||||
# using this file.
|
||||
|
||||
--inline-suppr
|
||||
--suppressions-list=${CMAKE_SOURCE_DIR}/tools/cppcheck/suppressions.txt
|
||||
|
||||
# N.B.: this path is also mentioned in use scripts
|
||||
--cppcheck-build-dir=${CMAKE_BINARY_DIR}/cppcheck
|
||||
|
||||
--error-exitcode=2
|
@@ -1,18 +0,0 @@
|
||||
# CppCheck global suppressions
|
||||
# Do not use this file for suppressions that could easily be declared inline.
|
||||
|
||||
# Allow the use of implicit constructors.
|
||||
noExplicitConstructor:*
|
||||
|
||||
# In most cases using STL algorithm functions causes unnecessary code bloat.
|
||||
useStlAlgorithm:*
|
||||
|
||||
# cppcheck trips on #include <embedded_resources.h> and there's no way to
|
||||
# suppress that exlusively
|
||||
missingInclude:*
|
||||
|
||||
# Shut up. Just shut up.
|
||||
unmatchedSuppression:*
|
||||
|
||||
# Do not check third-party libraries
|
||||
*:*lib*
|
@@ -1,65 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
usage=\
|
||||
"Usage: use-cppcheck.sh
|
||||
Run cppcheck with correct options.
|
||||
|
||||
Environment variables:
|
||||
PARALLELISM threads to use, default is 1
|
||||
|
||||
CPPCHECK cppcheck executable
|
||||
CMAKE cmake executable"
|
||||
|
||||
rsrc="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
|
||||
source "$rsrc/../bashlib.sh"
|
||||
|
||||
find_cmd CPPCHECK cppcheck
|
||||
find_cmd CMAKE cmake
|
||||
|
||||
case "$1" in
|
||||
-h | --help )
|
||||
echo "$usage"
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
|
||||
# Generate compile database for CppCheck
|
||||
command "$CMAKE" \
|
||||
-B "$build_dir" \
|
||||
-S "$source_dir" \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
|
||||
compile_database="$build_dir/compile_commands.json"
|
||||
|
||||
mkdir -p "$build_dir/cppcheck"
|
||||
|
||||
options=()
|
||||
|
||||
while IFS='' read -r line; do
|
||||
[ -z "$line" ] && continue
|
||||
[ "${line:0:1}" = '#' ] && continue
|
||||
|
||||
option="$(
|
||||
CMAKE_SOURCE_DIR="$source_dir" \
|
||||
CMAKE_BINARY_DIR="$build_dir" \
|
||||
envsubst <<<"$line"
|
||||
)"
|
||||
|
||||
options+=("$option")
|
||||
done < "$tools_dir/cppcheck/options.txt"
|
||||
|
||||
[ -n "${PARALLELISM+x}" ] && options+=(-j "$PARALLELISM")
|
||||
|
||||
errors="`
|
||||
echo_and_run "$CPPCHECK" \
|
||||
--project="$compile_database" \
|
||||
-D__CPPCHECK__ \
|
||||
"${options[@]}" \
|
||||
2>&1 >/dev/fd/0 # Store stderr into variable, pass stdout to our stdout
|
||||
`"
|
||||
|
||||
exit_code="$?"
|
||||
if [ "$exit_code" -eq 2 ]; then
|
||||
less - <<<"$errors"
|
||||
exit "$exit_code"
|
||||
fi
|
57
tools/dev-mode.cmake
Normal file
57
tools/dev-mode.cmake
Normal file
@@ -0,0 +1,57 @@
|
||||
if (DEV_MODE)
|
||||
find_program(clang_tidy_EXECUTABLE NAMES clang-tidy-13 clang-tidy REQUIRED)
|
||||
find_package(Python3 COMPONENTS Interpreter REQUIRED)
|
||||
|
||||
# Setup clang-tidy
|
||||
list(APPEND clang_tidy_command "${clang_tidy_EXECUTABLE}"
|
||||
"--warnings-as-errors=*"
|
||||
"--use-color")
|
||||
|
||||
set_target_properties(progressia
|
||||
PROPERTIES CXX_CLANG_TIDY "${clang_tidy_command}")
|
||||
|
||||
# Display the marker for pre-commit.py at build time
|
||||
add_custom_target(clang_tidy_marker ALL
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"Clang-tidy is enabled. This is a marker for pre-commit.py")
|
||||
|
||||
# Notify pre-commit.py about CMake settings
|
||||
execute_process(COMMAND ${Python3_EXECUTABLE} ${tools}/pre-commit.py
|
||||
set-build-info -- "${CMAKE_COMMAND}" "${CMAKE_BINARY_DIR}"
|
||||
RESULT_VARIABLE set_build_info_RESULT)
|
||||
|
||||
if(${set_build_info_RESULT})
|
||||
message(FATAL_ERROR "pre-commit.py set-build-info failed")
|
||||
endif()
|
||||
|
||||
# Setup pre-commit git hook
|
||||
if (IS_DIRECTORY "${CMAKE_SOURCE_DIR}/.git/hooks")
|
||||
set(pre_commit_hook "${CMAKE_SOURCE_DIR}/.git/hooks/pre-commit")
|
||||
if (NOT EXISTS "${pre_commit_hook}")
|
||||
file(WRITE "${pre_commit_hook}"
|
||||
"#!/bin/sh\n"
|
||||
"# Progressia autogenerated pre-commit hook\n"
|
||||
"# You may modify this hook freely "
|
||||
"(just make sure the checks run)\n"
|
||||
"/bin/env python3 ${CMAKE_SOURCE_DIR}/tools/pre-commit.py run")
|
||||
|
||||
if (${CMAKE_VERSION} VERSION_LESS "3.19.0")
|
||||
if (${CMAKE_HOST_UNIX})
|
||||
execute_process(COMMAND chmod "755" "${pre_commit_hook}"
|
||||
RESULT_VARIABLE chmod_RESULT)
|
||||
if (${chmod_RESULT})
|
||||
message(FATAL_ERROR "Could not make git pre-commit hook executable")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
file(CHMOD "${pre_commit_hook}"
|
||||
PERMISSIONS
|
||||
OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||
GROUP_READ GROUP_EXECUTE
|
||||
WORLD_READ WORLD_EXECUTE)
|
||||
endif()
|
||||
endif()
|
||||
unset(pre_commit_hook)
|
||||
endif()
|
||||
|
||||
endif()
|
89
tools/embed/embed.cmake
Normal file
89
tools/embed/embed.cmake
Normal file
@@ -0,0 +1,89 @@
|
||||
# embed.cmake
|
||||
# Generates embedded_resources.h and embedded_resources.cpp
|
||||
|
||||
find_package(Python3 COMPONENTS Interpreter REQUIRED)
|
||||
|
||||
macro (get_target_property_or var target prop default)
|
||||
get_property(__is_set TARGET ${target} PROPERTY ${prop} SET)
|
||||
if (__is_set)
|
||||
get_property(${var} TARGET ${target} PROPERTY ${prop})
|
||||
else()
|
||||
set(${var} "${default}")
|
||||
endif()
|
||||
unset(__is_set)
|
||||
endmacro()
|
||||
|
||||
function (target_embeds)
|
||||
set(expecting_name FALSE)
|
||||
set(target "")
|
||||
set(current_asset "")
|
||||
|
||||
foreach (word ${ARGV})
|
||||
|
||||
# First argument is target name
|
||||
if (target STREQUAL "")
|
||||
set(target "${word}")
|
||||
get_target_property_or(script_args "${target}" EMBED_ARGS "")
|
||||
get_target_property_or(embeds "${target}" EMBEDS "")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
if (current_asset STREQUAL "")
|
||||
# Beginning of asset declaration (1/2)
|
||||
set(current_asset "${word}")
|
||||
|
||||
elseif (expecting_name)
|
||||
# End of "asset AS asset_name"
|
||||
list(APPEND script_args "${current_asset};as;${word}")
|
||||
list(APPEND embeds ${current_asset})
|
||||
set(current_asset "")
|
||||
set(expecting_name FALSE)
|
||||
|
||||
elseif ("${word}" STREQUAL "AS")
|
||||
# Keyword AS in "asset AS asset_name"
|
||||
set(expecting_name TRUE)
|
||||
|
||||
else()
|
||||
# End of asset without AS, beginning of asset declaration (2/2)
|
||||
list(APPEND script_args "${current_asset};as;${current_asset}")
|
||||
list(APPEND embeds ${current_asset})
|
||||
set(current_asset "${word}")
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
|
||||
if (expecting_name)
|
||||
message(FATAL_ERROR "No name given for asset \"${current_asset}\"")
|
||||
endif()
|
||||
|
||||
if (NOT current_asset STREQUAL "")
|
||||
list(APPEND script_args "${current_asset};as;${current_asset}")
|
||||
endif()
|
||||
|
||||
set_target_properties("${target}" PROPERTIES EMBED_ARGS "${script_args}")
|
||||
set_target_properties("${target}" PROPERTIES EMBEDS "${embeds}")
|
||||
endfunction()
|
||||
|
||||
file(MAKE_DIRECTORY "${generated}/embedded_resources")
|
||||
|
||||
function(compile_embeds target)
|
||||
get_target_property(script_args "${target}" EMBED_ARGS)
|
||||
get_target_property(embeds "${target}" EMBEDS)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${generated}/embedded_resources/embedded_resources.cpp
|
||||
${generated}/embedded_resources/embedded_resources.h
|
||||
|
||||
COMMAND ${Python3_EXECUTABLE} ${tools}/embed/embed.py
|
||||
--cpp ${generated}/embedded_resources/embedded_resources.cpp
|
||||
--header ${generated}/embedded_resources/embedded_resources.h
|
||||
--
|
||||
${script_args}
|
||||
|
||||
DEPENDS ${embeds}
|
||||
${tools}/embed/embed.py
|
||||
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
COMMENT "Embedding assets"
|
||||
)
|
||||
endfunction()
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
usage = \
|
||||
'''Usage: embed.py --cpp OUT_CPP --header OUT_H [--] [INPUT as PATH]...
|
||||
'''Usage: %(me)s --cpp OUT_CPP --header OUT_H [--] [INPUT as PATH]...
|
||||
Generate C++ source code that includes binary contents of INPUT files.
|
||||
|
||||
Each file in INPUT is stored as a resource: a static array of unsigned char.
|
||||
@@ -79,6 +79,7 @@ def main():
|
||||
fail(f"Unknown option '{arg}'")
|
||||
|
||||
elif considerOptions and (arg == '-h' or arg == '--help'):
|
||||
print(usage % {'me': os.path.basename(sys.argv[0])})
|
||||
sys.exit(0)
|
||||
|
||||
elif considerOptions and arg == '--':
|
||||
@@ -237,8 +238,8 @@ namespace {
|
||||
|
||||
mid=\
|
||||
'''
|
||||
std::unordered_map<std::string,
|
||||
__embedded_resources::EmbeddedResource>
|
||||
const std::unordered_map<std::string,
|
||||
__embedded_resources::EmbeddedResource>
|
||||
EMBEDDED_RESOURCES =
|
||||
{
|
||||
''',
|
||||
|
@@ -1,51 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
me="$(realpath "${BASH_SOURCE[0]}")"
|
||||
if [ "$(basename "$me")" = 'pre-commit' ]; then
|
||||
# i write good shell scripts - Javapony 2022-10-07
|
||||
root_dir="$(realpath "$(dirname "$me")/../../")"
|
||||
|
||||
hook_source="$root_dir/tools/git/hook_pre_commit.sh"
|
||||
if [ "$hook_source" -nt "$me" ]; then
|
||||
if [ -n "${ALREADY_UPDATED+x}" ]; then
|
||||
echo >&2 "git pre-commit hook: Attempted recursive hook update. `
|
||||
`Something is very wrong."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ''
|
||||
echo "===== tools/git/hook_pre_commit.sh updated; `
|
||||
`replacing pre-commit hook ====="
|
||||
echo ''
|
||||
|
||||
cp "$hook_source" "$me" &&
|
||||
chmod +x "$me" \
|
||||
|| fail 'Update failed'
|
||||
|
||||
ALREADY_UPDATED=true "$me"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
source "$root_dir/tools/bashlib.sh"
|
||||
else
|
||||
rsrc="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
|
||||
source "$rsrc/../bashlib.sh"
|
||||
fi
|
||||
|
||||
unstaged_changes="`git diff --name-only`"
|
||||
if [ -n "$unstaged_changes" ]; then
|
||||
fail "Please stage all stash all unstaged changes in the following files:
|
||||
$unstaged_changes"
|
||||
fi
|
||||
|
||||
echo_and_run "$tools_dir/cppcheck/use-cppcheck.sh" \
|
||||
|| fail "Cppcheck has generated warnings, aborting commit"
|
||||
|
||||
echo_and_run "$tools_dir/clang-format/use-clang-format.sh" git \
|
||||
|| fail "clang-format has failed, aborting commit"
|
||||
|
||||
echo_and_run "$tools_dir/build.sh" --dont-generate \
|
||||
|| fail "Could not build project, aborting commit"
|
||||
|
||||
echo 'All checks passed'
|
||||
|
53
tools/glslc.cmake
Normal file
53
tools/glslc.cmake
Normal file
@@ -0,0 +1,53 @@
|
||||
# glslc.cmake
|
||||
# Compiles GLSL shaders to SPV files
|
||||
|
||||
find_package(Vulkan COMPONENTS glslc REQUIRED)
|
||||
find_program(glslc_EXECUTABLE NAMES glslc HINTS Vulkan::glslc REQUIRED)
|
||||
|
||||
macro (get_target_property_or var target prop default)
|
||||
get_property(__is_set TARGET ${target} PROPERTY ${prop} SET)
|
||||
if (__is_set)
|
||||
get_property(${var} TARGET ${target} PROPERTY ${prop})
|
||||
else()
|
||||
set(${var} "${default}")
|
||||
endif()
|
||||
unset(__is_set)
|
||||
endmacro()
|
||||
|
||||
function (target_glsl_shaders)
|
||||
set(target "")
|
||||
|
||||
foreach (word ${ARGV})
|
||||
# First argument is target name
|
||||
if (target STREQUAL "")
|
||||
set(target ${word})
|
||||
get_target_property_or(glsl_shaders ${target} GLSL_SHADERS "")
|
||||
else()
|
||||
list(APPEND glsl_shaders ${word})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set_target_properties(${target} PROPERTIES GLSL_SHADERS "${glsl_shaders}")
|
||||
endfunction()
|
||||
|
||||
file(MAKE_DIRECTORY "${generated}/compiled_glsl_shaders")
|
||||
|
||||
function(compile_glsl target)
|
||||
get_target_property(glsl_shaders ${target} GLSL_SHADERS)
|
||||
|
||||
foreach (source_path ${glsl_shaders})
|
||||
get_filename_component(source_basename ${source_path} NAME)
|
||||
set(spv_path
|
||||
"${generated}/compiled_glsl_shaders/${source_basename}.spv")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${spv_path}
|
||||
DEPENDS ${source_path}
|
||||
COMMAND ${glslc_EXECUTABLE}
|
||||
-o ${spv_path}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${source_path}
|
||||
COMMENT "Compiling shader ${source_path}"
|
||||
)
|
||||
target_embeds(${target} ${spv_path} AS "${source_basename}.spv")
|
||||
endforeach()
|
||||
endfunction()
|
416
tools/pre-commit.py
Executable file
416
tools/pre-commit.py
Executable file
@@ -0,0 +1,416 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
usage = \
|
||||
'''Usage: %(me)s run [OPTIONS...]
|
||||
or: %(me)s restore [OPTIONS...]
|
||||
or: %(me)s set-build-info CMAKE_EXECUTABLE CMAKE_BINARY_DIR
|
||||
In the 1st form, run standard pre-commit procedure for Progressia.
|
||||
In the 2nd form, attempt to restore workspace if the pre-commit hook failed.
|
||||
In the 3rd form, update cached build settings.
|
||||
|
||||
--dry-run do not change anything in git or in the filesystem;
|
||||
implies --verbose
|
||||
--verbose print commands and diagnostics
|
||||
--help display this help and exit
|
||||
--version display version information and exit
|
||||
|
||||
Currently, the pre-commit procedure performs the following:
|
||||
1. format staged changes
|
||||
2. attempt to compile with staged changes only
|
||||
|
||||
pre-commit-settings.json values:
|
||||
build-root CMake binary dir to use (filled in by CMake)
|
||||
parallelism threads to use, default is 1
|
||||
git git command, default is null
|
||||
cmake cmake command, default is null (filled in by CMake)
|
||||
clang-format-diff clang-format-diff command, default is null
|
||||
|
||||
Use semicolons to separate arguments in git, cmake and clang-format-diff'''
|
||||
|
||||
# Script version. Increment when script logic changes significantly.
|
||||
# Commit change separately.
|
||||
version = 1
|
||||
|
||||
# Source directories to format
|
||||
src_dirs = ['desktop', 'main']
|
||||
|
||||
# File extensions to format
|
||||
exts = ['cpp', 'h', 'inl']
|
||||
|
||||
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import shutil
|
||||
import json
|
||||
|
||||
|
||||
STASH_NAME = 'progressia_pre_commit_stash'
|
||||
# Paths are relative to this script's directory, tools/
|
||||
SETTINGS_PATH = 'pre-commit-settings.json'
|
||||
CLANG_TIDY_CHECK_MARKER = 'Clang-tidy is enabled. ' \
|
||||
'This is a marker for pre-commit.py'
|
||||
|
||||
|
||||
def fail(*args, code=1):
|
||||
"""Print an error message and exit with given code (default 1)"""
|
||||
print(my_name + ':', *args, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def verbose(*args):
|
||||
"""Print a message in verbose mode only."""
|
||||
if verbose_mode:
|
||||
print(my_name + ':', *args)
|
||||
|
||||
|
||||
def long_print_iter(title, it):
|
||||
"""Print contents of iterable titled as specified. If iterable is empty,
|
||||
print the string (nothing) instead.
|
||||
"""
|
||||
print(title + ':')
|
||||
|
||||
if len(it) > 0:
|
||||
print('\t' + '\n\t'.join(it) + '\n')
|
||||
else:
|
||||
print('\t(nothing)\n')
|
||||
|
||||
|
||||
def invoke(*cmd, result_when_dry=None, quiet=True, text=True, stdin=None):
|
||||
"""Execute given system command and return its stdout. If command fails,
|
||||
throw CalledProcessError.
|
||||
|
||||
When in verbose mode, log command before execution. If in dry-run mode and
|
||||
result_when_dry is not None, skip execution and return result_when_dry
|
||||
instead.
|
||||
|
||||
Keyword arguments:
|
||||
result_when_dry -- unless None (default), skip execution and return this
|
||||
quiet -- if False, print stdout (default True)
|
||||
text -- treat stdin and stdout as text rather than bytes (default False)
|
||||
stdin -- unless None (default), send this to stdin of spawned process
|
||||
"""
|
||||
verbose('command', *(repr(c) for c in cmd))
|
||||
|
||||
if dry_run and result_when_dry is not None:
|
||||
print(my_name + ': skipped: --dry-run')
|
||||
return result_when_dry
|
||||
|
||||
popen = subprocess.Popen(cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
text=text,
|
||||
universal_newlines=text,
|
||||
stdin=subprocess.PIPE if stdin else subprocess.DEVNULL)
|
||||
|
||||
stdout, _ = popen.communicate(input=stdin)
|
||||
|
||||
if text and not quiet:
|
||||
print(stdout, end='')
|
||||
|
||||
return_code = popen.wait()
|
||||
if return_code != 0:
|
||||
raise subprocess.CalledProcessError(return_code, cmd)
|
||||
|
||||
return stdout
|
||||
|
||||
|
||||
def get_file_sets():
|
||||
"""Return sets of indexed and unindexed files according to Git"""
|
||||
def git_z(*cmd):
|
||||
raw = invoke(*git, *cmd, '-z', text=False)
|
||||
return set(f.decode() for f in raw.split(b'\x00') if len(f) != 0)
|
||||
|
||||
indexed = git_z('diff', '--name-only', '--cached')
|
||||
unindexed = git_z('diff', '--name-only') | \
|
||||
git_z('ls-files', '--other', '--exclude-standard')
|
||||
|
||||
return indexed, unindexed
|
||||
|
||||
|
||||
def run_safety_checks(indexed, unindexed):
|
||||
if invoke(*git, 'stash', 'list', '--grep', f"\\b{STASH_NAME}$") != '':
|
||||
fail(f"Cannot run pre-commit checks: stash {STASH_NAME} exists. "
|
||||
f"Use `{my_name} restore` to restore workspace and repository "
|
||||
f"state")
|
||||
|
||||
both_changes = indexed & unindexed
|
||||
|
||||
if len(both_changes) != 0:
|
||||
fail(f"Cannot run pre-commit checks: files with indexed and unindexed "
|
||||
'changes exist:\n\n\t' +
|
||||
'\n\t'.join(both_changes) +
|
||||
'\n')
|
||||
|
||||
|
||||
def do_restore():
|
||||
"""Restore repository and filesystem. Fail if stash not found."""
|
||||
print('Redoing rolled back changes')
|
||||
|
||||
git_list = invoke(*git, 'stash', 'list', '--grep', f"\\b{STASH_NAME}$")
|
||||
|
||||
if len(git_list) == 0:
|
||||
if dry_run:
|
||||
stash_name = 'stash@{0}'
|
||||
else:
|
||||
fail(f"Cannot restore repository: stash {STASH_NAME} not found")
|
||||
else:
|
||||
stash_name, _, _ = git_list.partition(':')
|
||||
|
||||
invoke(*git, 'stash', 'pop', '--index', '--quiet', stash_name,
|
||||
result_when_dry='', quiet=False)
|
||||
|
||||
|
||||
def format_project():
|
||||
"""Format staged files with clang-format-diff."""
|
||||
diff = invoke(*git, 'diff', '-U0', '--no-color', '--relative', 'HEAD',
|
||||
*(f"{d}/*.{e}" for d in src_dirs for e in exts))
|
||||
|
||||
invoke(*clang_format_diff, '-p1', '-i', '--verbose',
|
||||
stdin=diff, result_when_dry='', quiet=False)
|
||||
|
||||
|
||||
def unformat_project(indexed_existing):
|
||||
"""Undo formatting changes introduced by format_project()."""
|
||||
print('Undoing formatting changes')
|
||||
|
||||
if len(indexed_existing) == 0:
|
||||
print('Nothing to do: all indexed changes are deletions')
|
||||
return
|
||||
|
||||
invoke(*git, 'restore', '--', *indexed_existing)
|
||||
|
||||
|
||||
def build_project():
|
||||
"""Build project with cmake."""
|
||||
print('Building project')
|
||||
build_log = invoke(*cmake,
|
||||
'--build', build_root,
|
||||
'--parallel', str(parallelism),
|
||||
result_when_dry=CLANG_TIDY_CHECK_MARKER,
|
||||
quiet=False)
|
||||
|
||||
if CLANG_TIDY_CHECK_MARKER not in build_log.splitlines():
|
||||
fail('Project build was successful, but clang-tidy did not run. '
|
||||
'Please make sure DEV_MODE is ON and regenerate CMake cache.')
|
||||
|
||||
print('Success')
|
||||
|
||||
|
||||
def pre_commit():
|
||||
"""Run pre-commit checks."""
|
||||
|
||||
if build_root is None:
|
||||
fail(f"build-root is not set in {SETTINGS_PATH}. Compile project "
|
||||
'manually to set this variable properly.')
|
||||
if not os.path.exists(build_root):
|
||||
fail(f"build-root {build_root} does not exist. Compile project "
|
||||
'manually to set this variable properly.')
|
||||
|
||||
cmakeCache = os.path.join(build_root, 'CMakeCache.txt')
|
||||
if not os.path.exists(cmakeCache):
|
||||
fail(f"{cmakeCache} does not exist. build-root is likely invalid. "
|
||||
'Compile project manually to set this variable properly.')
|
||||
|
||||
indexed, unindexed = get_file_sets()
|
||||
indexed_existing = [f for f in indexed if os.path.exists(f)]
|
||||
if verbose_mode:
|
||||
long_print_iter('Indexed changes', indexed)
|
||||
long_print_iter('Unindexed changes', unindexed)
|
||||
long_print_iter('Indexed changes without deletions', indexed_existing)
|
||||
|
||||
if len(indexed) == 0:
|
||||
fail('No indexed changes. You probably forgot to run `git add .`')
|
||||
|
||||
run_safety_checks(indexed, unindexed)
|
||||
|
||||
undo_formatting = False
|
||||
restore = False
|
||||
try:
|
||||
if len(unindexed) != 0:
|
||||
long_print_iter('Unindexed changes found in files', unindexed)
|
||||
print('These changes will be rolled back temporarily')
|
||||
|
||||
invoke(*git, 'stash', 'push',
|
||||
'--keep-index',
|
||||
'--include-untracked',
|
||||
'--message', STASH_NAME,
|
||||
result_when_dry='', quiet=False)
|
||||
restore = True
|
||||
|
||||
format_project()
|
||||
undo_formatting = True
|
||||
build_project()
|
||||
undo_formatting = False
|
||||
|
||||
finally:
|
||||
if undo_formatting:
|
||||
unformat_project(indexed_existing)
|
||||
if restore:
|
||||
do_restore()
|
||||
|
||||
print('Staging formatting changes')
|
||||
|
||||
if len(indexed_existing) == 0:
|
||||
print('Nothing to do: all indexed changes are deletions')
|
||||
else:
|
||||
invoke(*git, 'add', '--', *indexed_existing,
|
||||
result_when_dry='', quiet=False)
|
||||
|
||||
|
||||
def get_settings_path():
|
||||
return os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
SETTINGS_PATH))
|
||||
|
||||
|
||||
def save_settings():
|
||||
"""Save tools/pre-commit-settings.json."""
|
||||
path = get_settings_path()
|
||||
verbose(f"Saving settings into {path}")
|
||||
if not dry_run:
|
||||
with open(path, mode='w') as f:
|
||||
json.dump(settings, f, indent=4)
|
||||
else:
|
||||
verbose(' skipped: --dry-run')
|
||||
|
||||
|
||||
def set_build_info():
|
||||
"""Set build info in tools/pre-commit-settings.json."""
|
||||
settings['build_root'] = arg_build_root
|
||||
settings['cmake'] = arg_cmake_executable
|
||||
save_settings()
|
||||
|
||||
|
||||
def parse_args():
|
||||
"""Parse sys.argv and environment variables; set corresponding globals.
|
||||
Return (action, arguments for set-build-root).
|
||||
"""
|
||||
global action
|
||||
global verbose_mode
|
||||
global dry_run
|
||||
global allow_update
|
||||
|
||||
consider_options = True
|
||||
action = None
|
||||
arg_cmake_executable = None
|
||||
arg_build_root = None
|
||||
|
||||
for arg in sys.argv[1:]:
|
||||
if arg == 'restore' or arg == 'set-build-info' or arg == 'run':
|
||||
if action is not None:
|
||||
fail(f"Cannot use '{arg}' and '{action}' together")
|
||||
action = arg
|
||||
elif consider_options and arg.startswith('-'):
|
||||
if arg == '-h' or arg == '--help' or arg == 'help' or arg == '/?':
|
||||
print(usage % {'me': my_name})
|
||||
sys.exit(0)
|
||||
elif arg == '--version':
|
||||
print(f"Progressia pre-commit script, version {version}")
|
||||
sys.exit(0)
|
||||
elif arg == '--verbose':
|
||||
verbose_mode = True
|
||||
elif arg == '--dry-run':
|
||||
dry_run = True
|
||||
verbose_mode = True
|
||||
elif arg == '--':
|
||||
consider_options = False
|
||||
else:
|
||||
fail(f"Unknown option '{arg}'")
|
||||
elif action == 'set-build-info' and arg_cmake_executable is None:
|
||||
arg_cmake_executable = arg
|
||||
elif action == 'set-build-info' and arg_build_root is None:
|
||||
arg_build_root = arg
|
||||
else:
|
||||
fail(f"Unknown or unexpected argument '{arg}'")
|
||||
|
||||
if action is None:
|
||||
fail('No action specified')
|
||||
|
||||
if action == 'set-build-info' and arg_cmake_executable is None:
|
||||
fail('No CMake executable given')
|
||||
|
||||
if action == 'set-build-info' and arg_build_root is None:
|
||||
fail('No build root given')
|
||||
|
||||
return action, arg_build_root, arg_cmake_executable
|
||||
|
||||
|
||||
def load_settings():
|
||||
"""Ensure pre-commit-settings.json exists and is loaded into memory."""
|
||||
global settings
|
||||
|
||||
path = get_settings_path()
|
||||
if os.path.exists(path):
|
||||
with open(path, mode='r') as f:
|
||||
settings = json.load(f)
|
||||
else:
|
||||
verbose(f"{path} not found, using defaults")
|
||||
settings = {
|
||||
"__comment": "See `pre-commit.py --help` for documentation",
|
||||
"build_root": None,
|
||||
"git": None,
|
||||
"cmake": None,
|
||||
"clang_format_diff": None,
|
||||
"parallelism": 1
|
||||
}
|
||||
save_settings()
|
||||
|
||||
def parse_settings():
|
||||
"""Load values from settings and check their validity."""
|
||||
global settings
|
||||
global build_root
|
||||
global git
|
||||
global cmake
|
||||
global clang_format_diff
|
||||
global parallelism
|
||||
|
||||
build_root = settings['build_root']
|
||||
parallelism = settings['parallelism']
|
||||
|
||||
def find_command(hints, settings_name):
|
||||
if settings[settings_name] is not None:
|
||||
hints = [settings[settings_name]]
|
||||
|
||||
cmds = (hint.split(';') for hint in hints)
|
||||
res = next((cmd for cmd in cmds if shutil.which(cmd[0])), None) \
|
||||
or fail(f"Command {hints[0]} not found. Set {settings_name} " +
|
||||
f"in {path} or check PATH")
|
||||
|
||||
verbose(f"Found command {hints[0]}:", *(repr(c) for c in res))
|
||||
return res
|
||||
|
||||
git = find_command(['git'], 'git')
|
||||
cmake = find_command(['cmake'], 'cmake')
|
||||
clang_format_diff = find_command(['clang-format-diff-13',
|
||||
'clang-format-diff',
|
||||
'clang-format-diff.py'],
|
||||
'clang_format_diff')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
my_name = os.path.basename(sys.argv[0])
|
||||
verbose_mode = False
|
||||
dry_run = False
|
||||
allow_update = True
|
||||
|
||||
action, arg_build_root, arg_cmake_executable = parse_args()
|
||||
load_settings()
|
||||
|
||||
if dry_run:
|
||||
print('Running in dry mode: no changes to filesystem or git will '
|
||||
'actually be performed')
|
||||
|
||||
try:
|
||||
if action == 'set-build-info':
|
||||
set_build_info()
|
||||
elif action == 'restore':
|
||||
parse_settings()
|
||||
do_restore()
|
||||
indexed, unindexed = get_file_sets()
|
||||
if indexed & unindexed:
|
||||
unformat_project(indexed)
|
||||
else:
|
||||
parse_settings()
|
||||
pre_commit()
|
||||
except subprocess.CalledProcessError as e:
|
||||
fail('Command', *(repr(c) for c in e.cmd),
|
||||
f"exited with code {e.returncode}")
|
146
tools/setup.sh
146
tools/setup.sh
@@ -1,146 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
usage=\
|
||||
"Usage: setup.sh [--for-development]
|
||||
Set up the development environment after \`git clone\`
|
||||
|
||||
Options:
|
||||
--for-development perform additional setup only necessary for developers
|
||||
|
||||
-h, --help display this help and exit"
|
||||
|
||||
rsrc="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
|
||||
source "$rsrc/bashlib.sh" || {
|
||||
echo >&2 'Could not load bashlib'
|
||||
exit 1
|
||||
}
|
||||
cd "$root_dir"
|
||||
|
||||
|
||||
|
||||
# Parse arguments
|
||||
|
||||
for_development=''
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
-h | --help )
|
||||
echo "$usage"
|
||||
exit
|
||||
;;
|
||||
--for-development )
|
||||
for_development=true
|
||||
;;
|
||||
* )
|
||||
fail "Unknown option '$arg'"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
|
||||
# Сreate private.sh
|
||||
|
||||
if [ ! -e "$private_sh" ]; then
|
||||
echo '#!/bin/bash
|
||||
|
||||
# This file is ignored by git. Use it to configure shell scripts in tools/
|
||||
# for your development environment.
|
||||
|
||||
PARALLELISM=1
|
||||
#PATH="$PATH:/opt/whatever"
|
||||
' >"$private_sh" &&
|
||||
chmod +x "$private_sh" ||
|
||||
fail "tools/private.sh was not found; could not create it"
|
||||
|
||||
echo "Created tools/private.sh"
|
||||
else
|
||||
echo "Found and loaded private.sh"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Check available commands
|
||||
|
||||
failed=()
|
||||
|
||||
function check_cmd() {
|
||||
if FAIL_SILENTLY=true find_cmd found "$@"; then
|
||||
echo "Found command $found"
|
||||
else
|
||||
failed+=("command $1")
|
||||
echo "Could not find command $1"
|
||||
fi
|
||||
unset found
|
||||
}
|
||||
|
||||
check_cmd cmake
|
||||
check_cmd python3
|
||||
check_cmd glslc
|
||||
|
||||
if [ $for_development ]; then
|
||||
check_cmd git
|
||||
check_cmd cppcheck
|
||||
check_cmd clang-format-13 clang-format
|
||||
check_cmd clang-format-diff-13 clang-format-diff clang-format-diff.py
|
||||
check_cmd valgrind
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Try generating build files
|
||||
|
||||
if FAIL_SILENTLY=true find_cmd CMAKE cmake; then
|
||||
if CMAKE="$CMAKE" "$tools_dir/build.sh" --dont-build; then
|
||||
echo 'CMake did not encounter any problems'
|
||||
else
|
||||
echo 'Could not generate build files; libraries are probably missing'
|
||||
failed+=('some libraries, probably (see CMake messages for details)')
|
||||
fi
|
||||
else
|
||||
echo 'Skipping CMake test because cmake was not found'
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Display accumulated errors
|
||||
|
||||
[ ${#failed[@]} -ne 0 ] &&
|
||||
fail "Could not find the following required commands or libraries:
|
||||
|
||||
`for f in "${failed[@]}"; do echo " $f"; done`
|
||||
|
||||
You can resolve these errors in the following ways:
|
||||
1. Install required software packages. See README for specific instructions.
|
||||
2. Edit PATH or CMAKE_MODULE_PATH environment variables in tools/private.sh
|
||||
to include your installation directories.
|
||||
"
|
||||
|
||||
|
||||
|
||||
# Set executable flags
|
||||
|
||||
chmod -v +x tools/build.sh \
|
||||
tools/embed/embed.py \
|
||||
|| fail 'Could not make scripts executable'
|
||||
|
||||
if [ $for_development ]; then
|
||||
chmod -v +x tools/clang-format/use-clang-format.sh \
|
||||
tools/cppcheck/use-cppcheck.sh \
|
||||
|| fail 'Could not make developer scripts executable'
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Set git hook
|
||||
|
||||
if [ $for_development ]; then
|
||||
mkdir -vp .git/hooks &&
|
||||
cp -v tools/git/hook_pre_commit.sh .git/hooks/pre-commit &&
|
||||
chmod -v +x .git/hooks/pre-commit \
|
||||
|| fail 'Could not setup git pre-commit hook'
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo 'Setup complete'
|
Reference in New Issue
Block a user