c++ - 在 mac 上的 gnu/clang 编译器中定义相对于可执行文件的框架路径

标签 c++ macos clang sdl

我正在尝试用 SDL2 Framework 编译一个简单的 C++ 测试程序在带有 clang++ 5.1 的 mac 10.9.5 上。

我正在尝试了解如何在 gnu/clang 中手动编译框架,因此请避免回答需要 Xcode 的问题。


项目布局

Project/
|
|-- Output/
|   |-- <Unix Executable File>
|   |-- SDL2.framework
|
|-- Source/
|   |-- main.cpp
|
|-- Frameworks/
|   |-- SDL2.framework

其中 main.cpp 仅包含:

#include <iostream>
#include <SDL2/SDL.h>

int main(int, char**) {
  if (SDL_Init(SDL_INIT_VIDEO) != 0) {
    std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
    return 1;
  }
  std::cout << "SDL LOADED CORRECTLY!" << std::endl;
  SDL_Quit();
  return 0;
}

而SDL2.framework来自2.0.3 Mac Development Library .


编译

我可以用 clang 成功编译和链接:

clang++ -framework SDL2 -FFrameworks Source/main.cpp -o Output/main_test

使用 -F 预处理器标志手动将 Frameworks 目录添加到 Framework 包含文件的搜索路径。


运行

如果 SDL2.framework 存在于全局框架目录 /Library/Frameworks/ 中,生成的可执行文件将正确运行:

$ sudo cp -R Frameworks/SDL2.framework/ /Library/Frameworks/SDL2.framework/
$ ./Output/main_test
SDL LOADED CORRECTLY!

但是,如果可执行文件在输出目录中使用 SDL2.framework 而不是在 Global frameworks 目录中需要一个,我会更喜欢它。

但是如果没有全局框架,可执行文件将不再运行:

$ sudo rm -rf /Library/Frameworks/SDL2.framework/
$ sudo cp -R Frameworks/SDL2.framework/ Output/SDL2.framework/
$ ./Output/main_test
dyld: Library not loaded: @rpath/SDL2.framework/Versions/A/SDL2
  Referenced from: /Users/Jo/Desktop/Temp_Project/./Output/main_test
  Reason: image not found
Trace/BPT trap: 5

问题

@rpath 是可执行文件运行的路径吗?在这种情况下,为什么找不到它?据我所知,所需的文件位于正确的位置:

$ ls -l Output/ 
total 32
drwxr-xr-x@ 6 Jo  staff    204 Mar 15  2014 SDL2.framework
-rwxr-xr-x  1 Jo  staff  15252 Jun 24 17:35 main_test

$ ls -l Output/SDL2.framework/Versions/A/
total 3448
drwxr-xr-x@ 56 Jo  staff     1904 Mar 15  2014 Headers
drwxr-xr-x@  3 Jo  staff      102 Mar 15  2014 Resources
-rwxr-xr-x@  1 Jo  staff  1762208 Mar 15  2014 SDL2
drwxr-xr-x@  3 Jo  staff      102 Mar 15  2014 _CodeSignature

使用以下 otool 库输出:

otool -L Output/main_test 
Output/main_test:
    @rpath/SDL2.framework/Versions/A/SDL2 (compatibility version 1.0.0, current version 3.1.0)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)

长话短说

编译时我是否遗漏了一个步骤,使可执行文件能够在相对于它的位置而不是绝对全局位置用于框架?

好像this Question可能是相关的,但截至这篇文章,它还没有得到回答。

最佳答案

我花了一段时间,但我现在终于明白了如何使用 @rpath

库/框架上的@rpath 意味着可执行文件可以提供一个路径,我们可以使用-rpath 来设置它,我们可以根据@executable_path 来设置它>.

在这种情况下,在编译我的 main_test 可执行文件时,我需要执行以下操作:

clang++ -framework SDL2 -F ./Frameworks Source/main.cpp -o ./Output/main_test -rpath @executable_path/

然后在运行 main_test 时,因为 @rpath 将成为可执行文件的路径 (@executable_path),库将加载从它的相对位置正确。

关于c++ - 在 mac 上的 gnu/clang 编译器中定义相对于可执行文件的框架路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31039625/

相关文章:

c - 在 C 中链接文件/头文件

xcode - clang 中的 armv8 64 位架构支持

C++ 列表迭代器 reverse_iterator

c++ - 使用 Armadillo C++ 的余弦相似度给出了负面结果

c++ - 比较枚举和整数

swift - 动态添加 subview 后,NSSplitView 不调整 subview 的大小

c++ - 派生类中需要构造函数参数的成员对象如何初始化?

c# - 如何在 .NET Core 控制台应用程序中获取 MacOS 用户名?

macos - 如何在格式化的 JSON 文件中使用 sed(或 awk)在匹配后插入一行?

c - 静态与外部内在函数