深入Makefile解析及模板

一. Makefile 基础知识

    1.1. makefile常见符号

  $@  表示目标文件
  $^  表示所有的依赖文件
  $<  表示第一个依赖文件
  $?  表示比目标还要新的依赖文件列表

    1.2. 关于等于号

        +=的含义显而易见,将右值增加到左边的变量基础上。空格是自动添加的。
        =的含义是在右值在遍历整个Makefile,完全展开后再赋值给左边的变量。
        ?=的含义是如果左值未被赋值过,则将右值赋值给它,可见这里y不会再被赋值一次。
        :=的含义是将右值当前的值赋值给左值,不会遍历Makefile获取右值的最终值

    1.3. makefile 重要规则

         1.3.1. 每条规则前面都要用tab缩进

         1.3.2. 第一条规则的目标是“终极目标”,也就是直接执行make时默认使用的规则,比如此处就是test

         1.3.3. 关于@:用echo xxx会输出“echo xxx”,用@echo xxx才会会出“xxx”

         1.3.4. 关于-:删除不存在的文件会出错导致make终止,前面加上-表示忽略可能的错误

         1.3.5. clean并不是目标文件,而是希望make执行清除操作;通过.PHONY把clean标记成伪目标,避免了当前目录下真的有文件clean时,由于没有更“新”的依赖文件,导致清除操作不执行

 

    1.4. Makefile 默认符号

    @echo $(CXX) 
    @echo $(CC)
    @echo $(AR)
    @echo $(RM)
    @echo $(CXXFLAGS) 
    @echo $(CFLAGS) 
    @echo $(ARFLAGS) 

 

二. Makefile 模板

    2.1. 单文件项目

all: Hello
Hello:
    gcc -o Hello hello.c
clean:
    rm -rf Hello

    2.2. 多文件项目

        1. 假设一个工程下,有main.c和有多个.c源文件以及同名的.h头文件,虽然可以类似上述例子一样把每条gcc语句都写出来,但是这么就太啰嗦了。可以使用一些Makefile自带的规则简化着写

# 方便起见一般都会先定义编译器链接器
CC = gcc 
LD = gcc

# 正则表达式表示目录下所有.c文件,相当于:SRCS = main.c a.c b.c
SRCS = $(wildcard *.c)

# OBJS表示SRCS中把列表中的.c全部替换为.o,相当于:OBJS = main.o a.o b.o
OBJS = $(patsubst %c, %o, $(SRCS))

# 可执行文件的名字
TARGET = Hello

# .PHONE伪目标,具体含义百度一下一大堆介绍
.PHONY:all clean

# 要生成的目标文件
all: $(TARGET)

# 第一行依赖关系:冒号后面为依赖的文件,相当于Hello: main.o a.o b.o
# 第二行规则:$@表示目标文件,$^表示所有依赖文件,$<表示第一个依赖文件
$(TARGET): $(OBJS)
    $(LD) -o $@ $^

# 上一句目标文件依赖一大堆.o文件,这句表示所有.o都由相应名字的.c文件自动生成
%o:%c
    $(CC) -c $^

# make clean删除所有.o和目标文件
clean:
    rm -f $(OBJS) $(TARGET)

        2. 指定头文件目录以及库文件目录(假设程需要用到libs目录下的libtomcrypt.a静态库和include目录下libtom的头文件)

CC = cc
LD = cc
SRCS = $(wildcard *.cpp)
OBJS = $(patsubst %cpp, %o, $(SRCS))
# -I指定头文件目录
INCLUDE = -I./include
# -L指定库文件目录,-l指定静态库名字(去掉文件名中的lib前缀和.a后缀)
LIB = -L./libs -ltomcrypt
# 开启编译warning和设置优化等级
CFLAGS = -Wall -O2

TARGET = LibtomDemo

.PHONY:all clean

all: $(TARGET)
# 链接时候指定库文件目录及库文件名
$(TARGET): $(OBJS)
    $(LD) -o $@ $^ $(LIB)
 
# 编译时候指定头文件目录
%o:%cpp
    $(CC) -c $^ $(INCLUDE) $(CFLAGS) 

clean:
    rm -f $(OBJS) $(TARGET)

三. linux下C/C++编译时系统搜索 include 和 链接库 文件路径的指定

     3.1. include 头文件路径
        除了默认的/usr/include, /usr/local/include等include路径外,还可以通过设置环境变量来添加系统include的路径:
        # C
            export C_INCLUDE_PATH=XXXX:$C_INCLUDE_PATH
        # CPP
            export CPLUS_INCLUDE_PATH=XXX:$CPLUS_INCLUDE_PATH
        以上修改可以直接命令行输入(一次性),可以在/etc/profile中完成(对所有用户生效),也可以在用户home目录下的.bashrc或.bash_profile中添加(针对某个用户生效),修改完后重新登录即生效
    3.2. link链接库文件路径
        3.2.1.   链接库文件在连接(静态库和共享库)和运行(仅限于使用共享库的程序)时被使用,其搜索路径是在系统中进行设置的(也可以在编译命令中通过 -l  -L 来指定,这里讲的是使用系统默认搜索路径)。
        3.2.2. 一般 Linux 系统把 /lib  /usr/lib  /usr/local/lib 作为默认的库搜索路径,所以使用这几个目录中的链接库文件可直接被搜索到(不需要专门指定链接库路径)。对于默认搜索路径之外的库,则需要将其所在路径添加到gcc/g++的搜索路径之中。
       3.2.3. 链接库文件的搜索路径指定有两种方式:1)修改/etc/so.ld.conf   2)修改环境变量,在其中添加自己的路径
            3.2.3.1. 在环境变量中添加
                  a. 动态链接库搜索路径:
                         export LD_LIBRARY_PATH=XXX:$LD_LIBRARY_PATH
                  b. 静态链接库搜索路径:
                         export LIBRARY_PATH=XXX:$LIBRARY_PATH
                         以上修改可以直接命令行输入(一次性),可以在/etc/profile中完成(对所有用户生效),也可以在用户home目录下的.bashrc或.bash_profile中添加(针对某个用户生效),修改完后重新登录即生效
            3.2.3.2. 在/etc/ld.so.conf 中添加指定的链接库搜索路径(需要root权限),然后运行 /sbin/ldconfig,以达到刷新 /etc/ld.so.cache的效果

 四. 实战

#Target

TARGET = test

INCLUDES      := -I./includes
SRCS         := $(wildcard *.cpp xxxDir/*.cpp yyyDir/*.cpp)
OBJS         := $(patsubst %cpp, %o, $(SRCS))
USEDLIB      := -lxxx

#Compilers
CXX      := $(CROSS_PREFIX)g++
CPPFLAGS = -std=c++11 -g -Wall -O0

LD_LIBRARY_PATH := -L$(shell pwd)/..

.PHONY: all

#Rules
all: $(TARGET)
    @echo $(INCLUDES)
    @echo $(SRCS)
    @echo $(OBJS)


$(TARGET): $(OBJS)
    $(CXX) -o $@ $? $(LD_LIBRARY_PATH) $(USEDLIB)

%.o: %.cpp
    $(CXX) -c $^ -o $@ $(INCLUDES) $(CPPFLAGS) 

.PHONY: clean
clean:
    rm -f $(OBJS) $(TARGET)
View Code

 

参考文献:https://blog.csdn.net/shaosunrise/article/details/79968921

参考文献:https://www.cnblogs.com/bigfi/p/9487427.html

posted @ 2019-04-24 23:01  三七鸽  阅读(91)  评论(0编辑  收藏  举报