分享一个万能 Makefile

本文分享了一个易于理解的Makefile,适用于Linux开发,包含自动生成编译依赖、头文件搜索路径设置和简化编译流程,有助于新手快速上手。

分享一个万能的 Makefile。

 在 Linux 里开发代码Makefile是不可绕过的一个环节,之前为了方便代码编译和移植,自己也写过一些傻瓜式的 Makefile ,但是感觉还是不够傻瓜智能。


 最近正好在 Makefile 上遇到了点问题,于是顺手将之前写的 Makefile 优化了一下,嗯,这次觉得比较够傻瓜了,所以分享上来,希望对新手能有一些帮助。

在这里插入图片描述
 
 上图为我自己创建的代码工程结构。src文件夹用于放置工程源文件(支持子文件夹嵌套)、inc文件夹用于放置头文件(可以有子文件夹,编译时会指定为头文件搜索路径)、obj文件夹用于存放编译时生成的中间文件。
  

话不多说先贴一下 Makefile

TARGET := main

#CROSS_COMPILE := arm-linux-gnueabihf-
CC := $(CROSS_COMPILE)gcc

SRC := src
INC := inc
OBJ := obj

BUILD := $(shell find $(SRC)/* | grep "\.c$$")
HEAD_PATH := $(foreach n, $(shell ls -l $(INC) | awk '/^d/ {print $$NF}'), /$(n)/) /

C_FLAGS += $(foreach n, $(HEAD_PATH), -I $(INC)$(n))
#C_FLAGS += -I /usr/local/mysql/include

O_FLAGS += -g
#O_FLAGS += -L /usr/local/mysql/lib
#O_FLAGS += -lmysqlclient
O_FLAGS += -lpthread
O_FLAGS += -lusb-1.0

all : $(TARGET)

$(TARGET) : $(foreach n, $(BUILD), $(patsubst  $(SRC)%.c,$(OBJ)%.o, $(n)))
    $(CC) -o $@ $^ $(O_FLAGS)
#   $(CC) -o $@ $(foreach n, $^, $(OBJ)/$(notdir $(n))) $(O_FLAGS)

$(OBJ)/%.o : $(SRC)/%.c
    $(shell mkdir -p $(dir $@))
    $(CC) -c $< -o $@ $(C_FLAGS)
#   $(CC) -c $< -o $(OBJ)/$(notdir $@) $(C_FLAGS)

clean :
#   @echo $(foreach n, $(BUILD), $(patsubst  $(SRC)%.c,$(OBJ)%.o, $(n)))
    rm -f $(foreach n, $(BUILD), $(patsubst  $(SRC)%.c,$(OBJ)%.o, $(n)))
    rm -f $(TARGET)

 简单介绍一下功能,Makefile 将 src 路径下扫描到的所有源文件并保存到 BUILD 变量中,并将inc路径下扫描到的文件夹作为头文件搜索路径保存 HEAD_PATH 中。

 在编译时,BUILD 变量中的源文件名会进行一系列的替换操作,其中后缀会被替换成 .o 且根路径会被替换为 obj ,如: src/function/complete.c 会被替换为 obj/function/complete.o 。

 替换后的内容作为链接时生成目标文件的依赖,用于后续编译中间文件( .o 文件)时 Makefile 的规则匹配。中间文件的编译过程比较简单,不太懂Makefile编译规则的小伙伴可以去搜一下相关的帖子学习学习。

简单介绍一下 Makefile 里用到的几个函数:
  • patsubst
    原型:$(patsubst <pattern>,<to>,<text>)
    功能:比较 text 中的字符串 是否符合 pattern 中的格式, 符合的话, 用 to 替代,否则返回空。
    举例:
      $(patsubst abc_%.c, def_%.o, abc_123.c)
      首先比较字符串 “abc_123.c” 是否符合 “abc_%.c” 的格式,符合的话,匹配成功,这时%的内容变为123(相当于对%赋值为123),再将%代入 “def_%.o” ,最终输出 “def_123.o” 。

  • subst
    原型: $(subst <from>,<to>,<text>)
    功能:把字符串 text 中的 from 替换为 to
    举例:
       $(subst .c,.o,main.c)
      “main.c” 中的 “.c” 被 “.o” 替换,最终输出 “main.o” 。
      subst 与 patsubst 函数类似,但是 patsubst 强调一个匹配的过程,而 subst 只是一个简单的替换。

  • notdir
    原型:$(notdir <names>)
    功能:从文件名序列 names 中取出非目录部分。
    举例:
      $(notdir src/function/complete.c)
      去掉路径,最终输出“complete.c”。

  • dir
    原型:$(dir <names>)
    功能:从文件名序列 names 中取出目录部分。
    举例:
      $(dir src/function/complete.c)
      取出路径,最终输出“src/function/”。

  • foreach
    原型:$(foreach <value>,<list>,<text>)
    功能:类似于for循环,把 list 中的内容逐一赋值给 value ,然后执行 textlist 中的内容以空格或 tab 键分割。
    举例:
      names := a b c
      $(foreach n,$(names),$(n).o)
      依次取出 names 中的内容赋值给 n ,然后执行 $(n).o,最后输出 “a.o b.o c.o”。

  • wildcard
    原型:$(wildcard <pattern>)
    功能:扫描文件列表,输出符合 pattern 条件的所有文件名称,文件名称之间使用空格分开。
    举例:
      $(wildcard *.c)
      扫描当前路径下的文件列表,输出所有文件名后缀为 “.c” 的文件名称,文件名之间用空格分开。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值