Compiling and Linking Applications with Makefiles
When you create an application, you write your code in various source code files. For one application, you can have many different source code files. Some large corporate projects may have hundreds (or even thousands) of source code files with dozens of programmers working on the different files.
As you can imagine, dozens of strong-willed programmers working together makes for quite an adventure; but by using tools like make, these programmers are able to easily work together.
To transform these source code files into a single application, you need to compile and link them.
Compiling means transforming your C++ code (or whatever language you are using) into a machine-readable language called Assembler. The Assembler language differs among types of processors. Most of you reading this book are probably working on some version of an AMD or Intel processor, so the C++ compilers you use normally translate your applications into assembler code (also called machine code) that’s appropriate for the processor on your system.
You can also tell the compiler to target some other processor in many cases. The compiler stuffs all this assembler code into a file called an object file and typically names the file the same as the original source code file but with an .obj or .o extension. For each source code file, the compiler makes a single object file.
After you have compiled all your source code files, you run the linker. The linker takes the object files and combines them into a single file that you can run on your computer. This single file usually gets an .exe extension, which stands for executable.
The origin of this term comes from execution, which refers to the running of an application and probably had something to do with what the user of the first computer application wanted to do to the programmer after using the application.
The linker can produce other kinds of output files. For example, you can create a .lib (library) or .dll (Dynamic Link Library, or DLL) file. These files contain executable code, just as the .exe file does, but you don’t execute them as stand-alone files — an .exe file normally loads them and uses the executable code they contain.
The compiler also inserts into the object files a great deal of information in addition to the assembler code. For example, when you are still in the process of developing your application, you can instruct the compiler to put debug information in the file. (Although sometimes the debug information goes in a separate file; it depends on the compiler.)
Debug information includes the names of your variables and the line numbers of the source code. When you use a debugger tool, that tool knows about your code by looking at the debug information.
The compiler also puts information about the code, such as the names of items that occur, in other source code files. For example, if you are writing code that calls code in another source code file, the compiler includes the name of that code in the object file. That way, the linker can connect the two.
Finally, a compiler can add resources to the object files, such as graphics and sounds that your application requires. These resources appear as data that the application accesses later. Data appears in separate areas from executable code within the file, but you don’t need to worry about the object file organization — the compiler takes care of managing both code and data for you.