web-dev-qa-db-ja.com

MacOS、CMake、OpenMP

ClangはOpenMPをサポートしているため、Homebrewの最新のCMake(3.9.3)とBrewのLLVM 5.0.0を使用しています。

これは、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

ここで、clangおよびclang++/usr/local/opt/llvm/bin/clangおよび/usr/local/opt/llvm/bin/clang++を正しく指していることを確認しました

私が得るすべてはこれらの2行です:

-- 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で機能することを知っているので、私のプロジェクトに。

これは正しい方法ですか?

9
Mads Ohm Larsen

このメッセージは基本的に、ライブラリへのパスとライブラリの名前を指定する必要があることを示しています。次の例は問題を解決するはずです( find_package(OpenMP) も参照)。 「brew install llvm」コマンドを使用してbrewインストールを使用していることに注意してください。最初の4行は、完全を期すためのものです。

_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ライブラリを自動的に検出します( pthread および wiki を参照)。

14
Franzi

どうやら、ケースは重要です。無関係なプロジェクトの場合は、

find_package ( OPENMP REQUIRED )

これはうまくいきませんでした:

find_package ( OpenMP REQUIRED )

このディレクティブを使用すると、他のすべてのフラグを手動で設定する必要がなくなります。 cmake 3.13.2、clang-1000.11.45.5(High Sierra)

6
mjskier

多分それはCMakeバージョンのものかもしれませんが、私は Franzi's で少し異なる解決策を考え出します。

私のマシンでも_brew install libomp_を使用しています。 _OpenMP_CXX_FLAGS_は、ompをコンパイルする代わりにプロジェクトソースコードのコンパイルに使用されるようです(フラグはompターゲットに格納され、コマンド_target_link_libraries_によって入力されます)。

それ以外に、_OpenMP_CXX_LIB_NAMES_の前にlibを付けないでください。_-llibomp_が見つからないなどのエラーが発生するため、代わりに_-lomp_を使用する必要があります。

_CMAKE_C_COMPILER_ID_の後にproject(playground)を置くと、_cmake_minimum_required_がAppleClangではなくClangであることに気付きました。逆に、それはClangで、非常に煩わしく、その理由はわかりません。

ここで使用されているXpreprocessorは、Apple clangがOpenMPに同梱されておらず、このフラグがコンパイラに他の場所でプラグマ(プリプロセッサ拡張)を探すように指示するためです。この場合、それはヘッダーです。 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.
_
0
Izana