V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wowbaby
V2EX  ›  程序员

求助 cmake 编译 @rpath 问题

  •  
  •   wowbaby · 2023-04-16 10:25:50 +08:00 · 1427 次点击
    这是一个创建于 591 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这块不熟,我现在遇到的问题

    libheif 依赖 aom 而 aom 编译后的文件使用了 @rpath, 导致环境变量中必须设置 export DYLD_LIBRARY_PATH="/usr/local/aom/3.6.0/lib/:$DYLD_LIBRARY_PATH" 后 libheif 可以正常 找到 aom 的 dylib ,这倒是没有问题,但问题是我编译安装其它软件时,所有依赖 libheif 的编译,都会提示:

    dyld: Library not loaded: @rpath/libaom.3.dylib Referenced from: /usr/local/libheif/1.15.2/lib/libheif.1.dylib Reason: image not found

    cmake 编译如何去除这个 @rpath 改为绝对路径, 如 @rpath/libaom.3.dylib 改为 /usr/local/aom/3.6.0/lib/libaom.3.dylib

    有一些参数,目前试过没有成功 CMAKE_SKIP_BUILD_RPATH CMAKE_BUILD_WITH_INSTALL_RPATH CMAKE_INSTALL_RPATH_USE_LINK_PATH

    git clone https://aomedia.googlesource.com/aom cd aom mkdir -p ../aom_build cd ../aom_build

    cmake /Users/xx/Downloads/aom -DCMAKE_INSTALL_PREFIX=/usr/local/aom/3.6.0 -DENABLE_DOCS=0 -DENABLE_EXAMPLES=1 -DENABLE_TESTDATA=0 -DENABLE_TESTS=0 -DENABLE_TOOLS=0 -DBUILD_SHARED_LIBS=1 -DCONFIG_TUNE_BUTTERAUGLI=1 -DCONFIG_TUNE_VMAF=1 这里改怎么设置

    aom:

    otool -L /usr/local/aom/3.6.0/bin/aomenc
    /usr/local/aom/3.6.0/bin/aomenc:
    	@rpath/libaom.3.dylib (compatibility version 3.0.0, current version 3.6.0) #要改这里为绝对路径
    	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 800.7.0)
    	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
    

    heif:

    
    otool -L /usr/local/libheif/1.15.2/bin/heif-enc
    /usr/local/libheif/1.15.2/bin/heif-enc:
    	/usr/local/libheif/1.15.2/lib/libheif.1.dylib (compatibility version 17.0.0, current version 17.2.0)
    	@rpath/libaom.3.dylib (compatibility version 3.0.0, current version 3.6.0)
    	/usr/local/opt/libvmaf/lib/libvmaf.1.dylib (compatibility version 1.0.0, current version 1.0.0)
    	/usr/local/opt/[email protected]/lib/libjxl.0.6.dylib (compatibility version 0.6.0, current version 0.6.1)
    	/usr/local/opt/libde265/lib/libde265.0.dylib (compatibility version 2.0.0, current version 2.4.0)
    	/usr/local/opt/x265/lib/libx265.199.dylib (compatibility version 199.0.0, current version 199.0.0)
    	/usr/local/opt/jpeg-turbo/lib/libjpeg.8.dylib (compatibility version 8.0.0, current version 8.2.2)
    	/usr/local/opt/libpng/lib/libpng16.16.dylib (compatibility version 56.0.0, current version 56.0.0)
    	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1)
    	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
    
    
    5 条回复    2023-04-22 10:24:12 +08:00
    yzwduck
        1
    yzwduck  
       2023-04-16 12:36:28 +08:00
    有一个不修改 CMake 的思路: 在编译完 libaom 后, 手动执行 install_name_tool -id /usr/local/aom/3.6.0/lib/libaom.3.dylib /path/to/libaom.dylib

    具体用法参见 man install_name_tool

    手边暂时没有 mac 电脑, 没有办法实测有没有其他的坑.
    wowbaby
        2
    wowbaby  
    OP
       2023-04-16 13:31:43 +08:00
    @yzwduck 之前已经试过了 install_name_tool 有些地方修改不能成功,最后默认安装到 /usr/local 解决了,单还是想弄清这个问题,
    指定安装位置
    export PATH="/usr/local/aom/3.6.0/bin:$PATH"
    export LDFLAGS="$LDFLAGS -L/usr/local/aom/3.6.0/lib"
    export CPPFLAGS="$CPPFLAGS -I/usr/local/aom/3.6.0/include"
    export PKG_CONFIG_PATH="/usr/local/aom/3.6.0/lib/pkgconfig:$PKG_CONFIG_PATH"
    export DYLD_LIBRARY_PATH="/usr/local/aom/3.6.0/lib/:$DYLD_LIBRARY_PATH"

    加入以上环境变量 依赖 aom 的软件 @rpath/libaom.3.dylib 也找不到
    yzwduck
        3
    yzwduck  
       2023-04-16 14:18:28 +08:00
    可能是执行 install_name_tool 的时机不对.

    MachO 外部依赖项的路径是编译链接时的动态库里存储的 id 值, 所以需要在编译链接 heif-enc 之前修改 libaom.3.dylib 的 id.
    执行时机正确的话, otool -L libaom.3.dylib 和 heif-enc 的输出里不会出现 rpath.

    你指定的 5 个环境变量中, 前 4 个与 rpath 没有关联: PATH 只影响 execve, 下面 3 个是修改编译选项的, 不像会修改 rpath 的链接路径.
    我不确定 rpath 是否会从 DYLD_LIBRARY_PATH 搜索路径 (我猜不会), 以及在正式签名等场合下 DYLD_LIBRARY_PATH 是会被忽略的, 最好不要去依赖它.
    weidaizi
        4
    weidaizi  
       2023-04-17 12:34:04 +08:00
    看来一下 OP 的需求,改为 '/usr/local/aom/3.6.0/lib/libaom.3.dylib' ,这个路径不太符合 unix 规范。
    用 rpath 的目的就是为了无论是放在 /usr, /usr/local 还是 /opt 中,都不需要使用 LD_LIBRARY_PATH 。但是你需要按照文件夹规范来放

    一般情况下,你放在 /usr/local 中应该直接展开,不带包 aom/3.6.0 这个东西,看起来应该是这样:
    ```
    /usr/local/lib/libheif
    /usr/local/lib/libaom
    ...
    ```

    如果是单独的 fat 包,举个例子比如 java 吧,放在 /opt 当中,尽可能的把依赖打进去,看起来是这样的
    ```
    /opt/jdk-17.0.1/bin/jar
    /opt/jdk-17.0.1/lib/libjli.so
    ......
    ```

    只要运行 `objdump -x jar | grep 'R.*PATH'`,就可以看到输出
    ```
    RUNPATH $ORIGIN:$ORIGIN/../lib
    ```

    只要你的目录符合 unix 规范,无论你是独立的放在 /opt/xxx 当中,还是展开放到 /usr 当中,都是没问题的
    wowbaby
        5
    wowbaby  
    OP
       2023-04-22 10:24:12 +08:00
    @weidaizi /usr/local/aom/3.6.0/lib/ 这样是方便管理,因为包实在太多了,实则通过软链到 /usr/local/lib 也没有问题或直接装默认路径
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5474 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 07:37 · PVG 15:37 · LAX 23:37 · JFK 02:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.