Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure CMake in windows to use clang from command line to get modern OpenMP support

I have a small test project that uses OpenMP for parallelization. My target is to compile it so it produces .dll and .lib for libraries (because my real project links to external libraries distributed using these types), with support for OpenMP 4.5 or newer and do it from the command line so it can be done on a docker for testing and checking (the docker part is out of the scope of this question, it is just for reference on why I need it to work from the command line). I can compile this project with different compilers with which I am not happy:

  • MSVC: mkdir build-msvc, then cmake .. (from the newly created folder) and finally cmake --build . --config Release. This compiles fine but only supports OpenMP 2.0, therefore is not a good option for my real project.
  • Intel Parallel Studio: mkdir build-intel, then cmake .. -T "Intel C++ Compiler 19.0" (from the newly created folder) and finally cmake --build . --config Release. This supports OpenMP 5.0 but its licenses are pretty expensive for me.
  • MinGW x64 g++: mkdir build-g++, then cmake .. -G "MinGW Makefiles" (from the newly created folder) and finally cmake --build .. It supports OpenMP 4.5 but this compiler is not compatible wiht .lib (as far as I know) which I already mentioned is necessary for me.

I have tried without success to use clang:

  • CLANG from MSVC: mkdir build-clang-msvc, then cmake -G Ninja -DCMAKE_CXX_COMPILER=clang-cl .. (from the newly created folder), but it fails with the following error:
-- The CXX compiler identification is Clang 8.0.1 with MSVC-like command-line
-- 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 -- broken
CMake Error at C:/Program Files/CMake/share/cmake-3.15/Modules/CMakeTestCXXCompiler.cmake:53 (message):
  The C++ compiler

    "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/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/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 will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:2 (project)


-- Configuring incomplete, errors occurred!
See also "C:/Users/[USER NAME]/source/repos/test_openmp/build-clang-msvc/CMakeFiles/CMakeOutput.log".
See also "C:/Users/[USER NAME]/source/repos/test_openmp/build-clang-msvc/CMakeFiles/CMakeError.log".
  • Clang and Ninja apart from MSVC: mkdir build-clang-ninja, then cmake -G Ninja -DCMAKE_CXX_COMPILER=clang-cl .. (from the newly created folder and changing the PATH environmental variable so the non-msvc are found first), but it fails with the following error:
-- 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 will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:2 (project)


-- Configuring incomplete, errors occurred!
See also "C:/Users/[USER NAME]/source/repos/test_openmp/buid-clang-ninja/CMakeFiles/CMakeOutput.log".
See also "C:/Users/[USER NAME]/source/repos/test_openmp/buid-clang-ninja/CMakeFiles/CMakeError.log".

Any ideas on how to proceed with the clang? I think it is my best option for what I want to achieve (compile my test program with support for OpenMP 4.5 or newer and producing .lib and .dll).

Related posts/webpages that I have checked but have been non-useful to solve this:

  • Building c++ project on Windows with CMake, Clang and Ninja
  • Building with CMake, Ninja and Clang on Windows
  • Ways to Compile with Clang on Windows, specifically setting the linker: -DCMAKE_LINKER="C:/Program Files/LLVM/bin/lld-link.exe"
  • CMake building for Windows (clang-cl) using Ninja Generator
  • Clang-cl user manual
like image 294
apalomer Avatar asked Oct 08 '19 11:10

apalomer


1 Answers

I was able to duplicate this error for the Clang+MSVC case. Because we are attempting to use the Visual-Studio-tailored compiler from outside Visual Studio (i.e. the command line), it is necessary to initialize the VS build environment in our command line before using the compiler. The VCVarsXX.bat files accomplish this; they are part of the VS Command Prompt tools. So by picking your architecture (x86, x64, etc) and running the script, this should allow CMake to build the simple test program with clang-cl and proceed. Here is where it is located for 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
...

To expand on the OpenMP issue, I personally found using find_package(OpenMP REQUIRED) to be pretty fruitless. As you mentioned, I also received this CMake error:

Could NOT find OpenMP_CXX (missing: OpenMP_CXX_FLAGS OpenMP_CXX_LIB_NAMES)

There are a few suggestions on this site (for example here and here) claiming that populating all of the variables manually allows FindOpenMP.cmake to successfully find the libraries. I tried this with your example CMake file, with some success:

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)

This succeeded in "finding" the libraries on the second CMake configuration attempt (the first always yielded the same Could NOT find OpenMP_CXX error as before):

>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

However, this failed to build the executable, as none of the CMake OpenMP variables (particularly OpenMP_CXX_LIBRARIES) actually point to the library location. The shortcomings of CMake's FindOpenMP.cmake have been raised on the CMake issue site here, and there appear to be relevant limitations on the LLVM/Clang end as well.


Regardless, the cleanest way I was able to get the example working was to ditch find_package() altogether. The following allowed me to successfully generate the buildsystem, and compile and run the executable:

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)
like image 126
Kevin Avatar answered Nov 04 '22 14:11

Kevin