rxcode 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +17 -0
- data/LICENSE.txt +12 -0
- data/README.md +7 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/bin/rxcode +9 -0
- data/lib/rxcode.rb +17 -0
- data/lib/rxcode/command.rb +179 -0
- data/lib/rxcode/commands.rb +4 -0
- data/lib/rxcode/commands/env.rb +45 -0
- data/lib/rxcode/commands/init.rb +74 -0
- data/lib/rxcode/commands/unwrap.rb +76 -0
- data/lib/rxcode/environment.rb +80 -0
- data/lib/rxcode/macruby.rb +16 -0
- data/lib/rxcode/models.rb +8 -0
- data/lib/rxcode/models/archive.rb +78 -0
- data/lib/rxcode/models/archived_object.rb +62 -0
- data/lib/rxcode/models/build_configuration.rb +19 -0
- data/lib/rxcode/models/build_configuration_list.rb +15 -0
- data/lib/rxcode/models/file_reference.rb +23 -0
- data/lib/rxcode/models/model.rb +66 -0
- data/lib/rxcode/models/project.rb +71 -0
- data/lib/rxcode/models/target.rb +47 -0
- data/lib/rxcode/preferences.rb +32 -0
- data/lib/rxcode/spec/nserror_helpers.rb +19 -0
- data/lib/rxcode/spec/rake_ext.rb +27 -0
- data/lib/rxcode/spec/rake_task.rb +20 -0
- data/lib/rxcode/spec_helper.rb +19 -0
- data/lib/rxcode/tasks.rb +24 -0
- data/lib/rxcode/tasks/bridge_support.rb +39 -0
- data/lib/rxcode/tasks/ios_framework.rb +266 -0
- data/lib/rxcode/tasks/spec.rb +3 -0
- data/lib/rxcode/templates/Gemfile +4 -0
- data/lib/rxcode/templates/Rakefile +4 -0
- data/lib/rxcode/templates/spec/spec_helper.rb +14 -0
- data/lib/rxcode/templates/spec/support/.gitkeep +0 -0
- data/lib/rxcode/workspace.rb +173 -0
- metadata +184 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
module RXCode
|
2
|
+
|
3
|
+
class Target < Model
|
4
|
+
|
5
|
+
# ===== NAME =======================================================================================================
|
6
|
+
|
7
|
+
def name
|
8
|
+
archive_object['name']
|
9
|
+
end
|
10
|
+
|
11
|
+
# ===== PRODUCT ====================================================================================================
|
12
|
+
|
13
|
+
def product_name
|
14
|
+
archive_object['productName']
|
15
|
+
end
|
16
|
+
|
17
|
+
def product_reference
|
18
|
+
archive_object.model_object_for_key('productReference')
|
19
|
+
end
|
20
|
+
|
21
|
+
# ===== PRODUCT TYPE ===============================================================================================
|
22
|
+
|
23
|
+
def product_type
|
24
|
+
archive_object['productType']
|
25
|
+
end
|
26
|
+
|
27
|
+
def framework?
|
28
|
+
product_type == 'com.apple.product-type.framework'
|
29
|
+
end
|
30
|
+
|
31
|
+
def application?
|
32
|
+
product_type == 'com.apple.product-type.application'
|
33
|
+
end
|
34
|
+
|
35
|
+
def bundle?
|
36
|
+
product_type == 'com.apple.product-type.bundle'
|
37
|
+
end
|
38
|
+
|
39
|
+
# ===== BUILD CONFIGURATIONS =======================================================================================
|
40
|
+
|
41
|
+
def build_configuration_list
|
42
|
+
archive_object.model_object_for_key('buildConfigurationList')
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'plist'
|
2
|
+
|
3
|
+
module RXCode
|
4
|
+
|
5
|
+
def self.xcode_preferences
|
6
|
+
@preferences ||= Preferences.new
|
7
|
+
end
|
8
|
+
|
9
|
+
#
|
10
|
+
# Provides access to global XCode preferences.
|
11
|
+
#
|
12
|
+
class Preferences
|
13
|
+
|
14
|
+
attr_reader :defaults
|
15
|
+
|
16
|
+
def initialize(defaults = nil)
|
17
|
+
defaults ||= Plist::parse_xml(`defaults read com.apple.dt.Xcode | plutil -convert xml1 -o - -`)
|
18
|
+
|
19
|
+
@defaults = defaults
|
20
|
+
end
|
21
|
+
|
22
|
+
def derived_data_location
|
23
|
+
defaults['IDECustomDerivedDataLocation'] || File.expand_path("~/Library/Developer/Xcode/DerivedData")
|
24
|
+
end
|
25
|
+
|
26
|
+
def derived_data_location_is_relative_to_workspace?
|
27
|
+
!derived_data_location.start_with?('/')
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RXCode
|
2
|
+
module Spec
|
3
|
+
|
4
|
+
module NSErrorHelpers
|
5
|
+
|
6
|
+
def error_ptr
|
7
|
+
@error_ptr ||= Pointer.new(:object)
|
8
|
+
end
|
9
|
+
|
10
|
+
def check_error_ptr!
|
11
|
+
unless error_ptr[0].nil?
|
12
|
+
fail error_ptr[0].localizedDescription
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#
|
2
|
+
# Extensions to workaround segfaults in MacRuby and Rake 0.8.7
|
3
|
+
#
|
4
|
+
|
5
|
+
if defined?(Rake::AltSystem)
|
6
|
+
|
7
|
+
#
|
8
|
+
# The Rake gem aliases Kernel.system and the backtick operator into this module. For some reason, this causes a
|
9
|
+
# Segfault. Strangely AltSystem doesn't exist in the MacRuby-provided rake.
|
10
|
+
#
|
11
|
+
module Rake::AltSystem
|
12
|
+
|
13
|
+
def self.system(*args)
|
14
|
+
Kernel.system(*args)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.`(*args)
|
18
|
+
Kernel.method(:`).call(*args)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.backticks(*args)
|
22
|
+
Kernel.method(:`).call(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'rxcode/spec/rake_ext'
|
3
|
+
|
4
|
+
module RXCode
|
5
|
+
module Spec
|
6
|
+
|
7
|
+
class RakeTask < ::RSpec::Core::RakeTask
|
8
|
+
|
9
|
+
def initialize(*args)
|
10
|
+
super do |t|
|
11
|
+
t.pattern = "./**/Specs/**/*_spec.rb"
|
12
|
+
|
13
|
+
yield t if block_given?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
begin
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rspec'
|
4
|
+
rescue LoadError => e
|
5
|
+
puts "RSpec not found. Install it to rxcode spec tasks"
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'rxcode'
|
9
|
+
require 'rxcode/spec/nserror_helpers'
|
10
|
+
|
11
|
+
module RSpec
|
12
|
+
module Core
|
13
|
+
class ExampleGroup
|
14
|
+
|
15
|
+
include RXCode::Spec::NSErrorHelpers
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/rxcode/tasks.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rxcode'
|
2
|
+
|
3
|
+
module RXCode
|
4
|
+
|
5
|
+
def self.being_run_by_xcode?
|
6
|
+
ENV['XCODE_VERSION_ACTUAL'] != nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.building_cocoa_framework?
|
10
|
+
ENV['PACKAGE_TYPE'] == 'com.apple.package-type.wrapper.framework'
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.xcode_action
|
14
|
+
ENV['ACTION']
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'rxcode/tasks/bridge_support'
|
20
|
+
require 'rxcode/tasks/ios_framework'
|
21
|
+
|
22
|
+
if defined?(MACRUBY_VERSION)
|
23
|
+
require 'rxcode/tasks/spec'
|
24
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
if RXCode.being_run_by_xcode? && RXCode.building_cocoa_framework?
|
2
|
+
bridge_support_folder_path = File.join(ENV['BUILT_PRODUCTS_DIR'],
|
3
|
+
ENV['UNLOCALIZED_RESOURCES_FOLDER_PATH'],
|
4
|
+
'BridgeSupport')
|
5
|
+
|
6
|
+
framework_location = File.join(ENV['BUILT_PRODUCTS_DIR'], ENV['FULL_PRODUCT_NAME'])
|
7
|
+
bridge_support_file_location = File.join(bridge_support_folder_path, "#{ENV['PRODUCT_NAME']}.bridgesupport")
|
8
|
+
|
9
|
+
directory bridge_support_folder_path
|
10
|
+
|
11
|
+
file bridge_support_file_location => bridge_support_folder_path do |t|
|
12
|
+
|
13
|
+
puts "Building #{bridge_support_file_location.inspect}"
|
14
|
+
result = `gen_bridge_metadata --64-bit -f "#{framework_location}" -o "#{bridge_support_file_location}"`
|
15
|
+
unless $?.success?
|
16
|
+
puts result
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
public_headers_location = File.join(ENV['BUILT_PRODUCTS_DIR'], ENV['PUBLIC_HEADERS_FOLDER_PATH'])
|
23
|
+
FileList[File.join(public_headers_location, '**', '*.h')].each do |header_file|
|
24
|
+
file bridge_support_file_location => header_file
|
25
|
+
end
|
26
|
+
|
27
|
+
private_headers_location = File.join(ENV['BUILT_PRODUCTS_DIR'], ENV['PRIVATE_HEADERS_FOLDER_PATH'])
|
28
|
+
FileList[File.join(private_headers_location, '**', '*.h')].each do |header_file|
|
29
|
+
file bridge_support_file_location => header_file
|
30
|
+
end
|
31
|
+
|
32
|
+
namespace :rxcode do
|
33
|
+
|
34
|
+
desc %{Generates the BridgeSupport file for a Cocoa framework.}
|
35
|
+
task :generate_bridgesupport_file => bridge_support_file_location
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,266 @@
|
|
1
|
+
if RXCode.being_run_by_xcode?
|
2
|
+
|
3
|
+
module RXCode
|
4
|
+
module XCode
|
5
|
+
|
6
|
+
class CommandLine
|
7
|
+
|
8
|
+
def initialize(options = nil)
|
9
|
+
if options
|
10
|
+
options.each { |attr_name, attr_value| self.send("#{attr_name}=", attr_value) }
|
11
|
+
end
|
12
|
+
|
13
|
+
yield self if block_given?
|
14
|
+
end
|
15
|
+
|
16
|
+
# ===== ACTION =================================================================================================
|
17
|
+
|
18
|
+
attr_accessor :action
|
19
|
+
|
20
|
+
def action_arguments
|
21
|
+
if action
|
22
|
+
[ action ]
|
23
|
+
else
|
24
|
+
[]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# ===== PROJECT ================================================================================================
|
29
|
+
|
30
|
+
def project_name
|
31
|
+
ENV['PROJECT_NAME']
|
32
|
+
end
|
33
|
+
|
34
|
+
def project_file_path
|
35
|
+
ENV['PROJECT_FILE_PATH'] || "#{project_name}.xcodeproj"
|
36
|
+
end
|
37
|
+
|
38
|
+
def project_arguments
|
39
|
+
[ '-project', project_file_path ]
|
40
|
+
end
|
41
|
+
|
42
|
+
# ===== TARGET =================================================================================================
|
43
|
+
|
44
|
+
def target
|
45
|
+
@target || target_name
|
46
|
+
end
|
47
|
+
attr_writer :target
|
48
|
+
|
49
|
+
def target_name
|
50
|
+
ENV['TARGET_NAME']
|
51
|
+
end
|
52
|
+
|
53
|
+
def target_arguments
|
54
|
+
if target
|
55
|
+
[ "-target", "'#{target}'" ]
|
56
|
+
else
|
57
|
+
[]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# ===== CONFIGURATION ==========================================================================================
|
62
|
+
|
63
|
+
def configuration
|
64
|
+
ENV['CONFIGURATION']
|
65
|
+
end
|
66
|
+
|
67
|
+
def configuration_arguments
|
68
|
+
[ '-configuration', configuration]
|
69
|
+
end
|
70
|
+
|
71
|
+
# ===== SDK ====================================================================================================
|
72
|
+
|
73
|
+
attr_accessor :sdk
|
74
|
+
|
75
|
+
def sdk_arguments
|
76
|
+
if sdk.nil?
|
77
|
+
[]
|
78
|
+
else
|
79
|
+
[ '-sdk', sdk ]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# ===== BUILD LOCATION =========================================================================================
|
84
|
+
|
85
|
+
def symroot
|
86
|
+
ENV['SYMROOT']
|
87
|
+
end
|
88
|
+
|
89
|
+
# ===== ENVIRONMENT VARIABLES ==================================================================================
|
90
|
+
|
91
|
+
def default_environment
|
92
|
+
default_env = {}
|
93
|
+
default_env['SYMROOT'] = symroot if symroot
|
94
|
+
default_env
|
95
|
+
end
|
96
|
+
|
97
|
+
def environment
|
98
|
+
@environment ||= {}
|
99
|
+
end
|
100
|
+
|
101
|
+
def command_environment
|
102
|
+
default_environment.merge(environment)
|
103
|
+
end
|
104
|
+
|
105
|
+
def command_variables
|
106
|
+
environment.collect { |var_name, value| "#{var_name}='#{value}'" }.join(' ')
|
107
|
+
end
|
108
|
+
|
109
|
+
# ===== COMMAND ================================================================================================
|
110
|
+
|
111
|
+
def xcodebuild_binary
|
112
|
+
"xcodebuild"
|
113
|
+
end
|
114
|
+
|
115
|
+
def command_line_arguments
|
116
|
+
project_arguments + target_arguments + configuration_arguments + sdk_arguments + action_arguments
|
117
|
+
end
|
118
|
+
|
119
|
+
def command
|
120
|
+
command_args = command_line_arguments.join(' ')
|
121
|
+
command_variables = command_environment.collect { |var_name, value| "#{var_name}='#{value}'" }.join(' ')
|
122
|
+
|
123
|
+
"#{xcodebuild_binary} #{command_args} #{command_variables}"
|
124
|
+
end
|
125
|
+
|
126
|
+
def dry_run?
|
127
|
+
ENV['DRY_RUN'] =~ /^(1|yes|true)$/i
|
128
|
+
end
|
129
|
+
|
130
|
+
def run(print_command = false)
|
131
|
+
puts(command) if print_command
|
132
|
+
system(command) unless dry_run?
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
namespace :rxcode do
|
141
|
+
|
142
|
+
namespace :ios_framework do
|
143
|
+
|
144
|
+
def construct_ios_framework(platform_name, *source_platforms)
|
145
|
+
build_dir = ENV['BUILD_DIR']
|
146
|
+
configuration = ENV['CONFIGURATION']
|
147
|
+
project_name = ENV['PROJECT_NAME']
|
148
|
+
product_name = ENV['PRODUCT_NAME']
|
149
|
+
static_target = ENV['STATIC_TARGET']
|
150
|
+
|
151
|
+
if source_platforms.empty?
|
152
|
+
source_platforms = [ platform_name ]
|
153
|
+
end
|
154
|
+
|
155
|
+
source_library_paths =
|
156
|
+
source_platforms.collect do |source_platform_name|
|
157
|
+
"\"#{build_dir}/#{configuration}-#{source_platform_name}/lib#{static_target}.a\""
|
158
|
+
end
|
159
|
+
|
160
|
+
platform_dir = "#{build_dir}/#{configuration}-#{platform_name}"
|
161
|
+
platform_library_path = "#{platform_dir}/#{product_name}"
|
162
|
+
framework = "#{platform_dir}/#{product_name}.framework"
|
163
|
+
|
164
|
+
# Create framework directory structure.
|
165
|
+
# rm -rf "${FRAMEWORK}" &&
|
166
|
+
# mkdir -p "${UNIVERSAL_LIBRARY_DIR}" &&
|
167
|
+
# mkdir -p "${FRAMEWORK}/Versions/A/Headers" &&
|
168
|
+
# mkdir -p "${FRAMEWORK}/Versions/A/Resources" &&
|
169
|
+
|
170
|
+
FileUtils.rm_rf framework
|
171
|
+
FileUtils.mkdir_p platform_dir
|
172
|
+
FileUtils.mkdir_p "#{framework}/Versions/A/Headers"
|
173
|
+
FileUtils.mkdir_p "#{framework}/Versions/A/Resources"
|
174
|
+
|
175
|
+
# Generate universal binary from desktop, device, and simulator builds.
|
176
|
+
# lipo "${SIMULATOR_LIBRARY_PATH}" "${DEVICE_LIBRARY_PATH}" -create -output "${UNIVERSAL_LIBRARY_PATH}" &&
|
177
|
+
`lipo #{source_library_paths.join(' ')} -create -output "#{platform_library_path}"`
|
178
|
+
|
179
|
+
# Move files to appropriate locations in framework paths.
|
180
|
+
# cp "${UNIVERSAL_LIBRARY_PATH}" "${FRAMEWORK}/Versions/A" &&
|
181
|
+
# cd "${FRAMEWORK}/Versions" &&
|
182
|
+
# ln -s "A" "Current" &&
|
183
|
+
# cd "${FRAMEWORK}" &&
|
184
|
+
# ln -s "Versions/Current/Headers" "Headers" &&
|
185
|
+
# ln -s "Versions/Current/Resources" "Resources" &&
|
186
|
+
# ln -s "Versions/Current/${PRODUCT_NAME}" "${PRODUCT_NAME}"
|
187
|
+
|
188
|
+
FileUtils.cp platform_library_path, "#{framework}/Versions/A"
|
189
|
+
Dir.chdir(framework) do
|
190
|
+
Dir.chdir("Versions") do
|
191
|
+
FileUtils.ln_s "A", "Current"
|
192
|
+
end
|
193
|
+
|
194
|
+
FileUtils.ln_s "Versions/Current/Headers", "Headers"
|
195
|
+
FileUtils.ln_s "Versions/Current/Resources", "Resources"
|
196
|
+
FileUtils.ln_s "Versions/Current/#{product_name}", product_name
|
197
|
+
end
|
198
|
+
|
199
|
+
# Copy headers from a cocoa framework
|
200
|
+
script_input_file_count = ENV['SCRIPT_INPUT_FILE_COUNT'].to_i
|
201
|
+
script_input_files = []
|
202
|
+
script_input_file_count.times do |i|
|
203
|
+
input_file_glob = ENV["SCRIPT_INPUT_FILE_#{i}"]
|
204
|
+
|
205
|
+
script_input_files.concat(Dir[ENV["SCRIPT_INPUT_FILE_#{i}"]])
|
206
|
+
end
|
207
|
+
|
208
|
+
script_input_files.each do |input_file_path|
|
209
|
+
if input_file_path =~ /\.h$/
|
210
|
+
destination_file_path = File.join("#{framework}/Versions/Current/Headers", File.basename(input_file_path))
|
211
|
+
FileUtils.cp input_file_path, destination_file_path
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
namespace :iphonesimulator do
|
217
|
+
|
218
|
+
task :build do
|
219
|
+
RXCode::XCode::CommandLine.new(:sdk => 'iphonesimulator',
|
220
|
+
:target => ENV['STATIC_TARGET'],
|
221
|
+
:action => 'build').run(true)
|
222
|
+
construct_ios_framework('iphonesimulator')
|
223
|
+
end
|
224
|
+
task :clean do
|
225
|
+
RXCode::XCode::CommandLine.new(:sdk => 'iphonesimulator',
|
226
|
+
:target => ENV['STATIC_TARGET'],
|
227
|
+
:action => 'clean').run(true)
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|
231
|
+
|
232
|
+
namespace :iphoneos do
|
233
|
+
task :build do
|
234
|
+
RXCode::XCode::CommandLine.new(:sdk => 'iphoneos',
|
235
|
+
:target => ENV['STATIC_TARGET'],
|
236
|
+
:action => 'build').run(true)
|
237
|
+
construct_ios_framework('iphoneos')
|
238
|
+
end
|
239
|
+
task :clean do
|
240
|
+
RXCode::XCode::CommandLine.new(:sdk => 'iphoneos',
|
241
|
+
:target => ENV['STATIC_TARGET'],
|
242
|
+
:action => 'clean').run(true)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
namespace :universal do
|
247
|
+
|
248
|
+
task :build => [ "rxcode:ios_framework:iphonesimulator:build", "rxcode:ios_framework:iphoneos:build"] do
|
249
|
+
construct_ios_framework('iphoneuniversal', 'iphonesimulator', 'iphoneos')
|
250
|
+
end
|
251
|
+
|
252
|
+
task :clean => [ "rxcode:ios_framework:iphonesimulator:clean", "rxcode:ios_framework:iphoneos:clean"]
|
253
|
+
|
254
|
+
end
|
255
|
+
|
256
|
+
desc %{Builds a framework bundle that can be linked to by an iOS project}
|
257
|
+
task :build => [ "rxcode:ios_framework:universal:build" ]
|
258
|
+
|
259
|
+
desc %{Cleans up after rxcode:ios_framework:build}
|
260
|
+
task :clean => [ "rxcode:ios_framework:universal:clean" ]
|
261
|
+
|
262
|
+
end
|
263
|
+
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|