From 5b45b0445405d67c9e824dad72306571ff1eb714 Mon Sep 17 00:00:00 2001 From: McMassiveNZ <12842622+McMassiveNZ@users.noreply.github.com> Date: Fri, 2 Dec 2022 19:41:20 +0100 Subject: [PATCH] Initial Commit * A simple C-Make project setup * A lot of warnings enabled and warnings as errors * unit test discovery with google test In progress functionality - sanitizers - static analysis --- .gitignore | 8 +++ CMakeLists.txt | 30 ++++++++++ scripts/compilerwarnings.cmake | 106 +++++++++++++++++++++++++++++++++ scripts/googletest.cmake | 18 ++++++ scripts/precompiled.cmake | 8 +++ scripts/sanitizers.cmake | 20 +++++++ scripts/staticanalysis.cmake | 16 +++++ src/CMakeLists.txt | 26 ++++++++ src/main.cpp | 8 +++ test/CMakeLists.txt | 14 +++++ test/test_main.cpp | 6 ++ 11 files changed, 260 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 scripts/compilerwarnings.cmake create mode 100644 scripts/googletest.cmake create mode 100644 scripts/precompiled.cmake create mode 100644 scripts/sanitizers.cmake create mode 100644 scripts/staticanalysis.cmake create mode 100644 src/CMakeLists.txt create mode 100644 src/main.cpp create mode 100644 test/CMakeLists.txt create mode 100644 test/test_main.cpp diff --git a/.gitignore b/.gitignore index 259148f..4a7e2fa 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,11 @@ *.exe *.out *.app + +# MSVC Specific +*.pdb +*.exp + +build/ +.vs/ +Testing/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..388de9b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.23) + +# uncomment to enable vcpkg: +# # Setup vcpkg - should be called before defining project() +# run_vcpkg() + +project(blank-slate VERSION 1.0.0) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED true) +set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE) + +set_property(GLOBAL PROPERTY USE_FOLDERS ON) +OPTION(ENABLE_TESTS "Enable Unit Tests" ON) +OPTION(ENABLE_ALL_REASONABLE_WARNINGS "Enable all possible reasonable warnings" ON ) +OPTION(ENABLE_WARNINGS_AS_ERRORS "Warnings are treated as Errors" ON) +OPTION(ENABLE_STATIC_ANALYSIS "Enable Static Analysis Tools" ON) +OPTION(ENABLE_SANITIZERS "Enable Sanitizer Tools" ON) + +include(scripts/compilerWarnings.cmake) +include(scripts/sanitizers.cmake) +include(scripts/staticanalysis.cmake) + +if (ENABLE_TESTS) + message("Unit Testing Enabled") + enable_testing() + add_subdirectory(test) +endif() + +add_subdirectory(src) diff --git a/scripts/compilerwarnings.cmake b/scripts/compilerwarnings.cmake new file mode 100644 index 0000000..ec48bfa --- /dev/null +++ b/scripts/compilerwarnings.cmake @@ -0,0 +1,106 @@ +include_guard() + +function( target_enable_warnings _target ) + if(MSVC) + target_compile_options( + ${_target} + PUBLIC + /W4 # Baseline reasonable warnings + /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data + /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data + /w14263 # 'function': member function does not override any base class virtual member function + /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not + # be destructed correctly + /w14287 # 'operator': unsigned/negative constant mismatch + /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside + # the for-loop scope + /w14296 # 'operator': expression is always 'boolean_value' + /w14311 # 'variable': pointer truncation from 'type1' to 'type2' + /w14545 # expression before comma evaluates to a function which is missing an argument list + /w14546 # function call before comma missing argument list + /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect + /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'? + /w14555 # expression has no effect; expected expression with side- effect + /w14619 # pragma warning: there is no warning number 'number' + /w14640 # Enable warning on thread un-safe static member initialization + /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. + /w14905 # wide string literal cast to 'LPSTR' + /w14906 # string literal cast to 'LPWSTR' + /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied + /permissive- # standards conformance mode for MSVC compiler. + ) + elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + target_compile_options( + ${_target} + INTERFACE + -Wall + -Wextra # reasonable and standard + -Wextra-semi # Warn about semicolon after in-class function definition. + -Wshadow # warn the user if a variable declaration shadows one from a parent context + -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps + + # catch hard to track down memory errors + -Wold-style-cast # warn for c-style casts + -Wcast-align # warn for potential performance problem casts + -Wunused # warn on anything being unused + -Woverloaded-virtual # warn if you overload (not override) a virtual function + -Wpedantic # warn if non-standard C++ is used + -Wconversion # warn on type conversions that may lose data + -Wsign-conversion # warn on sign conversions + -Wnull-dereference # warn if a null dereference is detected + -Wdouble-promotion # warn if float is implicit promoted to double + -Wformat=2 # warn on security issues around functions that format output (ie printf) + -Wimplicit-fallthrough # warn on statements that fallthrough without an explicit annotation + ) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_compile_options( + ${_target} + INTERFACE + -Wall + -Wextra # reasonable and standard + -Wextra-semi # Warn about semicolon after in-class function definition. + -Wshadow # warn the user if a variable declaration shadows one from a parent context + -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps + + # catch hard to track down memory errors + -Wold-style-cast # warn for c-style casts + -Wcast-align # warn for potential performance problem casts + -Wunused # warn on anything being unused + -Woverloaded-virtual # warn if you overload (not override) a virtual function + -Wpedantic # warn if non-standard C++ is used + -Wconversion # warn on type conversions that may lose data + -Wsign-conversion # warn on sign conversions + -Wnull-dereference # warn if a null dereference is detected + -Wdouble-promotion # warn if float is implicit promoted to double + -Wformat=2 # warn on security issues around functions that format output (ie printf) + -Wimplicit-fallthrough # warn on statements that fallthrough without an explicit annotation + -Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist + -Wduplicated-cond # warn if if / else chain has duplicated conditions + -Wduplicated-branches # warn if if / else branches have duplicated code + -Wlogical-op # warn about logical operations being used where bitwise were probably wanted + -Wuseless-cast # warn if you perform a cast to the same type + ) + endif() +endfunction() + +function(target_warnings_as_errors _target) + if(MSVC) + target_compile_options( + ${_target} + PUBLIC + /WX + ) + elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + target_compile_options( + ${_target} + PUBLIC + -WError + ) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_compile_options( + ${_target} + PUBLIC + -WError + ) + endif() +endfunction() \ No newline at end of file diff --git a/scripts/googletest.cmake b/scripts/googletest.cmake new file mode 100644 index 0000000..29379ff --- /dev/null +++ b/scripts/googletest.cmake @@ -0,0 +1,18 @@ +include_guard() + +include(FetchContent) +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG 58d77fa8070e8cec2dc1ed015d66b454c8d78850 # release-1.12.1 +) +# For Windows: Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) + +set_property(TARGET + gtest + gtest_main + gmock + gmock_main + PROPERTY FOLDER GoogleTest) diff --git a/scripts/precompiled.cmake b/scripts/precompiled.cmake new file mode 100644 index 0000000..aefae37 --- /dev/null +++ b/scripts/precompiled.cmake @@ -0,0 +1,8 @@ +include_guard() + +function( target_precompiled_header _target _header _source ) + if( MSVC ) + set_target_properties( ${_target} PROPERTIES COMPILE_FLAGS "/Yu${_header}" ) + set_source_files_properties( ${_source} PROPERTIES COMPILE_FLAGS "/Yc${_header}" ) + endif() +endfunction() \ No newline at end of file diff --git a/scripts/sanitizers.cmake b/scripts/sanitizers.cmake new file mode 100644 index 0000000..baeb0d6 --- /dev/null +++ b/scripts/sanitizers.cmake @@ -0,0 +1,20 @@ +include_guard() + +function( target_enable_sanitizers _target ) + if( MSVC ) + string(FIND "$ENV{PATH}" "$ENV{VSINSTALLDIR}" index_of_vs_install_dir) + + if("${index_of_vs_install_dir}" STREQUAL "-1") + message( + SEND_ERROR + "Using MSVC sanitizers requires setting the MSVC environment before building the project. Please manually open the MSVC command prompt and rebuild the project." + ) + endif() + + target_compile_options(${_target} PUBLIC /fsanitize=address /Zi /INCREMENTAL:NO) + target_link_options(${_target} PUBLIC /INCREMENTAL:NO) + else() + target_compile_options(${_target} INTERFACE -fsanitize=address,leak,undefined) + target_link_options(${_target} INTERFACE -fsanitize=address,leak,undefined) + endif() +endfunction() \ No newline at end of file diff --git a/scripts/staticanalysis.cmake b/scripts/staticanalysis.cmake new file mode 100644 index 0000000..72736a4 --- /dev/null +++ b/scripts/staticanalysis.cmake @@ -0,0 +1,16 @@ +include_guard() + +function(target_enable_static_analysis _target) + set(_VS_CLANG_TIDY "false") + find_program(CLANGTIDY clang-tidy) + if(CLANGTIDY) + set(_VS_CLANG_TIDY "true") + endif() + set_target_properties( + ${_target} + PROPERTIES + VS_GLOBAL_EnableMicrosoftCodeAnalysis true + VS_GLOBAL_CodeAnalysisRuleSet "AllRules.ruleset" + VS_GLOBAL_EnableClangTidyCodeAnalysis "${_VS_CLANG_TIDY}" + ) +endfunction() \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..9aef086 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,26 @@ +set(current_target blank_slate) + +add_executable( + ${current_target} + main.cpp +) + +if( ENABLE_ALL_REASONABLE_WARNINGS ) + MESSAGE("Additional Warnings Enabled") + target_enable_warnings(${current_target}) +endif() + +if( ENABLE_WARNINGS_AS_ERRORS ) + MESSAGE("Warnings as Errors") + target_warnings_as_errors(${current_target}) +endif() + +if( ENABLE_SANITIZERS ) + MESSAGE("Sanitizers Enabled") + target_enable_sanitizers(${current_target}) +endif() + +if( ENABLE_STATIC_ANALYSIS ) + MESSAGE("Static Analysis Enabled") + target_enable_static_analysis(${current_target}) +endif() \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..f2ce303 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,8 @@ +#include + +auto main() -> int +{ + printf("Hello, World!"); + return 0; +} + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..3379e12 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,14 @@ +include(${CMAKE_SOURCE_DIR}/scripts/googletest.cmake) + +add_executable( + blank-slate-test + test_main.cpp +) + +target_link_libraries( + blank-slate-test + gtest_main +) + +include(GoogleTest) +gtest_discover_tests(blank-slate-test) diff --git a/test/test_main.cpp b/test/test_main.cpp new file mode 100644 index 0000000..d46382c --- /dev/null +++ b/test/test_main.cpp @@ -0,0 +1,6 @@ +#include + +TEST(testmain, example) +{ + EXPECT_EQ(42, 7*6); +} \ No newline at end of file