home *** CD-ROM | disk | FTP | other *** search
- <!--#exec cmd="header Guide: Multiple sources" -->
-
- <p>By the time you've gotten some experience with writing software,
- you'll realize that doing everything in one source file is just not
- going to work. Kind of like keeping all your clothes in one big box -
- eventually the socks get lost at the bottom. Most programs are built
- from more than one source, with each source containing a "module" of
- functionality, usually self-contained so that you can work on it
- separately and (hopefully) test it separately also.</p>
-
- <p>Another reason why you'd want to use multiple source files is so
- that you can write different parts of your program in different
- languages. For example, gcc uses C for most of its modules, but it
- uses bison to compile the grammar itself. Multiple sources also
- reduces your debugging cycle, because most of the sources will already
- be compiled when you go to rebuild your program after fixing that one
- last bug :-)</p>
-
- <p>Anyway, the purpose of this part of the Guide is to help you figure
- out <em>how</em> to build a program that is made up of more than one
- source file.</p>
-
- <p>The first thing you have to understand is the concept of a "global
- symbol". <em>Symbols</em> are things like function and variables.
- Global symbols are symbols that are known to the whole program. For
- example:
-
- <pre>
- int c;
-
- int foo(int x)
- {
- int y = x * 2 + 1 + c;
- printf("foo(%d)=%d\n", x, y);
- }
- </pre>
-
- In this code snippet, the symbols <tt>c</tt> and <tt>foo</tt> are
- global; <tt>c</tt> because it's a variable declared outside any
- functions, and <tt>foo</tt> because it's a function that other parts
- of the program will be able to use. There is another global symbol
- here also - <tt>printf</tt>. Even though this snippet doesn't
- <em>define</em> <tt>printf</tt>, it's still a symbol that this snippet
- uses. The difference is that <tt>foo</tt> is defined by us and
- <tt>printf</tt> is <em>external</em> to us.</p>
-
- <p>Consider these two functions, each in their own source file:
-
- <pre>
- int foo(int x) int bar(int j)
- { {
- return bar(x) + 47; printf("j is %d\n", j);
- } return j*j;
- }
- </pre>
-
- In this example, the file on the left defines the global symbol
- <tt>foo</tt> and refers to the external symbol <tt>bar</tt>. The file
- on the right, however, defines the global symbol <tt>bar</tt> and
- refers to the external symbol <tt>printf</tt>.</p>
-
- <p>When you compile these files to objects, by using "<tt>gcc -c
- foo.c</tt>" and "<tt>gcc -c bar.c</tt>" (go ahead and try it), the
- compiler doesn't yet know how it will resolve those references to
- symbols it doesn't know about it. What does it do? Pretty much
- nothing. It just writes down the missing information in the object
- file, and puts off the problem until later. When is later? Once you
- have all the files compiled, you <em>link</em> them all together.
- Unix calls this "loading", as in "load them all up into one program",
- hence the program that does this is called <tt>ld</tt>, even though
- <tt>gcc</tt> takes care of calling <tt>ld</tt> for you.</p>
-
- <p>When you combine these objects together (along with the standard C
- library, which happens automatically), the linker (<tt>ld</tt>) makes
- a big list of all the global symbols in all the objects, defined and
- external. It matches up the references to the symbols with the
- definitions of them. If any are still missing, you get an error - an
- "unresolved external". If none are missing, you get a program!</p>
-
- <p>One other thing that the linker does is make sure that no two files
- defined the same symbol. For example, no program can have two
- functions called <tt>foo</tt> - which would it use? This goes for
- variables also, which a lot of people stumble on. Consider these two
- files:
-
- <pre>
- int size = 42; extern int size;
- </pre>
-
- In this example, the left file defines a variable <tt>size</tt> and
- the right file refers to the external variable <tt>size</tt>. When
- you link these together, everyone is happy. Now consider this:
-
- <pre>
- int size = 42; int size;
- </pre>
-
- In this case, <em>both</em> files are defining the variable
- <tt>size</tt>, so when you link them, there's a problem. While this
- looks like an obvious problem, a lot of people put the definition in a
- header file, which is included in multiple source files, and
- inadvertently define it once in each file. Always use <em>extern</em>
- in header files! Remember, also, that <tt>extern</tt> alone won't
- define a symbol. At least one of the sources must have a definition
- for the variable as well.</p>
-
- <p>OK, enough about symbols. How do you compile and link these files?
- Well, let's start with two source files, <tt>main.c</tt> and
- <tt>foo.c</tt>:
-
- <pre>
- int main(void) int foo(int x)
- { {
- printf("foo(4)=%d\n", foo(4)); return 2*x+1;
- exit(0); }
- }
- </pre>
-
- OK, first we have to compile these files into objects. Use commands like
- this:
-
- <pre>
- gcc -c main.c
- gcc -c foo.c
- </pre>
-
- <p>You could have also done "<tt>gcc -c main.c foo.c</tt>", the
- results are the same. However, the two-command approach is better
- once you learn to use <tt>make</tt> to automate the compilations. The
- net result is that you have two new files in your directory,
- <tt>main.o</tt> and <tt>foo.o</tt>. These are the object files. Each
- contains the compiled versions of the sources, along with symbol
- tables and other information.</p>
-
- <p>To see the symbol tables, try this command:
-
- <pre>
- nm main.o foo.o
- </pre>
-
- <p>To build the final program, use <tt>gcc</tt> again:
-
- <pre>
- gcc main.o foo.o -o main.exe
- </pre>
-
- <p>When you run <tt>main.exe</tt>, you'll see that it prints out the
- correct value! If it didn't, you could edit just one of the two
- files, recompile just that file, and just link the two objects at the
- end. While this doesn't seem like much of a savings, consider
- building gcc. It has hundreds of source files and takes 20 minutes to
- build from scratch. Editing and compiling just one source file takes
- less than a minute, including building the program. Quite a savings,
- eh? </p>
-
- <!--#exec cmd="trailer" -->
-