(图一)(图2)
图一 为单独编译 单个模块 的Makefile模版
图一 38行的 CLASS_DIR 中包含编译单个模块所需的共同依赖文件,路径下会包含一个编译这些依赖文件的Makefile,见图2;
图一 56行的 $(AT) 就是符号 @, Makefile 中 @ 用于控制其后字符串的显示与否;如果没有$(AT)时,rm 前面是否有注释符 # 都会使rm这条命令的详细操作显示出来;
但如果是 @rm 则不会显示详细操作(注:@ 和 rm 间没有空格);如果是 #@rm 则会显示详细操作,但不执行 rm 的真实操作,方便Makefile文件的调试。
图一 45行的 $(MAKE) -C $(CLASS_DIR) 表示切换到路径 $(CLASS_DIR) 下 并 执行make操作,执行完还会从 $(CLASS_DIR) 路径中退出来,回到之前的路径下。
图一 42行的 all 表示此 Makefile 文件生成的最终总目标,必须放在所有 A : B 即 目标 :依赖 语句的最前面
图一 51行的 $(OBJS) 会由 40行 和 47行 的命令合作生成,40行表示将 $(SRCS) 下的所有 .cpp 变为 .o 文件的集合就是 OBJS,而 .cpp 如何变为 .o 则由 47行指定。
40行 和 47行的格式必须对应,如果40行为 .a=.b (注:= 号前后不能有空格),则47行必须为 %.b : %.a 。
make 调试技巧:
1. $(info ----1----$(变量))
2. 再写一个makefile, 故意引入你想了解的那个makefile,然后打印其中的变量 makefile中的条件判断
makefile和.sh都是字符串脚本语言,因此其一切内容都是字符和字符串,没有数字的概念;不要被c语言误导了,不要认为"中的才是字符串", 无"的就是数值";比如ifneq ($(SRCARCH),$(SUBARCH)) 就是比较这两个变量对应的字符串是否相同,而不是比较数值;因此ifneq ($(SRCARCH),0)就是看变量对应的字符串是不是字符0,而不是看变量的数值是否等于0,如果有点绕就理解下ifneq ($(SRCARCH), y)的形式。
makefile中用于判断和循环(for..in)的demo,makefile相当于make工具的源码,可以控制make工具做很多事,并非只能编译代码
Makefile 循环遍历子文件夹的示例:
1 CC = $(CROSS)gcc 2 CXX = $(CROSS)g++ 3 DEBUG = 4 CFLAGS = $(DEBUG) -Wall -c 5 MV = mv -f 6 RM = rm -rf 7 LN = ln -sf 8 9 TARGET = classify 10 11 TOP_PATH = $(shell pwd) 12 SRC_PATH = $(TOP_PATH)/src 13 MOD_PATH = $(TOP_PATH)/modules 14 MOD_LIB_PATH = $(MOD_PATH)/lib 15 MOD_INC_PATH = $(MOD_PATH)/include 16 DIRS = $(shell find $(SRC_PATH) -maxdepth 3 -type d) 17 FILES = $(foreach dir, $(DIRS), $(wildcard $(dir)/*.cpp)) 18 19 ########################################################## 20 # modules 21 ########################################################## 22 modules = 23 MODULES_PATH = $(foreach m, $(modules), $(MOD_PATH)/$(m)) 24 25 ########################################################## 26 # srcs 27 ########################################################## 28 SRCS_CPP += $(foreach dir, $(DIRS), $(wildcard $(dir)/*.cpp)) 29 SRCS_CC += $(foreach dir, $(DIRS), $(wildcard $(dir)/*.cc)) 30 SRCS_C += $(foreach dir, $(DIRS), $(wildcard $(dir)/*.c)) 31 32 ########################################################## 33 # objs 34 ########################################################## 35 OBJS_CPP = $(patsubst %.cpp, %.o, $(SRCS_CPP)) 36 OBJS_CC = $(patsubst %.cc, %.o, $(SRCS_CC)) 37 OBJS_C = $(patsubst %.c, %.o, $(SRCS_C)) 38 39 ########################################################## 40 # paths 41 ########################################################## 42 INC_PATH += -I$(MOD_INC_PATH) 43 INC_PATH += -I$(MOD_PATH) 44 LIB_PATH += -L$(TOP_PATH)/lib 45 LIB_PATH += -L$(MOD_LIB_PATH) 46 47 ########################################################## 48 # libs 49 ########################################################## 50 51 ########################################################## 52 # building 53 ########################################################## 54 all:$(TARGET) 55 56 $(TARGET) : $(OBJS_CPP) $(OBJS_CC) $(OBJS_C) 57 @ for i in $(MODULES_PATH); \ 58 do \ 59 make -C $$i; \ 60 done 61 62 @ $(CXX) $^ -o $@ $(LIB_PATH) $(LIBS) 63 @ echo Create $(TARGET) ok... 64 65 $(OBJS_CPP):%.o : %.cpp 66 $(CXX) $(CFLAGS) $< -o $@ $(INC_PATH) 67 68 $(OBJS_CC):%.o : %.cc 69 $(CXX) $(CFLAGS) $< -o $@ $(INC_PATH) 70 71 $(OBJS_C):%.o : %.c 72 $(CXX) $(CFLAGS) $< -o $@ $(INC_PATH) 73 74 .PHONY : clean show 75 clean: 76 @ $(RM) $(TARGET) $(OBJS_CPP) $(OBJS_CC) $(OBJS_C) 77 @ for i in $(MODULES_PATH); \ 78 do \ 79 make clean -C $$i; \ 80 done 81 @echo clean all...
82 show:
83 @echo OBJS_C = $(OBJS_C)
84 @echo OBJS_CC = $(OBJS_CC)
(图3)
图3 讲的是pps的概念,发送端的pps帧会和gprmc帧同一时刻发出,但传输需要时间,传输的耗时会体现在pps上,如上图的250ms;因此接收端的真实时间应该是由收到的gprmc中解析出的时间在加上pps的偏移时间所组成,gprmc中的时间精度是秒。
(图4)
图4 讲的是 2 进制单位和 10 进制单位对数据的描述, 1Ki = 2 ^ 10 = 1024 而 1K = 10 ^ 3 = 1000
链接时目标o文件必须放在库lib文件前,即$(LD) $(LDFLAGS) $^ $(LDLIBS) -o $(TARGET).elf (其中 LDLIBS = libm.a + libc.a + ...)