C/C++中的各文件的作用关系及编译过程

前言

学了c++,写的部分小工具都是用的VS、CLion这样的专门IDE,这些IDE都帮我处理好了多个c++文件的链接生成等工作,不用了解它的运作原理,导致有时候学习第三方库做的程序时不知道我的代码是怎么和它们联系起来的、离开了IDE两眼一抹黑,直接使用gcc/g++命令行的方式几乎没怎么用过。

直到今天我了解到了Cmake和makefiles,今天特此来梳理一下整个C/C++项目的构建过程、文件作用、名词解释等概念。

文件介绍

各后缀文件简介:

1.<obj> 目标文件,一般是程序编译后的二进制文件,通过链接器和资源文件链接后就成为exe文件(链接器将使用这些文件生成exe文件)。obj只给出了程序的相对地址,而exe是绝对地址,cpp对应的二进制代码格式,是未经重定位的!

2.<lib> lib有静态lib和动态lib之分, 静态lib将导出声明和实现都放在lib中。编译后所有代码都嵌入到宿主程序,动态lib相当于一个h头文件,实现部分(.dll文件)函数接口声明,编译后只是将导出声明部分编译到宿主程序中,运行时候需要相应的动态库文件支持。静态库LIB和动态库的区别:

1. 静态库: 函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在编译链接可执行文件时,链接器(Linker)从库中复制这些函数和数据并把它们和应用程序的其它模块组合起来创建最终的可执行文件。
2. 在使用动态库的时候 一般提供两个文件,一个引入库(.lib)和一个DLL。引入库(.lib)包含被DLL导出的函数和变量的符号名DLL包含实际的函数和数据。在编译链接可执行文件时,只需要链接引入库,DLL中的函数代码和数据并不复制到可执行文件中在运行可执行文件(.EXE文件)的时候,再去加载DLL,访问DLL中导出的函数。

   lib文件是不对外公开的,不能查看一个编译过后的文件

3.<dll> DLL 是一个包含可由多个程序同时使用的代码和数据的动态库,动态链接库通常都不能直接运行,它们是一些独立的文件,其中包含能被可执行程序或其它DLL调用来完成某项工作的函数,只有在其它模块调用动态链接库中的函数时,它才发挥作用。

4.<o> 目标文件,一般通过c或者cpp文件编译而来,相当于VC编译出来的obj文件。

5.<so> shared object 共享库(对象),相当于windows下的dll。

6.<a> archive 归档包,即静态库。其实质是多个.o文件打包的结果,相当于VC下的.lib文件,也有动态静态之分。

7.<la> 使用libtool工具编译出的库文件,其实是个文本文件,记录同名动态库和静态库的相关信息。

8.<lo> 使用libtool工具编译出的目标文件,其实就是在o文件中添加了一些信息。

9.<i> 进行预编译之后生成的文件,一般都是把头文件包含进去,进行宏替换这些工作之后生成的文件。

10.<s> 汇编 .i 文件后生成的汇编文件。

编译过程

gcc/g++编译文件分为四个步骤:

1.预处理 条件编译,头文件包含,宏替换的处理,生成 .i 文件。

2.编译 将预处理后的文件转换成汇编语言,生成 .s 文件。

3.汇编 汇编变为目标代码(机器代码),生成.o的文件。

4.链接 连接目标代码,生成可执行程序,可以链接多个.o文件。

编译环境

动态链接库需要在环境变量中,或者在最终可执行文件同路径下,可执行文件才能正常运行。

cmake与makefiles

介绍

CMake是一个跨平台的编译(Build)工具,可以用简单的语句来描述所有平台的编译过程。CMake能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。

假如我们有一个深度学习框架的部分工程列表,里面有超过40个互相调用的工程共同组成,一些用于生成库文件,一些用于实现逻辑功能。他们之间的调用关系复杂而严格,如果我想在这样复杂的框架下进行二次开发,显然只拥有它的源码是远远不够的,还需要清楚的明白这几十个项目之间的复杂关系,在没有原作者的帮助下进行这项工作几乎是不可能的。

即使是原作者给出了相关的结构文档,对新手来说建立工程的过程依旧是漫长而艰辛的,因此CMake的作用就凸显出来了。原作者只需要生成一份CMakeLists.txt文档,框架的使用者们只需要在下载源码的同时下载作者提供的CMakeLists.txt,就可以利用CMake,在”原作者的帮助下“进行工程的搭建。

Makefile 或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。因为,makefile关系到了整个工程的编译规则 。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。 makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。

对于一个大型软件,其编译、维护是一个复杂而耗时的过程。它涉及到大量的文件、目录,这些文件可能是在不同的时间、由不同的人、在不同的地方分别写的,其中一些是程序,有些是数据,有些是文档,有些是衍生文件。甚至参与开发的人员也不一定清楚所有文件的细节,包括如何处理它们。此外,构成软件的文件数目可能达到成百上千,甚至成千上万个,开发过程中当修改了少量几个文件后,往往只需要重新编译、生成少数几个文件。有效地描述这些文件之间的依赖关系以及处理命令,当个别文件改动后仅执行必要的处理,而不必重复整个编译过程,可以大大提高软件开发的效率。

基本使用配置

Cmake的配置文件时CMakeLists.txt,给个示例一目了然:

# cmake 的版本要求
cmake_minimum_required(VERSION 3.14) 
# 项目名称
project(myCppPractice)
# 设置 Debug 模式
set(CMAKE_BUILD_TYPE "Debug")
# 设置源文件根目录,并设置别名为DIR_ROOT
aux_source_directory(. DIR_ROOT)
# 设置myCppPractice版本标准
set(CMAKE_CXX_STANDARD 14)
# 项目包含哪些 文件
add_executable(${PROJECT_NAME} main.cpp Actor.cpp AnimSpriteComponent.cpp BGSpriteComponent.cpp
Component.cpp Game.cpp Math.cpp Ship.cpp SpriteComponent.cpp)
# 声明三方库位置路径
set(SDL2_DIR D:/program/resource/x86_64-w64-mingw32)
# headers头文件位置
include_directories(${SDL2_DIR}/include)
# 推荐使用find_package和find_library寻找共享库的绝对路径,再传给target_link_libraries使用。
find_library(SDL2MAIN SDL2main ${SDL2_DIR}/lib)
find_library(SDL2 SDL2 ${SDL2_DIR}/lib)
find_library(SDL2IAMGE SDL2_image ${SDL2_DIR}/lib)
# 链接库
target_link_libraries(${PROJECT_NAME} mingw32 ${SDL2MAIN} ${SDL2} ${SDL2IAMGE})

内容整理自博客来源

本文整理内容来自以下博客,原地址链接:

1.C++程序编译的四个过程
2.Linux中的动态库和静态库
3.dll、Lib、obj、.h文件的区别与作用
4.linux下的so、o、lo、a、la文件的区别
5.CMake是什么?有什么用?
6.C/C++动态链接库(DLL)详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值