C++ Makefile教学

本文介绍了Makefile在大型软件项目中的作用,包括其作为编译工具的基础要素,如目标、依赖和命令。讲解了如何编写基本的Makefile,使用变量和内置函数,以及如何利用wildcard和patsubst进行文件匹配和替换,以提升编译效率。
摘要由CSDN通过智能技术生成

Makefile是什么?

*学makefile之前需要复习一下编译过程

在大型软件项目设计中,我们不再像编译简单的C++程序一样包含头文件和源文件就直接开始编译。而是,需要制定规则去限制哪些文件需要怎么编译和怎么去链接。make是一种编译工具,makefile文件一旦确定了之后使得我们的编译过程自动化,提高软件开发效率。

大多数IDE都有自己的make工具,比如:Visual C++的nmake,QT Creator的qmake以及非常流行的CMake编译工具。

makefile的基本要素

  • 目标:要生成的目标文件(可执行文件或者库)
  • 依赖:目标通过哪些文件去生成
  • 命令:通过执行命令由依赖文件生成目标文件

makefile规则如下:

目标 依赖

TAB(*注意必须是tab键,不能是空格) 命令;

下面通过具体的例子来初识makefile:

当前目录下有main.cpp function1.cpp function2.cpp sum.cpp以及一个head.h

 下面是各个源文件和头文件的内容:

//head.h

void function1();
void function2();
int sum(int n);

//function1.cpp

#include <iostream>
using namespace std;

void function1(){
    cout<<"this is function1\n";
}

//function2.cpp

#include <iostream>
using namespace std;

void function2(){
    cout<<"this is function2\n";
}

//sum.cpp

#include <iostream>
using namespace std;

int sum(int n){
    int sum=0; 
    for(int i=0;i<n;i++){
        sum+=i;
    }
    return sum;
}


//main.cpp

#include <iostream>
#include "head.h"

int main(void){
    function1();
    function2();
    int n=0;
    std::cin>>n
    int result=sum(n);
    std::cout<<result<<std::endl;
    return 0;
}

最简单的makefile

vim makefile

        makefile的内容: 

main: main.cpp function1.cpp function2.cpp sum.cpp
    g++ -o main main.cpp function1.cpp function2.cpp sum.cpp

        这是一个最简单的makefile,包括了目标、依赖和命令三要素。

make

        之后在命令行输入make命令就直接按照我们制定的makefile规则编译生成可执行文件

        先再次分解一下g++ -o main main.cpp function.cpp function2.cpp sum.cpp

main: main.o function1.o function2.o sum.o
    g++ -o main main.o function1.o function2.o sum.o

main.o: main.c
    g++ -c main.c -I./

function1.o: function1.cpp
    g++ -c function1.cpp

function2.o: function2.cpp
    g++ -c function2.cpp

sum.o: sum.cpp
    g++ -c sum.cpp

不要慌,只是把一步编译到位模式分解了(没懂看C++编译过程)。 

进阶makefile:

在实际应用中我们像上一步一样写makefile还不如不写,当我们有数十个cpp和库依赖的时候makefile有什么作用呢?

makefile中的变量 :

  • 普通变量
  • 自带变量
  • 自动变量

普通变量:

简单来说:直接用"name1=name2"去定义 ,用$(name1)去使用。再来看看之前的makefile文件:

main: main.cpp function1.cpp function2.cpp sum.cpp
    g++ -o main main.cpp function1.cpp function2.cpp sum.cpp

通过普通变量运用:

target = main
objects = main.cpp function1.cpp function2.cpp sum.cpp
//以上都是变量部分,以下是我们对原来的makefile更改
$(target): $(objects)
    g++ -c $(target) $(objects)

自带变量:

        CC:编译器名称(g++\clang)

        CPPFLAGS:预处理选项  -I

        CFLAGS:编译器选项  -Wall -g(gdb调试) -c

        LDFLAGS:链接器选项 -L -l

再改进一次makefile:

target = main
objects = main.cpp function1.cpp function2.cpp sum.cpp
//以上都是变量部分,以下是我们对原来的makefile更改
$(target): $(objects)
CC = g++

    $(CC) -c $(target) $(objects)

自动变量:

$@:表示规则中的目标

$<:表示规则中的第一个条件

$^:表示规则中的所有条件组成一个列表,如果有重复项消除重复项

%:模式规则---在规则的目标定义中包含%,表示一个或多个。

先看一下之前分解的makefile:

main: main.o function1.o function2.o sum.o
    g++ -o main main.o function1.o function2.o sum.o

main.o: main.c
    g++ -c main.c -I./

function1.o: function1.cpp
    g++ -c function1.cpp

function2.o: function2.cpp
    g++ -c function2.cpp

sum.o: sum.cpp
    g++ -c sum.cpp

再利用普通变量和自带变量改进:

target = main
objects = main.o function1.o function2.o sum.o
CC = g++
CPPFLAGS = I./

$(target): $(objects)
    $(CC) -o $(target) $(objects)

main.o: main.cpp
    $(CC) -c main.cpp $(CPPFLAGS)

function1.o: function1.cpp
    $(CC) -c function1.cpp

function2.o: function2.cpp
    $(CC) -c function2.cpp

sum.o: sum.cpp
    $(CC) -c sum.cpp

再通过自动变量去改进:

target = main
objects = main.o function1.o function2.o sum.o
CC = g++
CPPFLAGS = I./

$(target): $(objects)
    $(CC) -o $@ $^

%.o: %.cpp
    $(CC) -c $< $(CPPFLAGS)
//main.o: main.cpp
//    $(CC) -c $< $(CPPFLAGS)

//function1.o: function1.cpp
//    $(CC) -c $<

//function2.o: function2.cpp
//    $(CC) -c $<

//sum.o: sum.cpp
//    $(CC) -c $<


//实际上makefile中的注释用#,不是//

最终:

target = main
objects = main.o function1.o function2.o sum.o
CC = g++
CPPFLAGS = I./

$(target): $(objects)
    $(CC) -o $@ $^

%.o: %.cpp
    $(CC) -c $< $(CPPFLAGS)

makefile中的函数

函数太多,主要介绍两个函数: 

  • wildcard--查找指定目录下的指定类型文件

       例如:src=$(wildcard*.cpp)-->查找当前目录下的所有后缀为cpp的文件赋值给变量src

  • patsubt---匹配替换

        例如:objects=$(patsubt%.cpp,%.o,$(src))-->将把src变量里的所有.cpp文件替换成.o

再次改进makefile:

target = main
src = $(wildcard *.cpp)
objects = $(patsubt %.cpp,%.o,$(src))
CC = g++
CPPFLAGS = I./

$(target): $(objects)
    $(CC) -o $@ $^

%.o: %.cpp
    $(CC) -c $< $(CPPFLAGS)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值