Issues with `opmi-cxx.pc`'s ldflags and `pkg_check_modules(... IMPORTED_TARGET ...)`

Hi! I’ve been looking into linking openmpi using its .pc files (I’ve got a separate question about FindMPI.cmake, but this post is about using the pkg-config information explicitly), and I found myself confused by how cmake translates LD_FLAGS into INTERFACE_LINK_OPTIONS. Cf. the transcript and annotations:

❯ cat CMakeLists.txt 
...
find_package(PkgConfig)
pkg_check_modules(MPI_CXX REQUIRED IMPORTED_TARGET mpi-cxx)
add_library(MPI::MPI_CXX ALIAS PkgConfig::MPI_CXX)
...
target_link_libraries(roundtrip PRIVATE MPI::MPI_CXX)

Aside from the -L flags, ompi-cxx.pc lists a number of arguments preceded by -Wl,-rpath. I’m not sure why, maybe they use dlopen:

❯ pkg-config --libs mpi-cxx
-L/nix/store/radkdwgnz90jx0fjssajsikjymp631cb-openmpi-4.1.6/lib -L/nix/store/iyzz6m4dr6grn10qi67a1g1lp3wrnk7j-libfabric-1.20.0-dev/lib -L/nix/store/bfk76ihs1whd9l51pq1s93sn0j2zd6zq-pmix-5.0.1/lib -L/nix/store/bdd88wiwfzyi7fh04f04y05y7kh1ycz0-libnl-3.7.0-dev/lib -L/nix/store/c8byxr5hgiqyf69d3jr51wgi7g420xsl-libpsm2-12.0.1/lib -Wl,-rpath -Wl,/nix/store/radkdwgnz90jx0fjssajsikjymp631cb-openmpi-4.1.6/lib -Wl,-rpath -Wl,/nix/store/iyzz6m4dr6grn10qi67a1g1lp3wrnk7j-libfabric-1.20.0-dev/lib -Wl,-rpath -Wl,/nix/store/bfk76ihs1whd9l51pq1s93sn0j2zd6zq-pmix-5.0.1/lib -Wl,-rpath -Wl,/nix/store/bdd88wiwfzyi7fh04f04y05y7kh1ycz0-libnl-3.7.0-dev/lib -Wl,-rpath -Wl,/nix/store/c8byxr5hgiqyf69d3jr51wgi7g420xsl-libpsm2-12.0.1/lib -Wl,--enable-new-dtags -lmpi_cxx -lmpi

These are directly translated into the MPI_CXX_LDFLAGS_OTHER and MPI_CXX_LIBRARIES used for the imported target:

❯ ... build ...
...
samples> -- Checking for module 'mpi-cxx'                
samples> --   Found mpi-cxx, version 4.1.6                                                                            
samples> MPI_CXX_CFLAGS=-I/nix/store/radkdwgnz90jx0fjssajsikjymp631cb-openmpi-4.1.6/include
samples> MPI_CXX_CFLAGS_OTHER=                
samples> MPI_CXX_LDFLAGS=-L/nix/store/radkdwgnz90jx0fjssajsikjymp631cb-openmpi-4.1.6/lib;-L/nix/store/iyzz6m4dr6grn10qi67a1g1lp3wrnk7j-libfabric-1.20.0-dev/lib;-L/nix/store/bfk76ihs1whd9l51pq1s93sn0j2zd6zq-pmix-5.0.1/lib;-L/nix/store/bd
d88wiwfzyi7fh04f04y05y7kh1ycz0-libnl-3.7.0-dev/lib;-L/nix/store/c8byxr5hgiqyf69d3jr51wgi7g420xsl-libpsm2-12.0.1/lib;-Wl,-rpath;-Wl,/nix/store/radkdwgnz90jx0fjssajsikjymp631cb-openmpi-4.1.6/lib;-Wl,-rpath;-Wl,/nix/store/iyzz6m4dr6grn10qi
67a1g1lp3wrnk7j-libfabric-1.20.0-dev/lib;-Wl,-rpath;-Wl,/nix/store/bfk76ihs1whd9l51pq1s93sn0j2zd6zq-pmix-5.0.1/lib;-Wl,-rpath;-Wl,/nix/store/bdd88wiwfzyi7fh04f04y05y7kh1ycz0-libnl-3.7.0-dev/lib;-Wl,-rpath;-Wl,/nix/store/c8byxr5hgiqyf69d

At link time, however, the compiler is executed with modified ldflags where all but the first -Wl,-rpath are omitted, such that -Wl,...-libfabric-1.20.0-dev/lib is seemingly interpreted as an object to link, rather than as a search path:

3jr51wgi7g420xsl-libpsm2-12.0.1/lib;-Wl,--enable-new-dtags;-lmpi_cxx;-lmpi                                                                                                                                                                  
samples> MPI_CXX_LDFLAGS_OTHER=-Wl,-rpath;-Wl,/nix/store/radkdwgnz90jx0fjssajsikjymp631cb-openmpi-4.1.6/lib;-Wl,-rpath;-Wl,/nix/store/iyzz6m4dr6grn10qi67a1g1lp3wrnk7j-libfabric-1.20.0-dev/lib;-Wl,-rpath;-Wl,/nix/store/bfk76ihs1whd9l51pq
1s93sn0j2zd6zq-pmix-5.0.1/lib;-Wl,-rpath;-Wl,/nix/store/bdd88wiwfzyi7fh04f04y05y7kh1ycz0-libnl-3.7.0-dev/lib;-Wl,-rpath;-Wl,/nix/store/c8byxr5hgiqyf69d3jr51wgi7g420xsl-libpsm2-12.0.1/lib;-Wl,--enable-new-dtags
samples> MPI_CXX_LIBRARIES=mpi_cxx;mpi
...
samples> /nix/store/sfgnb6rr428bssyrs54d6d0vv2avi95c-gcc-wrapper-12.3.0/bin/g++ -O3 -DNDEBUG -Wl,-rpath -Wl,/nix/store/radkdwgnz90jx0fjssajsikjymp631cb-openmpi-4.1.6/lib -Wl,/nix/store/iyzz6m4dr6grn10qi67a1g1lp3wrnk7j-libfabric-1.20.0-dev/lib -Wl,/nix/store/bfk76ihs1whd9l51pq1s93sn0j2zd6zq-pmix-5.0.1/lib -Wl,/nix/store/bdd88wiwfzyi7fh04f04y05y7kh1ycz0-libnl-3.7.0-dev/lib -Wl,/nix/store/c8byxr5hgiqyf69d3jr51wgi7g420xsl-libpsm2-12.0.1/lib -Wl,--enable-new-dtags CMakeFiles/roundtrip.dir/exercise_sheets/sheet3/time.cc.o -o roundtrip  /nix/store/radkdwgnz90jx0fjssajsikjymp631cb-openmpi-4.1.6/lib/libmpi_cxx.so /nix/store/radkdwgnz90jx0fjssajsikjymp631cb-openmpi-4.1.6/lib/libmpi.so
samples> /nix/store/fzlkaj1ax7gl655blfcr6zzvml1vx3bj-binutils-2.40/bin/ld: error: /nix/store/iyzz6m4dr6grn10qi67a1g1lp3wrnk7j-libfabric-1.20.0-dev/lib: read: Is a directory
samples> collect2: error: ld returned 1 exit status

Is my interpretation of the events above correct? At which stage do you think the -Wl,-rpaths are being reduced? Is there anything off with openmpi’s .pc?

Attaching the full file as well:

❯ cat /nix/store/radkdwgnz90jx0fjssajsikjymp631cb-openmpi-4.1.6/lib/pkgconfig/ompi-cxx.pc 
# Copyright (c) 2010 Cisco Systems, Inc.  All rights reserved.
# Copyright (c) 2016      IBM Corporation.  All rights reserved.
#
Name: Open MPI
Description: Portable high-performance MPI implementation
Version: 4.1.6
URL: http://www.open-mpi.org/
#
prefix=/nix/store/radkdwgnz90jx0fjssajsikjymp631cb-openmpi-4.1.6
exec_prefix=${prefix}
includedir=/nix/store/radkdwgnz90jx0fjssajsikjymp631cb-openmpi-4.1.6/include
libdir=/nix/store/radkdwgnz90jx0fjssajsikjymp631cb-openmpi-4.1.6/lib
pkgincludedir=${includedir}/openmpi
#
# Note that -lopen-pal and all the EXTRA_LIBS are only necessary when
# static linking (they're pulled in by libopen-rte.so's implicit
# dependencies), so only list these in Libs.private.
#
Libs: -L${libdir} -L/nix/store/iyzz6m4dr6grn10qi67a1g1lp3wrnk7j-libfabric-1.20.0-dev/lib -L/nix/store/bfk76ihs1whd9l51pq1s93sn0j2zd6zq-pmix-5.0.1/lib -L/nix/store/bdd88wiwfzyi7fh04f04y05y7kh1ycz0-libnl-3.7.0-dev/lib -L/nix/store/c8byxr5hgiqyf69d3jr51wgi7g420xsl-libpsm2-12.0.1/lib   -Wl,-rpath -Wl,${libdir}  -Wl,-rpath -Wl,/nix/store/iyzz6m4dr6grn10qi67a1g1lp3wrnk7j-libfabric-1.20.0-dev/lib -Wl,-rpath -Wl,/nix/store/bfk76ihs1whd9l51pq1s93sn0j2zd6zq-pmix-5.0.1/lib -Wl,-rpath -Wl,/nix/store/bdd88wiwfzyi7fh04f04y05y7kh1ycz0-libnl-3.7.0-dev/lib -Wl,-rpath -Wl,/nix/store/c8byxr5hgiqyf69d3jr51wgi7g420xsl-libpsm2-12.0.1/lib -Wl,--enable-new-dtags -lmpi_cxx -lmpi
Libs.private: -lopen-rte -lopen-pal -lhwloc -lfabric -lucp -luct -lucm -lucs -libverbs -lrdmacm -levent_core -levent_pthreads -lpmix -lnl-3 -lnl-route-3 -lucc -lpsm2 -lm  -lz
#
Cflags: -I${includedir}

Thanks!

There’s a deduplication phase that remove duplicate arguments. -Wl,-rpath is found multiple times and removed. While it is “fine” in the .pc file as-is, CMake’s pkg-config support needs to understand the flags to do things like this. A fix that could be done is to use -Wl,-rpath,/path instead of split arguments. Other than that, it would be better if PkgConfig would understand these flags and expose them as LINKER: link options instead, but that is…non-trivial.

1 Like

Thanks @ben.boeckel. Tracking in openmpi-4.1.2: ldflags in pkg-config incompatible with CMake's pkg_check_modules(... IMPORTED_TARGET ...) · Issue #12194 · open-mpi/ompi · GitHub