不能静态使用已安装的库

问题描述

我正在尝试静态链接并使用我安装在系统中的库。但即使在编译/链接时我也没有收到错误,但在运行时我得到了错误

获取图书馆

我下载并安装了 libpfm4。跑 make sudo make install

得到这个:

installing in /usr/local
make[1]: Entering directory '/home/username/libpfm4/lib'
building: libpfm.a libpfm.so.4.11.1
mkdir -p /usr/local/lib
install -m 644 libpfm.a /usr/local/lib
install libpfm.so.4.11.1 /usr/local/lib
cd /usr/local/lib; ln -sf libpfm.so.4.11.1 libpfm.so.4
cd /usr/local/lib; ln -sf libpfm.so.4.11.1 libpfm.so
ldconfig
make[1]: Leaving directory '/home/username/libpfm4/lib'
make[1]: Entering directory '/home/username/libpfm4/tests'
make[1]: nothing to be done for 'install'.
make[1]: Leaving directory '/home/username/libpfm4/tests'
make[1]: Entering directory '/home/username/libpfm4/examples'
make[1]: nothing to be done for 'install'.
make[1]: Leaving directory '/home/username/libpfm4/examples'
make[1]: Entering directory '/home/username/libpfm4/perf_examples'
make[1]: nothing to be done for 'install'.
make[1]: Leaving directory '/home/username/libpfm4/perf_examples'
make[1]: Entering directory '/home/username/libpfm4/include'
mkdir -p /usr/local/include/perfmon
install -m 644 perfmon/pfmlib.h perfmon/perf_event.h perfmon/pfmlib_perf_event.h /usr/local/include/perfmon
make[1]: Leaving directory '/home/username/libpfm4/include'
make[1]: Entering directory '/home/username/libpfm4/docs'
mkdir -p /usr/local/share/man/man3
( cd man3; install -m 644 libpfm.3 pfm_find_event.3 pfm_get_event_attr_info.3 pfm_get_event_info.3 pfm_get_event_encoding.3 pfm_get_event_next.3 pfm_get_pmu_info.3 pfm_get_os_event_encoding.3 pfm_get_version.3 pfm_initialize.3 pfm_terminate.3 pfm_strerror.3 libpfm_intel_core.3 libpfm_intel_x86_arch.3 libpfm_amd64.3 libpfm_amd64_k7.3 libpfm_amd64_k8.3 libpfm_amd64_fam10h.3 libpfm_amd64_fam15h.3 libpfm_amd64_fam16h.3 libpfm_amd64_fam17h.3 libpfm_amd64_fam17h_zen2.3 libpfm_amd64_fam19h_zen3.3 libpfm_amd64_fam19h_zen3_l3.3 libpfm_intel_atom.3 libpfm_intel_nhm.3 libpfm_intel_nhm_unc.3 libpfm_intel_wsm.3 libpfm_intel_wsm_unc.3 libpfm_intel_snb.3 libpfm_intel_snb_unc.3 libpfm_intel_ivb.3 libpfm_intel_ivb_unc.3 libpfm_intel_hsw.3 libpfm_intel_bdw.3 libpfm_intel_rapl.3 libpfm_intel_slm.3 libpfm_intel_tmt.3 libpfm_intel_skl.3 libpfm_intel_icl.3 libpfm_intel_glm.3 libpfm_intel_knl.3 libpfm_intel_knm.3 libpfm_intel_snbep_unc_cbo.3 libpfm_intel_snbep_unc_ha.3 libpfm_intel_snbep_unc_imc.3 libpfm_intel_snbep_unc_pcu.3 libpfm_intel_snbep_unc_qpi.3 libpfm_intel_snbep_unc_ubo.3 libpfm_intel_snbep_unc_r2pcie.3 libpfm_intel_snbep_unc_r3qpi.3 libpfm_intel_ivbep_unc_cbo.3 libpfm_intel_ivbep_unc_ha.3 libpfm_intel_ivbep_unc_imc.3 libpfm_intel_ivbep_unc_pcu.3 libpfm_intel_ivbep_unc_qpi.3 libpfm_intel_ivbep_unc_ubo.3 libpfm_intel_ivbep_unc_r2pcie.3 libpfm_intel_ivbep_unc_r3qpi.3 libpfm_intel_ivbep_unc_irp.3 libpfm_intel_knc.3 libpfm_intel_hswep_unc_cbo.3 libpfm_intel_hswep_unc_ha.3 libpfm_intel_hswep_unc_imc.3 libpfm_intel_hswep_unc_irp.3 libpfm_intel_hswep_unc_pcu.3 libpfm_intel_hswep_unc_qpi.3 libpfm_intel_hswep_unc_r2pcie.3 libpfm_intel_hswep_unc_r3qpi.3 libpfm_intel_hswep_unc_sbo.3 libpfm_intel_hswep_unc_ubo.3 libpfm_intel_bdx_unc_cbo.3 libpfm_intel_bdx_unc_ha.3 libpfm_intel_bdx_unc_imc.3 libpfm_intel_bdx_unc_irp.3 libpfm_intel_bdx_unc_pcu.3 libpfm_intel_bdx_unc_qpi.3 libpfm_intel_bdx_unc_r2pcie.3 libpfm_intel_bdx_unc_r3qpi.3 libpfm_intel_bdx_unc_sbo.3 libpfm_intel_bdx_unc_ubo.3 libpfm_intel_skx_unc_cha.3 libpfm_intel_skx_unc_imc.3 libpfm_intel_skx_unc_irp.3 libpfm_intel_skx_unc_m2m.3 libpfm_intel_skx_unc_m3upi.3 libpfm_intel_skx_unc_pcu.3 libpfm_intel_skx_unc_ubo.3 libpfm_intel_skx_unc_upi.3 pfm_get_perf_event_encoding.3 libpfm_perf_event_raw.3 /usr/local/share/man/man3 )
make[1]: Leaving directory '/home/username/libpfm4/docs'

我现在可以在 /usr/local/libpfm.{a,so,so.4,so.4.11.1} 中看到图书馆

编译程序

#include <stdio.h>
#include <perfmon/pfmlib.h>

int main(int argc,char **argv){
    int idx;
    pfm_os_t os;
    pfm_event_info_t info;

    idx = 239075328;
    os = PFM_OS_NONE;
    pfm_initialize();
    pfm_get_event_info(idx,os,&info);

    printf("Name:  %s\n"
           "Desc:  %s\n"
           "Equiv: %s\n"
           "Code:  %lu\n"
           "IDX:   %d\n"
           "Attr:  %d\n",info.name,info.desc,info.equiv,info.code,info.idx,info.nattrs);

    return 0;
}

我用它来编译:

gcc -lpfm -Wall -Werror -std=gnu11 -pthread -g -o0 -fno-omit-frame-pointer -I include -o out.bin code.c

我得到了一个干净的输出

运行程序

$ ./out.bin
./out.bin: error while loading shared libraries: libpfm.so.4: cannot open shared object file: No such file or directory

如果我使用 ldd,我会得到这个:

$ ldd out.bin   
    linux-vdso.so.1 (0x00007ffc8f9fe000)
    libpfm.so.4 => not found
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fdcdcf0b000)
    libc.so.6 => /lib64/libc.so.6 (0x00007fdcdcd40000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fdcdcf44000)

我可能缺少什么?感谢您抽出宝贵时间。

解决方法

库的链接时路径和运行时路径之间存在差异。

由于库位于运行时加载器(显然)未处理的位置,因此您必须在链接时添加一个标志,以告诉链接器在运行时加载器的可执行文件中添加有关它的信息检查。

这是通过 -rpath 链接器特定标志完成的。

您可以使用带有 gcc 选项的 -Wl 传递它:

gcc ... -Wl,-rpath=/usr/local/lib -L/usr/local/lib -lpfm