Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 138 additions & 36 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,46 +1,148 @@
# Apply to ALL headers (empty = no restriction)
HeaderFilterRegex: '.*'

# Treat warnings as errors (optional but recommended for CI)
# WarningsAsErrors: '*'
WarningsAsErrors: ''
---
# Configure clang-tidy for this project.

# Here is an explanation for why some of the checks are disabled:
#
# -google-readability-namespace-comments: the *_CLIENT_NS is a macro, and
# clang-tidy fails to match it against the initial value.
#
# -modernize-use-trailing-return-type: clang-tidy recommends using
# `auto Foo() -> std::string { return ...; }`, we think the code is less
# readable in this form.
#
# --modernize-concat-nested-namespaces: clang-tidy recommends
# `namespace google::cloud {}` over `namespace google { namespace cloud { } }`
# We need to support C++14, which does not supported nested namespaces.
#
# --modernize-use-nodiscard: clang-tidy recommends adding a nodiscard annotation
# to functions where the return value should not be ignored.
# We need to support C++14, which does not supported the annotation.
#
# -modernize-return-braced-init-list: We think removing typenames and using
# only braced-init can hurt readability.
#
# -modernize-avoid-c-arrays: We only use C arrays when they seem to be the
# right tool for the job, such as `char foo[] = "hello"`. In these cases,
# avoiding C arrays often makes the code less readable, and std::array is
# not a drop-in replacement because it doesn't deduce the size.
#
# -modernize-type-traits: clang-tidy recommands using c++17 style variable
# templates. We will enable this check after we moved to c++17.
#
# -modernize-unary-static-assert: clang-tidy asks removing empty string in
# static_assert(), the check is only applicable for c++17 and later code.
# We will enable this check after we moved to c++17.
#
# -performance-move-const-arg: This warning requires the developer to
# know/care more about the implementation details of types/functions than
# should be necessary. For example, `A a; F(std::move(a));` will trigger a
# warning IFF `A` is a trivial type (and therefore the move is
# meaningless). It would also warn if `F` accepts by `const&`, which is
# another detail that the caller need not care about.
#
# -performance-avoid-endl: we would like to turn this on, but there are too
# many legitimate uses in our samples.
#
# -performance-enum-size: Smaller enums may or not may be faster, it depends on
# the architechture. If data size was a consideration, we might decide to
# enable the warnings.
#
# -readability-redundant-declaration: A friend declaration inside a class
# counts as a declaration, so if we also declare that friend outside the
# class in order to document it as part of the public API, that will
# trigger a redundant declaration warning from this check.
#
# -readability-avoid-return-with-void-value: We believe this is idiomatic
# and saves typing, and the intent is obvious.
#
# -readability-function-cognitive-complexity: too many false positives with
# clang-tidy-12. We need to disable this check in macros, and that setting
# only appears in clang-tidy-13.
#
# -bugprone-narrowing-conversions: too many false positives around
# `std::size_t` vs. `*::difference_type`.
#
# -bugprone-easily-swappable-parameters: too many false positives.
#
# -bugprone-implicit-widening-of-multiplication-result: too many false positives.
# Almost any expression of the form `2 * variable` or `long x = a_int * b_int;`
# generates an error.
#
# -bugprone-unchecked-optional-access: too many false positives in tests.
# Despite what the documentation says, this warning appears after
# `ASSERT_TRUE(variable)` or `ASSERT_TRUE(variable.has_value())`.
#
# TODO(#14162): Enable clang-tidy checks. We initially omitted these checks
# because they require large cleanup efforts or were blocking the clang-tidy
# X update.
Checks: >
-*,
clang-diagnostic-*,
modernize-*,
-modernize-use-trailing-return-type,
-modernize-use-auto,
cppcoreguidelines-*,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-avoid-magic-numbers,
abseil-*,
bugprone-*,
google-*,
misc-*,
modernize-*,
performance-*,
portability-*,
readability-*,
-readability-magic-numbers,
-bugprone-exception-escape,
-google-readability-braces-around-statements,
-google-readability-namespace-comments,
-google-runtime-references,
-misc-non-private-member-variables-in-classes,
-misc-const-correctness,
-misc-include-cleaner,
-modernize-return-braced-init-list,
-modernize-use-trailing-return-type,
-modernize-concat-nested-namespaces,
-modernize-use-nodiscard,
-modernize-avoid-c-arrays,
-modernize-type-traits,
-modernize-unary-static-assert,
-performance-move-const-arg,
-performance-avoid-endl,
-performance-enum-size,
-readability-braces-around-statements,
-readability-identifier-length,
misc-*,
-misc-unused-parameters

CheckOptions:
- key: readability-identifier-naming.NamespaceCase
value: lower_case

- key: readability-identifier-naming.ClassCase
value: CamelCase

- key: readability-identifier-naming.StructCase
value: CamelCase

- key: readability-identifier-naming.FunctionCase
value: lower_case
-readability-magic-numbers,
-readability-named-parameter,
-readability-redundant-declaration,
-readability-avoid-return-with-void-value,
-readability-function-cognitive-complexity,
-bugprone-narrowing-conversions,
-bugprone-easily-swappable-parameters,
-bugprone-inc-dec-in-conditions,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-unchecked-optional-access,
-bugprone-unused-local-non-trivial-variable,
-bugprone-unused-return-value

- key: readability-identifier-naming.VariableCase
value: lower_case
# Turn all the warnings from the checks above into errors.
WarningsAsErrors: "*"

- key: readability-identifier-naming.MemberCase
value: lower_case
HeaderFilterRegex: "(google/cloud/|generator/).*\\.h$"

- key: modernize-use-nullptr.NullMacros
value: 'NULL'
CheckOptions:
- { key: readability-identifier-naming.NamespaceCase, value: lower_case }
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
- { key: readability-identifier-naming.StructCase, value: CamelCase }
- { key: readability-identifier-naming.TemplateParameterCase, value: CamelCase }
- { key: readability-identifier-naming.FunctionCase, value: aNy_CasE }
- { key: readability-identifier-naming.VariableCase, value: lower_case }
- { key: readability-identifier-naming.ClassMemberCase, value: lower_case }
- { key: readability-identifier-naming.ClassMemberSuffix, value: _ }
- { key: readability-identifier-naming.PrivateMemberSuffix, value: _ }
- { key: readability-identifier-naming.ProtectedMemberSuffix, value: _ }
- { key: readability-identifier-naming.EnumConstantCase, value: CamelCase }
- { key: readability-identifier-naming.EnumConstantPrefix, value: k }
- { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase }
- { key: readability-identifier-naming.ConstexprVariablePrefix, value: k }
- { key: readability-identifier-naming.GlobalConstantCase, value: CamelCase }
- { key: readability-identifier-naming.GlobalConstantPrefix, value: k }
- { key: readability-identifier-naming.MemberConstantCase, value: CamelCase }
- { key: readability-identifier-naming.MemberConstantPrefix, value: k }
- { key: readability-identifier-naming.StaticConstantCase, value: CamelCase }
- { key: readability-identifier-naming.StaticConstantPrefix, value: k }
- { key: readability-implicit-bool-conversion.AllowIntegerConditions, value: 1 }
- { key: readability-implicit-bool-conversion.AllowPointerConditions, value: 1 }
- { key: readability-function-cognitive-complexity.IgnoreMacros, value: 1 }
34 changes: 0 additions & 34 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,53 +1,29 @@
# ROOT CMAKE
# │
# ┌─────────────────┴─────────────────┐
# │ │
# src module tests module
# │ │
# ┌────┴────┐ │
# │ │ │
# core socket │
# │ │ │
# └──────┬──┘ │
# │ │
# ▼ ▼
# cpp_lab_project cpp_lab_project_unit_test
# (main executable) (GoogleTest executable)

cmake_minimum_required(VERSION 3.14)

# ----------------------------------------------------------------------------------------
# Project metadata
# ----------------------------------------------------------------------------------------
project(cpp_lab_project # ${PROJECT_NAME}
VERSION 1.0.0
DESCRIPTION "A C/C++ project uses CMake, GoogleTest, gcc, g++, cppcheck, and lcov, integrated with Docker and GitHub Actions for CI/CD."
LANGUAGES CXX
)

# ----------------------------------------------------------------------------------------
# Output directories to build/bin
# ----------------------------------------------------------------------------------------
# Executables
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Shared libraries
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
# Static libraries
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

# ----------------------------------------------------------------------------------------
# Compiler and language configuration
# ----------------------------------------------------------------------------------------
# Require at least C++17 for GoogleTest and modern C++ features
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Export compile_commands.json (useful for clang-tidy, clangd, IDEs)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# ----------------------------------------------------------------------------------------
# Build metadata
# ----------------------------------------------------------------------------------------
# Ensure directory exists for generated headers
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/generated)

Expand All @@ -60,24 +36,18 @@ configure_file(
${CMAKE_BINARY_DIR}/generated/version.h
)

# ----------------------------------------------------------------------------------------
# External dependencies (GoogleTest,...)
# ----------------------------------------------------------------------------------------
include(cmake/Dependencies.cmake)

# ----------------------------------------------------------------------------------------
# Compiler warnings (useful for learning/debugging)
# ----------------------------------------------------------------------------------------
add_compile_options(-Wall -Wextra -Wpedantic)

message(STATUS "C Compiler: ${CMAKE_C_COMPILER}")
message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER}")
message(STATUS "C++ Compiler ID: ${CMAKE_CXX_COMPILER_ID}")
message(STATUS "C++ Compiler Version: ${CMAKE_CXX_COMPILER_VERSION}")

# ----------------------------------------------------------------------------------------
# Code coverage configuration
# ----------------------------------------------------------------------------------------
option(ENABLE_COVERAGE "Enable coverage reporting" OFF)

if(ENABLE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
Expand All @@ -86,13 +56,9 @@ if(ENABLE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
add_link_options(--coverage)
endif()

# ----------------------------------------------------------------------------------------
# Enable CTest framework (used by GoogleTest)
# ----------------------------------------------------------------------------------------
enable_testing()

# ----------------------------------------------------------------------------------------
# Add project modules
# ----------------------------------------------------------------------------------------
add_subdirectory(src)
add_subdirectory(tests)
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Get-ChildItem -Recurse -Include *.cpp, *.h, *.hpp | ForEach-Object { clang-forma
$ sudo apt-get install cppcheck
$ sudo apt-get install -y clang-tidy
$ sudo apt install python3-gcovr
$ sudo apt-get install -y libgtkmm-4.0-dev
```
* Build the application and the tests
```bash
Expand Down
61 changes: 61 additions & 0 deletions include/Logger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#ifndef LOGGER_H_
#define LOGGER_H_

#include <iostream>

#ifndef NDEBUG
#include <mutex>
#include <source_location>
#include <string_view>

class Logger {
public:
static Logger& instance() {
static Logger logger; // guaranteed single instance, thread-safe in C++11+
return logger;
}

void log(std::string_view msg, std::string_view level = "INFO",
std::source_location loc = std::source_location::current()) {
std::lock_guard<std::mutex> lock(mutex_);

// Extract filename only (no full path)
std::string_view file = loc.file_name();
auto pos = file.find_last_of("/\\");
if (pos != std::string_view::npos) {
file = file.substr(pos + 1);
}

// Get current time
auto now = std::chrono::system_clock::now();
auto t = std::chrono::system_clock::to_time_t(now);
std::tm tm{};
localtime_r(&t, &tm);

char time_buf[9];
std::strftime(time_buf, sizeof(time_buf), "%H:%M:%S", &tm);

std::cout << "[" << time_buf << "]" << "[" << level << "]" << "[" << file
<< ":" << loc.line() << "]" << "[" << loc.function_name() << "] "
<< msg << '\n';
}

// Prevent copies
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;

private:
Logger() = default;
std::mutex mutex_;
};

#define LOG(msg) Logger::instance().log(msg)

#else

inline void LOG(const std::string& msg) {
std::cout << msg << '\n';
}

#endif
#endif
4 changes: 0 additions & 4 deletions scripts/run.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
## NOTE:
## This file was initially generated with the assistance of AI.
## The code has been reviewed and may have been modified by the developer
## to ensure correctness, readability, and compliance with project requirements.
#!/usr/bin/env bash

set -e # Exit immediately if a command fails
Expand Down
2 changes: 2 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <vector>

#include "ExampleRegistry.h"
#include "Logger.h"
#include "version.h"

int readChoice() {
Expand Down Expand Up @@ -103,6 +104,7 @@ void runMenu() {
}

int main(int argc, char* argv[]) {
LOG("Logger has been integrated");
std::cout << std::endl;
if (__cplusplus == 202302L)
std::cout << "C++23";
Expand Down
Loading