xcoder 0.0.21 → 0.1.0
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 +3 -0
- data/Gemfile +4 -1
- data/Guardfile +13 -0
- data/README.md +2 -0
- data/Rakefile +15 -0
- data/lib/xcode/build_file.rb +22 -0
- data/lib/xcode/build_phase.rb +46 -0
- data/lib/xcode/builder.rb +2 -0
- data/lib/xcode/configuration.rb +108 -30
- data/lib/xcode/core_ext/array.rb +23 -0
- data/lib/xcode/core_ext/boolean.rb +21 -0
- data/lib/xcode/core_ext/fixnum.rb +5 -0
- data/lib/xcode/core_ext/hash.rb +27 -0
- data/lib/xcode/core_ext/string.rb +11 -0
- data/lib/xcode/file_reference.rb +29 -0
- data/lib/xcode/group.rb +118 -0
- data/lib/xcode/info_plist.rb +4 -0
- data/lib/xcode/parsers/plutil_project_parser.rb +20 -0
- data/lib/xcode/project.rb +133 -34
- data/lib/xcode/registry.rb +120 -0
- data/lib/xcode/resource.rb +187 -0
- data/lib/xcode/target.rb +81 -15
- data/lib/xcode/variant_group.rb +8 -0
- data/lib/xcode/version.rb +1 -1
- data/lib/xcoder.rb +6 -0
- data/spec/TestProject/TestProject.xcodeproj/{xcuserdata/ray.xcuserdatad → xcshareddata}/xcschemes/TestProject.xcscheme +0 -0
- data/spec/build_phase_spec.rb +86 -0
- data/spec/builder_spec.rb +128 -0
- data/spec/configuration_spec.rb +63 -22
- data/spec/group_spec.rb +80 -0
- data/spec/project_spec.rb +92 -35
- data/spec/scheme_spec.rb +1 -16
- data/spec/spec_helper.rb +1 -0
- data/spec/target_spec.rb +71 -15
- data/spec/xcode_spec.rb +57 -0
- metadata +38 -16
- data/spec/TestProject/TestProject.xcodeproj/xcuserdata/ray.xcuserdatad/xcschemes/xcschememanagement.plist +0 -27
data/lib/xcode/target.rb
CHANGED
@@ -1,28 +1,94 @@
|
|
1
|
+
require_relative 'build_file'
|
2
|
+
|
1
3
|
module Xcode
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
|
5
|
+
#
|
6
|
+
# Within a project a user may define a number of targets. These targets may
|
7
|
+
# be to generate the application, generate a universal framework, or execute
|
8
|
+
# tests.
|
9
|
+
#
|
10
|
+
#
|
11
|
+
# @example Target as Hash
|
12
|
+
#
|
13
|
+
# E21D8AA914E0F817002E56AA /* newtarget */ = {
|
14
|
+
# isa = PBXNativeTarget;
|
15
|
+
# buildConfigurationList = E21D8ABD14E0F817002E56AA /* Build configuration list for PBXNativeTarget "newtarget" */;
|
16
|
+
# buildPhases = (
|
17
|
+
# E21D8AA614E0F817002E56AA /* Sources */,
|
18
|
+
# E21D8AA714E0F817002E56AA /* Frameworks */,
|
19
|
+
# E21D8AA814E0F817002E56AA /* Resources */,
|
20
|
+
# );
|
21
|
+
# buildRules = (
|
22
|
+
# );
|
23
|
+
# dependencies = (
|
24
|
+
# );
|
25
|
+
# name = newtarget;
|
26
|
+
# productName = newtarget;
|
27
|
+
# productReference = E21D8AAA14E0F817002E56AA /* newtarget.app */;
|
28
|
+
# productType = "com.apple.product-type.application";
|
29
|
+
# };
|
30
|
+
#
|
31
|
+
#
|
32
|
+
module Target
|
10
33
|
|
11
|
-
|
12
|
-
|
13
|
-
end
|
34
|
+
# A reference to the project for which these targets reside.
|
35
|
+
attr_accessor :project
|
14
36
|
|
15
|
-
|
16
|
-
|
37
|
+
#
|
38
|
+
# @return [PBXBuildConfiguration] the configurations that this target supports.
|
39
|
+
# these are generally 'Debug' or 'Release' but may be custom designed
|
40
|
+
# configurations.
|
41
|
+
#
|
42
|
+
def configs
|
43
|
+
buildConfigurationList.buildConfigurations.map do |config|
|
44
|
+
config.target = self
|
45
|
+
config
|
46
|
+
end
|
17
47
|
end
|
18
48
|
|
49
|
+
#
|
50
|
+
# Return a specific build configuration. When one is not found to match,
|
51
|
+
# an exception is raised.
|
52
|
+
#
|
53
|
+
# @param [String] name of a configuration to return
|
54
|
+
# @return [PBXBuildConfiguration] a specific build configuration that
|
55
|
+
# matches the specified name.
|
56
|
+
#
|
19
57
|
def config(name)
|
20
|
-
config =
|
21
|
-
raise "No such config #{name}, available configs are #{
|
58
|
+
config = configs.select {|config| config.name == name.to_s }.first
|
59
|
+
raise "No such config #{name}, available configs are #{configs.map {|c| c.name}.join(', ')}" if config.nil?
|
22
60
|
yield config if block_given?
|
23
61
|
config
|
24
62
|
end
|
25
63
|
|
64
|
+
#
|
65
|
+
# A ruby-friendly alias for the property defined at buildPhases.
|
66
|
+
#
|
67
|
+
def build_phases
|
68
|
+
buildPhases
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
# @return [BuildPhase] the framework specific build phase of the target.
|
73
|
+
#
|
74
|
+
def framework_build_phase
|
75
|
+
build_phases.find {|phase| phase.isa == 'PBXFrameworksBuildPhase' }
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# @return [BuildPhase] the sources specific build phase of the target.
|
80
|
+
#
|
81
|
+
def sources_build_phase
|
82
|
+
build_phases.find {|phase| phase.isa == 'PBXSourcesBuildPhase' }
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# @return [BuildPhase] the resources specific build phase of the target.
|
87
|
+
#
|
88
|
+
def resources_build_phase
|
89
|
+
build_phases.find {|phase| phase.isa == 'PBXResourcesBuildPhase' }
|
90
|
+
end
|
91
|
+
|
26
92
|
end
|
27
93
|
|
28
94
|
end
|
data/lib/xcode/version.rb
CHANGED
data/lib/xcoder.rb
CHANGED
File without changes
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Xcode::BuildPhase do
|
4
|
+
|
5
|
+
let(:project) { Xcode.project('TestProject') }
|
6
|
+
let(:target) { project.target('TestProject') }
|
7
|
+
|
8
|
+
describe "PBXSourcesBuildPhase" do
|
9
|
+
|
10
|
+
let(:subject) { target.sources_build_phase }
|
11
|
+
|
12
|
+
let(:first_build_file) { "main.m" }
|
13
|
+
let(:second_build_file) { "AppDelegate.m" }
|
14
|
+
|
15
|
+
describe "#build_files" do
|
16
|
+
it "should return the correct number of build files" do
|
17
|
+
subject.build_files.count.should == 2
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return the correct build files " do
|
21
|
+
subject.build_files.first.path.should == first_build_file
|
22
|
+
subject.build_files.last.path.should == second_build_file
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#build_file" do
|
27
|
+
it "should return the correct file by name" do
|
28
|
+
subject.build_file(first_build_file).should_not be_nil
|
29
|
+
subject.build_file(first_build_file).path.should == subject.build_files.first.path
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#add_build_file" do
|
34
|
+
it "should add the specified file to the build phase" do
|
35
|
+
source_file = project.groups.add_file 'NewFile.m'
|
36
|
+
subject.add_build_file source_file
|
37
|
+
subject.build_file('NewFile.m').should_not be_nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
describe "PBXFrameworksBuildPhase" do
|
44
|
+
|
45
|
+
let(:subject) { target.framework_build_phase }
|
46
|
+
|
47
|
+
let(:first_build_file) { "System/Library/Frameworks/UIKit.framework" }
|
48
|
+
let(:second_build_file) { "System/Library/Frameworks/Foundation.framework" }
|
49
|
+
let(:third_build_file) { "System/Library/Frameworks/CoreGraphics.framework" }
|
50
|
+
|
51
|
+
describe "#build_files" do
|
52
|
+
it "should return the correct number of build files" do
|
53
|
+
subject.build_files.count.should == 3
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should return the correct build files " do
|
57
|
+
subject.build_files[0].path.should == first_build_file
|
58
|
+
subject.build_files[1].path.should == second_build_file
|
59
|
+
subject.build_files[2].path.should == third_build_file
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
describe "PBXResourcesBuildPhase" do
|
68
|
+
|
69
|
+
let(:subject) { target.resources_build_phase }
|
70
|
+
|
71
|
+
let(:first_build_file) { "InfoPlist.strings" }
|
72
|
+
|
73
|
+
describe "#build_files" do
|
74
|
+
it "should return the correct number of build files" do
|
75
|
+
subject.build_files.count.should == 1
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should return the correct build files " do
|
79
|
+
subject.build_files.first.name.should == first_build_file
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'xcoder'
|
3
|
+
|
4
|
+
describe Xcode::Builder do
|
5
|
+
|
6
|
+
context "when using a builder built from a configuration" do
|
7
|
+
|
8
|
+
let(:configuration) { Xcode.project('TestProject').target('TestProject').config('Debug') }
|
9
|
+
|
10
|
+
let(:subject) { configuration.builder }
|
11
|
+
|
12
|
+
describe "#build" do
|
13
|
+
|
14
|
+
it "should be able to build" do
|
15
|
+
subject.clean
|
16
|
+
subject.build
|
17
|
+
File.exists?(subject.app_path).should==true
|
18
|
+
File.exists?(subject.dsym_path).should==true
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be able to package" do
|
22
|
+
subject.clean
|
23
|
+
subject.build
|
24
|
+
subject.package
|
25
|
+
File.exists?(subject.dsym_zip_path).should==true
|
26
|
+
File.exists?(subject.ipa_path).should==true
|
27
|
+
end
|
28
|
+
|
29
|
+
let(:default_build_parameters) do
|
30
|
+
[ "xcodebuild",
|
31
|
+
"-sdk #{configuration.target.project.sdk}",
|
32
|
+
"-project \"#{configuration.target.project.path}\"",
|
33
|
+
"-target \"#{configuration.target.name}\"",
|
34
|
+
"-configuration \"#{configuration.name}\"",
|
35
|
+
"OBJROOT=\"#{File.dirname(configuration.target.project.path)}/build/\"",
|
36
|
+
"SYMROOT=\"#{File.dirname(configuration.target.project.path)}/build/\"" ]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should build the project with the default parameters" do
|
40
|
+
Xcode::Shell.should_receive(:execute).with(default_build_parameters)
|
41
|
+
subject.build
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#clean" do
|
47
|
+
|
48
|
+
let(:default_clean_parameters) do
|
49
|
+
[ "xcodebuild",
|
50
|
+
"-project \"#{configuration.target.project.path}\"",
|
51
|
+
"-target \"#{configuration.target.name}\"",
|
52
|
+
"-configuration \"#{configuration.name}\"",
|
53
|
+
"OBJROOT=\"#{File.dirname(configuration.target.project.path)}/build/\"",
|
54
|
+
"SYMROOT=\"#{File.dirname(configuration.target.project.path)}/build/\"",
|
55
|
+
"clean" ]
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
it "should clean the project with the default parametesr" do
|
60
|
+
Xcode::Shell.should_receive(:execute).with(default_clean_parameters)
|
61
|
+
subject.clean
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
context "when using a builder built from a scheme" do
|
69
|
+
|
70
|
+
let(:scheme) { Xcode.project('TestProject').scheme('TestProject') }
|
71
|
+
|
72
|
+
let(:subject) { scheme.builder }
|
73
|
+
|
74
|
+
describe "#build" do
|
75
|
+
|
76
|
+
it "should be able to build" do
|
77
|
+
subject.clean
|
78
|
+
subject.build
|
79
|
+
File.exists?(subject.app_path).should==true
|
80
|
+
File.exists?(subject.dsym_path).should==true
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should be able to package" do
|
84
|
+
subject.clean
|
85
|
+
subject.build
|
86
|
+
subject.package
|
87
|
+
File.exists?(subject.dsym_zip_path).should==true
|
88
|
+
File.exists?(subject.ipa_path).should==true
|
89
|
+
end
|
90
|
+
|
91
|
+
let(:default_build_parameters) do
|
92
|
+
[ "xcodebuild",
|
93
|
+
"-sdk iphoneos",
|
94
|
+
"-project \"#{scheme.project.path}\"",
|
95
|
+
"-scheme #{scheme.name}",
|
96
|
+
"OBJROOT=\"#{File.dirname(scheme.project.path)}/build/\"",
|
97
|
+
"SYMROOT=\"#{File.dirname(scheme.project.path)}/build/\"" ]
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should build the project with the default parameters" do
|
101
|
+
Xcode::Shell.should_receive(:execute).with(default_build_parameters)
|
102
|
+
subject.build
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#clean" do
|
108
|
+
|
109
|
+
let(:default_clean_parameters) do
|
110
|
+
[ "xcodebuild",
|
111
|
+
"-project \"#{scheme.project.path}\"",
|
112
|
+
"-scheme #{scheme.name}",
|
113
|
+
"OBJROOT=\"#{File.dirname(scheme.project.path)}/build/\"",
|
114
|
+
"SYMROOT=\"#{File.dirname(scheme.project.path)}/build/\"",
|
115
|
+
"clean" ]
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
it "should clean the project with the default parametesr" do
|
120
|
+
Xcode::Shell.should_receive(:execute).with(default_clean_parameters)
|
121
|
+
subject.clean
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
data/spec/configuration_spec.rb
CHANGED
@@ -2,34 +2,75 @@ require 'rspec'
|
|
2
2
|
require 'xcoder'
|
3
3
|
|
4
4
|
describe Xcode::Configuration do
|
5
|
-
|
6
|
-
|
5
|
+
|
6
|
+
let(:target) { Xcode.project('TestProject').target('TestProject') }
|
7
|
+
|
8
|
+
let(:subject) { target.config 'Debug' }
|
9
|
+
|
10
|
+
describe "#name" do
|
11
|
+
it "should parse the correct name" do
|
12
|
+
subject.name.should == 'Debug'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#builder" do
|
17
|
+
it "should return an instance of builder" do
|
18
|
+
subject.builder.should_not be_nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#product_name" do
|
23
|
+
it "should return the correct product name" do
|
24
|
+
subject.product_name.should == "TestProject"
|
25
|
+
end
|
7
26
|
end
|
8
27
|
|
9
|
-
|
10
|
-
|
28
|
+
describe "#target" do
|
29
|
+
it "should maintain a reference to the target that it belongs" do
|
30
|
+
subject.target.should == target
|
31
|
+
end
|
11
32
|
end
|
12
33
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
34
|
+
describe "#info_plist_location" do
|
35
|
+
|
36
|
+
let(:expected_plist_location) { "TestProject/TestProject-Info.plist" }
|
37
|
+
|
38
|
+
it "should return the location for the Info.plist file" do
|
39
|
+
subject.info_plist_location.should == expected_plist_location
|
40
|
+
end
|
19
41
|
end
|
20
42
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
43
|
+
describe "#buildSettings" do
|
44
|
+
it "should return a hash of build settings" do
|
45
|
+
subject.buildSettings.should_not
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#set" do
|
50
|
+
|
51
|
+
let(:settings) { subject.buildSettings }
|
52
|
+
|
53
|
+
it "should set a value in the build configuration" do
|
54
|
+
subject.set 'KEY', 'VALUE'
|
55
|
+
settings['KEY'].should == 'VALUE'
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should override existing settings" do
|
59
|
+
linker_flags = settings['OTHER_LDFLAGS']
|
60
|
+
subject.set 'OTHER_LDFLAGS', '-NONE'
|
61
|
+
settings['OTHER_LDFLAGS'].should_not == linker_flags
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#get" do
|
67
|
+
|
68
|
+
let(:settings) { subject.buildSettings }
|
69
|
+
|
70
|
+
it "should return the correct configuration value" do
|
71
|
+
subject.get('OTHER_LDFLAGS').should == settings['OTHER_LDFLAGS']
|
72
|
+
end
|
73
|
+
|
28
74
|
end
|
29
75
|
|
30
|
-
# it "should run tests and fail" do
|
31
|
-
# builder = Xcode.project('TestProject').target('TestProjectTests').config('Debug').builder
|
32
|
-
# builder.clean
|
33
|
-
# builder.test
|
34
|
-
# end
|
35
76
|
end
|