Makefile学习笔记

前言


由于过去一直在做前端,虽然早就知道有makefile这种东西,但是一直都没去学。因为有ide啊,为什么要手动去搞呢。。。不过现在有用了,还是要看一看。
之前以为makefile就是用来做编译连接之类的东西的,但实际并不是这样,造成这种错误认知的原因一方面是看过的makefile都是做这个的,另一方面也是网上的教程基本都是用编译连接来做例子。确实,makefile最常用的就是用来构建项目,但实际上,正如它的名字一样,是用来制作文件的,所以不管是用编译链接生成库文件或者可执行文件,还是用别的方法或脚本来生成文件,都可以使用make指令+makefile的形式。至于用makefile来构建项目,那就是另一个问题了。

make与makefile


make这个指令,通常都是配合Makefile文件使用的。执行make的时候,会自动寻找当前目录名为Makefile的文件,然后根据Makefile中定义的规则来生成所需要的文件。当然,你也可以自定义别的文件名,在执行make指令的时候添加参数就可以做到:

$ make -f other_make
#或者
$ make --file=other_make

Makefile文件格式


Makefile文件的内容由一系列的规则组成,规则的形式如下:

target : prerequisites
[tab]commands
  • target: 构建的目标。必须,随便自己喜好定义名字就行了。
  • prerequisites:前置条件。前置条件是可以省略的,如果有前置条件,那么make的时候就会先去构建前置条件,等前置条件充分以后再去构建target。
  • tab:第二行必须要以一个tab符号起首。
  • commands:命令。命令是由一行或多行shell指令组成的,其目的基本都是生成目标文件。当然,你也可以打一行日志,没有强制的要求。
    下面来写一个简单的makefile:
.PHONY: b.txt c.txt
a: b.txt c.txt
    cat b.txt c.txt > a.txt
b.txt:
    @#create b.txt file
    echo "this is b.txt" > b.txt
c.txt:
    #create c.txt file
    echo "this is c.txt" > c.txt
clean:
    @rm *.txt                   

.PHONY是系统内置的,在上面的指令中,b.txt和c.txt是a的前置条件,但是如果make发现已经存在了一个和target名称同样的文件名(比如b.txt),那么就不会去执行b.txt对应的指令了,为了解决这种问题,就可以使用.PHONY这个命令。target可以在make的时候指定,比如make clean,如果不指定,默认只执行第一个。

使用makefile进行编译链接


了解了上面的东西,其实剩下需要学习的就不是属于make的知识,而是编译连接的知识了。其实makefile规则还有其他的,比如循环,函数之类的,不过这些后面需要的时候再看就行了,这篇文章主要也只是介绍一下大概makefile是个什么东西,用makefile构建工程又是一个什么概念,仅此而已,如果要学习更多的,还是要多看些资料多练习。
学习这个的时候写了几个简单的样例代码,首先看一下目录结构吧:
这里写图片描述
接下来是各个.h 和.cpp文件:

//hello.h
#include <cstdio>

int a = 123;
void runIt() {
    printf("run it\n");
};

int add(int a, int b);
//hello.cpp
#include <hello.h>
int add(int a,int b) {
    return a + b;
}
int main() {
    printf("hello world!\n");
    runIt();
    printf("a:%d\n",a);
    return 0;
}
//st.h
#include <cstdio>
void static_lib();
//st.cpp
#include "st.h"
void static_lib() {
    printf("static lib function.\n");
}
//run.cpp
#include <hello.h>
#include "st.h"

int main() {
    printf("this is test word\n");
    static_lib();
    int res = add(1,2);
    printf("add resullt : %d\n", res);
    return 0;
}

最后是makefile文件:

program:
    g++ -I. -I./hfile -fPIC -shared -std=c++11 -o libhello.so hello.cpp
    g++ -c hfile/st.cpp
    ar cqs libst.a st.o
    g++ -I. -I./hfile -L. -L./hfile -std=c++11 run.cpp -o run -lhello -lst
clean:
    rm -f *.out *.a
    rm -f *.so *.o

假定我们最终需要运行的是run.cpp,可以发现,这个文件依赖于hello.h 和 st.h,hello.cpp与run.cpp在同一目录,而其他文件在不同目录。首先将hello.cpp编译并生成动态链接库,然后编译st.cpp生成静态链接库。最后编译run.cpp,并链接前面生成的两个库,生成可执行文件run。
g++指令的各个参数:
- -I(大写i):指定头文件所在目录,可以使用相对目录。
- -L:表示要链接的库的所在目录。
- -l(小写L):指定需要链接的库的名称。
- -shared :指定生成动态连接库。
- -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时事通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码共享的目的。
- -std=c++11:使用C++11标准编译。
- -o:指定输出文件。
- -c:编译,生成目标文件。
- ar cqs:生成静态链接库。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值