♦ πŸ† 2 min, 🐌 5 min

All you need to know about the C++ compiler

The compiler is one of the essential tools in C++ that you need to master. You'll love it at times and hate it at others.

Knowing which compiler you use and how it works can make a pretty big difference. After all, compiling code in C++ is the messiest thing of all.

The compiler performs three main steps for you:

  • 1.) It pre-processes the code you wrote in C++. It copies the code from header .h files into the files where those headers were included. At this stage, code is still somewhat readable.
  • 2.) Compile step converts the pre-processed C++ code into the machine-readable object files .o
  • 3.) The last step is linking where the compiled objects are bundled together into an executable and then linked with any external libraries.

What C++ compiler do I use?

The first term you need to familiarise yourself with is GCC, the GNU Compiler Collection . gcc includes front ends for C, C++, Objective-C, Fortran, Ada, Go, and D, as well as libraries for these languages. The compiler is usually shipped with Linux operating systems.

Then we have two compiler-drivers in the GNU Compiler Collection:

  • gcc
  • g++

They are not the same.

What's the difference between gcc and g++?

Command:

g++

is equivalent to:

gcc -xc++ -lstdc++ -shared-libgcc 

If we run the gcc command we also need to specify the language we compile against: -xc++ and the libraries we want to link against:

  • -lstdc++ to use the standard library and,
  • -shared-libgcc to link to the libgcc library dynamically

In the case of g++ command, this is "done" for us.

What version of gcc do I have?

On ubuntu, for example, we have:

> gcc --version

gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.

And the g++:

> g++ --version

g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.

If we run any of the above on macOS we get:

> gcc --version

Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.0 (clang-1200.0.32.2)

Why the difference? The Unix and macOS system ship with clang, not gcc.

What is Clang?

Clang is a compiler front end and pretty much the only serious competition to gcc. Clang is pretty robust and well developed.

Clang works with C, C++, Objective-C and Objective-C++ programming languages, as well as the OpenMP, OpenCL. It uses LLVM compiler designed to be a drop-in replacement for gcc`.

In some sense clang works on top of LLVM.

What version of clang do I use?

So on macOS run:

> clang --version

Apple clang version 12.0.0 (clang-1200.0.32.2)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

You can also install clang on Linux. Sometimes developers use clang and gcc in parallel to get more insights in the debugging process. Every-now and then it can be of real help because one compiler will give you different information than the other.

From now on we'll use g++ command to compile so that the necessary libraries are linked. Remember in the back on macOS you are using clang even when you run g++ command πŸ˜‰

How to Compile a C++ program?

As we saw before:

g++ hello_world.cpp

Spits out an executable file (exe): a.out

How to name the compiled executable of a C++ program?

To specify the name of the output executable (exe) .out we use the -o flag:

g++ -o hello_word.out hello_world.cpp 

This will create the exe named hello_word.out instead of defaults a.out.

How to compile two separate .cpp files into one exe?

Usually, our program consists of more than one file, but we want to compile them together. To do that we use:

g++ hello_world.cpp my_function.cpp

That's it. And get out one exe.

How to link/add to the executable the header files?

We haven't talked about them yet, but sometimes our software also has header files .hpp (which it should). If the header files are in the current folder from which you call g++; you don't have to do anything.

If you have header files at another custom location, use -I flag and pass in the path:

g++ -I/path/to/headers hello_world.cpp

Mind the spaces πŸ˜‰

How to tell the compiler which C++ standard to use?

Or how to tell the compiler which standard of the C++ to build against? Specifying the correct standard is important because you sometimes are forced to use a specific standard of C++ due to your codebase. So to link against STD library 11:

g++ -o hello_world.out hello_world.cpp -std=c++11

Then for other version of the standard use the appropriate flag:

  • -std=c++14
  • -std=c++17
  • -std=c++20

What else?

A handy feature is -g flag used to generate debug info.

g++ hello_world.cpp -std=c++11 -g

This generates besides the exe file also a folder:

a.out.dSYM/

That contains the debugging information.

For more capabilities of the compiler check the official docs of your compiler. List of all the options is a mile long.

Eventually, this because unreadable as the project grows. So we use something called a build system. More on that in the next post

Get notified & read regularly πŸ‘‡