在Windows上配置CMake,使用命令行来使用clang,以获得现代OpenMP支持。

11
我有一个使用OpenMP进行并行化的小测试项目。我的目标是编译它,以便生成.dll.lib库(因为我的真实项目链接到使用这些类型分发的外部库),并支持OpenMP 4.5或更新版本,并且可以从命令行执行,以便在docker上进行测试和检查(docker部分不在本问题的范围内,只是为了说明我为什么需要它能够从命令行工作)。我可以用不同的编译器编译这个项目,但都不满意:
  • MSVC: mkdir build-msvc,然后cmake ..(从新创建的文件夹中)最后cmake --build . --config Release。这个编译很好,但只支持OpenMP 2.0,因此对于我的真实项目来说不是一个好选择。
  • Intel Parallel Studio: mkdir build-intel,然后cmake .. -T "Intel C++ Compiler 19.0"(从新创建的文件夹中)最后cmake --build . --config Release。它支持OpenMP 5.0,但其许可证对我来说相当昂贵。
  • MinGW x64 g++:mkdir build-g++,然后cmake .. -G "MinGW Makefiles"(从新创建的文件夹中)最后cmake --build .。它支持OpenMP 4.5,但这个编译器不兼容.lib(据我所知),而我已经提到这对我来说是必需的。

我尝试过使用clang,但没有成功:

  • 来自MSVC的CLANG:mkdir build-clang-msvc,然后cmake -G Ninja -DCMAKE_CXX_COMPILER=clang-cl ..(从新创建的文件夹中),但它失败并显示以下错误:
-- CXX编译器的标识是Clang 8.0.1 with MSVC-like command-line。 -- 检查CXX编译器是否可用:C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/bin/clang-cl.exe -- 检查CXX编译器是否可用:C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/bin/clang-cl.exe -- 错误 在C:/Program Files/CMake/share/cmake-3.15/Modules/CMakeTestCXXCompiler.cmake:53处发生错误(消息如下):
C++编译器
"C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/bin/clang-cl.exe"
无法编译简单测试程序。
以下是失败的输出:
Change Dir: C:/Users/[USER NAME]/source/repos/test_openmp/build-clang-msvc/CMakeFiles/CMakeTmp Run Build Command(s):C:/PROGRA~2/MICROS~1/2019/COMMUN~1/Common7/IDE/COMMON~1/MICROS~1/CMake/Ninja/ninja.exe cmTC_bd131 && [1/2] Building CXX object CMakeFiles\cmTC_bd131.dir\testCXXCompiler.cxx.obj [2/2] Linking CXX executable cmTC_bd131.exe FAILED: cmTC_bd131.exe cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\cmTC_bd131.dir --rc=rc --mt=CMAKE_MT-NOTFOUND --manifests -- C:\PROGRA~1\MINGW-~1\X86_64~1.0-P\mingw64\bin\ld.exe /nologo CMakeFiles\cmTC_bd131.dir\testCXXCompiler.cxx.obj /out:cmTC_bd131.exe /implib:cmTC_bd131.lib /pdb:cmTC_bd131.pdb /version:0.0 /machine:X86 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ." RC Pass 1: command "rc /fo CMakeFiles\cmTC_bd131.dir/manifest.res CMakeFiles\cmTC_bd131.dir/manifest.rc" failed (exit code 0) with the following output: The system cannot find the file specified ninja: build stopped: subcommand failed.
CMake将无法正确生成此项目。 调用栈(最近的调用在最前): CMakeLists.txt:2 (project)
-- 配置不完整,出现错误! 请参阅 "C:/Users/[USER NAME]/source/repos/test_openmp/build-clang-msvc/CMakeFiles/CMakeOutput.log"。 请参阅 "C:/Users/[USER NAME]/source/repos/test_openmp/build-clang-msvc/CMakeFiles/CMakeError.log"。
除了MSVC,还可以使用Clang和Ninja: mkdir build-clang-ninja,然后在新创建的文件夹中更改PATH环境变量,使非MSVC被优先找到,接着执行cmake -G Ninja -DCMAKE_CXX_COMPILER=clang-cl ..。但是会出现以下错误:
-- The CXX compiler identification is Clang 9.0.0 with MSVC-like command-line
-- Check for working CXX compiler: C:/Program Files/LLVM/bin/clang-cl.exe
-- Check for working CXX compiler: C:/Program Files/LLVM/bin/clang-cl.exe -- broken
CMake Error at C:/Program Files/CMake/share/cmake-3.15/Modules/CMakeTestCXXCompiler.cmake:53 (message):
  The C++ compiler

    "C:/Program Files/LLVM/bin/clang-cl.exe"
is not able to compile a simple test program.
It fails with the following output:
Change Dir: C:/Users/[USER NAME]/source/repos/test_openmp/buid-clang-ninja/CMakeFiles/CMakeTmp Run Build Command(s):C:/Ninja/ninja.exe cmTC_50b73 && [1/2] Building CXX object CMakeFiles\cmTC_50b73.dir\testCXXCompiler.cxx.obj [2/2] Linking CXX executable cmTC_50b73.exe FAILED: cmTC_50b73.exe cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\cmTC_50b73.dir --rc=rc --mt=CMAKE_MT-NOTFOUND --manifests -- CMAKE_LINKER-NOTFOUND /nologo CMakeFiles\cmTC_50b73.dir\testCXXCompiler.cxx.obj /out:cmTC_50b73.exe /implib:cmTC_50b73.lib /pdb:cmTC_50b73.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ." RC Pass 1: command "rc /fo CMakeFiles\cmTC_50b73.dir/manifest.res CMakeFiles\cmTC_50b73.dir/manifest.rc" failed (exit code 0) with the following output: The system cannot find the file specified ninja: build stopped: subcommand failed.
CMake将无法正确生成此项目。 Call Stack (most recent call first): CMakeLists.txt:2 (project)
-- 配置不完整,出现错误! 请参阅"C:/Users/[USER NAME]/source/repos/test_openmp/buid-clang-ninja/CMakeFiles/CMakeOutput.log"。 请参阅"C:/Users/[USER NAME]/source/repos/test_openmp/buid-clang-ninja/CMakeFiles/CMakeError.log"。

你对如何使用clang有什么想法吗?我认为这是我实现目标的最佳选择(使用OpenMP 4.5或更高版本编译我的测试程序并生成 .lib.dll)。

我查看了相关帖子/网页,但它们都没有解决我的问题:


在执行cmake命令之前,您是否尝试加载相关的vcvarsXX.bat文件? - Le Ngoc Thuong
我不知道,所以我猜不是。我只是打开一个命令提示符,导航到构建文件夹并执行我编写的CMake命令。我该如何加载这个相关文件? - apalomer
1
我正在使用MSVC构建一个项目。每当我想要构建该项目时,我总是需要先运行“%VCINSTALLDIR%\vcvarsall.bat amd64”。此外,根据此页面https://dev59.com/vGEh5IYBdhLWcg3wTBxc中的答案,他/她还建议“加载相关的vcvarsXX.bat文件(例如“<您的Visual Studio位置>\VC\vcvarsall.bat”x86)”。 当我忘记运行vcvarsall.bat时,我也遇到了与您相同的错误消息。 - Le Ngoc Thuong
那确实让我有所进展。现在我卡在了下一步:无法找到OpenMP_CXX(缺少:OpenMP_CXX_FLAGS OpenMP_CXX_LIB_NAMES)。我会深入研究这个新的错误,如果找不到答案,我会发一个新问题。谢谢! - apalomer
1个回答

4
我能够为Clang+MSVC情况复制此错误。由于我们试图在Visual Studio之外(即命令行)使用面向Visual Studio的编译器,因此在使用编译器之前需要在我们的命令行中初始化VS构建环境。 VCVarsXX.bat文件可以实现这一点。它们是VS命令提示工具的一部分。因此,通过选择您的架构(x86, x64,等等)并运行脚本,CMake将能够使用clang-cl构建简单测试程序并继续进行。以下是VS 2019的位置:
>"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86

>cmake -G Ninja -DCMAKE_CXX_COMPILER=clang-cl ..
-- The CXX compiler identification is Clang 8.0.1
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/bin/clang-cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/bin/clang-cl.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
...

关于OpenMP问题的具体说明,我个人认为使用find_package(OpenMP REQUIRED)是不太有用的。正如你所提到的,我也遇到了这个CMake错误:

Could NOT find OpenMP_CXX (missing: OpenMP_CXX_FLAGS OpenMP_CXX_LIB_NAMES)

本网站上有一些建议(例如这里这里),声称手动填充所有变量可以让FindOpenMP.cmake成功找到库。我尝试了您的示例CMake文件,并取得了一些成功。
cmake_minimum_required (VERSION 2.8)
project(test_openmp LANGUAGES CXX)

set(OpenMP_CXX "${CMAKE_CXX_COMPILER}")
set(OpenMP_CXX_FLAGS "-Xclang -fopenmp")
set(OpenMP_CXX_LIB_NAMES "libomp" "libiomp5")
set(OpenMP_libomp_LIBRARY libomp)
set(OpenMP_libiomp5_LIBRARY libiomp5)

#OPENMP
find_package(OpenMP REQUIRED)
if(OPENMP_FOUND)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
endif()

# Library
add_library(example_lib SHARED example_lib.h example_lib.cpp)
target_link_libraries(example_lib PUBLIC ${OpenMP_CXX_LIBRARIES})
target_compile_definitions(example_lib PRIVATE EXEMPLE_LIB_EXPORT)

# Executable
add_executable(test_openmp test_openmp.cpp)
target_link_libraries(test_openmp example_lib)

这一步在第二次CMake配置尝试中“找到”了库(第一次仍会出现同样的错误Could NOT find OpenMP_CXX,如之前所述):

>cmake -G Ninja -DCMAKE_CXX_COMPILER=clang-cl ..
-- Found OpenMP_CXX: -Xclang -fopenmp (found version "3.1")
-- Found OpenMP: TRUE (found version "3.1")
-- Configuring done
-- Generating done

然而,这种方法无法构建可执行文件,因为CMake的OpenMP变量(特别是OpenMP_CXX_LIBRARIES)实际上并没有指向库的位置。CMake的FindOpenMP.cmake的缺点已经在CMake的问题网站这里提出,并且似乎LLVM / Clang也存在相关限制。
无论如何,我能够找到最干净的方法是完全放弃使用find_package()。以下方式允许我成功地生成构建系统,并编译和运行可执行文件:
cmake_minimum_required (VERSION 2.8)
project(test_openmp LANGUAGES CXX)

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(example_lib SHARED example_lib.h example_lib.cpp)
# Link in the OpenMP libraries.
target_link_libraries(example_lib PUBLIC libomp libiomp5md)
target_compile_definitions(example_lib PRIVATE EXEMPLE_LIB_EXPORT)

# Executable
add_executable(test_openmp test_openmp.cpp)
target_link_libraries(test_openmp example_lib)

CMake 3.17 包含支持解决此错误的功能。这些错误已在提交中得到修复。 - apalomer
@apalomer 谢谢!如果您知道更简单的解决方案,请发表一下! - Kevin
运行 vcvarsall.bat 对我来说没有将 clang-cl 放入 PATH 中。有什么想法吗? - Alex Reinking
@AlexReinking 你安装了clang-cl吗?如果不知道你的设置和如何安装这些组件,很难知道。如果需要,请再提一个问题! - Kevin
是的,它是通过VS2019安装程序安装的。 - Alex Reinking

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接