Getting started on Windows? See WINDOWS_GETTING_STARTED.md — tool installation, build, tests, and VS Code setup in one place.
IDE Support: This project is configured for Visual Studio Code and works on Windows, macOS, and Linux. See VSCODE_SETUP.md for advanced features.
Minimal system-level tools only — no package managers or virtual environments needed. All C++ library dependencies (GoogleTest, spdlog, CLI11, nlohmann/json, tl-expected) are automatically fetched at build time via CMake FetchContent.
- CMake 3.20 or later
- C++ Compiler with C++20 support:
- Windows: GCC 11+ (via MinGW) — install with
choco install mingw - macOS: GCC 11+ or Clang 14+ (via Homebrew)
- Linux: GCC 11+ or Clang 14+
- Windows: GCC 11+ (via MinGW) — install with
- libcurl development library
Windows
REM First-time setup (as Administrator):
scripts\setup-windows.bat
REM Or manually:
choco install cmake mingw curlmacOS (Homebrew)
brew install cmake curlUbuntu/Debian
sudo apt-get install build-essential cmake libcurl4-openssl-dev- clang-format: Code formatting
- clang-tidy: Static analysis
- valgrind: Memory leak detection (Linux only)
macOS
brew install clang-formatUbuntu/Debian
sudo apt-get install clang-format clang-tidy valgrindA modern C++20 command-line application that fetches and displays current weather for any city using the OpenMeteo API. Run it from the terminal to get temperature (Celsius or Fahrenheit), humidity, wind speed, and weather description.
REM Install tools (one-time, as Administrator):
scripts\setup-windows.bat
REM Build:
mingw32-make build
REM Run:
build\weather_cli.exe London# Install tools
brew install cmake curl # macOS
sudo apt-get install cmake libcurl4-openssl-dev # Ubuntu/Debian
# Build
make build
# Run
./build/weather_cli LondonThe project uses a cross-platform Makefile as the primary build entrypoint.
| Command | Windows | macOS/Linux | What it does |
|---|---|---|---|
| Build (debug) | mingw32-make build |
make build |
Compile with debug symbols |
| Release | mingw32-make release |
make release |
Optimised release build |
| Tests | mingw32-make test |
make test |
Build and run all unit tests |
| Run | mingw32-make run CITY=Paris |
make run CITY=Paris |
Build and run for a city |
| Clean | mingw32-make clean |
make clean |
Delete build/ directory |
Executable location (all platforms): build/weather_cli (Windows: build\weather_cli.exe)
# Configure
cmake -B build -DCMAKE_BUILD_TYPE=Debug # macOS/Linux
cmake -B build -G "Unix Makefiles" -DCMAKE_CXX_COMPILER=g++ -DCMAKE_MAKE_PROGRAM=mingw32-make -DCMAKE_BUILD_TYPE=Debug # Windows
# Build
cmake --build build -jREM Windows
build\weather_cli.exe London
build\weather_cli.exe "New York" --fahrenheit
build\weather_cli.exe Tokyo --extended
build\weather_cli.exe --help# macOS/Linux
./build/weather_cli London
./build/weather_cli "New York" --fahrenheit
./build/weather_cli Tokyo --extended
./build/weather_cli --helpUsage: weather_cli [OPTIONS] city
Arguments:
city TEXT REQUIRED Name of the city to get weather for
Options:
-h,--help Print this help message
-v,--version Show version
-d,--debug Enable debug logging
-f,--fahrenheit Show temperature in Fahrenheit
-j,--json Output as JSON
-e,--extended Show extended weather information
Supported cities: Any city in the world. The CLI uses OpenMeteo geocoding to resolve city names to coordinates.
No API key required. Uses the OpenMeteo API which is completely free with no registration.
copilot-cpp/
├── .github/
│ ├── copilot-instructions.md # Project AI guidelines
│ ├── agents/ # Custom agent definitions
│ ├── instructions/ # Language/test rules
│ └── prompts/ # Reusable slash commands
├── .vscode/ # VS Code configuration
│ ├── settings.json
│ ├── tasks.json
│ ├── launch.json
│ ├── extensions.json
│ └── c_cpp_properties.json
├── scripts/
│ └── setup-windows.bat # One-time Windows tool installation
├── include/ # Public headers
│ ├── weather_data.h
│ ├── weather_client.h
│ ├── weather_service.h
│ ├── config.h
│ └── exceptions.h
├── src/ # Implementation
│ ├── main.cpp
│ ├── weather_client.cpp
│ ├── weather_service.cpp
│ ├── weather_data.cpp
│ ├── config.cpp
│ └── exceptions.cpp
├── tests/ # Unit tests (GoogleTest)
│ ├── test_main.cpp
│ ├── test_config.cpp
│ ├── test_weather_client.cpp
│ ├── test_weather_service.cpp
│ └── CMakeLists.txt
├── Makefile # Cross-platform build entrypoint
├── CMakeLists.txt # CMake build configuration
├── .clang-format # Code style configuration
├── .gitignore
├── VSCODE_SETUP.md # VS Code setup guide
├── WINDOWS_GETTING_STARTED.md # Windows setup, build, and IDE guide
└── README.md # This file
| Situation | Read This | Time |
|---|---|---|
| Windows, no tools installed | WINDOWS_GETTING_STARTED.md | 5–15 min |
| Want VS Code features | VSCODE_SETUP.md | 10 min |
| Architecture overview | This file — Architecture section | 5 min |
This project includes complete VS Code configuration:
- Auto-configured IntelliSense for C++20
- One-click build with
Ctrl+Shift+B - Integrated debugging with breakpoints (
F5) - CMake integration with auto-configuration
- Test Explorer for running/debugging tests
- Cross-platform support (Windows, macOS, Linux)
Quick start:
- Install recommended extensions: C/C++, CMake Tools, CMake
- Open the project folder in VS Code
- Press
Ctrl+Shift+Bto build - Press
F5to debug
See VSCODE_SETUP.md for the full guide.
make build # macOS/Linux
mingw32-make build # Windows
make test
make run CITY=London| Task | Command |
|---|---|
| Build | make build / mingw32-make build |
| Run tests | make test / mingw32-make test |
| Run app | make run CITY=Tokyo / mingw32-make run CITY=Tokyo |
| Clean | make clean / mingw32-make clean |
| Format code | clang-format -i src/*.cpp include/*.h tests/test_*.cpp |
| Static analysis | clang-tidy src/*.cpp -- -std=c++20 -I include/ |
Uses GoogleTest framework (auto-downloaded via CMake FetchContent). GoogleMock is included for mocking the WeatherClient interface.
make test # macOS/Linux
mingw32-make test # Windows
ctest --test-dir build -V -R ConfigManagerTest # specific test group
./build/tests/weather_cli_tests # binary directly (macOS/Linux)
build\tests\weather_cli_tests.exe # binary directly (Windows)Testing approach:
- Unit testing with GoogleMock — no real HTTP calls
- Error path testing for all
WeatherErrorenum values - Input validation — empty strings, invalid inputs
- Dependency injection —
MockWeatherClientinjected intoWeatherService
- clang-format for formatting, clang-tidy for static analysis
- Maximum line length: 100 characters (configured in
.clang-format) - C++ standard: C++20
- Naming: classes
PascalCase, methodsPascalCase, memberssnake_case_with trailing underscore
3-Layer Architecture:
- Entry Point (
src/main.cpp): CLI argument parsing via CLI11, spdlog logging setup, error handling - Service Layer (
weather_service.h/.cpp): Business logic with dependency injection - Client Layer (
weather_client.h/.cpp): HTTP API abstraction viaWeatherClientabstract class using libcurl - Data Models (
weather_data.h): Immutable data structures with strong typing - Configuration (
config.h/.cpp): Environment-based config management
class WeatherClient { // Abstract
public:
virtual std::expected<WeatherData, WeatherError>
GetWeather(std::string_view city) const = 0;
};auto result = client.GetWeather("London");
if (!result) {
handle_error(result.error());
} else {
use_data(result.value());
}WeatherService service(std::make_unique<MockWeatherClient>());Enables unit testing without real API calls.
- Modern C++20:
std::expected,std::string_view,std::optional, smart pointers - Structured logging with spdlog (
--debugflag) - JSON output (
--jsonflag) - Fahrenheit support (
--fahrenheitflag) - Extended info (
--extendedflag) - No API key: Uses OpenMeteo free API
- API keys never appear in logs (redacted as
"REDACTED") - HTTPS enforced for all API calls
- Input validation on all user-supplied data
- Compiled with
-fstack-protector-strong
Same as main repository