Xcode Reference a Framework Instead of Link Binary with Libraries

What are the libraries linking options in Xcode?

For dynamic frameworks built with carthage I usually use this setup:

  • Link the library with any target you want to use it in. You need this to be able to import the framework in your code.
  • Embed the library only in the containing app target. This will actually copy the framework in your app bundle. If you don't embed it your app will crash on startup, because your framework can't be found.

Only the app target is responsible for embedding all the frameworks and their dependencies. That way if an extension and the app both use a framework, it will be distributed with the app only once.

For the Xcode interface:

  • dragging a framework into General -> Embedded Binaries will add the framework to both "Link Binary With Libraries" and "Embed Frameworks" build phases
  • dragging a framework into General -> Linked Frameworks and Libraries will add the framework only to the "Link Binary With Libraries" build phase.

The views under General seem to be filled from the build phases tab so you can use either.

Hope that makes sense.

Edit: Target dependencies are just targets that need to be built before the current target can be built. So your app target would list its extension here, so that the extension gets built, whenever you build your app.

Link Binary with libraries VS Embed Frameworks

Link binary with libraries
Link frameworks and libraries with your project’s object files to produce a binary file. You can link a target’s source files against libraries in the target’s active SDK or against external libraries.

Embed Frameworks
You can create an embedded framework to share code between your app extension and its containing app.

-

Timeline (Look at this sentence)
- "If your containing app target links to an embedded framework, it must include the arm64 architecture or it will be rejected by the App Store."

When should we use embedded binaries rather than Linked Frameworks in Xcode?

The question you linked references the "Link Binary With Libraries" functionality, which is somewhat different than an embedded binary.

"Link Binary With Libraries" means what you'd expect it to with respect to linkage: Regardless of whether the binary is a static library, dynamic library, or framework it will be linked to your object code at link time after compilation.

When you think of linkage with a static library, what happens is pretty clear: the linker copies the code from the library (e.g. libFoo.a) into your output binary. Your output file grows in size but doesn't need to resolve any external dependencies at runtime. Everything your program needs to run (with respect to the static library) is present after it is built.

With a dynamic library (.dylib, or system-supplied framework), the expectation is that the library you are linking against will be present somewhere in the system's dynamic-library loader path when you run your program. This way you don't have the overhead of copying all the third party external libraries into your binary, and all the different programs on a computer that also link to that library will be able to find it, which saves minimally disk space, but also potentially memory space, depending on how and where the system caches libraries.

A framework is much like a dynamic library, but can contain resources in its directory structure (images, audio, other frameworks, etc.). In this case a simple static-library or .dylib file won't cut it so you might have to link to a framework just so it can find what it needs to run properly.

When you link to a third-party framework (say something you downloaded from github and built yourself), it might not be present on the system you intend to run on. In this case, you'd not only link to the framework, but embed it inside your application bundle as well using the "Copy Frameworks" phase. When your program runs, the runtime-linker (aka the resolver) will look inside your bundle in addition to the system loader path, find the embedded framework, and link it so your app will have the code it needs in order to run.

Finally, what is properly an "embedded binary" is an executable you both embed in your application bundle via a Copy-Files Phase, and that you execute yourself, perhaps with a call to popen() or similar. The embedded binary may be called by your program, but it isn't linked with it. It is a fully external entity (like programs in the /bin directory).

In practice, for system-supplied libraries and frameworks you will link against them and that's all you need to do.

If you need to link a library you built that doesn't need any embedded resources (i.e. doesn't require a framework to exist), then you can just link against a static library. If you find you have multiple modules in your program that want to use the same library code, then converting it to a framework or dynamic library and linking against that can save space and may be convenient (particularly if memory usage is a concern).

Finally, frameworks can include not only resources, but header and/or license files. Using a framework to convey these files is actually a convenient distribution mechanism so often you may want to incorporate a framework just so these things can tag along with your binary (i.e. license requirements may make this mandatory).

--- EDIT ---

Adam Johns posted the following question as a comment:

This is a great answer. There is something I'm still a little confused on, however. What does it mean to execute the binary yourself? Do you mean simply using the embedded framework's code? I know you mentioned popen(), but you're saying my app is calling popen()? I don't really know what that means.

I'm saying an embedded binary is just another resource file in your bundle, like an audio file or image, although the file is instead an executable command-line tool. The popen() function (man popen from your terminal to read more about it) lets you execute arbitrary programs from another running program. The system() function is another way. There are others, and I'll give a historical example here that may make understanding use of an embedded binary a bit more clear:

As you're probably aware, when you launch an app on Mac OS X it is launched with a user id of the current user. Under most common installations that's the default user-at-the-Desktop admin user, who is given user id 501.

On Unix-based operating systems only the root user (user id 0) has full access to the entire filesystem. Sometimes it happens that an installer program launched by the Desktop user needs to install files in a privileged directory (drivers for example). In this case, the application program needs to escalate its privileges to the root user so it can write in these restricted directories.

To facilitate this in operating systems through OS X 10.7, Apple provided in its Authorization Services API the function AuthorizationExecuteWithPrivileges() (this is now deprecated, but is still a useful example).

AuthorizationExecuteWithPrivileges() took as an argument a path to a command-line tool to execute as root. The command line tool was an executable shell script or compiled binary that you wrote to run your install logic. This tool was installed inside your application bundle just like any other resource file.

When called, the OS put up an authorization dialog asking for the user's password (you've seen this before!) and when entered would execute the program as root on your app's behalf. This process is similar to just executing a program with popen() yourself, although popen() alone doesn't give you the benefit of privilege escalation.

When to link frameworks/libraries on Xcode?

You have to link frameworks and libraries that are not provided by Apple in OS. As frameworks like "AVFoundation" are dynamic libraries provided in OS.

If you have made your own framework/library or using others then you have to link and embed them also in your xcode project.

From Xcode 5 LLVM and Clang provide option to auto-link libraries and Frameworks.By default the vaule is true.
That's why Apple system frameworks(default frameworks) do not have to be explicitly linked to Xcode projects.
See Options in Apple Clang-language- Modules in build settings.
Hope it Helps

How to 'link binary with libraries' with framework in '$Users/Library/Developer/Xcode/DerivedData'

The following shortcut will reveal hidden files & folders:

cmd + shift + .

HOWEVER....

I'd strongly recommend against manually linking to anything in DerivedData (unless you really know what you're doing); otherwise you could end-up facing issues later on (missing files, wrong architecture, etc).

You should use a package manager for this like SPM or Cocoapods instead.

Hope this helps!

In Xcode, moving a framework into a group removes it from Link Binary With Libraries

It's just a visual issue and won't actually affect the link phase. If you leave the Build Phases section and return (directly, or later), the framework's name will be black as you'd expect it to be. There's no need to re-drag or re-add a framework. In Xcode 4, there's no way to have Xcode put the framework in the correct group automatically.



Related Topics



Leave a reply



Submit