반응형
핵심 정리
이 글은 Makefile을 처음 사용할 때 헷갈리기 쉬운 기본 동작을 실행 예제로 확인한 메모입니다. 인자 없이 make를 실행할 때 어떤 target이 선택되는지, C 소스 파일이 오브젝트 파일로 암시적으로 컴파일되는 방식, CC와 CFLAGS로 컴파일러와 옵션을 지정하는 흐름을 정리합니다.
- make를 인자 없이 실행하면 Makefile에 적힌 첫 번째 target이 기본 목표로 실행됩니다.
- 특정 target을 실행하려면 make a.out처럼 목표 이름을 직접 지정하거나 의존 관계에 포함시켜야 합니다.
- C 소스 파일에서 오브젝트 파일로 만드는 기본 규칙은 make가 암시적 규칙으로 처리할 수 있습니다.
- CC와 CFLAGS를 지정하면 암시적 컴파일에 사용할 컴파일러와 디버그 같은 옵션을 바꿀 수 있습니다.
- 여러 오브젝트 파일에 같은 의존성과 recipe를 적용할 때는 target 목록을 이용해 규칙을 묶어 적을 수 있습니다.
본문에는 작은 Makefile 예제와 실제 출력 명령이 이어집니다. 먼저 기본 target과 암시적 컴파일의 역할을 잡은 뒤 CC, CFLAGS 예제를 따라가면 동작 차이를 확인하기 쉽습니다.
괜찮은 링크
http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
일반
make with no arguments executes the first rule in the file
재밌는건 아래와 같은 Makefile의 경우 가장 처음 target만 무조건 수행된다는 점이다.
clean:test.c
echo "clean"
clean2:test.c
echo "clean2"
a.out : test.c
gcc test.c
즉 위와 같은 Makefile 이 있을 때, make를 수행하면 가장 위에있는 target인 clean 만 수행되고 나머지 target인 clean2, a.out 은 깡그리 무시된다는 점이다.
clean2나 a.out 이 수행되려면 만앞에 있는 clean의 dependency chain에 언급해주거나 make a.out 이런식으로 직접 파라미터로 넣어주는 수밖에 없는것 같다.
.c를 .o로 바꾸어 주는 것은 자동이다.
이 특징을 이용하는게 좋은 것이.. 특정 .c 하나만 바뀌었을때 그 파일만 빌드되도록 만들기 쉽다는 점
아하!! 정말 중요한 것을 깨달았다.
1. 컴파일 (.c 파일에서 .o 로 변환되는 것) 은 원래 부터 자동이라는 것.
2. 그리고 이 컴파일에 사용되는 것이 바로 predefined macro 라는 것!! 즉 CC, CFLAGS 같은 애들이 이와 같이 자동 컴파일 될 때 쓰인다는 것이다!
그 예로서 다음과 같은 Makefile 이 있을 때.
6 OBJ = main.o func1.o
7
8 test : $(OBJ)
9 gcc -o test $(OBJ)
보면은 원래는 다음처럼 .c를 .o로 바꾸어주는 부분도 있어야 하지만
3 OBJ = main.o func1.o
4
5 test : $(OBJ)
6 gcc -o test $(OBJ)
7
8 main.o : main.c
9 gcc -c main.c
10
11 func1.o : func1.c
12 gcc -c func1.c
실제로 위에거 처럼해도 잘 되는걸 볼 수 있고 실행시 나타나는 명령은 다음과 같다.
cc -c -o main.o main.c
cc -c -o func1.o func1.c
gcc -o test main.o func1.o
보면은 컴파일러로 자동으로 cc 가 쓰였고 컴파일 옵션에는 -c 만 있음을 알 수 있다.
위를 gcc로 바꾸고 디버깅 옵션인 -g 를 추가하려면 다음과 같이 Makefile을 수정해주면 된다.
3 CC = gcc
4 CFLAGS = -g
5
6 OBJ = main.o func1.o
7
8 test : $(OBJ)
9 gcc -o test $(OBJ)
바로 predefined macro를 통하여 컴파일 옵션을 지정해 준것이다.
그럼 나타나는 명령어가 다음과 같이 잘 바뀐다.
gcc -g -c -o main.o main.c
gcc -g -c -o func1.o func1.c
gcc -o test main.o func1.o
타겟이 여러개인 경우도 가능하다
예제 2.1에서는 안 나왔지만 타겟이 여러 개인 경우는 어떻게 될까요? 그때에는 각 타겟에 대해서, 하나의 타겟을 가지는(그리고 나머지 선행조건 및 레시피는 모두 동일한) 다수의 규칙들을 작성하는 것과 동일합니다. 즉 다음의 규칙을 보시죠.
$(OBJS) : MyCommon.h
echo “$@ depends on MyCommon.h”
$(OBJS)는 MySocket.o MyClient.o 으로 정의되어 있기 때문에, 위의 규칙은 다음 두 개의 규칙으로 풀어 쓴 것과 동일합니다.
MySocket.o : MyCommon.h
echo “$@ depends on MyCommon.h”
MyClient.o : MyCommon.h
echo “$@ depends on MyCommon.h”
당연히 풀어 쓴 것 보다야 하나의 규칙이 훨씬 컴팩트해서 보기도 좋고 유지 보수도 용이합니다.. (아, 물론 타이핑도 적습니다.) 이제 실제 규칙의 처리는 어떻게 되는 지 알아 보도록 하겠습니다.
internal macro
내부적으로 정해짐. 바꿀수없음.
$@ 현재의 목표 파일(Target) ( :의 왼쪽 부분)
$^ :의 오른쪽 부분
$* 확장자가 없는 현재의 목표 파일(Target)
$< :의 오른쪽 부분중 첫번째 거
$? 현재의 목표 파일(Target)보다 더 최근에 갱신된 파일이름
gccmakedep
=== mac에서 gccmakedep 설치하기 ===
http://egloos.zum.com/manwooo/v/1808309
위에 링크보고 macport 깔고 gccmakedep 설치하면 됐다.
단, 터미널은 다시 구동해야 하더라.
=== 설명 ===
다른 것들은 모두 편리하고 좋은 것 같은데, Makefile 하단에 있는 파일 간의 종속에 대한 정보를 모두 타이핑해서 넣어야 할까요? 파일이 많을 경우 어떻게 일일이 입력할 수 있있겠습니까? 당연한 말씀입니다. 게으른 프로그래머에게는 말도 안되죠. 그래서 이와 같은 귀찮은 작업을 make에 떠 넘기겠습니다. 바로 파일간의 의존성을 찾아서 그 내용을 직접 구성해 달라고 요청하는 것이죠.
이렇게 파일의 의존성을 검색해서 그 내용을 작성해 주는 것이 gccmakedep 입니다. 아래와 같이 수정해서 make dep를 실행합니다.
TARGET = sample
OBJS = main.o tcp.o rs232.o
SRCS = $(OBJS:.o=.c)
CC = -I/home/jwjw/prjs/include -g -c
$(TARGET): $(OBJS)
gcc -lm -o $@ $^
.c.o:
gcc $(CC) $<
dep :
gccmakedep $(SRCS)
이렇게 추가 작성해서 make dep 를 실행하시면 make는 컴파일과 링크 작업 대신에 라벨 dep: 밑의 명령을 실행합니다. 새로 만들어진 SRCS는 OBJS에 열거된 파일 모록에 대해서 확장자를 .o를 .c로 바뀐 목록을 가지게 됩니다. gccmakedep는 소스 파일을 가지고 의존성을 검색할 수 있기 때문이죠.
]$ make dep
]$ vi Makefile
TARGET = sample
OBJS = main.o tcp.o rs232.o
SRCS = $(OBJS:.o=.c)
CC = -I/home/jwjw/prjs/include -g -c
$(TARGET): $(OBJS) gcc -lm -o $@ $^
.c.o:
gcc $(CC) $<
dep : gccmakedep $(SRCS)
# DO NOT DELETE
main.o: main.c /usr/include/stdio.h .........
tcp.o: tcp.c /usr/include/stdio.h .........
rs232.o: rs232.c /usr/include/stdio.h .........
하단에# DO NOT DELETE 행과 함께 밑으로 각 .o 에 대한 관련 파일 목록이 자동으로 생성되는 것을 보실 수 있습니다. 이제 make를 실행하면 위 정보에 맞추어 컴파일하게 됩니다.
재귀적 사용(sub directories)
이 링크가 좋네
옵션
j 옵션
make -j 12
위처럼하면 12개의 명령어를 동시에 패러럴 하게 수행하라는 것(논리 CPU개수 적어주면 될 듯)
반응형
'tistory' 카테고리의 다른 글
| 확률변수 개념: 표본공간의 결과를 수치 함수로 해석하기 (0) | 2026.05.26 |
|---|---|
| 베이즈 정리와 베이지안 네트워크: 조건부 확률과 DAG (0) | 2026.05.25 |
| 이항 분포 개념: 확률질량함수와 Python 계산 예제 (0) | 2026.05.23 |
| 티스토리 소스코드 붙여넣기: Color Scripter HTML 사용법 (0) | 2019.03.18 |
| 티스토리 이미지 붙여넣기: 맥 크롬 클립보드 우회 방법 (1) | 2017.11.14 |
