• 浅谈如何使用clang替换gcc进行编译(2)


    本来想直接把这一部分内容放到那一部分的,但是感觉篇幅有点太长了,就拆出新的一部分来发了。

    接着上边的内容来说,本文会从一个相对比较复杂的project出发,来介绍使用clang来切换gcc的过程。

    因为之前说想找到一个合适的project和一个合适的过程来介绍,后边就想到或许可以尝试下OpenCV来进行。选择OpenCV的理由主要为:

    1. 足够主流,能满足一部分人的实际需要,有真实价值
    2. OpenCV是一个大众(与小众相对)的软件,在写CMakeLists.txt的时候,考虑到了不同编译器,不同platform的需求,难度适中

     这里我没有经过太仔细的挑选,选的是master分支,看了下版本号,居然已经到了4.5.3版本,如果我的印象没错的话,我接触的第一个OpenCV版本还是2.4版本,变化真快。 下载代码:wget -O opencv.zip https://github.com/opencv/opencv/archive/master.zip 解压等过程不提

    略过上边的废话,我想把我的思路分成两节,第一节是一个不考虑OpenCV特性的解决思路,第二节是OpenCV推荐的方式。这里的OpenCV特性,主要指的是OpenCV足够“大众”,它本身对多compiler、多platform进行了支持,不仅对host代码进行了支持,甚至对于类似于需要交叉编译的环境也进行了支持,这个良好的平台和编译器移植性,是其他软件不具备的,第一节就是从这种一般软件入手来说明OpenCV的移植问题。

    第一节 普通软件的cmake编译移植

    按照OpenCV官网的介绍,整个正常流程如下(https://docs.opencv.org/master/d7/d9f/tutorial_linux_install.html):

    # Install minimal prerequisites (Ubuntu 18.04 as reference)
    sudo apt update && sudo apt install -y cmake g++ wget unzip
    # Download and unpack sources
    wget -O opencv.zip https://github.com/opencv/opencv/archive/master.zip
    unzip opencv.zip
    # Create build directory
    mkdir -p build && cd build
    # Configure
    cmake  ../opencv-master
    # Build
    cmake --build .

    请务必直接按照这个流程走一遍,确认系统默认环境下有什么问题,先解决,再考虑如何进行交叉编译器或者clang什么的事情,gcc使用的默认C标准是C89,而clang使用的是C99,一般的差异就是这么多,剩下的option和链接问题基本上对照着都有解决方案,最害怕一个人编译用GCC都编译不过的东西让你改换Clang,用nvcc编译不过的CUDA程序也让你换Clang。

    这里不考虑OpenCV本身的特性,考虑如何切换compiler。大概办法有两种,一种是直接指定,一种是在cmake执行的时候指定。

    直接指定就是自己修改CMakeList.txt。打开这个文件,发现OpenCV的CMakeLists.txt开头就有这两个选项,直接修改:

    # ----------------------------------------------------------------------------
    #  Root CMake file for OpenCV
    #
    #    From the off-tree build directory, invoke:
    #      $ cmake <PATH_TO_OPENCV_ROOT>
    #
    # ----------------------------------------------------------------------------
    
    # Disable in-source builds to prevent source tree corruption.
    if(" ${CMAKE_SOURCE_DIR}" STREQUAL " ${CMAKE_BINARY_DIR}")
      message(FATAL_ERROR "
    FATAL: In-source builds are not allowed.
           You should create a separate directory for build files.
    ")
    endif()
    set(CMAKE_C_COMPILER "clang")
    set(CMAKE_CXX_COMPILER "clang++")
    
    include(cmake/OpenCVMinDepVersions.cmake)

    然后按照上边的进行编译就好。当然有人会嫌改CMakeLists.txt有风险,在cmake的时候,使用-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++作用也是一样,这里简单说明一下,这两个选项是cmake自己所有的,因此没有这两个选项的CMakeLists.txt文件,建议搜下是否其包含的.cmake文件有对应的配置,如果确保都没有的话,请放心的加。

    当然这种切换其实是有风险的,毕竟编译器不是完全相同,中间大概率会遇到一些问题。比如版本,我使用gcc去编译就没有问题,而在使用clang7.0的时候就遇到了avx512指令部分不支持的情况,切换到高版本的clang就得以解决,如果你的项目必须使用低版本的话,就需要对比一下这个地方有哪些功能还没有support,需要人肉去diff和打patch。

    这里也介绍一点点经验,确定问题的真正来源,需要从make文件入手。在经历的cmake ..这一步骤后,往往会生成很多的文件,我这里拿OpenCV的dnn模块介绍一下。

     想确定dnn的问题,那么久需要切换到./modules/dnn/CMakeFiles/目录下查找问题,这种目录,基本的总控(或者说驱动)文件就是build.make文件,这里opencv_dnn又分成了 opencv_dnn.dir  opencv_perf_dnn.dir  opencv_test_dnn.dir这三个自文件,到了opencv_dnn.dir下边,可以清晰的看到

     居然有这么多文件,顾名思义,build.make驱动整个build过程,一般会依赖depend.make flags.make,link.txt是链接命令来源,想知道你对CmakeLists.txt的修改是否生效,请在这里最终确认,这里也可以方便的帮你确认最终的编译命令。比如build.make中的编译命令之一:

    modules/dnn/CMakeFiles/opencv_dnn.dir/misc/caffe/opencv-caffe.pb.cc.o: ../modules/dnn/misc/caffe/opencv-caffe.pb.cc
        @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/daily_learning/opencv-master/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building CXX object modules/dnn/CMakeFiles/opencv_dnn.dir/misc/caffe/opencv-caffe.pb.cc.o"
        cd /home/daily_learning/opencv-master/build/modules/dnn && /home/daily_learning/oldLLVM/build/bin/clang++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -Wno-inconsistent-missing-override -o CMakeFiles/opencv_dnn.dir/misc/caffe/opencv-caffe.pb.cc.o -c /home/daily_learning/opencv-master/modules/dnn/misc/caffe/opencv-caffe.pb.cc
    

     这个文件的最后甚至都清晰的告诉你了如何进行link:

    lib/libopencv_dnn.so.4.5.3: modules/dnn/CMakeFiles/opencv_dnn.dir/link.txt
        @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/daily_learning/opencv-master/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_109) "Linking CXX shared library ../../lib/libopencv_dnn.so"
        cd /home/daily_learning/opencv-master/build/modules/dnn && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/opencv_dnn.dir/link.txt --verbose=$(VERBOSE)
        cd /home/daily_learning/opencv-master/build/modules/dnn && $(CMAKE_COMMAND) -E cmake_symlink_library ../../lib/libopencv_dnn.so.4.5.3 ../../lib/libopencv_dnn.so.4.5 ../../lib/libopencv_dnn.so

     

    到对应link.txt中去查找link命令就好

    第二节 OpenCV推荐的编译思路

    看下源码目录下的cmake文件夹,你会有很多新的发现:

     这里清清楚楚的写明白了OpenCVDetectCXXCompiler.cmake和OpenCVCompilerOptions.cmake这两个文件。

    # Compilers:
    # - CV_GCC - GNU compiler (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    # - CV_CLANG - Clang-compatible compiler (CMAKE_CXX_COMPILER_ID MATCHES "Clang" - Clang or AppleClang, see CMP0025)
    # - CV_ICC - Intel compiler
    # - MSVC - Microsoft Visual Compiler (CMake variable)
    # - MINGW / CYGWIN / CMAKE_COMPILER_IS_MINGW / CMAKE_COMPILER_IS_CYGWIN (CMake original variables)
    #
    # CPU Platforms:
    # - X86 / X86_64
    # - ARM - ARM CPU, not defined for AArch64
    # - AARCH64 - ARMv8+ (64-bit)
    # - PPC64 / PPC64LE - PowerPC
    # - MIPS
    #
    # OS:
    # - WIN32 - Windows | MINGW
    # - UNIX - Linux | MacOSX | ANDROID
    # - ANDROID
    # - IOS
    # - APPLE - MacOSX | iOS
    # ----------------------------------------------------------------------------
    
    ocv_declare_removed_variables(MINGW64 MSVC64)
    # do not use (CMake variables): CMAKE_CL_64
    
    if(NOT DEFINED CV_GCC AND CMAKE_CXX_COMPILER_ID MATCHES "GNU")
      set(CV_GCC 1)
    endif()
    if(NOT DEFINED CV_CLANG AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")  # Clang or AppleClang (see CMP0025)
      set(CV_CLANG 1)
      set(CMAKE_COMPILER_IS_CLANGCXX 1)  # TODO next release: remove this
      set(CMAKE_COMPILER_IS_CLANGCC 1)   # TODO next release: remove this
    endif()
    
    function(access_CMAKE_COMPILER_IS_CLANGCXX)
      if(NOT OPENCV_SUPPRESS_DEPRECATIONS)
        message(WARNING "DEPRECATED: CMAKE_COMPILER_IS_CLANGCXX support is deprecated in OpenCV.
        Consider using:
        - CV_GCC    # GCC
        - CV_CLANG  # Clang or AppleClang (see CMP0025)
    ")
      endif()
    endfunction()
    variable_watch(CMAKE_COMPILER_IS_CLANGCXX access_CMAKE_COMPILER_IS_CLANGCXX)
    variable_watch(CMAKE_COMPILER_IS_CLANGCC access_CMAKE_COMPILER_IS_CLANGCXX)
    

     因此只需要配置下

    set(CMAKE_CXX_COMPILER_ID "clang")
    set(CV_CLANG 1)

      再进行cmake就可以顺利进行了,当然这里会进行一下版本和环境的检测。

  • 相关阅读:
    ApkTool动态打包
    Android
    hi3531 SDK 编译 uboot, 改动PHY地址, 改动 uboot 參数 .
    Unityclient通信測试问题处理(二)
    LIVE555研究之三:LIVE555基础
    【Unity Shaders】使用CgInclude让你的Shader模块化——创建CgInclude文件存储光照模型
    deep-learning-frameworks
    Upgrade R (升级R语言)
    Upgrade Bioconductor
    linux 中 ll 命令如何让查询结果按时间升序或降序排序?
  • 原文地址:https://www.cnblogs.com/jourluohua/p/15026742.html
Copyright © 2020-2023  润新知