Search
Duplicate
🔗

Makefile 리링크(re-link)를 방지하는 법

간단소개
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
Makefile
태그
makefile
Scrap
8 more properties
(22년 9월 중순 경 jmaing님께서 수요지식회에서 공유해주신 내용을 바탕으로 개인적으로 정리한 내용이며 팔만코딩경에 업로드 전 허락을 받고 올립니다. 좋은 지식 공유해주신 jmaing님께 감사의 말씀드립니다!)

문제 상황 (re-link가 발생하게 되는 경위)

1.
make 자체적으로 의존 파일의 수정 유무를 확인하여 의존 파일이 수정이 되었을 경우에만 타겟 파일을 생성하고 있다.
2.
근데, 보너스가 있는 과제의 경우 필수 파트와 보너스 파트가 각각 다른 의존 파일로 (보너스의 경우에는 suffix로 파일명에 _bonus 가 붙는다) 같은 타겟 파일(예를 들어, libft.a)을 생성하게 된다.
3.
그러므로, 이미 최종 타겟 파일(libft.a)가 존재하고 소스 파일(=의존 파일)의 수정이 현재 존재하는 최종 타겟 파일(libft.a)의 최종 수정 시각보다 더 먼저 이루어졌다면(즉 make 입장에서 타겟 파일의 수정 시기와 비교해 의존 파일이 수정되었다고 간주하지 않는 경우), make가 이루어지지 않는다.
4.
그렇다고 매번 최종 타겟 파일을 생성하려고 시도할 때마다 최종 타겟 파일(libft.a)를 지운 다음에 생성하게 할 수는 없다. 소스 파일(=의존 파일)이 수정되지 않았음에도 다시 컴파일 및 링크 작업을 수행하게 되기 때문이다. 이것이 바로 리링크(re-link)이다!

해결 방법

배경 지식 : make에서 수정 유무를 확인하는 방식은 타겟 파일과 의존 파일 각각의 ‘최종 수정 시각’을 비교하는 것이다. (의존 파일의 최종 수정 시각이 타겟 파일보다 더 최근일 경우, 의존 파일이 수정된 것으로 간주 → 타겟 파일 재생성)
예시
따라서, mandatory 파트와 bonus 파트 각각 언제 최종 타겟 파일이 생성되었었는지 그 시각을 어딘가에 저장할 수 있다면 이 문제를 해결할 수 있을 것이다!
make all / make bonus 명령어가 실행될 때 touch {파일명} 을 실행부에 추가하여 {파일명}이라는 이름의 파일을 생성하여서 언제 make all / make bonus를 하였는지 그 시각을 저장함 (파일의 생성 시각이 곧 make하였던 시간, 즉 최종 타겟 파일이 생성되었던 시각이 됨)

예시

TARGET = out.a SRCS = test1.c test2.c test3.c OBJS = $(SRCS:.c=.o) all : make_mandatory bonus : make_bonus clean : rm -f $(OBJS) $(OBJS:.o=_bonus.o) rm -f make_mandatory make_bonus rm -f $(TARGET) make_mandatory : $(OBJS) ar rcs $(TARGET) $(OBJS) touch $@ make_bonus : $(OBJS:.o=_bonus.o) ar rcs $(TARGET) $^ touch $@ %.o : %.c gcc -c $< -o $@ .PHONY : all bonus clean
Makefile
허수아비 타겟파일인 .PHONYmake_mandatorymake_bonus는 없는 것이 당연하다. 이 파일들의 존재가 무시되면 안되니까!
의존 파일과 비교하여 타겟 파일이 더 최신이면 해당 타겟 파일을 만들기 위한 명령어는 실행되지 않게되므로, 이것이 곧 리링크 방지가 됨.
임시 파일은 기계 평가에서 문제되지 않으니 OK.

번외. make를 두번 해야하는 경우…

libft도 컴파일해야하는 ft_printf 과제의 경우 리링크 문제를 피하기가 더 힘듦. 보통 make의 -C 옵션을 통해 libft를 컴파일하게 되는데, ….
→ printf의 makefile에서 libft의 소스파일 또한 관리한다. (즉 makefile을 여러개 쓰지 않고 하나만 쓴다.)