通用Makefile模板
Makefile模板
#############################################################################
# #
# 默认为release模式编译,debug模式请使用参数'MODE=DEBUG' #
# #
#############################################################################
###在这里添加源文件目录###
SRCDIR= ./\
###这里定义目标文件目录###
OBJDIR =./.obj/
TARGET_NAME=App
BIN=./
INCLUDE=
LIBDIR=-L./
LIB=
CC=g++
LDFLAG=-lrt
DEPENDS=-MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)"
MODE=DEBUG
ifeq ($(MODE), DEBUG)
BUILD_FLAG = -O0 -g3
else
BUILD_FLAG = -O3
endif
CONDITION=
COM_FLAG=-Wall -c -fmessage-length=0 -std=c++11
BIN_TARGET=$(OBJDIR)bin/$(TARGET_NAME)
SRCS=$(wildcard $(addsuffix *.cpp, $(SRCDIR)))
OBJECTS:=$(addprefix $(OBJDIR), $(subst ./,,$(SRCS:.cpp=.o)))
.PHONY:all mkobjdir clean dep
all:mkobjdir $(BIN_TARGET)
-include $(OBJECTS:.o=.d)
$(BIN_TARGET):$(OBJECTS)
@echo "Linking target $@"
$(CC) $(LDFLAG) -o $@ $^ $(LIBDIR) $(LIB)
@echo " "
@echo "Finished building target: $(TARGET_NAME)"
@echo " "
@-cp -f $(BIN_TARGET) $(BIN)
$(OBJDIR)%.o:%.cpp
ifeq ($(MODE), DEBUG)
@echo "Building DEBUG MODE target $@"
else
@echo "Building RELEASE MODE target $@"
endif
$(CC) $(INCLUDE) $(BUILD_FLAG) $(COM_FLAG) $(DEPENDS) $(CONDITION) -o "$(@)" "$(<)"
@echo " "
mkobjdir:
@test -d $(OBJDIR) || (mkdir $(OBJDIR) && mkdir $(OBJDIR)bin $(addprefix $(OBJDIR), $(subst ./,,$(SRCDIR))))
clean:
-rm -rf $(OBJDIR)
BUILD_FLAG = -O0 -g3
COM_FLAG=-Wall -c -fmessage-length=0 -std=c++11
其中-O0表示关闭所有优化选项,-wall开启大部分警告提示,-c只编译、汇编,不链接
-g3的参数表示gcc编译的时候,会将扩展的debug 信息编译进二进制文件里面,包括宏定义信息。所以,如果要使用gdb调试二进制文件里面的宏定义信息,这个选项必须开启。
-fmessage-length=0参数
默认情况下,gnu工具链编译过程中,控制台输出的一行信息是不换行的,这样,当输出信息过长时(如编译错误时的信息),会导致你无法看到完整的输出信息,加入-fmessage-length=0后,输出信息会根据控制台的宽度自动换行,这样就能看全输出信息了。
Linux常用的库
libz 压缩库(Z)
librt 实时库(real time)
libm 数学库(math)
libc 标准C库(C lib)
gcc/g++ 常用选项编译选项
选项 | 含义 |
---|---|
-E | 只进行预处理,不编译 |
-S | 只编译,不汇编 |
-c | 只编译、汇编,不链接 |
-g | 包含调试信息 |
-I | 指定include包含文件的搜索目录 |
-o | 输出成指定文件名 |
出错提示
选项 | 含义 |
---|---|
-w | 忽略所有警告 |
-Werror | 不区分警告和错误,遇到任何警告都停止编译 |
-Wall | 开启大部分警告提示 |
-Wshadow | 某语句块作用域变量与更大作用域的另一变量同名时发出警告(此警告未包含在-Wall选项中,需单独开启) |
-Wextra | 对所有合法但值得怀疑的表达式发出警告 |
优化选项
选项 | 含义 |
---|---|
-O0 | 关闭所有优化选项 |
-O1 | 第一级别优化,使用此选项可使可执行文件更小、运行更快,并不会增加太多编译时间,可以简写为-O |
-O2 | 第二级别优化,采用了几乎所有的优化技术,使用此选项会延长编译时间 |
-O3 | 第三级别优化,在-O2的基础上增加了产生inline函数、使用寄存器等优化技术 |
-Os | 此选项类似于-O2,作用是优化所占用的空间,但不会进行性能优化,常用于生成最终版本 |
-M -MM -MMD -MF -MT选项含义
- -M 生成文件关联的信息。包含目标文件所依赖的所有源代码
- -MM生成文件关联的信息,但是它将忽略由#include造成的依赖关系
- -MMD 和-MM相同,但是输出将导入到.d的文件里面
- -MF 指定一个文件用于存放生成文件的关联信息,这些信息与-M或-MM是一样的,所以要与-M或-MM一些使用,否则会报错
- -MT 指定目标文件名
- 注意:单独使用-M或-MM时,生成的目标文件没有可执行属性
➜ Test ls
kmp.cpp TestTime
➜ Test g++ kmp.cpp -M
kmp.o: kmp.cpp /usr/include/stdc-predef.h \
/apps/sylar/include/c++/9.1.0/iostream \
/apps/sylar/include/c++/9.1.0/x86_64-pc-linux-gnu/bits/c++config.h \
/apps/sylar/include/c++/9.1.0/x86_64-pc-linux-gnu/bits/os_defines.h \
/usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
/usr/include/gnu/stubs-64.h \
/apps/sylar/include/c++/9.1.0/x86_64-pc-linux-gnu/bits/cpu_defines.h \
/apps/sylar/include/c++/9.1.0/ostream /apps/sylar/include/c++/9.1.0/ios \
/apps/sylar/include/c++/9.1.0/iosfwd \
/apps/sylar/include/c++/9.1.0/bits/stringfwd.h \
/apps/sylar/include/c++/9.1.0/bits/memoryfwd.h \
/apps/sylar/include/c++/9.1.0/bits/postypes.h \
/apps/sylar/include/c++/9.1.0/cwchar /usr/include/wchar.h \
/usr/include/stdio.h \
/apps/sylar/lib/gcc/x86_64-pc-linux-gnu/9.1.0/include/stdarg.h \
/usr/include/bits/wchar.h \
/apps/sylar/lib/gcc/x86_64-pc-linux-gnu/9.1.0/include/stddef.h \
/usr/include/xlocale.h /apps/sylar/include/c++/9.1.0/exception \
/apps/sylar/include/c++/9.1.0/bits/exception.h \
/apps/sylar/include/c++/9.1.0/bits/exception_ptr.h \
/apps/sylar/include/c++/9.1.0/bits/exception_defines.h \
/apps/sylar/include/c++/9.1.0/bits/cxxabi_init_exception.h \
/apps/sylar/include/c++/9.1.0/typeinfo \
/apps/sylar/include/c++/9.1.0/bits/hash_bytes.h \
/apps/sylar/include/c++/9.1.0/new \
/apps/sylar/include/c++/9.1.0/bits/nested_exception.h \
/apps/sylar/include/c++/9.1.0/bits/move.h \
/apps/sylar/include/c++/9.1.0/bits/concept_check.h \
/apps/sylar/include/c++/9.1.0/type_traits \
/apps/sylar/include/c++/9.1.0/bits/char_traits.h \
/apps/sylar/include/c++/9.1.0/bits/stl_algobase.h \
/apps/sylar/include/c++/9.1.0/bits/functexcept.h \
/apps/sylar/include/c++/9.1.0/bits/cpp_type_traits.h \
/apps/sylar/include/c++/9.1.0/ext/type_traits.h \
/apps/sylar/include/c++/9.1.0/ext/numeric_traits.h \
/apps/sylar/include/c++/9.1.0/bits/stl_pair.h \
...
➜ Test ls
kmp.cpp TestTime
➜ Test
# 测试-MM
➜ Test g++ -MM kmp.cpp
kmp.o: kmp.cpp
➜ Test ls
kmp.cpp TestTime
# 注意这里的定法,即使没有指明目标-o,编译器也会自动生成a.out,这与前面-M,-MM有所不同。
➜ Test g++ -MMD kmp.cpp
➜ Test ls
a.out kmp.cpp kmp.d TestTime
➜ Test vim kmp.d
➜ Test ls
a.out kmp.cpp kmp.d TestTime
# 测试-MF
➜ Test ls
kmp.cpp TestTime
➜ Test g++ -MMD -MF test.d kmp.cpp
➜ Test ls
a.out kmp.cpp test.d TestTime
➜ Test g++ kmp.cpp -MT kmp.o
cc1plus: error: to generate dependencies you must specify either ‘-M’ or ‘-MM’
➜ Test g++ kmp.cpp -MT kmp.o -MM
kmp.o: kmp.cpp
➜ Test ls
kmp.cpp TestTime
➜ Test g++ kmp.cpp -MT kmp.d -MT kmp.o -MM
kmp.d kmp.o: kmp.cpp
➜ Test ls
kmp.cpp TestTime
➜ Test g++ kmp.cpp -MF kmp.d -MT kmp.d -MT kmp.o -MM
➜ Test ls
kmp.cpp kmp.d TestTime
➜ Test cat kmp.d
kmp.d kmp.o: kmp.cpp
➜ Test g++ kmp.cpp -MM -MF kmp.d -MT kmp.o -MT kmp.d
➜ Test cat kmp.d
kmp.o kmp.d: kmp.cpp
总结:
-M,-MM,-MMD,-MF,-MT这几个用法,主要是用来生成关联信息,以及指定输出文件名,项目中一般习惯用-MMD这一个,其他几个很少会用。另外加上-D,编译器会自动生成.d的的文件保存关联信息,同时最终生成的目标文件也不会没有可执行属性。