I would like to verify that the current compiler can build with openmp support. The application has do deploy across a wide variety of unix systems, some of which might have old versions of OpenMP, and I would like to test for important OpenMP functionality. So, I want to build a test source file that incorporates some of the OpenMP calls.
Thus, I created a very simple test file, and attempted to use the try_compile function from CMake. Ufortunately, it doesn't seem to apply the -fopenmp linker flag correctly. Does anyone know how to either force the linker flag or to see if the linker flag is being applied anywhere?
from 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
)
from 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;
}
The resulting output is
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
When I try to compile the test program on the command line, it works fine
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 has a standard module for testing if the compiler supports 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()
Note:
This answer is not recommended to be used anymore for including OpenMP
in the project for current CMake
versions. Refer to the other answers.
As of CMake 3.9 there are imported OpenMP targets per language. I consider this to be a much more elegant solution. Here's an example in 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)
This is more convenient since it is less typing, and this way you don't have to adjust with compile flags, libraries, etc which are error-prone. This is the direction that modern CMake is going.
If you are working with something older than CMake 3.9 I still don't recommend the currently accepted answer. I believe setting the flags per-target is better:
add_executable(solver solver.cc)
target_link_libraries(solver PRIVATE "${OpenMP_CXX_FLAGS}")
target_compile_options(solver PRIVATE "${OpenMP_CXX_FLAGS}")
This may not work with some compilers; this is partly why CMake revamped its OpenMP support in CMake 3.9.
OpenMP support has been improved in CMake 3.9+
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()
This way will correctly set the library link line differently from the compile line if needed.
In case you try to use the "modern" way with g++, you could also do:
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})
Notice:
If you would leave out only the target_compile_options your pragmas would simple be ignored (enabled warnings would tell you) If you would leave out only the target_link_libraries your code wouldn't compile, as g++ is not properly linked If you leave both out the 1. note applies rendering the linking no longer needed and your code would compile.
I don't know whether this linking "hack" with the flags is working for other compilers as well.
OpenMP_CXX_FLAGS
(no underline between Open
and MP
).
Success story sharing