构建一个简单的(hello-world-esque)示例,使用$ ORIGIN使用ld的选项-rpath [英] Building a simple (hello-world-esque) example of using ld's option -rpath with $ORIGIN

查看:175
本文介绍了构建一个简单的(hello-world-esque)示例,使用$ ORIGIN使用ld的选项-rpath的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:下面是完整的工作示例。原来的问题如下:



我在使用ld的 -rpath 参数时遇到问题, $ ORIGIN

因为我找不到完整的示例,所以我想我会自己写一个,以便我和其他人可以稍后使用它。一旦我得到它的工作,我会整理它。



,但我认为我的帖子有点混乱。示例项目生成一个共享库和一个链接到所述库的可执行文件。

它非常小(3个文件,22行包含buildscript) 。

您可以从
此处下载该项目




文件结构(构建之前):


  • 项目/


    • src /


      • foo.cpp

      • main.cpp


    • make.sh







project / src / foo.cpp

  
int foo()
{return 3; }

project / src / main.cpp
$ $ p $
$ f $($)

#include< iostream>
int main()
{
std :: cout<< foo()<<的std :: ENDL;
返回0;

project / make.sh code>

  
#制作目录:
mkdir -p -v obj
mkdir -p -v lib
mkdir -p -v run

#构建库:
g ++ -c -o obj / foo.o src / foo.cpp -fPIC
g ++ -shared -o lib / foo.sh obj / foo.o

#生成可执行文件:
g ++ -c -o obj / main。 o src / main.cpp
g ++ -o run / main.run obj / main.o -Wl,-rpath,'$ ORIGIN /../../ lib'-Llib -l:foo.sh
$ / code>






项目目录下运行 make.sh (确保它是可执行的)。




文件结构(建立后):


  • 项目/


    • src /


      • foo.cpp

      • main.cpp


      • obj /


        • foo.o

        • main.o

      • lib /


        • foo.so


      • 运行/


        • main.run

        • $ b $ b





        run / main.run 现在应该加载<$



        $在执行时,从任何地方执行c $ c> lib / foo.sh
        b $ b

        问题



        目前,这只有部分工作。

        文件编译并链接正常,但运行时无法链接从项目(这是练习的要点)之外的任何目录。



        检查 main.run with readelf -d 显示:

        0x0000000000000001(需要)共享库:[ lib / foo.sh]

        0x000000000000000f(RPATH)库rpath:[$ ORIGIN /../../ lib]
        看起来很接近(我宁愿 [foo.sh] [lib / foo.sh] 但我会稍后解决)。



        AFAICT -Wl中的 $ ORIGIN ,-rpath,'$ ORIGIN /../../ lib'表示 project / run / main.run ,所以这个rpath应该变成 project / lib



        我试过 $ ORIGIN /.. $ ORIGIN /../ lib $ ORIGIN /../.. $ ORIGIN /../../ lib 无效。



        注意:我使用 -l:这需要完整的库文件名(除其他原因外,当所有函数采用相同的名称格式时,使用变量进行脚本更容易)。



        有人知道为什么这不起作用吗?

        或者,有谁知道有一个完整的工作示例?

        解决方案


        (我宁愿有 [foo.sh] than [lib / foo.sh] 但我会在稍后解决)

        $ b

        问题大部分存在:名称中的 / 阻止动态链接器执行rpath magic。



        (你的rpath也是错的,想一想:从shell中,如果你当前在你的可执行文件所在的目录中,你将如何到达你的库所在的目录?在这里,你需要 cd ../ lib 。所以你的rpath应该是 $ ORIGIN /../ lib 。)



        如果您将对象构建为 libfoo.so 并与 -Llib -lfoo ,链接器会找出你想要的,做正确的事情。但是,如果你打算使用不同寻常的命名规则,你必须提供帮助:


        1. 更改链接行为图书馆显式设置你的图书馆的SONAME只是 foo.sh



          g ++ -shared -Wl,-soname,foo.sh -o lib / foo.sh obj / foo.o


        2. 修复rpath:



          g ++ -o run / main.run obj / main.o -Wl,-rpath,'$ ORIGIN / .. / lib'-Llib -l:foo.sh


        运行 ldd main / main.run 来查看发生了什么。在你最初的失败案例中,你会看到如下所示:

          lib / foo.sh(0xNNNNNNNN)

        (缺少任何 => / some / resolved / path 显示它没有做任何路径分辨率)。在固定情况下,您会看到如下所示的内容:

          foo.sh => /your/path/to/run/../lib/foo.sh(0xNNNNNNNN)


        Note: Full working example now below. Original question follows:

        I'm having problems using ld's -rpath parameter with $ORIGIN.
        As I couldn't find a complete example, I thought I'd try to write one myself, so that I and others can use it later. Once I get it working I'll tidy it up.

        I asked about this before, but I think my post was a bit confusing.

        The example project builds one shared library and one executable that links to said library.
        It's very small (3 files, 22 lines incl buildscript).
        You can download the project from here


        File structure (before building):

        • project/
          • src/
            • foo.cpp
            • main.cpp
          • make.sh

        project/src/foo.cpp

        
        int foo()
          { return 3; }
        

        project/src/main.cpp

        
        int foo();
        
        #include <iostream>
        int main()
          {
            std::cout << foo() << std::endl;
            return 0;
          }
        

        project/make.sh

        
        # Make directories:
        mkdir -p -v obj
        mkdir -p -v lib
        mkdir -p -v run
        
        # Build the library:
        g++ -c -o obj/foo.o src/foo.cpp -fPIC
        g++ -shared -o lib/foo.sh obj/foo.o
        
        # Build the executable:
        g++ -c -o obj/main.o src/main.cpp
        g++ -o run/main.run obj/main.o -Wl,-rpath,'$ORIGIN/../../lib' -Llib -l:foo.sh
        


        From the project directory, run make.sh (make sure it's executable).


        File structure (after building):

        • project/
          • src/
            • foo.cpp
            • main.cpp
          • obj/
            • foo.o
            • main.o
          • lib/
            • foo.so
          • run/
            • main.run
          • make.sh

        run/main.run should now load lib/foo.sh on execution, from anywhere.


        Problems

        Currently, this only partly works.
        The files compile and link OK, but it fails to link when run from any directory except project (which is the point of the exercise).

        Inspecting main.run with readelf -d shows:
        0x0000000000000001 (NEEDED) Shared library: [lib/foo.sh]
        0x000000000000000f (RPATH) Library rpath: [$ORIGIN/../../lib] Which looks close (I'd rather have [foo.sh] than [lib/foo.sh] but I'll fix that later).

        AFAICT the $ORIGIN in -Wl,-rpath,'$ORIGIN/../../lib' means project/run/main.run so this rpath should become project/lib.

        I have tried $ORIGIN/.., $ORIGIN/../lib, $ORIGIN/../.., $ORIGIN/../../lib to no avail.

        Note: I'm using -l: which requires the complete library filename (amongst other reasons, it's easier to script with variables when all functions take the same name format).

        Does anyone know why this isn't working?
        Or alternately, does anyone have or know of a complete working example?

        解决方案

        (I'd rather have [foo.sh] than [lib/foo.sh] but I'll fix that later).

        There's most of your problem: the / in the name stops the dynamic linker from doing the rpath magic.

        (Your rpath is wrong too. Think about it: from the shell, if you were currently in the directory where your executable is, how would you get to the directory where your library is? Here, you'd need to cd ../lib. So your rpath should be $ORIGIN/../lib.)

        If you built your object as libfoo.so and linked with -Llib -lfoo, the linker would work out what you were intending, and do the right thing. But if you're going to use unusual naming conventions, you'll have to help it out:

        1. Change the link line for the library to explicitly set the SONAME for your library to just foo.sh:

          g++ -shared -Wl,-soname,foo.sh -o lib/foo.sh obj/foo.o

        2. Fix the rpath:

          g++ -o run/main.run obj/main.o -Wl,-rpath,'$ORIGIN/../lib' -Llib -l:foo.sh

        It's useful to run ldd main/main.run to see what's going on. In your original failing case, you'll see something like:

            lib/foo.sh (0xNNNNNNNN)
        

        (the lack of any => /some/resolved/path showing that it's not done any path resolution). In the fixed case, you'll see something like:

            foo.sh => /your/path/to/run/../lib/foo.sh (0xNNNNNNNN)
        

        这篇关于构建一个简单的(hello-world-esque)示例,使用$ ORIGIN使用ld的选项-rpath的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆