diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml new file mode 100644 index 0000000..da11b68 --- /dev/null +++ b/.github/workflows/ci_tests.yml @@ -0,0 +1,73 @@ +name: "CI tests" + +on: [ push, workflow_dispatch ] + +jobs: + build-mingw: + name: Application run on Windows Latest MinGW + runs-on: windows-latest + + steps: + - uses: actions/checkout@v4 + + - name: Create CMake cache + run: | + cmake -S . -B cmake-build-release -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" + + - name: Build main target + shell: bash + run: | + cmake --build cmake-build-release --target SandPile || echo Built with errors + + - name: Run program + working-directory: .\cmake-build-release + run: | + .\SandPile.exe --help + + build-matrix: + name: Application run on ${{ matrix.config.name }} + runs-on: ${{ matrix.config.os }} + strategy: + fail-fast: false + matrix: + config: + - { + name: "Windows Latest MSVC", artifact: "Windows-MSVC.tar.xz", + os: windows-latest, + build_type: "Release", cc: "cl", cxx: "cl", + environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat" + } + - { + name: "Ubuntu Latest GCC", artifact: "Linux.tar.xz", + os: ubuntu-latest, + build_type: "Release", cc: "gcc", cxx: "g++" + } + - { + name: "macOS Latest Clang", artifact: "macOS.tar.xz", + os: macos-latest, + build_type: "Release", cc: "clang", cxx: "clang++" + } + + steps: + - uses: actions/checkout@v4 + + - name: Create CMake cache + shell: bash + run: | + cmake -S . -B cmake-build-release -DCMAKE_BUILD_TYPE=Release + + - name: Build main target + shell: bash + run: | + cmake --build cmake-build-release --target SandPile || echo "Built with errors" + + - name: Run program + shell: bash + working-directory: ./cmake-build-release + run: | + if [ "$RUNNER_OS" == "Windows" ]; then + cd Debug + ./SandPile.exe --help + else + ./SandPile --help + fi diff --git a/CMakeLists.txt b/CMakeLists.txt index b656e99..9193570 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,34 +1,35 @@ cmake_minimum_required(VERSION 3.12) project( - SandPile - VERSION 0.1.0 - DESCRIPTION "C++ Year 2023 Labwork3 - SandPile by bialger" - LANGUAGES C CXX + SandPile + VERSION 1.0 + DESCRIPTION "C++ Year 2023 Labwork3 - SandPile by bialger" + LANGUAGES C CXX ) - -set(CMAKE_CXX_COMPILER_VERSION 20) -add_compile_options( - -Werror +set(CMAKE_CXX_COMPILER_VERSION 20) +set(CMAKE_CXX_STANDARD 20) - -Wall - -Wextra - -Wpedantic +if (NOT WIN32) + add_compile_options( + -Wall + -Wextra + -Wpedantic - -Wcast-align - -Wcast-qual - -Wconversion - -Wctor-dtor-privacy - -Wenum-compare - -Wfloat-equal - -Wnon-virtual-dtor - -Wold-style-cast - -Woverloaded-virtual - -Wredundant-decls - -Wsign-conversion - -Wsign-promo -) + -Wcast-align + -Wcast-qual + -Wconversion + -Wctor-dtor-privacy + -Wenum-compare + -Wfloat-equal + -Wnon-virtual-dtor + -Wold-style-cast + -Woverloaded-virtual + -Wredundant-decls + -Wsign-conversion + -Wsign-promo + ) +endif () add_subdirectory(lib) diff --git a/PrintOS.cmake b/PrintOS.cmake new file mode 100644 index 0000000..d3ae2b2 --- /dev/null +++ b/PrintOS.cmake @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.12) + +if (UNIX AND NOT APPLE) + set(LINUX TRUE) +endif () + +if (WIN32) + message("Windows") +elseif (LINUX) + message("Linux") +else () + message("MacOS") +endif () diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..9d5ba52 --- /dev/null +++ b/install.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +OS_NAME="$(cmake -P ./PrintOS.cmake 2>&1)" +PROJECT_NAME="SandPile" +CMAKE_BUILD_DIR="$HOME/CMakeBuilds" +CMAKE_PROJECT_DIR="$CMAKE_BUILD_DIR/$PROJECT_NAME" + +if [ "x$SAVE_PREV" = "x" ]; then + if [ -e "$CMAKE_PROJECT_DIR" ]; then + rm -rf "$CMAKE_PROJECT_DIR" + fi +fi + +EXEC_EXTENSION=".exe" +EXEC_PATH="$CMAKE_PROJECT_DIR/$PROJECT_NAME$EXEC_EXTENSION" + +if [ "$OS_NAME" = "Linux" ]; then + EXEC_EXTENSION=".run" + EXEC_PATH="$CMAKE_PROJECT_DIR/$PROJECT_NAME" +elif [ "$OS_NAME" = "MacOS" ]; then + EXEC_EXTENSION=".run" + EXEC_PATH="$CMAKE_PROJECT_DIR/$PROJECT_NAME" +fi + +EXEC_LINK_PATH="$HOME/$PROJECT_NAME$EXEC_EXTENSION" + +if (cmake -S . -B "$CMAKE_PROJECT_DIR" -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" && cmake --build "$CMAKE_PROJECT_DIR" --target "$PROJECT_NAME"); then + rm -f "$EXEC_LINK_PATH" + ln -s "$EXEC_PATH" "$EXEC_LINK_PATH" + echo '' + + if ("$EXEC_LINK_PATH" -h >/dev/null 2>/dev/null); then + echo "Congratulations! $PROJECT_NAME was compiled successfully." + echo '' + "$EXEC_LINK_PATH" -h + echo '' + + if [ "$OS_NAME" = "Linux" ]; then + printf 'Do you want to add this utility to /usr/bin (y/n)? ' && read -r CHOISE + COMMON_LINK_PATH="/usr/bin/${PROJECT_NAME:?}" + COMMON_PROJECT_DIR="/opt/${PROJECT_NAME:?}" + COMMON_EXEC_PATH="$COMMON_PROJECT_DIR/$PROJECT_NAME" + + if [ "$CHOISE" = "y" ]; then + sudo -S rm -f "$COMMON_LINK_PATH" + + if (sudo ln -s "$EXEC_PATH" "$COMMON_LINK_PATH"); then + if [ -e "$COMMON_PROJECT_DIR" ]; then + sudo rm -rf "$COMMON_PROJECT_DIR" + fi + + sudo rm -f "$COMMON_LINK_PATH" + sudo cp -r "$CMAKE_PROJECT_DIR" "$COMMON_PROJECT_DIR" + sudo ln -s "$COMMON_EXEC_PATH" "$COMMON_LINK_PATH" + echo "Accepted, run utility with $PROJECT_NAME" + else + echo 'Please try again later.' + echo "Declined, run utility with $EXEC_LINK_PATH" + fi + else + echo "Declined, run utility with $EXEC_LINK_PATH" + fi + else + echo "Run utility with $EXEC_LINK_PATH" + fi + + exit 0 + elif (cd "$CMAKE_PROJECT_DIR" && "./$PROJECT_NAME$EXEC_EXTENSION" -h >/dev/null 2>/dev/null); then + rm -f "$EXEC_LINK_PATH" + rm -rf "$HOME/${PROJECT_NAME:?}" + echo "Congratulations! $PROJECT_NAME was compiled successfully." + echo "Because of Windows-specific limitations, it is not possible to create a link to it." + echo "You can run it from $HOME/$PROJECT_NAME as .\\$PROJECT_NAME$EXEC_EXTENSION" + echo "Or you can run CMD.EXE with administrative privileges and type: " + echo 'mklink "%userprofile%\SandPile.exe" "%userprofile%\SandPile\SandPile.exe"' + echo '' + mkdir "$HOME/$PROJECT_NAME" + cp "$CMAKE_PROJECT_DIR/$PROJECT_NAME$EXEC_EXTENSION" "$HOME/$PROJECT_NAME/$PROJECT_NAME$EXEC_EXTENSION" + # ALso copy all *dll files like following: + # cp -r "$CMAKE_PROJECT_DIR/liblib.dll" "$HOME/$PROJECT_NAME/liblib.dll" + cd "$HOME/$PROJECT_NAME" && "./$PROJECT_NAME$EXEC_EXTENSION" -h + exit 0 + else + echo 'Oops! Could not execute the program.' + exit 1 + fi +else + echo 'Error occurred during running CMake. Make sure that it is installed and configured properly.' + exit 1 +fi diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index f78bbcb..a9a14be 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -4,8 +4,13 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() -set(CMAKE_CXX_FLAGS_DEBUG "-g") -set(CMAKE_CXX_FLAGS_RELEASE "-O3") +if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(CMAKE_CXX_FLAGS_DEBUG "/MDd") + set(CMAKE_CXX_FLAGS_RELEASE "/O2") +else () + set(CMAKE_CXX_FLAGS_DEBUG "-g") + set(CMAKE_CXX_FLAGS_RELEASE "-O3") +endif() message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") diff --git a/lib/basic/basic_functions.cpp b/lib/basic/basic_functions.cpp index e69d84a..0cfa49a 100644 --- a/lib/basic/basic_functions.cpp +++ b/lib/basic/basic_functions.cpp @@ -148,7 +148,7 @@ bool IsDirectory(char* dirname) { } void PrintHelp() { - std::cout << "SandPile model version 0.1 by bialger.\n" + std::cout << "SandPile model version 1.0 by bialger.\n" << "SandPile model help page.\n" << "Usage: SandPile [OPTIONS]...\n" << "SandPile models an Abelian sandpile model. " diff --git a/lib/basic/basic_functions.hpp b/lib/basic/basic_functions.hpp index 4bee0f1..64d25eb 100644 --- a/lib/basic/basic_functions.hpp +++ b/lib/basic/basic_functions.hpp @@ -4,6 +4,9 @@ #include #if defined _WIN32 || defined _WIN64 || defined __CYGWIN__ +#ifndef NOMINMAX +#define NOMINMAX +#endif #include #else #define STD_OUTPUT_HANDLE 0 diff --git a/lib/bmp_writer/bmp_writer.cpp b/lib/bmp_writer/bmp_writer.cpp index afc2799..9c68185 100644 --- a/lib/bmp_writer/bmp_writer.cpp +++ b/lib/bmp_writer/bmp_writer.cpp @@ -3,6 +3,7 @@ #include #include +#include BmpWriter::BmpWriter() { width_ = 0; @@ -24,7 +25,7 @@ void BmpWriter::ExportField(char* dirname, CoordinatesField& field, file_.open(path, std::ios::out | std::ios::binary); if (!file_.is_open()) { - std::cout << "Can't open file: " << path.native() << std::endl; + std::cout << "Can't open file: " << path.string() << std::endl; return; } diff --git a/lib/field/tsv_handler.cpp b/lib/field/tsv_handler.cpp index 6941b92..c0f6af1 100644 --- a/lib/field/tsv_handler.cpp +++ b/lib/field/tsv_handler.cpp @@ -53,7 +53,7 @@ bool TsvHandler::ExportTSV(char* dirname, CoordinatesField& field, int64_t numbe std::ofstream file(path, std::ios::out); if (!file.is_open()) { - std::cout << "Can't open file: " << path.native() << std::endl; + std::cout << "Can't open file: " << path.string() << std::endl; return false; } diff --git a/main.cpp b/main.cpp index b75c19c..51af4c7 100644 --- a/main.cpp +++ b/main.cpp @@ -1,9 +1,15 @@ #include +#include #include "lib/basic/basic_functions.hpp" #include "lib/parser/arguments_parser.hpp" #include "lib/sand_pile/sand_pile.hpp" int main(int32_t argc, char** argv) { + if (argc == 2 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)) { + PrintHelp(); + return 0; + } + constexpr size_t kArgumentCount = 6; ArgumentInformation* arguments = new ArgumentInformation[kArgumentCount]; arguments[0] = {"-i", "--input=", "Path to input file",