熟悉linux的都知道,GUN 的make工具在生成可执行程序的过程中为我们提供了非常大的便利。不过要写出高效、简洁的Makefile可就不那么容易了(比如像我这样的菜鸟)。偶最近在进一步学习Makefile,就把遇到的问题以及自己的小小心得写出来,需要指正的大家尽管喷^_^
乍一看上面这个Makefile没啥问题,但是当你执行make的时候问题来了,错误提示说找不到相应的库,并且使用的编译工具是主机的g++,而不是交叉编译工具。
出现以上问题的根本原因就是make的隐晦规则在作祟。这里我先贴出常用的c/c++程序编译的隐晦规则。
(1) 编译C程序的隐含规则
*.o目标的依赖文件自动推导为*.c,并且其隐晦的生成命令一般是“$(CC) –c $(CPPFLAGS) $(CFLAGS)”
(2) 编译C++程序的隐含规则
*.o目标的依赖文件自动推导为*.cc或是*.C,并且其其隐晦的生成命令是“$(CXX) –c $(CPPFLAGS) $(CXXFLAGS)”。(建议使用“.cc”作为C++源文件的后缀,而不是“.C”)
不罗嗦了,先列出一个案例Makefile:
#CXX :=/opt/buildroot-ralink-mt7620/bin/mipsel-linux-g++ #point1
CC :=/opt/buildroot-ralink-mt7620/bin/mipsel-linux-g++
ROOTDIR := /home/yanwei/MTK7620/srcCFLAGS := -I$(ROOTDIR)/user/acmgr/include LDFLAGS := -L$(ROOTDIR)/user/acmgr/obj/cmapi -L$(ROOTDIR)/lib/liblog -L$(ROOTDIR)/lib/libLIB :=-ldl -lpthread -lezxml -llog -ldevutils -lm -lzlogCFLAGS +=-D_GNU_SOURCE -I$(ROOTDIR)/lib/liblog -I$(ROOTDIR)/lib/includeLDFLAGS +=-LlibLIB +=-lcmapi
#point2
#CPPFLAGS := $(CFLAGS)
SRC := acmgr_client.cc
OBJ := $(SRC:.cc=.o)
DEF := $(patsubst %.o, %.d, $(OBJ))
all : acmgr_client
acmgr_client: $(OBJ)
$(CC) -Wall -Wunused -o acmgr_client $< $(CFLAGS) $(LDFLAGS) $(LIB)
.PHONY: all clean
clean:
-rm acmgr_client *.o
-include $(DEF)
乍一看上面这个Makefile没啥问题,但是当你执行make的时候问题来了,错误提示说找不到相应的库,并且使用的编译工具是主机的g++,而不是交叉编译工具。
出现以上问题的根本原因就是make的隐晦规则在作祟。这里我先贴出常用的c/c++程序编译的隐晦规则。
(1) 编译C程序的隐含规则
*.o目标的依赖文件自动推导为*.c,并且其隐晦的生成命令一般是“$(CC) –c $(CPPFLAGS) $(CFLAGS)”
(2) 编译C++程序的隐含规则
*.o目标的依赖文件自动推导为*.cc或是*.C,并且其其隐晦的生成命令是“$(CXX) –c $(CPPFLAGS) $(CXXFLAGS)”。(建议使用“.cc”作为C++源文件的后缀,而不是“.C”)
现在我们明白了,makefile中我们没有写$(OBJ)的依赖规则,而是交给make去自动推导,对于c++程序而言,其隐晦推导的命令应该是“$(CXX) –c $(CPPFLAGS) $(CXXFLAGS)” (注意变量明的定义哦),如果makefile中没有对CXX, CPPFLAGS等进行定义,那么就会可能出现意想不到的问题(所以,将以上makefile中相应命令用注释的两个地方替换掉就没问题啦)。当然make的隐晦规则不止这些,其他更多的可以参考相关教程。