Expose some functions that allow the adding of a App Extensions to an Xcode project

#14 Open
Repository
Mighty_Scott
Branch
add-app-extension
Repository
Unity-Technologies
Branch
stable

Bitbucket cannot automatically merge this request.

The commits that make up this pull request have been removed.

Bitbucket cannot automatically merge this request due to conflicts.

Review the conflicts on the Overview tab. You can then either decline the request or merge it manually on your local system using the following commands:

hg update stable
hg pull -r add-app-extension https://bitbucket.org/Mighty_Scott/xcodeapi
hg merge add-app-extension
hg commit -m 'Merged in Mighty_Scott/xcodeapi/add-app-extension (pull request #14)'
Author
  1. Scott Beca
Reviewers
Description

I would like to be able to add an App Extension Target to an Xcode project during build time so that I can more easily support Sticker Pack Extensions.

There were some functions in the code related to adding Targets and App Extensions that were marked as internal that I have made external. These functions were very close to doing what I needed but required some extra functionality so I have made some required changes.

I have also added TargetNameByGuid and AddFileToResourcesForTarget functions which I required for some steps in the build process.

Finally, I have done a bit of code formatting.

Comments (10)

  1. Scott Beca author

    Hi @Alejandro Gonzalez, below is code that is pretty close to what I use to add a sticker pack to our apps. You'll need to do the following for it to work:

    1. Change "~/Desktop/XcodeBuild" to point to where your Xcode project will be output to by Unity
    2. Change "~/Documents/StickersSource" to point to where Stickers source folder is. To create this folder, the easiest way is to open an Xcode project, add a sticker pack extension, set it all up correctly with the right images and whatnot, then copy it out of the Xcode project to somewhere safe like your version control
    3. Change "com.yourcompany.yourgame.stickers" to be your game's bundle ID with ".stickers" added to the end
    4. (EDIT) Change "UnityEditor.iOS.Xcode" to the new namespace that you set the entire XcodeAPI project to when you built the XcodeAPI's dll. You need to use a different namespace so that it doesn't conflict with the built-in Unity code. E.g. I do a find-and-replace over the entire XcodeAPI project and change "UnityEditor.iOS.Xcode" to "MightyEditor.iOS.Xcode" before building this dll and then use "MightyEditor.iOS.Xcode" in the below code.
    private static void AddStickers()
    {
        string buildPath = "~/Desktop/XcodeBuild";
        string xcodeprojPath = buildPath + "/Unity-iPhone.xcodeproj";
        string pbxprojPath = xcodeprojPath + "/project.pbxproj";
    
        UnityEditor.iOS.Xcode.PBXProject pbxProject = new UnityEditor.iOS.Xcode.PBXProject();
        pbxProject.ReadFromFile(pbxprojPath);
    
        DirectoryCopy("~/Documents/StickersSource", buildPath + "/Stickers", true);
    
        string appGuid = pbxProject.TargetGuidByName(UnityEditor.iOS.Xcode.PBXProject.GetUnityTargetName());
        string stickersGuid = pbxProject.AddAppExtension(appGuid, "Stickers", "com.apple.product-type.app-extension.messages-sticker-pack", "Stickers/Info.plist");
    
        pbxProject.AddFile("Stickers/Stickers.xcassets", "Stickers/Stickers.xcassets");
        pbxProject.AddFileToResourcesForTarget(stickersGuid, "Stickers/Stickers.xcassets");
    
        pbxProject.AddBuildProperty(stickersGuid, "PRODUCT_BUNDLE_IDENTIFIER", "com.yourcompany.yourgame.stickers");
        pbxProject.SetBuildProperty(stickersGuid, "IPHONEOS_DEPLOYMENT_TARGET", "10.0");
        pbxProject.AddBuildProperty(stickersGuid, "TARGETED_DEVICE_FAMILY", "1,2");
        pbxProject.AddBuildProperty(stickersGuid, "ASSETCATALOG_COMPILER_APPICON_NAME", "iMessage App Icon");
        pbxProject.AddBuildProperty(stickersGuid, "ARCHS", "armv7 arm64");
    
        pbxProject.WriteToFile(pbxprojPath);
    
        // This is quite yuck, but there isn't a way with Unity's PBX library to add a scheme and we need to add one for the Stickers target or else xcodebuild fails when we try to build it
        File.WriteAllText(xcodeprojPath + "/xcshareddata/xcschemes/Stickers.xcscheme", "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Scheme LastUpgradeVersion = \"0800\" wasCreatedForAppExtension = \"YES\" version = \"2.0\"><BuildAction parallelizeBuildables = \"YES\" buildImplicitDependencies = \"YES\"><BuildActionEntries><BuildActionEntry buildForTesting = \"YES\" buildForRunning = \"YES\" buildForProfiling = \"YES\" buildForArchiving = \"YES\" buildForAnalyzing = \"YES\"><BuildableReference BuildableIdentifier = \"primary\" BlueprintIdentifier = \"" + stickersGuid + "\" BuildableName = \"Stickers.appex\" BlueprintName = \"Stickers\" ReferencedContainer = \"container:Unity-iPhone.xcodeproj\"></BuildableReference></BuildActionEntry></BuildActionEntries></BuildAction><TestAction buildConfiguration = \"Debug\" selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\" selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\" shouldUseLaunchSchemeArgsEnv = \"YES\"><Testables></Testables><MacroExpansion><BuildableReference BuildableIdentifier = \"primary\" BlueprintIdentifier = \"" + appGuid + "\" BuildableName = \"Unity-Target-New.app\" BlueprintName = \"Unity-iPhone\" ReferencedContainer = \"container:Unity-iPhone.xcodeproj\"></BuildableReference></MacroExpansion><AdditionalOptions></AdditionalOptions></TestAction><LaunchAction buildConfiguration = \"Debug\" selectedDebuggerIdentifier = \"\" selectedLauncherIdentifier = \"Xcode.IDEFoundation.Launcher.PosixSpawn\" launchStyle = \"0\" useCustomWorkingDirectory = \"NO\" ignoresPersistentStateOnLaunch = \"NO\" debugDocumentVersioning = \"YES\" debugServiceExtension = \"internal\" allowLocationSimulation = \"YES\" launchAutomaticallySubstyle = \"2\"><AdditionalOptions></AdditionalOptions></LaunchAction><ProfileAction buildConfiguration = \"Release\" shouldUseLaunchSchemeArgsEnv = \"YES\" savedToolIdentifier = \"\" useCustomWorkingDirectory = \"NO\" debugDocumentVersioning = \"YES\" launchAutomaticallySubstyle = \"2\"><MacroExpansion><BuildableReference BuildableIdentifier = \"primary\" BlueprintIdentifier = \"" + stickersGuid + "\" BuildableName = \"Stickers.appex\" BlueprintName = \"Stickers\" ReferencedContainer = \"container:Unity-iPhone.xcodeproj\"></BuildableReference></MacroExpansion></ProfileAction><AnalyzeAction buildConfiguration = \"Debug\"></AnalyzeAction><ArchiveAction buildConfiguration = \"Release\" revealArchiveInOrganizer = \"YES\"></ArchiveAction></Scheme>");
    }
    
    private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
    {
        // Get the subdirectories for the specified directory.
        DirectoryInfo dir = new DirectoryInfo(sourceDirName);
    
        if (!dir.Exists)
        {
            throw new DirectoryNotFoundException("Source directory does not exist or could not be found: " + sourceDirName);
        }
    
        DirectoryInfo[] dirs = dir.GetDirectories();
        // If the destination directory doesn't exist, create it.
        if (!Directory.Exists(destDirName))
        {
            Directory.CreateDirectory(destDirName);
        }
    
        // Get the files in the directory and copy them to the new location.
        FileInfo[] files = dir.GetFiles();
        foreach (FileInfo file in files)
        {
            string temppath = Path.Combine(destDirName, file.Name);
            file.CopyTo(temppath, false);
        }
    
        // If copying subdirectories, copy them and their contents to new location.
        if (copySubDirs)
        {
            foreach (DirectoryInfo subdir in dirs)
            {
                string temppath = Path.Combine(destDirName, subdir.Name);
                DirectoryCopy(subdir.FullName, temppath, copySubDirs);
            }
        }
    }
    
  2. Povilas Kanapickas

    It looks good, but we are in process of developing improved Xcode project manipulation API, which already supports what this PR implements. Thus there's no point in merging it.

  3. Povilas Kanapickas

    We've postponed the plans for the new API, it will be initially released as a user-buildable DLL much like code in this repository. The current stable branch of this repo already supports application extensions (but not sticker packs). We'll look into implementing this too.

  4. Mike Oliva

    Hello@Mighty_Scott , I’m trying to use your way to add programmatically a stickers pack into a unity ios build.
    I have 2 issues :

    • Xcode fails to parse the contents of the Info.plist that is copy and paste
    • I can’t set the signing team of the stickers target