zoukankan      html  css  js  c++  java
  • Makefile学习之路6——让编译环境更加有序

    在大多项目中都会合理设计目录结构来提高维护性,在编译一个项目时会产生大量中间文件,如果中间文件直接和源文件放在一起,就显得杂乱而不利于维护。在为现在这个complicated项目编写makefile之前,我们先给出目录结构需求:

    1.将所有的目标文件放在objs子目录中;

    2.将最终生成的可执行程序放在exes子目录中;

    在编译项目之前,需要将生成的文件目录准备好,可以手动创建,也可以通过编译Makefile创建。

     1 .PHONY: all clean
     2 
     3 MKDIR = mkdir
     4 RM = rm
     5 RMFLAGS = -rf
     6 
     7 DIRS =objs exes
     8 
     9 all:$(DIRS)
    10 $(DIRS):
    11     $(MKDIR) $@
    12 clean:
    13     $(RM) $(RMFLAGS) $(DIRS)

    为了将项目编译时所创建的文件分别放入objs和exes中,需要用到前面介绍的一个函数,addprefix。

     1 .PHONY: all clean
     2 
     3 MKDIR = mkdir
     4 RM = rm
     5 RMFLAGS = -rf
     6 
     7 CC=gcc
     8 
     9 DIR_OBJS=objs
    10 DIR_EXES=exes
    11 DIRS =$(DIR_OBJS) $(DIR_EXES)
    12 EXE=complicated
    13 SRCS=$(wildcard *.c)
    14 OBJS=$(SRCS:.c=.o)
    15 OBJS:=$(addprefix $(DIR_OBJS)/,$(OBJS))
    16 
    17 all:$(DIRS) $(DIR_EXES)/$(EXE)
    18 $(DIRS):
    19     $(MKDIR) $@
    20 $(DIR_EXES)/$(EXE):$(OBJS)
    21     $(CC) -o $@ $^
    22 $(DIR_OBJS)/%.o:%.c
    23     $(CC) -o $@ -c $^ 
    24 clean:
    25     $(RM) $(RMFLAGS) $(DIRS) $(EXE)

    这里运行之后就会在objs文件夹这种存放.o,在exes文件中存放可执行文件complicated。由于书上是把可执行文件放在当前目录的,所以它在clean加上了删除$(EXE),在我的Makefile中其实这句多余,因为把exes文件夹都删除了,在单独删除exes文件中的可执行文件没有意义,之所以没改,是为了提醒一下自己,这里完成了书上的不再赘述的任务O(∩_∩)O。

    到这里 ,你可能觉得自己又get了一个新技能,但是,这却不是一个好的Makefile,比如,我们把foo.h更改为:

    1 #ifndef __FOO_H
    2 #define __FOO_H
    3 
    4 void foo(int value);
    5 
    6 #endif /*__FOO_H*/

    这里仅仅改变了foo函数的参数,从void变成了int,但是我们执行make:

    注意,这里是在没有更改foo.h之前先make一次,然后在更改了foo.h之后再make,然后make提示居然没有任何事情可以做?奇怪吧,我们明明更改了函数声明不再匹配了啊,我们执行clean之后,再执行make:

    这下make终于发现错误了,为什么第一次重新make的时候,make不发现错误呢?因为我们的Makefile中,并没有依赖foo.h,所以,我们可以更改Makefile如下:

     1 .PHONY: all clean
     2 
     3 MKDIR = mkdir
     4 RM = rm
     5 RMFLAGS = -rf
     6 
     7 CC=gcc
     8 
     9 DIR_OBJS=objs
    10 DIR_EXES=exes
    11 DIRS =$(DIR_OBJS) $(DIR_EXES)
    12 EXE=complicated
    13 SRCS=$(wildcard *.c)
    14 OBJS=$(SRCS:.c=.o)
    15 OBJS:=$(addprefix $(DIR_OBJS)/,$(OBJS))
    16 
    17 all:$(DIRS) $(DIR_EXES)/$(EXE)
    18 $(DIRS):
    19     $(MKDIR) $@
    20 $(DIR_EXES)/$(EXE):$(OBJS)
    21     $(CC) -o $@ $^
    22 $(DIR_OBJS)/%.o:%.c foo.h
    23     $(CC) -o $@ -c $<
    24 clean:
    25     $(RM) $(RMFLAGS) $(DIRS) $(EXE)

    其中红色部分为更改部分。

    可以看到,我们先执行make生成目标文件,然后更改foo.h,再make,立即报错了。虽然这样可以解决问题,但是当项目复杂时,如果每一个头文件都要写入Makefile相应的规则中,那么将会是一个噩梦。看来我们还要寻找一个更好的办法。——当然,在后面的随笔中会提出的。

  • 相关阅读:
    VScode 修改中文字体
    missing KW_END at ')' near '<EOF>'
    SQL inner join, join, left join, right join, full outer join
    SQL字符替换函数translater, replace
    SQL COOKBOOK SQL经典实例代码 笔记第一章代码
    sqlcook sql经典实例 emp dept 创建语句
    dateutil 2.5.0 is the minimum required version python
    安装postgresql后找不到服务 postgresql service
    Postgres psql: 致命错误: 角色 "postgres" 不存在
    【西北师大-2108Java】第十六次作业成绩汇总
  • 原文地址:https://www.cnblogs.com/yangguang-it/p/6807612.html
Copyright © 2011-2022 走看看