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

时间:2017-12-14 21:46:06

标签: 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附带的lib。不幸的是,这没有任何改变。

我很欣赏有关此事的任何暗示。谢谢

2 个答案:

答案 0 :(得分:2)

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

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

  OS X上的

imwrite()错误:未定义的符号

您需要在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编译器。 请注意,您不能在Mac-Sierra上使用gcc编译器来处理需要openMP和openCV的项目。您需要使用llvm编译器。

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

答案 1 :(得分:1)

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