zoukankan      html  css  js  c++  java
  • makefile

    首先,如何用makefile执行一个我们熟悉的语句

    gcc main.c -o main

    目标项:依赖项
    main: main.c
            gcc main.c -o main

    那么,如果不止一个c文件呢

    main: main.o hello.o
        gcc main.o hello.o -o main
        
    main.o: main.c
        gcc -c main.c -o main.o
    
    hello.o: hello.c
        gcc -c hello.c -o hello.o

    如果我有很多个源文件呢?

    这样显然比较复杂,也不利于日后的修改,因为一旦我改了名字,或者删掉了某个c文件,那么整个makefile就要重写

    所以,我们用变量替代main.c hello.c等文件名

    下面介绍几种变量

    变量

    说明

    $@

    当前规则的目标文件

    $<

    当前规则的第一个依赖文件

    $^

    当前规则的所有依赖文件,以逗号分隔

    $?

    规则中日期新于目标文件的所有相关文件列表,逗号分隔

    $(@D)

    目标文件的目录名部分

    $(@F)

    目标文件的文件名部分

    使用一下 $@ 和 $<

    和上述代码相同,用$@ 和 $< 替代main main.c

    main: main.o hello.o
        gcc $^ -o $@
        
    main.o: main.c
        gcc -c $< -o main.o
    
    hello.o: hello.c
        gcc -c $< -o hello.o

    看起来简洁了很多,但是,仍然不能解决我们前面的问题——当有多个源文件需要编译,甚至还不确定是否都有需要的时候,怎么办?

    这里,我们可以将main.c hello.c iic.c adc.c等等等赋值给一个变量

    比如这样

    EXE := main
    SRC := main.c hello.c
    INC := hello.h main.h
    OBJ := main.o hello.o
    
    main: main.o hello.o
        gcc $^ -o $@
        
    main.o: main.c
        gcc -c $< -o main.o
    
    hello.o: hello.c
        gcc -c $< -o hello.o

    这里解释一下赋值号的问题

    有这么几种

    =    这种赋值,你可以先使用变量,后面再去声明,比如 B=A A=20 A的值是后来才赋上的,但是B仍然可以得到20

    :=    这种比较正经,跟C语言中 = 的使用基本差不多

    ?=    在赋值的时候他要判断一下,如果没被赋值,则赋值

    +=    类似于A = A + 1

    我声明了变量之后如何使用呢  用$( )

    还是刚才那个例子

    EXE := main
    SRC := main.c hello.c
    INC := hello.h main.h
    OBJ := main.o hello.o
    
    $(EXE): $(OBJ)
        gcc $^ -o $@
        
    main.o: main.c
        gcc -c $< -o main.o
    
    hello.o: hello.c
        gcc -c $< -o hello.o

    顺便再说一下,其实后面两句gcc可以不写,因为他会自动识别出你需要的o文件,并同同名文件中自动编译,哦,还有头文件也不需要写进去,你自己知道include 过了就可以了

    这样似乎轻松了很多,因为我们可以把各种文件归类了,以后编译什么新的源文件,只需要把xxx.c写进makefile就可以了

    然鹅,还是不够简单。linux中可以用*或者?当作通配符,makefile中也可以这样用

    上例中  o文件的变量和c文件的变量内容有高度一致性

    所以我们

    EXE := main
    SRC := main.c hello.c
    INC := hello.h main.h
    OBJ := $(SRC:%.c=%.o)
    
    $(EXE): $(OBJ)
        gcc $^ -o $@
    
    OBJ := $(SRC:%.c=%.o)这句话就表示,把SRC中所有以.c为结尾的文件名改成以.o为结尾 并把结果赋值给OBJ 其中%当作通配符用





    那么 SRC是否也可以像OBJ那样,也使用一个什么方法,自动提取出所有的.c文件呢

    答案必然是有的,这里用到shell函数
    EXE := main
    SRC := $(wildcard *.c)
    OBJ := $(SRC:%.c=%.o)
    
    $(EXE): $(OBJ)
        gcc $^ -o $@
    SRC := $(wildcard *.c)表示在本文件夹下,所有的.c文件,并把这个值返回给变量SRC
    这样看起来终于好多了
    其实我们也可以用下面两个函数表达同样的意思:
    SRC := $(shell echo *.c) 
    SRC := $(shell ls *.c)




    接下来,把刚才的内容完善一下
    这是一些预定义变量,什么意思呢?就是系统给你定了的变量,你可以通过修改他们稍微的改动一下makefile的效果

    AR:库文件打包程序默认为ar

    AS:汇编程序,默认为as

    CCc编译器默认为cc

    CPPc预编译器,默认为$(CC) -E

    CXXc++编译器,默认为g++

    RM:删除,默认为rm -f

    ARFLAGS:库选项,无默认

    ASFLAGS:汇编选项,无默认

    CFLAGSc编译器选项,无默认

    CPPFLAGSc预编译器选项,无默认

    CXXFLAGSc++编译器选项

    EXE := main
    SRC := $(wildcard *.c)
    OBJ := $(SRC:%.c=%.o)
    CFLAGS := -Wall -O2 -fpic
    
    $(EXE): $(OBJ)
        $(CC) $^ -o $@
    比如本例中,$(CC) 是编译器 和gcc一样用法
          CFLAGS是编译器的选项,Wall 可以发送警报 -O 进行一些优化 -fpic 为了节约内存 需要经常更新而且还要高效运行需要加的参数







    同样的,我们也可以使用通配符,把刚才被我们删掉的main.o : main.c表示出来
    %.o: %.c
        $(CC) $(CFLAGS) -c $< -o $@

     再完善一点,加上一个伪目标clean

    EXE := main
    SRC := $(wildcard *.c)
    OBJ := $(SRC:%.c=%.o)
    CFLAGS := -Wall -O2 -fpic
    
    $(EXE): $(OBJ)
        $(CC) $^ -o $@
    
    
    .PHONY: clean
    
    clean:
        @rm -f *.o
    .PHONY: clean类似于伪目标的声明,当然你不声明也没什么影响。。
    @rm -f *.o @放在命令前面表示这行命令执行的时候不用打印再终端上,自己默默执行就好了
            
    所以这个命令的意思就是:
    只有当我们输入 make clean 时,执行一个命令,删除所有的.o文件,并且不需要通知我。

    当然也可以写成这个样子 因为RM命令默认就是不提示的 所以不用-f了
    @$(RM)  $(OBJ)

    类似地,也可以加入一个rebuild重载
    EXE := main
    SRC := $(wildcard *.c)
    OBJ := $(SRC:%.c=%.o)
    CFLAGS := -Wall -O2 -fpic
    
    $(EXE): $(OBJ)
        $(CC) $^ -o $@
    
    
    .PHONY: clean rebuild
    
    clean:
        @rm -f *.o
    
    rebuild:
        @make clean
        @make $(EXE)

      执行make build 后,先清理一下.o文件,然后再重新编译一遍。

     

    下面时执行make常用的选项

    选项名

    说明

    -C dir

    读取指定目录的makefile

    -f fille

    读取当前目录的file文件做为Makefile

    -i

    忽略所有命令的执行错误

    -I dir

    指定被包含的Makefile所在目录

    -n

    只打印要执行的命令,但是不执行这些命令

    -p

    显示make 变量数据库和隐含规则

    -s

    在执行命令时候不显示命令

    -w

    如果在执行过程中改变目录,则打印当前目录名




     
     

     
  • 相关阅读:
    wpf button的mouse(leftbutton)down/up,click事件不响应解决办法
    多线程引发OutOfMemoryException
    WINDBUG常用命令
    有关OEP脱壳
    reversing.kr easykeygen 之wp
    reversing.kr easy crack 之write up
    pwnable.kr leg之write up
    pwnable input2 之 write up
    pwnable.kr random 之 write up
    pwnable.kr 之 passcode write up
  • 原文地址:https://www.cnblogs.com/qifeng1024/p/11688409.html
Copyright © 2011-2022 走看看