Skip to main content

Section 6.2 Exploring Separate Compilation

The file library.cpp below has some simple functions. The code does not depend on any other code (no includes). However, there is no main function. This means that if we try to compile and link the code into a program, using a recipe like the one below, the build will fail.
$ g++ library.cpp -o program.exe
Listing 6.2.1. library.cpp - attempt to compile and link
If you try out the ActiveCode, you should get an error about an undefined reference to main
We can’t link that file into a full program because there is no main function. But it is possible to just compile the code. To do that with g++, we can use the -c flag which tells the compiler to just compile the file and not link it:
$ g++ -c library.cpp -o library.o
Figure 6.2.2. Compiling but not linking library.cpp
This recipe will successfully build. But there is no program to run:
Listing 6.2.3. library.cpp - set to just compile and not link or execute
The main.cpp below has a different problem. Although it has a main function, it tries to call doubleValue, which is not declared. So if we try to compile it, we get an error:
$ g++ -c main.cpp -o main.o
Listing 6.2.4. main.cpp - set to just compile and not link
To compile main, we could declare the doubleValue function in main.cpp, like this:
Listing 6.2.5. main.cpp (with declaration) - set to just compile and not link
The declaration promises the compiler that doubleValue exists somewhere. The compiler goes ahead and builds the code in main by relying on the promise. (See SectionΒ 5.8 for a reminder of the difference between declaring and defining a function.)
Although we can compile main.cpp now, if we try to link it into a program, we will get an error because the linker does not know where to find the definition of doubleValue. This time we will try building without the -c flag:
$ g++ main.cpp -o program.exe
This recipe tells the compiler that we want to both compile main.cpp and try to link it into a full program.
Listing 6.2.6. main.cpp (with declaration) - set to compile and link
That recipe should result in an error like this:
/usr/bin/ld: /tmp/ccoUEcGg.o: in function `main':
test.cpp:(.text+0x19): undefined reference to `doubleValue(int)'
collect2: error: ld returned 1 exit status
ld is the linker. The final line tells us that the linker had an error. Above that is the error message. In this case, the linker could not find the definition of doubleValue that was called in main. The declaration in main.cpp promised that somewhere else there would be a definition for that function. The linker’s job is to resolve that promise and it can’t because we have not told it to use library.cpp.
Figure 6.2.7. Compiling and linking main.cpp without library.cpp
To successfully build the full program that, we need to tell the compiler to build both library.cpp and main.cpp. That way, the linker has all the necessary definitions to work with:
$ g++ main.cpp library.cpp -o program.exe
The code below looks the same, but it is set to compile with the library.cpp file from above:
Listing 6.2.8. main.cpp (with declaration) - set to compile with library.cpp and then link
Although we can declare the function doubleValue in multiple places, we are only allowed to have one definition. This final example illustrates what happens if both main.cpp and library.cpp contain a definition for doubleValue:
Listing 6.2.9. main.cpp (with a second definition)
This time, the linker (ld) complains about multiple definition of doubleValue(int). It found two copies of the function and is not sure which to use. (It will be an error even if the two versions of the function are identical.)
To summarize what we have learned from these examples:
  • Every file is compiled on its own. Any functions used in that file must be declared in that file (but not necessarily defined).
  • The linker merges the compiled files. It must find one (and only one!) copy of every function that is used in the program.

Checkpoint 6.2.1.

Checkpoint 6.2.2.

Which are the true statements?
  • To compile code, all functions used in a file must be declared in that file.
  • To compile code, all functions used in a file must be defined in that file.
  • To link code, all functions used in the program must be defined in each file.
  • To link code, all functions used in the program must be defined in one file.
You have attempted of activities on this page.