- gcc 개요
- gcc의 실행 과정
- 전처리 과정: 전처리 부분에 명시된 헤더 파일을 삽입, 실행 문장의 메크로를 상수(문자열)로 변환한다.
- 컴파일 단계: 전처리 된 파일 *.i를 이용하여 컴파일러가 어셈블리어 파일 *.s로 변환한다.
- 어셈블 단계: 어셈블리어로 된 *.s파일을 이용하여 이진 코드로 이루어진 *.o 파일 을 생성한다.
- 링크 단계: 링커는 라이브러리 함수와 오브젝트 파일들을 연결해 실행 가능한 파일(a.out)을 생성한다.
- gcc 옵션
- GCC 전역 옵션
- gcc -v : gcc의 버전을 확인 한다.
- -o : 출력(output) 화일명을 지정한다.
- -c : 오직 컴파일(compile) 작업만 실행한다. 여러 개의 소스 파일(c or cpp)을 각각 컴파일하여 링크하는 경우에 사용한다.
- 전처리기(cpp0) 옵션
- -l : 헤더 파일을 탐색할 디렉토리를 지정 (예: -l/dir/include)
- -include [Header file path] : 해당 헤더 파일을 모든 소스에 추가 (예: -include /dir/my.h)
- -D[macro] : 프로그램 외부에서 매크로(프로그램 내의 #define 과 동일한 효과)를 지정 (예: -DDEBUG)
- -D[macro]=[macro value] : 프로그램 외부에서 해당 매크로를 정의하고 값을 지정 (예: -DDEBUG=1)
- -C : 전처리 과정에서 주석을 제거하지 않는다.
- -Wp,[Option list] : 옵션 리스트를 전처리기(preprocessor)에 바로 전달한다.
- C컴파일러(cc1) 옵션
- 최적화 옵션
- -O0 : 최적화를 수행하지 않는다.
- -O1 : 최적화 레벨 1을(-O0보다는 조금 낮은 수중)의 최적화를 수행한다.
- -O2 : 가장 많이 사용하는 옵션. 일반 응용 프로그램이나 커널을 컴파일 할 때 사용(거의 대부분의 최적화를 수행한다.)
- -O3 : 가장 높은 레벨의 최적화. 모든 함수를 인라인 함수와 같이 취급한다.
- -O5 : 메모리 사이즈 최적화를 실행한다.(메모리 공간이 작은 경우 사용 - 임베디드 시스템 등)
- 경고 옵션 : cc1의 옵션을 이용하여 경고 수위를 조절할 수 있다.
- -Wall : 모든 모호한 코딩에 대해서 경고를 보내는 옵션
- -W : 합법적이지만 모호한 코딩에 대해서 경고를 보내는 옵션
- -W -Wall : 아주 사소한 모호성에 대해서도 경고가 발생한다.
- -Werror : 모든 경고를 오류로 취급하여 컴파일 중단 한다.
- 어셈블리(as) 옵션
- -Wa,[Option list] : 어셈블러에게 옵션 리스트를 바로 전달한다.
- -Wa,-al : 어셈블된 코드와 인스트럭션을 보임
- -Wa,-as : 정의된 심볼을 보임
- 링크(ld) 옵션
- -L[path] : 라이브러리 탐색 디렉토리를 지정한다. (ex_: -L/dir/lib)
- -l[path] : 해당 라이브러리를 링크 (예: -lmylib)한다. (ex_: -L/dir/lib)
- -shared : 공유 라이브러리를 우선하여 링크
- -static : 정적 라이브러리를 우선하여 링크
- -nostdlib : 표준 C 라이브러리를 사용하지 않음
- -Wl,[Option list] : 옵션 리스트를 링커(linker)에 바로 전달한다.
- 디버깅 옵션
- -g : 바이너리(Binary) 파일에 디버깅 정보를 삽입한다.
gcc(GNU Compiler Collection)는 자선 단체인 자유 소프트웨어 재단(FSF: Free Software Foundation)의 지원으로 GNU(GNU's Not UNIX) 프로젝트에 의해 만들어진 c 컴파일러(Compiler) 이기 때문에 누구나 무료로 자유롭게 사용 할 수 있다. 원래 C 언어만 지원하여 GNU C 컴파일러 였지만 현재는 C(gcc), C++(g++), Java(gcj), Fortran(gfortran), Ada(GNAT) 등 여러 언어를 컴파일 할 수 있게 확장되었다.
gcc는 소스파일을 이용하여 실행파일을 만들때 필요한 프로그램을 아래 예와 같이 차례로 실행하여 실행 파일을 생성한다.
소스파일(.c/, .c++) --> 전처리기(preprocessor)(*.i) --> 컴파일러(*.s) --> 어셈블러(*.o) --> 링커(a.out)
예: gcc -o hello hello.c
위 명령을 실행하면 hello.c를 컴파일하고 링크하여 hello 라는 실행 파일이 생성(출력) 된다. hello 파일을 아래 명령으로 실행 할 수 있다.
./hello
예: gcc -c hello.c or gcc -c -o hello.o hello.c
- Make 설명을 위한 c project
- 위 예에서와 같이 main.c 파일을 컴파일하여 Object File(main.o)을 생성하기 위하여는 main.c, print-msg.h, function.h 이 필요하고,
- print-msg.c 파일을 컴파일하여 Object File(print-msg.o)을 생성하기 위하여는 print-msg.c, print-msg.h,
- function.c 파일을 컴파일하여 Object File(function.o)을 생성하기 위하여는 function.c, function.h 파일이 필요하다.
- Make utility를 사용하지 않고 Build 하기
- 위 예의 c project을 Built 하기 위하여는 아래 예와 같이 순차적으로 각 c 파일을 컴파일하여 Object 파일을 만든다.
- 실행 파일(a.out)은 위 명령에 의하여 생성된 Object 파일을 아래 예와 같이 Link 하여 생성한다.
- 윗 예는 개발 환경을 제공하는 툴(IDE) 없이 콘솔 명령을 사용하여 Built 하는 예로 여러개의 파일을 포함하는 큰 과제인 경우 불편하고 오류가 발생 할 가능성이 매우 크다. 이런 문제를 해결하기 위하여 아래와 같이 make 유틸리티(Utility)를 사용한다.
- Make utility를 사용하여 Build 하기
- 위 예의 c project을 Build 하기 위한 makefile(linux 상에서 반복적으로 발생하는 컴파일을 쉽게 하기 위해서 사용하는 make Utility 프로그램의 설정 파일) 예
Make 설명을 위한 c project는 아래 그림과 같이 main.c, print-msg.c, print-msg.h, function.c, function.h 3개의 c 파일과 2개의 헤더 파일로 구성되어 있다.
gcc -c -o main.o main.c
gcc -c -o print-msg.o print-msg.c
gcc -c -o function.o function.c
윗 명령에서 -c 옵션은 Link 하지 않고 컴파일만 하겠다는 의미 이고, -o 옵션은 Object 파일 이름을 지정하는 옵션이다.
gcc -o a.out main.o print-msg.o function.o
위 예의 c project을 make 유틸리티(Utility)를 사용 하여 Built 하는 예이다.
a.out: main.o print-msg.o function.o
gcc -o a.out main.o print-msg.o function.o
main.o: print-msg.h function.h main.c
gcc -g -Wall -c -o main.o main.c
print-msg.o: print-msg.h print-msg.c
gcc -g -Wall -c -o print-msg.o print-msg.c
function.o: function.h function.c
gcc -g -Wall -c -o function.o function.c
make
make Utility는 makefile(or Makefile)의 설정에 따라 Build 동작을 실행한다.
- Make Utility 와 Makefile
- Makefile은 프로그램의 어느 부분을 다시 컴파일 하여야 하는지 결정하고, 명령을 실행하는 규칙(Rule)의 모음이다.
- Makefile은 소프트웨어 Build를 진행하는 절차와 종속성이 있는 작업을 자동화하는 방법이다.
- Makefile에는 종속성 규칙(dependency rules)과 매크로(macros), suffix(or implicit) rules이 포함된다.
- Makefile의 기본 구조와 이해
- 종속성 규칙(dependency rules)
- Target의 기본형
- Phony targets
- Macros
- Macro의 정의는 아래와 같이 한다.
- 정의된 Macro는 아래와 같이 이름을 괄호 또는 중괄호로 묶고 앞에 $ 기호를 붙여서 사용(참조) 한다.
- Internal macros: Internal macros는 make에서 미리 정의된 macros 이다.
- 아래 명령은 현재 빌드에 적용되는 모든 macro, suffix rules, target 목록을 표시한다.
- Special macros
- @ 매크로는 현재 target의 이름을 삽입한다.
- 자주 사용하는 내부 매크로(Internal macro)
- $* : 확장자가 없는 현재의 대상(Target) 파일
- $@ : 현재의 대상(Target) 파일
- $< : 현재의 대상(Target) 파일보다 더 최근에 갱신된 파일 이름(Dependency중에서 처음에 위치한 파일 이름)
- $? : 현재의 대상(Target) 파일보다 더 최근에 갱신된 파일 이름(모든 dependency 파일의 이름)
- Suffix rules
- Doubles-suffix는 Source suffix와 Target suffix로 정의 된다.
- Suffix rules은 현재 호환성을 위해 지원되지만 더 이상 사용이 권장되지 않는다. 가능한 패턴 규칙(규칙에 문자 '%'이 포함됨)을 사용하는 것이 좋다.
- 아래와 같이 패턴 규칙은 위에서 Suffix rule을 사용한 경우와 같은 결과를 생성한다.
- 명령(Command line)에서 macros 정의하기
- Make 동작에 대한 이해
- Make utility는 대상 파일(Target file)의 수정 시간과 종속 파일(Dependency files)의 수정 시간을 비교하여 대상 파일보다 종속 파일의 수정 시간이 최근인 모든 대상 파일을 다시 생성한다.
- 기본적(By default)으로 첫 번째 대상 파일은 빌드된 결과 파일이다. 다른 대상은 첫 번째 대상에 대한 종속성 확인에 사용된다.
- Make utility는 필요한 순서대로 빌드하기 때문에 첫 번째 대상을 제외하고 대상의 순서는 중요하지 않다.
- 새로 작성된 Makefile 예
- Macro를 사용하여 작성한(위 c project을 Build 하기 위한) makefile 예
Make utility는 많은 파일로 구성된 프로그램을 유지 관리하기위한 소프트웨어 도구이다. Make utility는 큰 프로그램의 어떤 부분을 다시 컴파일 해야 하는지 자동으로 결정하고 명령을 실행하여 컴파일한다.
Make는 별도로 지정하지 않는 경우 makefile(make descriptor file)에서 실행 할 명령을 읽는다.
Rule은 세 가지 부분(하나 이상의 Target, 0개 이상의 종속성(Dependency), 0개 이상의 명령)으로 구성된다.
target: dependencies
<tab> target를 구현하는 명령(command)
<tab> 문자는 여백문자(Space)로 대치 할 수 없다.
"target"은 일반적으로 파일 이름(예: executable or object files) 또는 작업 이름(예: clean) 이다.
Rule의 각 “command”는 shell에 의하여 해석(Interpreted)되고 실행된다.
"make target" 형태의 명령을 입력하면 target의 모든 종속성이 최신 상태인지 확인하고, 최신 상태가 아닌 경우 지정된 명령을 사용하여 target을 다시 생성한다.
“make” 만 명령으로 입력하면 makefile 내의 첫번째 target이 생성된다.
Phony targets은 실제 파일이 아닌 종속성을 갖지 않는 command의 나열(List)이다.
예: clean:
rm -rf *.o
Macro를 사용하면 반복되는 텍스트 입력을 피할 수 있으며 makefile을 쉽게 수정할 수 있다.
NAME = text string
예: CC = gcc
$(CC) main.o print-msg.o function.o -o a.out
윗 예에서 "$(CC)"는 "gcc"로 대치되어 "gcc main.o print-msg.o function.o -o a.out"과 동알한 명령이 된다.
make -p
예:
target1: $(objs):
$(CXX) -o $@ $(objs)
위 설정은 아래 설정과 같다.
target1: $(objs):
$(CXX) -o target1 $(objs)
main.o : main.c io.h
gcc -c $*.c
$* 는 확장자가 없는 현재의 대상 파일이므로 $* 는 main에 해당된다.
test : $(OBJECTS)
gcc –o $@ $*.c
$@ 는 현재의 대상 파일이므로 $* 는 test에 해당된다.
.c .o :
gcc -c $< (또는 gcc -c $*.c)
$< 는 현재의 대상 파일보다 더 최근에 갱싱된 파일 이름이므로, .o 파일보다 더 최근에 갱신된 .c 파일은 자동적으로 컴파일 된다.
이중 접미사와 단일 접미사를 이용하여 Default rules 또는 Implicit rules을 정의하여 프로그램을 작성하는 데 사용할 수 있다.
예:
.cpp.o:
$(CC) $(CFLAGS) -c $<
위 규칙은 make에게 .cpp 파일을 사용하여 .o 파일을 생성하게 한다.
위에서 $< 는 .o 파일을 생성하는 데 사용되는 .cpp 파일을 나타내는 특수 매크로이다.
예:
%.o: %.cpp
$(CC) $(CFLAGS) -c $<
Macro는 명령에서 정의 할 수 있다.
예:
make DEBUG_FLAG=-g
위 경우 DEBUG_FLAG는 -g로 정의된다.
# This is a comment line
CC = gcc
# CFLAGS will be the options passed to the compiler.
CFLAGS = -g -Wall
OBJS = main.o print-msg.o function.o
TARGET = a.out
$(TARGET): $(OBJS)
$(CC) ${CFLAGS} -o $@ $(OBJS)
%.o: %.c
$(CC) $(CFLAGS) -c $<
clean:
-rm -f *.o
-rm -f $(TARGET)
#Dependency check
main.o: print-msg.h function.h main.c
print-msg.o: print-msg.h print-msg.c
function.o: function.h function.c
make
make clean
참고자료: http://www.gnu.org/software/make/manual/html_node/