C++, Zero to Hello World
From empty project to Hello World in two days
2023/02
C++ with Asio
I spent a couple minutes searching the interwebs for a C++ web library and quickly found Asio and Oat++. I had podcast familiarity with Asio from the Boost project and the Networking TS. Asio is lower level than Beast, which would have been closer to the D, Go, and Rust tests, but after looking at examples from both, Asio looked easier to understand in a short amount of time. If I had to do this again, I would pick Oat++.
After downloading the C++20 Coroutine echo_server example I started looking for how to setup a C++ project.
To back up and give a little context, this series of tests was spurred while working through Professional C++, 5th Ed., by Marc Gregoire. Getting started on Windows with Visual Studio was too easy, so I tried doing the same on linux (my daily driver), but oof! The main problem is I don’t know CMake, and Makefiles only go so far. While I have nothing against C++ as a language, the tooling is not great.
I started with a search, c++ cmake hello world
. The first result was from Microsoft for VSCode C/C++
and CMake Tools
extensions. However, I am using Codium and these extensions are not available. I’m not tied to Codium for any philosophical reasons, it’s just what I have installed. The VSCode snap had some now forgotten limitation that Codium did not have. Let’s look for something else and come back to this if we have to.
There were several suggestions to just use CLion. I dabbled with the IntelliJ IDEA IDE with the Rust plugin, but it kept stalling and crashing. I could install the CLion 60 day trial, but realistically I would probably only use seven of those days. Right now I feel like I’m not corporate or professional enough to use C++.
Finally, I found an example project, cmake-vcpkg-example. I also read the first three chapters of Modern CMake for C++, by RafaΕ ΕwidziΕski. Okay, we go.
$ mkdir cppasio-test
$ cd cppasio-test
$ mkdir build
$ mkdir src
$ touch src/main.cpp
$ touch src/CMakeLists.txt
$ touch CMakeLists.txt
$ touch vcpkg.json
Project layout so far.
cppasio_test/
βββ build
βββ src
β ββ main.cpp
β ββ CMakeLists.txt
βββ CMakeLists.txt
βββ vcpkg.json
// main.cpp
#include <iostream>
int main() {
std::cout << "Hello World!";
return 0;
}
vcpkg.json
{
"name": "cppasio-test",
"version-string": "0.1.0",
"dependencies": [
"asio"
]
}
# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake CACHE STRING "Vcpkg toolchain file")
project(cppasio-test VERSION 0.1)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# from recommendation after vcpkg install
find_package(asio CONFIG REQUIRED)
add_subdirectory(src)
# src/CMakeLists.txt
add_executable(cppasio-test main.cpp)
# from recommendation after vcpkg install
target_link_libraries(cppasio-test PRIVATE asio::asio)
Install vcpkg into the project directory.
$ git clone https://github.com/Microsoft/vcpkg.git
$ ./vcpkg/bootstrap-vcpkg.sh -disableMetrics
$ ./vcpkg/vcpkg install
-> # this is heuristically generated, and may not be correct
find_package(asio CONFIG REQUIRED)
target_link_libraries(main PRIVATE asio::asio)
$ cd build
$ cmake ..
$ cmake --build .
$ ./cppasio-test
-> Hello World!
I added a .old
extension to main.cpp
and created a new file with the Asio C++20 echo server example.
$ cd build
$ rm -rf *
$ cmake ..
$ cmake --build .
$ ./src/cppasio-test
-> [blank line]
$ telnet 127.0.0.1 55555
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
asio hello world
-> asio hello world
Finally, after four hours across two days, I made a thing. The resulting executable is only 638K in size; however, it isn’t comparable in function to the other tests.
Let’s use this new knowledge to try a more comparable example with Oat++.
$ # overall project directory
$ cp -r cppasio_test cppoat_test
$ cd cppoat_test
$ rm -rf build/*
Change vcpkg.json
{
"name": "cppasio-test",
"version-string": "0.1.0",
"dependencies": [
"oatpp"
]
}
Install the dependencies.
$ ./vcpgk/vcpkg install
-> # this is heuristically generated, and may not be correct
find_package(oatpp CONFIG REQUIRED)
target_link_libraries(main PRIVATE oatpp::oatpp oatpp::oatpp-test)
Modify CMakeList.txt files and replace cppasio-test
with cppoat-test
.
After going through the Oat++ site, I realized that I chose wrong the first time. In the Oat++ docs there is the Simplest Project and a starter repo. I pulled the Simplest Project code and replaced the contents of main.cpp
. Attempted to build, and got a warning that main is not a target for this project and realized I forgot to change the project name when I copy/pasted into CMakeLists.txt from main to cppoat-test.
$ cd build
$ cmake ..
$ cmake --build .
$ ./src/cppoat-test - 9.7M executable
-> MyApp:Server running on port 8000
$ curl localhost:8000/hello
-> Hello World!
Start to finish this time was about 30 minutes, including writing these notes.
Again, I like C++ as a language, especially C++17/20, but between me and Modern C++ is Visual Studio, CMake, Meson, Ninja, vcpkg, Conan, Bezel, build2, etc. From empty project to writing code, if you don’t have build system knowledge or a budget for books and IDEs, Go and Rust are far easier to invest in. I’m almost $100 into a C++ and CMake book. Could I have just bought CLion instead and ignored learning a smidgen of CMake? I’d still be out at least one year of subscription costs and $65 for the C++ book.
To Asio and Oat++’s credit, both seem to be dependency free. Asio lists three optional dependencies, Boost.Coroutine, Boost.Regix, and OpenSSL; while Oat++ states it’s a zero-dependency framework.