MacOS, CMake and OpenMP

19,559

Solution 1

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).

Solution 2

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)

Solution 3

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.

Solution 4

With recent versions of CMake (3.18, didn't work with 3.14) and a fresh installation of MacOS (with developer CL tools installed, of course), brew install libomp was the only action needed to make things work.

Share:
19,559

Related videos on Youtube

Mads Ohm Larsen
Author by

Mads Ohm Larsen

Updated on June 13, 2022

Comments

  • Mads Ohm Larsen
    Mads Ohm Larsen about 2 years

    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.


    In my CMakeLists.txt I have

    find_package( OpenMP )
    

    and later I want to do

    if( OpenMP_CXX_FOUND )
    

    However CMake doesn't seem to pick up on the find_package directive.

    I run CMake with

    cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DUSE_WERROR=ON
    

    where I have checked that clang and clang++ points correctly to /usr/local/opt/llvm/bin/clang and /usr/local/opt/llvm/bin/clang++

    All I get is these two lines:

    -- Could NOT find OpenMP_C (missing: OpenMP_C_FLAGS OpenMP_C_LIB_NAMES) (found version "1.0")
    -- Could NOT find OpenMP_CXX (missing: OpenMP_CXX_FLAGS OpenMP_CXX_LIB_NAMES) (found version "1.0")
    

    If I set OpenMP_C_FLAGS myself (with -DOpenMP_C_FLAGS=-fopenmp=libomp) it changes the error to

    -- Could NOT find OpenMP_C (missing: OpenMP_C_LIB_NAMES) (found version "3.1")
    

    Notice that it changes the version number, so it must be finding something, right?

    What am I missing for this to work properly?


    Okay, it seem that inside the FindOpenMP.cmake supplied by CMake we do a try_compile, which fails silently (because we do it a lot of times and most of them will fail, this makes sense). However, with Clang a -Werror flag is supplied, which fails because of an unused command line argument. I can thus add:

    if(APPLE)
        if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
            set(OpenMP_C_FLAG "-fopenmp=libomp -Wno-unused-command-line-argument")
        endif()
        if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
            set(OpenMP_CXX_FLAG "-fopenmp=libomp -Wno-unused-command-line-argument")
        endif()
    endif()
    

    to my project because I know that -fopenmp=libomp will work for this Clang.

    Is this the right way of doing it?

    • compor
      compor over 6 years
      Yes, LGTM. You could use the imported targets from then on to make your life a bit easier.
  • valentin
    valentin over 4 years
    Sadly, this did not do it for me.
  • Yongwei Wu
    Yongwei Wu over 4 years
    The whole if(APPLE) block is unnecessary: CMake can detect the correct OpenMP options for Apple Clang and standard Clang.
  • ShnitzelKiller
    ShnitzelKiller over 3 years
    This was the only solution that worked for me. Strange, in another project I didn't need to do this and it found OpenMP fine. Yet when I created a small test to see if I could consistently build with OpenMP, find_package() couldn't find OpenMP anymore. Same arguments to -DCMAKE_CXX_COMPILER, same environment variables.
  • nac001
    nac001 over 3 years
    did you install macOS BigSur?
  • CharlesB
    CharlesB over 3 years
    @nac001 yes I did
  • ShnitzelKiller
    ShnitzelKiller almost 3 years
    This gets rid of the package not found error, but now the target OpenMP::OpenMP_CXX is no longer found. Changing that to all caps doesn't help.
  • Jimmy
    Jimmy about 2 years
    brew install libomp works for me