makefile 指定输出目录

1 makefile例子

     写这个例子的目的,由于工作中多数情况下是维护模块,makefile文件已经写好了,后面维护只是添加或修改文件,
 所以很少写这玩意,这次负责一个新模块,需要自己写这个模块的makefile,突然发现之前的makefile都忘差不多了,
 因此写个小例子实验并记录一下,方便以后参考,省的到处查找。
     例子中程序内容不重要,重要的是makefile文件,这个例子目的是生成libcacu.so库,生成的库和中间文件.o放
  在指定的目录下。

1.1 目录结构

	cacu/
	|-- add
	|   |-- add.c
	|-- dbg
	|   |-- dbg.c
	|-- div
	|   |-- div.c
	|-- mul
	|   |-- mul.c
	|-- sub
	    |-- sub.c
	|-- inc
	|   |-- add.h
	|   |-- cacu.h
	|   |-- comm.h
	|   |-- div.h
	|   |-- mul.h
	|   |-- sub.h
	|   |--dbg.h    
	|-- Makefile

1.2 makefile文件

SRC_DIR = add sub mul div dbg
#VPATH = add:sub:mul:div:dbg
vpath %.c add:sub:mul:div:dbg #查找依赖时如果遇到%.c,则自动到add:sub:mul:div:dbg目录下寻找
CUR_DIR  = $(shell pwd)
SRC = $(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
$(info "SRC:$(SRC)")
OBJ = $(patsubst %.c,%.o,$(SRC))
$(info "OBJ:$(OBJ)")
TARGET_NAME = libcacu.so
TARGET_TYPE = so# "#":标识结束,纺织在ifeq时出现预想不到的结果 ,so:dynamic library,bin:exe,a:static library
CFLAGS =  -fPIC -shared
INCLUDE = -I./inc
CC = gcc
#指定在源码目录意外的目录即可,原因,编译过程不影响源码的目录结构,方便提交代码,这里指定和源码同级的out目录
OUT_DIR = $(CUR_DIR)/../out
$(info "OUT_DIR:$(OUT_DIR)")
OBJ_DIR = $(OUT_DIR)/obj
$(info "OBJ_DIR:$(OBJ_DIR)")
BIN_DIR = $(OUT_DIR)/bin
$(info "BIN_DIR:$(BIN_DIR)")
LIB_DIR = $(OUT_DIR)/lib
$(info "LIB_DIR:$(LIB_DIR)")
OBJ_WITHOUT_DIR = $(notdir $(OBJ))
$(info "OBJ_WITHOUT_DIR:$(OBJ_WITHOUT_DIR)")
OBJ_WITH_DIR = $(addprefix $(OBJ_DIR)/,$(OBJ_WITHOUT_DIR))
$(info "OBJ_WITH_DIR:$(OBJ_WITH_DIR)")
ifeq ($(TARGET_TYPE),so)# 逗号和so之间最好有一个空格,可以没有,so后切记不要有空格
TARGET = $(LIB_DIR)/$(TARGET_NAME)#切记不要用tab键空格,想要空格的话可以space键打出空格,再强调一边不要用tab键!!!!!!!!!!
$(info "TARGET:$(TARGET)")
endif

all: dir_create $(TARGET)

FORCE: #force destion	没有使用,没删出的目的,记录下强制执行的方式

$(TARGET):$(OBJ_WITH_DIR)
ifeq ($(TARGET_TYPE),so)# 逗号和so之间最好有一个空格,so后切记不要有空格
	$(CC) $(CFLAGS) $(INCLUDE)  $^ -o $@
endif

#定义创建目录的功能块(由于类似与函数,一般叫做函数)
define CRT_DIR
	if [ ! -d $(1) ];\
	 	then\
    	mkdir -p $(1);\
    	echo "******$(1) created success!!!******";\
    else\
      echo "******$(1) has been created!!!******";\
	fi	
endef

#这个目标用于创建目录,并且是总目标依赖的第一个目标,这样执行总目标时可以保证第一个执行,因为后面的目标依赖这个这个目标创建的目录
dir_create:  
	@$(call CRT_DIR,$(OUT_DIR))
	@$(call CRT_DIR,$(OBJ_DIR))
	@$(call CRT_DIR,$(BIN_DIR))
	@$(call CRT_DIR,$(LIB_DIR))


#目录结构的规则模式替换,因为.o文件在OBJ_DIR目录下,所以要加OBJ_DIR路径
#OBJ_DIR = ../out/obj 也就是所有的中间文件.o都在这个目录下面。
#这时很容易联想到那么.c文件也应该加上目录SRC_DIR ,是的,一开始我也是这样做的,但结果是不行的
#原因,我的猜测是SRC_DIR是多个目录导致的,不能这样用,具体原因不清楚。
#到网上搜相关的内容,找到都是单个目录的(SRC_DIR只有一个值)
#如果是多个目录必须使用vpath或VPATH(个人看法)
#所以添加了一句 vpath %.c add:sub:mul:div:dbg ,意思是查找依赖时如果遇到%.c,则自动到add:sub:mul:div:dbg目录下寻找

#目录结构的规则模式替换,因为.o文件在OBJ_DIR目录下,所以要加OBJ_DIR路径
#源文件.c并不在同一个目录下,所以不能直接将SRC_DIR加到%.c前,需要使用VPATH或vpath自动化变量辅助
$(OBJ_DIR)/%.o:%.c
	$(CC) -c $< -o $@
	
	
clean:
	rm -rf $(OBJ_DIR)	$(BIN_DIR)  $(LIB_DIR)

1.3输出目录

   cacu/
	out/
	|-- bin
	|-- lib
	|   |-- libcacu.so
	|-- obj
	    |-- add.o
	    |-- dbg.o
	    |-- div.o
	    |-- mul.o
	    |-- sub.o
	 
说明:out目录和cacu在同一级(源码以外的目录),这样做的原因,编译的过程不改变代码目录结构,方便代码的提交

1.4 makefile 分析

1.4.1 makefile解释

	 1 查找依赖时如果遇到%.c,则自动到add:sub:mul:div:dbg目录下寻找 
	   vpath %.c add:sub:mul:div:dbg 
	   
	 2 遍历$(SRC_DIR)的所有子目录同时把子目录下的.c文件遍历出来
	    SRC = $(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
		SRC = add/add.c sub/sub.c mul/mul.c div/div.c dbg/dbg.c
		
	  3 把.c替换成.o
		OBJ = $(patsubst %.c,%.o,$(SRC))
		OBJ = :add/add.o sub/sub.o mul/mul.o div/div.o dbg/dbg.o
		
	  4 获取不含路径的.o	
        OBJ_WITHOUT_DIR = $(notdir $(OBJ))
        OBJ_WITHOUT_DIR = add.o sub.o mul.o div.o dbg.o
        
      5 增加前缀$(OBJ_DIR)/
        OBJ_WITH_DIR = $(addprefix $(OBJ_DIR)/,$(OBJ_WITHOUT_DIR))
        OBJ_WITH_DIR = /home/workspace/cacu/../out/obj/add.o  /home/workspace/cacu/../out/obj/sub.o /home/workspace/cacu/../out/obj/mul.o  /home/workspace/cacu/../out/obj/div.o  /home/workspace/cacu/../out/obj/dbg.o
        
      6 调用创建目录的函数
        $(call CRT_DIR,$(OUT_DIR))
        创建OUT_DIR目录
        
      7 打印变量的值方便调试
        $(info "OBJ:$(OBJ)")

1.4.2 makefile测试文件(有时间再上传)

	可以根据描述的目录结构自己完成,程序内容就是加、减、乘、除,可以忽略dbg文件。
  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值