initial commit

This commit is contained in:
dl92
2026-01-06 15:05:27 +00:00
parent a94f174a39
commit 62ab80b1d6
25 changed files with 1291 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
{
"cmake.sourceDirectory": "/home/ys/code/cplusplus/GeminiTutorial/tutorial-1",
"cmake.configureArgs": [
"-DCMAKE_TOOLCHAIN_FILE=/home/ys/code/cplusplus/vcpkg/scripts/buildsystems/vcpkg.cmake"
]
}

View File

@@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 3.15)
project(Tutorial1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Find dependencies
find_package(spdlog CONFIG REQUIRED)
find_package(GTest CONFIG REQUIRED)
# Create a library for our application code
# This allows us to share the code between the main app and the tests
add_library(MyLib src/calculator.cpp src/calculator.h)
target_include_directories(MyLib PUBLIC src)
# Define our main executable
add_executable(App src/main.cpp)
# Link our App against spdlog and our library
target_link_libraries(App PRIVATE spdlog::spdlog MyLib)
# Enable testing with CTest (CMake's testing framework)
enable_testing()
# Define the test executable
add_executable(RunTests test/test_calculator.cpp)
# Link our test executable against GTest and our library
target_link_libraries(RunTests PRIVATE GTest::gtest_main MyLib)
# Add the test to CTest
include(GoogleTest)
gtest_add_tests(TARGET RunTests)

View File

@@ -0,0 +1,5 @@
#include "calculator.h"
int Calculator::add(int a, int b) {
return a + b;
}

View File

@@ -0,0 +1,9 @@
#ifndef CALCULATOR_H
#define CALCULATOR_H
class Calculator {
public:
int add(int a, int b);
};
#endif // CALCULATOR_H

View File

@@ -0,0 +1,16 @@
#include <iostream>
#include "spdlog/spdlog.h"
#include "calculator.h"
int main() {
spdlog::info("Hello, Modern C++! Initializing trading strategy...");
Calculator calc;
int result = calc.add(40, 2);
spdlog::info("The result of 40 + 2 is: {}", result);
std::cout << "Check your terminal for spdlog output!" << std::endl;
return 0;
}

View File

@@ -0,0 +1,22 @@
#include <gtest/gtest.h>
#include "../src/calculator.h" // Include the header for the class we are testing
// Test fixture for Calculator class
class CalculatorTest : public ::testing::Test {
protected:
Calculator calc;
};
// Test case for the add method
TEST_F(CalculatorTest, Add) {
EXPECT_EQ(calc.add(2, 2), 4);
EXPECT_EQ(calc.add(-1, 1), 0);
EXPECT_EQ(calc.add(-5, -5), -10);
}
// Another test case for the add method for good measure
TEST_F(CalculatorTest, AddWithZero) {
EXPECT_EQ(calc.add(0, 5), 5);
EXPECT_EQ(calc.add(5, 0), 5);
EXPECT_EQ(calc.add(0, 0), 0);
}

View File

@@ -0,0 +1,173 @@
# Tutorial 1.1: Your First Modern C++ Project
**Objective:** To compile, run, debug, and manage dependencies for a C++ application using the modern, industry-standard toolchain on Linux. This single tutorial covers the entire end-to-end workflow.
---
## 1. Prerequisites: System Setup
First, you need to ensure the necessary base tools are installed. Open your terminal and run the following commands.
```bash
# Update package lists
sudo apt update
# Install compiler (g++), make, git, and other essential build tools
sudo apt install build-essential g++ git cmake curl
```
You will also need **Visual Studio Code**, which you can download from the [official website](https://code.visualstudio.com/).
After installing VSCode, launch it and install these two essential extensions from the Extensions view (Ctrl+Shift+X):
1. `C/C++` (Publisher: Microsoft)
2. `CMake Tools` (Publisher: Microsoft)
## 2. The Game Changer: `vcpkg` Package Manager
In C++ circa 2000, adding a library was a manual ordeal. `vcpkg` automates this. It downloads, builds, and prepares libraries for your project, acting like `pip` for Python.
In your terminal, choose a location for your development tools (e.g., `~/dev/tools`) and clone `vcpkg`:
```bash
# Create a directory for tools if you don't have one
mkdir -p ~/dev/tools
cd ~/dev/tools
# Clone the vcpkg repository
git clone https://github.com/microsoft/vcpkg.git
# Run the bootstrap script to build vcpkg itself
./vcpkg/bootstrap-vcpkg.sh
```
**IMPORTANT:** Note the absolute path to your vcpkg installation. You'll need it later. It will be something like `/home/YOUR_USERNAME/dev/tools/vcpkg`.
## 3. Project Setup
Now, let's create the project.
```bash
# Go to where you keep your code projects
cd ~/code/cplusplus/GeminiTutorial
# Create and enter the project directory
mkdir tutorial-1
cd tutorial-1
```
## 4. Installing a Library
Let's install `spdlog`, a popular and high-performance logging library.
```bash
# Use the vcpkg executable to install the library
# Replace /path/to/vcpkg with your actual vcpkg path
/home/YOUR_USERNAME/dev/tools/vcpkg/vcpkg install spdlog
```
This command will download, compile, and install `spdlog` into your `vcpkg` directory, making it available for any project.
## 5. Writing the Build Script (`CMakeLists.txt`)
This file tells `CMake` how to build your project. Create a file named `CMakeLists.txt` inside the `tutorial-1` directory with the following content.
```cmake
# Specifies the minimum version of CMake required.
cmake_minimum_required(VERSION 3.15)
# Defines the project name and sets C++ as the language.
project(Tutorial1 LANGUAGES CXX)
# Set the C++ standard to C++17. Modern C++ starts with C++11.
# C++17 is a great, stable choice.
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Find the spdlog library.
# CMake needs to be told how to find packages installed by vcpkg.
# We will do this in the VSCode settings in the next step.
# 'CONFIG REQUIRED' means it's a fatal error if the package isn't found.
find_package(spdlog CONFIG REQUIRED)
# Define our executable target, named 'App', from the source file 'main.cpp'.
add_executable(App main.cpp)
# Link our App against the spdlog library.
# This tells the compiler to include the necessary spdlog files when building App.
target_link_libraries(App PRIVATE spdlog::spdlog)
```
## 6. Writing the C++ Code (`main.cpp`)
Create a file named `main.cpp` in the `tutorial-1` directory.
```cpp
#include <iostream>
// Include the main header from the spdlog library.
#include "spdlog/spdlog.h"
int main() {
// Use the library to print an informational message.
// This is much more powerful than std::cout for real applications,
// as it can be configured to log to files, rotate logs, filter by level, etc.
spdlog::info("Hello, Modern C++! Initializing trading strategy...");
int x = 42;
double price = 102.5;
// spdlog supports formatted output similar to Python's f-strings.
spdlog::warn("A variable 'x' has value: {}", x);
spdlog::critical("Critical event! Price is: {}", price);
std::cout << "Check your terminal for spdlog output!" << std::endl;
return 0;
}
```
## 7. Building and Debugging in VSCode
This is where all the pieces come together.
1. **Open the Project:** Launch VSCode and open the `tutorial-1` folder (`File > Open Folder...`).
2. **Configure CMake:**
* The CMake Tools extension will activate. You may see a prompt asking to configure the project.
* **This will fail initially!** This is expected. An error will appear saying `Could not find a package configuration file for "spdlog"`.
* **Here is the fix:** We must tell CMake where to find `vcpkg`-installed libraries.
* Open the VSCode settings: `File > Preferences > Settings` (or `Ctrl+,`).
* Click the "Workspace" tab. Search for `cmake.configureArgs`.
* Click "Edit in settings.json".
* Add the following entry, **replacing the path with the actual absolute path to your vcpkg directory**:
```json
{
"cmake.configureArgs": [
"-DCMAKE_TOOLCHAIN_FILE=/home/YOUR_USERNAME/dev/tools/vcpkg/scripts/buildsystems/vcpkg.cmake"
]
}
```
* Save `settings.json`. A new `.vscode` directory will be created in your project folder to store this setting.
3. **Build the Project:**
* Run the `CMake: Configure` command from the command palette (Ctrl+Shift+P). It should now succeed.
* The status bar at the bottom of VSCode now shows buttons for building. Click the **`Build`** button.
* You'll see output in the terminal as CMake and the compiler build your `App` executable.
4. **Run and Debug:**
* **Run:** The "play" button in the status bar will run the executable. You'll see the `spdlog` output in the VSCode terminal.
* **Debug:**
1. Open `main.cpp`.
2. Click in the gutter to the left of the line number for `int x = 42;` to set a **breakpoint** (a red dot will appear).
3. Press **F5** (or click the "bug" icon next to the play button).
4. Execution will start and then **stop** at your breakpoint.
5. You can now inspect variables in the "Run and Debug" side panel and use the controls to step through the code (F10, F11).
---
**Congratulations!** You have successfully set up a modern C++ development environment, managed an external dependency, and used the integrated build/debug tools. This workflow is the foundation for all subsequent tutorials.
# 8 Feedback
There is a dependency on gdb debugger that was not mentioned. after building and installing everything works as expected

View File

@@ -0,0 +1,201 @@
# Tutorial 1.2: Introduction to Unit Testing
**Objective:** To introduce unit testing to the C++ project from Tutorial 1.1. This tutorial will cover adding a testing framework (`googletest`), creating a simple class, writing tests for that class, and integrating the tests into the CMake build system for easy execution within VSCode.
---
## 1. Prerequisites
* A completed and working project from "Tutorial 1.1: Your First Modern C++ Project".
* `vcpkg` installed and configured as per Tutorial 1.1.
---
## 2. Installing the Testing Framework
We will use `googletest`, a popular and powerful testing framework for C++.
Just like with `spdlog`, we use `vcpkg` to install it.
```bash
# Use the vcpkg executable to install the library
# Replace /path/to/vcpkg with your actual vcpkg path
/home/YOUR_USERNAME/dev/tools/vcpkg/vcpkg install gtest
```
*Note: The package name is `gtest` for `googletest`.*
---
## 3. Refactoring the Project Structure
To keep our project organized, we'll separate our main application code from the test code. The new structure inside `tutorial-1` will look like this:
```
tutorial-1/
├── CMakeLists.txt
├── src/
│ ├── calculator.h
│ ├── calculator.cpp
│ └── main.cpp
└── test/
└── test_calculator.cpp
```
The previous steps in this session have already created this structure for you.
---
## 4. Creating a Class to Test
We need some logic to test. We've created a simple `Calculator` class.
**File:** `tutorial-1/src/calculator.h`
```cpp
#ifndef CALCULATOR_H
#define CALCULATOR_H
class Calculator {
public:
int add(int a, int b);
};
#endif // CALCULATOR_H
```
**File:** `tutorial-1/src/calculator.cpp`
```cpp
#include "calculator.h"
int Calculator::add(int a, int b) {
return a + b;
}
```
We also updated `main.cpp` to use this new class.
**File:** `tutorial-1/src/main.cpp` (Updated)
```cpp
#include <iostream>
#include "spdlog/spdlog.h"
#include "calculator.h"
int main() {
spdlog::info("Hello, Modern C++! Initializing trading strategy...");
Calculator calc;
int result = calc.add(40, 2);
spdlog::info("The result of 40 + 2 is: {}", result);
std::cout << "Check your terminal for spdlog output!" << std::endl;
return 0;
}
```
---
## 5. Writing the Unit Tests
Now, we'll write our first test in the `test` directory.
**File:** `tutorial-1/test/test_calculator.cpp`
```cpp
#include <gtest/gtest.h>
#include "../src/calculator.h" // Include the header for the class we are testing
// Test fixture for Calculator class
class CalculatorTest : public ::testing::Test {
protected:
Calculator calc;
};
// Test case for the add method
TEST_F(CalculatorTest, Add) {
EXPECT_EQ(calc.add(2, 2), 4);
EXPECT_EQ(calc.add(-1, 1), 0);
EXPECT_EQ(calc.add(-5, -5), -10);
}
// Another test case for the add method for good measure
TEST_F(CalculatorTest, AddWithZero) {
EXPECT_EQ(calc.add(0, 5), 5);
EXPECT_EQ(calc.add(5, 0), 5);
EXPECT_EQ(calc.add(0, 0), 0);
}
```
---
## 6. Updating the Build System (CMake)
This is the most critical part. We have updated our `CMakeLists.txt` to build both our main application and our tests as separate executables.
**File:** `tutorial-1/CMakeLists.txt` (Updated)
```cmake
cmake_minimum_required(VERSION 3.15)
project(Tutorial1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Find dependencies
find_package(spdlog CONFIG REQUIRED)
find_package(GTest CONFIG REQUIRED)
# Create a library for our application code
# This allows us to share the code between the main app and the tests
add_library(MyLib src/calculator.cpp src/calculator.h)
target_include_directories(MyLib PUBLIC src)
# Define our main executable
add_executable(App src/main.cpp)
# Link our App against spdlog and our library
target_link_libraries(App PRIVATE spdlog::spdlog MyLib)
# Enable testing with CTest (CMake's testing framework)
enable_testing()
# Define the test executable
add_executable(RunTests test/test_calculator.cpp)
# Link our test executable against GTest and our library
target_link_libraries(RunTests PRIVATE GTest::GTest GTest::Main MyLib)
# Add the test to CTest
include(GoogleTest)
gtest_add_tests(TARGET RunTests)
```
---
## 7. Building and Running Tests in VSCode
1. **Install `gtest`:** Make sure you have installed `gtest` using `vcpkg` as described in step 2.
2. **Configure CMake:** Run `CMake: Configure` from the command palette (Ctrl+Shift+P). It should detect the changes and find `gtest`.
3. **Build:** Click the **Build** button in the status bar. This will now build `App` and `RunTests`.
4. **Run Tests:** The "CMake Tools" extension provides a "Test Explorer" view in VSCode.
* Open the Test Explorer from the side bar (the icon looks like a beaker).
* You should see your test suite (`CalculatorTest`) and the individual tests.
* Click the "play" button at the top of the Test Explorer to run all tests.
* You can also run individual tests. The results will be shown directly in the UI.
---
**Congratulations!** You have now added unit testing to your project. This is a crucial skill for writing robust and maintainable C++ applications. You've learned how to:
* Add a testing library (`googletest`) with `vcpkg`.
* Structure your project to separate app code from test code.
* Create a shared library and multiple executables with CMake.
* Write and run unit tests using the VSCode Test Explorer.
## Feedback and Questions
1. The line ```target_link_libraries(RunTests PRIVATE GTest::GTest GTest::Main MyLib)``` caused cmake compilation error, I changed to
```target_link_libraries(RunTests PRIVATE GTest::gtest_main MyLib)```
I looked up documentation for this.
2. Are there alternative ways to install dependencies other the through vcpkg? For example would FetchContent work (https://cmake.org/cmake/help/latest/module/FetchContent.html)?
3.Interestingly, in vscode, the line ```#include <gtest/gtest.h>``` i was curious where the files as located - as i had not specified where it is other the download gtest in a separate process via vcpkg. when in vscode i hovered and clicked on go to definition it went to the location. curious how vscode knows this information.
4.I was interested to debug unit tests individually and managed to do this by following https://github.com/microsoft/vscode-cmake-tools/blob/main/docs/debug-launch.md#debugging-tests