多平台编译OpenCV 4.6.0源码操作步骤

多平台包括Windows 10、Linux(Ubuntu 16.04、Ubuntu 18.04)、MacOS、Android、iOS、Wasm(WebAssembly)、嵌入式设备,以及它们不同的配置,如Ubuntu上不同的gcc版本,MacOS上不同的xcode版本。
将不同平台的编译命令全部写在一个shell脚本build.sh里,此脚本与OpenCV的主CMakeLists.txt在同一个目录下,外层通过输入一个参数来控制编译哪个平台哪个配置的库,如linux-x86_64-gcc5_4,命名组成方式为:platform-arch-toolchain,platform可为winodws、linux、osx(即MacOS)、andorid、ios、wasm;arch可为x86、x86_64、armv7、aarch64(arm64);toolchain可为gcc5.4、gcc8.2、clang-r23b、vs2015等。
编译前的说明:
(1).除特殊平台如Wasm、iOS只有静态库外,其它平台既包括动态库也包括静态库。
(2).除Windows外,其它平台只有Release库。
(3).为保证调用OpenCV接口时各平台结果的一致性,这里图像编解码库如libpng等不使用系统库中的,均使用OpenCV中自带的版本即3rdparty目录下的。
(4).为保证各平台结果一致(精度对齐),也关闭了OpenCV中的加速选项,如SIMD、OpenMP等,尽量只走普通C++实现部分。
(5).关闭了多线程:即设置WITH_PTHREADS_PF为OFF,设置OPENCV_DISABLE_THREAD_SUPPORT为ON后,当通过VideoCapture读取视频文件时,会有Warning:Corrupt JPEG data: premature end of data segment
(6).有些OpenCV的选项在多平台上是通用的,这里将它们放在了一起,如下:其中将外部的输入参数传给了PLATFORM_ARCH_TOOLCHAIN,用于不同的平台在CMakeList.txt中做的差异处理,设置OPENCV_DISABLE_THREAD_SUPPORT为ON,将不会编译objdetect模块

common_options="-DCMAKE_BUILD_TYPE=RELEASE \
    -DPLATFORM_ARCH_TOOLCHAIN=$1 \
    -DCMAKE_CXX_FLAGS=-fPIC \
    -DCMAKE_C_FLAGS=-fPIC \
    -DBUILD_EXAMPLES=OFF \
    -DBUILD_opencv_apps=OFF \
    -DBUILD_PERF_TESTS=OFF \
    -DBUILD_TESTS=OFF \
    -DBUILD_JAVA=OFF \
    -DBUILD_OBJC=OFF \
    -DBUILD_KOTLIN_EXTENSIONS=OFF \
    -DBUILD_opencv_gapi=OFF \
    -DOPENCV_FORCE_3RDPARTY_BUILD=ON \
    -DENABLE_PIC=ON \
    -DWITH_1394=OFF \
    -DWITH_EIGEN=OFF \
    -DWITH_ARAVIS=OFF \
    -DWITH_ARITH_DEC=ON \
    -DWITH_ARITH_ENC=ON \
    -DWITH_CLP=OFF \
    -DWITH_CUBLAS=OFF \
    -DWITH_CUDA=OFF \
    -DWITH_CUFFT=OFF \
    -DWITH_FFMPEG=OFF \
    -DWITH_GSTREAMER=OFF \
    -DWITH_GSTREAMER_0_10=OFF \
    -DWITH_HALIDE=OFF \
    -DWITH_HPX=OFF \
    -DWITH_IMGCODEC_HDR=ON \
    -DWITH_IMGCODEC_PXM=ON \
    -DWITH_IMGCODEC_SUNRASTER=ON \
    -DWITH_INF_ENGINE=OFF \
    -DWITH_IPP=OFF \
    -DWITH_ITT=OFF \
    -DWITH_OPENVINO=OFF \
    -DWITH_JASPER=ON \
    -DWITH_JPEG=ON \
    -DWITH_PNG=ON \
    -DWITH_TIFF=ON \
    -DWITH_WEBP=ON \
    -DWITH_LAPACK=OFF \
    -DWITH_PTHREADS_PF=OFF \
    -DOPENCV_DISABLE_THREAD_SUPPORT=ON \
    -DWITH_LIBREALSENSE=OFF \
    -DWITH_MSMF_DXVA=OFF \
    -DWITH_NVCUVID=OFF \
    -DWITH_OPENCL=OFF \
    -DWITH_OPENCLAMDBLAS=OFF \
    -DWITH_OPENCLAMDFFT=OFF \
    -DWITH_OPENCL_SVM=OFF \
    -DWITH_OPENCL_D3D11_NV=OFF \
    -DWITH_VA=OFF \
    -DWITH_VA_INTEL=OFF \
    -DWITH_OPENEXR=OFF \
    -DWITH_OPENGL=OFF \
    -DWITH_OPENMP=OFF \
    -DWITH_OPENNNI=OFF \
    -DWITH_OPENNNI2=OFF \
    -DWITH_OPENVX=OFF \
    -DWITH_PROTOBUF=OFF \
    -DWITH_PVAPI=OFF \
    -DWITH_QT=OFF \
    -DWITH_QUIRC=OFF \
    -DWITH_TBB=OFF \
    -DWITH_VULKAN=OFF \
    -DWITH_XIMEA=OFF \
    -DWITH_VTK=OFF \
    -DWITH_CPUFEATURES=OFF \
    -DENABLE_NEON=OFF \
    -DCPU_BASELINE=OFF \
    -DCV_ENABLE_INTRINSICS=OFF \
    -DCV_DISABLE_OPTIMIZATION=ON \
    -DINSTALL_C_EXAMPLES=OFF \
    -DINSTALL_PYTHON_EXAMPLES=OFF"

(7).因为编译的既有动态库又有静态库,这里定义了两个变量,如下:编译完的库存放在与build.sh同一目录下,动态库目录结构为install/$1/${dir_name_dynamic},静态库目录结构为install/$1/${dir_name_static}

dir_name_dynamic="shared"
dir_name_static="static"
toolchains_path="/usr/local/toolchains"
  1. Linux:Ubuntu 16.04、Ubuntu 18.04
    调整源码:
    (1).因为是在linux 64位机上编译linux x86的库,调整主CMakeLists.txt文件,对CMAKE_C_FLAGS和CMAKE_CXX_FLAGS追加-m32选项。
    (2).用海思arm-himix100-linux工具链编译时,需调整主CMakeLists.txt文件,增加一个变量:add_definitions(-DLINUX_ARMV7_HIMIX100=1),此变量应用在后面介绍的extend_std_funcs.hpp文件中,否则编译时会error,类似于android gcc,如:error: ‘cbrt’ is not a member of ‘std’。因为在海思arm-himix100-linux工具链中并没有找到仅在此工具链中适用的预定义宏,因此增加了LINUX_ARMV7_HIMIX100。在后面项目中使用此opencv库时,也需要在那个项目的CMakeLists.txt中添加:add_definitions(-DLINUX_ARMV7_HIMIX100=1)
    (3).用海思arm-himix200-linux工具链编译时,需调整主CMakeLists.txt文件,增加一个变量:add_definitions(-DLINUX_ARMV7_HIMIX200=1),此变量在modules/core/include/opencv2/core/detail/exception_ptr.hpp中使用,当定义此变量时,强制添加#undef CV__EXCEPTION_PTR,否则编译库时会报error,如error: ‘std::exception_ptr’ has not been declared。因为在海思arm-himix200-linux工具链中并没有找到仅在此工具链中适用的预定义宏,因此增加了LINUX_ARMV7_HIMIX200。在后面项目中使用此opencv库时,也需要在那个项目的CMakeLists.txt中添加:add_definitions(-DLINUX_ARMV7_HIMIX200=1)
    (4).使用QNX工具链编译时,在modules/calib3d/src/usac.hpp中,添加宏定义,如下,否则会报error,如:error: ‘M_SQRT2’ was not declared in this scope
#ifdef __QNX__
#define M_SQRT2     1.41421356237309504880  /* sqrt(2) */
#define M_PI        3.14159265358979323846  /* pi */
#endif

编译:

(1).编译linux-x86_64-gcc系列,如linux-x86_64-gcc5_4,则编译命令如下:

if [ $1 == "linux-x86_64-gcc5_4" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=${toolchains_path}/gcc-5.4/bin/gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/gcc-5.4/bin/g++ \
        -DBUILD_SHARED_LIBS=ON \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=${toolchains_path}/gcc-5.4/bin/gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/gcc-5.4/bin/g++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(2).编译linux-x86-gcc4_9,编译命令如下:

elif [ $1 == "linux-x86-gcc4_9" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=/usr/bin/gcc-4.9 \
        -DCMAKE_CXX_COMPILER=/usr/bin/g++-4.9 \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=/usr/bin/gcc-4.9 \
        -DCMAKE_CXX_COMPILER=/usr/bin/g++-4.9 \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(3).使用海思的工具链arm-himix100-linux,编译命令如下:

elif [ $1 == "linux-armv7-himix100" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=${toolchains_path}/hisi-linux/x86-arm/arm-himix100-linux/bin/arm-himix100-linux-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/hisi-linux/x86-arm/arm-himix100-linux/bin/arm-himix100-linux-g++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=${toolchains_path}/hisi-linux/x86-arm/arm-himix100-linux/bin/arm-himix100-linux-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/hisi-linux/x86-arm/arm-himix100-linux/bin/arm-himix100-linux-g++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(4).使用海思的工具链arm-himix200-linux,编译命令如下:

elif [ $1 == "linux-armv7-himix200" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=${toolchains_path}/hisi-linux/x86-arm/arm-himix200-linux/bin/arm-himix200-linux-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/hisi-linux/x86-arm/arm-himix200-linux/bin/arm-himix200-linux-g++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=${toolchains_path}/hisi-linux/x86-arm/arm-himix200-linux/bin/arm-himix200-linux-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/hisi-linux/x86-arm/arm-himix200-linux/bin/arm-himix200-linux-g++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(5).使用海思的工具链aarch64-hi3559a-linux,编译命令如下:关闭了webp,否则会有error: “internal compiler erro”错误,解决此问题可能需要升级gcc版本

elif [ $1 == "linux-aarch64-hi3559a" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=${toolchains_path}/hisi-linux/aarch64-hi3559a-linux/bin/aarch64-linux-gnu-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/hisi-linux/aarch64-hi3559a-linux/bin/aarch64-linux-gnu-g++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_GTK=OFF \
        -DWITH_WEBP=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=${toolchains_path}/hisi-linux/aarch64-hi3559a-linux/bin/aarch64-linux-gnu-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/hisi-linux/aarch64-hi3559a-linux/bin/aarch64-linux-gnu-g++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_GTK=OFF \
        -DWITH_WEBP=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(6).使用QNX工具链,编译命令如下:编译动态库时关闭OPENCV_ENABLE_MEMALIGN,关闭静态库时关闭OPENCV_ENABLE_MEMALIGN和WITH_ADE

elif [ $1 == "linux-aarch64-qnx" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    source ${toolchains_path}/qnx700/qnxsdp-env.sh
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=${toolchains_path}/qnx700/host/linux/x86_64/usr/bin/aarch64-unknown-nto-qnx7.0.0-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/qnx700/host/linux/x86_64/usr/bin/aarch64-unknown-nto-qnx7.0.0-g++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_GTK=OFF \
        -DOPENCV_ENABLE_MEMALIGN=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    source ${toolchains_path}/qnx700/qnxsdp-env.sh
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=${toolchains_path}/qnx700/host/linux/x86_64/usr/bin/aarch64-unknown-nto-qnx7.0.0-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/qnx700/host/linux/x86_64/usr/bin/aarch64-unknown-nto-qnx7.0.0-g++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_GTK=OFF \
        -DOPENCV_ENABLE_MEMALIGN=OFF \
        -DWITH_ADE=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install
  1. Android:在Ubuntu 16.04上交叉编译

调整源码:

(1).调整3rdparty/libpng/pngpriv.h:在第137行增加:#define PNG_ARM_NEON_OPT 0,强制关闭NEON,否则在编译imgcodecs模块时会报undefined symbol的error,如ld: error: undefined symbol: png_riffle_palette_neon,这是因为我们前面在编译OpenCV时设置关闭了加速。

(2).调整cmake/OpenCVUtils.cmake:增加函数modify_android_link_deps,并在函数ocv_target_link_libraries内增加对modify_android_link_deps的调用:否则在编译android时会查找rt库,错误信息如下:ld: error: unable to find library -lrt,但是在android上是不需要rt库,这里通过判断是不是编译的android的库,若是,则将link_deps中的rt替换为log,log库在android是需要的

function(modify_android_link_deps link_deps)
    set(new_link_deps "")
    foreach(dep ${${link_deps}})
        if("${dep}" STREQUAL "rt")
            list(APPEND new_link_deps "log")
        else()
            list(APPEND new_link_deps "${dep}")
        endif()
    endforeach()
    set(${link_deps} ${new_link_deps} PARENT_SCOPE)
endfunction()

function(ocv_target_link_libraries target)
    set(LINK_DEPS ${ARGN})
    string(FIND ${PLATFORM_ARCH_TOOLCHAIN} "android" compare_var)
    if(${compare_var} GREATER_EQUAL 0)
        modify_android_link_deps(LINK_DEPS)
    endif()
    _ocv_fix_target(target)
    set(LINK_MODE "PRIVATE")
    # ......

endfunction()

(3).使用gcc而不是clang编译android库时,会报一些error,如error: ‘cbrt’ is not a member of ‘std’类似错误,这是因为android gcc缺少一些std函数的实现,这里新增加一个modules/core/include/opencv2/core/extend_std_funcs.hpp文件,仅用于实现满足在android gcc下缺少的这些std函数,并将此函数在当前目录的base.hpp文件中include它

#ifndef EXTEND_STD_FUNCS_HPP
#define EXTEND_STD_FUNCS_HPP

#if (defined(__ANDROID__) && defined(__GNUC__) && !defined(__clang__)) || defined(LINUX_ARMV7_HIMIX100)

#include
#include
#include
#include

namespace std {

#if defined(__arm__) || defined(__i386__)
inline int sign(double val)
{
    return (double(0) < val) - (val < double(0));
}

inline double cbrt(double x)
{
    if (sign(x) == 0) return 0.;
    return sign(x) > 0 ? std::pow(x, double(1/3.)) : -std::pow(std::fabs(x), double(1/3.));
}

inline double copysign(double mag, double sgn)
{
    if (sign(sgn) == 0) return mag;
    return sign(sgn) > 0 ? std::fabs(mag) : -std::fabs(mag);
}
#endif

#if (defined(__ANDROID__) && defined(__GNUC__) && !defined(__clang__))
inline unsigned long long stoull(const std::string& str, std::size_t* pos = nullptr, int base = 10)
{
    (void)(pos);
    char* pEnd = nullptr;
    return strtoull(str.data(), &pEnd, base);
}

inline std::string to_string(int value)
{
    std::ostringstream os;
    os << value ;
    return os.str();
}
#endif

} // namespace std

#endif

#endif // EXTEND_STD_FUNCS_HPP

(4).编译android x86 gcc时,调整主CMakeLists.txt文件,对CMAKE_C_FLAGS和CMAKE_CXX_FLAGS追加-m32选项。

(5).编译android x86 clang时,调整主CMakeLists.txt文件,对CMAKE_C_FLAGS和CMAKE_CXX_FLAGS追加-m32选项。

编译:

(1).编译android-armv7-clang系列,如andorid-armv7-clang-r23b,则编译命令如下:

elif [ $1 == "android-armv7-clang-r23b" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="armeabi-v7a" \
        -DANDROID_ARM_MODE="arm" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="clang" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="armeabi-v7a" \
        -DANDROID_ARM_MODE="arm" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="clang" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(2).编译android-aarch64-clang系列,如android-aarch64-clang-r23b,则编译命令如下:

elif [ $1 == "android-aarch64-clang-r23b" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="arm64-v8a" \
        -DANDROID_ARM_MODE="arm64" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="clang" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="arm64-v8a" \
        -DANDROID_ARM_MODE="arm64" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="clang" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(3).编译android-x86-clang系列,如android-x86-clang-r23b,则编译命令如下:

elif [ $1 == "android-x86-clang-r23b" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="x86" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="clang" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/i686-linux-android21-clang \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/i686-linux-android21-clang++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="x86" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="clang" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/i686-linux-android21-clang \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/i686-linux-android21-clang++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(4).编译android-x86_64-clang系列,如android-x86_64-clang-r23b,则编译命令如下:

elif [ $1 == "android-x86_64-clang-r23b" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="x86_64" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="clang" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/x86_64-linux-android21-clang \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/x86_64-linux-android21-clang++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="x86_64" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="clang" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/x86_64-linux-android21-clang \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r23b/clang/prebuilt/linux-x86_64/bin/x86_64-linux-android21-clang++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(5).编译android-armv7-gcc-r14b,编译命令如下:

elif [ $1 == "android-armv7-gcc-r14b" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="armeabi-v7a" \
        -DANDROID_ARM_MODE="arm" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="gcc" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-armv7/bin/arm-linux-androideabi-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-armv7/bin/arm-linux-androideabi-g++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="armeabi-v7a" \
        -DANDROID_ARM_MODE="arm" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="gcc" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-armv7/bin/arm-linux-androideabi-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-armv7/bin/arm-linux-androideabi-g++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(6).编译android-aarch64-gcc-r14b,编译命令如下:

elif [ $1 == "android-aarch64-gcc-r14b" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="arm64-v8a" \
        -DANDROID_ARM_MODE="arm64" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="gcc" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-aarch64/bin/aarch64-linux-android-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-aarch64/bin/aarch64-linux-android-g++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="arm64-v8a" \
        -DANDROID_ARM_MODE="arm64" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="gcc" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-aarch64/bin/aarch64-linux-android-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-aarch64/bin/aarch64-linux-android-g++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(7).编译android-x86-gcc-r14b,编译命令如下:

elif [ $1 == "android-x86-gcc-r14b" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="x86" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="gcc" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-x86/bin/i686-linux-android-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-x86/bin/i686-linux-android-g++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="x86" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="gcc" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-x86/bin/i686-linux-android-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-x86/bin/i686-linux-android-g++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(8).编译android-x86_64-gcc-r14b,编译命令如下:

elif [ $1 == "android-x86_64-gcc-r14b" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="x86_64" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="gcc" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-x86_64/bin/x86_64-linux-android-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-x86_64/bin/x86_64-linux-android-g++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DANDROID_ABI="x86_64" \
        -DANDROID_PLATFORM="android-21" \
        -DANDROID_TOOLCHAIN="gcc" \
        -DCPU_BASELINE_DISABLE=ON \
        -DCMAKE_C_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-x86_64/bin/x86_64-linux-android-gcc \
        -DCMAKE_CXX_COMPILER=${toolchains_path}/android-ndk-r14b/gcc/android-21/android-x86_64/bin/x86_64-linux-android-g++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_GTK=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install
  1. Wasm:在Ubuntu 16.04上交叉编译

通用项定义:

wasm_common_options="--cmake_option=-DCMAKE_BUILD_TYPE=RELEASE \
    --cmake_option=-DCMAKE_CXX_FLAGS=-fPIC \
    --cmake_option=-DCMAKE_C_FLAGS=-fPIC \
    --cmake_option=-DPLATFORM_ARCH_TOOLCHAIN=$1 \
    --cmake_option=-DBUILD_SHARED_LIBS=OFF \
    --cmake_option=-DBUILD_PROTOBUF=OFF \
    --cmake_option=-DBUILD_ZLIB=ON \
    --cmake_option=-DBUILD_opencv_apps=OFF \
    --cmake_option=-DBUILD_opencv_gapi=OFF \
    --cmake_option=-DBUILD_opencv_highgui=ON \
    --cmake_option=-DBUILD_opencv_imgcodecs=ON \
    --cmake_option=-DBUILD_opencv_photo=ON \
    --cmake_option=-DBUILD_opencv_stitching=ON \
    --cmake_option=-DBUILD_opencv_dnn=OFF \
    --cmake_option=-DBUILD_opencv_objdetect=OFF \
    --cmake_option=-DBUILD_opencv_ts=OFF \
    --cmake_option=-DBUILD_opencv_ml=ON \
    --cmake_option=-DBUILD_opencv_videoio=ON \
    --cmake_option=-DOPENCV_FORCE_3RDPARTY_BUILD=ON \
    --cmake_option=-DBUILD_JASPER=ON \
    --cmake_option=-DBUILD_JPEG=ON \
    --cmake_option=-DBUILD_PNG=ON \
    --cmake_option=-DBUILD_TIFF=ON \
    --cmake_option=-DBUILD_WEBP=ON"

依赖项:本机需安装emcmake;本机需安装python3,版本要求>=3.2

调整源码:

(1).编译x86时,调整主CMakeLists.txt文件,对CMAKE_C_FLAGS和CMAKE_CXX_FLAGS追加-m32选项。

编译:

(1).编译wasm-x86,编译命令如下:

elif [ $1 == "wasm-x86" ]; then
    echo "#### build static libraries ..."
    rm -rf *
    TARGET_COMPILER_VERSION=1.39.20
    emcmake \
        python3 ../platforms/js/build_js.py . \
        --emscripten_dir=${toolchains_path}/emsdk-${TARGET_COMPILER_VERSION}/upstream/emscripten/ \
        ${wasm_common_options} \
        --cmake_option="-DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static}"
    emmake make install

(2).编译wasm-x86_64,编译命令如下:

elif [ $1 == "wasm-x86_64" ]; then
    echo "#### build static libraries ..."
    rm -rf *
    TARGET_COMPILER_VERSION=1.39.20
    emcmake \
        python3 ../platforms/js/build_js.py . \
        --emscripten_dir=${toolchains_path}/emsdk-${TARGET_COMPILER_VERSION}/upstream/emscripten/ \
        ${wasm_common_options} \
        --cmake_option="-DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static}"
    emmake make install
  1. Windows 10:

cmake/OpenCVCRTLinkage.cmake中,默认动态库是MD,静态库是MT,这里作了调整,无论是动态库还是静态库都可以指定是MD还是MT。为了让windows 10编译的库可以在windows xp上运行,这里指定了v140_xp选项。

基于windows的通用项定义如下:

msvc_mt_common_options="-DCMAKE_CXX_FLAGS=/DWIN32 /D_WINDOWS /W3 /GR /EHsc \
    -DCMAKE_CXX_FLAGS_DEBUG=/MTd /Zi /Ob0 /Od /RTC1 \
    -DCMAKE_CXX_FLAGS_RELEASE=/MT /O2 /Ob2 /DNDEBUG \
    -DCMAKE_CXX_FLAGS_MINSIZEREL=/MT /O1 /Ob1 /DNDEBUG \
    -DCMAKE_CXX_FLAGS_RELWITHDEBINFO=/MT /Zi /O2 /Ob1 /DNDEBUG \
    -DCMAKE_C_FLAGS=/DWIN32 /D_WINDOWS /W3 \
    -DCMAKE_C_FLAGS_DEBUG=/MTd /Zi /Ob0 /Od /RTC1 \
    -DCMAKE_C_FLAGS_RELEASE=/MT /O2 /Ob2 /DNDEBUG \
    -DCMAKE_C_FLAGS_MINSIZEREL=/MT /O1 /Ob1 /DNDEBUG \
    -DCMAKE_C_FLAGS_RELWITHDEBINFO=/MT /Zi /O2 /Ob1 /DNDEBUG \
    -DWITH_ADE=OFF \
    -DWITH_MSMF=OFF \
    -DBUILD_opencv_dnn=OFF"

msvc_md_common_options="-DCMAKE_CXX_FLAGS=/DWIN32 /D_WINDOWS /W3 /GR /EHsc \
    -DCMAKE_CXX_FLAGS_DEBUG=/MDd /Zi /Ob0 /Od /RTC1 \
    -DCMAKE_CXX_FLAGS_RELEASE=/MD /O2 /Ob2 /DNDEBUG \
    -DCMAKE_CXX_FLAGS_MINSIZEREL=/MD /O1 /Ob1 /DNDEBUG \
    -DCMAKE_CXX_FLAGS_RELWITHDEBINFO=/MD /Zi /O2 /Ob1 /DNDEBUG \
    -DCMAKE_C_FLAGS=/DWIN32 /D_WINDOWS /W3 \
    -DCMAKE_C_FLAGS_DEBUG=/MDd /Zi /Ob0 /Od /RTC1 \
    -DCMAKE_C_FLAGS_RELEASE=/MD /O2 /Ob2 /DNDEBUG \
    -DCMAKE_C_FLAGS_MINSIZEREL=/MD /O1 /Ob1 /DNDEBUG \
    -DCMAKE_C_FLAGS_RELWITHDEBINFO=/MD /Zi /O2 /Ob1 /DNDEBUG \
    -DWITH_ADE=OFF \
    -DWITH_MSMF=OFF \
    -DBUILD_opencv_dnn=OFF"

调整源码:

(1).关闭python的支持,否则会报error:ImportError: No module named numpy.distutils,调整主CMakeLists.txt,将

--- Python Support ---
if(NOT IOS)
  include(cmake/OpenCVDetectPython.cmake)
endif()

调整为:

--- Python Support ---
if((NOT IOS) AND (NOT CMAKE_GENERATOR MATCHES "Visual Studio"))
  include(cmake/OpenCVDetectPython.cmake)
endif()

(2).由于增加了v140_xp选项,需关闭FLS的支持,否则会报error:fatal error C1083: Cannot open include file: ‘fibersapi.h’: No such file or directory,调整主CMakeLists.txt,设置变量ST_COMPATIBLE_XP,如下:

if(${PLATFORM_ARCH_TOOLCHAIN} STREQUAL "windows-x86-vs2015" OR ${PLATFORM_ARCH_TOOLCHAIN} STREQUAL "windows-x86_64-vs2015")
  add_definitions(-DST_COMPATIBLE_XP)
endif()

调整modules/core/src/system.cpp,强制关闭FLS,如下

#if (_WIN32_WINNT >= 0x0602)
  #include
#endif
#ifdef ST_COMPATIBLE_XP
  #define CV_DISABLE_FLS // force close FLS when use v140_xp
#endif
#if ((_WIN32_WINNT >= 0x0600) && !defined(CV_DISABLE_FLS)) || defined(CV_FORCE_FLS)
  #include
  #define CV_USE_FLS
#endif

(3).由于动态库和静态库都需要同时支持MD和MT,这里在build.sh中定义ST_FORCE_MSVC_USE_MT和ST_FORCE_MSVC_USE_MD用来指定是编译MD模式还是MT模式,调整cmake/OpenCVRTLinkage.cmake,将原来的if(NOT BUILD_SHARED_LIBS AND BUILD_WITH_STATIC_CRT)调整为

if((NOT ST_FORCE_MSVC_USE_MD) AND ((NOT BUILD_SHARED_LIBS AND BUILD_WITH_STATIC_CRT) OR ST_FORCE_MSVC_USE_MT))

编译:

(1).编译windows-x86_64-vs系列,如windows-x86_64-vs2015,则编译命令如下:

elif [ $1 == "windows-x86_64-vs2015" ]; then
    echo "#### build mt dynamic libraries debug ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A x64 -T v140_xp \
        ${common_options} \
        ${msvc_mt_common_options} \
        -DCMAKE_BUILD_TYPE=Debug \
        -DCMAKE_CONFIGURATION_TYPES=Debug \
        -DST_FORCE_MSVC_USE_MT=1 \
        -DBUILD_SHARED_LIBS=ON \
        -DCMAKE_INSTALL_PREFIX=../install/$1/mt \
        ..

    cmake --build . --target install --config debug

    echo "#### build mt dynamic libraries release ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A x64 -T v140_xp \
        ${common_options} \
        ${msvc_mt_common_options} \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_CONFIGURATION_TYPES=Release \
        -DST_FORCE_MSVC_USE_MT=1 \
        -DBUILD_SHARED_LIBS=ON \
        -DCMAKE_INSTALL_PREFIX=../install/$1/mt \
        ..

    cmake --build . --target install --config release

    echo "#### build mt static libraries debug ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A x64 -T v140_xp \
        ${common_options} \
        ${msvc_mt_common_options} \
        -DCMAKE_BUILD_TYPE=Debug \
        -DCMAKE_CONFIGURATION_TYPES=Debug \
        -DST_FORCE_MSVC_USE_MT=1 \
        -DBUILD_SHARED_LIBS=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/mt \
        ..

    cmake --build . --target install --config debug

    echo "#### build mt static libraries release ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A x64 -T v140_xp \
        ${common_options} \
        ${msvc_mt_common_options} \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_CONFIGURATION_TYPES=Release \
        -DST_FORCE_MSVC_USE_MT=1 \
        -DBUILD_SHARED_LIBS=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/mt \
        ..

    cmake --build . --target install --config release

    echo "#### build md dynamic libraries debug ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A x64 -T v140_xp \
        ${common_options} \
        ${msvc_md_common_options} \
        -DCMAKE_BUILD_TYPE=Debug \
        -DCMAKE_CONFIGURATION_TYPES=Debug \
        -DST_FORCE_MSVC_USE_MD=1 \
        -DBUILD_SHARED_LIBS=ON \
        -DCMAKE_INSTALL_PREFIX=../install/$1/md \
        ..

    cmake --build . --target install --config debug

    echo "#### build md dynamic libraries release ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A x64 -T v140_xp \
        ${common_options} \
        ${msvc_md_common_options} \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_CONFIGURATION_TYPES=Release \
        -DST_FORCE_MSVC_USE_MD=1 \
        -DBUILD_SHARED_LIBS=ON \
        -DCMAKE_INSTALL_PREFIX=../install/$1/md \
        ..

    cmake --build . --target install --config release

    echo "#### build md static libraries debug ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A x64 -T v140_xp \
        ${common_options} \
        ${msvc_md_common_options} \
        -DCMAKE_BUILD_TYPE=Debug \
        -DCMAKE_CONFIGURATION_TYPES=Debug \
        -DST_FORCE_MSVC_USE_MD=1 \
        -DBUILD_SHARED_LIBS=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/md \
        ..

    cmake --build . --target install --config debug

    echo "#### build md static libraries release ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A x64 -T v140_xp \
        ${common_options} \
        ${msvc_md_common_options} \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_CONFIGURATION_TYPES=Release \
        -DST_FORCE_MSVC_USE_MD=1 \
        -DBUILD_SHARED_LIBS=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/md \
        ..

    cmake --build . --target install --config release

(2).编译windows-x86-vs系列,如windows-x86_64-vs2015,则编译命令如下:

elif [ $1 == "windows-x86-vs2015" ]; then
    echo "#### build mt dynamic libraries debug ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A Win32 -T v140_xp \
        ${common_options} \
        ${msvc_mt_common_options} \
        -DCMAKE_BUILD_TYPE=Debug \
        -DCMAKE_CONFIGURATION_TYPES=Debug \
        -DST_FORCE_MSVC_USE_MT=1 \
        -DBUILD_SHARED_LIBS=ON \
        -DCMAKE_INSTALL_PREFIX=../install/$1/mt \
        ..

    cmake --build . --target install --config debug

    echo "#### build mt dynamic libraries release ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A Win32 -T v140_xp \
        ${common_options} \
        ${msvc_mt_common_options} \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_CONFIGURATION_TYPES=Release \
        -DST_FORCE_MSVC_USE_MT=1 \
        -DBUILD_SHARED_LIBS=ON \
        -DCMAKE_INSTALL_PREFIX=../install/$1/mt \
        ..

    cmake --build . --target install --config release

    echo "#### build mt static libraries debug ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A Win32 -T v140_xp \
        ${common_options} \
        ${msvc_mt_common_options} \
        -DCMAKE_BUILD_TYPE=Debug \
        -DCMAKE_CONFIGURATION_TYPES=Debug \
        -DST_FORCE_MSVC_USE_MT=1 \
        -DBUILD_SHARED_LIBS=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/mt \
        ..

    cmake --build . --target install --config debug

    echo "#### build mt static libraries release ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A Win32 -T v140_xp \
        ${common_options} \
        ${msvc_mt_common_options} \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_CONFIGURATION_TYPES=Release \
        -DST_FORCE_MSVC_USE_MT=1 \
        -DBUILD_SHARED_LIBS=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/mt \
        ..

    cmake --build . --target install --config release

    echo "#### build md dynamic libraries debug ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A Win32 -T v140_xp \
        ${common_options} \
        ${msvc_md_common_options} \
        -DCMAKE_BUILD_TYPE=Debug \
        -DCMAKE_CONFIGURATION_TYPES=Debug \
        -DST_FORCE_MSVC_USE_MD=1 \
        -DBUILD_SHARED_LIBS=ON \
        -DCMAKE_INSTALL_PREFIX=../install/$1/md \
        ..

    cmake --build . --target install --config debug

    echo "#### build md dynamic libraries release ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A Win32 -T v140_xp \
        ${common_options} \
        ${msvc_md_common_options} \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_CONFIGURATION_TYPES=Release \
        -DST_FORCE_MSVC_USE_MD=1 \
        -DBUILD_SHARED_LIBS=ON \
        -DCMAKE_INSTALL_PREFIX=../install/$1/md \
        ..

    cmake --build . --target install --config release

    echo "#### build md static libraries debug ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A Win32 -T v140_xp \
        ${common_options} \
        ${msvc_md_common_options} \
        -DCMAKE_BUILD_TYPE=Debug \
        -DCMAKE_CONFIGURATION_TYPES=Debug \
        -DST_FORCE_MSVC_USE_MD=1 \
        -DBUILD_SHARED_LIBS=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/md \
        ..

    cmake --build . --target install --config debug

    echo "#### build md static libraries release ..."
    rm -rf *
    cmake \
        -G"Visual Studio 14 2015" -A Win32 -T v140_xp \
        ${common_options} \
        ${msvc_md_common_options} \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_CONFIGURATION_TYPES=Release \
        -DST_FORCE_MSVC_USE_MD=1 \
        -DBUILD_SHARED_LIBS=OFF \
        -DCMAKE_INSTALL_PREFIX=../install/$1/md \
        ..

    cmake --build . --target install --config release
  1. MacOS:

调整源码:

(1).调整主CMakeLists.txt,强制使HAVE_PTHREAD不生效,否则报error:CMake Error at CMakeLists.txt:Thread execution might be in use in some component,在build.sh中定义ST_FORCE_XCODE_CLOSE_GCD,然后将CMakeLists.txt中的

else())
  set(HAVE_PTHREAD 1)
endif()

调整为:

elseif(NOT ST_FORCE_XCODE_CLOSE_GCD)
  set(HAVE_PTHREAD 1)
endif()

(2).调整主CMakeLists.txt,强制使list(REMOVE_ITEM OPENCV_LINKER_LIBS pthread)不生效,否则报error:CMake Error at CMakeLists.txt: (list):list sub-command REMOVE_ITEM requires list to be present,将CMakeLists.txt中的

if (OPENCV_DISABLE_THREAD_SUPPORT)
  list(REMOVE_ITEM OPENCV_LINKER_LIBS pthread)
endif()

调整为:

if (OPENCV_DISABLE_THREAD_SUPPORT AND NOT ST_FORCE_XCODE_CLOSE_GCD)
  list(REMOVE_ITEM OPENCV_LINKER_LIBS pthread)
endif()

(3).调整cmake/OpenCVFindFrameworks.cmake,强制使HAVE_GCD不生效,否则报error:CMake Error at CMakeLists.txt: (message): Not all parallel frameworks have been disabled (using GCD),将OpenCVFindFrameworks.cmake中的

if(APPLE AND NOT HAVE_TBB)
  set(HAVE_GCD 1)
else()

调整为:

if(APPLE AND NOT HAVE_TBB AND NOT ST_FORCE_XCODE_CLOSE_GCD)
  set(HAVE_GCD 1)
else()

(4).编译osx x86的库时调整主CMakeLists.txt文件,对CMAKE_C_FLAGS和CMAKE_CXX_FLAGS追加-m32选项。

编译:

(1).编译osx-x86_64-xcode系列,如osx-x86_64-xcode12,则编译命令如下:

elif [ $1 == "osx-x86_64-xcode12" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc \
        -DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_ADE=OFF \
        -DST_FORCE_XCODE_CLOSE_GCD=1 \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc \
        -DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_ADE=OFF \
        -DST_FORCE_XCODE_CLOSE_GCD=1 \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(2).编译osx-x86-xcode系列,如osx-x86-xcode12,则编译命令如下:

elif [ $1 == "osx-x86-xcode12" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc \
        -DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_ADE=OFF \
        -DST_FORCE_XCODE_CLOSE_GCD=1 \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc \
        -DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_ADE=OFF \
        -DST_FORCE_XCODE_CLOSE_GCD=1 \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install

(3).编译osx-aarch64-xcode系列,如osx-aarch64-xcode12,则编译命令如下:Apple M1

elif [ $1 == "osx-aarch64-xcode12" ]; then
    echo "#### build dynamic libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc \
        -DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ \
        -DBUILD_SHARED_LIBS=ON \
        -DWITH_ADE=OFF \
        -DST_FORCE_XCODE_CLOSE_GCD=1 \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_dynamic} \
        ..

    make -j8
    make install

    echo "#### build static libraries ..."
    rm -rf *
    cmake \
        ${common_options} \
        -DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc \
        -DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ \
        -DBUILD_SHARED_LIBS=OFF \
        -DWITH_ADE=OFF \
        -DST_FORCE_XCODE_CLOSE_GCD=1 \
        -DCMAKE_INSTALL_PREFIX=../install/$1/${dir_name_static} \
        ..

    make -j8
    make install
  1. iOS

基于iOS的通用项定义如下:

ios_common_options="--without world --without gapi --without dnn --without objdetect --without objc --without ts \
    --disable 1394 --disable EIGEN --disable CUDA --disable FFMPEG --disable IPP --disable ITT --disable LAPACK \
    --disable LIBREALSENSE --disable NVCUVID --disable OPENCL --disable OPENEXR --disable OPENGL --disable OPENMP \
    --disable OPENVX --disable PROTOBUF --disable QT --disable TBB --disable ADE --disable QUIRC"

调整源码:主要调整platforms/ios/build_framework.py

(1).调整platforms/ios/build_framework.py,在_build函数内的cmake_flags = []后添加一句,否则在主CMakeLists.txt里会报error:CMake Error at CMakeLists.txt: (if): Unknown arguments specified,因为PLATFORM_ARCH_TOOLCHAIN变量没有被定义

cmake_flags.append("-DPLATFORM_ARCH_TOOLCHAIN=ios")

(2).调整platforms/ios/build_framework.py,对于–iphoneos_archs和–iphonesimulator_archs选项,如果不显示指定则会被赋予默认值,这里调整为–iphoneos_archs和–iphonesimulator_archs每次仅支持一种指定

iphoneos_archs = None
if args.iphoneos_archs:
    iphoneos_archs = args.iphoneos_archs.split(',')
elif not args.build_only_specified_archs:
    # Supply defaults
    iphoneos_archs = ["armv7", "armv7s", "arm64"]
print('Using iPhoneOS ARCHS=' + str(iphoneos_archs))

iphonesimulator_archs = None
if args.iphonesimulator_archs:
    iphonesimulator_archs = args.iphonesimulator_archs.split(',')
elif not args.build_only_specified_archs:
    # Supply defaults
    iphonesimulator_archs = ["i386", "x86_64"]
print('Using iPhoneSimulator ARCHS=' + str(iphonesimulator_archs))

if args.iphoneos_archs is None and args.iphonesimulator_archs is None:
    print_error("--iphoneos_archs and --iphonesimulator_archs are undefined; nothing will be built.")
    sys.exit(1)

if args.iphoneos_archs and args.iphonesimulator_archs:
    print_error("one of --iphoneos_archs and --iphonesimulator_archs must be specified.")
    sys.exit(1)

iphoneos_archs = None
if args.iphoneos_archs:
    iphoneos_archs = args.iphoneos_archs.split(',')
print('Using iPhoneOS ARCHS=' + str(iphoneos_archs))

iphonesimulator_archs = None
if args.iphonesimulator_archs:
    iphonesimulator_archs = args.iphonesimulator_archs.split(',')
print('Using iPhoneSimulator ARCHS=' + str(iphonesimulator_archs))

编译:

(1).编译ios_os-universal-xcode系列,如ios_os-universal-xcode12,真机,则编译命令如下:编译完后,会分别有基于armv7和arm64两套库,可以通过libtool将armv7和arm64整合成一套库

elif [ $1 == "ios_os-universal-xcode12" ]; then
    echo "#### build static libraries ..."
    rm -rf *
    python ../platforms/ios/build_framework.py ../install/$1 --iphoneos_archs armv7,arm64 ${ios_common_options}

    echo "#### CreateUniversalBinary ..."
    path=../install/$1/
    path_armv7=build/build-armv7-iphoneos/install/lib/
    path_arm64=build/build-arm64-iphoneos/install/lib/

    prefix_3rdparty=3rdparty/lib
    prefix_modules=libopencv_
    suffix=.a

    name_3rd_libs=("libpng" "libwebp" "zlib" "libjpeg-turbo")
    name_module_libs=("photo" "videoio" "calib3d" "features2d" "core" "imgcodecs" "highgui" "video" "ml" "stitching" "flann" "imgproc")

    mkdir -p ${path}${dir_name_static}/lib/3rdparty
    mkdir -p ${path}${dir_name_static}/lib

    for val in ${name_3rd_libs[@]}; do
        name_armv7_lib="${path}${path_armv7}${prefix_3rdparty}${val}${suffix}"
        name_arm64_lib="${path}${path_arm64}${prefix_3rdparty}${val}${suffix}"
        /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static ${name_armv7_lib} ${name_arm64_lib} -o ${path}${dir_name_static}/lib/${prefix_3rdparty}${val}${suffix}
    done

    for val in ${name_module_libs[@]}; do
        name_armv7_lib="${path}${path_armv7}${prefix_modules}${val}${suffix}"
        name_arm64_lib="${path}${path_arm64}${prefix_modules}${val}${suffix}"
        /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static ${name_armv7_lib} ${name_arm64_lib} -o ${path}${dir_name_static}/lib/${prefix_modules}${val}${suffix}
    done

    cp -a ${path}${path_armv7}../include ${path}${dir_name_static}/
    cp -a ${path}${path_armv7}../share ${path}${dir_name_static}/
    cp -a ${path}${path_armv7}cmake ${path}${dir_name_static}/lib/

(2).编译ios_sim-universal-xcode系列,如ios_sim-universal-xcode12,模拟器(simulator),则编译命令如下:编译完后,会分别有基于i386和x86_64两套库,可以通过libtool将i386和x86_64整合成一套库

elif [ $1 == "ios_sim-universal-xcode12" ]; then
    echo "#### build static libraries ..."
    rm -rf *
    python ../platforms/ios/build_framework.py ../install/$1 --iphonesimulator_archs i386,x86_64 ${ios_common_options}

    echo "#### CreateUniversalBinary ..."
    path=../install/$1/
    path_i386=build/build-i386-iphonesimulator/install/lib/
    path_x86_64=build/build-x86_64-iphonesimulator/install/lib/

    prefix_3rdparty=3rdparty/lib
    prefix_modules=libopencv_
    suffix=.a

    name_3rd_libs=("libpng" "libwebp" "zlib" "libjpeg-turbo")
    name_module_libs=("photo" "videoio" "calib3d" "features2d" "core" "imgcodecs" "highgui" "video" "ml" "stitching" "flann" "imgproc")

    mkdir -p ${path}${dir_name_static}/lib/3rdparty
    mkdir -p ${path}${dir_name_static}/lib

    for val in ${name_3rd_libs[@]}; do
        name_i386_lib="${path}${path_i386}${prefix_3rdparty}${val}${suffix}"
        name_x86_64_lib="${path}${path_x86_64}${prefix_3rdparty}${val}${suffix}"
        /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static ${name_i386_lib} ${name_x86_64_lib} -o ${path}${dir_name_static}/lib/${prefix_3rdparty}${val}${suffix}
    done

    for val in ${name_module_libs[@]}; do
        name_i386_lib="${path}${path_i386}${prefix_modules}${val}${suffix}"
        name_x86_64_lib="${path}${path_x86_64}${prefix_modules}${val}${suffix}"
        /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static ${name_i386_lib} ${name_x86_64_lib} -o ${path}${dir_name_static}/lib/${prefix_modules}${val}${suffix}
    done

    cp -a ${path}${path_i386}../include ${path}${dir_name_static}/
    cp -a ${path}${path_i386}../share ${path}${dir_name_static}/
    cp -a ${path}${path_i386}cmake ${path}${dir_name_static}/lib/

(3).编译ios_sim-aarch64-xcode系列,如ios_sim-aarch64-xcode12,模拟器(simulator),则编译命令如下:Apple M1

elif [ $1 == "ios_sim-aarch64-xcode12" ]; then
    echo "#### build static libraries ..."
    rm -rf *
    python ../platforms/ios/build_framework.py ../install/$1 --iphonesimulator_archs arm64 ${ios_common_options}

    path=../install/$1/
    mkdir -p ${path}${dir_name_static}
    cp -a ${path}build/build-arm64-iphonesimulator/install/ ${path}${dir_name_static}/
  1. 项目中使用OpenCV

(1).项目test中加入对OpenCV的支持,则CMakeLists.txt应包括类似语句:

FIND_PACKAGE(OpenCV)
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
MESSAGE("#### opencv include dirs: ${OpenCV_INCLUDE_DIRS}")
MESSAGE("#### opencv libs: ${OpenCV_LIBS}")

TARGET_LINK_LIBRARIES(test ${OpenCV_LIBS})

(2).cmake时应使用OpenCV_DIR指定opencv中OpenCVConfig.cmake文件路径,如linux-x86_64-gcc5_4,这样主机上可以同时包含多个版本的opencv,通过OpenCV_DIR来指定使用哪个版本

cmake -DOpenCV_DIR=/usr/local/toolchains/opencv/4.6.0/linux-x86_64-gcc5_4/shared/lib/cmake/opencv4/ ..

(3).因为opencv中编译选项较多,可通过调用cv::getBuildInformation()函数来查看编译opencv时开启了哪些选项.

  1. 因为编译的平台、架构较多,有时需要了解某个编译器(preprocessor)定义支持的宏,可通过执行如下命令获取,如/usr/bin/gcc和/usr/bin/g++
echo | /usr/bin/gcc -dM -E -
echo | /usr/bin/g++ -dM -E -x c++ -

Original: https://blog.csdn.net/fengbingchun/article/details/127006370
Author: fengbingchun
Title: 多平台编译OpenCV 4.6.0源码操作步骤

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/637119/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球