MacOS, CMake and OpenMP

后端 未结 3 1229
我在风中等你
我在风中等你 2020-12-01 17:03

I am using the newest CMake (3.9.3) from Homebrew along with LLVM 5.0.0 also from Brew, because Clang here has OpenMP support.

This worked in CMake 3.8.2 with LLVM 5

相关标签:
3条回答
  • 2020-12-01 17:13

    Apparently, case is important. For an unrelated project I can make it work with

    find_package ( OPENMP REQUIRED )
    

    This didn't work:

    find_package ( OpenMP REQUIRED )
    

    With that directive, no need for setting all the other flags by hand. cmake 3.13.2, clang-1000.11.45.5 (High Sierra)

    0 讨论(0)
  • 2020-12-01 17:22

    The message basically tells you that you have to provide the path to the libraries and the names of the libraries. The following example should fix your problem (see also find_package(OpenMP)). Note that I use the brew installation using the command "brew install llvm". The first four lines are just for completeness.

    set(CMAKE_C_COMPILER "/usr/local/Cellar/llvm/5.0.1/bin/clang")
    set(CMAKE_CXX_COMPILER "/usr/local/Cellar/llvm/5.0.1/bin/clang++")
    set(OPENMP_LIBRARIES "/usr/local/Cellar/llvm/5.0.1/lib")
    set(OPENMP_INCLUDES "/usr/local/Cellar/llvm/5.0.1/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)
    

    You might want to set e.g. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread") such that the linker automatically detects the appropriate pthread library (see pthread and wiki).

    0 讨论(0)
  • 2020-12-01 17:29

    Maybe it's a CMake version thing, I come up with a slightly different solution with Franzi's.

    I also use brew install libomp on my machine. It seems like OpenMP_CXX_FLAGS is used for compiling project source code instead of compiling the omp (the flag is stored in the omp target and will be populated by command target_link_libraries).

    Besides that, OpenMP_CXX_LIB_NAMES shouldn't have prefix lib because it will cause an error like -llibomp not found, where -lomp should be used instead.

    I also noticed that CMAKE_C_COMPILER_ID is AppleClang instead of Clang if I put project(playground) after cmake_minimum_required. In reverse, it's Clang, quite annoying and I don't know why.

    Xpreprocessor used here is because apple clang doesn't ship with OpenMP and this flag tells the compiler to look for pragma (preprocessor expansion) elsewhere. In our case, it's the header files in the include path where the libomp is installed.

    cmake_minimum_required(VERSION 3.12)
    
    project(playground)
    
    if(APPLE)
        set(CMAKE_C_COMPILER clang)
        set(CMAKE_CXX_COMPILER clang++)
    
        if(CMAKE_C_COMPILER_ID MATCHES "Clang\$")
            set(OpenMP_C_FLAGS "-Xpreprocessor -fopenmp")
            set(OpenMP_C_LIB_NAMES "omp")
            set(OpenMP_omp_LIBRARY omp)
        endif()
    
        if(CMAKE_CXX_COMPILER_ID MATCHES "Clang\$")
            set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp")
            set(OpenMP_CXX_LIB_NAMES "omp")
            set(OpenMP_omp_LIBRARY omp)
        endif()
    
    endif()
    
    find_package(OpenMP REQUIRED)
    
    add_executable(helloworld helloworld.cxx)
    target_link_libraries(helloworld PRIVATE OpenMP::OpenMP_CXX)
    
    

    Here's my helloworld

    #include <cstdio>
    #include <thread>
    #include <sstream>
    
    int main(void)
    {
        #pragma omp parallel
        {
          std::stringstream ss;
          ss << std::this_thread::get_id();
          printf("%s, Hello, world.\n", ss.str().c_str());
        }
    
      return 0;
    }
    

    output is,

    0x700002dc8000, Hello, world.
    0x10a17d5c0, Hello, world.
    0x7000045d1000, Hello, world.
    0x7000055d7000, Hello, world.
    0x700005dda000, Hello, world.
    0x7000035cb000, Hello, world.
    0x7000065dd000, Hello, world.
    0x700003dce000, Hello, world.
    0x700007de6000, Hello, world.
    0x700004dd4000, Hello, world.
    0x7000075e3000, Hello, world.
    0x700006de0000, Hello, world.
    
    0 讨论(0)
提交回复
热议问题