Table of Contents
Motivation
Nachdem ich mich in den letzten Wochen wieder vermehrt mit modernem C++ beschäftigt habe, möchte ich auch sicherstellen, dass mein Code maximal davon profitiert. Ein Aspekt davon ist es, möglichst sauberes C++ durch den Compiler zu erzwingen. Das geht am besten durch Compiler-Optionen.
Was sind Compiler-Optionen?
Compiler-Optionen oder auch Flags sind unverzichtbare Werkzeuge, um C++-Programme effizient, sicher und standard-konform zu erstellen. Sie ermöglichen die gezielte Steuerung des Kompilierungsprozesses – etwa durch die Auswahl des C++-Standards, die Aktivierung von Optimierungen oder die Kontrolle über Warnungen und Fehler.
Besonders in größeren Projekten helfen Flags typische Programmierfehler frühzeitig zu erkennen und die Codequalität langfristig zu sichern.
Ohne bewusst gesetzte Compiler-Optionen bleiben potenziell gefährliche Probleme oft unbemerkt, was sich negativ auf Wartbarkeit, Portabilität und Laufzeitverhalten auswirken kann.
Nachdem wir in Wie setze ich die C++ Version in CMake schon mal via Compiler-Option die C++-Version gesetzt haben, kümmern wir uns heute um weitere Optionen.
Wie füge ich Compiler-Optionen in CMake hinzu?
Mit dem Kommando add_compile_options kannst Du die Flags setzen:
add_compile_options(-W<option_name>)
Beispiel
add_compile_options(-Wall)
Die Optionen im Detail
Die folgenden Option gelten für GCC und Clang.
-Wall
-Wall heißt nicht „alle Warnungen“, sondern: „Viele sinnvolle Standardwarnungen, die dich vor typischen Fehlern bewahren“
-Wall erkennt zum Beispiel ungenutzte Variablen oder den beliebten Fehler Zuweisung statt Vergleichsoperator
Beispiel unused variable
warning: unused variable 'x' [-Wunused-variable]
38 | int x = 42;
| ^
Beispiel Zuweisungs- statt Vergleichsoperator
if (x = 5)
{
std::cout << x << '\n';
}
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
39 | if (x = 5) {
| ~~^~~
-Wextra
-Wextra kann zum Beispiel ungenutzte Parameter bei Funktionsaufrufen erkennen:
void unsused_param(std::string name)
{
std::cout << "unsused_param" << '\n';
}
warning: unused parameter 'name' [-Wunused-parameter]
35 | void unsused_param(std::string name)
| ~~~~~~~~~~~~^~~~
-Wpedantic
Aktiviert Warnungen für alles, was gegen den offiziellen C++-Standard verstößt.
Selbst wenn es der Compiler akzeptieren würde, wird eine Warnung ausgegeben.
Ein gutes Beispiel sind VLAs:
int len = 3;
int vla[len];
warning: ISO C++ forbids variable length array 'vla' [-Wvla]
52 | int vla[len];
| ^~~
-Wconversion
-Wconversion warnt bei impliziten Typumwandlungen, bei denen potenziell Informationen verloren gehen könnten – insbesondere bei „narrowing conversions“.
int z = 1.2;
std::cout << z << '\n';
warning: conversion from 'double' to 'int' changes value from '1.2e+0' to '1' [-Wfloat-conversion]
49 | int z = 1.2;
| ^~~
-Werror
Macht aus Warnungen Fehler und führt zum Build-Abbruch. Das ist nicht immer gewollt, deswegen kann man es beispielsweise nur für den Release-Build aktivieren:
if(CMAKE_BUILD_TYPE STREQUAL "Release")
add_compile_options(-Werror)
endif()
Beim Aufruf von CMake muss dann das folgende Flag an CMake übergeben werden:
-DCMAKE_BUILD_TYPE=Release
tl;dr;
Am besten setzt ihr zum Ausprobieren -Wall, -Wextra und -Wpedantic.