330 likes | 622 Views
2005 Fall. gcc 로 컴파일 , 링크하기. 주 홍 택 컴퓨터공학과 계명대학교. gcc 소개. FSF (Free Software Foundation) 의 C, C++ 컴파일러 컴파일 , 어셈블 , 로더 역할을 함 매우 많은 온라인 문서가 있음. C 컴파일하기. 위 과정은 gcc 명령어 호출로 실행됨. .c .cc .C. .s. .o. 전처리기 (preprocessor). 컴파일러 (compiler). 어셈블러 (assembler). 링커 (linker). .o.
E N D
2005 Fall gcc로 컴파일, 링크하기 주 홍 택 컴퓨터공학과 계명대학교
gcc 소개 • FSF (Free Software Foundation)의 C, C++ 컴파일러 • 컴파일, 어셈블, 로더 역할을 함 • 매우 많은 온라인 문서가 있음
C 컴파일하기 • 위 과정은 gcc 명령어 호출로 실행됨 .c .cc .C .s .o 전처리기 (preprocessor) 컴파일러 (compiler) 어셈블러 (assembler) 링커 (linker) .o .s a.out
컴파일 과정 • 전처리(preprocessing) • #define, #include, #if와 같은 전처리 지시자 해석 • 전처리 작업을 위한 cpp 프로그램을 호출 • 컴파일(compile) • 고급 언어 소스 프로그램을 입력 받아서 어셈블리 파일을 만듬(.s) • 일반적으로 어셈블리 파일은 저장하지 않고 바로 어셈블러를 호출함 • 여기서 컴파일은 좁은 의미의 컴파일이며 넓은 의미의 컴파일은 모든 과정을 포함함 • 어셈블(assemble) • 어셈블리 파일을 입력 받아서 오브젝트 파일을 만듬(.o) • 어셈블을 위한 gas 프로그램을 호출함 • 어셈블러는 플랫폼(CPU+OS)마다 다르며 해당 전용 어셈블러 호출 가능 • 링크(linking) • 오브젝트 파일을 엮어서 실행 파일을 만듬(.o) • 라이브러리 함수도 이 단계에서 사용함 • 링크를 위한 ld 프로그램을 호출
gcc 사용법 • 모든 컴파일 과정을 한번에 처리하기 $ gcc –o filter filter_driver.c define_stack.c • -o옵션은 실행 파일 명을 지정함 • 이 옵션을 지정하지 않으면 a.out이 실행 파일임 • 필요한 소스 파일만 컴파일 하기 $ gcc –c filter_driver.c $ gcc –c define_stack.c $ gcc –o filter filter_driver.o define_stack.o • -c옵션은 컴파일하지만 링크는 하지 않음(.o) 파일 만 만듬 • 이후에 define_stack.c가 변경되었다면 2,3번만 수행 • filter_driver는 컴파일 하지 않음 • 소스 코드가 매우 많은 파일로 분리되어 있는 경우에 상당히 효과적임
매크로 정의하기 • 컴파일러 매크로 • 컴파일러가 파일을 제어할때 사용하는 정보 • -D 옵션을 사용한 매크로 정의 $ gcc –c –DDOC_FILE=“info” –DUSE_POLL filter_driver.c • -D 옵션은 매크로를 정의함 • -DDOC_FILE은 소스에서 #define DOC_FILE info와 동일한 결과 • -DUSE_POLL은 소스에서 #define USE_POLL과 동일함 효과 (기본값 1로 정의됨) • -U 옵션은 매크로 정의를 해제함 • #undef와 동일한 효과임 • -I 옵션은 헤더 파일 위치 지정 $ gcc–I../headers filter_driver.c • 비표준 라이브러리를 위한 헤더 파일의 디렉토리를 지정
라이브러리와 링크하기 • -l 옵션은 라이브러리 지정 $ gcc –o plot main.o plot_line.o –lm • -lm은 수학 라이브러리를 포함한다는 의미임 • 표준 라이브러리를 담고 있는 디렉토리에서 libm.a을 찾음 • 라이브러리의 상대적 위치 순서대로 함수를 찾음 • 시스템 호출 라이브러리, 입출력 라이브러리, 실행 초기 루틴은 기본적으로 포함됨 • -L 옵션은 비표준 라이브러리 지정 $ gcc –o plot –L/usr/local/lib main.o plot_line.o –lx • 표준 라이브러리가 아니 비 표준 라이브러리 사용 • 표준 라이브러리가 이곳에 있으면 우선적으로 사용
gcc 파일 처리 • gcc 컴파일러는 파일 확장자에 따라서 처리
중간 결과 파일 • 중간 결과 파일의 생성 목적 • 디버깅 • 코드를 직접 다루기 위하여 (device driver 등) • 전처리 • -E 옵션으로 생성되며 표준 출력으로 내보냄 • 컴파일 • -S 옵션으로 생성되며 .s 확장자로 된 파일에 출력 • 어셈블 • -o 옵션으로 생성되며 .o 확장자로 된 파일에 출력
make와 컴파일러 • 유닉스에서 가장 중요한 도구중에 하나 • 컴파일을 자동화 하는 프로그램 • 실행 파일을 만드는 과정(빌드)을 정의하면 필요한 작업만을 수행하여 실행 파일 생성 • gmake gnumake는 make 보다 발전된 것임 • 간단한 예 $ for i in *.c; do make `basename $i .c`; done • 현재 디렉토리에 있는 모든 .c 소스 파일에 대하여 .o 파일을 만드는데 .o 파일이 만들어진 후에 .c 파일이 갱신된 것만 컴파일
gcc 컴파일러 옵션 • 중요한 옵션에 대하여만 설명함 • 거의 모든 UNIX 계열 C 언어 컴파일러와 동일한 옵션 사용 • 옵션은 매우 많아서 수백개 정도 됨 • 대부분의 경우 모든 옵션을 다 알 필요는 없음 • 목적에 따라서 특수한 목적으로 사용하는 경우에 자세히 공부할 필요가 있음
컴파일러 옵션: 컴파일러 동작 • 옵션 v (verbose) • 컴파일러의 버전과 각 단계에서 실행하는 자세한 사항을 출력 • 컴파일하는 과정에서 어떤 옵션이 사용되는지 알고자 할때 사용됨
컴파일러 옵션: 경고 메시지 제어 • 경고나 오류메세지 단위로 출력을 제어함 • 옵션 w • 모든 경고 메시지를 나오지 않도록 함 • 옵션 W • 합법적이지만 다소 모호한 코딩에 대하여 부가적인 경고 메시지 출력 • 옵션 Wall • 모호한 코딩에 대하여 자세한 경고 메시지 • 옵션 Wtraditional • K&R C와 ANSI C 간에 서로 다른 결과를 가져올 가능성 있는 것에 대한 경고 출력 • 옵션 Werror • 모든 경고를 에러로 만듬: 경고가 나오는 경우 오브젝트 파일을 만들지 않음
컴파일러 옵션: 언어 특성 제어 • C 언어 3가지 종류가 있음 • Traditional • Kernighan과 Ritchie가 최초에 만든 C 언어 • ANSI C • 미국 국가 표준으로 만들어진 C 언어 • FSF C • FSF에서 확장한 C언어 • 옵션 traditional • 전통적인 C 언어 지원 • 옵션 ansi • ANSI C 표준 지원 • 옵션 pedantic • 모든 경고 메시지 출력하고 FSF 확장 사용할 수 없음
컴파일러 옵션: 전처리기 • 옵션 M • 소스 파일을 읽어서 어떤 파일을 include하는지 알아내어 표준 출력으로 출력 • make 파일의 의존 관계를 처음에 생성하는데 도움을 줌 • 옵션 C • 일반적으로 전처리기에서 모든 주석을 지움 • 이 옵션을 사용하면 주석을 지우지 않음 • 디버깅시 필요함
컴파일러 옵션: 라이브러리 지정 옵션 • 옵션 nostartfiles • 링크할때 표준 시스템 구동 파일을 사용하지 않음 • 크로스 컴파일시, 임베디드 프로세서에 사용됨 • 옵션 nostdlib • 링크할때 표준 라이브러리와 구동 파일을 사용하지 않음 • 위와 마찬가지의 경우 타겟 시스템 라이브러리 제공 • 옵션 static • 공유 라이브러리가 아닌 정적 라이브러리와 링크 • 옵션 shared • 가능한 한 공유 라이브러리와 링크하고 공유 라이브러리가 없는 경우에만 정적 라이브러리와 링크(기본값)
컴파일러 옵션: 디버깅과 프로파일링 • 컴파일할때 디버깅을 위한 코드와 심볼 테이블을 삽입함 • Dbx, gdb, prof, gprof과 같은 프로그램에서 사용 가능한 코드를 생성함 • 개발 완료시 이 기능을 사용하지 않음 • 옵션 p • prof에서 프로파일링 할 수 있는 프로그램 생성 • 옵션 pg • gprof에서 프로파일링 할 수 있는 프로그램 생성 • 옵션 g • 디버거 gdb에서 쓸 수 있는 확장된 심볼 테이블 을 생성
컴파일러 옵션: 최적화 • 프로그램의 수행속도를 컴파일러가 최적화함 • 일반적으로 최적화와 디버깅 옵션은 양립하지 않음 • gcc는 최적화와 디버깅 옵션을 동시 사용하도록 허용하나 결과에 대하여는 보장 못함 • 옵션 O • 옵션 01 과 동일 • 옵션 O0 • 최적화 하지 않음(기본값): 정확한 동작 및 컴파일 시간 적음 • 옵션 O1 • 코드 크기와 실행 시간을 줄여 줌 • 옵션 O2 • 더 많은 최적화를 수행함
컴파일러 옵션: 최적화 • 옵션 ffast-math • 부동 소수점 연산에 대하여 최적화를 수행함 • 결과에 대한 확신을 할 수 없으므로 충분한 테스트 필요함 • 옵션 finline-functions • 단순한 함수의 경우 inline 함수로 변경하여 사용함 • 성능 개선은 반드시 확인 후 사용하여야 함 • 함수 호출에 대한 오버헤드와 명령 캐시 성능 개선간에 적절한 절충이 필요함 • 옵션 fno-inline • 모든 inline을 금지함 • 소스에서 inline을 지정한 경우에도 금지함 • 옵션 funroll-loops • 고정된 반복 횟수를 갖는 반복문을 모두 전개함 • 프로그램 코드 크기가 커짐나 루프의 오버헤드 줄임(캐시등)
컴파일러 옵션: 옵션 넘겨 주기 • 어셈블러에게 옵션 넘겨주기 -Wa,option-list • Option-list에는 여러 개의 옵션이 콤마(,)로 분리되어 들어감 • 링커에 옵션 넘겨주기 -Wl,option-list • Option-list에는 여러 개의 옵션이 콤마(,)로 분리되어 들어감
어셈블하기 • 어셈블리 언어로 작성된 프로그램을 가지고 오브젝트 모듈을 만듬 • GNU 어셈블러는 각 플랫폼마다 존재함 • 어셈블러 실행 $ as list-of-options list-of-source-files • 옵션들 -ah : C 프로그램의 리스트를 생성함 -al: : 어셈블리 언어 코드의 리스트를 생성함 -as : 심볼 테이블에 대한 리스트를 생성함
프로그램 세그먼트 • 생성된 오브젝트 파일은 여러 세그먼트로 나누어짐 • 텍스트 세그먼트 • 실행 코드가 들어 감 • 보통 읽기 전용 • 여러 프로세스가 공유하면 공유 텍스트(shared text)임 • 데이터 세그먼트 • 정적, 초기화된 데이터를 저장함 • bss (Block Started by Symbol) 세그먼트 • 초기화되지 않은 데이터를 보관하는 영역
링크하기 • ld 링커는 여러 오브젝트 모듈과 라이브러리를 결합하여 하나의 실행 파일을 만들어 냄 • 외부 변수, 외부 함수, 라이브러리에 대한 참조 위치를 찾아내어 완전한 실행 프로그램 생성 • 일반적으로 ld를 직접 수행하지 않고 gcc로 수행함 • 모든 라이브러리의 위치를 일일이 적어 줄 필요 없음 • 기본 라이브러리를 포함 시켜 줌
ld 실행 • $ ld list-of-options list-of-files-and-libraries • 파일명과 라이브러리 리스트에서 라이브러리는 –llib-name을 사용 • 파일 및 라이브러리의 순서는 중요함 • 라이브러리의 경우 외부 참조에 의하여 필요한 함수만 추출함 • $ ld prog1.o –lm prog2.o • prog2는 math 함수를 사용하지 않음 • 순서와 관계없이 라이브러리에서 모듈을 찾기 위하여 색인을 생성함 • $ ld prog1.o –lat –lfo • fo 라이브러리에서 at 함수 사용시 에러 • ranlib를 사용하여 색인을 만들어 주면 에러 발생 안함
ld 실행 파일 만들기 • 실행 파일을 만들때 시작 위치는 첫째 파일의 시작 부분임 • C 프로그램의 시작점과 같지는 않음 • OS에서 프로그램 시작전에 표준 런타임 초기화 루틴 실행함 • 이러한 일을 하는 루틴이 바로 초기화 루틴이고 플랫폼마다 제공함 • 보통 유닉스 계열에서는 /lib/crt0.o 임 • gcc와 ld $ gcc exp.o 는 아래와 같음 $ ld –dc –dp –e start –X –o a.out \ /usr/lib/crt0.o expo.o -lc
ld 옵션들 -o name : 실행 파일 이름 지정 -lname : 표준 라이브러리 링크 (/lib /usr/lib) -Ldir : 표준 라이브러리 디렉토리 추가 -s : 실행 파일에 심볼 테이블 제거 (ref. strip 명령) -x : 출력 파일에 로컬 심볼 제거 -n : 텍스트 영역을 읽기 전용으로 만듬 -r : 추후에도 링크 할 수 있도록 오브젝트 파일 만듬 -e name: 실행 파일의 시작위치를 name 심볼로 사용 -M : 전역 심볼의 값이 어느 함수에 위치하는지 보여주는 로드맵 작성 -b format : 오브젝트 파일을 주어진 형식으로 읽어 들임 -oformat format: 주어진 형식의 오브젝트 파일을 생성
라이브러리 만들기 • Ar 명령으로 오브젝트 모듈의 라이브러리 만듬 • 새로운 라이브러리 생성 • $ ar rs libname list-of-files • r 옵션: 파일을 추가하고 없으면 새로운 라이브러리 생성 • s 옵션: 정적 라이브러리 색인 생성(ranlib 불필요) • 라이브러리 갱신 • $ ar rus libname list-of-files • 라이브러리의 모듈과 파일의 날짜를 비교하여 갱신 • 라이브러리에서 파일 지우기 • $ ar ds libname list-of-files • 라이브러리에서 파일 추출 • $ ar x libname list-of-files
크로스 컴파일 • 한 플랫폼에서 컴파일한 코드를 다른 플랫폼에서 실행할 수 있는 컴파일 환경 • 예: IBM 호환 PC에서 컴파일하여 ARM 기반의 임베디드 리눅스에서 실행 • 어려운 점 • 크로스 컴파일 환경을 직접 만들어야 하는 경우 있음 • 타겟 아키텍처에 대한 어셈블러와 링커를 찾아야 함 • 다음과 같은 파일을 아키텍처에 맞추어 구해야 함 • 헤더 파일 • 라이브러리 • 구동 파일
크로스 컴파일러 만들기 • 우선 만들어진 크로스 컴파일러를 찾는 것이 가장 중요함 • CPU • Memory • OS : 만약 OS를 만든다면 소스를 구해야 함 • Board Spec등에 따라서