linux下用cmake对caffe静态编译时-static-libstdc++参数无效的问题

本文介绍了一个Caffe静态编译时遇到的问题:当启用OpenCV支持时,即使指定了静态链接libstdc++和libgcc,最终的可执行文件仍然依赖动态库。文章提供了解决方案,并探讨了问题的根本原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下是用于cmake 生成 Makefile文件对Caffe进行静态库连接编译的shell脚本,

#!/bin/bash
# cmake 静态编译 caffe-ssd 代码脚本
# author guyadong@gdface.net
shell_folder=$(cd "$(dirname "$0")";pwd)
. $shell_folder/build_funs
. $shell_folder/build_vars
# 项目安装路径
install_path=$SSD_INSTALL_PATH
echo install_path:$install_path
# gflags 安装路径
gflags_root=$GFLAGS_INSTALL_PATH
exit_if_not_exist "$gflags_root/lib/libgflags.a" "not found $gflags_root/lib/libgflags.a,please build $GFLAGS_PREFIX"
# glog 安装路径
glog_root=$GLOG_INSTALL_PATH
exit_if_not_exist "$glog_root/lib/libglog.a" "not found $glog_root/lib/libglog.a,please build $GLOG_PREFIX"
# hdf5 cmake 位置  
hdf5_cmake_dir=$HDF5_INSTALL_PATH/share/cmake
exit_if_not_exist $hdf5_cmake_dir "not found $hdf5_cmake_dir,please build $HDF5_PREFIX"
exit_if_not_exist $BOOST_INSTALL_PATH "not found $BOOST_INSTALL_PATH,please build $BOOST_PREFIX"
exit_if_not_exist $OPENBLAS_INSTALL_PATH "not found $OPENBLAS_INSTALL_PATH,please build $OPENBLAS_PREFIX"
exit_if_not_exist $PROTOBUF_INSTALL_PATH "not found $PROTOBUF_INSTALL_PATH,please build $PROTOBUF_PREFIX"
# protobuf lib 路径,
# centos下安装路径可能是lib64
[ -e "$PROTOBUF_INSTALL_PATH/lib" ] && protobuf_lib=$PROTOBUF_INSTALL_PATH/lib
[ -e "$PROTOBUF_INSTALL_PATH/lib64" ] && protobuf_lib=$PROTOBUF_INSTALL_PATH/lib64
exit_if_not_exist $SNAPPY_INSTALL_PATH "not found $SNAPPY_INSTALL_PATH,please build $SNAPPY_PREFIX"
# lmdb 安装路径根目录
lmdb_install_root=$LMDB_INSTALL_PATH/usr/local
exit_if_not_exist $lmdb_install_root "not found $lmdb_install_root,please build lmdb"
exit_if_not_exist $LEVELDB_INSTALL_PATH "not found $LEVELDB_INSTALL_PATH,please build $LEVELDB_PREFIX"
# opencv 配置文件(OpenCVConfig.cmake)所在路径
opencv_cmake_dir=$OPENCV_INSTALL_PATH/share/OpenCV
exit_if_not_exist $opencv_cmake_dir "not found $opencv_cmake_dir,please build $OPENCV_PREFIX"

pushd $SOURCE_ROOT/$SSD_FOLDER
clean_folder build.gcc
#mkdir_if_not_exist build.gcc
pushd build.gcc
# 指定 OpenBLAS 安装路径 参见 $caffe_source/cmake/Modules/FindOpenBLAS.cmake
export OpenBLAS_HOME=$OPENBLAS_INSTALL_PATH
# 指定 lmdb 安装路径 参见 $caffe_source/cmake/Modules/FindLMDB.cmake.cmake
export LMDB_DIR=$lmdb_install_root
# 指定 leveldb 安装路径 参见 $caffe_source/cmake/Modules/FindLevelDB.cmake.cmake
export LEVELDB_ROOT=$LEVELDB_INSTALL_PATH
# GLOG_ROOT_DIR 参见 $caffe_source/cmake/Modules/FindGlog.cmake
# GFLAGS_ROOT_DIR 参见 $caffe_source/cmake/Modules/FindGFlags.cmake
# HDF5_ROOT 参见 https://cmake.org/cmake/help/v3.8/module/FindHDF5.html
# BOOST_ROOT,Boost_NO_SYSTEM_PATHS 参见 https://cmake.org/cmake/help/v3.8/module/FindBoost.html
# SNAPPY_ROOT_DIR 参见 $caffe_source/cmake/Modules/FindSnappy.cmake
# PROTOBUF_LIBRARY,PROTOBUF_PROTOC_LIBRARY... 参见 https://cmake.org/cmake/help/v3.8/module/FindProtobuf.html
# OpenCV_DIR 参见https://cmake.org/cmake/help/v3.8/command/find_package.html
$CMAKE_EXE "$(dirs +1)" $CMAKE_VARS_DEFINE -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=$install_path \
	-DCMAKE_EXE_LINKER_FLAGS="-static-libstdc++ -static-libgcc" \
	-DGLOG_ROOT_DIR=$glog_root \
	-DGFLAGS_ROOT_DIR=$gflags_root \
	-DHDF5_ROOT=$HDF5_INSTALL_PATH \
	-DBOOST_ROOT=$BOOST_INSTALL_PATH \
	-DBoost_NO_SYSTEM_PATHS=on \
	-DSNAPPY_ROOT_DIR=$SNAPPY_INSTALL_PATH \
	-DOpenCV_DIR=$opencv_cmake_dir \
	-DPROTOBUF_LIBRARY=$protobuf_lib/libprotobuf.a \
	-DPROTOBUF_PROTOC_LIBRARY=$protobuf_lib/libprotoc.a \
	-DPROTOBUF_LITE_LIBRARY=$protobuf_lib/libprotobuf-lite.a \
	-DPROTOBUF_PROTOC_EXECUTABLE=$PROTOBUF_INSTALL_PATH/bin/protoc \
	-DPROTOBUF_INCLUDE_DIR=$PROTOBUF_INSTALL_PATH/include \
	-DCPU_ONLY=ON \
	-DBLAS=Open \
	-DBUILD_SHARED_LIBS=off \
	-DBUILD_docs=off \
	-DBUILD_python=off \
	-DBUILD_python_layer=off \
	-DUSE_LEVELDB=on \
	-DUSE_LMDB=on \
	-DUSE_OPENCV=on 
exit_on_error
remove_if_exist $install_path
make -j $MAKE_JOBS install
exit_on_error
popd
rm -fr build.gcc
popd

在脚本中,调用cmake生成Makefile时,添加了-DCMAKE_EXE_LINKER_FLAGS="-static-libstdc++ -static-libgcc"参数用于指定 将libstdc++,libgcc以静态库形式连接,然而在实际使用过程发现当指定 USE_OPENCV=on(即使用OpenCV,opencv已经预先做了静态库编译)时,编译出的caffe,用ldd查看还是会依赖libstdc++.so和libgcc.so,也就是说-static-libstdc++ -static-libgcc无效了。。。
USE_OPENCV=off时则能正常静态连接。

这个问题困扰了几天,后来通过比较<project>.dir下的link.txt(cmake生成的),发现,当USE_OPENCV=on时生成的link.txt中,自动在opencv静态库加了-lstdc++ 参数。。。
如下是caffe.bin项目link.txt(./tools/CMakeFiles/caffe.bin.dir/link.txt),太长我加了分行符:

/usr/local/bin/g++   -fPIC -Wall -Wno-sign-compare -Wno-uninitialized -O3 -DNDEBUG  -static-libstdc++ -static-libgcc -rdynamic CMakeFiles/caffe.bin.dir/caffe.cpp.o  -o caffe -Wl,-rpath,:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -Wl,--whole-archive ../lib/libcaffe.a -Wl,--no-whole-archive ../lib/libproto.a 
/home/hadoop/tmp/dl/depends/release/boost_linux_x86_64/lib/libboost_system.a 
/home/hadoop/tmp/dl/depends/release/boost_linux_x86_64/lib/libboost_thread.a 
/home/hadoop/tmp/dl/depends/release/boost_linux_x86_64/lib/libboost_filesystem.a 
/home/hadoop/tmp/dl/depends/release/boost_linux_x86_64/lib/libboost_regex.a -lpthread 
/home/hadoop/tmp/dl/depends/release/glog_linux_x86_64/lib/libglog.a 
/home/hadoop/tmp/dl/depends/release/gflags_linux_x86_64/lib/libgflags.a 
/home/hadoop/tmp/dl/depends/release/protobuf_linux_x86_64/lib64/libprotobuf.a -lpthread 
/home/hadoop/tmp/dl/depends/release/glog_linux_x86_64/lib/libglog.a 
/home/hadoop/tmp/dl/depends/release/gflags_linux_x86_64/lib/libgflags.a 
/home/hadoop/tmp/dl/depends/release/protobuf_linux_x86_64/lib64/libprotobuf.a 
/home/hadoop/tmp/dl/depends/release/hdf5_linux_x86_64/lib/libhdf5_cpp.a 
/home/hadoop/tmp/dl/depends/release/hdf5_linux_x86_64/lib/libhdf5.a 
/home/hadoop/tmp/dl/depends/release/hdf5_linux_x86_64/lib/libhdf5_hl_cpp.a 
/home/hadoop/tmp/dl/depends/release/hdf5_linux_x86_64/lib/libhdf5_hl.a /home/hadoop/tmp/dl/depends/release/hdf5_linux_x86_64/lib/libhdf5_cpp.a 
/home/hadoop/tmp/dl/depends/release/hdf5_linux_x86_64/lib/libhdf5.a 
/home/hadoop/tmp/dl/depends/release/hdf5_linux_x86_64/lib/libhdf5_hl_cpp.a 
/home/hadoop/tmp/dl/depends/release/hdf5_linux_x86_64/lib/libhdf5_hl.a 
/home/hadoop/tmp/dl/depends/release/lmdb_linux_x86_64/usr/local/lib/liblmdb.a 
/home/hadoop/tmp/dl/depends/release/leveldb_linux_x86_64/lib/libleveldb.a 
/home/hadoop/tmp/dl/depends/release/snappy_linux_x86_64/lib/libsnappy.a 
/home/hadoop/tmp/dl/depends/release/opencv_linux_x86_64/lib/libopencv_highgui.a 
/home/hadoop/tmp/dl/depends/release/opencv_linux_x86_64/share/OpenCV/3rdparty/lib/liblibjpeg.a 
/home/hadoop/tmp/dl/depends/release/opencv_linux_x86_64/share/OpenCV/3rdparty/lib/liblibpng.a 
/home/hadoop/tmp/dl/depends/release/opencv_linux_x86_64/share/OpenCV/3rdparty/lib/liblibtiff.a 
/home/hadoop/tmp/dl/depends/release/opencv_linux_x86_64/share/OpenCV/3rdparty/lib/liblibjasper.a 
/home/hadoop/tmp/dl/depends/release/opencv_linux_x86_64/share/OpenCV/3rdparty/lib/libIlmImf.a 
/home/hadoop/tmp/dl/depends/release/opencv_linux_x86_64/lib/libopencv_imgproc.a 
/home/hadoop/tmp/dl/depends/release/opencv_linux_x86_64/lib/libopencv_core.a 
/home/hadoop/tmp/dl/depends/release/opencv_linux_x86_64/share/OpenCV/3rdparty/lib/libzlib.a 
-lstdc++ -lm -lpthread -lrt 
/home/hadoop/tmp/dl/depends/release/OpenBLAS_linux_x86_64/lib/libopenblas.a 
-ldl -pthread -lrt 

就是这尾部的-lstdc++参数导致-static-libstdc++ -static-libgcc无效,尝试手工删除 -lstdc++,则编译通过,stdc++,libgcc都能静态连接进来了。于是在cmake生成Makefile后,添加了如下代码,则问题解决:

# 修改所有 link.txt 删除-lstdc++ 选项,保证静态连接libstdc++库,否则在USE_OPENCV=on的情况下,libstdc++不会静态链接
for file in $(find . -name link.txt)
do 
	echo "modifing file: $file"
	#sed -i -r "s/-lstdc\+\+/ /g" $file
done

静态编译后,ldd 查看bin下的caffe依赖关系显示如下,除了系统库之外,不再依赖任何其他动态库,文件大小也达到28MB。

[hadoop@t2-centos6 bin]$ ldd …/release/caffe-ssd_linux_x86_64/bin/caffe
linux-vdso.so.1 => (0x00007fff8fb58000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003c24600000)
librt.so.1 => /lib64/librt.so.1 (0x0000003c24e00000)
libdl.so.2 => /lib64/libdl.so.2 (0x0000003c24a00000)
libm.so.6 => /lib64/libm.so.6 (0x0000003c25200000)
libc.so.6 => /lib64/libc.so.6 (0x0000003c24200000)
/lib64/ld-linux-x86-64.so.2 (0x0000003c23e00000)

但是为什么opencv的库会导致这个问题。一直没搞明白。

本文贴出的脚本并不完整
关于caffe静态编译的完整脚本,请从从码云(gitee)获取:
https://gitee.com/l0km/caffe-static

<think>好的,用户现在问的是关于之前给出的命令中各个包的作用以及安装后的位置。首先,我需要回忆一下那个命令的组成:yum install -y gcc-c++ glibc-static gcc git make cmake libstdc++-static byacc flex wget。用户想知道这些包会下载什么内容,以及安装到哪个目录下。 首先,我要分解每个包的作用。比如gcc是GNU编译器集合,gcc-c++是C++编译器,glibc-static静态链接的C库,git是版本控制工具,make和cmake是构建工具,libstdc++-static静态C++库,byacc和flex是解析器生成器,wget是下载工具。需要逐一解释每个包的功能,以及它们通常安装的位置。 接下来,用户可能想知道这些软件包安装后存放在哪里。在RHEL系统中,使用yum安装的软件包通常会把可执行文件放在/usr/bin,库文件在/usr/lib或/usr/lib64,头文件在/usr/include,配置文件在/etc,文档在/usr/share/doc等目录下。需要指出这些标准路径,并说明每个组件可能安装的具体位置。 同时,用户可能有潜在的疑问,比如为什么要安装这些依赖包,是否会影响原有系统,或者如何确认安装成功。需要确保解释清楚每个包的作用是为了编译GCC所需的依赖,并且通过yum安装的包会遵循系统默认路径,不会干扰其他版本,尤其是之前安装的GCC 4.8.5在/usr/local下,与系统默认的/usr分开,避免冲突。 可能还需要提醒用户,使用yum安装的软件包是系统自带的版本,可能与较新的版本有差异,但在RHEL6.4中,这些包已经过测试,兼容性较好。此外,如果用户需要特定版本的软件,可能需要通过其他方式安装,但在这个命令中主要是为了获取编译GCC所需的基础工具和库。 最后,确保回答结构清晰,分点解释每个包的作用和安装位置,帮助用户全面理解命令的作用,以及后续步骤中这些工具如何被使用到。</think>以下是针对命令`yum install -y gcc-c++ glibc-static gcc git make cmake libstdc++-static byacc flex wget`的详细解析: --- ### **一、安装内容解析** 这个命令通过`yum`包管理器安装编译环境和开发工具,具体包含以下软件包: 1. **`gcc`** - **作用**:GNU C编译器(原系统自带的GCC 4.4.7版本) - **依赖文件**:C语言编译器核心文件 2. **`gcc-c++`** - **作用**:GNU C++编译器(支持C++语言编译) - **依赖文件**:C++编译器前端`g++`及相关库 3. **`glibc-static`** - **作用**:GNU C标准库的**静态链接版本**(用于生成不依赖动态库的可执行文件) 4. **`git`** - **作用**:分布式版本控制系统(用于从仓库拉取代码) 5. **`make`** - **作用**:自动化构建工具(解析`Makefile`执行编译流程) 6. **`cmake`** - **作用**:跨平台构建工具(生成`Makefile`或其他构建脚本) 7. **`libstdc++-static`** - **作用**:GNU C++标准库的**静态链接版本**(用于C++程序的静态编译) 8. **`byacc`** - **作用**:Berkeley YACC语法分析器生成器(编译需要语法解析的代码) 9. **`flex`** - **作用**:词法分析器生成器(与`byacc`配合使用) 10. **`wget`** - **作用**:命令行下载工具(用于获取源码包等资源) --- ### **二、安装目录结构** 通过`yum`安装的软件包会遵循RHEL系统的标准路径布局: | 组件类型 | 典型安装路径 | 示例文件/目录 | |--------------------|----------------------------------|------------------------------| | **可执行文件** | `/usr/bin` | `gcc`, `g++`, `git`, `make` | | **静态库文件** | `/usr/lib` 或 `/usr/lib64` | `libc.a`, `libstdc++.a` | | **动态库文件** | `/usr/lib` 或 `/usr/lib64` | `libc.so`, `libstdc++.so` | | **头文件** | `/usr/include` | `stdio.h`, `stdlib.h` | | **配置文件** | `/etc` | `ld.so.conf`, `gitconfig` | | **文档与手册** | `/usr/share/doc` 或 `/usr/share/man` | `gcc-doc`, `make-manual` | --- ### **三、验证安装结果** 1. **检查可执行文件路径**: ```bash which gcc # 输出应为 /usr/bin/gcc which make # 输出应为 /usr/bin/make ``` 2. **查看软件版本**: ```bash gcc --version # 显示系统原版GCC 4.4.7 git --version # 显示已安装的git版本 ``` 3. **检查静态库文件**: ```bash ls /usr/lib/libc.a # 验证glibc-static是否安装 ls /usr/lib/libstdc++.a # 验证libstdc++-static是否安装 ``` --- ### **四、与原GCC4.8.5的关系** - **路径隔离**:通过`yum`安装的GCC 4.4.7位于`/usr/bin`,而手动编译的GCC 4.8.5安装在`/usr/local/gcc-4.8.5`,两者互不干扰 - **依赖关系**:编译GCC 4.8.5时需要这些工具链(如`make`, `gcc`等)和静态库(如`glibc-static`)的支持 --- ### **注意事项** 1. **不覆盖原系统组件**:此操作仅安装基础编译工具,不会修改系统默认的GCC 4.4.7 2. **依赖库兼容性**:若后续使用GCC 4.8.5编译程序,需注意其动态库路径与系统版本的隔离(通过`LD_LIBRARY_PATH`控制)
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

10km

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

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

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

打赏作者

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

抵扣说明:

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

余额充值