• Makefile编程


    【个人体会】0.1 项目文件要合理分隔,功能模块分开放,分别设置Makefile自动编译,

                           0.2 源码和头文件分开放,一个或多个头文件对应一个源码文件。

                           0.3 头文件中不要定义变量。

    1. 默认变量与注释

    # 表示注释

    @ 取消回显

    $^ 表示所有依赖文件

    $@ 表示目标

    $< 表示第一个依赖文件

    2. 伪目标(伪目标重建时,并不影响其他的,所以很方便的添加和描述非预设的动作)

    .PHONY:clean 声明clean为伪目标(作用?)

    clean:

    rm -f hello main.o

    【注】作用:因为没有依赖文件,所以目标文件一定是最新的,所以即使用户明确命令 make clean 重新产生它,也不会有任何事情发生。解决方法是标明所有的伪目标(用 .PHONY),这就告诉 make 不用检查它们是否存在于磁碟上,也不用查找任何隐含规则,直接假设指定的目标需要被更新。

    3. 基本语法

        3.1 基本格式

    targets:prerequistes

    【tab】command

    eg:

    main.o:main.c

    gcc -c main.c

        3.2 =和:=区别

    eg:

    A = foo

    B = $(A)

    # 现在 B 是 $(A) ,而 $(A) 是 'foo' 。

    A = bar

    # 现在 B 仍然是 $(A) ,但它的值已随着变成 'bar' 了。

    B := $(A)

    # 现在 B 的值是 'bar' 。

    A = foo # B 的值仍然是 'bar' 。

    4. 时间戳的作用

    eg:

    myprog : foo.o bar.o

    gcc foo.o bar.o -o myprog

    foo.o : foo.c foo.h bar.h

    gcc -c foo.c -o foo.o

    bar.o : bar.c bar.h

    gcc -c bar.c -o bar.o

    【注】make 从最上面开始,把第一个目标myprog做为主要目标。只要文件myprog比文件foo.o或bar.o中的任何一个旧,下一行的命令将会被执行。但是,在检查文件 foo.o 和 bar.o 的时间戳之前,它会往下查找那些把 foo.o 或 bar.o 做为目标文件的规则。它找到的关于 foo.o 的规则,该文件的依靠文件是 foo.c, foo.h 和 bar.h 。 它从下面再找不到生成这些依靠文件的规则,它就开始检查磁碟 上这些依靠文件的时间戳。如果这些文件中任何一个的时间戳比 foo.o 的新,命令 'gcc -o foo.o foo.c' 将会执行,从而更新 文件 foo.o 。 接下来对文件 bar.o 做类似的检查,依靠文件在这里是文件 bar.c 和 bar.h 。

    5. 使用变量

    eg:

    OBJS = foo.o bar.o

    CC = gcc

    CFLAGS = -Wall -O -g

    myprog : $(OBJS)

    $(CC) $(OBJS) -o myprog

    foo.o : foo.c foo.h bar.h

    $(CC) $(CFLAGS) -c foo.c -o foo.o

    bar.o : bar.c bar.h

    $(CC) $(CFLAGS) -c bar.c -o bar.o

    编译的指令可以写为: #(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@

    CC 编译器

    CFLAGS 给c编译器传递变量,c++用CXXFLAGS

    CPPFLAGS c预处理器旗标

    TARGET_ARCH

    6. 函数

    SOURCES=$(wildcard  *.c) 使用函数wildcard,产生一列.c结尾的文件

    列表,空格分隔,存到SOURCES中。

    OBJS=$(patsubst %.c,%.o,$(SOURCES)) SOUCES中以.c结尾的都用.o代替.c。

    其中%匹配一个和多个字符。

    eg:

    SOURCES = $(wildcard *.c *.cc)

    OBJS = $(patsubst %.c,%.o,$(patsubst %.cc,%.o,$(SOURCES)))

    myprog : $(OBJS)

    gcc -o myprog $(OBJS)

    depends : $(SOURCES)

    gcc -M $(SOURCES) > depends

    7. 一个完整的Makefile

    ######################################

    # Generic makefile

    #

    # by AUTHOR

    #

    # Copyright (c)

    # All rights reserved.

    ######################################

    # 用户设定

    # 如果需要,调整下面的东西。 EXECUTABLE 是目标的可执行文件名, LIBS

    # 是一个需要连接的程序包列表(例如 alleg, stdcx, iostr 等等)。当然你

    # 可以在 make 的命令行覆盖它们,你愿意就没问题。

    #

    # 现在来改变任何你想改动的隐含规则中的变量。

    CFLAGS := -g -Wall -O3 -m486

    CXXFLAGS := $(CFLAGS)

    # 下面先检查你的 djgpp 命令目录下有没有 rm 命令,如果没有,我们使用

    # del 命令来代替,但有可能给我们 'File not found' 这个错误信息,这没

    # 什么大碍。如果你不是用 DOS ,把它设定成一个删文件而不废话的命令。

    # (其实这一步在 UNIX 类的系统上是多余的,只是方便 DOS 用户。 UNIX

    # 用户可以删除这5行命令。)

    ifneq ($(wildcard $(DJDIR)/bin/rm.exe),) #【注】ifneq与ifeq用法相反

    RM-F := rm -f

    else

    RM-F := del

    endif

    # 从这里开始,你应该不需要改动任何东西。(我是不太相信,太NB了!)

    SOURCE := $(wildcard *.c) $(wildcard *.cc)

    OBJS := $(patsubst %.c,%.o,$(patsubst %.cc,%.o,$(SOURCE)))

    DEPS := $(patsubst %.o,%.d,$(OBJS))

    MISSING_DEPS := $(filter-out $(wildcard $(DEPS)),$(DEPS))

    #【注】filter-out函数使用两个空格分开的列表,把第二列表中所有的存在于第一列表中的项目删除。

    MISSING_DEPS_SOURCES := $(wildcard $(patsubst %.d,%.c,$(MISSING_DEPS))

    $(patsubst %.d,%.cc,$(MISSING_DEPS)))

    CPPFLAGS += -MD

    .PHONY : everything deps objs clean veryclean rebuild

    everything : $(EXECUTABLE)

    deps : $(DEPS)

    objs : $(OBJS)

    clean : #【注】删除所有中介/依赖文件(*.d 和 *.o )

    @$(RM-F) *.o

    @$(RM-F) *.d

    veryclean: clean

    @$(RM-F) $(EXECUTABLE)

    rebuild: veryclean everything

    ifneq ($(MISSING_DEPS),)

    $(MISSING_DEPS) : @$(RM-F) $(patsubst %.d,%.o,$@)

    endif

    -include $(DEPS)

    $(EXECUTABLE) : $(OBJS)

    gcc -o $(EXECUTABLE) $(OBJS) $(addprefix -l,$(LIBS))

    #【注】addprefix函数把第二个参数列表每一项前缀上第一个参数值。

    # everything:(预设) 更新主要的可执行程序,并且为每一个源码文件

    # 生成或更新一个 '.d' 文件和一个 '.o' 文件。

    # deps: 只是为每一个源码程序产生或更新一个 '.d' 文件。

    # objs: 为每一个源码程序生成或更新 '.d' 文件和目标文件。

    # veryclean: 做 `clean' 和删除可执行文件。

    # rebuild: 先做 `veryclean' 然后 `everything' ;既完全重建。

    # 除了预设的 everything 以外,这里头只有 clean,veryclean,和 rebuild 对用户是有意义的。

    #

    #

  • 相关阅读:
    ACS 20070108 更新
    道德沦丧 还是意识淡薄
    Alienwave.CommunityServer 20070103 更新
    无题
    《白马啸西风》之李文秀
    突然感觉自己像拉皮条的
    数据库日志文件(x.ldf)如何打开?
    调试.NET出错
    老大离开南京了
    最近太任性了
  • 原文地址:https://www.cnblogs.com/lucas-hsueh/p/3714431.html
Copyright © 2020-2023  润新知