【问题标题】:Non-default compilers (GCC or Vanilla-Clang) on macOS High Sierra linking issuemacOS High Sierra 链接问题上的非默认编译器(GCC 或 Vanilla-Clang)
【发布时间】:2023-03-29 19:58:01
【问题描述】:

我目前正在开发一个基于 Mac 的爱好项目,该项目涉及一些并行化,我想为此使用 OpenMP,因为在我的情况下,这似乎非常便携且相对容易实现。经过一些在线阅读,我发现 gcc 和 clang 在当前版本中都可以使用 -fopenmp 进行编译。不过,Xcode 中包含的默认 macOS 编译器已去除此功能。所以,我在我的 macOS 上同时安装了 gcc 7 和 clang 5。由于我的项目是通过 CMake 构建的,因此我编写了以下 makefile。

cmake_minimum_required(VERSION 3.0)

project(Project C CXX)

#SET(CMAKE_C_COMPILER /usr/local/bin/gcc-7)
#SET(CMAKE_CXX_COMPILER /usr/local/bin/gcc-7)

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O2 -mavx2 -march=haswell -flto=thin -g0")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread")

set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
FIND_PACKAGE(Boost 1.65 COMPONENTS filesystem system thread atomic chrono regex)
FIND_PACKAGE(OpenCV REQUIRED core imgproc imgcodecs calib3d)

set(HDF5_USE_STATIC_LIBRARIES ON)
set(HDF5_ROOT /usr/local/HDF_GROUP/HDF5/1.10.0/)
FIND_PACKAGE(HDF5 REQUIRED)

include_directories(${CMAKE_SOURCE_DIR}/include ${Boost_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS} ${HDF5_INCLUDE_DIRS})

add_executable(Project /path/to/many/files..)

TARGET_LINK_LIBRARIES(Project ${Boost_LIBRARIES})
TARGET_LINK_LIBRARIES(Project ${OpenCV_LIBS})
TARGET_LINK_LIBRARIES(Project ${HDF5_LIBRARIES})

在禁用 CMAKE_CXX_COMPILER 设置的这个版本中,代码可以顺利编译、链接和运行。一旦我将 CMake 设置为对完全相同的项目使用 gcc 或 vanilla-clang 而没有任何进一步的更改,编译就可以顺利完成,但链接失败。链接器报告了数百个丢失的符号,从几个 OpenCV 符号到大多数 libc++ 符号,如

"std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)", referenced from:
      _main in main.cpp.o

因此,我显然遗漏了一些基本的东西。使用 vanilla-clang,我尝试添加 -L/usr/local/opt/llvm/lib 以将链接器指向 clang 附带的库。不幸的是,这并没有改变。

我会很感激有关此事的任何提示。谢谢

【问题讨论】:

    标签: c++ macos gcc linker clang


    【解决方案1】:

    我遇到了同样的问题,花了一整天的时间才找到解决方案。我正在使用 Mac-Sierra 10.13.4。我想使用Opencv3(我认为同样的问题也出现在opencv2)和openMP。我实际上是使用 Clion 作为 IDE(CLion 使用 cmake 来配置项目,不像其他 IDE),所以我必须编写 CMakeLists.txt 文件。

    使用 gcc 作为 openCV 和 openMP 的编译器存在冲突。如果您使用 gcc 作为编译器,那么它会为 opencv 提供错误:

    imwrite() on OS X 错误:未定义符号

    您需要在 OS X 上专门使用 llvm 编译器来解决此问题。接下来,我给出了在 Mac-Sierra 上使用 OpenCV 和 OpenMP 的正确代码:

    cmake_minimum_required(VERSION 3.10)
    project(MyOpenCVTest)
    
    set(CMAKE_CXX_STANDARD 11)
    
    add_executable(MyOpenCVTest main.cpp)
    
    # set("OpenCV_DIR" "/modules/opencv/3.4.1/share/OpenCV/")
    set(CMAKE_PREFIX_PATH "/usr/local/Cellar/opencv@3/")
    
    set(OpenCV_INCLUDE_DIRS "/usr/local/Cellar/opencv@3/include/")
    set(OpenCV_LIBS "/usr/local/Cellar/opencv@3/lib/")
    
    find_package(OpenCV REQUIRED)
    
    message(STATUS "OpenCV library status:")
    message(STATUS "    version: ${OpenCV_VERSION}")
    message(STATUS "    libraries: ${OpenCV_LIBS}")
    message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
    
    if(UNIX)
        SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=gnu++0x")
    endif()
    
    
    set(CMAKE_C_COMPILER "/usr/local/Cellar/llvm/6.0.0/bin/clang")
    set(CMAKE_CXX_COMPILER "/usr/local/Cellar/llvm/6.0.0/bin/clang++")
    set(OPENMP_LIBRARIES "/usr/local/Cellar/llvm/6.0.0/lib")
    set(OPENMP_INCLUDES "/usr/local/Cellar/llvm/6.0.0/include")
    
    OPTION (USE_OpenMP "Use OpenMP to enamble <omp.h>" ON)
    
    # Find OpenMP
    if(APPLE AND USE_OpenMP)
        if(CMAKE_C_COMPILER_ID MATCHES "Clang")
            set(OpenMP_C "${CMAKE_C_COMPILER}")
            set(OpenMP_C_FLAGS "-fopenmp=libomp -Wno-unused-command-line-argument")
            set(OpenMP_C_LIB_NAMES "libomp" "libgomp" "libiomp5")
            set(OpenMP_libomp_LIBRARY ${OpenMP_C_LIB_NAMES})
            set(OpenMP_libgomp_LIBRARY ${OpenMP_C_LIB_NAMES})
            set(OpenMP_libiomp5_LIBRARY ${OpenMP_C_LIB_NAMES})
        endif()
        if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
            set(OpenMP_CXX "${CMAKE_CXX_COMPILER}")
            set(OpenMP_CXX_FLAGS "-fopenmp=libomp -Wno-unused-command-line-argument")
            set(OpenMP_CXX_LIB_NAMES "libomp" "libgomp" "libiomp5")
            set(OpenMP_libomp_LIBRARY ${OpenMP_CXX_LIB_NAMES})
            set(OpenMP_libgomp_LIBRARY ${OpenMP_CXX_LIB_NAMES})
            set(OpenMP_libiomp5_LIBRARY ${OpenMP_CXX_LIB_NAMES})
        endif()
    endif()
    
    if(USE_OpenMP)
        find_package(OpenMP REQUIRED)
    endif(USE_OpenMP)
    
    if (OPENMP_FOUND)
        include_directories("${OPENMP_INCLUDES}")
        link_directories("${OPENMP_LIBRARIES}")
        set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
        set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
        # set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
    endif(OPENMP_FOUND)
    
    
    include_directories( ${OpenCV_INCLUDE_DIRS} )
    target_link_libraries( MyOpenCVTest ${OpenCV_LIBS})
    TARGET_LINK_LIBRARIES(MyOpenCVTest opencv_core opencv_highgui opencv_imgproc opencv_imgcodecs)
    

    您可能想要设置例如set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread") 以便链接器自动检测适当的 pthread 库

    brew 重新安装 llvm

    安装 llvm 编译器。 请注意,对于需要 openMP 和 openCV 的项目,您不能在 Mac-Sierra 上使用 gcc 编译器。你需要使用llvm编译器。

    验证llvm和opencv安装目录的位置是否正确。

    【讨论】:

      【解决方案2】:

      如果使用 gcc 编译器驱动来执行链接,将编译器从 'gcc' 更改为 'g++',g++ 会自动引入标准 c++ 库,而 gcc 没有,或者添加 -lstdc++,可能需要其他但使用g++ 作为编译器驱动程序通常更容易。

      【讨论】:

      • 感谢您的提示。这肯定会减少丢失符号的数量。有趣的是,缺少的符号仍然引用基本的 c++ 功能,例如 "std::__1::basic_string, std::__1::allocator >::~basic_string ()" 等等,但总是使用 boost 或 OpenCV 来引用它们。我是否也必须使用 gcc 重新编译这两个库?
      • 更新:这适用于 LLVM/clang 5.0。 GCC 似乎仍然在与以前由 Apple 的 clang 编译的库作斗争。无论如何,这很有帮助!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      • 2018-05-03
      • 2019-03-09
      • 2018-03-18
      • 2018-05-08
      相关资源
      最近更新 更多