Search
Duplicate
😈

include ../../../.. 지옥에서 벗어나기

간단소개
include ../../../../../../../../test/common/mock/malloc/include/variables.mk
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
Makefile
개발환경
상대경로
Scrap
태그
makefile
잡지식
개발지식
개발환경
꿀팁
9 more properties

[make] include ../../../.. 지옥에서 벗어나기

../../../../.. 지옥
해결방법

1. ../../../../.. 지옥

수십, 수백개의 Makefile을 관리하다 보면 include path가 꼬이는 문제가 생길 수 있습니다.

1) 그게 뭔데?

test/case1/ft_atoi/builddir/asan/Makefile에서 test/common/asan.mk를 include하는 경우
# 현재 디렉터리는 test/case1/ft_atoi/builddir/asan이므로 "../"이 네 번 include ../../../../common/asan.mk
Makefile
복사
include를 위한 코드가 대충 이렇게 됩니다. 보기만 해도 머리아프죠.
그리고 저 test/common/asan.mk는 이렇게 생겼어요.
ADDITIONAL_CC_LD_FLAGS := -g3 -fsanitize=address include ../../../../common/sanitizer_common.mk
Makefile
복사
왜 여기에도 ../../../이 들어가냐면요...
상대경로가 그 파일을 include한 파일이 아닌, make 명령이 실행된 cwd가 기준이에요.

2) 해결 안 하면?

코드가 좀 안 예쁘더라도 동작만 하면 그만 아닌가? 생각할 수 있는데요,
test/case1/ft_putstr_fd__mock/write/builddir/asan/Makefile에서도 include한다면 어떨까요?
# 이번에는 "../"이 다섯 번 include ../../../../../common/asan.mk
Makefile
복사
그냥 이렇게 끝난다면 행복할 것 같아요. ...하지만 현실은 그렇지 않아요.
asan.mk에서도 include를 하는데, 그 경로가 상대경로이기 때문에 재미있는 일이 일어날 거에요.

2. 해결방법

사실 엄청 간단한 방법으로 해결이 가능합니다.

1) 초간단 해결법!

임의의 어떤 한 변수(예를 들어 BASE_PATH)에 프로젝트 루트 디렉터리의 상대경로를 저장해둬요.
BASE_PATH := ../../../../.. include $(BASE_PATH)/test/common/asan.mk
Makefile
복사
그러면 test/case1/ft_atoi/builddir/asan/Makefile 의 첫 줄이 이렇게 시작하겠죠.
그리고 include에 이 BASE_PATH를 사용하는 거에요.
ADDITIONAL_CC_LD_FLAGS := -g3 -fsanitize=address include $(BASE_PATH)/test/common/sanitizer_common.mk
Makefile
복사
벌써 모든 문제가 말끔하게 해결됐습니다. 와!
여기에서 BASE_PATH를 다른 파일에서 가져온다면 디렉터리 구조 변경에 더 유연해질 거에요.
# 어딘가의 Makefile include base_path.mk # 후략 # 어딘가의 base_path.mk include ../base_path.mk BASE_PATH := $(BASE_PATH)/.. # 어딘가의 상위 디렉터리의 base_path.mk include ../base_path.mk BASE_PATH := $(BASE_PATH)/.. # ... 반복하다가 프로젝트 루트의 상위 디렉터리의 base_path.mk BASE_PATH := .
Makefile
복사

2) 더 좋은 해결법?

사실 아직 완벽한 방법은 아니에요.
test/common의 파일에서 test/common의 파일을 include하려면 test/common 써 쭤야 해요.
위 예시에서는 BASE_PATH 변수에 프로젝트 루트 디렉터리를 저장하는 방법을 썼는데요,
다른 변수(예를 들어 CURR_PATH)에 include 될 파일 기준 상대경로를 저장해도 돼요.
# test/case1/ft_atoi/builddir/asan/Makefile include base_path.mk CURR_PATH := $(BASE_PATH)/test/common include $(CURR_PATH)/asan.mk # test/common/asan.mk ADDITIONAL_CC_LD_FLAGS := -g3 -fsanitize=address include $(CURR_PATH)/sanitizer_common.mk # test/common/sanitizer_common.mk CURR_PATH := $(CURR_PATH)/../../common include $(CURR_PATH)/basic_common.mk
Makefile
복사
대신에 이 방법은 모든 Makefile에서 BASE_PATH를 설정해야 되는 것처럼, include를 할 때마다 매번 CURR_PATH를 재설정해야 한다는 불편함이 따를 수 있는데,
프로젝트가 정말 거대해져버리면 그 불편함을 감수하는 게 훨씬 나은 선택일 수 있어요.