Makefile查漏补缺

1 、基本框架

Target:Dependence
        cmd
 

//test.c:

#include<iostream>



int main(void){



        std::cout<<"hello world"<<tsd::endl;

}

Makefile:

APP=myapp

COMPILER=g++



all : $(APP)





$(APP) : test.o

        $(COMPILER) -o $(APP) test.o



test.o : test.c

        $(COMPILER) -c test.c

命令:

make

./myapp

2、伪目标

.Phony:all

伪目标不是文件,但是为了防止防止make不执行此命令,可以用.Phony指定

3、自动变量
        自动变量都是以$开头,加上一些特殊的符号,表示特殊的变量

  1. $%、$<、$^、$?

     

    /**helloworld.c**/
    
    #include<stdio.h>
    
    int main()
    {
        foo("hello world\n");
    }

    /**foo.c**/
    
    #include<stdio.h>
    
    int foo()
    {
        printf("hello world\n");
    }
    #Makefile
    
    helloworld:helloworld.c foo.c
    	gcc -o $@ $^
    
    all:helloworld

    从上述例子中看出, $%表示目标、$^表示所有依赖

    修改makefile

    #Makefile
    
    helloworld:helloworld.c foo.c
    	gcc -o $@ $<
    
    all:helloworld

    可以看出$<表示第一个依赖

    修改foo.c,修改Makefile:
    #Makefile
    
    helloworld:helloworld.c foo.c
    	@echo $?
    	gcc -o $@ $^
    
    all:helloworld
    /**foo.c**/
    
    #include<stdio.h>
    
    int foo()
    {
        printf("hello world\n");//test
    }

    可以看到$?表示更新了的依赖项 

4、常见语法

  1. 条件语句
    ifeq (a,b)
            statement
    endif
    如果a和b相同,则执行statement
    eg:
    #Makefile
    Version=1.0
    ifeq ($(Version),1.0)
    	NOTE=V1.0
    endif
    
    helloworld:helloworld.c foo.c
    	@echo $(NOTE)
    	gcc -o $@ $^
    
    all:helloworld

  2. 循环语句
    $(foreach n ,list,cmd)
    从list分别取出成员n,然后执行cmd。
    eg:
    #Makefile
    
    helloworld:helloworld.c foo.c
    	@echo $(foreach n, $^,$(n))
    	gcc -o $@ $^
    
    all:helloworld

5、常用函数

  1. wildcard
    $(wildcard pattern)
    返回符合模式的文件
    eg:
    #Makefile
    
    SRC := $(wildcard *.c) 
    
    helloworld:$(SRC)
    	@echo $^
    	gcc -o $@ $^
    
    all:helloworld

  2. patsubst和subst
    $(subst from,to,text)
    $(patsubst from,to,text)
    patsubst和subst都可以进行替换,不同的是patsubst可以将符合模式的进行替换,而subst只能进行明文替换
     
    #Makefile
    
    SRC := $(wildcard *.c) 
    OBJ := $(patsubst %.c,%.o,$(SRC)) 
    
    helloworld:$(OBJ)
    	@echo $^
    	gcc -o $@ $^
    
    all:helloworld

  3. filter和filter-out
    filter表示过滤符合pattern的项,filter-out表示过滤出符合pattern的项的剩余的项
    eg:过滤如下文件列表的test.c
    #Makefile
    
    SRC := $(wildcard *.c)
    FILTER_SRC := $(filter-out test%,$(SRC)) 
    OBJ := $(patsubst %.c,%.o,$(FILTER_SRC)) 
    
    .Phony : all clean
    
    helloworld:$(OBJ)
    	@echo $(SRC)
    	@echo $^
    	gcc -o $@ $^
    
    all:helloworld
    
    clean:
    	rm helloworld helloworld.o foo.o -f

6、常用代码框架管理

        1.代码文件替换

代码结构:project中的代码需要替换主线中的代码,在这个demo中,只需要编译主线中的helloworld.c,project分支中的foo.c和bar.c,不编译主线的foo.c和bar.c

 

/**helloworld.c**/

#include<stdio.h>

extern int foo();
extern int bar();

int main()
{
    foo();
	bar();
}
/**foo.c**/

#include<stdio.h>

int bar()
{
    printf("hello bar\n");//test
}
/**foo.c**/

#include<stdio.h>

int bar()
{
    printf("hello bar\n");//test
}
/**project/foo.c**/

#include<stdio.h>

int bar()
{
    printf("project hello bar\n");//test
}
/**project/foo.c**/

#include<stdio.h>

int foo()
{
    printf("project hello foo\n");//test
}
#Makefile

TARGET := helloworld
SRC := $(wildcard *.c)
PROJECT_SRC := $(wildcard ./project/*.c)
PROJECT_BASENAME := $(notdir $(PROJECT_SRC))
FILTER_SRC := $(filter-out %$(PROJECT_BASENAME),$(SRC)) 
ALL_SRC := $(FILTER_SRC)
ALL_SRC += $(PROJECT_SRC)
OBJ := $(patsubst %.c,%.o,$(ALL_SRC)) 

.Phony : all clean

helloworld:$(OBJ)
	@echo $(SRC)
	@echo $(PROJECT_SRC)
	@echo $(PROJECT_BASENAME)
	@echo $^
	gcc -o $@ $^

all:helloworld

clean:
	rm $(TARGET) $(OBJ) -f

使用如上makefile,关键在于两个函数,notdir函数取出路径文件中的文件名,filter-out过滤主线中包含此文件的主线文件,然后再加上分支代码,就组成了最后的代码机构。

        2.对每个文件都进行一次编译

eg:如下面helloworld.c和helloworld1.c都需要编译成可执行文件,

/**helloworld.c**/

#include<stdio.h>

int main()
{
    printf("helloworld\n");
}
/**helloworld1.c**/

#include<stdio.h>


int main()
{
    printf("helloworld1\n");
}
#Makefile


SRC := $(wildcard *.c)
OBJ := $(patsubst %.c,%.o,$(SRC)) 
TARGET := $(patsubst %.o,%,$(OBJ)) 

.Phony : all clean


all:$(TARGET)

%:%.o
	gcc -o $@ $^
clean:
	rm $(TARGET) $(OBJ) -f

这里主要用到了通配符%做目标的做法,要使用此语法,一定需要依赖项中包含了匹配的成员。

 当然,还有第二种做法
 

#Makefile


SRC := $(wildcard *.c)
OBJ := $(patsubst %.c,%.o,$(SRC)) 
TARGET := $(patsubst %.o,%,$(OBJ)) 

.Phony : all clean


all:$(TARGET)

$(TARGET):%:%.o
	gcc -o $@ $^
clean:
	rm $(TARGET) $(OBJ) -f

 可以看到虽然结果一样,但是执行命令不一样,使用$(TARGET):%:%.o后,会先生成.o文件,而使用%:%.o则会直接生成可执行文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值