makefile编译_C++ Lesson 5:编译Makefile

8c5821f60c6786c8128deab7494bc739.png

主要内容:

  • 编译程序的过程:preprocessor、compiler、assembler、linker、loader
  • Makefile
  • 类的Makefile
  • 其他方式:.h & .cpp

一、编译器compiler,汇编器assembler,连接器linker,加载器loader[1]

1、编译程序compiling program

  • 当我们在ubuntu中敲入g++ Myfile.cpp –o Myfile –std=c++11的时候,4个实体涉及到了编译过程:preprocessor,compiler,assembler,linker

2de86bd9835ba6a491fe2a47343f92ae.png
    • 首先,预处理器cpp将所有的宏定义和include语句进行扩展,然后将结果传递给真正的编译器。这一步生成的结果是C code。如果我们的代码中没有预处理声明,其实不必运行预处理器。
    • 然后,编译器(compiler)能够将预处理过的C code翻译成汇编代码(assembly code),进行各种优化寄存器分配
    • 然后,汇编器(assembler)将汇编代码翻译为机器代码(machine code),又称为目标文件(object file)。
    • 目标文件和其他的目标文件&libraries链接,通过链接器linker给所有的引用分配内存地址。
  • 例子,在ubuntu中生成code1.cpp文件,通过emacs编译
#include

回到ubuntu中,利用g++编译可执行的程序

g++ code1.cpp -o code1 -std=c++11
  • 整体的流程如下

46f7b21ed5287ec00104242dceb309a3.png

二、拆分code1.cpp

  • 为了能够讲解整个流程,将code1.cpp拆分为3个文件
    • add.h + add.cpp + code1.cpp
      • add.h——定义成员函数
#include
      • add.cpp——成员函数的细节
// file:add.cpp
      • code1.cpp——主函数
#include 
    • 如何将code1.cpp变成code1.o?
      • 首先,分别编译(-c=compile)两个cpp文件,生成目标文件(.o)
g++ -c code1.cpp
g++ -c add.cpp
      • 然后,对两个目标文件进行链接(linking)
g++ add.o code1.o -o code1
      • 执行最后的程序
./code1

三、Makefile

  • 上述文件的依存关系

  • 那么,我们能够通过Makefile,一步实现所有的步骤
    • 第一步,在ubuntu中创建Makefile,并且编辑
touch Makefile
emacs Makefile
    • 进入emacs中编辑Makefile
    • Makefile编辑如下。注意:每一句的第二行,前面的空格是按一下Tab键,千万不是随机的空格键。否则编译不通过。
add.o : add.h add.cpp  //依存关系
	g++ -c add.cpp  //ubuntu中的运行代码,下同

code1.o : add.h code1.cpp
	g++ -c code1.cpp

code1 : add.o code1.o
	g++ code1.o add.o -o code1

clean :
	rm -f add.o code1.o code1

Makefile中的编辑,实际上就是我们列表的依存关系(第一行) + ubuntu中一步一步运行(第二行)的结果。

    • 在ubuntu中输入,make,最后就得到了main文件。直接运行./main。
    • make clean——删除中间文件。

三、类的Makefile

例如,我定义一个复数的类。

首先,建立3个文件,分别是①complex.hpp(存放类的框架);②complex.cpp(存放类的具体的定义);③main.cpp(存放调用这个类函数的主函数)

danielshen@DESKTOP-VOSNAQJ:~$ touch complex.hpp
danielshen@DESKTOP-VOSNAQJ:~$ touch complex.cpp
danielshen@DESKTOP-VOSNAQJ:~$ touch main.cpp

再依次编辑;

danielshen@DESKTOP-VOSNAQJ:~$ emacs complex.hpp
danielshen@DESKTOP-VOSNAQJ:~$ emacs complex.cpp
danielshen@DESKTOP-VOSNAQJ:~$ emacs main.cpp

第一个complex.hpp中的编辑如下:

#include

第二个complex.cpp编辑如下:

//file: complex.cpp

第三个主函数编辑如下:

#include 

然后,在ubuntu中创建一个Makefile

danielshen@DESKTOP-VOSNAQJ:~$ touch Makefile
danielshen@DESKTOP-VOSNAQJ:~$ emacs Makefile

文件之间的关系如表

更新代码时,我们主要依照关系,更细相关文件。

Makefile编辑如下。注意:每一句的第二行,前面的空格是按一下Tab键,千万不是随机的空格键。否则编译不通过。

main

然后在ubuntu中运行:

danielshen@DESKTOP-VOSNAQJ:~$ make

结果是:

g++ -c complex.cpp
g++ -c main.cpp
g++ complex.o main.o -o main

运行主函数

danielshen@DESKTOP-VOSNAQJ:~$ ./main

结果是

Destroying : 4 + (6)i.
c1 = 1+1i

c2 + c3 = 4+6i

Destroying : 4 + (6)i.
Destroying : 3 + (4)i.
Destroying : 1 + (2)i.
Destroying : 1 + (1)i.

可以查看当前文件夹中的文件

danielshen@DESKTOP-VOSNAQJ:~$ ls

Makefile   complex.cpp   complex.hpp   complex.o  main.cpp   main.o
Makefile~  complex.cpp~  complex.hpp~  main       main.cpp~

我们可以clean一下

danielshen@DESKTOP-VOSNAQJ:~$ make clean

运行结果为

rm -f complex.o main.o main

再看文件夹中的文件:

danielshen@DESKTOP-VOSNAQJ:~$ ls

只剩下

Makefile   complex.cpp   complex.hpp   main.cpp
Makefile~  complex.cpp~  complex.hpp~  main.cpp~

因此,这个例子可以看出来,类的模板在hpp中定义,类具体在cpp中定义,调用时在main函数中声明.hpp文件即可。同时搞清楚Makefile中不同文件之间的关联性。

四、.h和.cpp在一个文件夹中

1、#ifndef #define #endif[2][3]

  • 经常看到这三个符号在文件的开头和结尾部分,作用:
    • 统称为#include guards。
    • 大型软件工程中,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行的文件的时候,就会出现大量“重定义”的错误;从而避免头文件的重定义。
    • 一旦headers被included,那么将会检查“唯一值”是否定义(唯一值就是#ifndef后面跟着的大写字符串)。如果没有定义,那么将会定义,并继续剩下的部分。防止对任何标识符(例如类型、枚举、静态变量)进行双重声明。
  • 例子:

首先在ubuntu中生成3个文件,分别是"p.h" "c.h" "main.cpp",然后通过emacs以及进入编辑。

p.h,定义坐标类

#ifndef POINT_H

c.h定义城市名+坐标类:

#ifndef CREATURE_H

主函数main.cpp

#include 

然后在ubuntu中,输入

g++ main.cpp -o main -std=c++11

就可以调用两个类、同时运行主函数。

参考

  1. ^https://courses.cs.washington.edu/courses/cse378/97au/help/compilation.html
  2. ^https://stackoverflow.com/questions/1653958/why-are-ifndef-and-define-used-in-c-header-files
  3. ^https://www.cnblogs.com/xuepei/p/4027946.html
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值