xcodeproj 0.28.2 → 1.0.0.beta.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eae456c17889ae1b3dc65acb3e95122776f584f5
4
- data.tar.gz: 30e4ee588cfccff194ad57520a64737e2bf7434e
3
+ metadata.gz: 55e5e01727aa2cef3b7bc6e1682340c8b795adfd
4
+ data.tar.gz: df9be60720e81d807f9206ef7e1aac6bbf2f47f2
5
5
  SHA512:
6
- metadata.gz: e149c929d82e0593c8accbbdedd4bb6a23405b976aefcfb551d50381aada69b8b39725240ff4c34f99918c3aaa57c178cc939dae69537eb04516e1cb0ea5d3d9
7
- data.tar.gz: 82e272ca562aae5487bd0ef985e411f1576a55b1e6056a3dd6b4434e88f5700632e236e06b98acad5d6af8acc8c292e3bca7d1c5a756a24a06bf79910e1934be
6
+ metadata.gz: e26720ad177f765056a554e514a9c4465aa94b4619fbd8947e0a221704926f8df605e8cc9a1a46c97e87dd4574023834e169144df4d0f4dce5e01460cfd937af
7
+ data.tar.gz: 72832c119af852d63ae64df30ebda2f7cb5090c83b57684b07b1cb57f3cd3686850c292dd2d66ece72c8ca3960ac54db87885aff33c0f60ea41df37e65da85fb
data/lib/xcodeproj.rb CHANGED
@@ -20,7 +20,7 @@ module Xcodeproj
20
20
  autoload :Constants, 'xcodeproj/constants'
21
21
  autoload :Differ, 'xcodeproj/differ'
22
22
  autoload :Helper, 'xcodeproj/helper'
23
- autoload :PlistHelper, 'xcodeproj/plist_helper'
23
+ autoload :Plist, 'xcodeproj/plist'
24
24
  autoload :Project, 'xcodeproj/project'
25
25
  autoload :Workspace, 'xcodeproj/workspace'
26
26
  autoload :XCScheme, 'xcodeproj/scheme'
@@ -23,7 +23,7 @@ module Xcodeproj
23
23
 
24
24
  def initialize(argv)
25
25
  self.xcodeproj_path = argv.shift_argument
26
- @output_path = Pathname(argv.shift_argument || '.')
26
+ @output_path = Pathname(argv.shift_argument || '.')
27
27
 
28
28
  super
29
29
  end
@@ -82,7 +82,7 @@ module Xcodeproj
82
82
  def to_s(prefix = nil)
83
83
  include_lines = includes.map { |path| "#include \"#{normalized_xcconfig_path(path)}\"" }
84
84
  settings = to_hash(prefix).sort_by(&:first).map { |k, v| "#{k} = #{v}".strip }
85
- [include_lines + settings].join("\n")
85
+ (include_lines + settings).join("\n") << "\n"
86
86
  end
87
87
 
88
88
  # Writes the serialized representation of the internal data to the given
@@ -275,9 +275,17 @@ module Xcodeproj
275
275
  #
276
276
  def merge_attributes!(attributes)
277
277
  @attributes.merge!(attributes) do |_, v1, v2|
278
- v1, v2 = v1.strip, v2.strip
279
- existing = v1.strip.shellsplit
280
- existing.include?(v2) ? v1 : "#{v1} #{v2}"
278
+ v1 = v1.strip
279
+ v2 = v2.strip
280
+ v1_split = v1.shellsplit
281
+ v2_split = v2.shellsplit
282
+ if (v2_split - v1_split).empty? || v1_split.first(v2_split.size) == v2_split
283
+ v1
284
+ elsif v2_split.first(v1_split.size) == v1_split
285
+ v2
286
+ else
287
+ "#{v1} #{v2}"
288
+ end
281
289
  end
282
290
  end
283
291
 
@@ -317,7 +325,8 @@ module Xcodeproj
317
325
  def extract_key_value(line)
318
326
  match = line.match(KEY_VALUE_PATTERN)
319
327
  if match
320
- key, value = match[1], match[2]
328
+ key = match[1]
329
+ value = match[2]
321
330
  [key.strip, value.strip]
322
331
  else
323
332
  []
@@ -8,7 +8,7 @@ module Xcodeproj
8
8
  # @return [Hash{Symbol, Array[String]}] Splits the given
9
9
  # other linker flags value by type.
10
10
  #
11
- # @param [String] flags
11
+ # @param [String, Array] flags
12
12
  # The other linker flags value.
13
13
  #
14
14
  def self.parse(flags)
@@ -21,7 +21,10 @@ module Xcodeproj
21
21
  }
22
22
 
23
23
  key = nil
24
- split(flags).each do |token|
24
+ if flags.is_a? String
25
+ flags = split(flags)
26
+ end
27
+ flags.each do |token|
25
28
  case token
26
29
  when '-framework'
27
30
  key = :frameworks
@@ -4,17 +4,17 @@ module Xcodeproj
4
4
  module Constants
5
5
  # @return [String] The last known iOS SDK (stable).
6
6
  #
7
- LAST_KNOWN_IOS_SDK = '9.0'
7
+ LAST_KNOWN_IOS_SDK = '9.2'
8
8
 
9
9
  # @return [String] The last known OS X SDK (stable).
10
10
  #
11
- LAST_KNOWN_OSX_SDK = '10.11'
11
+ LAST_KNOWN_OSX_SDK = '10.11'
12
12
 
13
- # @return [String] The last known tvOS SDK (unstable).
14
- LAST_KNOWN_TVOS_SDK = '9.0'
13
+ # @return [String] The last known tvOS SDK (stable).
14
+ LAST_KNOWN_TVOS_SDK = '9.1'
15
15
 
16
- # @return [String] The last known watchOS SDK.
17
- LAST_KNOWN_WATCHOS_SDK = '2.0'
16
+ # @return [String] The last known watchOS SDK (stable).
17
+ LAST_KNOWN_WATCHOS_SDK = '2.1'
18
18
 
19
19
  # @return [String] The last known archive version to Xcodeproj.
20
20
  #
@@ -25,15 +25,15 @@ module Xcodeproj
25
25
 
26
26
  # @return [String] The last known object version to Xcodeproj.
27
27
  #
28
- LAST_KNOWN_OBJECT_VERSION = 47
28
+ LAST_KNOWN_OBJECT_VERSION = 47
29
29
 
30
30
  # @return [String] The last known object version to Xcodeproj.
31
31
  #
32
- LAST_UPGRADE_CHECK = '0700'
32
+ LAST_UPGRADE_CHECK = '0700'
33
33
 
34
34
  # @return [String] The last known object version to Xcodeproj.
35
35
  #
36
- LAST_SWIFT_UPGRADE_CHECK = '0700'
36
+ LAST_SWIFT_UPGRADE_CHECK = '0720'
37
37
 
38
38
  # @return [String] The version of `.xcscheme` files supported by Xcodeproj
39
39
  #
@@ -119,6 +119,7 @@ module Xcodeproj
119
119
  :watch2_app => 'com.apple.product-type.application.watchapp2',
120
120
  :watch_extension => 'com.apple.product-type.watchkit-extension',
121
121
  :watch2_extension => 'com.apple.product-type.watchkit2-extension',
122
+ :tv_extension => 'com.apple.product-type.tv-app-extension',
122
123
  }.freeze
123
124
 
124
125
  # @return [Hash] The extensions or the various product UTIs.
@@ -138,13 +139,16 @@ module Xcodeproj
138
139
  #
139
140
  COMMON_BUILD_SETTINGS = {
140
141
  :all => {
141
- 'PRODUCT_NAME' => '$(TARGET_NAME)',
142
142
  'ENABLE_STRICT_OBJC_MSGSEND' => 'YES',
143
+ 'GCC_NO_COMMON_BLOCKS' => 'YES',
144
+ 'PRODUCT_NAME' => '$(TARGET_NAME)',
143
145
  }.freeze,
144
146
  [:debug] => {
147
+ 'DEBUG_INFORMATION_FORMAT' => 'dwarf',
145
148
  'MTL_ENABLE_DEBUG_INFO' => 'YES',
146
149
  }.freeze,
147
150
  [:release] => {
151
+ 'DEBUG_INFORMATION_FORMAT' => 'dwarf-with-dsym',
148
152
  'MTL_ENABLE_DEBUG_INFO' => 'NO',
149
153
  }.freeze,
150
154
  [:ios] => {
@@ -163,23 +167,18 @@ module Xcodeproj
163
167
  # Empty?
164
168
  }.freeze,
165
169
  [:release, :osx] => {
166
- 'DEBUG_INFORMATION_FORMAT' => 'dwarf-with-dsym',
170
+ # Empty?
167
171
  }.freeze,
168
172
  [:debug, :ios] => {
169
173
  # Empty?
170
174
  }.freeze,
171
175
  [:debug, :application, :swift] => {
172
176
  'SWIFT_OPTIMIZATION_LEVEL' => '-Onone',
173
- 'ENABLE_TESTABILITY' => 'YES',
174
177
  }.freeze,
175
- [:debug, :dynamic_library, :swift] => {
176
- 'ENABLE_TESTABILITY' => 'YES',
177
- }.freeze,
178
- [:debug, :framework, :swift] => {
179
- 'ENABLE_TESTABILITY' => 'YES',
178
+ [:debug, :swift] => {
179
+ 'SWIFT_OPTIMIZATION_LEVEL' => '-Onone',
180
180
  }.freeze,
181
181
  [:debug, :static_library, :swift] => {
182
- 'ENABLE_TESTABILITY' => 'YES',
183
182
  }.freeze,
184
183
  [:framework] => {
185
184
  'VERSION_INFO_PREFIX' => '',
@@ -200,25 +199,43 @@ module Xcodeproj
200
199
  [:osx, :framework] => {
201
200
  'LD_RUNPATH_SEARCH_PATHS' => ['$(inherited)', '@executable_path/../Frameworks', '@loader_path/Frameworks'],
202
201
  'FRAMEWORK_VERSION' => 'A',
202
+ 'CODE_SIGN_IDENTITY' => '-',
203
203
  'COMBINE_HIDPI_IMAGES' => 'YES',
204
204
  }.freeze,
205
+ [:watchos, :framework] => {
206
+ 'APPLICATION_EXTENSION_API_ONLY' => 'YES',
207
+ 'LD_RUNPATH_SEARCH_PATHS' => ['$(inherited)', '@executable_path/Frameworks', '@loader_path/Frameworks'],
208
+ 'TARGETED_DEVICE_FAMILY' => '4',
209
+ }.freeze,
210
+ [:tvos, :framework] => {
211
+ 'LD_RUNPATH_SEARCH_PATHS' => ['$(inherited)', '@executable_path/Frameworks', '@loader_path/Frameworks'],
212
+ 'TARGETED_DEVICE_FAMILY' => '3',
213
+ }.freeze,
205
214
  [:framework, :swift] => {
206
215
  'DEFINES_MODULE' => 'YES',
207
216
  }.freeze,
208
- [:debug, :framework, :swift] => {
209
- 'SWIFT_OPTIMIZATION_LEVEL' => '-Onone',
210
- }.freeze,
211
217
  [:osx, :static_library] => {
218
+ 'CODE_SIGN_IDENTITY' => '-',
212
219
  'EXECUTABLE_PREFIX' => 'lib',
213
220
  }.freeze,
214
221
  [:ios, :static_library] => {
222
+ 'CODE_SIGN_IDENTITY[sdk=iphoneos*]' => 'iPhone Developer',
223
+ 'OTHER_LDFLAGS' => '-ObjC',
224
+ 'SKIP_INSTALL' => 'YES',
225
+ }.freeze,
226
+ [:watchos, :static_library] => {
227
+ 'OTHER_LDFLAGS' => '-ObjC',
228
+ 'SKIP_INSTALL' => 'YES',
229
+ }.freeze,
230
+ [:tvos, :static_library] => {
215
231
  'OTHER_LDFLAGS' => '-ObjC',
216
232
  'SKIP_INSTALL' => 'YES',
217
233
  }.freeze,
218
234
  [:osx, :dynamic_library] => {
219
- 'EXECUTABLE_PREFIX' => 'lib',
235
+ 'CODE_SIGN_IDENTITY' => '-',
220
236
  'DYLIB_COMPATIBILITY_VERSION' => '1',
221
237
  'DYLIB_CURRENT_VERSION' => '1',
238
+ 'EXECUTABLE_PREFIX' => 'lib',
222
239
  }.freeze,
223
240
  [:application] => {
224
241
  'ASSETCATALOG_COMPILER_APPICON_NAME' => 'AppIcon',
@@ -226,12 +243,26 @@ module Xcodeproj
226
243
  [:ios, :application] => {
227
244
  'CODE_SIGN_IDENTITY[sdk=iphoneos*]' => 'iPhone Developer',
228
245
  'LD_RUNPATH_SEARCH_PATHS' => ['$(inherited)', '@executable_path/Frameworks'],
246
+ 'TARGETED_DEVICE_FAMILY' => '1,2',
229
247
  }.freeze,
230
248
  [:osx, :application] => {
231
249
  'COMBINE_HIDPI_IMAGES' => 'YES',
232
250
  'CODE_SIGN_IDENTITY' => '-',
233
251
  'LD_RUNPATH_SEARCH_PATHS' => ['$(inherited)', '@executable_path/../Frameworks'],
234
252
  }.freeze,
253
+ [:watchos, :application] => {
254
+ 'SKIP_INSTALL' => 'YES',
255
+ 'TARGETED_DEVICE_FAMILY' => '4',
256
+ }.freeze,
257
+ [:watchos, :application, :swift] => {
258
+ 'EMBEDDED_CONTENT_CONTAINS_SWIFT' => 'YES',
259
+ }.freeze,
260
+ [:tvos, :application] => {
261
+ 'ASSETCATALOG_COMPILER_APPICON_NAME' => 'App Icon & Top Shelf Image',
262
+ 'ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME' => 'LaunchImage',
263
+ 'TARGETED_DEVICE_FAMILY' => '3',
264
+ 'LD_RUNPATH_SEARCH_PATHS' => ['$(inherited)', '@executable_path/Frameworks'],
265
+ }.freeze,
235
266
  [:bundle] => {
236
267
  'PRODUCT_NAME' => '$(TARGET_NAME)',
237
268
  'WRAPPER_EXTENSION' => 'bundle',
@@ -241,9 +272,10 @@ module Xcodeproj
241
272
  'SDKROOT' => 'iphoneos',
242
273
  }.freeze,
243
274
  [:osx, :bundle] => {
275
+ 'CODE_SIGN_IDENTITY' => '-',
244
276
  'COMBINE_HIDPI_IMAGES' => 'YES',
245
- 'SDKROOT' => 'macosx',
246
277
  'INSTALL_PATH' => '$(LOCAL_LIBRARY_DIR)/Bundles',
278
+ 'SDKROOT' => 'macosx',
247
279
  }.freeze,
248
280
  }.freeze
249
281
 
@@ -281,6 +313,7 @@ module Xcodeproj
281
313
  :debug => {
282
314
  'ONLY_ACTIVE_ARCH' => 'YES',
283
315
  'COPY_PHASE_STRIP' => 'NO',
316
+ 'ENABLE_TESTABILITY' => 'YES',
284
317
  'GCC_DYNAMIC_NO_PIC' => 'NO',
285
318
  'GCC_OPTIMIZATION_LEVEL' => '0',
286
319
  'GCC_PREPROCESSOR_DEFINITIONS' => ['DEBUG=1', '$(inherited)'],
@@ -313,6 +346,6 @@ module Xcodeproj
313
346
 
314
347
  # @return [Array] The extensions which are associated with header files.
315
348
  #
316
- HEADER_FILES_EXTENSIONS = %w(.h .hh .hpp .ipp .tpp).freeze
349
+ HEADER_FILES_EXTENSIONS = %w(.h .hh .hpp .ipp .tpp .hxx .def).freeze
317
350
  end
318
351
  end
@@ -43,8 +43,8 @@ module Xcodeproj
43
43
  # @return [Nil] if the given values are equal.
44
44
  #
45
45
  def self.diff(value_1, value_2, options = {})
46
- options[:key_1] ||= 'value_1'
47
- options[:key_2] ||= 'value_2'
46
+ options[:key_1] ||= 'value_1'
47
+ options[:key_2] ||= 'value_2'
48
48
  options[:id_key] ||= nil
49
49
 
50
50
  if value_1.class == value_2.class
@@ -1,5 +1,5 @@
1
1
  module Xcodeproj
2
2
  # The version of the xcodeproj gem.
3
3
  #
4
- VERSION = '0.28.2' unless defined? Xcodeproj::VERSION
4
+ VERSION = '1.0.0.beta.1'.freeze unless defined? Xcodeproj::VERSION
5
5
  end
@@ -0,0 +1,89 @@
1
+ module Xcodeproj
2
+ # Provides support for loading and serializing property list files.
3
+ #
4
+ module Plist
5
+ autoload :FFI, 'xcodeproj/plist/ffi'
6
+ autoload :PlistGem, 'xcodeproj/plist/plist_gem'
7
+
8
+ # @return [Hash] Returns the native objects loaded from a property list
9
+ # file.
10
+ #
11
+ # @param [#to_s] path
12
+ # The path of the file.
13
+ #
14
+ def self.read_from_path(path)
15
+ path = path.to_s
16
+ unless File.exist?(path)
17
+ raise Informative, "The plist file at path `#{path}` doesn't exist."
18
+ end
19
+ if file_in_conflict?(path)
20
+ raise Informative, "The file `#{path}` is in a merge conflict."
21
+ end
22
+ implementation.read_from_path(path)
23
+ end
24
+
25
+ # Serializes a hash as an XML property list file.
26
+ #
27
+ # @param [#to_hash] hash
28
+ # The hash to store.
29
+ #
30
+ # @param [#to_s] path
31
+ # The path of the file.
32
+ #
33
+ def self.write_to_path(hash, path)
34
+ if hash.respond_to?(:to_hash)
35
+ hash = hash.to_hash
36
+ else
37
+ raise TypeError, "The given `#{hash.inspect}` must respond " \
38
+ "to #to_hash'."
39
+ end
40
+
41
+ unless path.is_a?(String) || path.is_a?(Pathname)
42
+ raise TypeError, "The given `#{path}` must be a string or 'pathname'."
43
+ end
44
+ path = path.to_s
45
+ raise IOError, 'Empty path.' if path.empty?
46
+ implementation.write_to_path(hash, path)
47
+ end
48
+
49
+ # The known modules that can serialize plists.
50
+ #
51
+ KNOWN_IMPLEMENTATIONS = [:FFI, :PlistGem]
52
+
53
+ class << self
54
+ # @return The module used to implement plist serialization.
55
+ #
56
+ attr_accessor :implementation
57
+ def implementation
58
+ @implementation ||= autoload_implementation
59
+ end
60
+ end
61
+
62
+ # Attempts to autoload a known plist implementation.
63
+ #
64
+ # @return a successfully loaded plist serialization implementation.
65
+ #
66
+ def self.autoload_implementation
67
+ failures = KNOWN_IMPLEMENTATIONS.map do |impl|
68
+ begin
69
+ impl = Plist.const_get(impl)
70
+ failure = impl.attempt_to_load!
71
+ return impl if failure.nil?
72
+ failure
73
+ rescue NameError, LoadError => e
74
+ e.message
75
+ end
76
+ end.compact
77
+ raise Informative, "Unable to load a plist implementation:\n\n#{failures.join("\n\n")}"
78
+ end
79
+
80
+ # @return [Bool] Checks whether there are merge conflicts in the file.
81
+ #
82
+ # @param [#to_s] path
83
+ # The path of the file.
84
+ #
85
+ def self.file_in_conflict?(path)
86
+ File.read(path).match(/^(<|=|>){7}/)
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,119 @@
1
+ module Xcodeproj
2
+ module Plist
3
+ # Provides support for loading and serializing property list files via
4
+ # Fiddle and CoreFoundation / Xcode.
5
+ #
6
+ module FFI
7
+ autoload :CoreFoundation, 'xcodeproj/plist/ffi/core_foundation'
8
+ autoload :DevToolsCore, 'xcodeproj/plist/ffi/dev_tools_core'
9
+
10
+ class << self
11
+ # Attempts to load the `fiddle` and Xcode based plist serializer.
12
+ #
13
+ # @return [String,Nil] The loading error message, or `nil` if loading
14
+ # was successful.
15
+ #
16
+ def attempt_to_load!
17
+ return @attempt_to_load if defined?(@attempt_to_load)
18
+ @attempt_to_load = begin
19
+ require 'fiddle'
20
+ nil
21
+ rescue LoadError
22
+ 'Xcodeproj relies on a library called `fiddle` to read and write ' \
23
+ 'Xcode project files. Ensure your Ruby installation includes ' \
24
+ '`fiddle` and try again.'
25
+ end
26
+ end
27
+
28
+ # Serializes a hash as an XML property list file.
29
+ #
30
+ # @param [#to_hash] hash
31
+ # The hash to store.
32
+ #
33
+ # @param [#to_s] path
34
+ # The path of the file.
35
+ #
36
+ def write_to_path(hash, path)
37
+ raise ThreadError, 'Can only write plists from the main thread.' unless Thread.current == Thread.main
38
+
39
+ if DevToolsCore.load_xcode_frameworks && path.end_with?('pbxproj')
40
+ ruby_hash_write_xcode(hash, path)
41
+ else
42
+ CoreFoundation.RubyHashPropertyListWrite(hash, path)
43
+ fix_encoding(path)
44
+ end
45
+ end
46
+
47
+ # @return [Hash] Returns the native objects loaded from a property list
48
+ # file.
49
+ #
50
+ # @param [#to_s] path
51
+ # The path of the file.
52
+ #
53
+ def read_from_path(path)
54
+ CoreFoundation.RubyHashPropertyListRead(path)
55
+ end
56
+
57
+ private
58
+
59
+ # Simple workaround to escape characters which are outside of ASCII
60
+ # character-encoding. Relies on the fact that there are no XML characters
61
+ # which would need to be escaped.
62
+ #
63
+ # @note This is necessary because Xcode (4.6 currently) uses the MacRoman
64
+ # encoding unless the `// !$*UTF8*$!` magic comment is present. It
65
+ # is not possible to serialize a plist using the NeXTSTEP format
66
+ # without access to the private classes of Xcode and that comment
67
+ # is not compatible with the XML format. For the complete
68
+ # discussion see CocoaPods/CocoaPods#926.
69
+ #
70
+ #
71
+ # @note Sadly this hack is not sufficient for supporting Emoji.
72
+ #
73
+ # @param [String, Pathname] The path of the file which needs to be fixed.
74
+ #
75
+ # @return [void]
76
+ #
77
+ def fix_encoding(filename)
78
+ output = ''
79
+ input = File.open(filename, 'rb', &:read)
80
+ input.unpack('U*').each do |codepoint|
81
+ if codepoint > 127 # ASCII is 7-bit, so 0-127 are valid characters
82
+ output << "&##{codepoint};"
83
+ else
84
+ output << codepoint.chr
85
+ end
86
+ end
87
+ File.open(filename, 'wb') { |file| file.write(output) }
88
+ end
89
+
90
+ # Serializes a hash as an ASCII plist, using Xcode.
91
+ #
92
+ # @param [Hash] hash
93
+ # The hash to store.
94
+ #
95
+ # @param [String] path
96
+ # The path of the file.
97
+ #
98
+ def ruby_hash_write_xcode(hash, path)
99
+ path = File.expand_path(path)
100
+ success = true
101
+
102
+ begin
103
+ plist = DevToolsCore::CFDictionary.new(CoreFoundation.RubyHashToCFDictionary(hash))
104
+ data = DevToolsCore::NSData.new(plist.plistDescriptionUTF8Data)
105
+ success &= data.writeToFileAtomically(path)
106
+
107
+ project = DevToolsCore::PBXProject.new(path)
108
+ success &= project.writeToFileSystemProjectFile
109
+ project.close
110
+ rescue Fiddle::DLError
111
+ success = false
112
+ end
113
+
114
+ CoreFoundation.RubyHashPropertyListWrite(hash, path) unless success
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end