makefile

  • 什么是makefile

    • 项目编译管理软件
  • makefile的好处

    • 可以方便的更改变量
  • 实现

    • 如果目标不存在,根据命令生成目标
    • 如果依赖文件修改时间新于目标,重新执行命令
  • 格式

    a.out:a.cpp
    	g++ a.cpp -std=c++11 -g
    
    目标:依赖
    	命令
    
  • 使用变量

    srcs := 1.c 2.c 3.c 4.c 5.c
    
    mybin: $(srcs)
    	gcc -omy.bin $(srcs)
    
    定义变量
    	srcs := 变量值 立即赋值
    	srcs = 变量值 运行时赋值
    使用变量 
    	$(变量)
    
  • 内置变量

    CC			gcc
    CPPFLAGS	预编译时的flags(pp pre process)
    CFLAGS 		C语言flags
    CXXFLAGS	C++语言的flags
    LIBS		链接库 -L.. -l
    AR			静态库打包的命令
    RM			删除命令
    
    内置变量可以覆盖或添加内容
    
    覆盖:
    CC := g++
    
    添加:
    CPPFLAGS += ...
    
    $@表示目标
    $^表示所有的依赖
    $<表示第一个依赖
    $*表示去掉后缀
    $?表示更新的部分
    $+表示更新的部分,但是把所有的更新全部打印
    
  • 一个文件修改导致整个程序完全重新编译

    srcs := 1.c 2.c 3.c 4.c 5.c
    my.bin: $(srcs)
    	gcc -omy.bin $(srcs)
    
    # 改进:
    objs := 1.o 2.o 3.o 4.o 5.o
    
    my.bin: $(objs)
    	gcc -o$@ $^
    
    %.o: %.c
    	gcc -c -o$@ $^
    
  • 当makefile文件有多个目标时,make命令默认编译第一个目标,可以使用make 目标名 来编译指定目标

  • 一个目标的依赖可以分开写,但是命令只能有一个

    my.bin: 1.o
    objs := 1.o 2.o 3.o 4.o 5.o
    
    my.bin: $(objs)
    	gcc -o$@ $^
    
    %.o: %.c
    	gcc -c -o$@ $^
    
  • 隐藏依赖

    • 默认依赖的原则是 .o依赖相应的.c 命令是:

      $(CC) $(CPPFLAGS) -c -o$@ $^
      
  • 自动生成依赖关系

    gcc -MM 1.c
    
  • 自动依赖makefile(多个.c生成一个可执行文件):

    #定义伪目标 表示目标不是文件,同目录下存在同名文件也不要冲突
    .PHONY: all clean install uninstall
    
    target := myapp
    # srcs := $(shell ls *.c) #shell是一个函数
    srcs := $(wildcard *.c)
    # objs := $(srcs:.c=.o)
    objs := $(patsubst %.c, %.o, $(srcs))
    # deps := $(srcs:.c=.d)
    deps := $(patsubst %.c, %.d, $(srcs))
    
    all: $(target)
    
    -include $(deps) #include前面加-表示包含的文件不存在也不报错
    
    %.d: %.c
    	$(CC) -MM $^ > $@
    
    %.o: %.c
    	$(CC) -c -o $@ $<
    
    $(target): $(objs)
    	$(CC) -o $@ $^
    
    clean:
    	$(RM) $(objs)
    	$(RM) $(deps)
    	$(RM) $(target)
    
    install:
    	sudo cp $(target) /usr/bin/
    
    uninstall:
    	sudo $(RM) /usr/bin/$(target)
    
  • 多个.c对应生成多个可执行文件

    .PHONY: all clean install uninstall
    
    srcs := $(wildcard *.c)
    objs := $(patsubst %.c, %.o, $(srcs))
    bins := $(patsubst %.c, %.bin, $(srcs))
    deps := $(patsubst %.c, %.d, $(srcs))
    
    all: $(bins)
    
    -include $(deps)
    
    %.d: %.c
    	$(CC) -MM $^ > $@
    %.o: %.c
    	$(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS)
    %.bin: %.o
    	$(CC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS) $(LIBS)
    
    clean:
    	$(RM) $(objs) $(bins) $(deps)
    
  • 进入目录执行make

    make -C 目录
    
  • make目录下的所有文件夹,根据目录名称分别生成可执行文件

    # 外面的makefile:
    .PHONY: all clean
    
    dirs := $(shell find -type d)
    dirs := $(subst .,,$(dirs))
    dirs := $(subst /,,$(dirs))
    
    all:
    	for d in $(dirs);do make -C $$d;done; # $$d在makefile中使用shell变量
    
    clean:
    	for d in $(dirs);do make -C $$d clean;done; 
    
    # 各个目录里的makefile:
    .PHONY: all clean install uninstall
    
    target := $(shell pwd)
    target := $(notdir $(target))
    # srcs := $(shell ls *.c)
    srcs := $(wildcard *.c)
    # objs := $(srcs:.c=.o)
    objs := $(patsubst %.c, %.o, $(srcs))
    # deps := $(srcs:.c=.d)
    deps := $(patsubst %.c, %.d, $(srcs))
    
    all: $(target)
    
    -include $(deps)
    
    %.d: %.c
    	$(CC) -MM $^ > $@
    
    %.o: %.c
    	$(CC) -c -o $@ $<
    
    $(target): $(objs)
    	$(CC) -o $@ $^
    
    clean:
    #       $(RM) *.o
    	$(RM) $(objs)
    #       $(RM) *.d
    	$(RM) $(deps)
    	$(RM) $(target)
    
    install:
    	sudo cp $(target) /usr/bin/
    
    uninstall:
    	sudo $(RM) /usr/bin/$(target)
    
  • make指定makefile文件

    make -f 文件名
    
  • 强制完整的执行makefile 忽略文件修改时间

    make -B
    
  • 公共文件可以放在当前目录下生成静态库

    #lib.mk
    
    .PHONY: all clean
    target := mylib.a
    srcs := $(wildcard *.c)
    objs := $(patsubst %.c, %.o, $(srcs))
    deps := $(patsubst %.c, %.d, $(srcs))
    
    all:$(target)
    
    -include $(deps)
    
    %.d: %.c
    	$(CC) -MM $^ > $@
    
    %.o: %.c
    	$(CC) -c -o $@ $<
    
    $(target): $(objs)
    	$(AR) cr $@ $^
    
    clean:
    	$(RM) $(objs) $(deps) $(target)
    
    #def.mk
    
    LIBS += L../ -lmylib
    
    #当前目录下的makefile
    .PHONY: all clean
    
    dirs := $(shell find -type d)
    dirs := $(subst .,,$(dirs))
    dirs := $(subst /,,$(dirs))
    
    all:
    	make -f lib.mk
    	for d in $(dirs);do make -C $$d;done;
    
    clean:
    	make -f lib.mk clean;
    	for d in $(dirs);do make -C $$d clean;done;
    
    #每个目录下的makefile
    
    .PHONY: all clean install uninstall
    
    target := $(shell pwd)
    target := $(notdir $(target))
    # srcs := $(shell ls *.c)
    srcs := $(wildcard *.c)
    # objs := $(srcs:.c=.o)
    objs := $(patsubst %.c, %.o, $(srcs))
    # deps := $(srcs:.c=.d)
    deps := $(patsubst %.c, %.d, $(srcs))
    
    all: $(target)
    
    include ../def.mk
    -include $(deps)
    
    %.d: %.c
    	$(CC) -MM $^ > $@
    
    %.o: %.c
    	$(CC) -c -o $@ $<
    
    $(target): $(objs)
    	$(CC) -o $@ $^ $(LIBS)
    
    clean:
    #       $(RM) *.o
    	$(RM) $(objs)
    #       $(RM) *.d
    	$(RM) $(deps)
    	$(RM) $(target)
    
    install:
    	sudo cp $(target) /usr/bin/
    
    uninstall:
    	sudo $(RM) /usr/bin/$(target)
    
  • 更高级的makefile

  1. automake 最常见(GNU)

    ./configure
    make
    sudo make install
    
  2. cmake

    mkdir build
    cd build
    cmake ../
    make
    
  3. qmake

    qmake -project
    qmake
    make
    
posted @ 2018-06-04 22:45  ret  阅读(110)  评论(0)    收藏  举报