diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 5865d8b2..66c07ea1 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -16,7 +16,7 @@ jobs: # Don't fail on empty include (not tracked by git) - run: if ! [ -d include ]; then mkdir include; fi - run: sudo apt update && sudo apt install -y libglfw3-dev libglm-dev libgl-dev libtinyxml2-dev - - run: make + - run: make -j$(nproc) format: runs-on: ubuntu-latest steps: @@ -45,4 +45,4 @@ jobs: # Don't fail on empty include (not tracked by git) - run: if ! [ -d include ]; then mkdir include; fi - - run: cppcheck src -I include -I /usr/include/tinyxml2 + - run: make cppcheck diff --git a/.github/workflows/latexchecks.yml b/.github/workflows/latexchecks.yml index 63d03f99..d310d978 100644 --- a/.github/workflows/latexchecks.yml +++ b/.github/workflows/latexchecks.yml @@ -5,6 +5,7 @@ on: - '.github/workflows/**' - 'scripts/formatlatex.sh' - 'reports/**' + - 'Makefile' jobs: build-reports: runs-on: ubuntu-latest diff --git a/.github/workflows/scriptchecks.yml b/.github/workflows/scriptchecks.yml index 4a593356..8bc38179 100644 --- a/.github/workflows/scriptchecks.yml +++ b/.github/workflows/scriptchecks.yml @@ -4,6 +4,7 @@ on: paths: - '.github/workflows/**' - 'scripts/**' + - 'Makefile' jobs: shellcheck: runs-on: ubuntu-latest diff --git a/DEVELOPERS.md b/DEVELOPERS.md index bf105366..bba844cf 100644 --- a/DEVELOPERS.md +++ b/DEVELOPERS.md @@ -8,9 +8,10 @@ Some programs, not listed in [README.md](README.md), are not required to build t *per se*, but are very useful for developing it: - [clang-format](https://clang.llvm.org) (code formatting); +- [cppcheck](https://cppcheck.sourceforge.io/) (code linting); - [TeX Live](https://www.tug.org/texlive/) (`pdflatex` in specific, for report generation); - [Valgrind](https://valgrind.org/) (profiling); -- [Kcachegrind](https://invent.kde.org/sdk/kcachegrind) (seeing profiling results); +- [Kcachegrind](https://invent.kde.org/sdk/kcachegrind) (seeing profiler results); - [ShellCheck](https://www.shellcheck.net/) (static analysis of scripts); - [act](https://nektosact.com) (running GitHub actions locally). @@ -24,7 +25,7 @@ $ DEBUG=1 make $ PROFILE=1 make ``` -Don't forget to run `make clean` between different build types. +Don't forget to run `make clean` after switching between different build types. ## Report compilation @@ -51,7 +52,7 @@ A `PROFILE` build is recommended. ### C++ formatting -The `format.sh` script will attempt to format the whole project to a temporary directory (using +The `format.sh` script will attempt to format the whole project in a temporary directory (using `clang-format`), and then compare the results with your original source files. You can choose whether or not you want to keep those changes (you may want to manually disable formatting for a snippet of code, for example). Keep in mind that there's a CI action that requires formatting to be @@ -65,10 +66,11 @@ As any other formatter configuration, there are many tunable parameters. For you set the column limit to 100, the tab size to 4, with tab expansion on, and let `clang-format` handle the rest. -### Naming +#### Naming Methods and variables should be named in `camelCase`. Type names (classes and enums) should be named -in `PascalCase`. +in `PascalCase`. The name of files containing a class must match the class's name, and directory +names should be in `snake_case`. ### LaTeX formatting @@ -82,11 +84,17 @@ Report formatting can be checked with the `formatlatex.sh` script. It isn't as c ## GitHub Actions -The CI pipeline is very simple: it checks if the code is correctly formatted, and it builds and -lints the project. `shellcheck` verification of scripts is also present. All of these can be run -locally, without any containerization. +The CI pipeline is very simple. C++ code is formatted, linted, and compiled; LaTeX code is formatted +and compiled; and shell scripts are checked with `shellcheck`. All of these can be run locally: -However, you may want to run the CI actions in a environment similar to the one in a GitHub runner, -for example, to use the same version of `clang-format`. Our actions are compatible with -[`act`](https://nektosact.com). However, you are sure to expect a longer running time, as -`clang-format`, not available on `act`'s default Ubuntu image, needs to be installed. + - C++ compilation: `make` + - C++ linting: `make cppcheck` + - C++ formatting: `./scripts/format.sh` + - LaTeX compilation: `make reports` + - LaTeX formatting: `./scripts/formatlatex.sh` + - Shell linting: `cd scripts && shellcheck **` + +However, you may want to run the CI actions in a environment similar to the one of a GitHub runner. +For that, you can use [`act`](https://nektosact.com). However, you are sure to expect a longer +running time, as some software is not available on `act`'s default Ubuntu image and needs to be +installed. diff --git a/Makefile b/Makefile index 6f66fe38..1844706b 100644 --- a/Makefile +++ b/Makefile @@ -129,3 +129,15 @@ install: $(BUILDDIR)/$(ENGINE_EXENAME) $(BUILDDIR)/$(GENERATOR_EXENAME) .PHONY: uninstall uninstall: rm $(PREFIX)/bin/cgmain $(PREFIX)/bin/$(ENGINE_EXENAME) $(PREFIX)/bin/$(GENERATOR_EXENAME) + +.PHONY: cppcheck +cppcheck: + $(eval CPPCHECK_EXHAUSTIVE_SUPPORT := \ + $(shell cppcheck --version | grep -qP '2\.(1[1-8]|1\d{2,}|[2-9]\d+)|[3-9]+\.'; echo $$?)) + cppcheck \ + --enable=all --suppress=missingIncludeSystem --suppress=unusedFunction \ + --library=opengl --library=posix --library=tinyxml2 \ + $$([ $(CPPCHECK_EXHAUSTIVE_SUPPORT) -eq 0 ] && echo "--check-level=exhaustive") \ + --error-exitcode=1 \ + -Iinclude \ + src diff --git a/README.md b/README.md index 5674913f..eae368a9 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,14 @@ $ git clone https://github.com/voidbert/CG.git First, you'll need to install the following dependencies: - [GNU Make](https://www.gnu.org/software/make/) (build-time); -- [GCC](https://www.gnu.org/software/gcc/) (build-time); -TODO - add glfw, glad, glm +- [GCC](https://www.gnu.org/software/gcc/) / [Clang](https://clang.llvm.org/) (build-time); +- [GLFW](https://www.glfw.org/) (build-time); +- [GLM](https://github.com/g-truc/glm) (build-time); +- [TinyXML 2](https://github.com/leethomason/tinyxml2) (build-time). + +Other libraries are already included in this repository: + + - [GLAD](https://glad.dav1d.de/). Then, to compile the project, run: diff --git a/include/engine/Axis.hpp b/include/engine/Axis.hpp index 41577605..d71c33f8 100644 --- a/include/engine/Axis.hpp +++ b/include/engine/Axis.hpp @@ -25,7 +25,7 @@ class Axis { glm::vec4 color; public: - Axis(const glm::vec3 &direction); + explicit Axis(const glm::vec3 &direction); Axis(const Axis &model) = delete; Axis(Axis &&) = delete; diff --git a/include/engine/Model.hpp b/include/engine/Model.hpp index a1379881..6a3f09b1 100644 --- a/include/engine/Model.hpp +++ b/include/engine/Model.hpp @@ -26,7 +26,7 @@ class Model { unsigned int vertexCount; public: - Model(const std::vector &vertices, const std::vector indices); + Model(const std::vector &vertices, const std::vector &indices); explicit Model(const utils::WavefrontOBJ &objectFile); Model(const Model &model) = delete; diff --git a/include/engine/Scene.hpp b/include/engine/Scene.hpp index f3327a10..0ccd7dd9 100644 --- a/include/engine/Scene.hpp +++ b/include/engine/Scene.hpp @@ -37,7 +37,7 @@ class Scene { std::vector> entities; public: - Scene(const std::string &file); + explicit Scene(const std::string &file); Scene(const Scene &scene) = delete; Scene(Scene &&scene) = delete; diff --git a/include/engine/SceneWindow.hpp b/include/engine/SceneWindow.hpp index 4d0057af..234ba7a5 100644 --- a/include/engine/SceneWindow.hpp +++ b/include/engine/SceneWindow.hpp @@ -29,11 +29,11 @@ class SceneWindow : public Window { Axis xAxis, yAxis, zAxis; public: - SceneWindow(const std::string &sceneFile); + explicit SceneWindow(const std::string &sceneFile); protected: - void onUpdate(float time, float timeElapsed); - void onRender(); - void onResize(int _width, int _height); + void onUpdate(float time, float timeElapsed) override; + void onRender() override; + void onResize(int _width, int _height) override; }; } diff --git a/include/utils/TriangleFace.hpp b/include/utils/TriangleFace.hpp index b33cba00..d16109f4 100644 --- a/include/utils/TriangleFace.hpp +++ b/include/utils/TriangleFace.hpp @@ -14,12 +14,13 @@ #pragma once +#include #include namespace utils { struct TriangleFace { - uint32_t positions[3]; + std::array positions; TriangleFace(uint32_t p1, uint32_t p2, uint32_t p3); }; diff --git a/include/utils/Vertex.hpp b/include/utils/Vertex.hpp index 2f23b8fd..1fae1b2f 100644 --- a/include/utils/Vertex.hpp +++ b/include/utils/Vertex.hpp @@ -21,7 +21,7 @@ namespace utils { struct Vertex { glm::vec4 position; - Vertex(const glm::vec4 &_position); + explicit Vertex(const glm::vec4 &_position); Vertex(float x, float y, float z); bool operator==(const Vertex &) const = default; diff --git a/include/utils/WavefrontOBJ.hpp b/include/utils/WavefrontOBJ.hpp index 73308b4a..bc0cf03b 100644 --- a/include/utils/WavefrontOBJ.hpp +++ b/include/utils/WavefrontOBJ.hpp @@ -29,7 +29,7 @@ class WavefrontOBJ { public: WavefrontOBJ(); - WavefrontOBJ(const std::string &filename); + explicit WavefrontOBJ(const std::string &filename); void writeToFile(const std::string &filename) const; std::pair, std::vector> getIndexedVertices() const; diff --git a/scripts/formatlatex.sh b/scripts/formatlatex.sh index ce29d87b..ed41686d 100755 --- a/scripts/formatlatex.sh +++ b/scripts/formatlatex.sh @@ -18,22 +18,17 @@ . "$(dirname "$0")/utils.sh" +grep_error_message() { + sed -r "s/^([^:]*):([^:]*):.*$/\2:\1: $1/g" +} + # shellcheck disable=SC2266 find reports -type f -name "*.tex" | while IFS="" read -r file; do - i=1 - while IFS="" read -r line; do - if printf "%s" "$line" | grep -Pq '\t'; then - printf "%s:%s: Use of tabs: \"%s\"\n" "$file" "$i" "$line" - fi - - if printf "%s" "$line" | grep -Pq '[\t ]$'; then - printf "%s:%s: Trailing whitespace: \"%s\"\n" "$file" "$i" "$line" - fi - - if [ "$(printf "%s" "$line" | wc -m)" -gt 100 ]; then - printf "%s:%s: Column limit of 100 surpassed: \"%s\"\n" "$file" "$i" "$line" - fi - - i=$((i + 1)) - done < "$file" -done | tee /dev/stderr | [ "$(wc -l)" = 0 ] + grep -PHn '.{101,}$' "$file" | grep_error_message "Column exceeds 100 characters" + grep -PHn '\t$' "$file" | grep_error_message "Use of tabs" + grep -PHn '\s+$' "$file" | grep_error_message "Trailing whitespace" +done | + sort -n | + sed -r "s/^([^:]*):([^:]*):(.*)$/\2:\1:\3/g" | + tee /dev/stderr | + test "$(wc -l)" = 0 diff --git a/src/engine/Model.cpp b/src/engine/Model.cpp index 45e891d5..e9b39f53 100644 --- a/src/engine/Model.cpp +++ b/src/engine/Model.cpp @@ -18,7 +18,7 @@ namespace engine { -Model::Model(const std::vector &vertices, const std::vector indices) { +Model::Model(const std::vector &vertices, const std::vector &indices) { glGenVertexArrays(1, &this->vao); glBindVertexArray(this->vao); diff --git a/src/utils/WavefrontOBJ.cpp b/src/utils/WavefrontOBJ.cpp index f7eace28..45041125 100644 --- a/src/utils/WavefrontOBJ.cpp +++ b/src/utils/WavefrontOBJ.cpp @@ -12,6 +12,7 @@ /// See the License for the specific language governing permissions and /// limitations under the License. +#include #include #include #include @@ -57,10 +58,12 @@ WavefrontOBJ::WavefrontOBJ(const std::string &filename) : positions(), faces() { } for (const TriangleFace &face : this->faces) { - for (const uint32_t &positionIndex : face.positions) { - if (positionIndex >= this->positions.size()) { - throw std::runtime_error("Invalid data in OBJ file: " + filename); - } + if (std::any_of(face.positions.cbegin(), + face.positions.cend(), + [this](const uint32_t &positionIndex) { + return positionIndex >= this->positions.size(); + })) { + throw std::runtime_error("Invalid data in OBJ file: " + filename); } } }