如何编译CFortran动态静态链接库

如何编译CFortran动态静态链接库,第1张

首先,传统的编译,也就是

静态编译

是把

文件

翻译成目标文件,这个是一次性过程,也就是你所谓的静态编译。

后来的Java和.NET等语言,首先编译成中间形式,然后运行过程中根据需要编译成本地代码(注意这个过程不是一次性的,下次运行重新编译),这个就是JIT(即时编译)技术,从即时编译发展出了动态编译技术

————————————

(传统的)编译完成后,像C/C++、Fortran、汇编等语言,可以把多个目标文件合并到一个

库文件

中,这个就是静态库。比如常说的

库函数

printf就是libc里面的函数。

如果有了启动函数(main),main里面使用了printf,就可以通含配过

静态链接

技术,从libc中提取出printf所在的文件加入到可执行谈仔指文件中,如果printf还需要其它函数,就继续搜索并加入戚族列表,直到形成一个

闭包

。这个就是静态链接。

可是静态链接有个明显的缺点,如果每个程序都需要printf,那么printf这个函数的代码就会同时存在在每个程序中,这样也太占地方了吧。所以发明了动态连接技术,其实有两种形式。无论哪一种,都是首先记录下需要调用printf这个函数以及所在的

动态库

,等到运行的时候再加载动态库,从动态库中找到真正的printf去执行。

由于,

动态链接

技术需要一些额外的信息,传统的静态库是不具备的,这些额外信息主要是重复加载和卸载时所需要的一些代码,因此需要

动态链接库

在一个项目中需要用到OpenCV,刚开始使用了OpenCV的动态链接库,这样,在移动可执行程序时还必须将OpenCV动态支持库一起搬移,很是麻烦。所以,最终选择OpenCV静态链接库,这样程序移植运行就方便了很多。

需要编译成静态库以便于应用程序链接。

网上有的教程中写的在VC++2010下安装OpenCV2.1时用到了TBB库,而我在编译链接自己的程序后需要用到TBB.dll。本人设计的目的就是要做一个独立的界面程序,不需要携带其他第三方库。经过一段时间的努力最终找到了编译OpenCV2.1静态库的方法。

需要的工具环境及文件:

-------------------------------------------------------------------------------------------------------------

1、Windows XP

2、VC++2010(VS2010)

3、为编译OpenCV源码包(我下载的有:OpenCV2.1.0,OpenCV2.3.0及OpenCV2.4.4)

4、CMake2.8.9

说明:OpenCV各版本官方下载地址:opencv.org/

cmake-2.8.9下载地址:ishare.iask.sina.com.cn/download/explain.php?fileid=35025936

--------------------------------------------------------------------------------------------------------------

以OpenCV2.1.0编译静态库为例

CMake配置

-------------------------------------------------------------------------------------------------------------

打开CMake并设置:

Where is the rource code :OpenCV源代码所在的文件夹

Where to build the binaries:CMake配置好得到的文件放在位置(我的:E:\OpenCV2.1.0-prj)

然后点击configure,选择"Visual Studio 10"。然后确定。

等待configure完成,会出现很多红色的选项,因为主要是生成OpenCV的库,所以只需保留某些选项:肢烂搏

去掉BUILD_NEW_PYTHON_SUPPORT,BUILD_SHARED_LIBS, BUILD_TESTS

勾选OPENCV_BUILD_3RDPARTY_LIBS, WITH_TBB,WITH_JASPER, WITH_JPEG,

WITH_PNG, WITH_TIFF选项,

然后再点击configure,如下图:

提示TBB_INCLUDE_DIR找不到,因为我们不需要TBB库,所历腊以忽略,再一次点击configure。

等待配置完成,最后点击generate,完成后关闭CMake。

-------------------------------------------------------------------------------------------------------------

VC++2010编译静态库

-------------------------------------------------------------------------------------------------------------

进入E:\OpenCV2.1.0-prj目录,使用VC++2010打开.sln文件,打开项目管理器

这时候会看到

解决方案历祥中有很多小项目存在。

注:这时我们右键任意点击一个子项目(如cv),选择属性,可以在配置属性下的常规项目中看到,配置类型为

静态库(lib)。

按住ctrl键,选中除过ALL_BUILD, INSTALL, ZERO_CHECK,

uninstall四个项目的其他所有项目,在菜单中选择项目->属性,打开配置属性->c/c++->代码生成选项,在右侧窗口中的运行时库中选择多线程调试(/MTd),然后确认。

说明:这里有四个选项(/MT, /MTd, /MD,

/MDd),前两个一组,为静态链接运行时库,运行时不需要运行时库的支持,代码直接插入到程序中去;后两个一组,为动态链接运行时库,运行时需要msvcr90.dll或msvcp90.dll支持。

我们先编译Debug版的OpenCV静态库,在解决方案"opencv"(22个项目)上单击右键,选择重新生成解决方案,此时便开始编译OpenCV库了,等编译结束会提示完成16个,失败4个:

这四个项目生成的是exe程序,不需要管他们。到这步我们已经生成了Debug版本的静态库!

然后我们用相同的方式生成Release版的库,在之前的基础上只需要将选项选择多线程/MT,再进行编译。编译时警告很多,直接忽略!

注意:/MT即是Release版本,/MTD即是Debug版本。

最终我们需要的静态库就存在:E:\OpenCV2.1.0-prj/lib 和 E:\OpenCV2.1.0-prj/3rdparty/lib

两个目录,我们编译好的库就在这两个文件夹下。分别

将E:\OpenCV2.1.0-prj/3rdparty/lib中Debug

下面的所有文件Copy到E:\OpenCV2.1.0-prj/lib中的Debug 文件中。

将E:\OpenCV2.1.0-prj/3rdparty/lib中Release下面的所有文件Copy到E:\OpenCV2.1.0-prj/lib中的Release文件中。

在 Linux 开发时,我们经常会看到一些形如 xxx.so 的名称出现,其中 so 是 Shared Object 的缩写,即可以共享的目标文件,也就是我们所称为的动态链接库,和在 Windows 下大家玩 游戏 时遇到的 xxx.dll 错误中的文件是一个类型的。

面试中经常会问到以下问题:

库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。本质上来说库是一种可执行代码的二进制形式,可以被 *** 作系统载入内存执行。

库有两种:

在一个程序的编译过程中,分为以下几个步骤: 预处理 编译 汇编 链接 。本文中讨论的链接库就是针对最后一个步骤「链接」而言的。

动态库和静态库的区别

左图为静态链接库,右图为动态链接库

对于静态链接库而言在链接阶段,会将汇编生成的「目标文件.o」与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接:

静态链接可以理解为最后生成了一个「单文件免安装绿色版」的程序,优点在于移植的时候只需要移动这一个文件,缺点在于文件体积非常大,为了解决这样的问题,就有了动态链接库。动态链接库在程序编译时并不会被连接到目标代码敬大中,而是在程序运行时才被载入。

动态库连接到系统空间,如果多个程序连接了同一个库,那么只需要一份,优点在于编译程序的时候不会将对应的库文件全部打包在生成的程序中,而是保留了到对应库的链接,缺点就是移植的时候如果只移动了对应的程序没有安装相关的库的话,就会看到类似以下喜闻乐见的结果了。

在 Linux 下一个动态库有y三个不同名字的文件组成:

当程序在内部列出所需要的链亮核竖接库时,仅仅使用 soname。当你创建一个链接库时,使用 real name。安装一个新的链接库时,把它复制到一个DLL文件夹里,然后运行程序 ldconfig。ldconfig 检查氏磨存在的 real name 文件,并且创建指向它符号链接 soname 文件。可能大家比较常见到的有 libsodium 等。

有了上面关于库的一些基础知识之后,我们可以开始尝试创建一个动态库来供程序使用了。

比如我们有一个求最大值的函数 max(int a,int b,int c) ,放在文件 max.c 中文件内容如下:

可以通过:

将其编译为共享库,-fPIC是编译选项,PIC是 Position Independent Code 的缩写,表示要生成位置无关的代码,这是动态库需要的特性; -shared是链接选项,告诉 gcc 生成动态库而不是可执行文件。为了让用户知道我们的动态库中有哪些接口可用,我们需要编写对应的头文件,比如可以写一个 max.h :

设置一个驱动函数来测试我们编写的动态库:

通过 gcc test.c -L. -lmax来生成 a.out,其中-lmax表示要链接 libmax.so,-L.表示搜索要链接的库文件时包含当前路径。

但是这样直接运行的话,会出现一个错误:

由于 Linux 是通过/etc/ld.so.cache文件搜寻要链接的动态库的,而 /etc/ld.so.cache 是 ldconfig 程序读取 /etc/ld.so.conf 文件生成的,本次使用的动态库 libmax.so 并不在对应的目录下,就会导致程序无法找到对应的动态链接库,这样我们的解决方法有二:

小结

​动态链接库是各个系统中的一个重要的组成部分且在 Linux 开发相关领域中尤为重要,也是一个面试的高频考点,除了动态链接库以外,还有以下相关知识也是高频考点,在面试前一定要准备好:

本文作者:Nova Kwok


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12439373.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存