Wednesday, January 5, 2022

[SOLVED] Is this explicit linking against OpenMP::OpenMP_CXX still necessary with this CMake linking command?

Issue

I am using CMake and GNU's parallel algorithms and the following code snippet in my CMakeLists.txt:

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().

Does that make the following command redundant?

target_link_libraries(MyTarget OpenMP::OpenMP_CXX)?

I have tried to find the answer here but to no avail. Upon printing the output of the above variables using the message command, I see that the last two are empty.

-- OpenMP_CXX_FLAGS are: -fopenmp
-- OpenMP_C_FLAGS are: -Xclang -fopenmp 
-- CMAKE_EXE_LINKER_FLAGS are:  
-- OpenMP_EXE_LINKER_FLAGS are:

I tried looking up the variable definition here but did not find out anything more. A small test programme using:

__gnu_parallel::for_each 

ran in parallel regardless whether I included:

target_link_libraries(MyTarget OpenMP::OpenMP_CXX) 

which leads me to conclude that it is not necessary. Is that true?

My gcc is g++-9 (Homebrew GCC 9.3.0_1) 9.3.0.


Solution

While the code:

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")

will update your C++ compile flags with the proper -fopenmp option, this is an old antiquated approach.

By linking against the provided imported target OpenMP::OpenMP_CXX, you achieve the same effect because this target provides the -fopenmp compile option in its INTERFACE_COMPILE_OPTIONS property. Likewise, this imported target propagates any dependent OpenMP libraries you may need (depending on the language), which would otherwise require an additional manual step of linking to ${OpenMP_CXX_LIBRARIES}. So, linking directly to the imported target OpenMP::OpenMP_CXX should be the preferred approach; it saves you the extra manual steps and adheres to modern CMake axioms:

target_link_libraries(MyTarget PRIVATE OpenMP::OpenMP_CXX)

Note, the official documentation for the CMake OpenMP Find Module, and the variables/targets it provides, is here.



Answered By - Kevin