Chinaunix首页 | 论坛 | 博客
  • 博客访问: 795587
  • 博文数量: 455
  • 博客积分: 9776
  • 博客等级: 中将
  • 技术积分: 5870
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-19 23:23
文章分类

全部博文(455)

文章存档

2011年(455)

分类:

2011-04-22 13:28:58

原文地址:程序编译步骤 作者:onezeroone

  •  what are all Program compilation steps in c language

When programmers talk about creating programs, they often say, "it compiles fine" or, when asked if the program works, "let's compile it and see". This colloquial usage might later be a source of confusion for new programmers. Compiling isn't quite the same as creating an executable file! Instead, creating an executable is a multistage process divided into two components: compilation and linking. In reality, even if a program "compiles fine" it might not actually work because of errors during the linking phase. The total process of going from source code files to an executable might better be referred to as a build.
Compilation
Compilation refers to the processing of source code files (.c, .cc, or .cpp) and the creation of an 'object' file. This step doesn't create anything the user can actually run. Instead, the compiler merely produces the machine language instructions that correspond to the source code file that was compiled. For instance, if you compile (but don't link) three separate files, you will have three object files created as output, each with the name .o or .obj (the extension will depend on your compiler). Each of these files contains a translation of your source code file into a machine language file -- but you can't run them yet! You need to turn them into executables your operating system can use. That's where the linker comes in.
Linking
Linking refers to the creation of a single executable file from multiple object files. In this step, it is common that the linker will complain about undefined functions (commonly, main itself). During compilation, if the compiler could not find the definition for a particular function, it would just assume that the function was defined in another file. If this isn't the case, there's no way the compiler would know -- it doesn't look at the contents of more than one file at a time. The linker, on the other hand, may look at multiple files and try to find references for the functions that weren't mentioned.

You might ask why there are separate compilation and linking steps. First, it's probably easier to implement things that way. The compiler does its thing, and the linker does its thing -- by keeping the functions separate, the complexity of the program is reduced. Another (more obvious) advantage is that this allows the creation of large programs without having to redo the compilation step every time a file is changed. Instead, using so called "conditional compilation", it is necessary to compile only those source files that have changed; for the rest, the object files are sufficient input for the linker. Finally, this makes it simple to implement libraries of pre-compiled code: just create object files and link them just like any other object file. (The fact that each file is compiled separately from information contained in other files, incidentally, is called the "separate compilation model".)

To get the full benefits of condition compilation, it's probably easier to get a program to help you than to try and remember which files you've changed since you last compiled. (You could, of course, just recompile every file that has a timestamp greater than the timestamp of the corresponding object file.) If you're working with an integrated development environment (IDE) it may already take care of this for you. If you're using command line tools, there's a nifty utility called that comes with most *nix distributions. Along with conditional compilation, it has several other nice features for programming, such as allowing different compilations of your program -- for instance, if you have a version producing verbose output for debugging.

Knowing the difference between the compilation phase and the link phase can make it easier to hunt for bugs. Compiler errors are usually syntactic in nature -- a missing semicolon, an extra parenthesis. Linking errors usually have to do with missing or multiple definitions. If you get an error that a function or variable is defined multiple times from the linker, that's a good indication that the error is that two of your source code files have the same function or variable. 


The compilation Process
All 5 stages are implemented by one program in UNIX, namely cc, or in our case, gcc (or g++). The general order of things goes gcc -> gcc -E -> gcc -S -> as -> ld. 

/*hello.c*/
  1. #include <stdio.h>

  2. int
  3. main(void)
  4. {
  5.         printf("hello world\n");

  6.         return (0);
  7. }

gcc -E hello.c -o hello.i
  1. ......
  2. ......
  3. extern int pclose (FILE *__stream);

  4. extern char *ctermid (char *__s) __attribute__ ((__nothrow__));
  5. # 820 "/usr/include/stdio.h" 3 4
  6. extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__));



  7. extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__)) ;


  8. extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__));
  9. # 850 "/usr/include/stdio.h" 3 4

  10. # 2 "test_hello.c" 2

  11. int
  12. main(void)
  13. {
  14.  printf("hello world\n");

  15.  return (0);
  16. }

gcc -S hello.i -o hello.s
  1. .file "test_hello.c"
  2.         .section .rodata
  3. .LC0:
  4.         .string "hello world"
  5.         .text
  6. .globl main
  7.         .type main, @function
  8. main:
  9.         leal 4(%esp), %ecx
  10.         andl $-16, %esp
  11.         pushl -4(%ecx)
  12.         pushl %ebp
  13.         movl %esp, %ebp
  14.         pushl %ecx
  15.         subl $4, %esp
  16.         movl $.LC0, (%esp)
  17.         call puts
  18.         movl $0, %eax
  19.         addl $4, %esp
  20.         popl %ecx
  21.         popl %ebp
  22.         leal -4(%ecx), %esp
  23.         ret
  24.         .size main, .-main
  25.         .ident "GCC: (GNU) 4.1.0 20060304 (Red Hat 4.1.0-3)"
  26.         .section .note.GNU-stack,"",@progbits
gcc -c hello.s -o hello.o
  1. 00000000 T main
  2.          U puts

gcc hello.o -o hello
  1. hello world


阅读(789) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~