编译,发版,链接库问题
一般发版我们就发一个.so和头文件。
头文件说明类的方法调用,so是方法的实现。比如opencv库就是头文件和so。就提供两个文件夹一个include和lib。
但是我们工程还依赖于各种库,这个时候你除了提供以上2个文件还需要提供所用到的第三方库简称3rdparty。
我们现在工程比较麻烦,需要在不同平台下面运行,比如1070,2080,3090,寒武纪。每个平台下面所依赖的库不同。
所以我们现在用的方法是提供各个平台的库在文件夹3rdparty下面,然后再写一个配置环境变量的shell脚本。
这个脚本可自动识别当前是哪个平台比如1070,还是寒武纪。然后export当前平台所对应的3rdparty。
具体来说就是如下shell代码:
#!/bin/bash
if test $( nvidia-smi | grep 'GPU'| wc -l ) -eq 0
then
echo "start on cambricon"
export LD_LIBRARY_PATH=$PWD/../hwj_lib/:$PWD/../3rdlib/libboost:$PWD/../3rdlib/opencv-3.4.10:$PWD/../3rdlib/glog:$PWD/../3rdlib/gflags:$PWD/../3rdlib/caffe_hwj/:$PWD/../3rdlib/libtorch_hwj:$PWD/../3rdlib/cuda_10:$PWD/../3rdlib/cambricon/:$PWD/../3rdlib/atlas:$PWD/../3rdlib/lib:$PWD/../3rdlib/protobuf:$PWD/../3rdlib/python2:$PWD/../3rdlib/lib_gtk/:$PWD/../3rdlib/freetype:$PWD/../nvidia_lib:$PWD/../3rdlib/curl/
else
if test $( nvidia-smi -L | grep 'TX 1070' | wc -l ) -gt 0
then
echo "start on nvidia 1070"
export LD_LIBRARY_PATH=$PWD/../3rdlib/libboost:$PWD/../3rdlib/opencv-3.4.10:$PWD/../3rdlib/glog:$PWD/../3rdlib/gflags:$PWD/../3rdlib/caffe_8:$PWD/../3rdlib/libtorch_8:$PWD/../3rdlib/cuda_8:$PWD/../3rdlib/lib:$PWD/../3rdlib/protobuf:$PWD/../3rdlib/python2:$PWD/../3rdlib/atlas:$PWD/../3rdlib/lib_gtk/:$PWD/../3rdlib/freetype:$PWD/../lib:$PWD/../3rdlib/cambricon/:$PWD/../3rdlib/curl/
fi
if test $( nvidia-smi -L | grep 'TX 1080' | wc -l ) -gt 0
then
echo "start on nvidia 1080"
export LD_LIBRARY_PATH=$PWD/../3rdlib/libboost:$PWD/../3rdlib/opencv-3.4.10:$PWD/../3rdlib/glog:$PWD/../3rdlib/gflags:$PWD/../3rdlib/caffe_8:$PWD/../3rdlib/libtorch_8:$PWD/../3rdlib/cuda_8:$PWD/../3rdlib/lib:$PWD/../3rdlib/protobuf:$PWD/../3rdlib/python2:$PWD/../3rdlib/atlas:$PWD/../3rdlib/lib_gtk/:$PWD/../3rdlib/freetype:$PWD/../lib:$PWD/../3rdlib/cambricon/:$PWD/../3rdlib/curl/
fi
fi
当我接手一个新需求,就是单独实现一个识别功能只用cpu,同样的也是需要适应各个平台。踩了不少坑,最后的最后向着我们工程的方法靠拢就解决了!!!
下面是杂杂念:
源码编译工程文件夹是源代码,在本地机器上编译通过。
走了不少弯路,一开始随便在一台电脑上编译,成功了然后拿到另外一台电脑编译,然后有的电脑好使有的就会报错!
能编译成功,但是一运行就报非法指令。
车检工程发版的库文件有3,4个,比如在1070卡上面有三个库文件夹,3rdparty_10,3rdparty_20,3rdparty_30.
这里面的库文件很重要,和电脑配置息息相关。应该说这里的库文件和当前电脑的配置有关。各个库之间的依赖关系也都是对的。但是具体哪些库和什么配置有关或者哪些库依赖与哪些配置我现在还不清楚。最拿基本的caffe来说,不同平台需要编译不同版本的caffe库,因为在1070上面caffe依赖的cuda是8.0. 在2080卡上面caffe依赖的cuda是10.0. 所以不同平台各个库都有对应的依赖关系。
现在编译也和车检发版一样。在不同平台上面编译用对应的3rdparty编译就可以了。
但是发版的时候只需要发布库文件就可以了,就是发布/lib/libchejian.so这个库文件和对应的头文件就可以了!!
但是依赖的第三方库也需要提供。这里可以直接用车检工程发布的第三方库就可以。因为是一样的。
在执行的时候首先需要运行source chejian_redis_env.sh。可以根据当前硬件初始化环境LD_LIBRARY_PATH.
文件夹bin下面的可执行文件就是调用libchejian.so来运行,这个可以供我们测试当前环境是否可以跑。
现在有个疑问是在源码编译的时候比如我们需要放boost的头文件,然后编译libchejian.so。
在发版的时候只需要发布libchejian.so和其头文件,这个时候只需要放置boost库文件不需要boost的头文件。
写着写着这些疑问的时候好像又理解了。
源码编译工程的时候需要用到boost的头文件和库,当你编译好工程的时候生成你自己的so库。别人用你这个库你只需要提供库和头文件。
你的库所依赖的其他库你提供库就可以,不需要头文件了,因为头文件都编译在你自己库里面了。如此。
用的caffe库是寒武纪文件夹下面的,然后编译出来在寒武纪和我的电脑i7上面是可以运行跑的,但是在i5机器跑不了。
可以编译出来库,但是一运行就报错!报非法指令。然后gdb运行,看错误。
root@-desktop:/home/yhl/yanzhengma_1022_0/yanzhengma/bin# gdb
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) file cpu_test
Reading symbols from cpu_test...(no debugging symbols found)...done.
(gdb) r
Starting program: /home/yhl/yanzhengma_1022_0/yanzhengma/bin/cpu_test
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7fffd7ff8700 (LWP 6312)]
[New Thread 0x7fffd77f7700 (LWP 6313)]
[New Thread 0x7fffd4ff6700 (LWP 6314)]
Thread 1 "cpu_test" received signal SIGILL, Illegal instruction.
0x00007fffefa17fc3 in CryptoPP::DetectX86Features () at cpu.cpp:262
262 cpu.cpp: 没有那个文件或目录.
(gdb)
然后把caffe换成cuda8的caffe,然后报protobuf未定义的引用什么的。。。
无解
然后我突然想到在发版服务器70.209上面,分了好几个3rdparty文件夹,发版哪个就软连接哪个。就说明各个平台的库是不一样的。
而且有个重要的点就是,我发现算法提供给软件部算法库里面的3rdparty里面有些库是没有头文件的,比如我一开始到一台电脑上面去源码编译我的代码,然后有的电脑就会报缺少boost头文件,我一看我3rdparty下面确实只提供了库,没有提供头文件。然后只能网上百度sudo apt-get 安装库。然后就可以。
于里超说是因为你编译的时候是需要头文件的,编译好了就在库里面了。
所以一般而言,我们算法编译出来的库只需要提供其他库的.so,头文件不需要提供。因为其他库头文件已经被你编译到当前so库中了,后面只需要提供其他库的so文件。
写的好乱,我只当我自己的记录。在此过程中还是出现了好多报错,我都感觉无从下手,比如
libXXX.so依赖于XXX,not found
未定义的引用
突然想起来,一个问题现象是,就是我用别人的机器来跑我的这个识别的demo。然后编译的时候一堆错误啊,无从下手,然后让同事看,然后同事最后解决了说我这个工程所依赖的库和这个电脑上面所需要的一样,
然后就调用这个电脑其他路径下面的库了,他把在一个地方指定搜寻库路径注释掉就好了,在系统哪个目录下面,什么/etc/ld_conf.so之类的地方,是一个文本可以写路径,具体忘记了。
但是我想说的是,我在
cmakelist文件中已经指定了各个库路径,比如如下:
set(BOOST_ROOT ${CMAKE_SOURCE_DIR}/3rdparty/libboost)
include_directories(${BOOST_ROOT}/include)
link_directories(${BOOST_ROOT}/lib)
cmakelist已经指定了,它还是会优先找其他地方啊。
可能cmakelis指定的库路径优先级比系统其他某处指定的路径优先级低。先在系统指定路径下面找到了这个库就不在其他地方找了。
所以这个时候你指定的库优先在其他地方找到了就不会用你自己指定的库了。