Makefile编写规则

make是一个命令工具,它解释Makefile 中的指令规则。在makefile文件中描述了整个工程所有文件的编译顺序、编译规则。makefile 有自己的书写格式、关键字、函数。像C 语言有自己的格式、关键字和函数一样。而且在makefile 中可以使用系统shell所提供的任何命令来完成想要的工作。makefile(在其它的系统上可能是另外的文件名)在绝大多数的IDE 开发环境中都在使用,已经成为一种工程的编译方法。
.o后缀文件:编译生成的中间代码文件;
.a后缀文件:静态库文件,编译的时候会合到可执行程序中,文件比较大;
.so后缀文件:动态库文件,只是一个指向,不会合到可执行程序中,当要调用函数库的时候才使用;

一、Makefile的规则

  目标 : 需要的条件 (注意冒号两边有空格)
  命令   (注意前面用tab键开头)
解释一下:
  1. 目标可以是一个或多个,可以是Object File,也可以是执行文件,甚至可以是一个标签。
  2. 需要的条件就是生成目标所需要的文件或目标
  3. 命令就是生成目标所需要执行的脚本

二、make是如何工作

 在默认的方式下,也就是我们只输入make命令。
1、make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
2、如果找到,它会找文件中的第一个目标文件(target),并把这个文件作为最终的目标文件。
3、如果目标文件不存在,或是目标文件所依赖的后面的 .o 文件的文件更新时间比目标文件更新时间早,则就会执行后面所定义的命令来重新生成目标文件。
4、如果目标文件所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。
5、make会生成目标文件对应的.o 文件,然后再用 .o 文件生成执行文件。

三、常用变量和符号

$+ :所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。
$?:所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚。
$^ :所有的依赖文件,以空格分开,不包含重复的依赖文件。
$< :第一个依赖文件的名称。
$@ :目标的完整名称。
$* :不包含扩展名的目标文件名称。
$% :如果目标是归档成员,则该变量表示目标的归档成员名称
@echo :这个命令是输出一行字符串。

四、常用编译项说明

-I:指定头文件搜索的路径
-L:连接需要的库文件路径
–l:连接需要的库文件(比如:libpthread.so写作 –lpthread)
# :注释符号
\ :如果一行太长,我们可以通过 符号 \ 来进行换行
-c:意味着产生object文件

五、后缀规则

.SUFFIXES:.cpp .hpp .c .h .o .so .ec .C .sqc 制定新的后缀规则。
(%.c:%.sqc),(%.o:%.c)即规则行为。就是将所有.sqc转为.c,.c再转为.o。
.c.o:等价于%.o:%.c

六、make编译

1.编译可执行程序

假设主函数main.c中调用的有3个文件file1.c, file2.c, file3.cpp和3个头文件file1.h, file2.h, file3.h
注意$(CC) 等前的缩进才用tab按键,不能采用空格替代。
main.c内容如下:

#include "file1.h"
#include "file2.h"
#include "file3.h"
int main()
{
    //这里有N多代码调用file1 file2 file3中方法

    return 0;
}

makefile文件内容:

TARGET =  main

CC =  g++ 
CCFLAGS =  -g -Wall

#依赖库文件
LIB =  -lpthread

#当前目录和CPPINC目录下查找原文件
CPPINC = /usr/include
INC = -I. -I$(CPPINC)

#创建执行文件路径
BIN_DIR = ./bin/
$(shell mkdir -p ${BIN_DIR})

all : $(TARGET)
main: main.o file1.o file2.o file3.o
    $(CC) $(CCFLAGS) -o $@ $^ $(INC) $(LIB) 

#编译所有.cpp文件为.o文件
.cpp.o: 
    @echo $<
    $(CC) $(CCFLAGS) -c -o $@ $< 
    #$(CC) $(CCFLAGS)  -c -o $*.o $*.cpp $(INC) $(LIB)

#编译所有.c文件为.o文件
.c.o:
    @echo $<
    $(CC) $(CCFLAGS) -c -o $@ $< 
    #$(CC)  $(CCFLAGS) -c -o $*.o $*.c  $(INC) $(LIB)
clean: 
    - rm -f *.o   $(TARGET)

2.编译静态库
编译生成静态库 libfiletest.a 并调用在main.c中调用

CC =  g++ 
CCFLAGS =  -g -Wall
#生成静态库文件命令
AR = ar rc

#依赖库文件
LIB =  -lpthread

#当前目录和CPPINC目录下查找原文件
CPPINC = /usr/include
INC = -I. -I$(CPPINC)

#调用shell脚本,创建静态库文件和执行文件目录
LIB_DIR = ./lib/
BIN_DIR = ./bin/
$(shell mkdir -p ${LIB_DIR})
$(shell mkdir -p ${BIN_DIR})

#静态库文件变量
LIB_OBJECT = libfiletest.a
BIN_OBJECT = main

TEST_LIB = -L./lib -lfiletest

all:$(LIB_OBJECT) $(BIN_OBJECT)

$(LIB_OBJECT):file1.o file2.o file3.o
    $(AR) $@ $^
    #将生成的文件移动到对应的文件夹
    mv $(LIB_OBJECT) $(LIB_DIR)

$(BIN_OBJECT): main.o
    $(CC) $(CCFLAGS) -o $@ $^ $(TEST_LIB)
    mv $(BIN_OBJECT) $(BIN_DIR)

#编译所有.cpp文件为.o文件
.cpp.o: 
    @echo $<
    $(CC) $(CCFLAGS) -c -o $@ $< 
    #$(CC) $(CCFLAGS)  -c -o $*.o $*.cpp $(INC) $(LIB)

#编译所有.c文件为.o文件
.c.o:
    @echo $<
    $(CC) $(CCFLAGS) -c -o $@ $< 
    #$(CC)  $(CCFLAGS) -c -o $*.o $*.c  $(INC) $(LIB)
clean: 
    - rm -f *.o   $(LIB_DIR)$(LIB_OBJECT) $(BIN_DIR)$(BIN_OBJECT)

3.编译so动态库

CC =  g++ 
CCFLAGS =  -g -Wall

SHARED = -shared -o
FPIC = -fPIC -c

#依赖库文件
LIB =  -lpthread

#当前目录和CPPINC目录下查找原文件
CPPINC = /usr/include
INC = -I. -I$(CPPINC)

#调用shell脚本,创建动态库文件和执行文件目录
LIB_DIR = ./lib/
BIN_DIR = ./bin/
$(shell mkdir -p ${LIB_DIR})
$(shell mkdir -p ${BIN_DIR})

#动态库文件变量
LIB_OBJECT = libfiletest.so
BIN_OBJECT = main

TEST_LIB = -L./lib/ -lfiletest

all:$(LIB_OBJECT) $(BIN_OBJECT)
OBJECT =file1.o file2.o file3.o
SRC_OBJECT =file1.c file2.c file3.cpp
H_OBJECT = file1.h file2.h file3.h

$(LIB_OBJECT):$(OBJECT)
    $(CC) $(CCFLAGS) $(SHARED) -fPIC -o $@ $^
    mv $(LIB_OBJECT) $(LIB_DIR)

$(OBJECT):$(SRC_OBJECT) $(H_OBJECT)
    $(CC) $(FPIC) $(SRC_OBJECT)

$(BIN_OBJECT): main.o
    $(CC) $(CCFLAGS) -o $@ $^ $(TEST_LIB)
    mv $(BIN_OBJECT) $(BIN_DIR)

main.o: main.c
    $(CC) $(CCFLAGS) -c $^
clean: 
    - rm -f *.o   $(LIB_DIR)$(LIB_OBJECT) $(BIN_DIR)$(BIN_OBJECT)

注意生成动态库后调用动态库时需要将动态库的路径增加到LD_LIBRARY_PATH中,否则会出现找不到动态库文件。
增加方法如下:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/lyuming/maketest/dynamic/lib/

下载演示代码

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值