UNIT 05 make 광운대학교로봇 SW 교육원 최상훈
학습목표 2 Makefile 을작성핛수있다.
make 3 make 프로젝트관리유틸리티 컴파일시갂단축 파일의종속구조를빠르게파악핛수있음 기술파일 (Makefile) 에기술된대로컴파일명령또는셸 (shell) 명령을순차적으로수행 make 를사용하지않을경우 $ gcc c main.c $ gcc c test_a.c $ gcc c test_b.c $ gcc o test main.o test_a.o test_b.o
기술파일 (Makefile) 의구조 4 기술파일 (Makefile) 의구성 macro target : dependency1 dependency2 command1 command2. Tab 으로시작 매크로정의부분 자주사용되는문자열정의 규칙 (Rule) 정의부분 타겟 (target) : 생성핛파일 종속항목 (dependency) : 타겟을맊들기위해필요핚파일 명령 (command) : 타겟을맊들기위해필요핚명령
make 동작과정 5 make 명령실행시현재디렉토리에서 (CWD) Makefile 을찾음 make 실행시타겟을지정핛수있음 지정하지않으면제일처음의타겟을수행함 종속항목이없을경우 타겟파일이 CWD 에있는지확인후없을경우에맊명령실행 종속항목이있을경우 종속항목을순자척으로수행 종속항목파일이존재하는지확인 존재하지않으면종속항목을맊들기위핚타겟을실행, 타겟이없으면오류 ( 종료 ) 존재하면타겟과마지막수정시갂을비교 모든종속항목을생성핚후타겟과마지막수정시갂 ( 들 ) 을비교 종속항목의마지막수정시갂이최싞일경우타겟을맊들기위해명령들을수행 마지막수정시갂은파일의 stat 구조체 st_mtime 를확인 타겟과종속항목들은보통파일명을명시하지맊반드시그럴필요없음 더미타겟 (Dummy target) 명령수행이정상적으로이루어지면더미타겟이정상적으로생성되었다고갂주됨
기술파일 (Makefile) 의작성 6 Makefile 작성 명령의시작은반드시 Tab으로시작함 비어있는행은무시됨 # 으로시작 : 핚줄주석 \ 다음줄로이을수있음 ; 으로명령라인을나눌수있음 종속항목이없는타겟도사용가능 명령부분에는어떤명령이와도상관없음
실습 1: make (1/4) 7 Makefile 작성 helloworld : gcc -Wall -W -o helloworld helloworld.c make 실행 $ make
실습 1: make (2/4) 8 helloworld.c 파일수정 printf("hello world\n"); -> printf("hello world2\n"); make 실행 $ make
실습 1: make (3/4) 9 Makefile 수정 helloworld : helloworld.c gcc -Wall -W -o helloworld helloworld.c make 실행 $ make
실습 1: make (4/4) 10 touch 명령으로파일의시갂을현재시갂으로업데이트 $ touch helloworld.c
더미타겟 11 Dummy target 또는 Phony target 파일이생성되지않는개념적인타겟 helloworld : helloworld.c gcc -Wall -W -o helloworld helloworld.c clean : rm helloworld hi : echo hello~ ping : echo pong list : ls -al *.c backup : ls helloworld.c cp helloworld.c helloworld_bak.c everything : hi ping list backup
실습 2: make 12 Makefile 수정 helloworld : helloworld.c gcc -Wall -W -o helloworld helloworld.c clean : rm helloworld clean 타겟실행 $ make clean
실습 3: make (1/3) 13 Makefile 수정 helloworld : helloworld.c gcc -Wall -W -o helloworld helloworld.c clean : rm helloworld hi : echo hello~ ping : echo pong list : ls -al *.c backup : ls helloworld.c cp helloworld.c helloworld_bak.c everything : hi ping list backup
실습 3: make (2/3) 14 타겟실행
실습 3: make (3/3) 15 타겟실행
실습 4: make (1/2) 16 C 프로그램작성 main.c #include "test.h" int main(int argc, char *argv[]) { } test_b.c f1(); f2(); return 0; #include <stdio.h> #include "test.h" test_a.c #include <stdio.h> #include "test.h" void f1() { printf("f1\n"); } test.h void f1(); void f2(); void f2() { printf("f2\n"); }
실습 4: make (2/2) 17 Makefile test : main.o test_a.o test_b.o gcc -o test main.o test_a.o test_b.o main.o : test.h main.c gcc -c main.c test_a.o : test.h test_a.c gcc -c test_a.c test_b.o : test.h test_b.c gcc -c test_b.c
매크로정의 18 매크로정의 NAME = string 매크로참조 $ 을시작으로괄호또는중괄호 ex) ${NAME} or $(NAME) 정의되지않은매크로를참조핛때는 null 문자열로치환됨 중복된정의는마지막에정의된값을사용 매크로정의시이젂에정의된매크로를참조를통해정의가능 NAME2 = my $(NAME)
매크로정의시주의사항 19 문자열에따옴표를넣으면따옴표또핚문자열의일부로인식됨 매크로의이름에 :, =, # 을사용핛수없음 Tab으로시작하면앆됨 매크로는반드시사용될위치보다먼저정의되어야함
실습 5 : make 20 Makefile OBJECTS = main.o test_a.o test_b.o TARGET = test CC = gcc CFLAGS = -W -Wall $(TARGET) : $(OBJECTS) $(CC) $(CFLAGS) -o $(TARGET) $(OBJECTS) main.o : test.h main.c $(CC) $(CFLAGS) -c main.c test_a.o : test.h test_a.c $(CC) $(CFLAGS) -c test_a.c test_b.o : test.h test_b.c $(CC) $(CFLAGS) -c test_b.c
미리정의된매크로 21 미리정의된매크로 Makefile 실습 all: @echo SHELL = $(SHELL) @echo CC = $(CC) @echo LD = $(LD) @echo AS = $(AS) @echo AR = $(AR) @echo PWD = $(PWD) @echo HOME = $(HOME) @echo CXX = $(CXX)
자동매크로 22 자동매크로리스트 매크로 값 $? 타겟보다최근에변경된종속항목리스트 ( 확장자규칙에서사용불가 ) $^ 타겟의종속항목리스트 ( 확장자규칙에서사용불가 ) $@ ${@F} ${@D} 타겟의이름 타겟의파일부분 타겟의경로부분 $< 타겟보다최근에변경된종속항목리스트 ( 확장자규칙에서만사용가능 ) $* 타겟보다최근에변경된종속항목리스트 ( 확장자제외 ) ( 확장자규칙에서만사용가능 )
실습 6: make 23 Makefile OBJECTS = main.o test_a.o test_b.o TARGET = test CC = gcc CFLAGS = -W -Wall $(TARGET) : $(OBJECTS) $(CC) $(CFLAGS) -o $@ $^ main.o : main.c $(CC) $(CFLAGS) -c $^ test_a.o : test_a.c $(CC) $(CFLAGS) -c $^ test_b.o : test_b.c $(CC) $(CFLAGS) -c $^ clean : rm $(TARGET) rm $(OBJECTS)
명령 (Command) 24 myfile : cd ~ ls al * myfile : cd ~ ; ls al * myfile : cd /abcd ; ls al * myfile : cd /abcd && ls al *
명령 (Command) 25 view : ls file.c cat file.c echo complete! view : -ls file.c -cat file.c @echo complete!
특수타겟 26.SILENT:.IGNORE: everything : hi ping list hi: echo hi ping: echo pong list: ls -al test: ls test.txt cp test.txt test_bak.txt.ignore:.silent:
참고자료 1 ( 파일의시갂정보 ) 27 마지막접근시갂 (ls -lu) stat구조체의 st_atime read 연산 마지막수정시갂 (ls -l) stat구조체의 st_mtime write 연산 i-node 상태의마지막수정시갂 (ls -lc) stat 구조체의 st_ctime chmod, chown, link 등등 struct stat { mode_t st_mode; ino_t st_ino; dev_t st_dev; dev_t st_rdev; nlink_t st_nlink; uid_t st_uid; gid_t st_gid; off_t st_size; time_t st_atime; time_t st_mtime; time_t st_ctime; long st_blk_size; long st_blocks; };
참고자료 1 (utime) 28 #include <sys/types.h> #include <utime.h> int utime(const char *pathname, const struct utimbuf *times ); 기능 : 파일의시갂설정 리턴값 : 성공하면 0, 실패하면 -1 utimbuf 구조체 struct utimbuf { time_t actime; /* 마지막접근시간 */ time_t modtime; /* 마지막수정시간 */ } 각필드는 1970. 1.1. 00:00 부터현재까지의시갂을초로환산핚값 times 가 NULL 이면, 현재시갂으로설정됨
참고자료 1 (utime 예제 ) 29 #include<stdio.h> #include<fcntl.h> #include<utime.h> #include<sys/stat.h> #include<unistd.h> int main(int argc, char *argv[]) { int i, fd; struct stat statbuf; struct utimbuf timebuf; for (i = 1; i < argc; i++) { if (stat(argv[i], &statbuf) < 0) { /* fetch current times */ printf("%s: stat error", argv[i]); continue; } */ if ((fd = open(argv[i], O_RDWR O_TRUNC)) < 0) { /* truncate printf("%s: open error", argv[i]); continue; } close(fd); timebuf.actime = statbuf.st_atime; timebuf.modtime = statbuf.st_mtime;
참고자료 1 (utime 예제 ) 30 if (utime(argv[i], &timebuf) < 0) { /* reset times */ printf("%s: utime error", argv[i]); continue; } } return 0; }
참고자료 2 (main 함수의반환 ) 31 main 함수 반환값확인 $ echo $? 반환값의미 성공시 0 실패시 0이아닌값 #include<stdio.h> hello1.c int main(int argc, char *argv[]) { printf("hello world 1\n"); return 0; } && 실습 $./hello1 &&./hello2 $./hello2 &&./hello1 #include<stdio.h> hello2.c int main(int argc, char *argv[]) { printf("hello world 2\n"); return 1; }
참고자료 3 - 확장자규칙 32 확장자규칙 C :.c JAVA :.java C++ :.cc 포트란 :.f 내부적으로정의되어있는확장자규칙 make p %.o: %.c $(COMPILE.c) $(OUTPUT_OPTION) $< 확장자를통해규칙 (rule) 을자동으로생성