Xcode create shared framework across lots of targets - xcode

I'm making stuff for IOS, Mac, and WatchOS - I have certain common functionality that is more about me and the way I program than about whatever it is I'm programming - helper methods etc
What I'd like is to have a "Common" framework or library in my app which is included into every other library. I understand I need a separate target for each of ios, macos, watchos, but I can't figure out how to set it up.
I can create a framework - and it comes with a target - I can duplicate that target and change stuff, but I don't seem to be able to change it from IOS to macos for instance. I can create a separate macos target, but then I can't seem to be able to change where it gets the code from.
Essentially in my source tree I want a single directory:
Common
and then have target frameworks CommonIOS, CommonMacOs, CommonWatchOS - that all just compile "Common". How do I achieve that?

You're misusing the word "framework". All you want is to keep some source code as a library that all your projects and targets, no matter what system they'll be compiled for, can use. You are describing a Swift package.

Related

How to create a single shared framework between iOS and OS X

I am attempting to create a framework to hold the common entity classes for an app that runs on iOS and OS X. Currently I am just including the files in each target but that requires changing the data model so it get the class from the current target (since in Swift you have to specify the module that has the class in the model file). This of course means I forget at times and things don't work.
The obvious solution is to create a shared framework that holds the entity classes so that the data model always points to the same place.
The problem is there doesn't seem to be any way to create a framework that builds on both platforms.
Has anyone found a way to create a single framework, or library, that works on both platforms?
If you wish to create a single dynamic framework binary, here are the steps you can follow (as outlined in http://colemancda.github.io/2015/02/11/universal-ios-osx-framework):
1. Change the project's valid architectures and supported platforms.
This should change your framework's and test unit's valid architectures and supported platforms as well. If not, then manually change them to inherit from the project's build settings.
Base SDK: I recommend OS X, but it will work with iOS too. Note that with with iOS as the base SDK, "My Mac" target is separated into 3 different targets.
Supported Platforms: macosx iphoneos iphonesimulator
Valid Architectures: arm64 armv7 armv7s i386 x86_64
2. Change the search paths for the Unit Test bundle
Runpath Search Paths: $(inherited) #executable_path/Frameworks #loader_path/Frameworks #executable_path/../Frameworks #loader_path/../Frameworks
Framework Search Paths: $(SDKROOT) $(inherited)
Its a better solution than having two separate targets.
It turns out the answer is super simple but not very obvious, at least not until after I posted this question and worked on something else.
All that needs to be done is to make a framework target for each platform but then set the product names to be the same. As this is also the module name in Swift you can then set the class field in the Core Data model to one value and have it work on both platforms.
The setup I'm using is to include the model files in both frameworks but to include the model itself directly into each app target.
You should also be able to set both apps to have the same product name and have everything work but I didn't test it and the frameworks allow you to have MyApp and MyAppMobile if you want.

install app on mac with shared libraries outside bundle

I am working on a Qt app with some library dependencies, for which I will have to make an installer.
From everything I read, seems like the best way is to make a bundle app with all library dependencies, and the required Qt frameworks, inside myapp.app/Contents/Frameworks
There are other applications created in parallel... that will get to be deployed on mac as well. They will have the same library dependencies and will be built using the same Qt version.
In that case it makes sense for the libraries and Qt to be installed OUTSIDE the bundle... so both (all) apps have access without having multiple copies of the same libraries.
Does that seem reasonable - and do-able with mac osx concept of bundle islands ? And how would I create such an installer that places libraries outside the app bundle ?
The simplest method of deploying Qt for OS X is to use the macdeployqt command line tool, and you have identified correctly that the normal method is to place the frameworks inside the app bundle, but multiple apps will each have copies of the frameworks.
It is reasonable to suggest moving the Qt frameworks to a separate, external location and linking to that instead. However, you will need to manage the framework carefully, especially when it comes to providing updates and be aware that if the framework is removed or altered, all your applications will fail to load. This, however is the same for any framework dependent application.
The thing to consider is where to place the framework. Normally, external frameworks reside in /Library/Frameworks, but if we all start to use that for Qt, problems may occur when your app is installed and another developer installs their app's frameworks with a different version of the libraries.
Apple defines various 'key directories' for applications and initially, the most likely location would appear to be the "Application Support Directory", but the documentation states that this is for: -
any type of file that supports the app but is not required for the app to run
This location is often used for support files, such as templates for the user to select.
If your application is to be deployed via the Apple Store, I wouldn't be surprised if it is rejected if you use this location. However, you're not using the Apple Store, then you could deploy the frameworks here.
If the Apple Store is your method of deployment, then /Library/Frameworks is probably the only place acceptable for the Qt framework to reside, with the possibility of the problems I've mentioned above.
Alternatively, consider just how many applications you're developing and is it really an issue to bundle the frameworks multiple times against the advantages that it brings, such as allowing the user to cleanly remove the application and all of its dependencies, as well as reducing problems of the framework being altered or removed accidentally?
If you choose to move them externally, you can refer to the answer to this question, which comprehensively explains how to make installer packages, after having updated your binary dependencies on the frameworks with the install_name_tool, as outlined here.

How to compile swift library project into .so file?

I'm new to XCode and Objective C / Swift. I'm trying to make a Swift library project that doesn't depend on cocoa or anything. So it's just Swift files. What type of project should I be creating (I'm assuming there are multiple ways of doing this? How do I need to configure the project so that it builds to a .so file? And finally, how do I build it to a .so file?
I'm using Xcode6-beta.
You can create a Swift library for iOS by creating a new Xcode Project and selecting iOS/OS X -> Framework & Library -> Cocoa Touch Framework and then setting the language to Swift on the next screen.
Once this project has been created you are not required to link against the Cocoa frameworks, and can remove any references to them if needed.
Upon compiling this project Xcode will create a .framework folder in your build directory which contains a dynamic library which you should then be able to link against. Note however that I haven't had any success myself yet at linking directly against this file, even though it appears to be a standard dynamic library.
In terms of using this shared object file on Android I believe you will be out of luck, as the Swift language (much like Objective-C) requires a runtime library which is simply not available on other platforms at this time.
... I think you are limiting your train of thought a bit or expecting leaps and bounds to quickly swift is ready to work with objective c and cocoa so you aren't going to be able completely avoid cocoa however you wont have to write any of it the compiler will do that for you. but you will still have to use cocoa frameworks or modules like foundation( contains many specialized objects for program development), UIKit, CoreData however these don't require you to write the cocoa. and if Im not mistaken the .so file is made on compile so you never actually touch that file but rather is supporting files .swift
to do it
if your looking to do everything programmatically or if you want to xib or storyboards just make a new project I prefer an empty project.(set programming language to swift and decide if you want core data or not finish the project wizard thing and bam you have a YourAppDelegate.swift you can make another .swift file or a storyboard and hopefully you know what to do from there. Swift book is available on ibooks for free its nicely written
although it will be quite a while before cocoa and swift are completely separate... if ever

Creating static framework for OS X

With the use of a mild hack, it is possible to make static frameworks for iOS. Static frameworks are quite convenient to use: they can simply be dropped into new projects without extra steps (like adding them to the build and adding header search paths).
I've recently started doing OS X programming, and the first thing I noticed was that static frameworks don't seem to be available. Dynamic frameworks are obviously available and recommended, but as I want to make a little private framework intended for application use (not installation in /Library/Frameworks), using a dynamic framework in new application projects still requires a bunch of extra steps.
In my ideal world, I'd create a static framework (a framework which contains header files and a compiled .a file), drag & drop the framework onto a new project, and start coding. Is there any way to make such a static framework on OS X?
P.S. I already tried setting the Mach-O output type to "static library" in a normal framework project, but I just get the error Framework target has invalid MACH_O_TYPE value of 'staticlib'..
You can create a dynamic framework on Mac OS X. In your dynamic framework you can set the LD_DYLIB_INSTALL_NAME as #rpath/Foo.framework/Versions/A/Foo
If you have an app that wants to link with this framework then you make sure you run the
install_name_tool -add_rpath <rpath> <full-path-to-app-binary>
So if I had Foo.app
install_name_tool -add_rpath Foo.app/Contents/Library Foo.app/Contents/MacOS/Foo
Now if you just copy your Foo.framework into Contents/Library it should get loaded and everything should work.
I hope this helps.
Probably simpler would be to use a static library with public headers. When you build the static lib you can have Xcode copy the headers for you automatically. And in your target you can add the folder to your search path.
If you use a static library Xcode will strip away some dead code that your app doesn't really need but is compiled into the static lib.
Static frameworks aren't really supported on OS X. They're fairly brittle anyway, and solve a specific problem that exists on iOS but not on OS X.
If you're looking to make it easy for developers to use a library you create, you have a couple options:
Use Cocoapods. They have a tutorial for publishing your library on CocoaPods. This is probably the easiest way to distribute a library on OS X.
Package your library as a framework. If you set the install name correctly (to #rpath/<library name>), the downstream developer merely needs to copy the framework into their Xcode project and set the runtime search path of their application to #executable_path/../Frameworks).

Including a framework without embedding it in the app bundle

I'm still not 100% sure with the framework linking process, but from what I've seen here before nobody has asked a similar question, perhaps because this could be a silly question, but I'll give it a go anyway.
In my current X-Code project, I'm using a custom framework, say example.framework. At the moment, as far as I'm aware of, in order for the program to function with the framework, I need to have it either in /Library/Frameworks, or I need to have it copied into the bundle resources in the build phase.
Would anybody know about adding a framework to a project in a way that it gets compiled into the executable, so I don't have to include the raw framework with the app? I'd rather not share the whole framework...
Thank you in advance! Any suggestions are also welcome!
A Mac OS X framework is basically a shared library, meaning it's a separate binary.
Basically, when your main executable is launched, the OS will load the framework/dylib into memory, and map the symbols, so your main executable can access them.
Note that a framework/dylib (bundled into the application or not), does not need to contain the header files, as those are only needed at compilation time.
With Xcode, you can actually decide whether or not to include the header files, when you are copying the framework to its installation directory (see your build phases).
If you don't copy header files, people won't be able to use your framework/dylib (unless they reverse-engineer it, of course).
If you still think a framework is not suitable for your needs, you may want to create a static library instead.
A static library is a separate object file (usually .a) that is «included» with your final binary, at link time.
This way, you only have a single binary file, containing the code from the library and from your project.

Resources