Type g++ on Ubuntu and you are trusting an alias to point at the right compiler. This walkthrough uses the versioned x86_64-linux-gnu-g++-13 driver directly: check its syntax, build an object file, then link and run a real executable.
Allow about fifteen minutes. You need a shell, the installed g++-13-x86-64-linux-gnu package, and a writable working directory. These examples do not need sudo.
Warning: Do not compile source you do not trust. Compilation can run build hooks or produce a program that does something harmful when you execute it.
The aliases c++, g++, g++-13, x86_64-linux-gnu-g++ and x86_64-linux-gnu-g++-13 all point at this compiler family here, but an alias can be redirected by system configuration. Check the exact binary and version before you trust it:
$ command -v x86_64-linux-gnu-g++-13
/usr/bin/x86_64-linux-gnu-g++-13
$ x86_64-linux-gnu-g++-13 --version
x86_64-linux-gnu-g++-13 (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
The installed manual is the GCC 13 manual dated 4 September 2024. GCC normally preprocesses, compiles, assembles and links in one invocation; options such as -c, -S and -E stop it at earlier stages.
Checkpoint: If command -v prints nothing, stop here. The compiler package is missing or the executable is not on your PATH; installing a package or changing PATH is an administrative decision outside this example.
Make a new file in your own project directory. The program has one standard-library include and returns a visible result:
$ mkdir -p ~/tmp/gpp-13-check
$ cd ~/tmp/gpp-13-check
$ editor hello.cpp
Put this in hello.cpp and save it:
#include <iostream>
int main() {
std::cout << "g++-13-ok\n";
}
If you prefer a shell-only way to create a disposable test file, use a quoted here-document so the shell does not expand the source while writing it:
$ cat > hello.cpp <<'CPP'
#include <iostream>
int main() {
std::cout << "g++-13-ok\n";
}
CPP
Run the compiler with an explicit language standard and warnings turned up. -fsyntax-only checks the source but produces no object file or executable:
$ x86_64-linux-gnu-g++-13 -std=c++20 -Wall -Wextra -pedantic -fsyntax-only hello.cpp
-std=c++20 selects the dialect; it does not turn on warnings.-Wall, -Wextra and -pedantic ask for diagnostics, but they do not make every possible defect impossible.Checkpoint: If you see a diagnostic with a source line and a caret, fix the first error, then run the same command again. Later diagnostics can just be consequences of that first problem.
Use -c when compiling one source file as part of a larger build. It runs preprocessing, compilation and assembly, but deliberately skips the linker:
$ x86_64-linux-gnu-g++-13 -std=c++20 -Wall -Wextra -pedantic -c hello.cpp -o hello.o
$ file hello.o
hello.o: ELF 64-bit relocatable, x86-64, version 1 (SYSV), not stripped
-o names the output; without it, GCC picks a default derived from the input, handy for quick experiments but less clear in scripts. An object file is not directly runnable, because references to the C++ standard library and other components still need resolving.
Omit -c to let the C++ driver link the program, and keep the output name explicit:
$ x86_64-linux-gnu-g++-13 -std=c++20 -Wall -Wextra -pedantic -g -O0 hello.cpp -o hello
$ ./hello
g++-13-ok
$ printf 'exit status: %s\n' "$?"
exit status: 0
-g adds debugging information and -O0 disables optimisation, which makes a first debugging session easier to follow. These flags shape the generated program; they are not a substitute for tests. With multiple source files, compile each with -c, then pass all the resulting .o files to one final driver invocation.
Safety warning: -o hello replaces an existing file named hello. A failed compile normally leaves the old output untouched, but redirection and build scripts can still truncate files. Use a new output name when preserving an existing executable matters, then replace it deliberately once the test passes.
-I/path/to/include; do not fix it by copying headers into system directories.-l matters.-Werror for that build or CI job, deliberately, because a new compiler warning can then stop an otherwise successful build.command -v and --version. Do not infer the version from the executable name alone.For a link investigation, -### prints the commands GCC would run without executing them. Useful for checking the selected target and libraries, but it can expose paths and build details in logs:
$ x86_64-linux-gnu-g++-13 -### -std=c++20 hello.cpp -o hello 2>&1 | sed -n '1,12p'
Using built-in specs.
COLLECT_GCC=x86_64-linux-gnu-g++-13
Target: x86_64-linux-gnu
--version reports the intended GCC 13 driver.-fsyntax-only completes with no diagnostic for your source.-c produces the expected .o file.