1. 下载最新的clapack-cmake包
2. 解压 tar –zxf 压缩包
3. 下载cmake linux i386版本,依个人而异(本人虚拟机Ubuntu 14 32bit)
4. 目标平台powerpc 交叉工具链eldk,ppc_6xx
5. 执行cmake-gui配置(关键步骤)
第一步:
第二步:
点击configure,选择unix_makefile,选择配置交叉工具链选项,如下图
第三步:
第四步:
第五步:
点击configure 完成后点击 generate(NOTE:一般没什么问题,如果有问题请google;另外,warning一般没事,主要是error)
选择CMAKE的选项菜单,添加编译选项的值,需要配置的有这么几个值
CMAKE_C_FLAGS 配置成-fPIC –DNON_UNIX_STDIO
-fPIC选项链接成动态库有用
原因具体如下,参考clapack的源码下f2c目录下的makfile
# Unix makefile: see README. # For C++, first "make hadd". # If your compiler does not recognize ANSI C, add # -DKR_headers # to the CFLAGS = line below. # On Sun and other BSD systems that do not provide an ANSI sprintf, add # -DUSE_STRLEN # to the CFLAGS = line below. # On Linux systems, add # -DNON_UNIX_STDIO # to the CFLAGS = line below. For libf2c.so under Linux, also add # -fPIC # to the CFLAGS = line below. |
CMAKE_EXE_LINKER_FLAGS 配置成-lm
CMAKE_SHARED_LINKER_FLAGS 配置成-shared(此标志在链接成共享库时有效)
第六步:
所有填完以后点击generate
应该有一个完整的Makefile了,Makefile的目录就在之前选择的“where to build the binaries”
第七步:
到指定的目录下,执行make
1) 发现有个错误,形如:
错误的原因是,代码用交叉工具链生成了一个arithchk,然后执行,意图得到一个头文件叫arith.h,但是实际这是有问题的。因为,根本不能运行。需要将其拷贝到目标板运行,将输出到arith.h文件,手动生成一个.h文件即可。
我这边的头文件内容如下:
#define IEEE_MC68k #define Arith_Kind_ASL 2 #define Double_Align #define NO_LONG_LONG #define QNaN0 0x7ff80000 #define QNaN1 0x0 |
将此文件拷贝到 F2CLIBS/libf2c/即可,此路径是相对于目前执行make的当前目录而言。
拷贝以后,再次执行make即可。一马平川,应该会非常顺利!
2) 拷贝真正的链接库
在当前目录执行 find . –name *.a 即可看到当前目录及其子目录下的静态库,将其拷贝出来即可。
到此为止,静态库的方法制作完毕,可以直接调用。
第八步
动态库的制作
这时候修改这么4个文件:(本人下载的版本是3.2.1)
clapack-3.2.1-CMAKE/BLAS/SRC/CMakeLists.txt 139 18:add_library(blas SHARED ${ALLOBJ}) clapack-3.2.1-CMAKE/SRC/CMakeLists.txt 378 20:add_library(lapack SHARED ${ALLOBJ} ${ALLXOBJ}) clapack-3.2.1-CMAKE/F2CLIBS/libf2c/CMakeLists.txt 61 17:add_library(f2c SHARED ${OFILES} ${CMAKE_CURRENT_BINARY_DIR}/arith.h) clapack-3.2.1-CMAKE/TESTING/MATGEN/CMakeLists.txt 68 20:add_library(tmglib SHARED ${ALLOBJ} ) |
即,添加了几个SHARED的关键字
这句话的意思是:
add_library的作用是指示CMake生成一个库,根据参数SHARED还是STATIC来决定生成动态库还是静态库
第九步
修改完后,重新再cmake-gui里点击generate,
然后,再到指定的目录执行make(可能还有错误上次一样的错误,处理即可!)
第十步
链接库的使用
1) 静态库的使用
静态库的使用就在makefile里引用即可
2) 动态库的使用
上述编译的动态库,其实还不能用。使用的时候有这么几个问题;
动态库之间的依赖问题
对生成的4个动态库进行readelf会发现,相互之间有依赖关系,并且库的引用是引用的相对路径。带来的问题是,根本找不到依赖库,怎么办呢?
重新做库,别无他法!
做库的方法,即将所用到的库复制到链接的目录下,手动执行link.txt的内容,手动指定链接库的目录为当前目录,和链接库的名字。编译的时候,注意所有的OBJ文件还在子目录里也有
3) 编译应用程序
结果发现,还是不能用,提示错误。f2c.so中的MAIN__是“ undefined reference to'MAIN__'”
到源码中会发现,确实f2c中有个main.c,其中确实引用了MAIN__,确实MAIN__没定义
需要思考的是!库咱们只需要用其中的function api,根本不需要main的入口。解决办法,即把做f2c动态库的时候,将main.c.obj删除,然后编译还是不行!分析代码就会知道,还需要把getarg_.c.obj 和iargc_.c.obj删除。
将重新做好的libf2c.so拷贝出来,执行例程引用库,编译OK!
6. 需要思考的
为什么同样是库,包含同样的obj,结果还是不一样呢?
这一点需要说明下动态库和静态库的区别
静态链接库是在程序连接的时候将静态库中的数据代码,插入到源程序当中去,这样有个缺点就是程序会过于庞大;而在应用动态链接库的程序,链接器需要检查动态链接库,确保其包括生成的可执行文件所需的所有符号,这是编译器并不将代码插入到执行文件当中,而是在程序运行的时候,告诉系统的动态加载程序动态链接库的位置,然后动态的装载与动态的卸载 |
关键点,主要就是红字部分;展开来说,动态静态各有优缺点,静态库使用时会把公用的函数自己保存一份,结果就是可能好多个app引用,好多个函数副本。但是,如果库很大,你只用了其中几个函数,这实话片子资源紧张,静态库是优势的;如果动态库,恰好相反。
并且,参考上面遇到的错误,还有一点。当库里某个api没有定义时,引用库时会提示未定义,而静态却没有问题。为什么呢?
首先把静态和动态的文件file下看下区别
很明显,动态库链接在链接库时会坚持所有的符号,确保是有效的。
但是,静态库只是一个类似文件夹的作用,只是把所有的obj打包在一起。用哪个,我最终链接哪个obj,其他的我不关心。
qdzhaox 20160614