xcoder 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # XCoder
2
+
3
+ A ruby wrapper around various xcode tools and the project.pbxproj
4
+
5
+ ## Example Usage
6
+
7
+ You will need to install the gem:
8
+
9
+ `gem install xcoder`
10
+
11
+ and then require the gem in your project/rakefile/etc
12
+
13
+ `require 'xcoder'`
14
+
15
+ ### Finding all projects from the current directory down
16
+
17
+ `Xcode.find_projects.each {|p| puts p.name }`
18
+
19
+ ### Find a configuration for a target on a project
20
+
21
+ `
22
+ project = Xcode.find_projects.first
23
+ config = project.target(:Target).config(:Debug)
24
+ `
25
+
26
+ ### Building a configuration
27
+
28
+ `config.build`
29
+
30
+ ### Packaging a built .app
31
+
32
+ `config.package :sign => 'Developer Identity Name', :profile => 'Profile.mobileprovision'`
33
+
34
+ ### Incrementing the build number
35
+
36
+ config.info_plist do |info|
37
+ info.version = info.version.to_i + 1
38
+ info.save
39
+ end
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,56 @@
1
+ module Xcode
2
+ class Configuration
3
+ attr_reader :target
4
+
5
+ def initialize(target, json)
6
+ @target = target
7
+ @json = json
8
+ end
9
+
10
+ def info_plist_location
11
+ @json['buildSettings']['INFOPLIST_FILE']
12
+ end
13
+
14
+ def name
15
+ @json['name']
16
+ end
17
+
18
+ def info_plist
19
+ puts @json.inspect
20
+ info = Xcode::InfoPlist.new(self, info_plist_location)
21
+ yield info if block_given?
22
+ info
23
+ end
24
+
25
+ def build
26
+ cmd = []
27
+ cmd << "-target #{@target.name}"
28
+ cmd << "-configuration #{name}"
29
+ @target.project.execute_xcodebuild(cmd.join(' '))
30
+ end
31
+
32
+ def app_path
33
+ "#{File.dirname(@target.project.path)}/build/#{name}-#{@target.project.sdk}/#{@target.productName}.app"
34
+ end
35
+
36
+ def ipa_path
37
+ "#{File.dirname(@target.project.path)}/build/#{name}-#{@target.project.sdk}/#{@target.productName}.ipa"
38
+ end
39
+
40
+ def package(options={})
41
+ cmd = []
42
+ cmd << "-v #{app_path}"
43
+ cmd << "-o #{ipa_path}"
44
+
45
+ if options.has_key? :sign
46
+ cmd << "--sign #{options[:sign]}"
47
+ end
48
+
49
+ if options.has_key? :profile
50
+ cmd << "--embed #{options[:profile]}"
51
+ end
52
+
53
+ @target.project.execute_package_application(cmd.join(' '))
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,37 @@
1
+ require 'plist'
2
+ require 'pp'
3
+
4
+ module Xcode
5
+ class InfoPlist
6
+ def initialize(project, plist_location)
7
+ @project = project
8
+
9
+ @plist_location = File.expand_path(plist_location)
10
+ unless File.exists?(@plist_location)
11
+ puts 'Plist not found ' + @plist_location
12
+ exit 1
13
+ end
14
+ @plist = Plist::parse_xml(@plist_location)
15
+ end
16
+
17
+ def marketing_version
18
+ @plist['CFBundleShortVersionString']
19
+ end
20
+
21
+ def marketing_version=(version)
22
+ @plist['CFBundleShortVersionString'] = version
23
+ end
24
+
25
+ def version
26
+ @plist['CFBundleVersion']
27
+ end
28
+
29
+ def version=(version)
30
+ @plist['CFBundleVersion'] = version.to_s
31
+ end
32
+
33
+ def save
34
+ File.open(@plist_location, 'w') {|f| f << @plist.to_plist}
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,80 @@
1
+ require 'json'
2
+ require 'xcode/target'
3
+ require 'xcode/configuration'
4
+
5
+ module Xcode
6
+ class Project
7
+ attr_reader :targets, :sdk, :path
8
+ def initialize(path, sdk=nil)
9
+ @sdk = sdk || "iphoneos" # FIXME: should support OSX/simulator too
10
+ @path = File.expand_path path
11
+ @targets = {}
12
+
13
+ parse_pbxproj
14
+ # parse_configurations
15
+ end
16
+
17
+ def execute_package_application(options=nil)
18
+ cmd = []
19
+ cmd << "xcrun"
20
+ cmd << "-sdk #{@sdk.nil? ? "iphoneos" : @sdk}"
21
+ cmd << "PackageApplication"
22
+ cmd << options unless options.nil?
23
+
24
+ execute(cmd.join(' '), true)
25
+ end
26
+
27
+ def execute_xcodebuild(cmd_line=nil, show_output=true)
28
+ cmd = []
29
+ cmd << "xcodebuild"
30
+ cmd << "-sdk #{@sdk}" unless @sdk.nil?
31
+ cmd << "-project #{@path}"
32
+ cmd << cmd_line unless cmd_line.nil?
33
+ yield cmd if block_given?
34
+
35
+ execute(cmd.join(' '), show_output)
36
+ end
37
+
38
+ def target(name)
39
+ target = @targets[name.to_s.to_sym]
40
+ raise "No such target #{name}, available targets are #{@targets.keys}" if target.nil?
41
+ yield target if block_given?
42
+ target
43
+ end
44
+
45
+ private
46
+
47
+ def parse_pbxproj
48
+ json = JSON.parse(`plutil -convert json -o - "#{@path}/project.pbxproj"`)
49
+
50
+ root = json['objects'][json['rootObject']]
51
+ root['targets'].each do |target_id|
52
+ target = Xcode::Target.new(self, json['objects'][target_id])
53
+
54
+ buildConfigurationList = json['objects'][target_id]['buildConfigurationList']
55
+ buildConfigurations = json['objects'][buildConfigurationList]['buildConfigurations']
56
+
57
+ buildConfigurations.each do |buildConfiguration|
58
+ config = Xcode::Configuration.new(target, json['objects'][buildConfiguration])
59
+ target.configs[config.name.to_sym] = config
60
+ end
61
+
62
+ @targets[target.name.to_sym] = target
63
+ end
64
+ end
65
+
66
+ def execute(cmd, show_output=false)
67
+ out = []
68
+ puts "EXECUTE: #{cmd}"
69
+ IO.popen (cmd) do |f|
70
+ f.each do |line|
71
+ puts line if show_output
72
+ out << line
73
+ end
74
+ end
75
+ #puts "RETURN: #{out.inspect}"
76
+ out
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,28 @@
1
+ module Xcode
2
+ class Target
3
+ attr_reader :configs, :project
4
+
5
+ def initialize(project, json)
6
+ @project = project
7
+ @json = json
8
+ @configs = {}
9
+ end
10
+
11
+ def productName
12
+ @json['productName']
13
+ end
14
+
15
+ def name
16
+ @json['name']
17
+ end
18
+
19
+ def config(name)
20
+ config = @configs[name.to_s.to_sym]
21
+ raise "No such config #{name}, available configs are #{@configs.keys}" if config.nil?
22
+ yield config if block_given?
23
+ config
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,3 @@
1
+ module Xcode
2
+ VERSION = "0.0.1"
3
+ end
data/lib/xcoder.rb ADDED
@@ -0,0 +1,59 @@
1
+ require 'find'
2
+ require 'fileutils'
3
+ require "xcode/version"
4
+ require "xcode/project"
5
+ require "xcode/info_plist"
6
+
7
+ module Xcode
8
+ @@projects = nil
9
+ @@sdks = nil
10
+
11
+ # def self.project(name)
12
+ # parse_projects if @@projects.nil?
13
+ # @@projects.each do |p|
14
+ # return p if p.name == name
15
+ # end
16
+ # raise "Unable to find project named #{name}"
17
+ # end
18
+
19
+ def self.find_projects(dir='.')
20
+ parse_projects(dir)
21
+ end
22
+
23
+ def self.is_sdk_available?(sdk)
24
+ parse_sdks if @@sdks.nil?
25
+ @@sdks.values.include? sdk
26
+ end
27
+
28
+ def self.available_sdks
29
+ parse_sdks if @@sdks.nil?
30
+ @@sdks
31
+ end
32
+
33
+ private
34
+ def self.parse_sdks
35
+ @@sdks = {}
36
+ parsing = false
37
+ `xcodebuild -showsdks`.split("\n").each do |l|
38
+ l.strip!
39
+ if l=~/(.*)\s+SDKs:/
40
+ parsing = true
41
+ elsif l=~/^\s*$/
42
+ parsing = false
43
+ elsif parsing
44
+ l=~/([^\t]+)\t+\-sdk (.*)/
45
+ @@sdks[$1.strip] = $2.strip unless $1.nil? and $2.nil?
46
+ end
47
+ end
48
+ end
49
+
50
+ def self.parse_projects(dir='.')
51
+ projects = []
52
+ Find.find(dir) do |path|
53
+ if path=~/(.*)\.xcodeproj$/
54
+ projects << Xcode::Project.new(path)
55
+ end
56
+ end
57
+ projects
58
+ end
59
+ end
data/xcoder.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "xcode/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "xcoder"
7
+ s.version = Xcode::VERSION
8
+ s.authors = ["Ray Hilton"]
9
+ s.email = ["ray@wirestorm.net"]
10
+ s.homepage = "https://github.com/rayh/xcoder"
11
+ s.summary = %q{Ruby wrapper around xcodebuild, xcrun, agvtool and pbxproj files}
12
+ s.description = %q{Provides a ruby based object-model for parsing project structures and invoking builds}
13
+
14
+ s.rubyforge_project = "xcoder"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_runtime_dependency "json"
22
+ s.add_runtime_dependency "plist"
23
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xcoder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ray Hilton
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-08-18 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json
16
+ requirement: &70220191343000 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70220191343000
25
+ - !ruby/object:Gem::Dependency
26
+ name: plist
27
+ requirement: &70220191371480 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70220191371480
36
+ description: Provides a ruby based object-model for parsing project structures and
37
+ invoking builds
38
+ email:
39
+ - ray@wirestorm.net
40
+ executables: []
41
+ extensions: []
42
+ extra_rdoc_files: []
43
+ files:
44
+ - .gitignore
45
+ - Gemfile
46
+ - README.md
47
+ - Rakefile
48
+ - lib/xcode/configuration.rb
49
+ - lib/xcode/info_plist.rb
50
+ - lib/xcode/project.rb
51
+ - lib/xcode/target.rb
52
+ - lib/xcode/version.rb
53
+ - lib/xcoder.rb
54
+ - xcoder.gemspec
55
+ homepage: https://github.com/rayh/xcoder
56
+ licenses: []
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubyforge_project: xcoder
75
+ rubygems_version: 1.8.6
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: Ruby wrapper around xcodebuild, xcrun, agvtool and pbxproj files
79
+ test_files: []