makefile 入门第一课
makefile入门第一课
百度百科makefile词条:
一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中。
makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,
甚至于进行更复杂的功能操作,因为 makefile 就像一个 Shell 脚本一样,其中也可以执行操作系统的命令。
简单了解 g++
g++ 是 GNU 的 C++ 编译器
用 g++ 编译单个文件生成可执行文件
在 vim 中编写下列代码,保存在 main.cpp 文件中:
// in main.cpp
#include <iostream>
using namespace std;
int main()
{
cout << "hello, g++!" << endl;
return 0;
}
在该文件夹下,执行下列语句编译该文件为执行文件:
g++ main.cpp -o hello
这句命令是编译 main.cpp 文件, 并将其输出文件命名为 hello。
此时,可以发现,当前文件夹生成了可执行文件 hello,输入下列语句执行该文件:
./hello
此时,shell 输出 hello, g++!。
用 g++ 通过编译中间文件生成可执行文件
可执行文件的生成一般包括编译和链接,首先编译生成中间目标文件,然后将各个目标文件链接成可执行文件:
用 vim 编写下列代码,分别保存在不同的文件下:
- hello.h
#ifndef SRC_HELLO_H
#define SRC_HELLO_H
class hello
{
public:
hello();
~hello();
};
#endif // SRC_HELLO_H
- hello.cpp
#include "hello.h"
#include <iostream>
using std::cout;
using std::endl;
hello::hello()
{
cout << "hello, object!" << endl;
}
hello::~hello()
{
cout << "goodbye, obejct!" << endl;
}
- main.cpp
#include <iostream>
#include "hello.h"
using namespace std;
int main()
{
hello h;
return 0;
}
在当前路径输入下列语句,编译 hello.cpp,生成中间目标文件 hello.o:
g++ -c hello.cpp此时,当前目录生成 hello.o 文件。
在当前路径输入下列语句,编译 main.cpp,生成中间目标文件 main.o:
g++ -c main.cpp此时,当前目录生成 main.o 文件。
在当前路径输入下列语句,链接 hello.o 和 main.o,生成可执行文件 hello :
g++ main.o hello.o -o hello此时,当前文件夹生成可执行文件 hello。
在当前路径输入下列语句,执行 hello 程序:
./hello此时控制台输出为:
hello, object!
goodbye, obejct!
makefile 编译文件
makefile 的基本结构
makefile 由下面的基本结构组成:
target … : prerequisites …
recipe
…
…
taget 通常是待生成的可执行文件目标文件,也可以是标签,
prerequisites 是用来生成待生成文件的文件,即待生成文件所依赖的文件,
recipe 是 make 命令需要执行的动作(action), 通常是不止一条的 shell 命令。
makefile 编译单个文件生成可执行文件
在当前路径下,创建下面的 .cpp 文件:
// in main.cpp
#include <iostream>
using namespace std;
int main()
{
cout << "hello, makefile!" << endl;
return 0;
}
用 vim 创建文件名为 makefile 的文件:
# in makefile
#可执行文件 hello 由 main.cpp 编译得到
hello: main.cpp
# 打印一句话
echo "Begin to compile..."
# 编译 main.cpp 生成可执行文件 hello 的命令行
g++ main.cpp -o hello
# 打印一句话
echo "Has been Compiled..."
在当前路径下,输入并执行 make 命令,控制台输出:
Begin to compile...
Has been compiled...
此时,当前路径下生成可执行文件 hello ,执行 hello 文件:
./hello
此时,控制台输出:
hello, makefile!
makefile 编译中间文件并链接为可执行文件
在当前路径下,创建下面的 .cpp 文件和 .h 文件:
- hello.h
#ifndef SRC_HELLO_H
#define SRC_HELLO_H
class hello
{
public:
hello();
~hello();
};
#endif // SRC_HELLO_H
- hello.cpp
#include "hello.h"
#include <iostream>
using std::cout;
using std::endl;
hello::hello()
{
cout << "hello, makefile!" << endl;
}
hello::~hello()
{
cout << "goodbye, makefile!" << endl;
}
- main.cpp
#include <iostream>
#include "hello.h"
using namespace std;
int main()
{
hello h;
return 0;
}
用 vim 创建文件名为 makefile 的文件:
#可执行文件 hello 由中间目标文件 main.o 和 hello.o 链接得到
hello: main.o hello.o
# 打印一句话
echo "Begin to link main.o and hello.o..."
# 链接 main.o 和 hello.o 生成可执行文件 hello 的命令行
g++ main.o hello.o -o hello
# 打印一句话
echo "main.o and hello.o have been linked..."
#中间目标文件 hello.o 由 hello.cpp 编译得到
hello.o: hello.cpp
# 打印一句话
echo "Begin to compile hello.o..."
# 编译 hello.cpp 生成中间目标文件 hello.o
g++ -c hello.cpp
# 打印一句话
echo "hello.o has been compiled..."
main.o: main.cpp
# 打印一句话
echo "Begin to compile main.o..."
# 编译 main.cpp 生成中间目标文件 main.o
g++ -c main.cpp
# 打印一句话
echo "main.o has been compiled..."
在当前路径下,输入并执行 make 命令,控制台输出:
Begin to compile main.o...
main.o has been compiled...
Begin to compile hello.o...
hello.o has been compiled...
Begin to link main.o and hello.o...
main.o and hello.o have been linked...
此时,当前路径下生成中间目标文件 hello.o, main.o 和可执行文件 hello ,执行 hello 文件:
./hello
此时,控制台输出:
hello, makefile!
goodbye, makefile!
makefile 删除编译过程中产生的中间目标文件
在上一 part 的 makefile 文件末尾加上 clean 标签及相关清理中间目标文件的,命令行,就可以在生成最终文件后自动删除相关中间文件:
clean:
rm -f main.o hello.o
则原文件变为:
#可执行文件 hello 由中间目标文件 main.o 和 hello.o 链接得到
hello: main.o hello.o
# 打印一句话
echo "Begin to link main.o and hello.o..."
# 链接 main.o 和 hello.o 生成可执行文件 hello 的命令行
g++ main.o hello.o -o hello
# 打印一句话
echo "main.o and hello.o has been linked..."
#中间目标文件 hello.o 由 hello.cpp 编译得到
hello.o: hello.cpp
# 打印一句话
echo "Begin to compile hello.o..."
# 编译 hello.cpp 生成中间目标文件 hello.o
g++ -c hello.cpp
# 打印一句话
echo "hello.o has been compiled..."
main.o: main.cpp
# 打印一句话
echo "Begin to compile main.o..."
# 编译 main.cpp 生成中间目标文件 main.o
g++ -c main.cpp
# 打印一句话
echo "main.o has been compiled..."
# 清理中间目标文件
clean:
rm -f main.o hello.o
执行 make 命令后,显式执行 make clean。此时当前路径下只有可执行文件 hello,而没有相关中间目标文件。
后记
本文主要是为从零开始学习 makefile 抛砖引玉, 相关内容尽量简单处理,详细介绍,让新手可以跟着一步一步的操作。
因此,本文可能对有一定基础的童鞋来说有一点冗长。见谅。
另外,点击下列参考文献的名称就可以跳转到相关下载页面。相关细节,参考文献中有具体的介绍。
参考文献
makefile 入门第一课的更多相关文章
- Asp.Net Web API 2(入门)第一课
Asp.Net Web API 2(入门)第一课 前言 Http不仅仅服务于Web Pages.它也是一个创建展示服务和数据的API的强大平台.Http是简单的.灵活的.无处不在的.你能想象到几乎 ...
- emacs 入门第一课:Emacs里的基本概念
Table of Contents 无聊的开场白 buffer(缓冲区) window(窗口)与frame Emacs的mode Emacs Lisp 函数function.命令command.键绑定 ...
- Android入门第一课之Java基础
通知:由于本周六场地申请没通过,所以本周的培训临时取消. 今天给大家带来的是Android入门的第一课,由于教室申请的不确定性,因此,每次培训的内容都会在博客先提前释放出来.首先Android的APP ...
- Docker入门 第一课 --.Net Core 使用Docker全程记录
微服务架构无疑是当前最火热的开发架构,而Docker作为微服务架构的首选工具,是我们必须要了解掌握的. 我通过一天的时间,网上查文档,了解基础概念,安装Docker,试验Docker命令,通过Dock ...
- Kotlin入门第一课:从对比Java开始
1. 介绍 今年初,甲骨文再次对谷歌所谓的安卓侵权使用Java提起诉讼,要求后者赔偿高达90亿美元.随后便传出谷歌因此计划将主力语言切换到苹果主导的Swift,不过这事后来没了跟进. 但谷歌在这两天的 ...
- Spring入门第一课:Spring基础与配置Bean
1.入门 Spring是简化java开发的一个框架,其中IoC和AOP是Spring的两个重要核心.由于Spring是非侵入性的,通过Ioc容器来管理bean的生命周期,还整合了许多其他的优秀框架,所 ...
- JavaScrip 入门第一课
一.代码引入的三种方式 1.直接在head中书写 在head标签里面可以写,在body标签里面也可以写,放到head标签里面和放到body标签里面到底有什么区别,我们后续在讲~ <head> ...
- python 语言学入门第一课必看:编码规范
命名 module_name, package_name, ClassName, method_name, ExceptionName, function_name, GLOBAL_VAR_NAME, ...
- 1、C#入门第一课
C# 读作C Sharp,所以程序文件的扩展名为.cs 新建项目-窗体应用程序 所谓的Visual C#就是指的可视化编程,主要在设计窗口布置好自己的控件(一些具有一定功能的小部件,例如如可以点击的按 ...
- Android 入门第一课 一个简单的提示框
1.打开Android开发环境Eclipse来到主界面 2.新建一个安卓项目 File->New->Android Application project 在上面有红色错误的地方填上应用程 ...
随机推荐
- 基于echarts的带流动光效的折线图-lowline-for-echarts使用记录
起源 在技术群看到有人问这个react插件,带着好奇心看了一下. 标题:基于echarts的带流动光效的折线图 - 掘金 网址:https://juejin.cn/post/7090566240233 ...
- oracle 内置函数(二)字符函数
主要函数: 大小写转换函数 获取子字符串函数(字符串截取) 获取字符串长度函数 字符串连接函数 去除子字符串函数 字符替换函数 字符串出现次数 字符串按照特定符号拆分多行 一.大小写转换 1.uppe ...
- 【实习项目介绍】XXXXX大数据平台介绍
一.技术架构 1.整体介绍及架构 (1)概述 Odeon大数据平台以全图形化Web操作的形式为用户提供一站式的大数据能力:包括数据采集.任务编排.调度及处理.数据展现(BI)等:同时提供完善的权限管理 ...
- SAP程序发布流程
更改程序名称 如果你想要更改程序名称的话,首先进入程序,关闭编辑,只显示代码 点击重命名就可以了 或者直接输入事务代码se38进入APAP编辑器,输入程序名称,重命名 为程序创建事务代码 事务代码为s ...
- 1分钟理清楚C++类模板和模板类区别
1.定义区别 类模板和模板类主要关注点是后一个单词. 类模板:主要描述的是模板,这个模板是类的模板.可以理解为一个通用的类,这个类中的数据成员,成员函数的形参类型以及成员函数的返回值类型不用具体的指定 ...
- Redis的数据被删除,占用内存咋还那么大?
通过 CONFIG SET maxmemory 100mb 或者在 redis.conf 配置文件设置 maxmemory 100mb Redis 内存占用限制.当达到内存最大值值,会触发内存淘汰策略 ...
- 精华推荐 | 【深入浅出RocketMQ原理及实战】「性能原理挖掘系列」透彻剖析贯穿RocketMQ的事务性消息的底层原理并在分析其实际开发场景
什么是事务消息 事务消息(Transactional Message)是指应用本地事务和发送消息操作可以被定义到全局事务中,要么同时成功,要么同时失败.RocketMQ的事务消息提供类似 X/Open ...
- 开发一个MyBatis通用Mapper的轮子
一.前言 程序猿为什么如此执着于造轮子?MyBatis-Plus如此强大的工具流行这么多年了,我为啥还在重复造这样的轮子? 1.公司的技术规范不允许使用MyBatis-Plus,咱也不知道什么原因: ...
- Apache Dubbo 官方正式发布 Spring 6 & Spring Boot 3 支持
Dubbo 简介 Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java.Golang 等多语言 SDK 实现.使用 Dubbo 开发的 ...
- STL vector常用API
1.容器:序列容器(时间决定).关联式容器(容器中的数据有一定规则) 2.迭代器:通过迭代器寻找.遍历容器中的数据 vetor的使用:数据遍历与输出 #define _CRT_SECURE_NO_WA ...