diff --git a/.gitignore b/.gitignore index 385ca73..b746b06 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *build -*private* \ No newline at end of file +*private* +*.vscode \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fba6c3..9db9342 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,10 +5,20 @@ cmake_minimum_required(VERSION 3.14) # ---------------------------------------------------------------------------------------- project(cpp_lab_project # ${PROJECT_NAME} VERSION 1.0.0 - DESCRIPTION "The project with GoogleTest and CMake" + DESCRIPTION "A C/C++ project uses CMake, GoogleTest, gcc, g++, cppcheck, and lcov, integrated with Docker and GitHub Actions for CI/CD." LANGUAGES CXX ) +# Build timestamp +file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/include) +string(TIMESTAMP BUILD_TIME "%Y-%m-%d %H:%M:%S") + +configure_file( + ${CMAKE_SOURCE_DIR}/include/version.h.in + ${CMAKE_BINARY_DIR}/generated/version.h +) + + set(PROJECT_NAME_TEST ${PROJECT_NAME}_unit_test) # name for the unit-test executable # ---------------------------------------------------------------------------------------- @@ -60,11 +70,14 @@ enable_testing() # Header files directory set(APP_HEADERS "include" + "${CMAKE_BINARY_DIR}/generated" # cmake generated headers ) # Core source files set(APP_SOURCES "src/DeleteMe.cpp" + "src/core/basics/InitializeVariable.cpp" + "src/core/basics/Operations.cpp" ) # Test files diff --git a/README.md b/README.md index d00429d..65f3d06 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,67 @@ -## OVERVIEW - - Structure: - includes/ → header files (.h, .hpp) - src/ → source files (.cpp) - tests/ → GoogleTest test cases +## 1. OVERVIEW +**Project Structure** +``` +includes/ → Header files (.h, .hpp) +src/ → Source files (.cpp) +tests/ → GoogleTest test cases +``` +## 2. DEPENDENCIES +Make sure the following tools are installed before building the project: +- **g++ / gcc** +- **CMake** +- **Git** +- **lcov** (for code coverage) +- **cppcheck** (for static analysis) -## DEPENDENCIES - -## SETUP +## 3. SETUP * Setup the Local Test Environment - * Using your own Ubuntu system + * 1.Using your own Ubuntu system * Install `gcc`, `cmake`, `git`, and `pthread` (Skip this step if you already install) ``` $ sudo apt-get update - $ sudo apt-get install g++=4:5.3.1-1ubuntu1 - $ sudo apt-get install lcov=1.12-2 - $ sudo apt-get install cmake=3.5.1-1ubuntu3 - $ sudo apt-get install git=1:2.7.4-0ubuntu1.6 - $ sudo apt-get install libpthread-stubs0-dev=0.3-4 - + $ sudo apt-get install g++ + $ sudo apt-get install lcov + $ sudo apt-get install cmake + $ sudo apt-get install git + $ sudo apt-get install cppcheck ``` * Build the application and the tests ``` $ cd build $ cmake .. $ cmake --build . - ``` * Run the application and the test ``` $ ./cpp_lab_project $ ./cpp_lab_project_test ``` - * (Optional) Run the cpp check + * (Optional) Run static analysis ``` $ sudo apt-get install cppcheck $ cppcheck "folder" / "file" ``` - * Using **Docker** - * Use the -t or --tag flag to set the name of the image to be created. (the full name is actually sample-ci-cpp:latest, since latest is the default tag) - * Opening an interactive shell inside your Docker container to explore, test, or debug the environment built from your image. - * docker run → start a new container. - * -it → run it interactively: - * -i = keep STDIN open (so you can type commands) - * -t = allocate a terminal (TTY) - * sample-ci-cpp:latest → the image you built earlier. - * /bin/bash → the command to execute inside the container (opens a Bash shell). + * 2.Using **Docker** + * Build the Docker image ``` docker build --tag sample-ci-cpp . + ``` + * Run an interactive container + ``` docker run -it sample-ci-cpp:latest /bin/bash + ``` + * Inspect the environment + ``` printenv ``` + * *Notes:* + * Use the -t or --tag flag to set the name of the image to be created. (the full name is actually sample-ci-cpp:latest, since latest is the default tag) + * Opening an interactive shell inside your Docker container to explore, test, or debug the environment built from your image. + * docker run to start a new container. + * -it → run it interactively: + * -i = keep STDIN open (so you can type commands) + * -t = allocate a terminal (TTY) + * sample-ci-cpp:latest → the image you built earlier. + * /bin/bash → the command to execute inside the container (opens a Bash shell). -## DOCUMENTATIONs \ No newline at end of file +## 4. DOCUMENTATIONS \ No newline at end of file diff --git a/include/version.h.in b/include/version.h.in new file mode 100644 index 0000000..4d31f37 --- /dev/null +++ b/include/version.h.in @@ -0,0 +1,6 @@ +#pragma once + +#define APP_NAME "@PROJECT_NAME@" +#define APP_VERSION "@PROJECT_VERSION@" +#define APP_DESCRIPTION "@PROJECT_DESCRIPTION@" +#define APP_BUILD_TIME "@BUILD_TIME@" diff --git a/src/core/basics/InitializeVariable.cpp b/src/core/basics/InitializeVariable.cpp new file mode 100644 index 0000000..6ff05fa --- /dev/null +++ b/src/core/basics/InitializeVariable.cpp @@ -0,0 +1,65 @@ +#include +using namespace std; + +void initialize_variable(); + +// A struct that runs code when its object is created +struct InitializeVariable +{ + InitializeVariable() + { + cout << "\n" + << "\n" + << "InitializeVariable\n"; + initialize_variable(); + } +}; + +// All global and static objects are constructed before main() begins. +static InitializeVariable autoRunInstance; + +struct Foo +{ + Foo() + { + cout << "Default constructor/ default init\n"; + } + + // explicit Foo(int) + explicit Foo(int) + { + cout << "Constructor called with int / copy init\n"; + } + + Foo(const Foo &other) + { + std::cout << "Copy constructor called\n"; + } +}; + +void initialize_variable() +{ + cout << "\n--- Variable Initialization Examples ---\n"; + // There are there common ways to intialize a variable + // * Default + [[maybe_unused]] int initDefaultVar; + [[maybe_unused]] Foo initDefaultObj; + + // * Traditional initialization + // * Copy-init: Type var = value; + // 1. Compiler tries to convert the value to a temporary Foo. + // 2. If the constructor is explicit, implicit conversion is blocked -> compilation error. + // 3. Otherwise, a temporary Foo is created and then copied/moved into the variable. + [[maybe_unused]] Foo copyInitObj = (Foo)2.3; // explicit cast: double 2.3 -> int 2 (implicit narrowing) -> Foo(int) -> temporary Foo -> copied/moved into copyInitObj + // Foo copyInitObjError = 2.3; // ERROR: implicit conversion blocked by explicit constructor + // We can explicitly prevent certain conversions using = delete or using {} + + // * direct-init: Type var(value); + [[maybe_unused]] Foo directInitObj(4); // call Foo(int) + [[maybe_unused]] Foo directInitObj2(4.3); // look for constructor -> implicit 4.3(float) -> 4(int) -> call Foo(int) -> + + // * Brace init + // calls the constructor directly without allowing implicit conversions. + [[maybe_unused]] Foo braceInit{3}; + // Foo braceInit2{3.3}; // ERORR => Prefer this way +} \ No newline at end of file diff --git a/src/core/basics/Operations.cpp b/src/core/basics/Operations.cpp new file mode 100644 index 0000000..06dfee2 --- /dev/null +++ b/src/core/basics/Operations.cpp @@ -0,0 +1,129 @@ +#include +using namespace std; + +void arithmeticOperator(); +void logicalOperator(); +void bitWiseOperator(); + +struct Operations +{ + Operations() + { + cout << "\n" + << "\n" + << "Operation\n"; + arithmeticOperator(); + logicalOperator(); + bitWiseOperator(); + } +}; + +static Operations autoRunInstance; + +void arithmeticOperator() +{ + cout << "\n--- ArithmeticOperator Examples ---\n"; + int a{100}, b{200}; + + // Addition + cout << "a = " << a << ", b = " << b << "\n"; + int sum = a + b; + cout << "sum = " << sum << "\n"; + + // Subtraction + cout << "a = " << a << ", b = " << b << "\n"; + int different = a - b; + cout << "different = " << different << "\n"; + + // Multiplication + cout << "a = " << a << ", b = " << b << "\n"; + int product = a * b; + cout << "product = " << product << "\n"; + + // Division + cout << "a = " << a << ", b = " << b << "\n"; + int quotient = a / b; + cout << "quotient = " << quotient << "\n"; + + // Modulus + cout << "a = " << a << ", b = " << b << "\n"; + int remainder = a % b; + cout << "remainder = " << remainder << "\n"; + + // Increment + cout << "a = " << a << "\n"; + int preIn = ++a; // increase a, return copy + cout << "preIn = " << preIn << "\n"; + + cout << "a = " << a << "\n"; + int postIn = a++; // copy a to a copy, then increase a, return copy + cout << "postIn = " << postIn << "\n"; + + // Decrement + cout << "b = " << b << "\n"; + int preDe = --b; + cout << "preDe = " << preDe << "\n"; + + cout << "b = " << b << "\n"; + int postDe = b--; + cout << "postDe = " << postDe << "\n"; + + // Comma: + int value = (a++, b); // a is incremented, then b is returned + cout << "a = " << a << ", b = " << b << "\n"; + cout << "comma(a++, b) = " << value << "\n"; +} + +void logicalOperator() +{ + cout << "\n--- LogicalOperator Examples ---\n"; + bool a = true; + bool b = false; + bool c = true; + + cout << boolalpha; // show true/false instead of 1/0 + cout << "a = " << a << ", b = " << b << ", c = " << c << "\n\n"; + + // AND (&&) + cout << "[AND] a && b = " << (a && b) << "\n"; + + // OR (||) + cout << "[OR ] a || b = " << (a || b) << "\n"; + + // NOT (!) + cout << "[NOT] !c = " << (!c) << "\n"; +} + +#include +void bitWiseOperator() +{ + cout << "\n--- BitWiseOperator Examples ---\n"; + bitset<8> bitsA{0b1111'1111}; + bitset<8> bitsB{0b1111'0000}; + + cout << "bitA = " << bitsA << ", bitB = " << bitsB << "\n"; + + // AND + bitset<8> result = bitsA & bitsB; + cout << "bitA && bitB= " << result << "\n"; + + // OR + result = bitsA | bitsB; + cout << "bitA | bitB= " << result << "\n"; + + // XOR + result = bitsA ^ bitsB; + cout << "bitA ^ bitB= " << result << "\n"; + + // NOT + result = ~bitsA; + cout << "~bitA = " << result << "\n"; + + // LEFT SHIFT + result = bitsA << 1; + cout << "bitA << 1 = " << result << "\n"; + + // RIGHT SHIFT + result = bitsA >> 1; + cout << "bitA >> 1 = " << result << "\n"; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 6d8bfc1..974edfb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,9 @@ #include +#include "version.h" int main(int argc, char *argv[]) { - std::cout << "Hello World" << std::endl; + std::cout << APP_NAME << " v" << APP_VERSION << std::endl; + std::cout << APP_DESCRIPTION << std::endl; return 0; } \ No newline at end of file