반응형
출처 : https://wiki.kldp.org/KoreanDoc/html/GNU-Make/GNU-Make-1.html
make 유틸리티
- make : 만들다.라는뜻
- man make
- 프로그램 그룹에서 어느 부분이 새롭게 컴파일 되어야 하는지 자동적으로 판단하여 필요한 커맨드(gcc 등)을 이용해 그들을 재컴파일 시킴.
make가 사용되는 경우
- 입력파일이 바뀌어 자동적으로 결과 파일이 바뀌기 원할 때
- LaTex 파일 처럼 자동적으로 프로그램이 수행되길 바랄 때 (batch의 개념)
- latex 프로그램 : 문서 조판에 사용되는 프로그램 == 매크로 스크립트
- <latex 구성도>
- latex make 다루기
- makefile 구성전 1차적 명령어12% latex make.tex <- make.dvi 가 만들어진다.% dvips make.dvi -o <- make.ps 가 만들어진다.
- makefle 만듦123456make.ps : make.dvidvips make.dvi -omake.dvi : make.texlatex make.tex
- makefile에 매크로 추가123456789101112.SUFFIXES : .tex .dviTEX = latex <- TEX 매크로를 재정의PSFILE = make.psDVIFILE = make.dvi$(PSFILE) : $(DVIFILE)dvips $(DVIFILE) -omake.ps : make.dvimake.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 test1.o test2.o test3.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
- 1234567891011121314151617181920.SUFFIXES : .c .oOBJECTS = main.o read.o write.oSRCS = 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) coremain.o : io.h main.c <- (1)read.o : io.h read.cwrite.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 만들 때 팁
- 긴 명령어를 여러 라인으로 표시
- \를 이용
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) 형식으로 치환
- 예시
- 12MY_NAME = Michael JacksonYOUR_NAME = $(NAME:Jack=Jook)
- 자동 의존 관계 생성 (Automatic dependency)
- make 구조는 target, dependency, command가 연쇄적으로 정의된 구조.123target : dependencycommand...
- 자동으로 의존관계를 생성하는 유틸리티
>> gccmakedep - 파일의 의존관계를 조사하여 자동으로 Makefile의 뒷부분에 추가해주는 도구
make dep 기능 추가
- 의존관계를 작성해주는 것
- 1234567891011.SUFFIXES : .c .oCFLAGS = -O2 -gOBJS = main.o read.o write.oSRCS = $(OBJS:.o=.c)test : $(OBJS)$(CC) -o test $(OBJS)dep :gccmakedep $(SRCS)
- 다중 타겟(Multiple target)
- 여러개의 결과 파일이 필요한 경우
- 12345678910111213141516171819202122.SUFFIXES : .c .oCC = gccCFLAGS = -O2 -gOBJS1 = main.o test1.o <- 각각의 매크로를 정의OBJS2 = main.o test2.oOBJS3 = main.o test3.oSRCS = $(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을 동작시킬 필요가 있을 경우 사용
- 12345subsystem:cd subdir; $(MAKE) .....(1)subsystem:$(MAKE) -C subdir .....(2)
- subsystem이란 타겟에서 subdir로 이동하여 Makefile을 동작하는 구조
- (1)과 (2)는 동일한 명령을 수행함.
- ex 2)1234567891011.SUFFIXES : .c .oCC = gccCFLAGS = -O2 -gall : 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, ranlib123456% ar rcv libio.a read.o write.oa - read.o <- 라이브러리에 추가 (add)a - write.o% ranlib libio.a <- libio.a의 색인(index)을 생성
- makefile12345TARGET = libio.a$(TARGET) : $(OBJS)$(AR) rcv $@ $(OBJS) <- ar rcv libio.a read.o write.oranlib $@ <- 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 지정 - 12% gcc -c test.c% gcc -o test test.o -L. -lio <- 현재 디렉토리에 있다고 가정
- Makefile
- 12345678910111213141516171819202122.SUFFIXES : .c .oCC = gccINC =LIBS =CFLAGS = -g $(INC) -fPIC <- -fPIC 추가OBJS = read.o write.oSRCS = read.c write.cTARGET = 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: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/침입차단시스템/Snort (0) | 2017.11.30 |
---|---|
Linux/Kernel-analysis/LXR 개발환경 구축하기 (0) | 2017.11.21 |
Linux/2-factor-Authentication/GoogleOTP사용하기 (0) | 2017.11.07 |
Linux/Unix/파일 - 일반 파일, 장치 파일, 디렉토리 (0) | 2017.11.02 |
Linux/웹방화벽/ModSecurity (0) | 2017.10.31 |