OpenMP with clang links to system libomp.so or drops rpath, when clang in non-standard location.
This issue comes up with hipcc, but I think it can be reproduced when just using clang from LLVM + OpenMP project enabled in a non-system location (where the llvm/lib folder is not in the dynamic linker's search path).
For example I have a main.cpp like this:
#include <iostream>
#include <sstream>
#include <omp.h>
int main() {
#pragma omp parallel
{
std::stringstream ss;
ss << "hello world from " << omp_get_thread_num() << '\n';
std::cout << ss.str();
}
}
And I'm using AMD's clang++ to compile with -fopenmp
:
$ docker run --rm -v $PWD:/sources -w /sources rocm/dev-ubuntu-18.04 bash -c "/opt/rocm/llvm/bin/clang++ -fopenmp main.cpp && readelf -d ./a.out && ldd ./a.out"
0x0000000000000001 (NEEDED) Shared library: [libomp.so]
0x000000000000001d (RUNPATH) Library runpath: [/opt/rocm-4.0.0/llvm/bin/../lib]
libomp.so => /opt/rocm-4.0.0/llvm/bin/../lib/libomp.so (0x00007f2647aaf000)
It ends up linking to /opt/rocm-4.0.0/llvm/lib/libomp.so
and setting the RPATH. That's what I would expect CMake to do.
However, when I try something similar with CMake:
cmake_minimum_required(VERSION 3.0.0)
project(TestOpenMP LANGUAGES CXX)
set(CMAKE_VERBOSE_MAKEFILE ON)
find_package(OpenMP REQUIRED)
add_executable(main main.cpp)
target_link_libraries(main OpenMP::OpenMP_CXX)
it (a) links to the system libomp.so when that is installed or (b) does not set the rpath to clang's libomp.so so that it cannot be found at runtime. Just the relevant bits:
$ docker run --rm -w /sources/ -v $PWD:/sources rocm/dev-ubuntu-18.04 bash -c 'apt-get update -qq &> /dev/null && apt-get install -qq wget tar &> /dev/null && wget -qO- "https://cmake.org/files/v3.19/cmake-3.19.4-Linux-x86_64.tar.gz" | tar --strip-components=1 -xz -C /usr/local && rm -rf build && mkdir build && cd build && cmake -DCMAKE_CXX_COMPILER=/opt/rocm/llvm/bin/clang++ .. && make && readelf -d main && ldd main'
-- The CXX compiler identification is Clang 12.0.0
-- Check for working CXX compiler: /opt/rocm/llvm/bin/clang++
-- Found OpenMP_CXX: -fopenmp=libomp (found version "5.0")
/opt/rocm/llvm/bin/clang++ -fopenmp=libomp -o CMakeFiles/main.dir/main.cpp.o -c /sources/main.cpp
/opt/rocm/llvm/bin/clang++ -rdynamic CMakeFiles/main.dir/main.cpp.o -o main -lomp -lpthread
0x0000000000000001 (NEEDED) Shared library: [libomp.so]
libomp.so => not found
If I install libomp-dev, it links to the system libomp:
$ docker run --rm -w /sources/ -v $PWD:/sources rocm/dev-ubuntu-18.04 bash -c 'apt-get update -qq &> /dev/null && apt-get install -qq wget tar libomp-dev &> /dev/null && wget -qO- "https://cmake.org/files/v3.19/cmake-3.19.4-Linux-x86_64.tar.gz" | tar --strip-components=1 -xz -C /usr/local && rm -rf build && mkdir build && cd build && cmake -DCMAKE_CXX_COMPILER=/opt/rocm/llvm/bin/clang++ .. && make && readelf -d main && ldd main'
-- The CXX compiler identification is Clang 12.0.0
-- Check for working CXX compiler: /opt/rocm/llvm/bin/clang++
-- Found OpenMP_CXX: -fopenmp=libomp (found version "5.0")
/opt/rocm/llvm/bin/clang++ -fopenmp=libomp -o CMakeFiles/main.dir/main.cpp.o -c /sources/main.cpp
/opt/rocm/llvm/bin/clang++ -rdynamic CMakeFiles/main.dir/main.cpp.o -o main -lomp -lpthread
0x0000000000000001 (NEEDED) Shared library: [libomp.so.5]
libomp.so.5 => /usr/lib/x86_64-linux-gnu/libomp.so.5 (0x00007fe0dcec5000)
Which is probably not what you would want.
Is there a reason CMake doesn't use -fopenmp=libomp
as a linker flag?
If -lomp -lpthread
was replaced with -fopenmp=libomp
, then it would the expected libomp shipped with llvm/clang both during linking and runtime, without having to figure out rpaths or setting LD_LIBRARY_PATH.