如何在CMake的try_compile函数中为OpenMP设置链接器标志

dus*_*der 48 cmake openmp

我想验证当前编译器是否可以使用openmp支持构建.该应用程序已经部署在各种各样的unix系统上,其中一些可能有旧版本的OpenMP,我想测试重要的OpenMP功能.所以,我想构建一个包含一些OpenMP调用的测试源文件.

因此,我创建了一个非常简单的测试文件,并尝试使用CMake的try_compile函数.遗憾的是,它似乎没有正确应用-fopenmp链接器标志.有谁知道如何强制链接器标志或查看链接器标志是否被应用于任何地方?

来自CMakeLists.txt

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
    )
Run Code Online (Sandbox Code Playgroud)

来自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;
}
Run Code Online (Sandbox Code Playgroud)

结果输出是

Change Dir: src/config/CMakeFiles/CMakeTmp

Run Build Command:/usr/bin/make "cmTryCompileExec/fast"
/usr/bin/make -f CMakeFiles/cmTryCompileExec.dir/build.make CMakeFiles/cmTryCompileExec.dir/build
make[1]: Entering directory `src/config/CMakeFiles/CMakeTmp'
/usr/bin/cmake -E cmake_progress_report /data/work/source/apbs/src/config/CMakeFiles/CMakeTmp/CMakeFiles 1
Building C object CMakeFiles/cmTryCompileExec.dir/omp_test.c.o
/usr/bin/gcc    -o CMakeFiles/cmTryCompileExec.dir/omp_test.c.o   -c /data/work/source/apbs/src/config/omp_test.c
Linking C executable cmTryCompileExec
/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec.dir/link.txt --verbose=1
/usr/bin/gcc         CMakeFiles/cmTryCompileExec.dir/omp_test.c.o  -o cmTryCompileExec -rdynamic 
CMakeFiles/cmTryCompileExec.dir/omp_test.c.o: In function `main':
omp_test.c:(.text+0x19): undefined reference to `omp_get_thread_num'
collect2: ld returned 1 exit status
make[1]: *** [cmTryCompileExec] Error 1
make[1]: Leaving directory `src/config/CMakeFiles/CMakeTmp'
make: *** [cmTryCompileExec/fast] Error 2

CMake Error at CMakeLists.txt:688 (message):
  Test OpenMP program would not build.  OpenMP disabled
Run Code Online (Sandbox Code Playgroud)

当我尝试在命令行上编译测试程序时,它工作正常

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
Run Code Online (Sandbox Code Playgroud)

sak*_*kra 119

如果编译器支持OpenMP,CMake有一个标准模块用于测试:

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()
Run Code Online (Sandbox Code Playgroud)

  • 还需要设置链接器标志.我不知道如何设置它们,但是应该警告读者. (5认同)
  • 真棒!我想知道为什么我在搜索中没有找到这个...我假设它正确处理不同的编译器(icc,gcc,borland等)标志? (4认同)
  • 看看FindOpenMP.cmake源代码,它似乎可以处理GNU,MSVC,Intel,Sun,HP,IBM和MIPSpro编译器. (2认同)

Lev*_*son 39

从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)
Run Code Online (Sandbox Code Playgroud)

这样更方便,因为它更少键入,这样您就不必使用容易出错的编译标志,库等进行调整.这是现代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}")
Run Code Online (Sandbox Code Playgroud)

这可能不适用于某些编译器; 这也是CMake在CMake 3.9中改进其OpenMP支持的部分原因.


Moj*_*oko 6

如果您尝试在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})
Run Code Online (Sandbox Code Playgroud)

注意:

  1. 如果仅保留target_compile_options,那么编译指示将被忽略(启用的警告会告诉您)

  2. 如果您只留下了target_link_libraries,那么您的代码将无法编译,因为g ++没有正确链接

  3. 如果您都忽略了1.注释,则不再需要链接,代码将被编译。

我不知道这种将“ hack”与标志链接起来是否也适用于其他编译器。


ase*_*sni 5

在CMake 3.9+中,OpenMP支持得到了显着改善

CMakeLists.txt

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()
Run Code Online (Sandbox Code Playgroud)

如果需要,这种方式将正确地将库链接行设置为与编译行不同。

来源

  • 赞成,因为它显示了包含 OpenMP(即使用目标)的正确方法,以防它是可选依赖项,这与包括我自己的现有答案不同。 (4认同)