如何在CMake';s try_编译函数
我想验证当前编译器是否可以使用openmp支持构建。该应用程序已经部署在各种各样的unix系统上,其中一些可能有旧版本的OpenMP,我想测试重要的OpenMP功能。因此,我想构建一个包含一些OpenMP调用的测试源文件 因此,我创建了一个非常简单的测试文件,并尝试使用CMake的try_compile函数。不幸的是,它似乎没有正确应用-fopenmp链接器标志。是否有人知道如何强制链接器标志或查看链接器标志是否应用于任何地方 来自CMakeLists.txt如何在CMake';s try_编译函数,cmake,openmp,Cmake,Openmp,我想验证当前编译器是否可以使用openmp支持构建。该应用程序已经部署在各种各样的unix系统上,其中一些可能有旧版本的OpenMP,我想测试重要的OpenMP功能。因此,我想构建一个包含一些OpenMP调用的测试源文件 因此,我创建了一个非常简单的测试文件,并尝试使用CMake的try_compile函数。不幸的是,它似乎没有正确应用-fopenmp链接器标志。是否有人知道如何强制链接器标志或查看链接器标志是否应用于任何地方 来自CMakeLists.txt try_compile(
try_compile(
HAVE_OPENMP
${APBS_ROOT}/src/config
${APBS_ROOT}/src/config/omp_test.c
CMAKE_FLAGS "-DCMAKE_C_FLAGS=-fopenmp -DCMAKE_EXE_LINKER_FLAGS=-fopenmp"
OUTPUT_VARIABLE TRY_COMPILE_OUTPUT
)
来自omp_test.c
#include <stdio.h>
#include <omp.h>
int main()
{
int i;
int threadID = 0;
#pragma omp parallel for private(i, threadID)
for(i = 0; i < 16; i++ )
{
threadID = omp_get_thread_num();
#pragma omp critical
{
printf("Thread %d reporting\n", threadID);
}
}
return 0;
}
当我尝试在命令行上编译测试程序时,它运行良好
src/config$ gcc -fopenmp omp_test.c -o omp_test && ./omp_test
Thread 1 reporting
Thread 4 reporting
Thread 7 reporting
Thread 11 reporting
Thread 9 reporting
Thread 12 reporting
Thread 6 reporting
Thread 8 reporting
Thread 15 reporting
Thread 13 reporting
Thread 10 reporting
Thread 0 reporting
Thread 3 reporting
Thread 2 reporting
Thread 5 reporting
Thread 14 reporting
CMake具有用于测试编译器是否支持OpenMP的功能:
find_package(OpenMP)
if (OPENMP_FOUND)
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()
注意:对于当前的
CMake
版本,不建议在项目中包含OpenMP
时再使用此答案。请参阅其他答案。如果您尝试使用g++的“现代”方式,您还可以执行以下操作:
find_package(OpenMP REQUIRED)
add_executable(Foo foo.cpp)
target_compile_options(Foo PRIVATE -Wall ${OpenMP_CXX_FLAGS})
target_link_libraries(Foo PRIVATE ${OpenMP_CXX_FLAGS})
注意:
我不知道这个带有标志的链接“hack”是否也适用于其他编译器。从CMake 3.9开始,每种语言都有导入的OpenMP目标。我认为这是一个更优雅的解决方案。下面是C++中的一个示例:
cmake_minimum_required(VERSION 3.9)
project(solver LANGUAGES CXX)
find_package(OpenMP REQUIRED)
add_executable(solver solver.cc)
target_link_libraries(solver PRIVATE OpenMP::OpenMP_CXX)
这更方便,因为它的类型更少,这样您就不必使用编译标志、库等进行调整,因为编译标志、库等容易出错。这是现代CMake的发展方向
如果您使用的是比CMake 3.9更旧的版本,我仍然不推荐使用。我认为设置每个目标的标志更好:
add_executable(solver solver.cc)
target_link_libraries(solver PRIVATE "${OpenMP_CXX_FLAGS}")
target_compile_options(solver PRIVATE "${OpenMP_CXX_FLAGS}")
这可能不适用于某些编译器;这就是为什么CMake在CMake 3.9中改进了OpenMP支持的部分原因。OpenMP在CMake 3.9中得到了改进+ CMakeLists.txt 如果需要,这种方法将正确地将库链接行设置为不同于编译行
.太棒了!我想知道为什么我在搜索中没有找到这个。。。我假设它正确处理不同的编译器(icc、gcc、borland等)标志?查看FindOpenMP.cmake源代码,它似乎处理GNU、MSVC、Intel、Sun、HP、IBM和MIPSpro编译器。链接器标志也需要设置。我不知道如何设置它们,但请读者注意。如果您的OpenMP是通过您的gcc安装拉取的,那么find_package()调用仍然是针对OpenMP的,还是使用其他名称?我无法让CLion在使用OpenMP的简单多线程程序的命令行中执行!CMAKE_EXE_链接器_标志不存在且不需要。模块文档也没有提到任何关于该标志的内容。变量应该是
OpenMP\u CXX\u FLAGS
(在Open
和MP
之间没有下划线)。如果您使用的是CLion:我认为它不起作用,因为CMake无法找到OpenMP。然后我在命令行上尝试了一下,它成功了。因此,CMake缓存存在问题。转到工具->CMake->重置缓存并重新加载项目为我修复了它为什么是私有的而不是公共的?如果我对CMake的不成熟理解是正确的,那么PUBLIC也是合理的,因为链接使用OpenMP构建的库需要再次使用-fopenmp标志,请参阅。实际上,这并没有什么区别,因为它位于默认的header/lib搜索路径上,但我想知道正确的方法。“为什么是PRIVATE而不是PUBLIC[?]”只有在内部和外部接口都需要时才使用PUBLIC。我展示了一个可执行文件,所以在实践中它是没有意义的,我更喜欢默认为PRIVATE而不是PUBLIC。但在库中,它可能仍然是私有的,因为您通常不会在头中公开OpenMP类型。Up投票,因为它显示了正确的方式来包含OpenMP(即使用目标),以防它是可选依赖项,而不是现有的答案,包括我自己的答案。
add_executable(solver solver.cc)
target_link_libraries(solver PRIVATE "${OpenMP_CXX_FLAGS}")
target_compile_options(solver PRIVATE "${OpenMP_CXX_FLAGS}")
cmake_minimum_required(VERSION 3.9)
project(openmp_test) # you can change the project name
find_package(OpenMP)
add_executable(openmp_para_test main.cpp) # you can change the excutable name
if(OpenMP_CXX_FOUND)
target_link_libraries(openmp_para_test PUBLIC OpenMP::OpenMP_CXX)
endif()