C++makefile入门

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__
class Student{
private:
	char name[20];
	int age;
	bool sex;
public:
	void Init(char* name,int age,bool sex);
	void read();
	void write();

};
#endif

student.cpp

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include"student.h"
#include<cstring>
using namespace 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"
using namespace std;
int main(){
	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(打印后面字符 做提示用)
发布了27 篇原创文章 · 获赞 4 · 访问量 1335

猜你喜欢

转载自blog.csdn.net/weixin_45639955/article/details/104311039