Search
Duplicate

[토막글] Make + Sanitizer 더 잘 쓰기? 2

간단소개
make SANITIZER=address 입력하기 귀찮아요? 자동화해요!
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
C
C++
개발환경
Makefile
Scrap
태그
makefile
sanitizer
개발환경
9 more properties
관련 글 보기
[토막글] Make와 Sanitizer 더 잘 쓰기에서 이어지는 내용입니다.

기존 Makefile

우선 전형적인 Makefile 예시입니다.
# 예시 이름 NAME := libft.a # 소스코드 목록 - 제출용이 아닌 경우에만 사용 SRCS ?= $(shell find . -name "*.c" | xargs) # 기본 변수 CC := clang CFLAGS := -Wall -Wextra -Werror # Norm 필수 규칙 (all, clean, fclean, re) all: $(NAME) clean: find . \( -name "*.o" -o -name "*.d" \) -delete fclean: clean rm -f $(NAME) re: $(MAKE) fclean $(MAKE) all .PHONY: all clean fclean re # **************************************************************************** # # # # 여기서부터 중요!!! # # 플래그로 바이너리가 달라지는 경우 파일명에 $(SUFFIX)를 붙입니다. # # make $(NAME)으로 $(NAME)을 만들려고 할 경우, 타겟 파일을 단순히 복사합니다. # 타겟 파일은 $(NAME)과 이름이 겹칠 수 있어 이름에 .target을 붙였습니다. # # **************************************************************************** # # 여기에 코드 추가 SUFFIX := $(if $(SANITIZER),.$(SANITIZER)) %.a: $(AR) rcs $@ $^ %$(SUFFIX).o: %.c # SANITIZER가 있을 때만 -fsanitizer 플래그 사용 $(CC) $(CFLAGS) -c $< -o $@ -MMD $(if $(SANITIZER),-fsanitize=$(SANITIZER),) $(NAME:.a=.target$(SUFFIX).a): $(patsubst ./%.c,%$(SUFFIX).o,$(SRCS)) .PHONY: $(NAME) $(NAME): $(NAME:.a=.target$(SUFFIX).a) cp $< $@ -include $(SRCS:.c=$(SUFFIX).d)
Makefile
복사
전형적인 Makefile 예시
여기서 SANITIZER 변수를 make에 전달해야만 해당 sanitizer를 사용하게 됩니다.

플래그를 저장하자

위 예시 코드의 여기에 코드 추가 부분에 아래 코드를 추가해 주세요
ifeq ($(SANITIZER),) ifeq ($(SAVE),1) # SANITIZER가 주어지지 않았는데 저장한다면 (SAVE 변수가 1이라면) 이전 설정 삭제 TMP := $(shell rm -f flag_sanitizer.mk) # 바로 쉘을 실행할 수 없기 때문에 `아무_변수명 := $(shell 실행할_것)` 트릭을 사용합니다. else # SANITIZER가 주어지지 않으면 (+ 저장하지 않는다면) 기본값으로 이전 설정을 사용합니다. -include flag_sanitizer.mk endif else # SANITIZER가 주어진 경우! ifeq ($(SAVE),1) # 설정을 저장한다면 -include로 사용할 수 있게 flag_sanitizer.mk에 저장합니다. TMP := $(shell printf "TMP := \$$(shell printf 'No SANITIZER given. using previous one. (run \`make reset\` to reset)\\\\n' 1>&2)\\nSANITIZER := $(SANITIZER)\n" > flag_sanitizer.mk) # 이전 설정을 사용한다는 경고 메시지를 출력하고 SANITIZER 변수를 설정하는 파일을 생성 endif endif # 이전 설정을 저장한 flag_sanitizer.mk를 삭제하는 reset 스크립트를 추가합니다. .PHONY: reset reset: rm -f flag_sanitizer.mk # 그리고 clean 스크립트를 실행하면 reset 스크립트도 실행되도록 dependency에 추가합니다. clean: reset
Makefile
복사
SANITIZER를 저장하는 예시
SAVE=1 없이도 항상 유지하려면 ifeq ($(SAVE),1)와 그 endif를 제거하면 됩니다.
추가로, 제출 파일에 제한이 없다면 이렇게 추가한 코드를 별도의 파일로 분리하는 게 좋겠죠.

결론

Sanitizer를 잘 쓰자는 것이 아닙니다. 물론 Sanitizer 잘 쓰면 좋습니다.
Sanitizer만이 아니라 뭐든지, 시간을 많이 잡아먹는 게 있다면 자동화로 시간을 아끼세요.
그렇게 조금씩 아낀 시간이 모여 뭔가 할 수 있는 시간이 만들어질 거에요