Question

I am wondering if it is possible to add a run script build phase to another Xcode project from within my Mac utility app. I can see what takes place in an Xcode project when a run script is added (doing a diff), but I don't know how to safely add the equivalent in code.

Am I supposed to parse it manually? Is there documentation or libraries available for this? This would be a useful feature if I can make sure I do it safely and right. I don't want to be messing up people's Xcode projects!

Was it helpful?

Solution 4

I actually decided to add a run script. It turned out to be quite easy. First, in Xcode, add a run script to your project and observe the changes via the diff tool. There is an addition to the 'buildPhases' array (which is nested down pretty deep in some arbitrarily named dictionaries), and then the key that was added to the 'buildPhases' array was also added to the 'objects' dictionary with a dictionary that represents the actual run script build phase format.

So to replicate this programmatically, get the contents of the pbxproj file into an NSDictionary, and iterate through the dictionaries looking for the buildPhases array. Then, add your key. Finally, add an object to the 'objects' array with the key and a dictionary that mirrors the format in Xcode.

Save the file back to disk in the same location and voila! You have programmatically added a run script build phase.

OTHER TIPS

For anyone looking for the easy way to do this, there is a great python library that lets you mod all types of things in the .pbxproj file. You can check it out here: https://github.com/kronenthaler/mod-pbxproj.

Now to add a run script build phase you can write a simple python script like:

from pbxproj import XcodeProject
import sys

project = XcodeProject.load('path/to/my-project.xcodeproj/project.pbxproj')
project.add_run_script('bash my_run_script.sh')
project.save()

Now just run the python script and you should be good to go.

The possibly easiest solution is to add a Run Script Phase to the other Project which defines a command line executing a script which resides as a particular file in some known location.

The first project then may have a Run Script Phase, or execute a program which creates or modifies this script file. When the other project starts, it starts the Run Script Phase and - voilà - executes whatever has been defined.

My solution requires a little bit of ruby knowledge. There is a library called xcodeproj that it is included with Cocoapods

sudo gem install cocoapods

or,

gem install xcodeproj

To install only the library.

To create a ruby file that adds a run script phase into your targets:

require 'xcodeproj'

project = Xcodeproj::Project.open "./TargetTest.xcodeproj"

for target in project.targets 
    puts "Target -> " + target.name
    phase = target.shell_script_build_phases().find {|item| item.name == "My run phase"}
    if (phase.nil?)
        puts "Creating script 'My run phase'"
        phase = target.new_shell_script_build_phase("My run phase")
        phase.shell_script = "echo Hello script"
    else
        puts "'My run phase' already exist"
        phase.shell_script = "echo modified"
    end
end

project.save() 

And you can run it:

ruby add_run_phase_script.rb

Edit: Replace "=" with "==" in find, otherwise the first script will be replaced, and we need an append

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top