02. 알아두면 정말 유용한 C소스 컴파일 과정(1)
Language/C 2011. 9. 8. 12:14|| C 소스의 전체 컴파일 과정
gcc는 GNU에서 만든 C컴파일러라고 말하지만 사실 컴파일러 드라이버이다.
gcc는 실제 컴파일 과정을 담당하지 않고 전처리기와 C 컴파일러, 어셈블러, 링커를 각각 호출해 주는 역할만 한다.
이렇게 각각의 컴파일 과정에 필요한 명령을 순차적으로 호출해 주는 것을 컴파일러 드라이버라고 한다.
그럼 진짜 컴파일러는 어디에 있을까?
[oneone@study study]$ /usr/libexec/gcc/i686-redhat-linux/4.4.4/
cc1 cc1plus collect2 f951
like.c소스 → [cpp0 or cc1 -E 전처리기] → like.i 전처리 결과 → [cc1 C컴파일러] → like.s 어셈블리 파일 → → [as 어셈블러] → like.o 오브젝트 파일 → [ld or collect2] → like 실행파일 |
like.c 파일의 컴파일 과정을 알아보기 위해 다음 명령으로 컴파일 한다.
[oneone@study study]$ gcc -v -save-temps -o like like.c
[oneone@study study]$ gcc -v -save-temps -o like like.c Using built-in specs. Target: i686-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch=i686 --build=i686-redhat-linux Thread model: posix gcc version 4.4.4 20100503 (Red Hat 4.4.4-2) (GCC) COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'like' '-mtune=generic' '-march=i686' /usr/libexec/gcc/i686-redhat-linux/4.4.4/cc1 -E -quiet -v like.c -mtune=generic -march=i686 -fpch-preprocess -o like.i ignoring nonexistent directory "/usr/lib/gcc/i686-redhat-linux/4.4.4/include-fixed" ignoring nonexistent directory "/usr/lib/gcc/i686-redhat-linux/4.4.4/../../../../i686-redhat-linux/include" #include "..." search starts here: #include <...> search starts here: /usr/local/include /usr/lib/gcc/i686-redhat-linux/4.4.4/include /usr/include End of search list. COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'like' '-mtune=generic' '-march=i686' /usr/libexec/gcc/i686-redhat-linux/4.4.4/cc1 -fpreprocessed like.i -quiet -dumpbase like.c -mtune=generic -march=i686 -auxbase like -version -o like.s GNU C (GCC) version 4.4.4 20100503 (Red Hat 4.4.4-2) (i686-redhat-linux) compiled by GNU C version 4.4.4 20100503 (Red Hat 4.4.4-2), GMP version 4.3.1, MPFR version 2.4.2. GGC heuristics: --param ggc-min-expand=42 --param ggc-min-heapsize=24314 Compiler executable checksum: 72dc052d4f2936b9a3bac52ec96d8f03 COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'like' '-mtune=generic' '-march=i686' as -V -Qy -o like.o like.s GNU assembler version 2.20.51.0.2 (i686-redhat-linux) using BFD version version 2.20.51.0.2-15.fc13 20091009 COMPILER_PATH=/usr/libexec/gcc/i686-redhat-linux/4.4.4/:/usr/libexec/gcc/i686-redhat-linux/4.4.4/:/usr/libexec/gcc/i686-redhat-linux/:/usr/lib/gcc/i686-redhat-linux/4.4.4/:/usr/lib/gcc/i686-redhat-linux/:/usr/libexec/gcc/i686-redhat-linux/4.4.4/:/usr/libexec/gcc/i686-redhat-linux/:/usr/lib/gcc/i686-redhat-linux/4.4.4/:/usr/lib/gcc/i686-redhat-linux/ LIBRARY_PATH=/usr/lib/gcc/i686-redhat-linux/4.4.4/:/usr/lib/gcc/i686-redhat-linux/4.4.4/:/usr/lib/gcc/i686-redhat-linux/4.4.4/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'like' '-mtune=generic' '-march=i686' /usr/libexec/gcc/i686-redhat-linux/4.4.4/collect2 --no-add-needed --eh-frame-hdr --build-id -m elf_i386 --hash-style=gnu -dynamic-linker /lib/ld-linux.so.2 -o like /usr/lib/gcc/i686-redhat-linux/4.4.4/../../../crt1.o /usr/lib/gcc/i686-redhat-linux/4.4.4/../../../crti.o /usr/lib/gcc/i686-redhat-linux/4.4.4/crtbegin.o -L/usr/lib/gcc/i686-redhat-linux/4.4.4 -L/usr/lib/gcc/i686-redhat-linux/4.4.4 -L/usr/lib/gcc/i686-redhat-linux/4.4.4/../../.. like.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i686-redhat-linux/4.4.4/crtend.o /usr/lib/gcc/i686-redhat-linux/4.4.4/../../../crtn.o |
like.i |
.... 생략 extern char *ctermid (char *__s) __attribute__ ((__nothrow__)); # 908 "/usr/include/stdio.h" 3 4 extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__));
extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__)) ;
extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__)); # 938 "/usr/include/stdio.h" 3 4
# 2 "like.c" 2
int main() {
printf("I like you!\n"); return 0; } |
like.s |
.file "like.c" .section .rodata .LC0: .string "I like you!" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $16, %esp movl $.LC0, (%esp) call puts movl $0, %eax leave ret .size main, .-main .ident "GCC: (GNU) 4.4.4 20100503 (Red Hat 4.4.4-2)" .section .note.GNU-stack,"",@progbits |
이런 like.i파일과 like.s파일은 컴파일 중간 과정의 산물로서 컴파일러 오류로 인한 문제나 전처리 과정에서의
오류로 인한 문제가 발생 했을 때 유용하게 사용할 수 있다.
|| cc1 -E에 의한 전처리 과정
첫번째 과정은 헤더파일 삽입, 두 번째 과정은 매크로 치환 및 적용이다.
like.c |
#include <stdio.h>
void myFunc(void);
int main() {
myFunc(); return 0; }
void myFunc(void) { printf("I like you\n"); } |
main() 함수 내에서 myFunc() 함수를 사용할려면 myFunc() 함수 사용 이전에 함수의 원형을 void myFunc();과 같은 형식으로 선언해야한다.
printf()함수는 include한 stdio.h파일에 선형이 되어있다. 헤더파일을 C 소스내에 include하면 전처리기가 include한 자리에 헤더파일의 내용을 붙인다. 헤더파일은 설정된 디렉토리 순으로 파일을 찾는다. include할 디렉토리를 추가하기 위해선 gcc 옵션으로 -I[디렉토리] 라고 추가하면 된다.
osCode.c |
#include <stdio.h> #include <stdlib.h>
void main(){
#ifdef __oneone__ printf("oneone\n"); #elif __babo__ printf("babo\n"); #endif
} |
[oneone@study study]$ gcc -D__babo__ -g -o osCode osCode.c
[oneone@study study]$ ./osCode
babo
출처 :
http://www.oneone.kr/?mid=UnixPUtil&page=1&document_srl=5653
'Language > C' 카테고리의 다른 글
02. 알아두면 정말 유용한 C소스 컴파일 과정(3) (0) | 2011.09.08 |
---|---|
02. 알아두면 정말 유용한 C소스 컴파일 과정(2) (0) | 2011.09.08 |
01. 컴파일의 의미 (0) | 2011.09.08 |
링킹/로더 (0) | 2011.09.08 |
모듈과 라이브러리 (0) | 2011.09.08 |