J'utilise le plus récent CMake (3.9.3) de Homebrew avec LLVM 5.0.0 également de Brew, car Clang a ici le support d'OpenMP.
Cela a fonctionné dans CMake 3.8.2 avec LLVM 5.
Dans mon CMakeLists.txt
J'ai
find_package( OpenMP )
et plus tard je veux faire
if( OpenMP_CXX_FOUND )
Cependant CMake ne semble pas reprendre la directive find_package
.
Je lance CMake avec
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DUSE_WERROR=ON
où j'ai vérifié que clang
et clang++
pointe correctement vers /usr/local/opt/llvm/bin/clang
et /usr/local/opt/llvm/bin/clang++
Tout ce que je reçois, ce sont ces deux lignes:
-- 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")
Si je mets OpenMP_C_FLAGS
Moi-même (avec -DOpenMP_C_FLAGS=-fopenmp=libomp
), Cela change l'erreur en
-- Could NOT find OpenMP_C (missing: OpenMP_C_LIB_NAMES) (found version "3.1")
Notez qu'il modifie le numéro de version, il doit donc trouver quelque chose, non?
Que me manque-t-il pour que cela fonctionne correctement?
D'accord, il semble qu'à l'intérieur du FindOpenMP.cmake
Fourni par CMake, nous faisons un try_compile
, Qui échoue silencieusement (parce que nous le faisons souvent et que la plupart échouent, cela a du sens). Cependant, avec Clang, un indicateur -Werror
Est fourni, qui échoue en raison d'un argument de ligne de commande inutilisé. Je peux donc ajouter:
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()
à mon projet parce que je sais que -fopenmp=libomp
fonctionnera pour ce Clang.
Est-ce la bonne façon de procéder?
Le message vous indique essentiellement que vous devez fournir le chemin d'accès aux bibliothèques et les noms des bibliothèques. L'exemple suivant devrait résoudre votre problème (voir aussi find_package (OpenMP) ). Notez que j'utilise l'installation de brew en utilisant la commande "brew install llvm". Les quatre premières lignes sont juste pour être complètes.
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)
Vous voudrez peut-être définir par exemple set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread")
de telle sorte que l'éditeur de liens détecte automatiquement la bibliothèque pthread appropriée (voir pthread et wiki ).
Apparemment, le cas est important. Pour un projet indépendant, je peux le faire fonctionner avec
find_package ( OPENMP REQUIRED )
Cela n'a pas fonctionné:
find_package ( OpenMP REQUIRED )
Avec cette directive, pas besoin de régler tous les autres drapeaux à la main. cmake 3.13.2, clang-1000.11.45.5 (High Sierra)
C'est peut-être une version CMake, je trouve une solution légèrement différente avec Franzi's .
J'utilise également brew install libomp
Sur ma machine. Il semble que OpenMP_CXX_FLAGS
Soit utilisé pour compiler le code source du projet au lieu de compiler l'omp (l'indicateur est stocké dans la cible omp et sera rempli par la commande target_link_libraries
).
En plus de cela, OpenMP_CXX_LIB_NAMES
Ne devrait pas avoir de préfixe lib
car cela entraînera une erreur comme -llibomp
Introuvable, où -lomp
Devrait être utilisé à la place.
J'ai également remarqué que CMAKE_C_COMPILER_ID
Est AppleClang
au lieu de Clang
si je mets project(playground)
après cmake_minimum_required
. En sens inverse, c'est Clang
, assez ennuyeux et je ne sais pas pourquoi.
Xpreprocessor
utilisé ici parce que Apple clang n'est pas livré avec OpenMP et cet indicateur indique au compilateur de rechercher pragma (extension de préprocesseur) ailleurs. Dans notre cas, c'est l'en-tête fichiers dans le chemin d'inclusion où le libomp est installé.
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)
Voici mon 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;
}
la sortie est,
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.