Compile and Check C and C++ with clang-20
You will use the installed clang-20 driver to check a source file, produce an object file, and link a runnable program. The same workflow also shows where assembly, debug information and preprocessor output fit. Allow about 10 minutes for the first run. You need the clang-20 package, a shell, and a writable working directory; none of the commands below needs elevated privileges.
The route
Jump straight to the step you need, or tick off Done means at the end.
Checkpoint: confirm the compiler
Check that the command resolves to Clang 20.
clang-20 --version dpkg-query -W -f='${Package} ${Version}\n' clang-20
On the machine described by this guide, the installed package is clang-20 version 1:20.1.8~++20250804090239+87f0227cb601-1~exp1~20250804210352.139. The compiler identifies itself as Clang 20.1.8 and targets x86_64-pc-linux-gnu. Package versions and the target can differ on another machine, so keep this check with build notes when reproducibility matters.
Checkpoint: check source without creating a program
Create a small C source file in a scratch directory.
mkdir -p "$HOME/clang-20-example" cd "$HOME/clang-20-example" cat > hello.c <<'EOF' #include <stdio.h> int main(void) { puts("hello from clang"); return 0; } EOFRun only preprocessing, parsing and semantic analysis.
clang-20 -std=c17 -Wall -Wextra -fsyntax-only hello.c
A successful check prints nothing and returns status 0. -fsyntax-only does not write an object or executable. -Wall -Wextra enables useful warning groups, but warnings are still not failures unless you add -Werror. If Clang reports a source location and an error, fix that diagnostic before moving on. A frequent distraction is a missing header: check the include path and the selected language before changing unrelated flags.
Checkpoint: build an executable
Compile and link in one command, naming the output explicitly.
clang-20 -std=c17 -Wall -Wextra -O0 -g hello.c -o hello ./hello
The expected program output is:
hello from clang
With no stage-selection option, the driver compiles the source, assembles the result and invokes the linker. -o hello avoids the less helpful default output name a.out. The -g option adds debug information, and -O0 keeps optimisation off, which makes source-level debugging easier. Neither option makes a program safe or correct; they only change the generated artefact and its diagnostics.
Use the stages separately when diagnosing a build
Produce an object file without linking.
clang-20 -std=c17 -Wall -Wextra -c hello.c -o hello.o file hello.oLink that object file into a new executable.
clang-20 hello.o -o hello-from-object ./hello-from-objectInspect the generated assembly when code generation itself is the question.
clang-20 -std=c17 -O0 -S hello.c -o hello.s sed -n '1,40p' hello.s
The stages are deliberately cumulative: -E stops after preprocessing, -fsyntax-only stops after semantic analysis, -S emits assembly, and -c emits an object file. Do not confuse a successful -fsyntax-only check with a successful link: missing libraries and duplicate symbols appear later.
Build a C++ file with an explicit standard
Choose the C++ standard and invoke the same driver.
cat > hello.cpp <<'EOF' #include <iostream> int main() { std::cout << "hello from C++\n"; } EOF clang-20 -std=c++20 -Wall -Wextra -O0 -g hello.cpp -o hello-cpp ./hello-cpp
The installed manpage says the default C++ mode is gnu++17. An explicit -std=c++20 makes this build independent of that default and disables GNU language extensions for the selected standard. Use -std=gnu++20 when the source intentionally depends on GNU extensions. The available standard-library choice is platform-dependent; -stdlib=libstdc++ and -stdlib=libc++ are the documented choices when both are installed.
Inspect a failing or surprising command
Ask the driver to show the commands it would run without running them.
clang-20 -### -std=c17 -Wall hello.c -o helloShow include and linker search paths when a dependency cannot be found.
clang-20 -v -print-search-dirs
-### is useful for seeing the assembler and linker stages without changing files. -v prints the tools and paths used during a real invocation. Keep the output when reporting a build problem: it records the selected target and toolchain assumptions. Avoid copying a -Wl, or -Xlinker argument from another machine without checking its linker and target first.
Common traps and safe recovery
- Wrong input language: use a meaningful suffix such as
.cor.cpp. For generated or extensionless input, select it explicitly with-x cor-x c++; the setting applies to subsequent input files. - Unexpected include files:
-I/pathadds an include directory, whileCPATHand language-specific include-path environment variables also affect lookup. Check them when a build works in one shell but not another. - Overwriting an existing output:
-o helloreplaces that path. Before using it in a script, confirm it is the intended file. To undo this guide's changes, remove only the scratch directory withrm -rf -- "$HOME/clang-20-example"after checking its contents; that removal is irreversible and must not be pointed at a directory containing other work. - Optimisation assumptions:
-O3can produce larger code and take longer than-O2. The manpage marks-Ofastas deprecated in Clang 19 because it can enable behaviour that violates strict language standards; use an explicit, justified fast floating-point setting only when its changed rules are acceptable.
Done means
clang-20 --versionreports the expected installed compiler.-fsyntax-onlychecks the source without producing a binary.-cproduces an object and a separate link command produces the executable.- The executable runs and prints the expected line.
- The selected language standard, warning level, optimisation level and output path are explicit.