initial commit
This commit is contained in:
6
cplusplus/geminitutorial/tutorial1/.vscode/settings.json
vendored
Normal file
6
cplusplus/geminitutorial/tutorial1/.vscode/settings.json
vendored
Normal 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"
|
||||
]
|
||||
}
|
||||
33
cplusplus/geminitutorial/tutorial1/CMakeLists.txt
Normal file
33
cplusplus/geminitutorial/tutorial1/CMakeLists.txt
Normal 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)
|
||||
5
cplusplus/geminitutorial/tutorial1/src/calculator.cpp
Normal file
5
cplusplus/geminitutorial/tutorial1/src/calculator.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "calculator.h"
|
||||
|
||||
int Calculator::add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
9
cplusplus/geminitutorial/tutorial1/src/calculator.h
Normal file
9
cplusplus/geminitutorial/tutorial1/src/calculator.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef CALCULATOR_H
|
||||
#define CALCULATOR_H
|
||||
|
||||
class Calculator {
|
||||
public:
|
||||
int add(int a, int b);
|
||||
};
|
||||
|
||||
#endif // CALCULATOR_H
|
||||
16
cplusplus/geminitutorial/tutorial1/src/main.cpp
Normal file
16
cplusplus/geminitutorial/tutorial1/src/main.cpp
Normal 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;
|
||||
}
|
||||
22
cplusplus/geminitutorial/tutorial1/test/test_calculator.cpp
Normal file
22
cplusplus/geminitutorial/tutorial1/test/test_calculator.cpp
Normal 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);
|
||||
}
|
||||
173
cplusplus/geminitutorial/tutorial1/tutorial-part1-1.md
Normal file
173
cplusplus/geminitutorial/tutorial1/tutorial-part1-1.md
Normal 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
|
||||
201
cplusplus/geminitutorial/tutorial1/tutorial-part1-2.md
Normal file
201
cplusplus/geminitutorial/tutorial1/tutorial-part1-2.md
Normal 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
|
||||
Reference in New Issue
Block a user