CMake之RPath

CMake之RPath

 

其实rpath并不是定义或者发明的,这个东西是linux的东西,为什么把它和CMake放在一起讨论呢?是因为鄙人之前一直用手写Makefile来管理和编译工程,但是如今使用CMake,结果发现编译出来的可执行文件的链接到绝对路径的动态库,这样可执行文件就不可以拷贝到别的机器执行了,而之前使用makefile就没有这个问题。

[xxx@localhost src]$ ldd speaker
    linux-vdso.so.1 =>  (0x00007fff19124000)
    libgreetings.so => /home/xxx/study/tryCMake/build/src/greetings/libgreetings.so (0x00007f4bdbe43000)
    libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f4bdbb22000)
    libm.so.6 => /lib64/libm.so.6 (0x00007f4bdb820000)
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f4bdb60a000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f4bdb248000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f4bdc046000)

 

这是什么问题,后来发现是rpath的导致。

先说说rpath是什么玩意,它是定义在ELF文件头中用来告诉该可执行文件依赖的动态库的绝对路径,ELF文件对应的windows的PE(portable executable),是

Executable and Linkable Format 或者是 Extensible Linking Format

的缩写。

这种文件都有一个头,那么怎么查看这个文件的头部来验证上面的说法,使用linux自带的工具readelf

 

[xxx@localhost build]$ readelf -d src/speaker

Dynamic section at offset 0xdd8 contains 29 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libgreetings.so]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: [/home/xxx/study/tryCMake/build/src/greetings:]
 0x000000000000000c (INIT)               0x400910
 0x000000000000000d (FINI)               0x400bb4
 0x0000000000000019 (INIT_ARRAY)         0x600db8
 0x000000000000001b (INIT_ARRAYSZ)       16 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x600dc8
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x400298
 0x0000000000000005 (STRTAB)             0x400570
 0x0000000000000006 (SYMTAB)             0x400300
 0x000000000000000a (STRSZ)              546 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000003 (PLTGOT)             0x601000
 0x0000000000000002 (PLTRELSZ)           216 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x400838
 0x0000000000000007 (RELA)               0x400808
 0x0000000000000008 (RELASZ)             48 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x4007c8
 0x000000006fffffff (VERNEEDNUM)         2
 0x000000006ffffff0 (VERSYM)             0x400792
 0x0000000000000000 (NULL)               0x0

那么怎么让cmake不要把rpath放在ELF文件中呢?就需要用到CMAKE_SKIP_RPATH这个变量,cmake就是根据这个变量来是否设置rpath,

set(CMAKE_SKIP_RPATH TRUE)

将上面这行放在顶级的CMakeLists.txt文件中,就可以了。

但是这样带来问题,你当前的编译出来的可执行文件,说找不到依赖的动态库了,怎么办呢?使用 LD_LIBRARY_PATH或者 使用ldconfig命令

另外提一点:

cmake的install可以去掉ELF文件头rpath。如果用cmake的cpack来打包的话,rpath也不是问题。

 

版权所有,禁止转载. 如需转载,请先征得博主的同意,并且表明文章转载自:IT夜班车,否则按侵权处理.

    分享到:

Leave a Reply

Your email address will not be published. Required fields are marked *