Daily Notes of Learned Things 230814

X anonymous
3 min readAug 14, 2023

--

How C++ compile and link program

How C++ compile and link program

original article: How C++ Works: Understanding Compilation

Typically, file with .cpp, .cxx, .cc, .cu extensions is known as a Source file, while file with .h, .hpp, .hxx .hcu extensions is known as a Header file.

Overall, for building a C++ project, there are three phases happened:

Preprocess -> Compile -> Link

Preprocessing Phase

Before compilation, the preprocessor will be launched.

The Preprocessor will go through each source file. When it see “#include”, it will literally replace the line containing the #include directive with the entire content of the included file. Hence, header files won’t be passed to the preprocessor and compiler. In other hands, header files will be opened several times during the preprocessing phase, depending on how many source files or other header files include them. On the contrary, source files will be opened only once.

Lastly, the preprocessor will build a translation unit after finishing all tasks described on here. These tasks can be organized as below:

  • macro definitions (#define, #undef)
  • Conditional inclusions (#ifdef, #ifndef, #if, #endif, #else and #elif)
  • Line control (#line)
  • Error directive (#error)
  • Source file inclusion (#include) (mentioned above)
  • Pragma directive (#pragma)
  • Predefined macro names

In addition, the preprocessor will also strip code out of the source file and of the headers when it finds conditional compilation blocks whose directive evaluates to false.

To see the actual content of translation unit, we can add -E option after build command, along with the -o option to specify the output file location.

// main.cpp

#include <iostream>

int main([[maybe_unused]] const int argc, [[maybe_unused]] const char *argv[]) {
std::cout << "Hello, World!" << std::endl;
return 0;
}
g++ -E main.cpp -o main.li # Output the translated file

Then we may use the following command to see how many lines does the file have:

wc -l main.li
# 35235 main.li
# so many lines because it includes <iostream>.

You can open the main.li file to see what is actually inside.

Compiling Phase

Now the compiler start to use translation unit to build object files.

Each C++ source file needs to be compiled into an object file. Object files come from multiple source files and then linked to a specific executable or library.

When it comes to mixing C and C++ code, it is important to mention how to avoid C++ mangle function name in the compiling phase.

Since C++ contains overload feature, the compiler can not only use a function’s name as its unique identifier. So the C++ compiler will add some additional information like parameter’s or argument’s type information to the original function name, this is the C++ function mangle feature. However, C compiler does not need to do this and it also not know the mixed name while linking to the function. Hence, we can add extern “C” to disable the function mangle feature.

#ifdef __cplusplus // Make it only appears when using C++. C doesn't know extrtern...
extern "C" {
#endif

int sumI(int a, int b);
float sumF(float a, float b);

#ifdef __cplusplus
} // end extern "C"
#endif

What this accomplishes is that it allows you to use C code with your C++ code, because the macro __cplusplus will be defined. But you can also still use it with your legacy C code, where the macro is NOT defined, so it won't see the uniquely C++ construct.

For the rest of the article’s content, I’ll make my summary in the future post :)

--

--