MacOS,CMake和OpenMP

Mad*_*sen 9 cmake openmp

我使用Homebrew的最新CMake(3.9.3)以及Brew的LLVM 5.0.0,因为Clang在这里有OpenMP支持.

这适用于CMake 3.8.2和LLVM 5.


在我的CMakeLists.txt

find_package( OpenMP )
Run Code Online (Sandbox Code Playgroud)

后来我想做

if( OpenMP_CXX_FOUND )
Run Code Online (Sandbox Code Playgroud)

然而,CMake似乎没有接受该find_package指令.

我用CMake运行

cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DUSE_WERROR=ON
Run Code Online (Sandbox Code Playgroud)

我已经检查过clangclang++正确指向/usr/local/opt/llvm/bin/clang/usr/local/opt/llvm/bin/clang++

我得到的只是这两行:

-- 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")
Run Code Online (Sandbox Code Playgroud)

如果我OpenMP_C_FLAGS自己设置(带-DOpenMP_C_FLAGS=-fopenmp=libomp)它会将错误更改为

-- Could NOT find OpenMP_C (missing: OpenMP_C_LIB_NAMES) (found version "3.1")
Run Code Online (Sandbox Code Playgroud)

请注意,它会更改版本号,因此必须找到一些东西,对吗?

我错过了什么才能正常工作?


好吧,似乎在FindOpenMP.cmakeCMake提供的内部我们做了一个try_compile,它默默地失败了(因为我们做了很多次,而且大多数都会失败,这是有道理的).但是,使用Clang时-Werror会提供一个标志,该标志由于未使用的命令行参数而失败.我可以这样补充:

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()
Run Code Online (Sandbox Code Playgroud)

到我的项目,因为我知道这-fopenmp=libomp将适用于这个Clang.

这是正确的做法吗?

Fra*_*nzi 14

该消息基本上告诉您必须提供库的路径和库的名称.以下示例应解决您的问题(另请参阅find_package(OpenMP)).请注意,我使用命令"brew install llvm"使用brew安装.前四行只是为了完整性.

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)
Run Code Online (Sandbox Code Playgroud)

您可能希望设置eg set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread"),以便链接器自动检测适当的pthread库(请参阅pthreadwiki).


Iza*_*ana 8

也许这是一个 CMake 版本的问题,我想出了一个与Franzi略有不同的解决方案。

brew install libomp我也在我的机器上使用。似乎OpenMP_CXX_FLAGS用于编译项目源代码而不是编译 omp (该标志存储在 omp 目标中并将由 command 填充target_link_libraries)。

除此之外,OpenMP_CXX_LIB_NAMES不应该有前缀lib,因为它会导致类似-llibomp未找到的错误,-lomp应该使用 where 。

我还注意到 是CMAKE_C_COMPILER_IDAppleClang不是Clang如果我project(playground)放在cmake_minimum_required. 相反,这Clang很烦人,我不知道为什么。

Xpreprocessor此处使用的原因是 apple clang 不随 OpenMP 一起提供,并且此标志告诉编译器在其他地方查找 pragma(预处理器扩展)。在我们的例子中,它是安装 libomp 的包含路径中的头文件。

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)

Run Code Online (Sandbox Code Playgroud)

这是我的你好世界

#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;
}
Run Code Online (Sandbox Code Playgroud)

输出是

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.
Run Code Online (Sandbox Code Playgroud)


小智 6

显然,案例很重要。对于不相关的项目,我可以使其与

find_package ( OPENMP REQUIRED )
Run Code Online (Sandbox Code Playgroud)

这不起作用:

find_package ( OpenMP REQUIRED )
Run Code Online (Sandbox Code Playgroud)

使用该指令,无需手动设置所有其他标志。cmake 3.13.2,clang-1000.11.45.5(High Sierra)