Home / Alt manpages / clang-20(1)

  • clang-20(1)
  • User command
  • linux

Compile and Check C and C++ with clang-20

clang-20 can check, assemble and link a program in one command, or pull those stages apart one at a time. This guide walks through both, so when a build breaks you know exactly which stage did it. 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.

1. 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 your build notes when reproducibility matters.

2. 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;
}
EOF

Then run 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 writes neither an object nor an executable. -Wall -Wextra enables useful warning groups, but warnings still aren't 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 touching unrelated flags.

3. 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. -g 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.

4. 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.o

Link that object file into a new executable:

clang-20 hello.o -o hello-from-object
./hello-from-object

Inspect 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. Don't confuse a successful -fsyntax-only check with a successful link: missing libraries and duplicate symbols only show up later.

5. 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 turns off GNU language extensions for the selected standard. Use -std=gnu++20 when the source intentionally depends on those extensions. The available standard-library choice is platform-dependent; -stdlib=libstdc++ and -stdlib=libc++ are the documented choices when both are installed.

6. 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 hello

Show include and linker search paths when a dependency can't be found:

clang-20 -v -print-search-dirs

-### is useful for seeing the assembler and linker stages without changing any 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

  • Wrong input language. Use a meaningful suffix such as .c or .cpp. For generated or extensionless input, select it explicitly with -x c or -x c++; the setting applies to subsequent input files.
  • Unexpected include files. -I/path adds an include directory, while CPATH and 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 hello replaces that path. Confirm it's the intended file before using it in a script. To undo this guide's changes, remove only the scratch directory with rm -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. -O3 can produce larger code and take longer than -O2. The manpage marks -Ofast as 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

  • Compiler confirmed. clang-20 --version reports the expected installed compiler.
  • Syntax checked separately. -fsyntax-only checks the source without producing a binary.
  • Object and link stages separated. -c produces an object and a separate link command produces the executable.
  • Run confirmed. The executable runs and prints the expected line.
  • Build settings explicit. Language standard, warning level, optimisation level and output path are all stated, not left to defaults.