从软件国产化迁移视角研究Linux程序的编译链接

1.程序构建的基本过程回顾

        我们在学习C语言是时,知道构建一个应用程序典型的过程是:“编辑、编译、链接、运行”四个步骤。实际上,这四个步骤中的编译指的是广义的编译,包括预编译和编译两个阶段,如下图所示:

 

        以Windows操作系统中构建一个C++可执行程序为例,首先进行软件代码的编辑,形成一个个的头文件(.h)和源文件(.cpp);然后进行预编译,主要是将每个源文件中include的头文件、宏等进行等效替换,形成中间文件(.i),其中源文件和中间文件是一一对应的关系;然后进行编译,将中间文件编译形成目标文件(.obj),中间文件和目标文件也是一一对应的关系;最后进行链接将目标文件整合成为一个动态库(.dll)或者执行体(.exe)。

        大多数的书籍都是按照上述四个步骤在介绍,实际上再补充一张构建流程中国文件映射的图更加便于理解,如下图所示:

        预编译和编译的阶段都是依靠一个编译器程序进行处理,编译器程序遍历每个源文件进行预编译和编译,形成这个源文件对应的目标文件(如将a.cpp编译形成a.obj),也就是说一个代码工程中有多少个源文件(.cpp)便会生成多少个目标文件(.obj);链接过程依靠链接器程序进行处理,将一个代码工程中所有的目标文件链接到一个可执行文件中。

        Linux操作系统中的编译链接过程和Windows操作系统中的过程是完全一致的,只不过Linux操作系统中不同阶段的文件后缀不一样,例如可执行文件的后缀是.so或者.a等。

2. 软件国产化迁移问题场景

         随着国产化要求越来越高,常常要求软件运行在国产化硬件平台和国产化操作系统中。比如笔者就面临要将软件运行在硬件为Arm64架构的CPU、操作系统为银河麒麟的环境中,而软件原有的运行环境为硬件为X86架构CPU、操作系统为CentOS7,且软件开发的IDE为codebolcks。

        面对这样的软件国产化需求,典型的解决办法有两种:一是在原有的开发环境中采用交叉编译的方式重新构建软件;另一种办法是将软件代码直接在目标环境中重新构建。而交叉编译通常会因为目标环境的差异而调试繁琐,最直接最有效的办法还是直接在目标环境中重新构建。

       在目标环境中重新构建软件首先要解决的是在目标环境中重新安装IDE环境codeblocks,但是在离线环境中常常因为依赖的问题codeblocks安装失败,这就促使我们需要回过头来研究下Linux操作系统中程序的编译链接特点。

3. Linux操作系统中典型的程序构建形式

        在Linux操作系统中典型的程序构建形式包括:makefile构建、cmake构建、集成IDE构建(以codeblocks为例)。

        对于makefile构建的方式,makefile文件用于管理和组织代码工程的编译和链接,其不是可执行文件,其被make工具解析并完成相关动作,makefile文件遵循一定的格式,可采用手动或者自动化工具生成该文件。

        对于cmake构建的方式,CMake是一种跨平台编译工具,比make更为高级,使用起来要方便得多。CMake主要是编写CMakeLists.txt文件,然后用cmake命令将CMakeLists.txt文件转化为make所需要的makefile文件,最后用make命令编译源码生成可执行程序或共享库(so(shared object))。

        对于采用codeblocks这类集成IDE方式构建,只需要目标环境中安装有codeblocks便可直接编译,也可以借助cbp2make这类转换工具直接将工程文件.cbp转换为makefile。

Codeblocks的工程文件cbp格式如下:

 

        以编译一个工程为例,可以看到其编译日志如下:

         仔细分析其日志内容如下:

-------------- 清理: Debug 在 ProtoPackLib 中 (编译器: GNU GCC Compiler)---------------

已清理 "ProtoPackLib - Debug"

-------------- 构建: Debug 在 ProtoPackLib 中 (编译器: GNU GCC Compiler)---------------

g++ -Wall -fexceptions -w -std=c++11 -fPIC -g -Iinclude -c /home/user/ProtoPackLib/src/EnumDefine.pb.cc -o obj/Debug/src/EnumDefine.pb.o

g++ -Wall -fexceptions -w -std=c++11 -fPIC -g -Iinclude -c /home/user/ProtoPackLib/src/SimuModelDataOut.pb.cc -o obj/Debug/src/SimuModelDataOut.pb.o

g++ -shared -Llib obj/Debug/src/EnumDefine.pb.o obj/Debug/src/SimuModelDataOut.pb.o  -o bin/libProtoPackLib.so -Wl,-rpath="./":"bin/bin"  -lprotobuf

输出文件为 bin/libProtoPackLib.so,大小为 3.41 MB

程序退出, 返回状态码:0 (0 分, 51 秒)

0个错误, 0个警告 (0 分, 51 秒)

        可以看出codeblocks实际上就是将工程文件.cbp中记录的编译链接信息变成了一条条的编译链接指令序列,指令序列执行完成后可执行文件便生成了,所有直接将这些指令序列整理到一个批处理文件中,执行该批处理文件也能达到同样的效果。

         总结几种构建方式的关系如下:

         实际就是以不同格式的文件(cbp、cmakelists、makefile等)记录一个代码工程的编译链接设置选项,利用对应的工具(codeblocks、cmake、make等)将代码工程转换为编译链接指令序列,并逐条执行指令序列中的指令形成最终的可执行文件。

4、对于软件国产化迁移的启示

为了将codeblocks工程在目标环境中编译通过的解决办法有以下几种:

  1. 可以考虑在目标环境中直接安装codeblocks环境,在目标环境中利用codeblocks直接编译链接。
  2. codeblocks环境若安装成功难度大,可以考虑利用cbp2make程序将cbp工程文件转换为makefile在目标平台上编译链接。
  3. 可以考虑直接编写makefile文件,利用make工具编译链接。
  4. 可以直接编写cmakelists文件利用cmake工具进行编译链接。
  5. 若是代码工程比较简单可以考虑直接将编译链接命令序列写为sh批处理文件,运行sh实现代码工程编译。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

saint198

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值