compiler llvm clang

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 test

GCC 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:

FlagPurpose
-Wl,--dynamic-linker=bin/lib/ld.soSets the runtime dynamic linker path in the ELF header
-Wl,-rpath=bin/libAdds a runtime search path for shared libraries
-Wl,-Map=a.mapGenerates a map file of the linked binary
-Wl,--no-undefinedCauses 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:

FlagPurpose
-Wa,-alGenerate an assembler listing
-Wa,-gdwarf-4Use DWARFv4 for debug info in assembly
-Wa,-march=haswellTarget specific architecture in .S files

-Wp: Pass Options to the Preprocessor (cpp)

-Wp,option passes arguments directly to the C preprocessor.

Example:

FlagPurpose
-Wp,-MD,depfile.dEmit 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/lib

However, -Wl,-rpath=bin/lib is more concise and easier to read.


Summary Table

FlagForPurpose
-Wl,LinkerPass options to ld
-Wa,AssemblerPass options to as
-Wp,PreprocessorPass options to cpp
-XlinkerLinkerPass a single linker flag
-XassemblerAssemblerPass a single assembler flag
-XpreprocessorPreprocessorPass 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.