5 Answers
5

Efficiency.
When you compile a program you create an object file for each source file, if you change a source file you only need to recompile that module and then relink (relinking is cheap).
If the compiler did everything in one pass it would have to recompile everything for every change.

It also fits with the unix philosophy of small programs that do one thing, so you have a pre-processor, a compiler, a linker, a library creator. These steps might now be different modes of the same tool.

However there are reasons why you want the compiler to link in one step, there are some optimizations you can do if you allow the compiler to change object files at link time - most modern compilers allow this but it requires them to put extra info into the object files at compile time.

It would be better if the compiler could store the entire project in a single database, rather than the mess of sources, resources, browse info files, object files etc - but developers are very conservative!

Yea, that is also what I mentioned as development productivity, but, is there any consideration from compiler algorithm perspective?
–
Baiyan HuangJun 11 '10 at 15:43

2

Another thing to consider is that its entirely possible to create more executables from different subsets of obj files (ie two project can use the same source code files = modules = obj files). This of course is possible thanks to the separation of compile and link phase. You do not need to rebuild everything from scratch.
–
PeterKJun 11 '10 at 16:06

-1: this has nothing to do with Unix
–
John SaundersJun 13 '10 at 1:30

@John Saunders - I would argue that separate cpp,compile,link,ar etc of 'C' are a unix heritage. A language developed on mainframes has a different tool chain
–
Martin BeckettJun 13 '10 at 5:42

@Martin: you are displaying ignorance. Exact same tool chain (except for Loader) in DECsystem-10 30+ years ago, before Unix.
–
John SaundersJun 13 '10 at 7:32

Part of this is historical. Back in the dark ages, computers had little memory. It was easy to to create a program with enough source code that all of it couldn't be processed at one time. So the processing had to be done in stages: preprocessing source code, compile source to assembly (one by one), assembly to object code, all object files linked into the final executable. Each of these steps had one or more stand alone tools to do its task. Over the years the tools were improved incrementally, but no major redesign of the process has ever become mainstream.

It's important that the build time, even for a very large project, be under 24 hours. And being able to build overnight is better. Separate compilation, which is to say dividing a program into "compilation units" and compiling them independently, is the way to reduce build time:

If a compilation unit hasn't been changed, and if nothing it depends on has changed, you can reuse the result of an old compilation.

You can often compile multiple units in parallel, or even distributed over a network of workstations. The lowly Make will compile in parallel, and other tools like ccdist exist to distribute the work of compilation.

Linking provides few benefits in and of itself but is necessary to use the results of separate compilation.

Compiling the file changes the code into binary that the computer can read. Linking the file tells the computer how to complete a command. So its impossible to generate it all at once, without the two steps.