Programming/C,C++

[C, C++] Make

충남대이적 2025. 10. 10. 22:26

Make를 사용해야하는 이유

1학년때는 Window에서 visualstduio를 사용해 Run버튼 딸깍 누르면 실행되는 건 줄 알았지만 리눅스 세상에서는 어림도없다.

소스코드를 빌드하기 위해서는 컴파일과 링킹단계를 거치는데 소스코드를 기계어로 바꾸는 컴파일 단계와 실행파일로 만들기 위해 어떤 목적파일(.o)들이 필요한지 명시해주는 링킹단계가 필요한데 이들을 매번 Shell에 입력할 수 없으니 하나의 파일로 만들어 둬야하고 이 파일이 Makefile이다.

 

아래에서는 실습 때 사용한 Makefile을 예제로 어떻게 작성하는지와 어떻게 동작하는지에 대해서 알아본다.
아래 글은 아주 잘 정리된 글이니 이 글을 읽고오면 아래 예제 파일을 이해하기 쉽다.

씹어먹는 C++ - <19 - 1. Make 사용 가이드 (Makefile 만들기)>

 

 

Makefile 실전

아래 코드는 Makefile을 실행하기 전 변수를 세팅하는 것이다. g++을 사용한다면 CC = g++이라고 입력해주면된다. 그 외 다른 변수들은 googletest를 사용할꺼라면 거의 수정하지 않고 사용하는 것 같다.

#TODO: Set your googletest directory path
GTEST_DIR = /home/park/googletest/googletest

CC = clang++
CPPFLAGS += -isystem $(GTEST_DIR)/include
TIDYFLAGS = --checks=-*,cppcoreguidelines-*,-cppcoreguidelines-owning-memory,readability-*

GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
				$(GTEST_DIR)/include/gtest/internal/*.h

GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)

 

 

보통 make 명령문은 Target : prerequisite 형식으로 적고 아래에는 Recipe를 적어준다.

make를 입력하게 되면 make all이라고 입력하는 것과 같고, make에서 all target을 빌드하기위해 어떤 prerequisite가 필요한지 찾는다. hw6는 hw6.cc, node.o, int_node.o등등 다양한 목적파일이 필요하다. node.o가 없다면 node.o target을 찾아 내려간다. 이런 식으로 목적파일을 모두 만들고나면 hw6를 빌드하고, all을 빌드한다.

자신이 작성한 test파일을 빌드하고 싶다면 make test를 해주면 된다.

 

이제 레시피에 대해서 알아보자.

레시피에서 $^는 모든 prerequisite를 가리키며, $@은 target name을 가리킨다.

그러니 hw6 target의 레시피는 clang++ --std=c++17 hw6.cc node.o int_node.o string_node.o tree_util.o -o hw6가 된다.

-c 옵션은 compile only이고, -o 옵션은 output file name을 설정하는 옵션이다.

all : hw6

hw6: hw6.cc node.o int_node.o string_node.o tree_util.o
	$(CC) --std=c++17 $^ -o $@

tree_util.o : tree_util.cc
	$(CC) --std=c++17 -c $^ -o $@

node.o : node.cc
	$(CC) --std=c++17 -c $^ -o $@

int_node.o : int_node.cc
	$(CC) --std=c++17 -c $^ -o $@

string_node.o : string_node.cc
	$(CC) --std=c++17 -c $^ -o $@


test.o : test.cc $(GTEST_HEADERS)
	$(CC) $(CPPFLAGS) $(CXXFLAGS) --std=c++17 -c $< -o $@

test: test.o node.o int_node.o string_node.o tree_util.o gtest_main.a
	$(CC) $(CPPFLAGS) $(CXXFLAGS) --std=c++17 $^ -o $@

clean:
	 rm -f gtest.a gtest_main.a *.o hw6 test

tidy:
	clang-tidy $(shell find . -name "*.cc" -o -name "*.h") $(TIDYFLAGS) --fix -- -x c++ -std=c++17

 

아래 코드들은 googletest 사용할려면 기본적으로 들어가는 코드인 거 같다.

gtest-all.o: $(GTEST_SRCS_) 
	$(CC) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) --std=c++17 -c\
		$(GTEST_DIR)/src/gtest-all.cc

gtest_main.o : $(GTEST_SRCS_)
	$(CC) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) --std=c++17 -c\
		$(GTEST_DIR)/src/gtest_main.cc

gtest.a : gtest-all.o
	$(AR) $(ARFLAGS) $@ $^

gtest_main.a : gtest-all.o gtest_main.o
	$(AR) $(ARFLAGS) $@ $^

.PHONY: all clean

'Programming > C,C++' 카테고리의 다른 글

[C,C++] Inheritance and Type Casting  (0) 2025.10.10
오버라이딩을 통한 다형성의 실현(virtual 개념, 오버라이딩 개념)  (0) 2022.03.01
참조리턴  (0) 2022.02.23
복사생성자  (0) 2022.02.23
연산자 중복  (0) 2022.02.22