- Home /
How do I automatically include a framework with my iOS Xcode project
I have an iOS Unity project, which makes some calls to frameworks, the StoreKit framework for example.
I take the generated project from Unity, open it in Xcode and use Add Files to include the framework manually.
It seems like there should be some automated way of dealing with the framework libraries.
You should read some answers below before asking.. several solutions.
Well then take a look again, because there ARE multiple solutions that all work very well. The most simple without installing any shit is $$anonymous$$e, you just copypaste that script and change the string operations to whatever you want to add...
Answer by Raumgleiter · May 04, 2018 at 04:22 PM
Since this question still ranks highly on Google, I'll allow myself a little necroing ;)
eppz has a script on GitHub with a very simple example: https://gist.github.com/eppz/1ebbc1cf6a77741f56d63d3803e57ba3
//
// Copyright (c) 2017 eppz! mobile, Gergely Borbás (SP)
//
// http://www.twitter.com/_eppz
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.IO;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
public class BuildPostProcessor
{
[PostProcessBuildAttribute(1)]
public static void OnPostProcessBuild(BuildTarget target, string path)
{
if (target == BuildTarget.iOS)
{
// Read.
string projectPath = PBXProject.GetPBXProjectPath(path);
PBXProject project = new PBXProject();
project.ReadFromString(File.ReadAllText(projectPath));
string targetName = PBXProject.GetUnityTargetName(); // note, not "project." ...
string targetGUID = project.TargetGuidByName(targetName);
AddFrameworks(project, targetGUID);
// Write.
File.WriteAllText(projectPath, project.WriteToString());
}
}
static void AddFrameworks(PBXProject project, string targetGUID)
{
// Frameworks (eppz! Photos, Google Analytics).
project.AddFrameworkToProject(targetGUID, "MessageUI.framework", false);
project.AddFrameworkToProject(targetGUID, "AdSupport.framework", false);
project.AddFrameworkToProject(targetGUID, "CoreData.framework", false);
project.AddFrameworkToProject(targetGUID, "SystemConfiguration.framework", false);
project.AddFrameworkToProject(targetGUID, "libz.dylib", false);
project.AddFrameworkToProject(targetGUID, "libsqlite3.tbd", false);
// Add `-ObjC` to "Other Linker Flags".
project.AddBuildProperty(targetGUID, "OTHER_LDFLAGS", "-ObjC");
}
}
Best answer but it doesn't work as is because project.GetUnityTargetName() gives compile error due to it being a static method that you can only call by its type name not as an instance.
So please replace
string targetName = project.GetUnityTargetName();
with
string targetName = PBXProject.GetUnityTargetName();
And just for the sake of cleaner code, you can also replace
project.ReadFromString(File.ReadAllText(projectPath));
with
project.ReadFromFile(projectPath);
Fantastic tip, @krisventure ! I edited in the fix.
error CS0619: GetUnityTargetName()' is obsolete: 'This function is deprecated
GetUnity$$anonymous$$ainTargetGuid() - for app GetUnityFrameworkTargetGuid() - for source
Answer by ubik2 · Mar 02, 2012 at 01:39 AM
I ended up using the PostprocessBuildPlayer script (see the Unity manual entry for "Build Player Pipeline") to patch the project.pbxproj used by Xcode.
This script is run after the Xcode project is created, but before it is built or run. In the script, I patch the project.pbxproj to include the references to StoreKit. To get the info, I modified an existing project in Xcode, noticed what was changed in the project, and incorporated those changes into a diff.
It's not particularly elegant, but it works.
Can you post your script for the framework as an example so others can use it?
great question and thanks for posting how you solved it. heh - I tried just dropping my frameworks into the Plugins/iOS folder, and curiously the .meta files got copied into the xcode project, but the actual frameworks didn't.
Answer by OpenKit · Dec 04, 2014 at 10:52 PM
You can see how we did it in the OpenKit unity plugin:
https://github.com/openkit/openkit-unity
We used a python script & a python project called PBXMOD that modifies the Xcode project and adds the frameworks..
yup, ended up using it as well. pbxmod did a good job even for xcode 5 and xcode 6 projects.
The mod-pbxproj can be found here: https://github.com/kronenthaler/mod-pbxproj
Answer by sagi · Jun 04, 2013 at 01:07 PM
I used a post build processor as well, but only to add the framework in the OTHER_LDFLAGS, e.g
OTHER_LDFLAGS = (
-weak_framework
PassKit
);
did not use any script though, since the ref provided in the previous answer did not seem to work for me, and required some install packages I did not have on my box...
@sagi, could you please specify what file you added this to?
Answer by naii · Nov 24, 2014 at 09:04 AM
I used this solution: build the project, copy the project file, then add the framework in xcode and compare the project file to the old one we saved... (svn merge, whatever you like...) Now you can see the difference that you need to add. Of course you can go around the string editing part in many ways... I chose the most stupid one :) I "Replace()" the above/below line to my desired framework with that framework.
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using System.Collections;
using System.IO;
public class PostprocessBuildPlayer
{
[PostProcessBuild]
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
{
LinkLibraries(target, pathToBuiltProject);
}
//
public static void LinkLibraries(BuildTarget target, string pathToBuiltProject)
{
if(target == BuildTarget.iPhone)
{
string projectFile = pathToBuiltProject+"/Unity-iPhone.xcodeproj/project.pbxproj";
string contents = File.ReadAllText(projectFile);
// StoreKit.framework
contents = contents.Replace("Ref = 8AFA69D8161605E7009663A5 /* iPhone_OrientationSupport.mm */; };",
"Ref = 8AFA69D8161605E7009663A5 /* iPhone_OrientationSupport.mm */; };\n\t\t9AA477301A1F575F00974444 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AA4772F1A1F575F00974444 /* StoreKit.framework */; };");
contents = contents.Replace("wnFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };",
"wnFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t9AA4772F1A1F575F00974444 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };");
contents = contents.Replace("1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,",
"9AA477301A1F575F00974444 /* StoreKit.framework in Frameworks */,\n\t\t\t\t1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,");
contents = contents.Replace("8358D1B70ED1CC3700E3A684 /* AudioToolbox.framework */,",
"9AA4772F1A1F575F00974444 /* StoreKit.framework */,\n\t\t\t\t8358D1B70ED1CC3700E3A684 /* AudioToolbox.framework */,");
File.WriteAllText(projectFile, contents);
}
}
}