본문 바로가기

System/Linux

Linux/Make/Makefile 정리

반응형
make 유틸리티
- make : 만들다.라는뜻
- man make
  • 프로그램 그룹에서 어느 부분이 새롭게 컴파일 되어야 하는지 자동적으로 판단하여 필요한 커맨드(gcc 등)을 이용해 그들을 재컴파일 시킴.
 
make가 사용되는 경우
- 입력파일이 바뀌어 자동적으로 결과 파일이 바뀌기 원할 때
- LaTex 파일 처럼 자동적으로 프로그램이 수행되길 바랄 때 (batch의 개념)
    • latex 프로그램 : 문서 조판에 사용되는 프로그램 == 매크로 스크립트
    • <latex 구성도>
    • latex make 다루기
      • makefile 구성전 1차적 명령어
1
2
% latex make.tex <- make.dvi 가 만들어진다.
% dvips make.dvi -<- 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 = --<- 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 내부에서 기본적으로 서비스를 제공해 주는 확장자 리스트
 
리스트
.out .a .ln .o .c .cc .C .p .f .F .r .y .l .s .S .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo .w .ch .web .sh .elc .el

 

  • .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 = --
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 만들 때 팁
- 긴 명령어를 여러 라인으로 표시
  • \를 이용
 
1
2
3
4
5
OBJS = shape.o \
rectangle.o \
circle.o \
line.o \
bezier.o 
 
 
- 확장자 규칙 이용
  • 아래 규칙은 따로 정의 하지 않은 상태에서 바로 이용할 수 있는 것들
    • 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)
    • $(MACRO_NAME:OLB=NEW) 형식으로 치환
    • 예시
 
1
2
MY_NAME = Michael Jackson
YOUR_NAME = $(NAME:Jack=Jook)
 
 
- 자동 의존 관계 생성 (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
 
- read.o <- 라이브러리에 추가 (add)
- 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 수행시 나타나는 에러들
  1. Makefile:17: *** missing separator. Stop.
    >> TAB을 쓰지않아 발생 >> 17번줄 근처를 TAB문자로 시작하게 바꿈
  2. make: *** No rule to make target `io.h', needed by `read.o'. Stop.
    >> 의존 관계에서 문제가 발생 >> io.h를 찾을 수 없음.
  3. Makefile:10: *** commands commence before first target. Stop.
    >> 첫번째 타겟이 나오기 전에 명령어가 시작되었다는 에러 >> \ 부분은 라인의 가장 끝문자가 되어야함 즉, \ 뒷 부분에 스페이스를 넣었거나 하는 경우 발생.
  4. 컴파일 했던 파일을 고치지 않았는데도 다시 컴파일 >> make가 의존 관계를 모르기 때문에 발생 >> 의존 관계 재생성.
 

 

반응형