# Umbrella Frameworks
What is an Umbrella framework ? It's a frameworks that contains and exposes
embedded frameworks. You only link against the Umbrella framework. But you can
include the headers of the embedded frameworks without having to set crazy
> An example of an Umbrella framework in OS X is <tt>CoreService.framework</tt>
Ideally for development you would have the Umbrella.framework in a convenient
space to link against, which would be <tt>/Library/Frameworks</tt>. An app
could then when you package it for distribution, copy this Framework into its
bundle Frameworks folder, possibly stripping away the headers.
## What works and what not
1) The C compiler picks up the embedded Frameworks directory from the Umbrella
framework and adds it (silently) to it's search path. So <tt><Child/Child.h></tt> is
2) The dynamic loader picks up the information during execution. The App is
only linked against the Umbrella framework, and the Child framework gets
3) The linker is stupid. It only needs to link against Umbrella.framework, but
it gets confused with the @rpath of the Child framework, which it eventually
doesn't even link against.
4) Nothing gets code-signed in this example.
## What's in this project ?
This Xcode workspace contains a minimal project with a **Tool** and an **App** project,
that share the same Umbrella framework.
For the tool to run, the Umbrella framework should be installed in
<tt>/Library/Frameworks</tt>. For the App the Framework is embedded into the App
The settings of all the targets and projects have been pared down to the
minimum. So when you look at the **Build Settings** with **Basic** and
**Combined** set, you should get an easy enough overview.
Of the remaining settings I tried to change as little as possible from the way Xcode set up the projects by default.
> When building from the commandline make sure you use **-scheme** and not
### Umbrella Framework.xctemplate
With this Xcode template you can easily
set up your own Umbrella framework project. Use ``install-templates.sh`` to copy
it to your ~/Library folder and restart Xcode. It should show up under "OS X"
"Framework & Library".
After creating the Umbrella target add your embedded frameworks
as dependencies to the framework and edit the user defined build setting
### Umbrella Framework Symlinks.xctemplate
This template does a lot of shell scripting phases, so that you do
not have actual copies of the embedded frameworks residing in /Library/Frameworks
but just symbolic links. The resulting Frameworks are much "nicer", but the scripts mave prove to be fragile in the long run.
## Various Thoughts
### Xcode strips off the embedded framework Headers during copy
When Xcode copies the a framework it strips off the headers... sometimes. I
guess it depends on the destination of the copy phase. Maybe there are some
settings that avoids excluding the headers, but I couldn't figure it out
from the [Xcode documentation](https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html)
PBXCp /Volumes/Source/srcM/mulle-umbrella-example/build/Products/Debug/Child.framework /Volumes/Source/srcM/mulle-umbrella-example/build/Products/Debug/Umbrella.framework/Versions/A/Frameworks/Child.framework
builtin-copy -exclude .DS_Store -exclude CVS -exclude .svn -exclude .git -exclude .hg -exclude Headers -exclude PrivateHeaders -resolve-src-symlinks /Volumes/Source/srcM/mulle-umbrella-example/build/Products/Debug/Child.framework /Volumes/Source/srcM/mulle-umbrella-example/build/Products/Debug/Umbrella.framework/Versions/A/Frameworks
This isn't bad for deployment only.
### Xcode passes LDFLAGs to clang, which may choke on them
clang isn't aware of all linker flags. It doesn't (yet) know about `-reexport_framework` so one needs to use <tt>-Xlinker</tt> to shield the linker parameters:
OTHER_LDFLAGS = -Xlinker -reexport_framework -Xlinker Child
I see no technical difference between `-reexport_framework` and `-sub_umbrella`. `-reexport_framework` is according to the documentation more "modern".
SKIP_INSTALL on the embedded framework toggles, if it will show up in /Library/Frameworks when you archive/install. If you go for symlinks, it's nicer to have SKIP_INSTALL turned on, otherwise it should be turned off.
### Running the targets in Xcode may give surprising paths
That is, because the Frameworks are lying besides the executable
and are loaded first. (Isn't that a bug really ? gotta check that)
$ otool -L /tmp/App.app/Contents/MacOS/App
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1343.14.0)
@rpath/Umbrella.framework/Versions/A/Umbrella (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1151.16.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 283.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1151.16.0)
Notice that Child does not appear in the listing, which is good.
### Module map is "Neuland" to me
I added a `module.map` file, which I don't really know what it's good for
(Swift?) to the symlinked Umbrella framework just in case...
### Stuff that didn't work
* Adding <tt>/Library/Frameworks/Umbrella.framework/Frameworks</tt> to `
LD_RUNPATH_SEARCH_PATHS` in the Umbrella did not help the linker
* neither did adding <tt>/Library/Frameworks</tt> to `FRAMEWORK_SEARCH_PATHS
in the App target help the linker. Adding <tt>/Library/Frameworks/Umbrella.framework/Frameworks</tt> would fix it though, but this is unwieldy IMO.
created by Nat! 2015 [www.mulle-kybernetik.com]()