1.Makefile基本语法与执行
1.1实例
all:test.o set.o set1.o #这样就可以执行全部了
test.o:test.c #如果依赖文件找不到直接报错
g++ test.c-o test.o
#但是只执行第一个
set.o:set.c
g++ set.c-o set.o
set1.o:set1.c
g++ set1.c-o set1.o
clean:
rm-f test.o
rm-f set.o
rm-f set1.o
编译: make
清空: make clean
1.2构成
Makefile主要由多条规则构成,每条规则由三部分构成:目标(target)、依赖(prerequiries)和命令(command)。
目标:最终要生成什么东西
依赖:用那些东西来生成
命令:执行的命令(每个命令行前面必须是一个Tab字符,即命令行第一个字符是Tab。这是不小心容易出错的地方。)
格式
目标(target): 依赖(prerequiries)...
命令(command)
2 Makefile多文件编译
2.1代码
student.h
#ifndef __STUDENT_H__#define __STUDENT_H__classStudent{private:char name[20];int age;bool sex;public:voidInit(char* name,int age,bool sex);voidread();voidwrite();};#endif
student.cpp
#include<iostream>#include<cstdio>#include<cstdlib>#include"student.h"#include<cstring>usingnamespace std;void Student::Init(char* name,int age,bool sex){strcpy(this->name,name);this->age=age;this->sex=sex;}void Student::read(){
cin>>name>>age>>sex;}void Student::write(){
cout<<"姓名:"<<name<<endl<<"年龄:"<<age<<endl<<"性别:"<<sex<<endl;}
student.test
#include<iostream>#include<cstdio>#include"student.h"usingnamespace std;intmain(){char name[20]={"lvke"};int age=18;bool sex=1;
Student student;
student.Init(name,age,sex);
student.write();// student.read();int n=0;
cin>>n;#ifdef VAR_ARRAY
Student arr[n];for(int i=0;i<n;i++){
arr[i].read();}for( i=0;i<n;i++){
arr[i].write();}#endif
Student* p=new Student[n];for(int i=0;i<n;++i){
p[i].read();}for(int k=0;k<n;++k){
p[k].write();}delete[] p;
p=NULL;}
2.2 makefile
Student_Test:student_test.o student.o
g++-o Student_Test student_test.o student.o
student_test.o:student_test.cpp student.h
g++-c student_test.cpp
student.o:student.cpp student.h
g++-c student.cpp
test:./Student_Test
clean:
rm-f Student_Test student_test.o student.o
2.3结果
3使用变量简化makefile
3.1概念
每次增加新的文件,需要在makefile的很多地方增加依赖,容易导致遗漏。可以使用变量可以简化,避免这种出错的可能。
变量定义:变量 = 字符串
变量使用:$(变量名)
3.2示例
#变量定义:变量= 字符串
OBJS= student_test.o student.o
Student_Test:$(OBJS)#变量使用:$(变量名)
g++-o Student_Test $(OBJS)
student_test.o:student_test.cpp student.h
g++-c student_test.cpp
student.o:student.cpp student.h
g++-c student.cpp
test:./Student_Test
clean:
rm-f Student_Test $(OBJS)
4命令自动推导
4.1概念
make提供一种简化写法,可以自动推导出该规则
文件名.o:文件名.cpp 头文件
g++-c 文件名.cpp
可以推导成下面的(这种简化规则称为隐含规则,非简化规则成为具体规则。)
文件名.o:头文件
4.2示例
OBJS= student_test.o student.o
Student_Test:$(OBJS)
g++-o Student_Test $(OBJS)
student_test.o: student.h
student.o: student.h#student_test.o:student_test.cpp student.h# g++ -c student_test.cpp#student.o:student.cpp student.h# g++ -c student.cpp
test:./Student_Test
clean:
rm-f Student_Test $(OBJS)
如果
4.3优化
通常,规则按照目标进行分组。规则也可以按照依赖分组。例如,例子中student.o和studentTest.o都依赖String.h。那么,可以这两个合并到一个规则中。
OBJS= student_test.o student.o
Student_Test:$(OBJS)
g++-o Student_Test $(OBJS)
student_test.o student.o: student.h#student.o: student.h#student_test.o:student_test.cpp student.h# g++ -c student_test.cpp#student.o:student.cpp student.h# g++ -c student.cpp
test:./Student_Test
clean:
rm-f Student_Test $(OBJS)
5. 假想目标
5.1问题:
例如例子中的clean,只是执行清理动作。如果,makefile同级目录存在与假象目标同名的文件(例如:clean),那么会导致命令不会被执行。
5.2解决方法
表达动作的目标称为假想目标。所以需要把目标显示声明为假想目标。因为通常规则会生成或者更新与目标的同名文件,但是假想目标不生成文件,只是作为几个命令组成特殊规则的名称。
5.3实例
OBJS= student_test.o student.o.PHONY: clean test
Student_Test:$(OBJS)
g++-o Student_Test $(OBJS)
student_test.o student.o: student.h
test:./Student_Test
clean:
rm-f Student_Test $(OBJS)
5.4常用假想目标
6. 通配符与变量
6.1. 通配符
通配符主要用于匹配文件名,makefile中使用%作为通配符。从匹配目标格式的目标名中依据通配符抽取部分字符串,再按照抽取字符串分配到每一个依赖格式中产生依赖名。例如,使用%.o:%.cpp。
6.2自动变量
自动变量是在规则每次执行时都基于目标和依赖产生新值的变量。下面是常用的自动变量。
No. | 自动变量 | 含义 |
---|---|---|
1 | $< | 表示第一个匹配的依赖 |
2 | $@ | 表示目标 |
3 | $^ | 所有依赖 |
6.3. 预定义变量
预定义变量是makefile已经**定义好的变量,**用户可以在makefile文件中改变变量的值。
程序名变量
变量 | 程序 | 默认 |
---|---|---|
CC | C语言编译程序 | cc |
CXX | C++编译程序 | g++ |
CPP | 带有标准输出的C语言预处理程序 | $(CC) -E |
程序运行参数的变量:两个都为空
变量 | 程序参数 |
---|---|
CFLAGS | 用于C编译器的额外标志 |
CXXFLAGS | 用于C++编译器的额外标志 |
6.4变量值
VAL=hello
test:
echo $(VAL)
echo $(CXX)
echo $(CC)
echo $(CXXFLAGS)
echo $(CFLAGS)
6.5代码
OBJS= student_test.o student.o.PHONY: clean test
Student_Test:$(OBJS)# g++ -o Student_Test $(OBJS)
$(CXX) $(OBJS)-o $@#student.o: student.h#student_test.o:student_test.cpp student.h# g++ -c student_test.cpp#student.o:student.cpp student.h# g++ -c student.cpp
$(OBJS):%.o:%.cpp student.h
$(CXX)-c $(CXXFLAGS) $<-o $@
test:./Student_Test
clean:
rm-f Student_Test $(OBJS)
7. 其他
注释#
换行\
回显命令@echo(打印后面字符 做提示用)