home *** CD-ROM | disk | FTP | other *** search
/ Chip 2000 January / Chip_2000-01_cd.bin / zkuste / freesoft / djgpp / ug / larger / multisrc.html < prev   
Encoding:
C/C++ Source or Header  |  1997-04-28  |  6.1 KB  |  157 lines

  1. <!--#exec cmd="header Guide: Multiple sources" -->
  2.  
  3. <p>By the time you've gotten some experience with writing software,
  4. you'll realize that doing everything in one source file is just not
  5. going to work.  Kind of like keeping all your clothes in one big box -
  6. eventually the socks get lost at the bottom.  Most programs are built
  7. from more than one source, with each source containing a "module" of
  8. functionality, usually self-contained so that you can work on it
  9. separately and (hopefully) test it separately also.</p>
  10.  
  11. <p>Another reason why you'd want to use multiple source files is so
  12. that you can write different parts of your program in different
  13. languages.  For example, gcc uses C for most of its modules, but it
  14. uses bison to compile the grammar itself.  Multiple sources also
  15. reduces your debugging cycle, because most of the sources will already
  16. be compiled when you go to rebuild your program after fixing that one
  17. last bug :-)</p>
  18.  
  19. <p>Anyway, the purpose of this part of the Guide is to help you figure
  20. out <em>how</em> to build a program that is made up of more than one
  21. source file.</p>
  22.  
  23. <p>The first thing you have to understand is the concept of a "global
  24. symbol".  <em>Symbols</em> are things like function and variables.
  25. Global symbols are symbols that are known to the whole program.  For
  26. example:
  27.  
  28. <pre>
  29. int c;
  30.  
  31. int foo(int x)
  32. {
  33.   int y = x * 2 + 1 + c;
  34.   printf("foo(%d)=%d\n", x, y);
  35. }
  36. </pre>
  37.  
  38. In this code snippet, the symbols <tt>c</tt> and <tt>foo</tt> are
  39. global; <tt>c</tt> because it's a variable declared outside any
  40. functions, and <tt>foo</tt> because it's a function that other parts
  41. of the program will be able to use.  There is another global symbol
  42. here also - <tt>printf</tt>.  Even though this snippet doesn't
  43. <em>define</em> <tt>printf</tt>, it's still a symbol that this snippet
  44. uses.  The difference is that <tt>foo</tt> is defined by us and
  45. <tt>printf</tt> is <em>external</em> to us.</p>
  46.  
  47. <p>Consider these two functions, each in their own source file:
  48.  
  49. <pre>
  50. int foo(int x)                  int bar(int j)
  51. {                               {
  52.   return bar(x) + 47;              printf("j is %d\n", j);
  53. }                                  return j*j;
  54.                                 }
  55. </pre>
  56.  
  57. In this example, the file on the left defines the global symbol
  58. <tt>foo</tt> and refers to the external symbol <tt>bar</tt>.  The file
  59. on the right, however, defines the global symbol <tt>bar</tt> and
  60. refers to the external symbol <tt>printf</tt>.</p>
  61.  
  62. <p>When you compile these files to objects, by using "<tt>gcc -c
  63. foo.c</tt>" and "<tt>gcc -c bar.c</tt>" (go ahead and try it), the
  64. compiler doesn't yet know how it will resolve those references to
  65. symbols it doesn't know about it.  What does it do?  Pretty much
  66. nothing.  It just writes down the missing information in the object
  67. file, and puts off the problem until later.  When is later?  Once you
  68. have all the files compiled, you <em>link</em> them all together.
  69. Unix calls this "loading", as in "load them all up into one program",
  70. hence the program that does this is called <tt>ld</tt>, even though
  71. <tt>gcc</tt> takes care of calling <tt>ld</tt> for you.</p>
  72.  
  73. <p>When you combine these objects together (along with the standard C
  74. library, which happens automatically), the linker (<tt>ld</tt>) makes
  75. a big list of all the global symbols in all the objects, defined and
  76. external.  It matches up the references to the symbols with the
  77. definitions of them.  If any are still missing, you get an error - an
  78. "unresolved external".  If none are missing, you get a program!</p>
  79.  
  80. <p>One other thing that the linker does is make sure that no two files
  81. defined the same symbol.  For example, no program can have two
  82. functions called <tt>foo</tt> - which would it use?  This goes for
  83. variables also, which a lot of people stumble on.  Consider these two
  84. files:
  85.  
  86. <pre>
  87. int size = 42;            extern int size;
  88. </pre>
  89.  
  90. In this example, the left file defines a variable <tt>size</tt> and
  91. the right file refers to the external variable <tt>size</tt>.  When
  92. you link these together, everyone is happy.  Now consider this:
  93.  
  94. <pre>
  95. int size = 42;            int size;
  96. </pre>
  97.  
  98. In this case, <em>both</em> files are defining the variable
  99. <tt>size</tt>, so when you link them, there's a problem.  While this
  100. looks like an obvious problem, a lot of people put the definition in a
  101. header file, which is included in multiple source files, and
  102. inadvertently define it once in each file.  Always use <em>extern</em>
  103. in header files!  Remember, also, that <tt>extern</tt> alone won't
  104. define a symbol.  At least one of the sources must have a definition
  105. for the variable as well.</p>
  106.  
  107. <p>OK, enough about symbols.  How do you compile and link these files?
  108. Well, let's start with two source files, <tt>main.c</tt> and
  109. <tt>foo.c</tt>:
  110.  
  111. <pre>
  112. int main(void)                      int foo(int x)
  113. {                                   {
  114.   printf("foo(4)=%d\n", foo(4));      return 2*x+1;
  115.   exit(0);                          }
  116. }
  117. </pre>
  118.  
  119. OK, first we have to compile these files into objects.  Use commands like
  120. this:
  121.  
  122. <pre>
  123. gcc -c main.c
  124. gcc -c foo.c
  125. </pre>
  126.  
  127. <p>You could have also done "<tt>gcc -c main.c foo.c</tt>", the
  128. results are the same.  However, the two-command approach is better
  129. once you learn to use <tt>make</tt> to automate the compilations.  The
  130. net result is that you have two new files in your directory,
  131. <tt>main.o</tt> and <tt>foo.o</tt>.  These are the object files.  Each
  132. contains the compiled versions of the sources, along with symbol
  133. tables and other information.</p>
  134.  
  135. <p>To see the symbol tables, try this command:
  136.  
  137. <pre>
  138. nm main.o foo.o
  139. </pre>
  140.  
  141. <p>To build the final program, use <tt>gcc</tt> again:
  142.  
  143. <pre>
  144. gcc main.o foo.o -o main.exe
  145. </pre>
  146.  
  147. <p>When you run <tt>main.exe</tt>, you'll see that it prints out the
  148. correct value!  If it didn't, you could edit just one of the two
  149. files, recompile just that file, and just link the two objects at the
  150. end.  While this doesn't seem like much of a savings, consider
  151. building gcc.  It has hundreds of source files and takes 20 minutes to
  152. build from scratch.  Editing and compiling just one source file takes
  153. less than a minute, including building the program.  Quite a savings,
  154. eh?  </p>
  155.  
  156. <!--#exec cmd="trailer" -->
  157.