views:

140

answers:

5

So I get the point of headers vs source files. What I don't get is how the compiler knows to compile all the source files. Example:

example.h

#ifndef EXAMPLE_H
#define EXAMPLE_H

int example(int argument); // prototype

#endif

example.c

#include "example.h"

int example(int argument)
    {
    return argument + 1; // implementation
    }

main.c

#include "example.h"

main()
    {
    int whatever;
    whatever = example(whatever); // usage in program
    }

How does the compiler, compiling main.c, know the implementation of example() when nothing includes example.c?

Is this some kind of an IDE thing, where you add files to projects and stuff? Is there any way to do it "manually" as I prefer a plain text editor to quirky IDEs?

+3  A: 

Yes, you have to tell the compiler (usually through a makefile if you're not using an IDE) which source files to compile into object files, and the compiler compiles each one individually. Then you give the linker the list of object files to combine into the executable. If the linker is looking for a function or class definition and can't find it, you'll get a link error.

Graeme Perrow
So that's where makefiles come in, always wondered where they fit in. Thanks.
Core Xii
A: 

The compiler doesn't. But your build tool does. IDE or make tool. The manual way is hand-crafted Makefiles.

Michael Krelin - hacker
+3  A: 

It doesn't ... you have to tell it to.
For example, whe using gcc, first you would compile the files:

gcc file1.c -c -ofile1.o
gcc file2.c -c -ofile2.o

Then the compiler compiles those files, assuming that symbols that you've defined (like your example function) exist somewhere and will be linked in later. Then you link the object files together:

gcc file1.o file2.o -oexecutable

At this point of time, the linker looks at those assumtions and "clarifies" them ie. checks whether they're present. This is how it basically works...

As for your IDE question, Google "makefiles"

Aviral Dasgupta
you mean `-c`, not `-S`, otherwise you shouldn't be using `.o` as output.
Michael Krelin - hacker
@hacker Thanks. Fixed... it's pretty hard to read a long page of options...
Aviral Dasgupta
+6  A: 

Compiling in C or C++ is actually split up into 2 separate phases.

  • compiling
  • linking

The compiler doesn't know about the implementation of example(). It just knows that there's something called example() that will be defined at some point. So it just generated code with placeholders for example()

The linker then comes along and resolves these placeholders.

To compile your code using gcc you'd do the following

gcc -c example.c -o example.o
gcc -c main.c -o main.o
gcc example.o main.o -o myProgram

The first 2 invocations of gcc are the compilation steps. The third invocation is the linker step.

Glen
I think you meant gcc -c main.c -o main.o in step 2.
baskin
@baskin, yes I did. thanks for catching that. fixed.
Glen
A: 

The compiler does not know the implementation of example() when compiling main.c - the compiler only knows the signature (how to call it) which was included from the header file. The compiler produces .o object files which are later linked by a linker to create the executable binary. The build process can be controlled by an IDE, or if you prefer a Makefile. Makefiles have a unique syntax which takes a bit of learning to understand but will make the build process much clearer. There are lots of good references on the web if you search for Makefile.

Timothy Pratley