cocoapods-mapfile 0.2.0 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +80 -43
- data/bin/{hmap_writer → hmapfile} +2 -2
- data/lib/cocoapods_plugin.rb +18 -6
- data/lib/hmap/command/hmap_gen.rb +52 -0
- data/lib/{cocoapods-hmap → hmap}/command/hmap_reader.rb +14 -11
- data/lib/hmap/command/hmap_writer.rb +55 -0
- data/lib/hmap/command.rb +28 -0
- data/lib/hmap/constants.rb +198 -0
- data/lib/{cocoapods-hmap → hmap}/exceptions.rb +0 -0
- data/lib/{cocoapods-hmap → hmap/helper}/executable.rb +5 -6
- data/lib/{cocoapods-hmap → hmap/helper}/utils.rb +0 -4
- data/lib/hmap/hmap/hmap_bucketstr.rb +20 -0
- data/lib/{cocoapods-hmap → hmap/hmap}/hmap_reader.rb +4 -19
- data/lib/{cocoapods-hmap/hmap_save.rb → hmap/hmap/hmap_saver.rb} +21 -6
- data/lib/{cocoapods-hmap → hmap/hmap}/hmap_struct.rb +5 -4
- data/lib/hmap/hmap/hmap_writer.rb +52 -0
- data/lib/{cocoapods-hmap → hmap/hmap}/mapfile.rb +1 -1
- data/lib/hmap/user_interface.rb +22 -0
- data/lib/hmap/version.rb +5 -0
- data/lib/hmap/xc/context.rb +23 -0
- data/lib/hmap/xc/header_entry.rb +55 -0
- data/lib/hmap/xc/header_type.rb +32 -0
- data/lib/hmap/xc/pbx_helper.rb +68 -0
- data/lib/hmap/xc/product_helper.rb +36 -0
- data/lib/hmap/xc/resolver.rb +129 -0
- data/lib/hmap/xc/target/build_setting.rb +126 -0
- data/lib/hmap/xc/target/target.rb +76 -0
- data/lib/hmap/xc/target/target_context.rb +29 -0
- data/lib/hmap/xc/target/target_helper.rb +114 -0
- data/lib/hmap/xc/target/target_vfs.rb +122 -0
- data/lib/hmap/xc/target/xcconfig_helper.rb +109 -0
- data/lib/hmap/xc/workspace/project.rb +120 -0
- data/lib/hmap/xc/workspace/project_helper.rb +92 -0
- data/lib/hmap/xc/workspace/workspace.rb +83 -0
- data/lib/hmap.rb +24 -0
- metadata +76 -38
- data/bin/hmap_reader +0 -12
- data/lib/cocoapods-hmap/command/hmap_gen.rb +0 -52
- data/lib/cocoapods-hmap/framework/framework_vfs.rb +0 -95
- data/lib/cocoapods-hmap/helper/build_setting_helper.rb +0 -40
- data/lib/cocoapods-hmap/helper/pods_helper.rb +0 -104
- data/lib/cocoapods-hmap/helper/xcconfig_helper.rb +0 -82
- data/lib/cocoapods-hmap/hmap_writer.rb +0 -107
- data/lib/cocoapods-hmap/pods_specification.rb +0 -60
- data/lib/cocoapods-hmap/version.rb +0 -5
- data/lib/cocoapods-hmap/view.rb +0 -34
- data/lib/cocoapods_hmap.rb +0 -21
@@ -1,22 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require 'hmap/hmap/hmap_struct'
|
2
3
|
|
3
4
|
module HMap
|
4
|
-
# hmap bucket
|
5
|
-
class HMapBucketStr
|
6
|
-
attr_reader :key, :perfix, :suffix
|
7
|
-
|
8
|
-
def initialize(key, perfix, suffix)
|
9
|
-
@key = key
|
10
|
-
@perfix = perfix
|
11
|
-
@suffix = suffix
|
12
|
-
end
|
13
|
-
|
14
|
-
def description
|
15
|
-
<<-DESC
|
16
|
-
Key #{@key} -> Prefix #{@perfix}, Suffix #{@suffix}
|
17
|
-
DESC
|
18
|
-
end
|
19
|
-
end
|
20
5
|
# hmap file reader
|
21
6
|
class MapFileReader
|
22
7
|
# @return [String, nil] the filename loaded from, or nil if loaded from a binary
|
@@ -31,7 +16,7 @@ module HMap
|
|
31
16
|
# @return [HMap::HMapHeader]
|
32
17
|
attr_reader :header
|
33
18
|
|
34
|
-
# @return [Hash<HMap::HMapBucket => HMap::
|
19
|
+
# @return [Hash<HMap::HMapBucket => HMap::BucketStr>] an array of the file's bucktes
|
35
20
|
# @note bucktes are provided in order of ascending offset.
|
36
21
|
attr_reader :bucktes
|
37
22
|
|
@@ -54,7 +39,7 @@ module HMap
|
|
54
39
|
bucket_s = bucket.to_a.map do |key|
|
55
40
|
string_t[key..-1].match(/[^\0]+/)[0]
|
56
41
|
end
|
57
|
-
|
42
|
+
BucketStr.new(*bucket_s)
|
58
43
|
end
|
59
44
|
end
|
60
45
|
|
@@ -101,7 +86,7 @@ module HMap
|
|
101
86
|
|
102
87
|
# description
|
103
88
|
def description
|
104
|
-
sum = " Header map: #{filename}\n" + header.description
|
89
|
+
sum = " Header map path: #{filename}\n" + header.description
|
105
90
|
bucktes.each_with_index do |buckte_h, index|
|
106
91
|
sum += "\t- Bucket: #{index}" + Utils.safe_encode(buckte_h.values[0].description, 'UTF-8') unless buckte_h.nil?
|
107
92
|
sum
|
@@ -1,9 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'hmap/hmap/hmap_struct'
|
4
|
+
require 'hmap/hmap/mapfile'
|
5
|
+
|
3
6
|
module HMap
|
4
7
|
class HMapSaver
|
5
8
|
attr_reader :string_table, :buckets, :headers
|
6
9
|
|
10
|
+
def self.new_from_buckets(buckets)
|
11
|
+
saver = new
|
12
|
+
saver.add_to_buckets(buckets)
|
13
|
+
saver
|
14
|
+
end
|
15
|
+
|
7
16
|
def initialize
|
8
17
|
@string_table = "\0"
|
9
18
|
@buckets = []
|
@@ -13,7 +22,7 @@ module HMap
|
|
13
22
|
def header_to_hash(keys, headers, index, buckets)
|
14
23
|
index = index.length
|
15
24
|
keys.inject('') do |sum, bucket|
|
16
|
-
buckte =
|
25
|
+
buckte = BucketStr.new(*bucket)
|
17
26
|
string_t = buckte.bucket_to_string(headers, index + sum.length)
|
18
27
|
buckets.push(buckte)
|
19
28
|
sum + string_t
|
@@ -32,15 +41,21 @@ module HMap
|
|
32
41
|
headers[key]
|
33
42
|
end
|
34
43
|
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
|
44
|
+
def add_to_bucket(buckte)
|
45
|
+
key = add_to_headers(buckte.key)
|
46
|
+
perfix = add_to_headers(buckte.perfix)
|
47
|
+
suffix = add_to_headers(buckte.suffix)
|
48
|
+
bucket = HMapBucket.new(key, perfix, suffix)
|
49
|
+
bucket.uuid = Utils.string_downcase_hash(buckte.key)
|
39
50
|
@buckets << bucket
|
40
51
|
end
|
41
52
|
|
53
|
+
def add_to_buckets(buckets)
|
54
|
+
buckets.each { |bucket| add_to_bucket(bucket) }
|
55
|
+
end
|
56
|
+
|
42
57
|
def write_to(path)
|
43
|
-
MapFile.new(@string_table, @buckets).write(path)
|
58
|
+
MapFile.new(@string_table, @buckets).write(Pathname(path))
|
44
59
|
end
|
45
60
|
end
|
46
61
|
end
|
@@ -65,7 +65,7 @@ module HMap
|
|
65
65
|
# @see https://clang.llvm.org/doxygen/structclang_1_1HMapHeader.html
|
66
66
|
# @abstract
|
67
67
|
class HMapHeader < HMapStructure
|
68
|
-
# @return [HMap::
|
68
|
+
# @return [HMap::HMapHeader, nil] the raw view associated with the load command,
|
69
69
|
# or nil if the HMapHeader was created via {create}.
|
70
70
|
attr_reader :num_entries, :magic, :version, :reserved, :strings_offset, :num_buckets, :max_value_length
|
71
71
|
|
@@ -112,6 +112,7 @@ module HMap
|
|
112
112
|
}.merge super
|
113
113
|
end
|
114
114
|
end
|
115
|
+
|
115
116
|
# HMapBucket structure.
|
116
117
|
# @see https://clang.llvm.org/doxygen/structclang_1_1HMapHeader.html
|
117
118
|
# @abstract
|
@@ -157,7 +158,7 @@ module HMap
|
|
157
158
|
@header = populate_hmap_header(nums, entries)
|
158
159
|
@buckets = add_bucket(buckets, nums)
|
159
160
|
end
|
160
|
-
|
161
|
+
|
161
162
|
def num_buckets(count, pow2)
|
162
163
|
if count < 8
|
163
164
|
pow2 <<= 1 if count * 4 >= pow2 * 3
|
@@ -181,8 +182,8 @@ module HMap
|
|
181
182
|
def serialize
|
182
183
|
@header.serialize + @buckets.inject('') do |sum, bucket|
|
183
184
|
sum += if bucket.nil?
|
184
|
-
|
185
|
-
|
185
|
+
empty_b = [HEADER_CONST[:HMAP_EMPTY_BUCKT_KEY]] * 3
|
186
|
+
empty_b.pack('L<3')
|
186
187
|
else
|
187
188
|
bucket
|
188
189
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'hmap/xc/workspace/workspace'
|
4
|
+
|
5
|
+
module HMap
|
6
|
+
class HMapTarget
|
7
|
+
attr_reader :name, :target
|
8
|
+
end
|
9
|
+
|
10
|
+
# Helper module which returns handle method from MapFileWriter.
|
11
|
+
class MapFileWriter
|
12
|
+
# @param save_origin_header_search_paths save_origin_header_search_paths
|
13
|
+
# @param clean_hmap clean up all hmap setup
|
14
|
+
# @param allow_targets this targets will save origin build setting
|
15
|
+
# @param use_build_in_headermap option use Xcode header map
|
16
|
+
def initialize(use_origin, project_root, clean_hmap)
|
17
|
+
UserInterface.puts("[hmapfile] Workspace/project root: #{project_root}..............")
|
18
|
+
UserInterface.puts("[hmapfile] Analyzing dependencies..............")
|
19
|
+
Resolver.instance.installation_root = project_root
|
20
|
+
Resolver.instance.use_origin = use_origin
|
21
|
+
create_hmapfile(clean_hmap)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Integrates the projects mapfile associated
|
25
|
+
# with the App project and Pods project.
|
26
|
+
#
|
27
|
+
# @param [clean] clean hmap dir @see #podfile
|
28
|
+
# @return [void]
|
29
|
+
#
|
30
|
+
def create_hmapfile(clean)
|
31
|
+
# {a,b}– Match pattern a or b.
|
32
|
+
# Though this looks like a regular expression quantifier, it isn't.
|
33
|
+
# For example, in regular expression, the pattern a{1,2} will match 1 or 2 'a' characters.
|
34
|
+
# In globbing, it will match the string a1 or a2.
|
35
|
+
paths = Dir.glob(File.join(Resolver.instance.installation_root, '*.{xcworkspace,xcodeproj}'))
|
36
|
+
workspace_paths = paths.select { |f| File.extname(f) == '.xcworkspace' }
|
37
|
+
xcs = if workspace_paths.nil?
|
38
|
+
project_paths = paths.select { |f| File.extname(f) == '.xcodeproj' }
|
39
|
+
Workspace.new_from_xcprojects(project_paths) unless project_paths.nil?
|
40
|
+
else
|
41
|
+
Workspace.new_from_xcworkspaces(workspace_paths)
|
42
|
+
end
|
43
|
+
xcs.each do |xc|
|
44
|
+
if clean
|
45
|
+
xc.remove_hmap_settings!
|
46
|
+
else
|
47
|
+
xc.write_save!
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -6,7 +6,7 @@ module HMap
|
|
6
6
|
# @return mapfile string_table
|
7
7
|
attr_reader :string_table
|
8
8
|
|
9
|
-
# @return [Array<HMap::
|
9
|
+
# @return [Array<HMap::BucketStr>] an array of the file's bucktes
|
10
10
|
# @note bucktes are provided in order of ascending offset.
|
11
11
|
attr_reader :buckets
|
12
12
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module HMap
|
2
|
+
# Manages the UI output so clients can customize it.
|
3
|
+
#
|
4
|
+
module UserInterface
|
5
|
+
# Prints a message to standard output.
|
6
|
+
#
|
7
|
+
# @return [void]
|
8
|
+
#
|
9
|
+
def self.puts(message)
|
10
|
+
STDOUT.puts message
|
11
|
+
end
|
12
|
+
|
13
|
+
# Prints a message to standard error.
|
14
|
+
#
|
15
|
+
# @return [void]
|
16
|
+
#
|
17
|
+
def self.warn(message)
|
18
|
+
STDERR.puts message
|
19
|
+
end
|
20
|
+
end
|
21
|
+
UI = UserInterface
|
22
|
+
end
|
data/lib/hmap/version.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HMap
|
4
|
+
class Context
|
5
|
+
attr_reader :build_root, :hmap_root, :temp_name, :build_dir, :temp_dir
|
6
|
+
|
7
|
+
def initialize(build_root, temp_dir, hmap_root, temp_name, build_dir)
|
8
|
+
@build_root = build_root
|
9
|
+
@temp_dir = temp_dir
|
10
|
+
@hmap_root = hmap_root
|
11
|
+
@temp_name = temp_name
|
12
|
+
@build_dir = build_dir || ''
|
13
|
+
end
|
14
|
+
|
15
|
+
def build_path(platform)
|
16
|
+
File.join(build_root, platform.to_s, build_dir)
|
17
|
+
end
|
18
|
+
|
19
|
+
def temp_path(platform)
|
20
|
+
File.join(temp_dir, platform.to_s, temp_name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module HMap
|
2
|
+
class HeaderEntry
|
3
|
+
attr_reader :path, :extra_keys, :type
|
4
|
+
|
5
|
+
def initialize(path, extra_keys, type)
|
6
|
+
@path = path
|
7
|
+
@extra_keys = extra_keys
|
8
|
+
@type = type
|
9
|
+
end
|
10
|
+
|
11
|
+
def project_buckets
|
12
|
+
h_name = File.basename(path)
|
13
|
+
h_dir = File.dirname(path)
|
14
|
+
[BucketStr.new(h_name, "#{h_dir}/", h_name)]
|
15
|
+
end
|
16
|
+
|
17
|
+
def module_buckets(moudle_name)
|
18
|
+
h_name = File.basename(path)
|
19
|
+
module_p = "#{moudle_name}/"
|
20
|
+
[BucketStr.new(h_name, module_p, h_name)]
|
21
|
+
end
|
22
|
+
|
23
|
+
def full_module_buckets(moudle_name)
|
24
|
+
h_name = File.basename(path)
|
25
|
+
h_dir = File.dirname(path)
|
26
|
+
module_k = "#{moudle_name}/#{h_name}"
|
27
|
+
[BucketStr.new(module_k, "#{h_dir}/", h_name)]
|
28
|
+
end
|
29
|
+
|
30
|
+
def project_buckets_extra
|
31
|
+
h_name = File.basename(path)
|
32
|
+
h_dir = File.dirname(path)
|
33
|
+
buckets = []
|
34
|
+
buckets << BucketStr.new(h_name, "#{h_dir}/", h_name) unless extra_keys.include?(h_name)
|
35
|
+
buckets + extra_keys.map { |key| BucketStr.new(key, "#{h_dir}/", h_name) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def module_buckets_extra(moudle_name)
|
39
|
+
h_name = File.basename(path)
|
40
|
+
module_p = "#{moudle_name}/"
|
41
|
+
buckets = []
|
42
|
+
buckets << BucketStr.new(h_name, module_p, h_name) unless extra_keys.include?(h_name)
|
43
|
+
buckets + extra_keys.map { |key| BucketStr.new(key, module_p, h_name) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def full_module_buckets_extra(moudle_name)
|
47
|
+
h_name = File.basename(path)
|
48
|
+
h_dir = File.dirname(path)
|
49
|
+
module_k = "#{moudle_name}/#{h_name}"
|
50
|
+
buckets = []
|
51
|
+
buckets << BucketStr.new(module_k, "#{h_dir}/", h_name) unless extra_keys.include?(module_k)
|
52
|
+
buckets + extra_keys.map { |key| BucketStr.new(key, "#{h_dir}/", h_name) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
require 'hmap/xc/header_entry'
|
3
|
+
|
4
|
+
module HMap
|
5
|
+
module HeaderType
|
6
|
+
def public_entrys
|
7
|
+
return @public_entrys if defined?(@public_entrys)
|
8
|
+
|
9
|
+
@public_entrys = entrys.select { |entry| entry.type == :Public }
|
10
|
+
end
|
11
|
+
|
12
|
+
def private_entrys
|
13
|
+
return @private_entrys if defined?(@private_entrys)
|
14
|
+
|
15
|
+
@private_entrys = entrys.select { |entry| entry.type == :Private }
|
16
|
+
end
|
17
|
+
|
18
|
+
def project_entrys
|
19
|
+
return @project_entrys if defined?(@project_entrys)
|
20
|
+
|
21
|
+
@project_entrys = entrys.select { |entry| entry.type == :Project }
|
22
|
+
end
|
23
|
+
|
24
|
+
def use_vfs?
|
25
|
+
!public_entrys.empty? || !private_entrys.empty? || build_as_framework?
|
26
|
+
end
|
27
|
+
|
28
|
+
def headers_hash(*types)
|
29
|
+
Hash[types.map { |type| [type, send(type)] }]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module HMap
|
2
|
+
module PBXHelper
|
3
|
+
def self.get_groups(xct)
|
4
|
+
groups = xct.referrers.select { |e| e.is_a?(Constants::PBXGroup) } || []
|
5
|
+
groups += groups.flat_map { |g| get_groups(g) }
|
6
|
+
groups.compact.reverse
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.group_paths(xct)
|
10
|
+
ps = get_groups(xct).map do |g|
|
11
|
+
s_hash = g.instance_variable_get('@simple_attributes_hash')
|
12
|
+
s_hash['path'] unless s_hash.nil?
|
13
|
+
end.compact
|
14
|
+
File.join(*ps)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.uses_swift?(target)
|
18
|
+
source_files = target.build_phases.flat_map do |phase|
|
19
|
+
phase.files if phase.is_a?(Constants::PBXSourcesBuildPhase)
|
20
|
+
end.compact
|
21
|
+
source_files.any? do |file|
|
22
|
+
path = file.file_ref.instance_variable_get('@simple_attributes_hash')['path'] || ''
|
23
|
+
File.extname(path) == '.swift'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.build_as_framework?(target)
|
28
|
+
target.symbol_type == :framework if target.respond_to?(:symbol_type)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.defines_module?(target)
|
32
|
+
return true if build_as_framework?(target)
|
33
|
+
|
34
|
+
bus = target.build_configuration_list.build_configurations.map do |bu|
|
35
|
+
bu.instance_variable_get('@simple_attributes_hash')['buildSettings'] || {}
|
36
|
+
end
|
37
|
+
|
38
|
+
bus.any? { |s| s['DEFINES_MODULE'] == 'YES' }
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.projects(*p_paths)
|
42
|
+
return if p_paths.empty?
|
43
|
+
|
44
|
+
p_paths.flat_map do |pj|
|
45
|
+
project = Xcodeproj::Project.open(pj)
|
46
|
+
p_path = File.dirname(project.path)
|
47
|
+
project.root_object.project_references.map do |sp|
|
48
|
+
ff = sp[:project_ref]
|
49
|
+
path = ff.instance_variable_get('@simple_attributes_hash')['path'] || ''
|
50
|
+
full_path = File.join(p_path, path)
|
51
|
+
Xcodeproj::Project.open(full_path)
|
52
|
+
end << project
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.project_references(project)
|
57
|
+
return if project.nil?
|
58
|
+
|
59
|
+
p_path = File.dirname(project.path)
|
60
|
+
project.root_object.project_references.map do |sp|
|
61
|
+
ff = sp[:project_ref]
|
62
|
+
path = ff.instance_variable_get('@simple_attributes_hash')['path'] || ''
|
63
|
+
full_path = File.join(p_path, path)
|
64
|
+
Xcodeproj::Project.open(full_path)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'hmap/xc/resolver'
|
3
|
+
module HMap
|
4
|
+
class ProductPath
|
5
|
+
attr_reader :path, :build_setting, :name
|
6
|
+
|
7
|
+
def initialize(path)
|
8
|
+
@path = path
|
9
|
+
raise ArgumentError, "#{path}: can not get build directory" if @build_setting.nil?
|
10
|
+
end
|
11
|
+
|
12
|
+
def build_root
|
13
|
+
Pathname(build_setting[Constants::BUILD_DIR])
|
14
|
+
end
|
15
|
+
|
16
|
+
def obj_root
|
17
|
+
Pathname(build_setting[Constants::OBJROOT])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class WorkspaceProductPath < ProductPath
|
22
|
+
def initialize(path)
|
23
|
+
@name = File.basename(path, '.xcworkspace')
|
24
|
+
@build_setting = Resolver.instance.workspace_build_settings(path)
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class ProjectProductPath < ProductPath
|
30
|
+
def initialize(path)
|
31
|
+
@name = File.basename(path, '.xcodeproj')
|
32
|
+
@build_setting = Resolver.instance.project_build_settings(path)
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'hmap/helper/executable'
|
4
|
+
|
5
|
+
module HMap
|
6
|
+
class Resolver
|
7
|
+
# @return [Array<String>] The filenames that the Podfile can have ordered
|
8
|
+
# by priority.
|
9
|
+
#
|
10
|
+
PODFILE_NAMES = [
|
11
|
+
'CocoaPods.podfile.yaml',
|
12
|
+
'CocoaPods.podfile',
|
13
|
+
'Podfile',
|
14
|
+
'Podfile.rb'
|
15
|
+
].freeze
|
16
|
+
|
17
|
+
attr_accessor :use_origin
|
18
|
+
|
19
|
+
def self.instance
|
20
|
+
@instance ||= new
|
21
|
+
end
|
22
|
+
|
23
|
+
# Sets the current config instance. If set to nil the config will be
|
24
|
+
# recreated when needed.
|
25
|
+
#
|
26
|
+
# @param [Config, Nil] the instance.
|
27
|
+
#
|
28
|
+
# @return [void]
|
29
|
+
#
|
30
|
+
class << self
|
31
|
+
attr_writer :instance
|
32
|
+
end
|
33
|
+
|
34
|
+
def workspace_build_settings(workspace)
|
35
|
+
workspace_dic = xcodebuild_list(workspace)['workspace']
|
36
|
+
schemes = workspace_dic['schemes'] || []
|
37
|
+
targets = xcodebuild_workspace(workspace, schemes[0]) || []
|
38
|
+
targets.first['buildSettings']
|
39
|
+
end
|
40
|
+
|
41
|
+
def project_build_settings(project_path)
|
42
|
+
targets = xcodebuild(project_path) || []
|
43
|
+
targets.first['buildSettings']
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Pathname] the root of the workspace or project where is located.
|
47
|
+
#
|
48
|
+
def installation_root
|
49
|
+
@installation_root ||= begin
|
50
|
+
current_dir = Pathname.new(Dir.pwd.unicode_normalize)
|
51
|
+
current_path = current_dir
|
52
|
+
until current_path.root?
|
53
|
+
if podfile_path_in_dir(current_path)
|
54
|
+
installation_root = current_path
|
55
|
+
puts("[in #{current_path}]") unless current_path == current_dir
|
56
|
+
break
|
57
|
+
else
|
58
|
+
current_path = current_path.parent
|
59
|
+
end
|
60
|
+
end
|
61
|
+
installation_root || current_dir
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
attr_writer :installation_root
|
66
|
+
alias project_root installation_root
|
67
|
+
|
68
|
+
def verbose?
|
69
|
+
false
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [String] Executes xcodebuild list in the current working directory and
|
73
|
+
# returns its output (both STDOUT and STDERR).
|
74
|
+
#
|
75
|
+
def xcodebuild_list(workspace)
|
76
|
+
command = %W[-workspace #{workspace}]
|
77
|
+
command += %w[-json -list]
|
78
|
+
results = Executable.execute_command('xcodebuild', command, false)
|
79
|
+
JSON.parse(results) unless results.nil?
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [hash] Executes xcodebuild -workspace -scheme in the current working directory and
|
83
|
+
# returns its output (both STDOUT and STDERR).
|
84
|
+
#
|
85
|
+
def xcodebuild_workspace(workspace, scheme)
|
86
|
+
command = %W[-workspace #{workspace}]
|
87
|
+
command += %W[-scheme #{scheme}]
|
88
|
+
xcodebuild(command)
|
89
|
+
end
|
90
|
+
|
91
|
+
# @return [hash] Executes xcodebuild -project in the current working directory and
|
92
|
+
# returns its output (both STDOUT and STDERR).
|
93
|
+
#
|
94
|
+
def xcodebuild_project(project)
|
95
|
+
command = %W[-project #{project}]
|
96
|
+
xcodebuild(command)
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# Returns the path of the Podfile in the given dir if any exists.
|
102
|
+
#
|
103
|
+
# @param [Pathname] dir
|
104
|
+
# The directory where to look for the Podfile.
|
105
|
+
#
|
106
|
+
# @return [Pathname] The path of the Podfile.
|
107
|
+
# @return [Nil] If not Podfile was found in the given dir
|
108
|
+
#
|
109
|
+
def podfile_path_in_dir(dir)
|
110
|
+
PODFILE_NAMES.each do |filename|
|
111
|
+
candidate = dir + filename
|
112
|
+
return candidate if candidate.file?
|
113
|
+
end
|
114
|
+
nil
|
115
|
+
end
|
116
|
+
|
117
|
+
# @return [hash] Executes xcodebuild in the current working directory, get build settings and
|
118
|
+
# returns its output as hash (both STDOUT and STDERR).
|
119
|
+
#
|
120
|
+
def xcodebuild(command)
|
121
|
+
command += %w[-json -showBuildSettings]
|
122
|
+
results = Executable.execute_command('xcodebuild', command, false)
|
123
|
+
index = results.index(/"action"/m)
|
124
|
+
reg = results[index..-1]
|
125
|
+
reg = "[\n{\n#{reg}"
|
126
|
+
JSON.parse(reg) unless results.nil?
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|