4

I'm trying to compile a simple c++ test program with the SDL2 Framework on mac 10.9.5 with clang++ 5.1.

I'm trying to understand how to compile with frameworks manually in gnu/clang, so please refrain from answers that would require Xcode.


Project layout

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

Where main.cpp simply contains:

#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;
}

And SDL2.framework is from the 2.0.3 Mac Development Library.


Compiling

I can successfully compile and link with clang:

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

Using the -F preprocessor flag to manually add the Frameworks directory to the search path for Framework include files.


Running

The resulting executable runs correctly if SDL2.framework exists in the Global frameworks directory, /Library/Frameworks/:

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

However I would prefer it if the executable used the SDL2.framework in the Output directory instead of requiring one in the Global frameworks directory.

But without the global framework the executable no longer runs:

$ 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

Question

Is @rpath the path from where the executable is being run? In which case, why is it not able to find it? As far as I can tell the files needed are in the correct location:

$ 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

With the following otool Library output:

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)

TL;DR

Is there a step that I am missing when compiling that would enable the executable to use for the Framework in a location relative to it instead of an absolute global one?

It seems like this Question could be related but as of this post it has yet to be answered.

Community
  • 1
  • 1
Johannes
  • 6,232
  • 9
  • 43
  • 59

1 Answers1

2

It took me a while but I now finally understand how to use @rpath.

@rpath on a library/framework means that the executable can provide a path, which we can set using -rpath, and we can set it in terms of @executable_path.

In this case, when compiling my main_test executable I would need to do the following:

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

Then when running main_test, because @rpath is going to be the path to the executable (@executable_path), the library will load correctly from its relative location.

Johannes
  • 6,232
  • 9
  • 43
  • 59