makefile的简单例子

示例

树形结构:

1
2
3
4
5
6
7
8
9
ubuntu@VM-12-11-ubuntu:~/c++/makefile$ tree
.
├── factorial.cpp
├── functions.h
├── main.cpp
├── Makefile
└── printHello.cpp

0 directories, 5 files

functions.h

1
2
3
4
5
6
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#include <iostream>
void printHello();
int factorial(int n);
#endif

factorial.cpp

1
2
3
4
5
6
7
8
9
#include "functions.h"

int factorial(int n) {
  if (n == 1) {
    return 1;
  } else {
    return n * factorial(n - 1);
  }
}

main.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include "functions.h"

using namespace std;

int main() {
    printHello();

    cout << "This is main:" << endl;
    cout << "The factorial of 5 is:" << factorial(5) << endl;
}

printHello.cpp

1
2
3
4
5
6
7
8
#include "functions.h"

using namespace std;

void printHello() {
    int i;
    cout << "Hello World!" << endl;
}

版本 1

1
2
3
## VERSION 1
hello: main.cpp printHello.cpp factorial.cpp
	g++ -o hello main.cpp printHello.cpp factorial.cpp

第一个版本比较简单:

  • hello的生成依赖于:main.cpp printHello.cpp factorial.cpp
  • 通过:g++ -o hello main.cpp printHello.cpp factorial.cpp 来生成hello这个目标

版本 2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
CXX = g++
TARGET = hello
OBJ = main.o printHello.o factorial.o

$(TARGET) : $(OBJ)
	$(CXX) -o $(TARGET) $(OBJ)

main.o : main.cpp
	$(CXX) -c main.cpp

printHello.o : printHello.cpp
	$(CXX) -c printHello.cpp

factorial.o : factorial.cpp
	$(CXX) -c factorial.cpp

首先定义了3个变量,CXX、TARGET、OBJ;然后再说明定义的TARGET变量依赖于OBJ这个变量,如果OBJ变量更新的化,使用命令($(CXX) -o $(TARGET) $(OBJ))重新生成CXX。而OBJ变量依赖于main.o printHello.o factorial.o这三个文件,然后make会根据后面的解释生成这三个文件。

make生成:

1
2
3
4
5
ubuntu@VM-12-11-ubuntu:~/c++/makefile$ make
g++ -c main.cpp
g++ -c printHello.cpp
g++ -c factorial.cpp
g++ -o hello main.o printHello.o factorial.o

版本 3

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
CXX = g++
TARGET = hello
OBJ = main.o printHello.o factorial.o

# 增加了一条编译选项
CXXFLAGS = -c -Wall

$(TARGET) : ${OBJ}
	${CXX} -o $@ $^

%.o : %.cpp
	$(CXX) $(CXXFLAGS) $< -o $@

.PHONY : clear
clear : 
	rm -f *.o $(TARGET)

其中,$@ 代表的就是 $(TARGET)$^ 代表的就是 ${OBJ}

1
2
$(TARGET) : ${OBJ}
	${CXX} -o $@ $^

如下的命令是将所以的.cpp文件生成对应的.o文件,以$(CXX) $(CXXFLAGS) $< -o $@命令的方式生成。

1
2
%.o : %.cpp
	$(CXX) $(CXXFLAGS) $< -o $@

这条命令是删除对应*.o文件和$(TARGET)文件

1
2
3
.PHONY : clear
clear : 
	rm -f *.o $(TARGET)

其中.PHONY : clear用来避免歧义

可以通过 make clear来执行:

1
2
ubuntu@VM-12-11-ubuntu:~/c++/makefile$ make clear
rm -f *.o hello

版本 4

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
CXX = g++
TARGET = hello
SRC = $(wildcard *.cpp)
OBJ = $(patsubst %.cpp, %.o, ${SRC})

CXXFLAGS = -c -Wall

$(TARGET) : ${OBJ}
	${CXX} -o $@ $^

%.o : %.cpp
	$(CXX) $(CXXFLAGS) $< -o $@

.PHONY : clear
clear : 
	rm -f *.o $(TARGET)

SRC = $(wildcard *.cpp),将所有当前目录的.cpp 都放到SRC变量中。

OBJ = $(patsubst %.cpp, %.o, ${SRC}),将SRC所有的.cpp文件 替换为.o文件

0%