■ Makefile에서 디록토리가 없을 때 디렉토리 생성하는 방법
@test -d $(@D) || mkdir -p $(@D)
@`[ -d $(OBJS_DIR) ] || $(MKDIR) $(OBJS_DIR)`
■ c++ 파일 확장자
.C, .cc, .cpp, .CPP, .c++, .cp, .cxx
:대문자 .C도 c++ 파일 확장자라고함.■ c++ 헤더파일 확장자
.h 대신에 .hpp 를 쓰기도 한다.
■ 10.3 Variables Used by Implicit Rules참조CFLAGS: C 컴파일러 플래그
CPPFLAGS: C 전처리기 및 이를 사용하는 프로그램(C 및 Fortran 컴파일러)에 제공할 추가 플래그.
-I (헤더파일 경로)나 -D (전처리 매크로) 등을 지정
CXXFLAGS: C++ 컴파일러의 플래그
LDFLAGS: 링커 플래그. -L을 지정
LDLIBS: -l을 지정
■ 컴파일 옵션
-pthread 옵션과 -lpthread는 약간 다르지만 거의 비슷하다고 함.
gcc를 이용한 컴파일 옵션■ -ansi -pedantic 둘 다 사용할 것
-pedantic 옵션 : ANSI C89 표준에서 요구하는 모든 경고 메시지를 표시한다.
-pedantic-errors 옵션 : ANSI C89 표준에서 요구하는 모든 오류 메시지를 표시한다.
-ansi: tells the compiler to implement the ANSI language option. This turns off certain "features" of GCC which are incompatible with the ANSI standard.
-pedantic: used in conjunction with -ansi, this tells the compiler to be adhere strictly to the ANSI standard, rejecting any code which is not compliant.
■ Makefile 에서 제공하는 자동 변수
$@ : 타겟 이름에 대응
$< : 의존 파일 목록에 첫 번째 파일에 대응
$^ : 의존 파일 목록 전체에 대응
$? : 타겟 보다 최신인 의존 파일들에 대응
$+ : $^ 와 비슷하지만, 중복된 파일 이름들 까지 모두 포함
■ 의존파일 생성
gcc에서 -MD/-MMD 옵션을 사용하면 의존 파일(dependency file)이 자동 생성됨.
디폴트로 '(소스 파일명).d'로 생성되며, -MF로 의존 파일명 별도 지정가능.
-M과 -MM 둘다 소스 파일의 종속 항목을 출력하지만,
-M 은 전체 시스템 헤더 디렉토리에 있는 헤더 파일들의 종속성까지 모두 출력하는데 비해,
-MM 은 전체 시스템 헤더 디렉토리는 제외하고, Makefile에서 직접 설정된 디렉토리의 헤더 파일들만 출력함.
시스템 헤더 파일은 변하지 않는다고 가정했기 때문에 -MM 을 주로 사용.
Makefile이 아닌 임의의 Makefile을 지정하려면 -f 옵션 뒤에 Makefile명을 명시하면 된다.
make [-f filename]
make [-f filename] target_name : 임의의 타겟 생성
make [-f filename] label_name : 임의의 레이블(더미타겟) 호출
CC := gcc
CXX := g++
SRCS := $(wildcard *.c) $(wildcard *.cpp)
OBJS := $(SRCS:.c=.o)
OBJS := $(OBJS:.cpp=.o)
TARGET := tt.exe
$(TARGET): $(OBJS)
$(CXX) -o $@ $^ $(LDFLAGS) $(LDLIBS)
clean:
rm -f *.o $(TARGET)
D:\git\MyTools\make_sample\source>make
gcc -c -o module.o module.c
g++ -c -o main.o main.cpp
g++ -c -o tiger.o tiger.cpp
g++ -o tt.exe module.o main.o tiger.o
CC := gcc
CXX := g++
CPPFLAGS = -D DEBUG # -I "./include"
CFLAGS = -pthread -pedantic -Wall -g -std=c99
CXXFLAGS = -pthread -pedantic -Wall -g -std=c++0x
LDFLAGS = -pthread # -L
LDLIBS = #-l
SRCS := $(wildcard *.c) $(wildcard *.cpp)
OBJS := $(SRCS:.c=.o)
OBJS := $(OBJS:.cpp=.o)
TARGET := tt.exe
$(TARGET): $(OBJS)
$(CXX) -o $@ $^ $(LDFLAGS) $(LDLIBS)
clean:
rm -f *.o $(TARGET)
D:\git\MyTools\make_sample\source>make
gcc -pthread -pedantic -Wall -g -std=c99 -D DEBUG -c -o module.o module.c
g++ -pthread -pedantic -Wall -g -std=c++0x -D DEBUG -c -o main.o main.cpp
g++ -pthread -pedantic -Wall -g -std=c++0x -D DEBUG -c -o tiger.o tiger.cpp
g++ -o tt.exe module.o main.o tiger.o -pthread
D:\git\MyTools\make_sample\source>
#.SUFFIXES:.c.o
#.SUFFIXES:.cpp.o
# The default suffix list is: .out, .a, .ln, .o, .c, .cc, .C, .cpp, .p, .f, .F, .m, .r, .y, .l, .ym, .lm, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch .web, .sh, .elc, .el.
#
CC := gcc
CXX := g++
CPPFLAGS = -D DEBUG # -I "./include"
CFLAGS = -pthread -pedantic -Wall -g -std=c99
CXXFLAGS = -pthread -pedantic -Wall -g -std=c++0x
LDFLAGS = -pthread # -L
LDLIBS = #-l
SRCS := $(wildcard *.c) $(wildcard *.cpp)
OBJS := $(SRCS:.c=.o)
OBJS := $(OBJS:.cpp=.o)
TARGET := tt.exe
all: $(TARGET)
$(TARGET): $(OBJS)
@echo [Link] $@ FROM: $^
$(CXX) -o $@ $^ $(LDFLAGS) $(LDLIBS)
.c.o:
@echo [Compile C] $<
$(CC) -o $@ $< -c $(CFLAGS) $(CPPFLAGS)
.cpp.o:
@echo [Compile C++] $<
$(CXX) -o $@ $< -c $(CXXFLAGS) $(CPPFLAGS)
clean:
rm -f *.o $(TARGET)
D:\git\MyTools\make_sample\source>make
[Compile C] module.c
gcc -o module.o module.c -c -D DEBUG
[Compile C++] main.cpp
g++ -o main.o main.cpp -c -pthread -pedantic -Wall -g -std=c++0x -D DEBUG
[Compile C++] tiger.cpp
g++ -o tiger.o tiger.cpp -c -pthread -pedantic -Wall -g -std=c++0x -D DEBUG
[Link] tt.exe FROM: module.o main.o tiger.o
g++ -o tt.exe module.o main.o tiger.o -pthread
#.SUFFIXES:.c.o
#.SUFFIXES:.cpp.o
# The default suffix list is: .out, .a, .ln, .o, .c, .cc, .C, .cpp, .p, .f, .F, .m, .r, .y, .l, .ym, .lm, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch .web, .sh, .elc, .el.
#
CC := gcc
CXX := g++
CPPFLAGS = -D DEBUG # -I "./include"
CFLAGS = -pedantic -Wall -pthread -g -std=c99
CXXFLAGS = -pedantic -Wall -pthread -g -std=c++0x
LDFLGAS = # -L
LDLIBS = #-l
DEPEND_FILE = depend_file
SRCS := $(wildcard *.c) $(wildcard *.cpp)
OBJS := $(SRCS:%.c=%.o)
OBJS := $(OBJS:%.cpp=%.o)
TARGET := tt.exe
all: $(TARGET)
$(TARGET): $(OBJS)
@echo [Link] $@ FROM: $^
@test -d $(@D) || mkdir -p $(@D)
$(CXX) -o $@ $^ $(LDFLGAS) $(LDLIBS)
%.o:%.c
@echo [Compile C] $<
@test -d $(@D) || mkdir -p $(@D)
$(CC) -o $@ $< -c $(CFLAGS) $(CPPFLAGS)
%.o:%.cpp
@echo [Compile C++] $<
@test -d $(@D) || mkdir -p $(@D)
$(CXX) -o $@ $< -c $(CXXFLAGS) $(CPPFLAGS)
depend:
@$(RM) -f $(DEPEND_FILE)
$(CC) -MM $(SRCS) > $(DEPEND_FILE)
clean:
rm -f *.o $(TARGET) $(DEPEND_FILE)
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),depend)
ifneq ($(SRCS),)
-include $(DEPEND_FILE)
endif
endif
endif
D:\git\MyTools\make_sample\source>make clean
rm -f *.o tt.exe depend_file
D:\git\MyTools\make_sample\source>make depend
gcc -MM module.c main.cpp tiger.cpp > depend_file
D:\git\MyTools\make_sample\source>type depend_file
module.o: module.c module.h
main.o: main.cpp module.h tiger.h
tiger.o: tiger.cpp tiger.h
D:\git\MyTools\make_sample\source>make
[Compile C] module.c
gcc -o module.o module.c -c -D DEBUG
[Compile C++] main.cpp
g++ -o main.o main.cpp -c -pedantic -Wall -pthread -g -std=c++0x -D DEBUG
[Compile C++] tiger.cpp
g++ -o tiger.o tiger.cpp -c -pedantic -Wall -pthread -g -std=c++0x -D DEBUG
[Link] tt.exe FROM: module.o main.o tiger.o
g++ -o tt.exe module.o main.o tiger.o
D:\git\MyTools\make_sample\source>
#.SUFFIXES:.c.o
#.SUFFIXES:.cpp.o
# The default suffix list is: .out, .a, .ln, .o, .c, .cc, .C, .cpp, .p, .f, .F, .m, .r, .y, .l, .ym, .lm, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch .web, .sh, .elc, .el.
#
CC := gcc
CXX := g++
CPPFLAGS = -D DEBUG # -I "./include"
CFLAGS = -pedantic -Wall -pthread -g -std=c99
CXXFLAGS = -pedantic -Wall -pthread -g -std=c++0x
LDFLGAS = # -L
LDLIBS = #-l
OBJ_DIR = obj
DEPEND_FILE = depend_file
SRCS := $(wildcard *.c) $(wildcard *.cpp)
OBJS := $(SRCS:%.c=$(OBJ_DIR)/%.o)
OBJS := $(OBJS:%.cpp=$(OBJ_DIR)/%.o)
TARGET := tt.exe
MKDIR := mkdir
RM := rm -f
.PHONY: all depend clean
all: $(TARGET)
$(TARGET): $(OBJS)
@echo [Link] $@ FROM: $^
@test -d $(@D) || mkdir -p $(@D)
$(CXX) -o $@ $^ $(LDFLGAS) $(LDLIBS)
$(OBJ_DIR)/%.o:%.c
@echo [Compile C] $<
@test -d $(@D) || mkdir -p $(@D)
$(CC) -o $@ $< -c $(CFLAGS) $(CPPFLAGS)
$(OBJ_DIR)/%.o:%.cpp
@echo [Compile C++] $<
@test -d $(@D) || mkdir -p $(@D)
$(CXX) -o $@ $< -c $(CXXFLAGS) $(CPPFLAGS)
depend:
@`[ -d $(OBJ_DIR) ] || $(MKDIR) $(OBJ_DIR)`
@$(RM) $(DEPEND_FILE)
@$(foreach FILE, $(filter %.c,$(SRCS)), $(CC) -MM -MT obj/$(FILE:%.c=%.o) $(FILE) >> $(DEPEND_FILE);)
@$(foreach FILE, $(filter %.cpp,$(SRCS)), $(CXX) -MM -MT obj/$(FILE:%.cpp=%.o) $(FILE) >> $(DEPEND_FILE);)
clean:
@$(RM) -r $(OBJ_DIR) $(TARGET) $(DEPEND_FILE)
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),depend)
ifneq ($(SRCS),)
-include $(DEPEND_FILE)
endif
endif
endif
D:\git\MyTools\make_sample\source>
D:\git\MyTools\make_sample\source>make clean
D:\git\MyTools\make_sample\source>make depend
D:\git\MyTools\make_sample\source>type depend_file
obj/module.o: module.c module.h
obj/main.o: main.cpp module.h tiger.h
obj/tiger.o: tiger.cpp tiger.h
D:\git\MyTools\make_sample\source>make
[Compile C] module.c
gcc -o obj/module.o module.c -c -pedantic -Wall -pthread -g -std=c99 -D DEBUG
[Compile C++] main.cpp
g++ -o obj/main.o main.cpp -c -pedantic -Wall -pthread -g -std=c++0x -D DEBUG
[Compile C++] tiger.cpp
g++ -o obj/tiger.o tiger.cpp -c -pedantic -Wall -pthread -g -std=c++0x -D DEBUG
[Link] tt.exe FROM: obj/module.o obj/main.o obj/tiger.o
g++ -o tt.exe obj/module.o obj/main.o obj/tiger.o
D:\git\MyTools\make_sample\source>
#.SUFFIXES:.c.o
#.SUFFIXES:.cpp.o
# The default suffix list is: .out, .a, .ln, .o, .c, .cc, .C, .cpp, .p, .f, .F, .m, .r, .y, .l, .ym, .lm, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch .web, .sh, .elc, .el.
#
# 아래와 같이 설징 시 "make DEBUG_FLAG=yes" 라고 실행하면, -g 옵션이 활성화 된다.
CC := gcc
CXX := g++
ifdef DEBUG_FLAG
DEBUG_OPT := -g
DEBUG_DEF := -D DEBUG
endif
CPPFLAGS = $(DEBUG_DEF) -I "./sub"
CFLAGS = -pedantic -Wall -pthread $(DEBUG_OPT) -std=c99
CXXFLAGS = -pedantic -Wall -pthread $(DEBUG_OPT) -std=c++0x
LDFLGAS = # -L
LDLIBS = # -l
SRC_DIR = . ./sub
OBJ_DIR = obj
DEPEND_FILE = depend_file
#SRCS := $(wildcard *.c) $(wildcard *.cpp)
#SRCS := $(foreach dir,$(SRC_DIR),$(notdir $(wildcard $(dir)/*.c )))
SRCS := $(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c )) \
$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.cpp ))
SRCS := $(subst ./,,$(SRCS))
OBJS := $(SRCS:%.c=$(OBJ_DIR)/%.o)
OBJS := $(OBJS:%.cpp=$(OBJ_DIR)/%.o)
OBJS := $(OBJS:%.cpp=$(OBJ_DIR)/%.o)
MKDIR := mkdir
RM := rm -f
TARGET := tt.exe
.PHONY: all depend clean
all: $(TARGET)
$(TARGET): $(OBJS)
@echo [Link] $@ FROM: $^
@test -d $(@D) || mkdir -p $(@D)
$(CXX) -o $@ $^ $(LDFLGAS) $(LDLIBS)
$(OBJ_DIR)/%.o:%.c
@echo [Compile C] $<
@test -d $(@D) || $(MKDIR) -p $(@D)
$(CC) -o $@ $< -c $(CFLAGS) $(CPPFLAGS)
$(OBJ_DIR)/%.o:%.cpp
@echo [Compile C++] $<
@test -d $(@D) || $(MKDIR) -p $(@D)
$(CXX) -o $@ $< -c $(CXXFLAGS) $(CPPFLAGS)
depend:
@`[ -d $(OBJ_DIR) ] || $(MKDIR) $(OBJ_DIR)`
@$(RM) $(DEPEND_FILE)
@$(foreach FILE, $(filter %.c,$(SRCS)), $(CC) $(CPPFLAGS) -MM -MT $(OBJ_DIR)/$(FILE:%.c=%.o) $(FILE) >> $(DEPEND_FILE);)
@$(foreach FILE, $(filter %.cpp,$(SRCS)), $(CXX) $(CPPFLAGS) -MM -MT $(OBJ_DIR)/$(FILE:%.cpp=%.o) $(FILE) >> $(DEPEND_FILE);)
clean:
$(RM) -r $(OBJ_DIR) $(TARGET) $(DEPEND_FILE)
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),depend)
ifneq ($(SRCS),)
-include $(DEPEND_FILE)
endif
endif
endif
D:\git\MyTools\make_sample\source>make clean
rm -f -r obj tt.exe depend_file
D:\git\MyTools\make_sample\source>make depend
D:\git\MyTools\make_sample\source>make
[Compile C] module.c
gcc -o obj/module.o module.c -c -pedantic -Wall -pthread -std=c99 -I "./sub"
[Compile C++] main.cpp
g++ -o obj/main.o main.cpp -c -pedantic -Wall -pthread -std=c++0x -I "./sub"
[Compile C++] sub/tiger.cpp
g++ -o obj/sub/tiger.o sub/tiger.cpp -c -pedantic -Wall -pthread -std=c++0x -I "./sub"
g++ -o obj/main.o main.cpp -c -pedantic -Wall -pthread -std=c++0x -I "./sub"
[Compile C++] sub/tiger.cpp
g++ -o obj/sub/tiger.o sub/tiger.cpp -c -pedantic -Wall -pthread -std=c++0x -I "./sub"
[Link] tt.exe FROM: obj/module.o obj/main.o obj/sub/tiger.o
g++ -o tt.exe obj/module.o obj/main.o obj/sub/tiger.o
D:\git\MyTools\make_sample\source>make clean
rm -f -r obj tt.exe depend_file
D:\git\MyTools\make_sample\source>make depend
D:\git\MyTools\make_sample\source>make DEBUG_FLAG=yes
[Compile C] module.c
gcc -o obj/module.o module.c -c -pedantic -Wall -pthread -g -std=c99 -D DEBUG -I "./sub"
[Compile C++] main.cpp
g++ -o obj/main.o main.cpp -c -pedantic -Wall -pthread -g -std=c++0x -D DEBUG -I "./sub"
[Compile C++] sub/tiger.cpp
g++ -o obj/sub/tiger.o sub/tiger.cpp -c -pedantic -Wall -pthread -g -std=c++0x -D DEBUG -I "./sub"
[Link] tt.exe FROM: obj/module.o obj/main.o obj/sub/tiger.o
g++ -o tt.exe obj/module.o obj/main.o obj/sub/tiger.o
D:\git\MyTools\make_sample\source>type depend_file
obj/module.o: module.c module.h
obj/main.o: main.cpp module.h sub/tiger.h
obj/sub/tiger.o: sub/tiger.cpp sub/tiger.h
D:\git\MyTools\make_sample\source>
.SUFFIXES:
.SUFFIXES:.c.cpp.o
# 아래와 같이 설징 시 "make DEBUG_FLAG=yes" 라고 실행하면, -g 옵션이 활성화 된다.
CC := gcc
CXX := g++
ifdef DEBUG_FLAG
DEBUG_OPT := -g
DEBUG_DEF := -D DEBUG
endif
CPPFLAGS = $(DEBUG_DEF) -I "./sub"
CFLAGS = -pedantic -Wall -pthread $(DEBUG_OPT) -std=c99
CXXFLAGS = -pedantic -Wall -pthread $(DEBUG_OPT) -std=c++0x
LDFLGAS = # -L
LDLIBS = # -l
SRC_DIR = . ./sub
OBJ_DIR = obj
SRCS := $(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c )) \
$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.cpp ))
SRCS := $(subst ./,,$(SRCS))
OBJS := $(SRCS:%.c=$(OBJ_DIR)/%.o)
OBJS := $(OBJS:%.cpp=$(OBJ_DIR)/%.o)
OBJS := $(OBJS:%.cpp=$(OBJ_DIR)/%.o)
DEPS = $(OBJS:.o=.d)
MKDIR := mkdir
RM := rm -f
TARGET := tt.exe
.PHONY: all clean
all: $(TARGET)
$(TARGET): $(OBJS)
@echo [Link] $@ FROM: $^
@test -d $(@D) || mkdir -p $(@D)
$(CXX) -o $@ $^ $(LDFLGAS) $(LDLIBS)
$(OBJ_DIR)/%.o:%.c
@echo [Compile C] $<
@test -d $(@D) || $(MKDIR) -p $(@D)
$(CC) -o $@ $< -c $(CFLAGS) $(CPPFLAGS) -MMD
$(OBJ_DIR)/%.o:%.cpp
@echo [Compile C++] $<
@test -d $(@D) || $(MKDIR) -p $(@D)
$(CXX) -o $@ $< -c $(CXXFLAGS) $(CPPFLAGS) -MMD
clean:
$(RM) -r $(OBJ_DIR) $(TARGET)
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(SRCS),)
-include $(DEPS)
endif
endif
D:\git\MyTools\make_sample\source>make
[Compile C] module.c
gcc -o obj/module.o module.c -c -pedantic -Wall -pthread -std=c99 -I "./sub" -MMD
[Compile C++] main.cpp
g++ -o obj/main.o main.cpp -c -pedantic -Wall -pthread -std=c++0x -I "./sub" -MMD
[Compile C++] sub/tiger.cpp
g++ -o obj/sub/tiger.o sub/tiger.cpp -c -pedantic -Wall -pthread -std=c++0x -I "./sub" -MMD
[Link] tt.exe FROM: obj/module.o obj/main.o obj/sub/tiger.o
g++ -o tt.exe obj/module.o obj/main.o obj/sub/tiger.o
D:\git\MyTools\make_sample\source>make clean
rm -f -r obj tt.exe
D:\git\MyTools\make_sample\source>make clean
make DEBUG_FLAG=yes
[Compile C] module.c
gcc -o obj/module.o module.c -c -pedantic -Wall -pthread -g -std=c99 -D DEBUG -I "./sub" -MMD
[Compile C++] main.cpp
g++ -o obj/main.o main.cpp -c -pedantic -Wall -pthread -g -std=c++0x -D DEBUG -I "./sub" -MMD
[Compile C++] sub/tiger.cpp
g++ -o obj/sub/tiger.o sub/tiger.cpp -c -pedantic -Wall -pthread -g -std=c++0x -D DEBUG -I "./sub" -MMD
[Link] tt.exe FROM: obj/module.o obj/main.o obj/sub/tiger.o
g++ -o tt.exe obj/module.o obj/main.o obj/sub/tiger.o
D:\git\MyTools\make_sample\source>