1. Linux驱动开发之开篇--Makefile

摘要:
此处使用rm rf$(OBJS)$(TARGET)4特殊符号。由于$^将包含从属文件名,因此将返回包含路径的文件名。因此,$(通配符$^)用于过滤$^包含的所有文件,并且该文件确实存在于本地。自动化变量$?自动变量$^表示通过目录搜索获得的所有从属文件的完整路径名(目录+常规文件名)列表。自动化变量$@表示规则的目标。获取所有列表。工作目录中的c文件“

基本Makefile
假设现在有3个文件,file2.h是函数声明,file2.c是函数定义,文件file1.c调用file2.c中的函数。则Makefile文件的编写如下:

helloworld:file1.o file2.o
    gcc file1.o file2.o -o helloworld
file1.o:file1.c file2.h
    gcc -c file1.c -o file1.o
file2.o:file2.c file2.h
    gcc -c file2.c -o file2.o
clean:
    rm -rf *.o helloworld



2 自动推导

helloworld:file1.o file2.o
    gcc file1.o file2.o -o helloworld
%.o:%.c
    gcc -c $< -o $@
clean:
    rm -rf *.o helloworld

3 变量使用

CC= gcc
CFLAGS= -I/home/mymakefile/include
LDFLAGS= -L/home/mymakefile/lib
LIBS = -lsocket -lmath
CFLAGS= -g -Wall -O2
#PATH = /path/to/bin
SRCS=file1.c file2.c
OBJS=file1.o file2.o
TARGET=helloworld

$(TARGET):$(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o $(TARGET)
%.o:%.c
    $(CC) -c $< -o $@
clean:
     rm -rf $(OBJS) $(TARGET)

4 特殊符号使用
这里$^因为会包含依赖的文件名,如果包含的该文件存在,那么将返回其含路径的文件名
所以$(wildcard $^)就是用来过滤$^包含的所有文件并且该文件确实在本地存在.

自动化变量$?代表依赖文件列表中被改变过的所有文件。
自动化变量$^代表所有通过目录搜索得到的依赖文件的完整路径名(目录 + 一般文件名)列表。
自动化变量$@代表规则的目标。
自动化变量$<代表规则中通过目录搜索得到的依赖文件列表的第一个依赖文件。
自动化变量$(@D)


5 关键词使用

wildcard
subst
  用法是$(subst FROM,TO,TEXT),即将TEXT中的东西从FROM变为TO
TARGETS = 111.cpp 222.cpp 333.cpp
OTARGETS= $(subst cpp,o,$(TARGETS))
LTARGETS= $(subst cpp,lo,$(TARGETS))

patsubst <pattern>,<replacement>,<text> )
(patsubst %.c,%.o,x.c.c bar.c)

把字串“x.c.c bar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.o bar.o”

$(wildcard PATTERN...) 。在Makefile中,它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。
一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表。

可以使用“$(patsubst %.c,%.o,$(wildcard *.c))”,首先使用“wildcard”函数获取工作目录下的.c文件列表;之后将列表中所有文件名的后缀.c替换为.o。

filter


6 选项使用

7 进入子目录

在学习Makefile过程中,一般是Makefile文件和源码、头文件存放在同一个目录中,但对于我们实际的工作过程中,通常是分开的。分开主要有两种方式,一种是根据模块,一种是根据文件的不同。如下面两图:

1. Linux驱动开发之开篇--Makefile第1张     1. Linux驱动开发之开篇--Makefile第2张

对于第一种,按照文件类型进行划分代码,只需要一个Makefile文件就可以,具体的形式如下所示:

1. Linux驱动开发之开篇--Makefile第3张1. Linux驱动开发之开篇--Makefile第4张
 1 ###########################################
 2 # Makefile
 3 #                            By Guo Jianwei
 4 #                                 2014-8-26
 5 #                  EMAIL: gjianw217@163.com
 6 ###########################################
 7 NAME      = app
 8 BIN       = bin/debug/$(NAME)
 9 
10 CC        = gcc
11 CXX       = g++
12 
13 LINKOPT   = -O3
14 FLAGS     = $(LINKOPT)
15 
16 LIBS      = 
17 CFLAGS    = $(LIBS)
18 CXXFLAGS  = $(LIBS) -g
19 
20 INCS      = -I$(INCPATH)/common
21             -I$(INCPATH)/third-party
22 
23 SRCPATH   = src/
24 INCPATH   = include
25 
26 SRCS      = $(shell find $(SRCPATH) -name '*.c' -o -name '*.cpp' 
27                 -o -name '*.cc' 
28               | grep -v 'socket')
29 
30 OBJS      = $(filter %.o,$(SRCS:%.c=%.c.o))
31 OBJS     += $(filter %.o,$(SRCS:%.cpp=%.cpp.o))
32 OBJS     += $(filter %.o,$(SRCS:%.cc=%.cc.o))
33 
34 .PHONY: clean print
35 
36 all: print $(BIN)
37 
38 print:
39     @echo "===================================================="
40     @echo "                   $(BIN)"
41     @echo "===================================================="
42 
43 $(BIN): $(OBJS)
44     $(CXX) $(FLAGS) -o $@ $^
45 
46 %.c.o: %.c
47     $(CXX) $(CFLAGS) $(INCS) -o $@ -c $^
48 
49 %.cpp.o: %.cpp
50     $(CXX) $(CXXFLAGS) $(INCS) -o $@ -c $^
51 
52 %.cc.o: %.cc
53     $(CXX) $(CXXFLAGS) $(INCS) -o $@ -c $^
54 
55 clean:
56     rm -rf $(BIN) $(OBJS)
View Code

对于第二种,按照功能进行组织代码,在每个功能模块中,都需要包含一个Makefile文件,具体的形式如下:

1. Linux驱动开发之开篇--Makefile第5张1. Linux驱动开发之开篇--Makefile第6张
 1 #Makefile
 2 ###########################################
 3 # Makefile
 4 #                            By Guo Jianwei
 5 #                                 2014-8-26
 6 #                  EMAIL: gjianw217@163.com
 7 ###########################################
 8 OBJ=fun1/fun1.o
 9     fun2/fun2.o
10     main.o
11 DEL=fun1/fun1.h
12     fun2/fun2.h
13 SRC=$(patsubst %.o,%.cpp,$(OBJ))
14 TARGET=app
15 .PHONY:all fun1 fun2 app
16 all:fun1 fun2 app
17 fun1:
18     $(MAKE) -C fun1
19 fun2:
20     $(MAKE) -C fun2
21 $(TARGET):$(OBJ)
22     g++ -o $(TARGET) $(OBJ) $(DEL)
23 %.o:%.cpp
24     g++ -c $< $(DEL) 
25 clean:
26     rm $(OBJ) $(TARGET) 
27 
28 ###########################################
29 #Makefile fun1
30 #                            By Guo Jianwei
31 #                                 2014-8-26
32 #                  EMAIL: gjianw217@163.com
33 ###########################################
34 OBJ=
35     fun1.o
36 DEP=
37     fun1.h
38 SRC=
39     fun1.cpp
40 $(OBJ):$(SRC)
41     @echo "fun1 fun1"
42     g++ -c $< $(DEP) 
43 
44 ###########################################
45 #Makefile fun2
46 #                            By Guo Jianwei
47 #                                 2014-8-26
48 #                  EMAIL: gjianw217@163.com
49 ###########################################
50 OBJ=fun2.o
51 DEP=$(patsubst %.o,%.h,$(OBJ))
52 SRC=$(patsubst %.o,%.cpp,$(OBJ))
53 CXX=g++
54 CFLAGS= -O2 -c -Wall -g
55 #$(OBJ):$(SRC)
56 #    $(CXX) $(CFLAGS) $< 
57 $(OBJ):%.o:%.cpp
58     $(CXX) $(CFLAGS) $< $(DEP) 
View Code

 完整的测试代码

免责声明:文章转载自《1. Linux驱动开发之开篇--Makefile》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇VC++创建、调用dll的方法步骤打造你的前端神器-webstorm11下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

在linux7环境下安装oracle的问题记录

问题1 xhost:unable to open display oracle用户运行./runInstaller有如下提示: [oracle@yhxtest-1 database]$ ./runInstaller Starting Oracle Universal Installer... Checking Temp space: must be g...

flume使用之httpSource

flume自带很长多的source,如:exe、kafka...其中有一个非常简单的source——httpsource,使用httpSource,flume启动后会拉起一个web服务来监听指定的ip和port。常用的使用场景:对于有些应用环境中,不能部署Flume SDK及其依赖项,可以在代码中通过HTTP而不是Flume的PRC发送数据的情况,此时HT...

从别人的代码中学习golang系列--01

自己最近在思考一个问题,如何让自己的代码质量逐渐提高,于是想到整理这个系列,通过阅读别人的代码,从别人的代码中学习,来逐渐提高自己的代码质量。本篇是这个系列的第一篇,我也不知道自己会写多少篇,但是希望自己能坚持下去。 第一个自己学习的源码是:https://github.com/LyricTian/gin-admin 自己整理的代码地址:https://g...

Jquery 父、子、兄弟节点查询方法

JQUERY的父,子,兄弟节点查找方法: jQuery.parent(expr)  找父亲节点,可以传入expr进行过滤,比如$("span").parent()或者$("span").parent(".class"); jQuery.parents(expr),类似于jQuery.parents(expr),但是是查找所有祖先元素,不限于父元素; jQu...

隐藏Apache版本号

  为什么要隐藏版本号? 一般情况下,软件的漏洞信息和特定版本是相关的,因此,软件的版本号对攻击者来说是很有价值的。 如何隐藏? 要隐藏Apache版本号其实方法很简单在,只要在httpd.conf中对ServerTokens Prod与ServerSignature Off进行设置即可。 在默认情况下,系统会把Apache版本模块都显示出来(http返回...

Android常见问题1:窗体泄露(1)

  今天学习对话框AlertDialog,写一个Demo,需求是:只有一个Activitty,在这个Activity中只有一个按钮Button,当点击按钮Button时,弹出对话框,提示是否关闭该Activity,退出程序(只有一个界面). MainActivity源码: 1 package com.my.day22_my_dialog1; 2 3...