rxcode 0.0.5
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/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
|