【问题标题】:MacOS, CMake and OpenMPMacOS、CMake 和 OpenMP
【发布时间】:2018-03-06 23:32:54
【问题描述】:

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

这适用于带有 LLVM 5 的 CMake 3.8.2。


在我的CMakeLists.txt 我有

find_package( OpenMP )

后来我想做

if( OpenMP_CXX_FOUND )

但是 CMake 似乎没有接受 find_package 指令。

我使用 CMake 运行

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

我检查了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")

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

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

注意它改变了版本号,所以它一定是在找东西,对吧?

为了让它正常工作,我缺少什么?


好吧,似乎在 CMake 提供的FindOpenMP.cmake 中,我们执行了一个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()

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

这是正确的做法吗?

【问题讨论】:

  • 是的,LGTM。从那时起,您可以使用imported targets 让您的生活更轻松。

标签: cmake openmp


【解决方案1】:

该消息基本上告诉您必须提供库的路径和库的名称。以下示例应该可以解决您的问题(另请参阅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)

您可能想要设置例如set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread") 以便链接器自动检测适当的 pthread 库(请参阅 pthreadwiki)。

【讨论】:

    【解决方案2】:

    显然,大小写很重要。对于一个不相关的项目,我可以让它工作

    find_package ( OPENMP REQUIRED )
    

    这不起作用:

    find_package ( OpenMP REQUIRED )
    

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

    【讨论】:

    • 很遗憾,这对我没有用。
    • 这消除了未找到包的错误,但现在不再找到目标 OpenMP::OpenMP_CXX。将其更改为全部大写没有帮助。
    【解决方案3】:

    可能是 CMake 版本的问题,我想出一个与 Franzi's 略有不同的解决方案。

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

    除此之外,OpenMP_CXX_LIB_NAMES 不应该有前缀lib,因为它会导致类似-llibomp not found 的错误,而应该使用-lomp

    我还注意到 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)
    
    

    这是我的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;
    }
    

    输出是,

    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.
    

    【讨论】:

    • 整个 if(APPLE) 块是不必要的:CMake 可以检测 Apple Clang 和标准 Clang 的正确 OpenMP 选项。
    • 这是唯一对我有用的解决方案。奇怪,在另一个项目中我不需要这样做,它发现 OpenMP 很好。然而,当我创建了一个小测试以查看是否可以始终使用 OpenMP 进行构建时,find_package() 再也找不到 OpenMP。 -DCMAKE_CXX_COMPILER 的参数相同,环境变量相同。
    【解决方案4】:

    使用最新版本的 CMake(3.18,不适用于 3.14)和全新安装的 MacOS(当然,安装了开发人员 CL 工具),brew install libomp 是使事情正常运行所需的唯一操作。

    【讨论】:

    • 你安装了 macOS BigSur 吗?
    • @nac001 是的,我做到了
    猜你喜欢
    • 2021-12-04
    • 1970-01-01
    • 2016-10-24
    • 2017-07-15
    • 1970-01-01
    • 2020-06-05
    • 2020-07-30
    • 2013-02-15
    相关资源
    最近更新 更多