参考
http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
工程文件
来自C++ Primer的第9章
包括coordin.h file1.cpp file2.cpp
coordin.h
// coordin.h -- structure templates and function prototypes
// structure templates
#ifndef COORDIN_H_
#define COORDIN_H_
struct polar
{
double distance;
double angle;
};
struct rect
{
double x;
double y;
};
polar rect_to_polar(rect xypos);
void show_polar(polar dapos);
#endif
file1.cpp
#include<iostream>
#include"coordin.h"
using namespace std;
int main()
{
rect rplace;
polar pplace;
cout << "enter the x and y values: ";
while (cin >> rplace.x >> rplace.y)
{
pplace = rect_to_polar(rplace);
show_polar(pplace);
cout << "next two numbers (q to quit):";
}
cout << "Bye!\n" ;
return 0;
}
file2.cpp
#include <iostream>
#include <cmath>
#include "coordin.h"
polar rect_to_polar(rect xypos)
{
using namespace std;
polar answer;
answer.distance = sqrt(xypos.x * xypos.x + xypos.y * xypos.y);
answer.angle = atan2(xypos.y, xypos.x);
return answer;
}
void show_polar(polar dapos)
{
using namespace std;
const double Rad_to_deg = 57.29577951;
cout << "distance = " << dapos.distance;
cout << ", angle = " << dapos.angle * Rad_to_deg;
cout << " degrees\n";
}
这样的情况下,使用的g++命令是
g++ file1.cpp file2.cpp -o a.out
makefile 可以这样写:
coordin.o: file2.cpp file1.cpp
g++ file1.cpp file2.cpp -o coordin.o
clean:
-rm *.o
但是如果这样写的话,.h文件修改了是不会重新编译的。
于是我们引入下面的一个makefile:
CC=g++
CFLAGS=-I.
DEPS=coordin.h
OBJ=file1.o file2.o
%.o: %.cpp $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
target: $(OBJ)
$(CC) -o $@ $^ $(CFLAGS)
clean:
-rm *.o
-rm target
make之后有以下的输出:
g++ -c -o file1.o file1.cpp -I.
g++ -c -o file2.o file2.cpp -I.
g++ -o target file1.o file2.o -I.
解释
用到了一些变量
CC
代表用g++
来编译
CFLAGS
使用-I.
来表示在当前目录搜寻
DEPS
说明依赖文件是coordin.h
OBJ
是两个.o
文件
第一句命令:所有的.o
文件依赖于相应的.cpp
文件。在这里就像是for循环
一样展开,因为有两个.o
文件,所以会展开成两个命令。
其中$@
表示循环目标文件,在这里是循环.o
文件file1.o
和file2.o
。
$<
表示将$@
的.o
去掉,再加上.cpp
,在这里,就是将file1.o
去掉.o
,加上.cpp
,变成file1.cpp
。同理循环得到file2.cpp
,于是有以下转换:
%.o: %.cpp $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
<-->
g++ -c -o file1.o file1.cpp -I.
%.o: %.cpp $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
<-->
g++ -c -o file2.o file2.cpp -I.
然后还有一个@^
是代表所有的依赖。在这里所有的依赖就是OBJ=file1.o file2.o
,于是做简单的替换得到实际执行的命令:
target: $(OBJ)
$(CC) -o $@ $^ $(CFLAGS)
<-->
g++ -o target file1.o file2.o -I.