MacOS、CMake和OpenMP

gmol1639  于 2023-01-26  发布在  Mac
关注(0)|答案(5)|浏览(238)

我使用的是来自Homebrew的最新CMake(3.9.3)沿着来自Brew的LLVM 5.0.0,因为这里的Clang支持OpenMP。
这在CMake 3.8.2和LLVM 5中有效。
在我的CMakeLists.txt

find_package( OpenMP )

然后我想做

if( OpenMP_CXX_FOUND )

然而,CMake似乎并不支持find_package指令。
我用

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。
这样做对吗?

uttx8gqw

uttx8gqw1#

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

lmyy7pcs

lmyy7pcs2#

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

find_package ( OPENMP REQUIRED )

这不起作用:

find_package ( OpenMP REQUIRED )

有了这个指令,就不需要手动设置所有其他标志了。cmake 3.13.2,clang-1000.11.45.5(High Sierra)

holgip5t

holgip5t3#

也许这是一个CMake版本的事情,我想出了一个稍微不同的解决方案与Franzi's
我也在我的机器上使用brew install libomp,看起来OpenMP_CXX_FLAGS是用于编译项目源代码而不是编译omp(标志存储在omp目标中,并将由命令target_link_libraries填充)。
除此之外,OpenMP_CXX_LIB_NAMES不应该有前缀lib,因为它会导致类似-llibomp not found的错误,而应该使用-lomp
我还注意到,如果我把project(playground)放在cmake_minimum_required后面,CMAKE_C_COMPILER_ID会变成AppleClang而不是Clang,反过来,它会变成Clang,很烦人,我不知道为什么。
这里使用Xpreprocessor是因为apple clang没有随OpenMP一起提供,这个标志告诉编译器在其他地方寻找pragma(预处理器扩展)。在我们的例子中,它是安装libomp的include路径中的头文件。

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)

这是我的地狱

#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.
dz6r00yl

dz6r00yl4#

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

zte4gxcn

zte4gxcn5#

MacOS文图拉
cmake:/usr/本地/Hive/cmake/3.25.1开放多媒体编程语言:/usr/本地/存储单元/libomp/15.0.7 llvm:/usr/本地/存储单元/llvm/15.0.7_1
将编译器目录和libomp目录设置为正确值后,上述解决方案有效
变更内容:
设置(OpenMP_C_FLAGS“-打开函数=库函数”)
对于clang和clangxx部分

相关问题