zoukankan      html  css  js  c++  java
  • Makefile学习12——支持头文件目录制定

    在对应目录中放入对应的文件

    /×    foo.h     */
    
    #ifndef __FOO_H
    #define __FOO_H
    
    void foo(void)
    
    #endif/*__FOO_H*/
    
    
    /*    foo.c     */
    
    #include <stdio.h>
    #include "foo.h"
    void foo(void)
    {
        printf("This is foo()!
    ");
    }
    
    /*     main.c   */
    
    #include "foo.h"
    int main(void)
    {
        return 0;
    }

    执行make后报错:

    这是在构建依赖文件时,gcc因为找不到foo.h而报错。那是因为foo.h和foo.c放在不同的目录中,这样需要使用gcc的 -I 选项,指定包含路径,所以,更改后的Makefile如下:

    .PHONY: all clean
    
    MKDIR = mkdir
    RM = rm
    RMFLAGS =-rf
    
    CC = gcc
    AR = ar
    ARFLAGS = crs
    
    DIR_OBJS = objs
    DIR_EXES = $(ROOT)/build/exes
    DIR_DEPS = deps
    DIR_LIBS = $(ROOT)/build/libs
    DIRS = $(DIR_OBJS) $(DIR_EXES) $(DIR_DEPS) $(DIR_LIBS)
    RMS = $(DIR_OBJS) $(DIR_DEPS)
    
    ifneq ("$(EXE)", "")
    EXE := $(addprefix $(DIR_EXES)/, $(EXE))
    RMS += $(EXE)
    endif
    
    ifneq ("$(LIB)", "")
    LIB := $(addprefix $(DIR_LIBS)/, $(LIB))
    RMS += $(LIB)
    endif
    
    SRCS = $(wildcard *.c)
    OBJS = $(SRCS:.c=.o)
    OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))
    DEPS = $(SRCS:.c=.dep)
    DEPS := $(addprefix $(DIR_DEPS)/, $(DEPS))
    
    ifeq ("$(wildcard $(DIR_OBJS))", "")
    DEP_DIR_OBJS := $(DIR_OBJS)
    endif
    ifeq ("$(wildcard $(DIR_EXES))", "")
    DEP_DIR_EXES := $(DIR_EXES)
    endif
    ifeq ("$(wildcard $(DIR_DEPS))", "")
    DEP_DIR_DEPS := $(DIR_DEPS)
    endif
    ifeq ("$(wildcard $(DIR_LIBS))", "")
    DEP_DIR_LIBS := $(DIR_LIBS)
    endif
    
    all: $(EXE) $(LIB)
    
    ifneq ($(MAKECMDGOALS), clean)
    include $(DEPS)
    endif
    
    ifneq ("$(INCLUDE_DIRS)", "")
    INCLUDE_DIRS := $(strip $(INCLUDE_DIRS))
    INCLUDE_DIRS := $(addprefix -I, $(INCLUDE_DIRS))
    endif
    
    $(DIRS):
        $(MKDIR) $@
    $(EXE): $(DEP_DIR_EXES) $(OBJS) 
        $(CC) -o $@ $(filter %.o, $^)
    $(LIB): $(DEP_DIR_LIBS) $(OBJS)
        $(AR) $(ARFLAGS) $@ $(filter %.o, $^)
    $(DIR_OBJS)/%.o: $(DEP_DIR_OBJS) %.c
        $(CC) $(INCLUDE_DIRS) -o $@ -c $(filter %.c, $^)
    $(DIR_DEPS)/%.dep: $(DEP_DIR_DEPS) %.c
        @echo "Creating $@ ..."
        @set -e ; 
        $(RM) $(RMFLAGS) $@.tmp ; 
        $(CC) $(INCLUDE_DIRS) -E -MM $(filter %.c, $^) > $@.tmp ; 
        sed 's,(.*).o[ :]*,objs/1.o $@: ,g' < $@.tmp > $@ ; 
        $(RM) $(RMFLAGS) $@.tmp
    clean:
        $(RM) $(RMFLAGS) $(RMS)

    这样就完成了支持头文件目录指定。

    从Makefile的角度看,一个可以改善编译效率的地方与其中的隐式规则有关。为了了解make的隐式规则,我们把之前的simple项目的Makefile做一点更改,删除生成.o文件的规则(与隐式规则相对应的是,在Makefile中定义的规则称为显示规则)。

    .PHONY: clean
    
    CC = gcc
    RM = rm
    
    EXE =simple
    SRCS =$(wildcard *.c)
    OBJS =$(patsubst %.c, %.o, $(SRCS))
    $(EXE): $(OBJS)
        $(CC) -o $@ $^
    #
    %.o : %.c
        $(CC) -o $@ -c $^删除这两句
    clean:
        $(RM) -rf $(EXE) $(OBJS)

    我们make一下,还是成功了,这就是make存在自带的隐式规则的缘故。

    在make中存在大量的隐式规则,通过隐式规则将大大简化Makefile的编写。这里简化后的Makefile之所以能工作,是因为make中有着下面这样的隐式规则:

     %.o :%.c
     
       $(CC) -c $(CPPFLAGS) $(CFLAGS)  $^

    make需要查找隐式规则会降低编译效率,为了禁止使用make所自带的隐式规则,可以通过make 的 -r选项来实现。

    所以,隐式规则是可以被覆盖的。当Makefile中自己定义了生成.o的文件规则时,make就以它为规则,该规则覆盖了make自带的隐式规则。更多隐式规则可以查看GNU MAKE。make -r的使用可以提高每个源文件的编译效率。

    恰当的书写注释是个好习惯。

    Makefile中的注释以“#”开始,注释多行可以在行末加上""。

  • 相关阅读:
    vuex 简单理解
    es2015(es6)学习总结
    工作资源知识点总结收集
    margin-top使用需要注意的地方
    关于用display:table让元素居中的小结
    display:table-cell
    margin:0 auto;不居中
    css选择器总结
    css 选择器优先级
    给行内元素加上绝对定位之后,元素属性的变化
  • 原文地址:https://www.cnblogs.com/Liu-Jing/p/8324458.html
Copyright © 2011-2022 走看看