xcoder 0.1.1 → 0.1.2

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.
@@ -0,0 +1,101 @@
1
+ module Xcode
2
+ class Buildfile
3
+
4
+ def initialize
5
+ @values = {}
6
+ @before = {:clean => [], :build => [], :package => []}
7
+ @after = {:clean => [], :build => [], :package => []}
8
+ end
9
+
10
+ def method_missing(method, *args)
11
+ @values[method.to_sym] = args[0]
12
+ end
13
+
14
+ def before(event, &block)
15
+ @before[event]<< block
16
+ end
17
+
18
+ def after(event, &block)
19
+ @after[event]<< block
20
+ end
21
+
22
+ def getBinding
23
+ binding()
24
+ end
25
+
26
+ def self.load(file)
27
+ file = File.expand_path file
28
+ raise "Unable to find the buildfile #{file}" if !File.exists? file
29
+
30
+
31
+ puts "Loading Buildfile: #{file}"
32
+ bc = Xcode::Buildfile.new
33
+ eval(File.read(file), bc.getBinding, file)
34
+ bc
35
+ end
36
+
37
+ def build
38
+ label = "#{@values[:target]}"
39
+ puts "[#{label}] Loading project #{@values[:project]}, target #{@values[:target]}, config #{@values[:config]}"
40
+ config = Xcode.project(@values[:project]).target(@values[:target]).config(@values[:config])
41
+ config.info_plist do |info|
42
+ puts "[#{label}] Update info plist version to #{@values[:version]}"
43
+ info.version = @values[:version]
44
+ end
45
+ builder = config.builder
46
+
47
+ # unless @values[:identity].nil?
48
+ # builder.identity = @values[:identity]
49
+ # puts "[#{label}] Set build identity to #{@values[:identity]}"
50
+ # end
51
+
52
+ unless @values[:profile].nil?
53
+ builder.profile = @values[:profile]
54
+ puts "[#{label}] Set build profile to #{@values[:profile]}"
55
+ end
56
+
57
+ Keychain.temp_keychain(@values[:project]) do |kc|
58
+ kc.import @values[:certificate], @values[:password]
59
+
60
+ builder.identity = @values[:identity] || kc.certificates.first
61
+ builder.keychain = kc
62
+
63
+ puts "[#{label}] CLEAN"
64
+ @before[:clean].each do |b|
65
+ b.call(builder)
66
+ end
67
+ builder.clean
68
+ @after[:clean].each do |b|
69
+ b.call(builder)
70
+ end
71
+
72
+ puts "[#{label}] BUILD"
73
+ @before[:build].each do |b|
74
+ b.call(builder)
75
+ end
76
+ builder.build
77
+ @after[:build].each do |b|
78
+ b.call(builder)
79
+ end
80
+
81
+ puts "[#{label}] PACKAGE"
82
+ @before[:package].each do |b|
83
+ b.call(builder)
84
+ end
85
+ builder.package
86
+ @after[:package].each do |b|
87
+ b.call(builder)
88
+ end
89
+ end
90
+
91
+
92
+ if @values.has_key? :testflight_api_token and @values.has_key? :testflight_team_token
93
+ puts "[#{label}] Uploading to testflight"
94
+ `curl -X POST http://testflightapp.com/api/builds.json -F file=@"#{builder.ipa_path}" -F dsym=@"#{builder.dsym_zip_path}" -F api_token='#{@values[:testflight_api_token]}' -F team_token='#{@values[:testflight_team_token]}' -F notify=True -F notes=\"#{@values[:testflight_notes]}\" -F distribution_lists='#{@values[:testflight_lists].join(',')}'`
95
+ end
96
+
97
+ builder
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,161 @@
1
+ require 'xcode/builder'
2
+
3
+ module Xcode
4
+
5
+ #
6
+ # Projects have a number of build configurations. These configurations are
7
+ # usually the default 'Debug' and 'Release'. However, custom ones can be
8
+ # defined.
9
+ #
10
+ # @see https://developer.apple.com/library/ios/#documentation/ToolsLanguages/Conceptual/Xcode4UserGuide/Building/Building.html
11
+ #
12
+ # Each configuration is defined and then a reference of that configuration is
13
+ # maintained in the Target through the XCConfigurationList.
14
+ #
15
+ # @example Xcode configuration
16
+ #
17
+ # E21D8ABB14E0F817002E56AA /* Debug */ = {
18
+ # isa = XCBuildConfiguration;
19
+ # buildSettings = {
20
+ # "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
21
+ # GCC_PRECOMPILE_PREFIX_HEADER = YES;
22
+ # GCC_PREFIX_HEADER = "newtarget/newtarget-Prefix.pch";
23
+ # INFOPLIST_FILE = "newtarget/newtarget-Info.plist";
24
+ # PRODUCT_NAME = "$(TARGET_NAME)";
25
+ # WRAPPER_EXTENSION = app;
26
+ # };
27
+ # name = Debug;
28
+ # };
29
+ #
30
+ module Configuration
31
+
32
+ def self.default_properties(name)
33
+ { 'isa' => 'XCBuildConfiguration',
34
+ 'buildSettings' => {
35
+ "SDKROOT" => "iphoneos",
36
+ "OTHER_CFLAGS" => "-DNS_BLOCK_ASSERTIONS=1",
37
+ "TARGETED_DEVICE_FAMILY" => "1,2",
38
+ "GCC_C_LANGUAGE_STANDARD" => "gnu99",
39
+ "ALWAYS_SEARCH_USER_PATHS" => "NO",
40
+ "GCC_VERSION" => "com.apple.compilers.llvm.clang.1_0",
41
+ "ARCHS" => "$(ARCHS_STANDARD_32_BIT)",
42
+ "GCC_WARN_ABOUT_MISSING_PROTOTYPES" => "YES",
43
+ "GCC_WARN_ABOUT_RETURN_TYPE" => "YES",
44
+ "CODE_SIGN_IDENTITY[sdk=>iphoneos*]" => "iPhone Developer",
45
+ "GCC_PRECOMPILE_PREFIX_HEADER" => "YES",
46
+ "VALIDATE_PRODUCT" => "YES",
47
+ "IPHONEOS_DEPLOYMENT_TARGET" => "5.0",
48
+ "COPY_PHASE_STRIP" => "YES",
49
+ "GCC_PREFIX_HEADER" => "#{name}/#{name}-Prefix.pch",
50
+ "INFOPLIST_FILE" => "#{name}/#{name}-Info.plist",
51
+ "PRODUCT_NAME" => "$(TARGET_NAME)",
52
+ "WRAPPER_EXTENSION" => "app" },
53
+ "name" => name }
54
+ end
55
+
56
+ #
57
+ # The configuration is defined within a target.
58
+ # @see PBXNativeTarget
59
+ #
60
+ attr_accessor :target
61
+
62
+ #
63
+ # @return the location for the InfoPlist file for the configuration.
64
+ # @see InfoPlist
65
+ #
66
+ def info_plist_location
67
+ build_settings['INFOPLIST_FILE']
68
+ end
69
+
70
+ #
71
+ # Opens the info plist associated with the configuration and allows you to
72
+ # edit the configuration.
73
+ #
74
+ # @example Editing the configuration
75
+ #
76
+ # config = Xcode.project('MyProject.xcodeproj').target('Application').config('Debug')
77
+ # config.info_plist do |plist|
78
+ # puts plist.version # => 1.0
79
+ # plist.version = 1.1
80
+ # marketing_version = 12.1
81
+ # end
82
+ #
83
+ # @see InfoPlist
84
+ #
85
+ def info_plist
86
+ # puts @json.inspect
87
+ info = Xcode::InfoPlist.new(self, info_plist_location)
88
+ yield info if block_given?
89
+ info.save
90
+ info
91
+ end
92
+
93
+ #
94
+ # @return the name of the product that this configuration will generate.
95
+ #
96
+ def product_name
97
+ substitute(build_settings['PRODUCT_NAME'])
98
+ end
99
+
100
+ #
101
+ # Retrieve the configuration value for the given name
102
+ #
103
+ # @param [String] name of the configuration settings to return
104
+ # @return [String,Array,Hash] the value stored for the specified configuration
105
+ #
106
+ def get(name)
107
+ build_settings[name]
108
+ end
109
+
110
+ #
111
+ # Set the configuration value for the given name
112
+ #
113
+ # @param [String] name of the the configuration setting
114
+ # @param [String,Array,Hash] value the value to store for the specific setting
115
+ #
116
+ def set(name, value)
117
+ build_settings[name] = value
118
+ end
119
+
120
+
121
+ #
122
+ # Create a builder for this given project->target->configuration.
123
+ #
124
+ # @return [Builder] this is a builder for the configuration.
125
+ # @see Builder
126
+ #
127
+ def builder
128
+ puts "Making a Builder with #{self} #{self.methods}"
129
+ Xcode::Builder.new(self)
130
+ end
131
+
132
+
133
+ private
134
+
135
+ #
136
+ # Within the configuration properties variables reference the target,
137
+ # i.e."$(TARGET_NAME)". This method will find and replace the target
138
+ # constant with the appropriate value.
139
+ #
140
+ # @param [String] value is a property of the configuration that may contain
141
+ # the target variable to replace.
142
+ #
143
+ # @return [String] a string without the variable reference.
144
+ #
145
+ def substitute(value)
146
+ if value=~/\$\(.*\)/
147
+ value.gsub(/\$\((.*)\)/) do |match|
148
+ case match
149
+ when "$(TARGET_NAME)"
150
+ @target.name
151
+ else
152
+ raise "Unknown substitution variable #{match}"
153
+ end
154
+ end
155
+ else
156
+ value
157
+ end
158
+ end
159
+
160
+ end
161
+ end
@@ -0,0 +1,85 @@
1
+ module Xcode
2
+ module ConfigurationList
3
+
4
+ #
5
+ # @example configuration list
6
+ #
7
+ # 7165D47D146B4EA100DE2F0E /* Build configuration list for PBXNativeTarget "TestProject" */ = {
8
+ # isa = XCConfigurationList;
9
+ # buildConfigurations = (
10
+ # 7165D47E146B4EA100DE2F0E /* Debug */,
11
+ # 7165D47F146B4EA100DE2F0E /* Release */,
12
+ # );
13
+ # defaultConfigurationIsVisible = 0;
14
+ # defaultConfigurationName = Release;
15
+ # };
16
+ def self.configration_list
17
+ { 'isa' => 'XCConfigurationList',
18
+ 'buildConfigurations' => [],
19
+ 'defaultConfigurationIsVisible' => '0',
20
+ 'defaultConfigurationName' => '' }
21
+ end
22
+
23
+ #
24
+ # @return [Hash] a hash of symbol names to configuration names.
25
+ #
26
+ def self.symbol_config_name_to_config_name
27
+ { :debug => 'Debug', :release => 'Release' }
28
+ end
29
+
30
+ #
31
+ # Create a configuration for this ConfigurationList. This configuration needs
32
+ # to have a name.
33
+ #
34
+ # @note unique names are currently not enforced but likely necessary for the
35
+ # the target to be build successfully.
36
+ #
37
+ # @param [Types] name Description
38
+ #
39
+ def create_config(name)
40
+
41
+ name = ConfigurationList.symbol_config_name_to_config_name[name] if ConfigurationList.symbol_config_name_to_config_name[name]
42
+
43
+ # @todo a configuration has additional fields that are ususally set with
44
+ # some target information for the title.
45
+
46
+ new_config = @registry.add_object(Configuration.default_properties(name))
47
+ @properties['buildConfigurations'] << new_config.identifier
48
+
49
+ yield new_config if block_given?
50
+
51
+ new_config.save!
52
+ end
53
+
54
+ #
55
+ # @return [BuildConfiguration] the build configuration that is set to default;
56
+ # nil if no configuration has been set as default.
57
+ #
58
+ def default_config
59
+ build_configurations.find {|config| config.name == default_configuration_name }
60
+ end
61
+
62
+ #
63
+ # @return [String] the name of the default build configuration; nil if no
64
+ # configuration has been set as default.
65
+ #
66
+ def default_config_name
67
+ default_configuration_name
68
+ end
69
+
70
+ #
71
+ # @todo allow the ability for a configuration to set itself as default and/or
72
+ # let a configuration be specified as a parameter here. Though we need
73
+ # to check to see that the configuration is part of the this configuration
74
+ # list.
75
+ #
76
+ # @param [String] name of the build configuration to set as the default
77
+ # configuration; specify nil if you want to remove any default configuration.
78
+ #
79
+ def set_default_config(name)
80
+ # @todo ensure that the name specified is one of the available configurations
81
+ @properties['defaultConfigurationName'] = name
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,23 @@
1
+ class Array
2
+
3
+ #
4
+ # Arrays in an Xcode project take a particular format.
5
+ #
6
+ # @note the last element in the array can have a comma; it is optional.
7
+ #
8
+ # @example output format:
9
+ #
10
+ # (
11
+ # ITEM1,
12
+ # ITEM2,
13
+ # ITEM3
14
+ # )
15
+ #
16
+ def to_xcplist
17
+ plist_of_items = map {|item| item.to_xcplist }.join(",\n")
18
+
19
+ %{(
20
+ #{plist_of_items}
21
+ )}
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+
2
+
3
+ class TrueClass
4
+
5
+ #
6
+ # Xcode project's expect boolean trues to be the word YES.
7
+ #
8
+ def to_xcplist
9
+ "YES"
10
+ end
11
+ end
12
+
13
+ class FalseClass
14
+
15
+ #
16
+ # Xcode project's expect boolean trues to be the word NO.
17
+ #
18
+ def to_xcplist
19
+ "NO"
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ class Fixnum
2
+ def to_xcplist
3
+ to_s
4
+ end
5
+ end
@@ -0,0 +1,27 @@
1
+ class Hash
2
+
3
+ #
4
+ # Hashes in an Xcode project take a particular format.
5
+ #
6
+ # @note the keys are represeted in this output with quotes; this is actually
7
+ # optional for certain keys based on their format. This is done to ensure
8
+ # that all keys that do not conform are ensured proper output.
9
+ #
10
+ # @example output format:
11
+ #
12
+ # {
13
+ # "KEY" = "VALUE";
14
+ # "KEY" = "VALUE";
15
+ # "KEY" = "VALUE";
16
+ # }
17
+ #
18
+ def to_xcplist
19
+ plist_of_items = map do |k,v|
20
+ "\"#{k}\" = #{v.to_xcplist};"
21
+ end.join("\n")
22
+
23
+ %{{
24
+ #{plist_of_items}
25
+ }}
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ require 'json'
2
+
3
+ class String
4
+
5
+ #
6
+ # Xcode format for a string is exactly the same as you would expect in JSON
7
+ #
8
+ def to_xcplist
9
+ to_json
10
+ end
11
+
12
+ #
13
+ # Similar to ActiveRecord's underscore method. Return a string version
14
+ # underscored. This is used specifically to convert the property keys into
15
+ # Ruby friendly names as they are used for creating method names.
16
+ #
17
+ # @return [String] convert camel-cased words, generating underscored, ruby
18
+ # friend names.
19
+ def underscore
20
+ self.gsub(/::/, '/').
21
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
22
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
23
+ tr("-", "_").
24
+ downcase
25
+ end
26
+ end