3.20 Regression: FindOpenMP selects static libgomp instead of shared
Summary
Through no fault of the FindOpenMP.cmake
module that I can find, between CMake 3.19.7 and CMake 3.20.0, the default inferred OpenMP library type has changed from shared to static. Since default distributions of libgomp.a
are not -fPIC
, this can fail shared library builds.
Reproduce
Shared library build:
find_package(OpenMP REQUIRED)
[...]
target_link_libraries([...] OpenMP::OpenMP_CXX)
On a centos:7
docker image with devtoolset-9
, looking at CMakeFiles/CMakeOutput.log
where FindOpenMP
parses the output of a trial -fopenmp
compilation to figure out flags and link line:
[...]
implicit libs: [stdc++;m;gomp;gcc_s;gcc;pthread;c;gcc_s;gcc]
implicit dirs: [/opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9;/opt/rh/devtoolset-9/root/usr/lib64;/lib64;/usr/lib64;/opt/rh/devtoolset-9/root/usr/lib]
Then the find_library
calls for each implicit lib name in FindOpenMP.cmake
, around line 260:
find_library(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY
NAMES "${_OPENMP_IMPLICIT_LIB_NAME}"
DOC "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP"
HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS}
CMAKE_FIND_ROOT_PATH_BOTH
NO_DEFAULT_PATH
)
Finding, per CMakeCache.txt
:
//Path to the gomp library for OpenMP
OpenMP_gomp_LIBRARY:FILEPATH=/opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/libgomp.a
Finally populating the link line with, per link.txt
:
[...]
/opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/libgomp.a
[...]
Which fails the link by relocation errors hinting at libgomp.a
not having been built with -fPIC
. This is faulty because the -fopenmp
flag should imply shared linking with GCC as far as I know. CMake 3.19 does not show this behavior, finding libgomp.so
instead. I can reproduce this on ubuntu docker images too.
Suggested culprits
I'm frankly stumped by the change in behavior. I've only delved into the CMake module files but haven't looked into the C++ source files. I don't think any changes between 3.19 and 3.20 in the FindOpenMP.cmake
module can have caused this. My unqualified opinion on the matter is that find_library
might have changed to cause this. I might also only have myself to blame through something I don't understand or didn't know about.
Suggested fixes
It might be possible to augment the find_library
call with the right library prefixes and suffixes which could be detected by the true linked libraries with ldd
or so. As far as I can tell, the compiler output that is parsed doesn't actually offer any clues as to which OpenMP library type was linked (short of tracking the spec file and imitating its logic), and only the resulting binary has that information. If that is true, then FindOpenMP.cmake
is currently somewhat fragile. Perhaps the information of whether to link static or shared openmp is present on the link line, but the parsing module does not capture that information.
Alternatively, the OpenMP target property population module code could be altered not to include any found omp
library at all, since this is implied in the -fopenmp
flag in the few compilers I know.
There is also no way to select the OpenMP library type desired, so this may present an opportunity to improve the module.