Xcode 5 how to Linking Dynamic Libraries from App Bundle - objective-c

I want to distribute some libraries in to my OS X application bundle, last two days i am working on this however couldn't make it. until now what i did.
with using install name tool i have fixed library paths. additionally in time i have tried #loader_path/../Libraries and #executable_path/../Libraries as well.
otool -L libMagickWand-6.Q16.2.dylib
#rpath/../Libraries/libMagickWand-6.Q16.2.dylib (compatibility version 3.0.0, current version 3.0.0)
#rpath/../Libraries/libMagickCore-6.Q16.2.dylib (compatibility version 3.0.0, current version 3.0.0)
#rpath/../Libraries/libfreetype.6.dylib (compatibility version 18.0.0, current version 18.2.0)
#rpath/../Libraries/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.5)
#rpath/../Libraries/libz.1.2.5.dylib (compatibility version 1.0.0, current version 1.2.5)
#rpath/../Libraries/libltdl.7.dylib (compatibility version 11.0.0, current version 11.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
in project targets / Build Phases / Add New Build Phase / Add Copy Files build Phase and copied all dynamic libraries to my app bundle.
that worked well, I can see the libraries are in the app bundle.
then adding #rpath/../Libraries/ to Build Settings / Runpath Search Paths
but still getting error message..
ld: library not found for -lMagickWand-6.Q16.2 clang: error: linker
command failed with exit code 1 (use -v to see invocation)
if i add direct path lets say libraries are located in /User/username/libs/ to Library Search Paths in build settings it works.
am i missing something?

Content/Libraries is not a standard directory within an app bundle; use Contents/Frameworks instead (.dylibs are allowed in that directory just the same as .frameworks).
Set the Install Name of each library to #rpath/libWhatever.dylib and set the Runpath Search Path of the executable (in Contents/MacOS) to #loader_path/../Frameworks.
For library interdependencies then Runpath Search Path will need to be simply #loader_path so dependent libraries can be loaded from the same directory.
EDIT: People might find the copy_dylibs.py script in this repo useful for copying third-party .dylibs into the App Bundle. It recursively hunts for libraries that need copying and corrects the Install Name of the libraries as well as code-signing them.

Related

clion wsl "CMake 3.20 or higher is required. You are running version 3.16.3"

so I just downloaded wslusing the wsl --install command using PowerShell
now I'm trying to connect it to Clion which works
i cant add images so here is a link to it
but when i'm tying to build the project i get this error
"CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
CMake 3.20 or higher is required. You are running version 3.16.3"
my cmake file:
cmake_minimum_required(VERSION 3.20)
project(ex2 C)
set(CMAKE_C_STANDARD 99)
add_executable(ex2
ex2.c ex2.h
main1.c
main2.c)
i tried updating wsl using wsl --update (in powershell)
The CMake installation inside the WSL is used. Unfortunately currently snap doesn't seem to be available in WSL, but installing the latest CMake version isn't too complicated nonetheless:
(optional) uninstall the old cmake installation in WSL; personally I don't see any benefit in multiple CMake installations, but there may be valid reasons for this. Most likely this will just makes the use of cmake more complex, since you need to remember which cmake version is used.
Download the appropriate cmake version from the cmake website ( https://cmake.org/download/ ). The version to choose is the tar.gz file under binary distributions for the x86_64 target. To get version 3.21.4 (currently the latest release), you can download the file from https://github.com/Kitware/CMake/releases/download/v3.21.4/cmake-3.21.4-linux-x86_64.tar.gz (Identical to the link on the CMake download page).
Unpack the archive from WSL. Navigate to the directory where you want the cmake installation to recide. This will add the cmake-3.21.4-linux-x86_64 directory containing all the files required to work with cmake to the current working directory. Let's assume you want to add the cmake files to the /opt directory. Furthermore let's assume the windows user name to be fabian, C: to be the primary hard drive and the download to be saved to the Downloads directory in the user directory:
cd /opt
tar -xf /mnt/c/Users/fabian/Downloads/cmake-3.21.4-linux-x86_64.tar.gz
(optional) make CMake available without specifying the path; this could be done as described here: https://unix.stackexchange.com/questions/3809/how-can-i-make-a-program-executable-from-everywhere ; don't do this, if an existing cmake installation is already available in the command line assuming you did install cmake to /opt, the cmake binary recides at /opt/cmake-3.21.4-linux-x86_64/bin
You should now be able to use cmake specifying either the full path to the executable (/opt/cmake-3.21.4-linux-x86_64/bin/cmake assuming you used the /opt directory) or directly via a command after opening the WLS commandline again (provided you followed step 4).
Now the only thing left to do should be telling CLion about the location of the cmake executable. Note that I haven't tested this, since I don't use this IDE. It's working fine using Visual Studio Code though...

SFML with Thor in Fedora 27 Codeblocks

Im trying to start a simple game with SFML 2.4 and Thor 2.0 using Code Blocks in C++.
Im linking dynamically the libraries.
For the Release option on Linker settings tab
sfml-audio
sfml-graphics
sfml-window
sfml-system
thor
In Search directories -> Compiler:
/usr/include
In Search directories -> Linker:
/usr/lib
The game compile well but throw some warnings:
||warning: libsfml-graphics.so.2.3, needed by /usr/lib/libthor.so, not found (try using -rpath or -rpath-link)|
||warning: libsfml-window.so.2.3, needed by /usr/lib/libthor.so, not found (try using -rpath or -rpath-link)|
||warning: libsfml-system.so.2.3, needed by /usr/lib/libthor.so, not found (try using -rpath or -rpath-link)|
When I run it a window open that says:
error while loading shared libraries: libsfml-graphics.so.2.3: cannot open shared object file: No such file or directory
I supose that Thor is searching an old verison of SFML. Any idea how could i correct that?
Note: in /usr/lib/ are there all the libsfml files with the extension 2.4.2 and 2.4 in some cases. Not 2.3
The version of Thor you're using is compiled to be used with SFML 2.3, not 2.4. You'll either need to grab the Thor source from here and compile it your self, or get the SFML 2.3 libraries.

Cmake errors when using LLVM 5.0.0 from brew

I'm trying to use the stock LLVM 5.0.0 provided by Homebrew (MacOS High Sierra 10.13.3). LLVM is installed on my machine under /usr/local/Cellar/llvm/5.0.0/
Now, in my project, I have the following lines in CMakeLists.txt:
# Find the LLVM library
find_package( LLVM 5.0.0 REQUIRED )
include_directories( "${LLVM_INCLUDE_DIRS}" )
link_directories(${LLVM_LIBRARY_DIRS})
message(STATUS "LLVM include dirs: ${LLVM_INCLUDE_DIRS}")
If I run CMake without any parameters, I get:
CMake Error at CMakeLists.txt:74 (find_package):
By not providing "FindLLVM.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "LLVM", but
CMake did not find one.
Could not find a package configuration file provided by "LLVM" (requested
version 5.0.0) with any of the following names:
LLVMConfig.cmake
llvm-config.cmake
Add the installation prefix of "LLVM" to CMAKE_PREFIX_PATH or set
"LLVM_DIR" to a directory containing one of the above files. If "LLVM"
provides a separate development package or SDK, be sure it has been
installed.
It tells me that it couldn't find LLVM. So, I pass the path to the LLVM_DIR, like this:
cmake .. -DLLVM_DIR=/usr/local/Cellar/llvm/5.0.0/share/cmake/modules/
I would expect everything to work. Instead I get the following error:
CMake Error at CMakeLists.txt:74 (find_package):
Could not find a configuration file for package "LLVM" that is compatible
with requested version "5.0.0".
The following configuration files were considered but not accepted:
/usr/local/Cellar/llvm/5.0.0/share/cmake/modules/llvm-config.cmake,
version: unknown
For some reason the version is not present anywhere in the share/cmake/modules directory.
How can I fix this, without changing the brew-installed LLVM?
Found the answer. I was passing a wrong path to LLVM_DIR.
I just have to use another directory (buried in lib, not in share):
cmake .. -DLLVM_DIR=/usr/local/Cellar/llvm/5.0.0/lib/cmake/llvm/
Not sure why brew decided to install 2 versions of CMake helpers for LLVM, one in share and one in lib.

Use libmediainfo in Mac XCode project

I'm trying to use libmediainfo in an Xcode project but I'm unable to get it to work properly.
I've added the dylib to the Frameworks folder of my project and made sure it is added to the "Link Binary with Libraries" section in the build settings of the target.
Every time I try to build the app it says:
dyld: Library not loaded: /usr/lib/libmediainfo.0.dylib
 Referenced from: ......
Checkout loader path: otool -L libmediainfo.dylib
If it has #loader_path, change it to #rpath with install_name_tool
install_name_tool -id #rpath/libmediainfo.dylib libmediainfo.dylib
Or, you can place the dylib in the MacOS folder and use #executable_path instead of #rpath.

Can I include a framework in another framework?

I'm writing a framework (called Lighthouse.framework) that, in turn, uses code from another framework (RegexKit.framework, to be precise). I have copied RegexKit.framework into my own framework, so that it has a structure like the following:
Lighthouse.framework/
Versions/
A/
Frameworks/
RegexKit.framework
Lighthouse
However, when I try to run an application that uses Lighthouse.framework (my framework), I get the following error:
dyld: Library not loaded: #executable_path/../Frameworks/RegexKit.framework/Versions/A/RegexKit
Referenced from: /Users/mdippery/Developer/Projects/Current/lighthouse/build/Debug/Lighthouse.framework/Versions/A/Lighthouse
Reason: image not found
Obviously, the loader isn't finding RegexKit.
Here're the paths the loader expects to load, courtesy otool:
build/Debug/Lighthouse.framework/Versions/A/Lighthouse:
/Users/mdippery/Library/Frameworks/Lighthouse.framework/Versions/A/Lighthouse (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 12.0.0)
#executable_path/../Frameworks/RegexKit.framework/Versions/A/RegexKit (compatibility version 0.4.0, current version 0.6.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.1.4)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 476.19.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 677.26.0)
Can I include a framework in another framework? Is this the proper way to do it? How can I resolve my error?
The easiest way is to use #rpath. Your configuration should look like:
Set RegExKit.framework's Installation Directory to #rpath
Set Lighthouse.frameworks's Installation Directory to #rpath
Set Lighthouse.framework's Runpath Search Paths to #loader_path/Frameworks
Ensure that RegExKit.framework is copied into Lighthouse.framework's Framework subfolder (use a custom build phase for this)
Finally, any applications linking to Lighthouse.framework should set Runpath Search Paths to #loader_path/../Frameworks
Yes, you can.
However, you need the included framework to "know" what its installed location will be at the time that it is built; otherwise, dyld won't be able to find it at run time, as you saw.
The relevant settings in XCode, if I recall correctly, are "Installation Directory" and "Framework Install Name". The latter probably won't matter for your usage, but you're going to need the former to be something along the lines of: #executable_path/../Frameworks/Lighthouse.framework/Versions/A/Frameworks/RegexKit.framework/Versions/A/
I discovered a fix for this problem. I incorporated some ideas from sbooth's answer, but the fix was simpler. I ran this script:
install_name_tool -change #executable_path/../Frameworks/RegexKit.framework/Versions/A/RegexKit #loader_path/Frameworks/RegexKit.framework/Versions/A/RegexKit "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.framework/Versions/A/${PRODUCT_NAME}"
as a Run Build Script phase.
Note that, for the general case, you have to change #executable_path/../ to #loader_path/, and all is well.