반응형
make 유틸리티
- make : 만들다.라는뜻
- man make
- 프로그램 그룹에서 어느 부분이 새롭게 컴파일 되어야 하는지 자동적으로 판단하여 필요한 커맨드(gcc 등)을 이용해 그들을 재컴파일 시킴.
make가 사용되는 경우
- 입력파일이 바뀌어 자동적으로 결과 파일이 바뀌기 원할 때
- LaTex 파일 처럼 자동적으로 프로그램이 수행되길 바랄 때 (batch의 개념)
- latex 프로그램 : 문서 조판에 사용되는 프로그램 == 매크로 스크립트
- <latex 구성도>
- latex make 다루기
- makefile 구성전 1차적 명령어
1
2
|
% latex make.tex <- make.dvi 가 만들어진다.
% dvips make.dvi -o <- make.ps 가 만들어진다.
|
- makefle 만듦
1
2
3
4
5
6
|
make.ps : make.dvi
dvips make.dvi -o
make.dvi : make.tex
latex make.tex
|
- makefile에 매크로 추가
1
2
3
4
5
6
7
8
9
10
11
12
|
.SUFFIXES : .tex .dvi
TEX = latex <- TEX 매크로를 재정의
PSFILE = make.ps
DVIFILE = make.dvi
$(PSFILE) : $(DVIFILE)
dvips $(DVIFILE) -o
make.ps : make.dvi
make.dvi : make.tex
|
GNU make
- GNUmakefile, Makefile, makefile 중 하나가 있으면 그파일을 읽음.
- Makefile의 구성은 makefile database로 불리우는 일종의 쉘 스크립트 언어 같이 구성된다.
Make의 필요성
- 개발과 유지
- 라인수가 늘어나면서 소스의 관계성에 따라 우리가 필요에 의해 그 파일의 함수를 바꿀 때 다른 연관된 소스의 함수도 바꿔 새롭게 컴파일 되어야하는 것.
- 컴파일에 필요없는 것을 컴파일 할 수 있고, 컴파일해야 할것을 하지 않을 수도 있다.
Makefile 내부구조
- 목표(target), 의존 관계(dependency), 명령(command)로 구성된 규칙(rule).
- 목표 : 명령을 수행(목적 파일== object file을 실행한)한 결과 파일을 지정.
>> 쉘 스크립트도 지원.
>> 명령 부분은 TAB으로 시작 해야하는 문법 규칙(안지키면 make 실행 중 에러) make가 명령어가 맞는지 아닌지 인식하는 규칙.
Gcc 컴파일 과정
- 명령어
- $ gcc -c test1.c
- $ gcc -c test2.c
- $ gcc -c test3.c
- $ gcc -o output.out main.o read.o write.o
Make 컴파일 과정
- 소스
1
2
3
4
5
6
7
8
9
|
output.out : test1.o test2.o test3.o
gcc -o output.out test1.o test2.o test3.o
test1.o : test1.c
gcc -c test1.c
test2.o : test2.c
gcc -c test2.c
test3.o: test3.c
gcc -c test3.c
|
- 의존성 구조
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
+---------------+
| 헤더파일 |
+------+--------+
|
+---------+----------+
| |
+--------------+ | +------+-------+ | +--------------+
| test1.c | | | test2.c | | | test3.c |
+------+-------+ | +------+-------+ | +------+-------+
| | | | |
+------+-------+ | +------+-------+ | +------+-------+
| test1.o +--+--| test2.o | +--+ test3.o |
+------+-------+ +------+-------+ +------+-------+
| | |
+--------------------+--------------------+
+-------|-------+
| output.out |
+------+--------+
|
- 경우 1: 헤더파일이 바뀌었다고 하면 모든 파일이 컴파일 되어 목적파일.o 이생기고 그것들이 다시링크되어 output.out이 생긴다.
- 경우 2: test1.c 만 고쳤다면 test1.c이 컴파일되어 main.o가 생기고 output.out이 다시 고쳐진다.
Make 매크로의 사용
- output.out : test1.o test2.o test3.o 부분을 매크로로 고친다.
- 대체한 매크로는 반드시 $(..)에 넣어서 사용한다.
1
2
3
4
5
6
7
8
9
10
11
|
OBJECTS = test1.o test2.o test3.o
output.out : $(OBJECTS)
gcc -o output.out $(OBJECTS)
test1.o : test1.o
gcc -c test1.c
test2.o : test2.c
gcc -c test2.c
test3.o : test3.c
gcc -c test3.c
|
Make 레이블의 사용
- 레이블로 사용될 때는 의존성 관계 부분이 존재하지 않아도 된다.
- 목표 파일의 매크로는 레이블과 같이 사용 될 수 있다.
1
2
3
4
5
6
7
8
9
10
11
|
OBJECTS = test1.o test2.o test3.o
output.out : $(OBJECTS)
gcc -o output.out $(OBJECTS)
test1.o : test1.o
gcc -c test1.c
test2.o : test2.c
gcc -c test2.c
test3.o : test3.c
gcc -c test3.c
clean :
rm $(OBJECTS)
|
- clean 명령은 make clean으로 사용.
매크로(macro)와 접두사(Suffix) 규칙
- 매크로란 무엇인가?
- 로터스, 한글, 엑셀 등의 모든 패키지는 매크로라는 것을 사용
- 특정한 코드를 간단하게 표현하는 것.
- 매크로 정의 - 프로그램을 작성할 때 변수 지정하는 것과 동일
미리 정해져있는 매크로 (Pre-defined macro)
- make -p : make에 미리 세팅되어 있는 모든 값들이 출력됨.
- 모든 값들(매크로, 환경 변수 (environment) 등 )
- 매크로를 재 정의한다면 충분히 재 작성해야하는 부분
- 매크로는 관습적으로 대문자로 작성
접두사 규칙 (Suffix rule)
- 매크로를 제공하고 있는 이유이며, 어떻게 매크로를 이용하는지에 대한 해답
- 파일의 확장자 보고 그에 따라 적절한 연산을 수행시키는 규칙
- .SUFFIXES 매크로
- make파일에게 주의 깊게 처리할 파일들의 확장자를 등록할 수 있다.
- ex) .SUFFIXES : .c .o
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
.SUFFIXES : .c .o
OBJECTS = main.o read.o write.o
SRCS = main.c read.c write.c <- 없어도 됨
CC = gcc <- gcc 로 세팅
CFLAGS = -g -c <- gcc 의 옵션에 -g 추가
TARGET = test <- 결과 파일을 test 라고 지정
$(TARGET) : $(OBJECTS)
$(CC) -o $(TARGET) $(OBJECTS)
clean :
rm -rf $(OBJECTS) $(TARGET) core
main.o : io.h main.c <- (1)
read.o : io.h read.c
write.o: io.h write.c
|
- 추가적으로 CFLAGS를 이용하지 않았지만 make파일 내부에서 이용되어 컴파일할때 이용된다.
make 내부에서 기본적으로 서비스를 제공해 주는 확장자 리스트
- .SUFFIXES 매크로 설정이 필요
접두사 규칙을 구현한 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
.SUFFIXES : .c .o
OBJECTS = main.o read.o write.o
SRCS = main.c read.c write.c
CC = gcc
CFLAGS = -g -c
INC = -I/home/raxis/include <- include 패스 추가
TARGET = test
$(TARGET) : $(OBJECTS)
$(CC) -o $(TARGET) $(OBJECTS)
.c.o : <- 우리가 확장자 규칙을 구현
$(CC) $(INC) $(CFLAGS) $<-
clean :
rm -rf $(OBJECTS) $(TARGET) core
main.o : io.h main.c
read.o : io.h read.c
write.o : io.h write.c
|
내부 매크로 (Internal macro)
- 사용자 임의로 정할 수 없는 매크로
- 내부 매크로를 연산, 처리 하는데 사용
1
2
3
4
5
6
7
|
$* <- 확장자가 없는 현재의 목표 파일(Target)
$@ <- 현재의 목표 파일(Target)
$< <- 현재의 목표 파일(Target)보다 더 최근에 갱신된 파일 이름
$? <- 현재의 목표 파일(Target)보다 더 최근에 갱신된 파일이름
|
Makefile 만들 때 팁
- 긴 명령어를 여러 라인으로 표시
- \를 이용
- 확장자 규칙 이용
- 아래 규칙은 따로 정의 하지 않은 상태에서 바로 이용할 수 있는 것들
- C 컴파일 (XX.c -> XX.o)
- C++ 컴파일 (XX.cc 또는 XX.C -> XX.o)
- Pascal 컴파일 (XX.p -> XX.o)
- Fortran 컴파일 (XX.f 또는 XX.F -> XX.o)
- Modula-2 컴파일 (XX.def -> XX.sym)
- (XX.mod -> XX.o)
- assembly 컴파일 (XX.s -> XX.o)
- assembly 전처리 (XX.S -> XX.s)
- single object file 의 링크 (XX.o -> XX)
- Yacc 컴파일(?) (XX.y -> XX.o)
- Lex 컴파일(?) (XX.l -> XX.o)
- lint 라이브러리 생성 (XX.c -> XX.ln)
- tex 파일 처리 (XX.tex -> XX.dvi)
- texinfo 파일처리 (XX.texinfo 또는 XX.texi -> XX.dvi)
- RCS 파일 처리 (RCS/XX,v -> XX)
- SCCS 파일처리 (SCCS/XX.n -> XX)
- 재 정의 해야할 것들
- AR = ar (Archive maintaining program)
- AS = as (Assembler)
- CC = cc (= gcc , C compiler)
- CXX = g++ (C++ compiler)
- CO = co (extracting file from RCS)
- CPP = $(CC) -E (C preprocessor)
- FC = f77 (Fortran compiler)
- LEX = lex (LEX processor)
- PC = pc (Pascal compiler)
- YACC = yacc (YACC processor)
- TEX = tex (TEX processor)
- TEXI2DVI = texi2dvi (Texiinfo file processor)
- WEAVE = weave (Web file processor)
- RM = rm -f (remove file)
- 플래그 옵션
- ARFLAGS = (ar achiver의 플래그) *
- ASFLAGS = (as 어셈블러의 플래그)
- CFLAGS = (C 컴파일러의 플래그) *
- CXXFLAGS = (C++ 컴파일러의 플래그) *
- COFLAGS = (co 유틸리티의 플래그)
- CPPFLAGS = (C 전처리기의 플래그)
- FFLAGS = (Fortran 컴파일러의 플래그)
- LDFLAGS = (ld 링커의 플래그) *
- LFLAGS = (lex 의 플래그) *
- PFLAGS = (Pascal 컴파일러의 플래그)
- YFLAGS = (yacc 의 플래그) *
- * >> 자주쓰이는 플래그
- 매크로 치환 (Macro substitution)
- 자동 의존 관계 생성 (Automatic dependency)
- make 구조는 target, dependency, command가 연쇄적으로 정의된 구조.
1
2
3
|
target : dependency
command
...
|
- 자동으로 의존관계를 생성하는 유틸리티
>> gccmakedep - 파일의 의존관계를 조사하여 자동으로 Makefile의 뒷부분에 추가해주는 도구
make dep 기능 추가
- 의존관계를 작성해주는 것
1
2
3
4
5
6
7
8
9
10
11
|
.SUFFIXES : .c .o
CFLAGS = -O2 -g
OBJS = main.o read.o write.o
SRCS = $(OBJS:.o=.c)
test : $(OBJS)
$(CC) -o test $(OBJS)
dep :
gccmakedep $(SRCS)
|
- 다중 타겟(Multiple target)
- 여러개의 결과 파일이 필요한 경우
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
.SUFFIXES : .c .o
CC = gcc
CFLAGS = -O2 -g
OBJS1 = main.o test1.o <- 각각의 매크로를 정의
OBJS2 = main.o test2.o
OBJS3 = main.o test3.o
SRCS = $(OBJS1:.o=.c) $(OBJS2:.o=.c) $(OBJS3:.o=.c)
all : test1 test2 test3 <- 요기에 주의
test1 : $(OBJS1)
$(CC) -o test1 $(OBJS1)
test1 : $(OBJS2)
$(CC) -o test2 $(OBJS2)
test1 : $(OBJS3)
$(CC) -o test3 $(OBJS3)
dep :
gccmakedep $(SRCS)
|
- 순환 make (Recursive MAKE)
- 각각의 서브 디렉토리에 존재하는 여러 개의 Makefile을 동작시킬 필요가 있을 경우 사용
1
2
3
4
5
|
subsystem:
cd subdir; $(MAKE) .....(1)
subsystem:
$(MAKE) -C subdir .....(2)
|
- subsystem이란 타겟에서 subdir로 이동하여 Makefile을 동작하는 구조
- (1)과 (2)는 동일한 명령을 수행함.
- ex 2)
1
2
3
4
5
6
7
8
9
10
11
|
.SUFFIXES : .c .o
CC = gcc
CFLAGS = -O2 -g
all : DataBase Test <- 요기에 집중.
DataBase:
cd db ; $(MAKE) <- db 로 이동해서 make 실행
Test:
cd test ; $(Make) <- db 로 이동해서 make 실행
|
- 불필요한 재컴파일 막기
- 의존 관계 규칙에 따라 하나가 바뀌면 그 영향을 받는 모든 파일이 바뀌지만, 한가지 예외에서 다른 파일에 아무 영향을 주지 않도록 수정하였는데도 다른 파일을 재컴파일 시도한다면 시간적 낭비가 있다.
- make -t : touch 옵션으로 써 새 컴파일을 하지 않는 대신 생성 날짜만 가장 최근으로 변경함.
Make 중요 옵션
- -c dir : Makefile을 읽지 말고 dir로 이동
- -d : Makefile을 수행하면서 정보를 출력함 (-debug옵션)
- -h : 설명
- -f file : file 인자에 해당하는 파일을 Makefile로 취급함
- -r : 내장하고 있는 각 종 규칙을 없는 것으로 간주.
- -t : 파일의 생성날짜를 현재 시간으로 생성
- -v : make의 버전을 출력
- -p : 내부적으로 세팅되는 값을 출력
- -k : 에러가 나더라도 계속 실행
라이브러리와 링크가 필요한 Makefile
- 필요한 도구
- ar, ranlib
1
2
3
4
5
6
|
% ar rcv libio.a read.o write.o
a - read.o <- 라이브러리에 추가 (add)
a - write.o
% ranlib libio.a <- libio.a의 색인(index)을 생성
|
- makefile
1
2
3
4
5
|
TARGET = libio.a
$(TARGET) : $(OBJS)
$(AR) rcv $@ $(OBJS) <- ar rcv libio.a read.o write.o
ranlib $@ <- ranlib libio.a
|
동적 라이브러리 만들기
1
2
3
4
|
% 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
|
- 동적 라이브러리 사용법
- /usr/lib로 파일을 옴겨 ldconfig -v 로 설정 갱신 또는 LB_LIBRARY_PATH 지정
1
2
|
% gcc -c test.c
% gcc -o test test.o -L. -lio <- 현재 디렉토리에 있다고 가정
|
- Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
.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
|
Make 수행시 나타나는 에러들
- Makefile:17: *** missing separator. Stop.
>> TAB을 쓰지않아 발생 >> 17번줄 근처를 TAB문자로 시작하게 바꿈 - make: *** No rule to make target `io.h', needed by `read.o'. Stop.
>> 의존 관계에서 문제가 발생 >> io.h를 찾을 수 없음. - Makefile:10: *** commands commence before first target. Stop.
>> 첫번째 타겟이 나오기 전에 명령어가 시작되었다는 에러 >> \ 부분은 라인의 가장 끝문자가 되어야함 즉, \ 뒷 부분에 스페이스를 넣었거나 하는 경우 발생. - 컴파일 했던 파일을 고치지 않았는데도 다시 컴파일 >> make가 의존 관계를 모르기 때문에 발생 >> 의존 관계 재생성.
반응형
'System > Linux' 카테고리의 다른 글
Linux/Virtual Environment/Docker/Dockerfile 사용하기 (0) | 2017.12.18 |
---|---|
Linux/Virtual Environment/Docker/도커 시작하기 (0) | 2017.12.18 |
Linux/침입차단시스템/Snort (0) | 2017.11.30 |
Linux/Kernel-analysis/LXR 개발환경 구축하기 (0) | 2017.11.21 |
Linux/Makefile 정리 (0) | 2017.11.16 |