Understanding -W: How Clang and GCC Pass Options Internally
When using GCC or Clang, it’s common to see flags like -Wl, -Wa, or -Wp. These are used to pass specific options to the linker, assembler, or preprocessor, respectively. Understanding how these flags work requires understanding the multi-layer architecture of the compiler toolchain.
🧠 How GCC and Clang Work Internally
Both GCC and Clang are driver programs that invoke a series of underlying tools:
- Preprocessor (
cpp) – Handles macros,#include,#define, etc. - Compiler (
cc1,cc1plus) – Translates preprocessed code to assembly - Assembler (
as) – Converts assembly to object code - Linker (
ld) – Links object files and libraries into a final binary
So when you run:
gcc test.c -o testGCC breaks it into these phases and passes options to each tool as needed. Flags like -Wl, -Wa, and -Wp let you control what is passed to each phase manually.
-Wl: Pass Options to the Linker (ld)
-Wl,option tells the compiler to pass this option to the linker exactly as written. Multiple options can be comma-separated.
Examples:
| Flag | Purpose |
|---|---|
-Wl,--dynamic-linker=bin/lib/ld.so | Sets the runtime dynamic linker path in the ELF header |
-Wl,-rpath=bin/lib | Adds a runtime search path for shared libraries |
-Wl,-Map=a.map | Generates a map file of the linked binary |
-Wl,--no-undefined | Causes the linker to error if symbols are unresolved |
-Wa: Pass Options to the Assembler (as)
-Wa,option tells the compiler to pass this option to the assembler.
Examples:
| Flag | Purpose |
|---|---|
-Wa,-al | Generate an assembler listing |
-Wa,-gdwarf-4 | Use DWARFv4 for debug info in assembly |
-Wa,-march=haswell | Target specific architecture in .S files |
-Wp: Pass Options to the Preprocessor (cpp)
-Wp,option passes arguments directly to the C preprocessor.
Example:
| Flag | Purpose |
|---|---|
-Wp,-MD,depfile.d | Emit dependency info to a file |
Alternatives: -Xlinker, -Xassembler, -Xpreprocessor
These are alternatives to -Wl, -Wa, etc., used to pass one argument at a time.
Examples:
-Xlinker --no-undefined
-Xlinker -rpath
-Xlinker bin/libHowever, -Wl,-rpath=bin/lib is more concise and easier to read.
Summary Table
| Flag | For | Purpose |
|---|---|---|
-Wl, | Linker | Pass options to ld |
-Wa, | Assembler | Pass options to as |
-Wp, | Preprocessor | Pass options to cpp |
-Xlinker | Linker | Pass a single linker flag |
-Xassembler | Assembler | Pass a single assembler flag |
-Xpreprocessor | Preprocessor | Pass a single preprocessor flag |
Use -v when compiling to see how Clang or GCC breaks down the steps into preprocessor, compiler, assembler, and linker stages.