加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

如何使用docker中的静态opencv库编译c应用程序

发布时间:2020-12-16 03:35:14 所属栏目:安全 来源:网络整理
导读:我正在用C构建我的第一个基于OpenCV的应用程序.我的目标是构建一个中间docker镜像,它可以静态编译应用程序,以便它可以在生成的较小图像中独立运行.我愿意在此步骤中使用任何泊坞窗图像,但只是为了让您可以看到我拥有的内容,这里是重现整个环境的dockerfile:

我正在用C构建我的第一个基于OpenCV的应用程序.我的目标是构建一个中间docker镜像,它可以静态编译应用程序,以便它可以在生成的较小图像中独立运行.我愿意在此步骤中使用任何泊坞窗图像,但只是为了让您可以看到我拥有的内容,这里是重现整个环境的dockerfile:

FROM ubuntu:18.04 as compiler

ENV OPENCV_VERSION='3.4.2' DEBIAN_FRONTEND=noninteractive

RUN apt-get -y update && 
    apt-get -y upgrade && 
    apt-get -y dist-upgrade && 
    apt-get -y autoremove && 
    apt-get install -y build-essential cmake 
RUN apt-get install -y qt5-default libvtk6-dev
RUN apt-get install -y zlib1g-dev libjpeg-dev libwebp-dev libpng-dev libtiff5-dev libopenexr-dev libgdal-dev
RUN apt-get install -y libdc1394-22-dev libavcodec-dev libavformat-dev libswscale-dev libtheora-dev libvorbis-dev libxvidcore-dev libx264-dev yasm libopencore-amrnb-dev libopencore-amrwb-dev libv4l-dev libxine2-dev
RUN apt-get install -y unzip wget
RUN wget --progress=dot:giga https://github.com/opencv/opencv/archive/${OPENCV_VERSION}.zip && 
    unzip -q ${OPENCV_VERSION}.zip && 
    rm ${OPENCV_VERSION}.zip && 
    mv opencv-${OPENCV_VERSION} OpenCV && 
    cd OpenCV && 
    mkdir build && 
    cd build && 
    cmake  
        -D BUILD_SHARED_LIBS=OFF  
        -D WITH_QT=ON 
        -D WITH_OPENGL=ON  
        -D FORCE_VTK=ON 
        -D WITH_TBB=ON  
        -D WITH_GDAL=ON  
        -D WITH_XINE=ON  
        -D BUILD_EXAMPLES=OFF 
        -D ENABLE_PRECOMPILED_HEADERS=OFF 
        -D BUILD_DOCS=OFF 
        -D BUILD_PERF_TESTS=OFF 
        -D BUILD_TESTS=OFF 
        -D BUILD_opencv_apps=OFF 
        .. && 
    make -j4 && 
    make install && 
    ldconfig

COPY compile-test.cpp compile-test.cpp

RUN g++ -std=c++11 -static compile-test.cpp -o /app $(pkg-config --cflags --libs opencv)

我现在可以使用dyanmic libs编译我的c应用程序,但这会创建一个庞大的docker镜像,我真的希望能够以最小的大小构建独立的二进制文件以进行分发.

正如您所看到的,我正在从源代码编译OpenCV,包括标志BUILD_SHARED_LIBS = OFF,以确保我获得.a静态库,而不是.so动态库.我从highly recommended build script中得到了一个提示,并修改它以便使用docker省略一些python的东西,因为我正在使用c.

因为我在实际应用程序中遇到了很多麻烦,所以我继续创建了一个更简单的应用程序,它在编译时也会爆炸.我相信这与包含的cflags和libs有关.这个问题目前无法理解.当我在编译命令中调整单个包含时,我会发现大量的错误.这是我正在尝试编译的最简单的应用程序.它确实没有做任何事情,但确实包含了一个lib.

#include "opencv2/imgcodecs.hpp"
using namespace cv; 
Mat img;

int main( int argc,char** argv ) {
  img = cv::imread( argv[1],IMREAD_COLOR );
}

然后我尝试编译这样:

g++ -std=c++11 -static compile-test.cpp -o /app $(pkg-config --cflags --libs opencv)

它最终会出现一堆错误太久而无法在此完全粘贴.

//usr/local/lib/libopencv_imgcodecs.a(grfmt_jpeg.cpp.o): In function `cv::JpegEncoder::write(cv::Mat const&,std::vector

我已经尝试过的一些事情

>开始谷歌每个看似独特的编译错误,并在我的编译代码的末尾添加相关的标志.
>重新排序一些包含标志,但有太多可以有效地做到这一点
>使用opencv-dev软件包而不是自己编译,但似乎你不能这样做并期望使用静态库.

最佳答案
经过大量的实验,我终于有了一些工作!这个Dockerfile中有一些问题已得到解决.为了重现这一点,请创建一个包含以下内容的Dockerfile,并使用上面问题中的简单代码在同一文件夹中创建另一个名为app.cpp的文件.

我将解释下面的问题:

FROM alpine:3.8 as compiler

RUN echo -e '@edgunity http://nl.alpinelinux.org/alpine/edge/community 
    @edge http://nl.alpinelinux.org/alpine/edge/main 
    @testing http://nl.alpinelinux.org/alpine/edge/testing 
    @community http://dl-cdn.alpinelinux.org/alpine/edge/community' 
    >> /etc/apk/repositories

RUN apk add --update --no-cache 
      build-base 
      openblas-dev 
      unzip 
      wget 
      cmake 
      g++ 
      libjpeg  
      libjpeg-turbo-dev 
      libpng-dev 
      jasper-dev 
      tiff-dev 
      libwebp-dev 
      clang-dev 
      linux-headers 

ENV CC /usr/bin/clang
ENV CXX /usr/bin/g++
ENV OPENCV_VERSION='3.4.2' DEBIAN_FRONTEND=noninteractive

RUN mkdir /opt && cd /opt && 
  wget https://github.com/opencv/opencv/archive/${OPENCV_VERSION}.zip && 
  unzip ${OPENCV_VERSION}.zip && 
  rm -rf ${OPENCV_VERSION}.zip

RUN mkdir -p /opt/opencv-${OPENCV_VERSION}/build && 
  cd /opt/opencv-${OPENCV_VERSION}/build && 
  cmake 
    -D BUILD_DOCS=OFF 
    -D BUILD_EXAMPLES=OFF 
    -D BUILD_opencv_apps=OFF 
    -D BUILD_opencv_python2=OFF 
    -D BUILD_opencv_python3=OFF 
    -D BUILD_PERF_TESTS=OFF 
    -D BUILD_SHARED_LIBS=OFF  
    -D BUILD_TESTS=OFF 
    -D CMAKE_BUILD_TYPE=RELEASE 
    -D ENABLE_PRECOMPILED_HEADERS=OFF 
    -D FORCE_VTK=OFF 
    -D WITH_FFMPEG=OFF 
    -D WITH_GDAL=OFF  
    -D WITH_IPP=OFF 
    -D WITH_OPENEXR=OFF 
    -D WITH_OPENGL=OFF  
    -D WITH_QT=OFF 
    -D WITH_TBB=OFF  
    -D WITH_XINE=OFF  
    -D BUILD_JPEG=ON  
    -D BUILD_TIFF=ON 
    -D BUILD_PNG=ON 
  .. && 
  make -j$(nproc) && 
  make install && 
  rm -rf /opt/opencv-${OPENCV_VERSION}

RUN wget --progress=dot:giga https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.0.0-linux-x86-64.tar.gz && 
    pwd && 
    tar -xzf libwebp-1.0.0-linux-x86-64.tar.gz && 
    mv /libwebp-1.0.0-linux-x86-64/lib/libwebp.a /usr/lib && 
    rm -rf /libwebp*

RUN wget --progress=dot:giga http://www.ece.uvic.ca/~frodo/jasper/software/jasper-2.0.10.tar.gz && 
    tar -xzf jasper-2.0.10.tar.gz && 
    cd jasper-2.0.10 && 
    mkdir BUILD && 
    cd BUILD && 
    cmake -DCMAKE_INSTALL_PREFIX=/usr    
      -DCMAKE_BUILD_TYPE=Release     
      -DCMAKE_SKIP_INSTALL_RPATH=YES 
      -DCMAKE_INSTALL_DOCDIR=/usr/share/doc/jasper-2.0.10 
      -DJAS_ENABLE_SHARED=FALSE 
      ..  && 
    make install && 
    rm -rf /jasper-2.0.10*

ENV PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig:/usr/lib/pkgconfig

COPY app.cpp app.cpp

RUN g++ -Wl,-Bstatic -static-libgcc -std=c++11 
    app.cpp  
    -o /app 
    $(pkg-config --cflags --libs -static opencv) 
    -lgfortran -lquadmath

FROM alpine    
COPY --from=compiler /app /bin/app

问题

链接

确实存在需要链接但不存在的文件,有两个原因:

> pkg-config命令应该发出所有必要的编译标志,但在我之前的尝试中,我没有将-static标志包含在pkg-config中.添加-static标志时,请确保链接所需的额外包.我看到一些人遇到了这个问题的解决方案,添加了额外的标志,如-pthread,但我发现-static标志为我做了这个,所以更可取.
> ld:找不到-lgcc_s错误.这似乎是通过向g添加-static-libgcc标志来解决的.其中一些对我来说仍然是一个谜.

缺少静态库

我希望将两个库作为静态包含在内,需要从apk以外的其他来源获取.这些是libjasper和libwebp.上面有构建步骤,可以根据需要获取和构建这些步骤,并将资源复制到所需的位置.

更多缺失的链接

由于原因我还不能解释pkg-config没有提供最后两个必要的标志.那些是-lgfortran和-lquadmath.

关于此解决方案的说明

我切换到alpine linux,只是因为我读过有些人用它取得了成功,我确信Ubuntu也可以这样做.它确实产生了一个小得多的图像,所以我喜欢这样.对于中间图像,这大约是900mb,虽然很大,但比1.9GB的Ubuntu图像要小得多.

实际生成的图像大约为44mb,包括所有静态链接的OpenCV库.对于那些需要小型docker镜像来运行单个C bin的人来说,这似乎是一个很好的解决方案.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读