티스토리 뷰
7. Makefile의 실제 예제
지금까지 강좌를 진행하면서 Makefile
의 여러 가지 예제들을 제시하였다. 강좌에 나온 예제들을 조금만 바꾸면 자신의 Makefile
로써 사용할 수 있다. 여기에서는 여러 가지 Makefile
들의 기본틀(template)들을 소개하고자 한다.
7.1 프로그램 제작에 쓰일 수 있는 Makefile
여기서는 우선 가장 많이 사용되는 C와 C++에서의 Makefile
을 소개하기로 한다. 여러 개의 파일들을 컴파일해서 하나의 실행 파일을 만드는 예제 틀이 바로
.SUFFIXES : .c .o CC = gcc INC = <- include 되는 헤더 파일의 패스를 추가한다. LIBS = <- 링크할 때 필요한 라이브러리를 추가한다. CFLAGS = -g $(INC) <- 컴파일에 필요한 각종 옵션을 추가한다. OBJS = <- 목적 파일의 이름을 적는다. SRCS = <- 소스 파일의 이름을 적는다. TARGET = <- 링크 후에 생성될 실행 파일의 이름을 적는다. all : $(TARGET) $(TARGET) : $(OBJS) $(CC) -o $@ $(OBJS) $(LIBS) dep : gccmakedep $(INC) $(SRCS) clean : rm -rf $(OBJS) $(TARGET) core new : $(MAKE) clean $(MAKE)
% make dep <- 자동으로 의존 관계 생성 % make <- make 동작
지금까지의 강좌를 이해하고 있다면 위의 Makefile
의 독해란 어렵지 않을 것이다. 개략적인 사항만 설명하기로 한다.
- .SUFFIXES : .c .o
-
make 내부에서 정의된 확장자 규칙을 이용하기 위한 것이다. make는 자동적으로 .c와 .o로 끝나는 파일들간에 정의된 규칙이 있는지 찾게 되고 적당한 규칙을 찾아서 수행하게 된다.
- CFLAGS = -g $(INC)
-
CFLAGS 매크로를 재정의 하고 있다. -g 는 디버그 정보를 추가하라는 것이고, $(INC)는 컴파일할때 필요한 include 패스를 적어 두는 곳이다.
- all : $(TARGET)
-
make는
Makefile
을 순차적으로 읽어서 가장 처음에 나오는 규칙을 수행하게 된다. 여기서 all 이란 더미타겟(dummy target)이 바로 첫 번째 타겟으로써 작용하게 된다. 관습적으로 all이란 타겟을 정의해 두는 것이 좋다. 결과 파일이 많을 때도 all의 의존 관계(dependency)로써 정의해 두면 꽤 편리하다. - dep : gccmakedep $(INC) $(SRCS)
-
의존 관계를 자동적으로 생성해 주기 위한 것이다. 헤더 파일의 패스까지 추가되어야 한다는 것에 주의하기 바람. 이것은 내부적으로 gcc가 작동되기 때문이다.
.SUFFIXES : .cc .o CXX = g++ CXXFLAGS = -g $(INC) $(TARGET) : $(OBJS) $(CXX) -o $@ $(OBJS) $(LIBS)
물론 각자의 취향에 따라서 Makefile
을 만들어도 된다. 여기서 제시하고 있는 Makefile
은 어디까지나 필자의 관점에서 만든 Makefile
을 소개하고 있는 것뿐이니까...
7.2 라이브러리와의 링크가 필요한 필요한 Makefile
라이브러리를 만들기 위한 Makefile
은 어떤 차이가 있을까.
=> 참고: 라이브러리 만드는 방법을 소개하기로 한다. read.o, write.o를 libio.a로 만들어 보자. 라이브러리를 만들기 위해서는 ar 유틸리티와 ranlib 유틸리티가 필요하다. (자세한 설명은 man 을 이용)
% ar rcv libio.a read.o write.o a - read.o <- 라이브러리에 추가 (add) a - write.o % ranlib libio.a <- libio.a의 색인(index)을 생성
그럼 위의 과정을 Makefile
로 일반화시킨다면 어떻게 될까? 아주 조금만 생각하면 된다.
TARGET = libio.a $(TARGET) : $(OBJS) $(AR) rcv $@ $(OBJS) <- ar rcv libio.a read.o write.o ranlib $@ <- ranlib libio.a
ELF 기반에서 동적 라이브러리(dynamic library, shared library)를 만들어 보기로 하자. ELF 상에서는 동적 라이브러리 만드는 방법이 이전에 비해 아주 간단해 졌다. (옛날에 모티프 소스 가지고 동적 라이브러리 만든다고 고생한 것에 비하면 세상이 너무 좋아진 것 같음) BSD계열의 유닉스를 사용해 본 사람이라면 비슷하다는 것을 느낄 것이다. 그럼 read.c write.c를 컴파일해서 libio.so.1을 만들어 보자.(so는 shared object를 의미, 뒤의 .1은 동적 라이브러리의 버전을 의미)
% gcc -fPIC -c read.c <- -fPIC을 추가해서 컴파일한다. % gcc -fPIC -c write.c % gcc -shared -Wl,-soname,libio.so.1 -o libio.so.1 read.o write.o
동적 라이브러리를 만들기 위한 옵션
위와 같이 하면 libio.so.1 가 생성된다. 사용자가 만든 동적 라이브러리를 사용하는 방법에 대해서는 간단히만 언급하기로 한다. 우선 libio.so.1 을 /usr/lib로 옮겨서 ldconfig -v 해서 라이브러리 설정을 갱신해 주던지, 아니면 LD_LIBRARY_PATH를 지정해 두면 된다. 아래는 test.c를 libio.so.1과 링크 시키는 예제이다.
% gcc -c test.c % gcc -o test test.o -L. -lio <- 현재 디렉토리에 있다고 가정
Makefile
을 소개한다.
.SUFFIXES : .c .o CC = gcc INC = LIBS = CFLAGS = -g $(INC) -fPIC <- -fPIC 추가 OBJS = read.o write.o SRCS = read.c write.c TARGET = libio.so.1 <- libio.so.1이 최종 파일 all : $(TARGET) $(TARGET) : $(OBJS) $(CC) -shared -Wl,-soname,$@ -o $@ $(OBJS) dep : gccmakedep $(INC) $(SRCS) clean : rm -rf $(OBJS) $(TARGET) core
아주 조금밖에 바뀌지 않았다. 따라서 이 글을 읽는 여러분은 이제 각자의 목적에 맞게 Makefile
을 구성할 수 있을 것이다. 대부분 확장자 규칙과 최종 파일을 생성해 내기 위한 명령어가 무엇인지 알고 있으면 Makefile
을 자기 개성껏 꾸밀 수 있을 것이다.
7.3 LaTeX에서 쓰일 수 있는 Makefile
Makefile
이 쓰일 수 있는 다른 예로써 가장 대표적인 것이 latex를 사용할 때이다. 이미 이전 강좌에서 여러 차례 소개된 적도 있다. 그럼 doc.tex를 doc.ps로 만들어 보기로 하자. 약간 어렵게 하기 위해서 doc.tex는 내부적으로 intro.tex 와 conclusion.tex를 포함하고 있다고 가정한다. (논문 같은 것을 작성할 때는 이렇게 .tex 파일이 많아지게 된다.)
% latex doc.tex <- doc.dvi의 생성 % dvips doc.dvi -o <- doc.tex의 생성
위와 같은 일을 수행하는 Makefile
을 한번 살펴보자.
.SUFFIXES : .tex .dvi <- 확장자 규칙 TEX = latex OBJ = doc.dvi SRC = doc.tex TARGET = doc.ps <- 결과 파일 all : $(TARGET) $(TARGET) : $(OBJ) dvips $(OBJ) -o <- dvips doc.dvi -o new : <- 강제적으로 다시 make touch $(SRC) ; $(MAKE) doc.tex : intro.tex conclusion.tex <- 의존 관계 설정
=> 참고로 gccmakedep는 latex 파일은 지원을 하지 않는 것 같다. 따라서 의존 관계 같은 것은 우리가 직접 적어 주어야 한다.
여기에서 제시된 응용 말고 그 외의 다른 응용에 대해서는 각자가 한번 생각해 보기 바란다. 타이핑하기 귀찮은 것은 모조리 make를 이용할 수 있다는 것을 염두. 약간은 원인, 결과를 따지는 논리(?)가 적용된다고 볼 수도 있는 것이 make 라는 것을 기억하기 바람. (삼단논법 정도만 안다면야...)
'Development > CM&CI&CD' 카테고리의 다른 글
[Git] Project 진행 중 Github Repo를 만들고 합치기 (0) | 2019.12.24 |
---|---|
[GIT] GIT 실행 안되는 문제 (0) | 2019.04.24 |
[GIT] Host별로 ssh publickey / privatekey 따로 관리하기 (0) | 2016.11.09 |
GNU Make 강좌 #8 - make 수행 시에 나타나는 에러들 (0) | 2010.04.05 |
GNU Make 강좌 #6 - Makefile 작성의 가이드라인 (0) | 2010.04.05 |
GNU Make 강좌 #5 - make 중요 옵션 정리 (0) | 2010.04.05 |
GNU Make 강좌 #4 - Makefile를 작성할 때 알면 좋은 것들 (0) | 2010.04.05 |
GNU Make 강좌 #3 - 매크로(Macro) 와 확장자(Suffix) 규칙 (2) | 2010.04.05 |
- Total
- Today
- Yesterday
- NDK
- gcc
- android
- jni
- C
- db
- kering
- 프로그래밍
- it
- algorithm
- database
- MFC
- AWS
- jni강좌
- 드라이버
- Troubleshooting
- 안드로이드
- linux
- Cloud
- Quiz
- 리눅스
- API
- driver
- winapi
- Visual C++
- Python
- 음악
- source
- C++
- java
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |