The C++ Build Process - A Beginner's Guide to LLVM/Clang
Monday, April 5, 2021
Preamble If you’re a beginner and started to learn C++ very recently, read the chapters Preprocessor, Compiler, Linker, and Conclusions first. For the most part, all definitions and explanations in these chapters are compiler-independent. Come back to this document later after you moved on from writing terminal applications exclusively. The remaining chapters provide additional information by example of LLVM/Clang. See also the Appendix and Bibliography for further reading. Introduction For many developers who have primarily worked with interpreted languages such as Python or JavaScript in the past, learning C++ may seem like a daunting task at first: There’re many moving parts between your hello_world.…more
Series 101-2 Development Environment
Tuesday, March 30, 2021
C++ compilers support being passed various flags to control a multitude of options. One such flag determines whether the compiler embeds debugging symbols into/alongside the binary builds, which generates mappings between source code and line numbers that are used by debuggers to set breakpoints, watch variables, modify registers/memory, etc. Most build systems (Make, Ninja, MSBuild, Xcode, etc) group a collection of these options and flags into a build configuration, and most multi-generator build systems (MSBuild, Xcode) provide a handful of built-in defaults (Debug, Release).…more
Series 101-1 Getting Started
Tuesday, March 23, 2021
C++ is a statically typed application/library programming language, where the source code is compiled (and linked) into a native binary for a particular target platform, like x64, ARMv8, etc (and usually also operating system, like Windows, GNU/Linux, Android, etc). The C++ standard only specifies the rules of the language and its behaviour on an abstract machine, and the standard library‘s interface; compilers like Microsoft VC++, LLVM Clang, GCC, Apple C++ (and others) implement the standard and translate the source to actual platform instructions, and also provide the corresponding implementation of the standard library.…more
Debugging
Friday, April 24, 2020
Debugging Symbols When invoking a C++ compiler, several options/flags can be passed, including optimisation level, pre-processor defines, and whether to include debugging symbols in the binary. These symbols are effectively mappings between binary addresses and source code (file, line number, symbol name, etc), which a compatible debugger can use. Including debugging symbols dramatically increases the size of the resulting binary, often by orders of magnitude. A debugger (given an executable with debugging symbols) offers many useful features, such as stepping through code one line at a time, setting breakpoints, watching variables, changing values stored in memory, the entire call stack (when broken), etc.…more
Topics Outline
Wednesday, February 26, 2020
Pre-3D Topics Environment Setup CMake basics Dealing with paths - preprocessor vs working directory vs runtime directory, relative vs absolute Limiting symbols in global scope (everything is global by default) Debugging basics: embedding symbols, using breakpoints, watching variables, changing memory, etc Enabling useful compiler warnings I/O, OS, code scope Generic types vs fixed-size types Manual memory management IO and type conversions: <iostream>, std::getline, std::string/std::string_view, std::atoi, etc Containers: std::stringstream, std::vector, std::unordered_map, std::unordered_set, std::list, std::deque, std::bitset Files: <fstream>, std::filesystem Random generation: <random> Function templates Advanced C++…more
Memory Management
Tuesday, February 25, 2020
C++ Memory Model Unlike higher level languages, the programmer is responsible for all memory management in C/C++. Automatic/stack-allocated memory is automatically cleaned up when it goes out of scope (hence automatic storage duration) and should always be preferred, even for managing heap memory (smart pointers). This is the basis of RAII. A definition like char x = 'a'; will result in the compiler storing enough space (1 byte) to hold one char.…more
Primitive Data Types
Monday, February 24, 2020
Primitive Data Types C/C++ being rather old languages, the width of types like int, long, etc have changed over time, from 16 bit CPUs to 32 bit and now 64 bit ones. This enables programs using such types to be generic and largely usable on all these target CPU architectures (potentially even ones in the future). The only generic type that has a guaranteed size is char (1 signed/unsigned byte on all modern platforms) - this is also a reason why files are read as arrays of chars (bytes).…more
February Challenges
Saturday, February 1, 2020
Number of words in a string Mini exercise: count the number of words in a string. bonus points: count the number of characters in each word Note: you can do both in one pass Short Exercise: Create a function to “bisect” a string given a delimiter: "id=fubar", '=' should return id and fubar. Prototype: std::pair<std::string, std::string> bisect(std::string_view str, char delim); pair can be found in <utility>. string_view instead of string const& allows for use of string literals / C strings without suffering a pointless string allocation.…more