c++ - macOS High Sierra 上的非默认编译器(GCC 或 Vanilla-Clang)链接问题

标签 c++ macos gcc linker clang

我目前正在开发一个基于 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 附带的库。不幸的是,这没有改变任何事情。

如果有任何关于此事的提示,我将不胜感激。谢谢

最佳答案

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

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

imwrite() on OS X error: Undefined symbols

您需要在 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)

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

brew reinstall llvm

安装llvm编译器。 请注意,您无法在 Mac-Sierra 上为需要 openMP 和 openCV 的项目使用 gcc 编译器。您需要使用llvm编译器。

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

关于c++ - macOS High Sierra 上的非默认编译器(GCC 或 Vanilla-Clang)链接问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47822547/

相关文章:

c++ - 在 C++ 上迭代 ini 文件,可能使用 boost::property_tree::ptree?

python - 如何创建 'pure' virtualenv?

c++ - 本地 CGEventRef 是否被视为指针?

linux - "make check"安装HDF5失败

c++ - C 风格字符串的 boost::spirit::qi 和 qi::alnum 的模板编译错误

c++ - 关于常量表达式的困惑

c++ - 需要用 QFileDialog 保存一个新文件

PHP 开发 : Which Operating System do you use?

c++ - ISR 中使用的指针指向寄存器

c - Linux 内核中 ATOMIC_INIT 宏的用途