【问题标题】:Cannot statically use an installed library无法静态使用已安装的库
【发布时间】:2021-04-29 05:58:42
【问题描述】:

我正在尝试静态链接并使用我安装在系统中的库,但即使在编译/链接时我也不会出错。在运行时我会得到它们。

获取库

我下载并安装了libpfm4。我跑了makesudo 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)

我可能缺少什么?

【问题讨论】:

    标签: c linker runtime-error static-libraries libraries


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 这不是说我在动态链接吗?我想静态链接。 (显然我现在没有做的事情。)
    • @onlycparra 啊,好的。要静态链接,您必须在链接时使用-static 选项。但这将静态链接所有个可能的库。
    • 啊,我明白了,即使是不使用的,对吧?像 pthread。这很不方便。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    相关资源
    最近更新 更多