Thorsten Schmitz
Thorsten Schmitz

Reputation: 572

Using OpenMP with Clang and CMake in Visual Studio

I'm trying to compile a simple app to test a few libraries I might be using in the future. Because of some problems I had with msvc I tried Clang, which made a strange error I got disappear.

The problem I have now is that the libraries I want to test use OpenMP. They import it using the FindOpenMP module CMake privides. However the module doesn't find it with Clang.

cmake_minimum_required(VERSION 3.14.0)
project(blaze-test VERSION 0.1.0)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(OpenMP)

I got this output :

1> CMake generation started for configuration: 'x64-Debug'.
1> Environment settings:
1>     CXXFLAGS=-m64 -fdiagnostics-absolute-paths
1>     CFLAGS=-m64 -fdiagnostics-absolute-paths
1> Command line: "cmd.exe" /c ""C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2019\COMMUNITY\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe"  -G "Ninja" -DCMAKE_INSTALL_PREFIX:PATH="PATH\blaze-test\install\x64-Debug" -DCMAKE_CXX_COMPILER:FILEPATH="C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/COMMUNITY/VC/Tools/Llvm/8.0.0/bin/clang-cl.exe" -DCMAKE_C_COMPILER:FILEPATH="C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/COMMUNITY/VC/Tools/Llvm/8.0.0/bin/clang-cl.exe"  -DCMAKE_BUILD_TYPE="Debug" -DCMAKE_MAKE_PROGRAM="C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2019\COMMUNITY\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\Ninja\ninja.exe" "PATH\blaze-test" 2>&1"
1> Working directory: PATH\blaze-test\build\x64-Debug
1> [CMake] -- The C compiler identification is Clang 8.0.0
1> [CMake] -- The CXX compiler identification is Clang 8.0.0
1> [CMake] -- Check for working C compiler: C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/COMMUNITY/VC/Tools/Llvm/8.0.0/bin/clang-cl.exe
1> [CMake] -- Check for working C compiler: C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/COMMUNITY/VC/Tools/Llvm/8.0.0/bin/clang-cl.exe -- works
1> [CMake] -- Detecting C compiler ABI info
1> [CMake] -- Detecting C compiler ABI info - done
1> [CMake] -- Detecting C compile features
1> [CMake] -- Detecting C compile features - done
1> [CMake] -- Check for working CXX compiler: C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/COMMUNITY/VC/Tools/Llvm/8.0.0/bin/clang-cl.exe
1> [CMake] -- Check for working CXX compiler: C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/COMMUNITY/VC/Tools/Llvm/8.0.0/bin/clang-cl.exe -- works
1> [CMake] -- Detecting CXX compiler ABI info
1> [CMake] -- Detecting CXX compiler ABI info - done
1> [CMake] -- Detecting CXX compile features
1> [CMake] -- Detecting CXX compile features - done
1> [CMake] -- Could NOT find OpenMP_C (missing: OpenMP_C_FLAGS OpenMP_C_LIB_NAMES) 
1> [CMake] -- Could NOT find OpenMP_CXX (missing: OpenMP_CXX_FLAGS OpenMP_CXX_LIB_NAMES) 
1> [CMake] -- Could NOT find OpenMP (missing: OpenMP_C_FOUND OpenMP_CXX_FOUND)  

Based on this I added

set(OpenMP_CXX_FLAGS "-Xclang -fopenmp" CACHE STRING "" FORCE)
set(OpenMP_C_FLAGS "-Xclang -fopenmp" CACHE STRING "" FORCE)

right before the find_package call. It removed the part about the compiler flags from the error message. I added libomp.lib the same way. Then I get

1> [CMake] -- Could NOT find OpenMP_C (missing: OpenMP_C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/8.0.0/lib/libomp.lib_LIBRARY) 
1> [CMake] -- Could NOT find OpenMP_CXX (missing: OpenMP_C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/8.0.0/lib/libomp.lib_LIBRARY) 
1> [CMake] -- Could NOT find OpenMP (missing: OpenMP_C_FOUND OpenMP_CXX_FOUND)

I hope someone can tell me how to get CMake to find it. These unreliable Find Modules are really annoying.

ps: I'm using Clang 8 (clang-cl.exe) with CMake 3.14 and Visual Studio 2019.

Upvotes: 4

Views: 4592

Answers (2)

zjyhjqs
zjyhjqs

Reputation: 711

(Tested for CMake 3.29, LLVM 18 on Win64. Worked for both clang (GNU driver) and clang-cl (MSVC driver))

Add this before find_package(OpenMP) (or set in your related preset)

if (("${CMAKE_C_COMPILER_ID};${CMAKE_C_SIMULATE_ID}" STREQUAL "Clang;MSVC") OR
    ("${CMAKE_CXX_COMPILER_ID};${CMAKE_CXX_SIMULATE_ID}" STREQUAL "Clang;MSVC"))
  # Assume we install LLVM to default path
  # Or for Visual Studio like `$ENV{ProgramFiles}/Microsoft Visual Studio/2022/Community/VC/Tools/Llvm/lib`
  set(CMAKE_SYSTEM_LIBRARY_PATH "$ENV{ProgramFiles}/LLVM/lib")
endif()

The problem (in FindOpenMP.cmake):

elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Clang" AND WIN32)
  # Check for separate OpenMP library for Clang on Windows
  find_library(OpenMP_libomp_LIBRARY
    NAMES libomp libgomp libiomp5
    HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
  )
  mark_as_advanced(OpenMP_libomp_LIBRARY)
  if(OpenMP_libomp_LIBRARY)
    try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}
      SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT
      LOG_DESCRIPTION "Trying ${LANG} OpenMP compiler with '${OpenMP_libomp_LIBRARY}'"
      CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
      LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
    )
    if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
      set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
      set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE)
      break()
    endif()
  endif()
endif()

Noticed that CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES is empty, and so do CMAKE_SYSTEM_LIBRARY_PATH (the default search path for the find_library() command).

It seems a CMake bug to me.

Upvotes: 0

Kevin
Kevin

Reputation: 18243

When using find_package(OpenMP REQUIRED), I have also received similar errors when using clang-cl from Visual Studio. There are known limitations with CMake's FindOpenMP.cmake module, as well as some lack of support the clang-cl side. There are other answers on this site suggesting to populate the CMake OpenMP_ variables manually, but this seems backwards. When I tried it, CMake claimed that OpenMP was FOUND, but the paths to the libraries was still unknown and compilation was unsuccessful. I was able to successfully run CMake then compile my applications with MSVC+Clang by avoiding the use of find_package and (unfortunately) hard-coding the path to the OpenMP libraries for now:

cmake_minimum_required(VERSION 3.14.0)
project(blaze-test VERSION 0.1.0)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(OpenMP_LIBRARY_DIR "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/lib")
set(OpenMP_CXX_FLAGS "-Xclang -fopenmp")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")

# Tell CMake where to find the OpenMP libraries.
link_directories(${OpenMP_LIBRARY_DIR})

# Library
add_library(MyLibrary SHARED MyExample.h MyExample.cpp)
# Link in the OpenMP libraries.
target_link_libraries(MyLibrary PUBLIC libomp libiomp5md)

# Executable
add_executable(MyOpenMpTest MyOpenMpTest .cpp)
target_link_libraries(MyOpenMpTest MyLibrary)

Hopefully, the folks at CMake and LLVM will get this issue worked out soon and FindOpenMP.cmake can be used more reliably.

Upvotes: 2

Related Questions