cocoapods 0.37.2 → 0.38.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +136 -1
- data/lib/cocoapods.rb +0 -5
- data/lib/cocoapods/command.rb +3 -0
- data/lib/cocoapods/command/cache.rb +28 -0
- data/lib/cocoapods/command/cache/clean.rb +90 -0
- data/lib/cocoapods/command/cache/list.rb +69 -0
- data/lib/cocoapods/command/lib.rb +11 -4
- data/lib/cocoapods/command/list.rb +4 -4
- data/lib/cocoapods/command/outdated.rb +1 -10
- data/lib/cocoapods/command/project.rb +3 -2
- data/lib/cocoapods/command/spec.rb +0 -17
- data/lib/cocoapods/command/spec/cat.rb +1 -1
- data/lib/cocoapods/command/spec/create.rb +1 -0
- data/lib/cocoapods/command/spec/edit.rb +1 -1
- data/lib/cocoapods/command/spec/lint.rb +10 -4
- data/lib/cocoapods/config.rb +6 -0
- data/lib/cocoapods/downloader/cache.rb +48 -1
- data/lib/cocoapods/executable.rb +27 -6
- data/lib/cocoapods/gem_version.rb +1 -1
- data/lib/cocoapods/generator/copy_resources_script.rb +1 -0
- data/lib/cocoapods/generator/embed_frameworks_script.rb +23 -28
- data/lib/cocoapods/generator/header.rb +5 -1
- data/lib/cocoapods/generator/umbrella_header.rb +1 -1
- data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +139 -33
- data/lib/cocoapods/generator/xcconfig/private_pod_xcconfig.rb +2 -2
- data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +3 -3
- data/lib/cocoapods/installer.rb +64 -109
- data/lib/cocoapods/installer/analyzer.rb +167 -336
- data/lib/cocoapods/installer/analyzer/analysis_result.rb +46 -0
- data/lib/cocoapods/installer/analyzer/specs_state.rb +76 -0
- data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +41 -0
- data/lib/cocoapods/installer/analyzer/target_inspector.rb +203 -0
- data/lib/cocoapods/installer/file_references_installer.rb +48 -13
- data/lib/cocoapods/installer/podfile_validator.rb +86 -0
- data/lib/cocoapods/installer/{hooks_context.rb → post_install_hooks_context.rb} +3 -3
- data/lib/cocoapods/installer/pre_install_hooks_context.rb +41 -0
- data/lib/cocoapods/installer/target_installer.rb +1 -7
- data/lib/cocoapods/installer/target_installer/aggregate_target_installer.rb +15 -17
- data/lib/cocoapods/installer/target_installer/pod_target_installer.rb +4 -4
- data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +16 -16
- data/lib/cocoapods/sandbox/file_accessor.rb +20 -2
- data/lib/cocoapods/sandbox/path_list.rb +15 -13
- data/lib/cocoapods/sandbox/podspec_finder.rb +1 -0
- data/lib/cocoapods/sources_manager.rb +2 -0
- data/lib/cocoapods/target.rb +7 -37
- data/lib/cocoapods/target/aggregate_target.rb +25 -1
- data/lib/cocoapods/target/pod_target.rb +106 -10
- data/lib/cocoapods/user_interface.rb +26 -0
- data/lib/cocoapods/user_interface/error_report.rb +6 -0
- data/lib/cocoapods/validator.rb +22 -0
- metadata +21 -16
- data/lib/cocoapods/generator/target_environment_header.rb +0 -171
- data/lib/cocoapods/hooks/installer_representation.rb +0 -133
- data/lib/cocoapods/hooks/library_representation.rb +0 -93
- data/lib/cocoapods/hooks/pod_representation.rb +0 -70
@@ -8,15 +8,6 @@ module Pod
|
|
8
8
|
spec repos, not those from local/external sources or `:head` versions.
|
9
9
|
DESC
|
10
10
|
|
11
|
-
def self.options
|
12
|
-
[['--no-repo-update', 'Skip running `pod repo update` before install']].concat(super)
|
13
|
-
end
|
14
|
-
|
15
|
-
def initialize(argv)
|
16
|
-
config.skip_repo_update = !argv.flag?('repo-update', !config.skip_repo_update)
|
17
|
-
super
|
18
|
-
end
|
19
|
-
|
20
11
|
# Run the command
|
21
12
|
#
|
22
13
|
# @todo the command report new dependencies added to the Podfile as
|
@@ -98,7 +89,7 @@ module Pod
|
|
98
89
|
|
99
90
|
def spec_sets
|
100
91
|
@spec_sets ||= begin
|
101
|
-
analyzer.send(:
|
92
|
+
analyzer.send(:update_repositories) unless config.skip_repo_update?
|
102
93
|
aggregate = Source::Aggregate.new(analyzer.sources.map(&:repo))
|
103
94
|
installed_pods.map do |pod_name|
|
104
95
|
aggregate.search(Dependency.new(pod_name))
|
@@ -134,8 +134,9 @@ module Pod
|
|
134
134
|
verify_lockfile_exists!
|
135
135
|
|
136
136
|
# Check if all given pods are installed
|
137
|
-
|
138
|
-
|
137
|
+
lockfile_roots = config.lockfile.pod_names.map { |p| Specification.root_name(p) }
|
138
|
+
missing_pods = @pods.map { |p| Specification.root_name(p) }.select do |pod|
|
139
|
+
!lockfile_roots.include?(pod)
|
139
140
|
end
|
140
141
|
|
141
142
|
if missing_pods.length > 0
|
@@ -30,23 +30,6 @@ module Pod
|
|
30
30
|
help! 'A valid regular expression is required.'
|
31
31
|
end
|
32
32
|
|
33
|
-
# @return [Fixnum] the index of the chosen array item
|
34
|
-
#
|
35
|
-
def choose_from_array(array, message)
|
36
|
-
array.each_with_index do |item, index|
|
37
|
-
UI.puts "#{ index + 1 }: #{ item }"
|
38
|
-
end
|
39
|
-
|
40
|
-
UI.puts message
|
41
|
-
|
42
|
-
index = UI.gets.chomp.to_i - 1
|
43
|
-
if index < 0 || index > array.count - 1
|
44
|
-
raise Informative, "#{ index + 1 } is invalid [1-#{ array.count }]"
|
45
|
-
else
|
46
|
-
index
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
33
|
# @param [String] spec
|
51
34
|
# The name of the specification.
|
52
35
|
#
|
@@ -37,7 +37,7 @@ module Pod
|
|
37
37
|
query = @use_regex ? @query : Regexp.escape(@query)
|
38
38
|
filepath = if @show_all
|
39
39
|
specs = get_path_of_spec(query, @show_all).split(/\n/)
|
40
|
-
index = choose_from_array(specs, "Which spec would you like to print [1-#{ specs.count }]? ")
|
40
|
+
index = UI.choose_from_array(specs, "Which spec would you like to print [1-#{ specs.count }]? ")
|
41
41
|
specs[index]
|
42
42
|
else
|
43
43
|
get_path_of_spec(query)
|
@@ -177,6 +177,7 @@ Pod::Spec.new do |s|
|
|
177
177
|
# When using multiple platforms
|
178
178
|
# s.ios.deployment_target = "5.0"
|
179
179
|
# s.osx.deployment_target = "10.7"
|
180
|
+
# s.watchos.deployment_target = "2.0"
|
180
181
|
|
181
182
|
|
182
183
|
# ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
@@ -38,7 +38,7 @@ module Pod
|
|
38
38
|
if @show_all
|
39
39
|
specs = get_path_of_spec(query, @show_all).split(/\n/)
|
40
40
|
message = "Which spec would you like to edit [1-#{specs.count}]? "
|
41
|
-
index = choose_from_array(specs, message)
|
41
|
+
index = UI.choose_from_array(specs, message)
|
42
42
|
filepath = specs[index]
|
43
43
|
else
|
44
44
|
filepath = get_path_of_spec(query)
|
@@ -42,7 +42,7 @@ module Pod
|
|
42
42
|
|
43
43
|
def run
|
44
44
|
UI.puts
|
45
|
-
|
45
|
+
failure_reasons = []
|
46
46
|
podspecs_to_lint.each do |podspec|
|
47
47
|
validator = Validator.new(podspec, @source_urls)
|
48
48
|
validator.quick = @quick
|
@@ -53,7 +53,7 @@ module Pod
|
|
53
53
|
validator.only_subspec = @only_subspec
|
54
54
|
validator.use_frameworks = @use_frameworks
|
55
55
|
validator.validate
|
56
|
-
|
56
|
+
failure_reasons << validator.failure_reason
|
57
57
|
|
58
58
|
unless @clean
|
59
59
|
UI.puts "Pods project available at `#{validator.validation_dir}/Pods/Pods.xcodeproj` for inspection."
|
@@ -63,11 +63,17 @@ module Pod
|
|
63
63
|
|
64
64
|
count = podspecs_to_lint.count
|
65
65
|
UI.puts "Analyzed #{count} #{'podspec'.pluralize(count)}.\n\n"
|
66
|
-
|
66
|
+
|
67
|
+
failure_reasons.compact!
|
68
|
+
if failure_reasons.empty?
|
67
69
|
lint_passed_message = count == 1 ? "#{podspecs_to_lint.first.basename} passed validation." : 'All the specs passed validation.'
|
68
70
|
UI.puts lint_passed_message.green << "\n\n"
|
69
71
|
else
|
70
|
-
raise Informative, count == 1
|
72
|
+
raise Informative, if count == 1
|
73
|
+
"The spec did not pass validation, due to #{failure_reasons.first}."
|
74
|
+
else
|
75
|
+
"#{invalid_count} out of #{count} specs failed validation."
|
76
|
+
end
|
71
77
|
end
|
72
78
|
podspecs_tmp_dir.rmtree if podspecs_tmp_dir.exist?
|
73
79
|
end
|
data/lib/cocoapods/config.rb
CHANGED
@@ -19,6 +19,7 @@ module Pod
|
|
19
19
|
|
20
20
|
:clean => true,
|
21
21
|
:integrate_targets => true,
|
22
|
+
:deduplicate_targets => true,
|
22
23
|
:lock_pod_source => true,
|
23
24
|
:new_version_message => ENV['COCOAPODS_SKIP_UPDATE_MESSAGE'].nil?,
|
24
25
|
|
@@ -89,6 +90,11 @@ module Pod
|
|
89
90
|
attr_accessor :integrate_targets
|
90
91
|
alias_method :integrate_targets?, :integrate_targets
|
91
92
|
|
93
|
+
# @return [Bool] Whether CocoaPods should deduplicate pod targets.
|
94
|
+
#
|
95
|
+
attr_accessor :deduplicate_targets
|
96
|
+
alias_method :deduplicate_targets?, :deduplicate_targets
|
97
|
+
|
92
98
|
# @return [Bool] Whether the installer should skip the repos update.
|
93
99
|
#
|
94
100
|
attr_accessor :skip_repo_update
|
@@ -19,7 +19,7 @@ module Pod
|
|
19
19
|
#
|
20
20
|
def initialize(root)
|
21
21
|
@root = Pathname(root)
|
22
|
-
|
22
|
+
ensure_matching_version
|
23
23
|
end
|
24
24
|
|
25
25
|
# Downloads the Pod from the given `request`
|
@@ -38,8 +38,54 @@ module Pod
|
|
38
38
|
raise
|
39
39
|
end
|
40
40
|
|
41
|
+
# @return [Hash<String, Hash<Symbol, String>>]
|
42
|
+
# A hash whose keys are the pod name
|
43
|
+
# And values are a hash with the following keys:
|
44
|
+
# :spec_file : path to the spec file
|
45
|
+
# :name : name of the pod
|
46
|
+
# :version : pod version
|
47
|
+
# :release : boolean to tell if that's a release pod
|
48
|
+
# :slug : the slug path where the pod cache is located
|
49
|
+
#
|
50
|
+
def cache_descriptors_per_pod
|
51
|
+
specs_dir = root + 'Specs'
|
52
|
+
release_specs_dir = specs_dir + 'Release'
|
53
|
+
return {} unless specs_dir.exist?
|
54
|
+
|
55
|
+
spec_paths = specs_dir.find.select { |f| f.fnmatch('*.podspec.json') }
|
56
|
+
spec_paths.reduce({}) do |hash, spec_path|
|
57
|
+
spec = Specification.from_file(spec_path)
|
58
|
+
hash[spec.name] ||= []
|
59
|
+
is_release = spec_path.to_s.start_with?(release_specs_dir.to_s)
|
60
|
+
request = Downloader::Request.new(:spec => spec, :released => is_release)
|
61
|
+
hash[spec.name] << {
|
62
|
+
:spec_file => spec_path,
|
63
|
+
:name => spec.name,
|
64
|
+
:version => spec.version,
|
65
|
+
:release => is_release,
|
66
|
+
:slug => root + request.slug,
|
67
|
+
}
|
68
|
+
hash
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
41
72
|
private
|
42
73
|
|
74
|
+
# Ensures the cache on disk was created with the same CocoaPods version as
|
75
|
+
# is currently running.
|
76
|
+
#
|
77
|
+
# @return [Void]
|
78
|
+
#
|
79
|
+
def ensure_matching_version
|
80
|
+
version_file = root + 'VERSION'
|
81
|
+
version = version_file.read.strip if version_file.file?
|
82
|
+
|
83
|
+
root.rmtree if version != Pod::VERSION && root.exist?
|
84
|
+
root.mkpath
|
85
|
+
|
86
|
+
version_file.open('w') { |f| f << Pod::VERSION }
|
87
|
+
end
|
88
|
+
|
43
89
|
# @param [Request] request
|
44
90
|
# the request to be downloaded.
|
45
91
|
#
|
@@ -105,6 +151,7 @@ module Pod
|
|
105
151
|
def uncached_pod(request)
|
106
152
|
in_tmpdir do |target|
|
107
153
|
result, podspecs = download(request, target)
|
154
|
+
result.location = nil
|
108
155
|
|
109
156
|
podspecs.each do |name, spec|
|
110
157
|
destination = path_for_pod(request, :name => name, :params => result.checkout_options)
|
data/lib/cocoapods/executable.rb
CHANGED
@@ -64,7 +64,7 @@ module Pod
|
|
64
64
|
end
|
65
65
|
|
66
66
|
status = popen3(bin, command, stdout, stderr)
|
67
|
-
output = stdout.join
|
67
|
+
output = stdout.join + stderr.join
|
68
68
|
unless status.success?
|
69
69
|
if raise_on_failure
|
70
70
|
raise Informative, "#{full_command}\n\n#{output}"
|
@@ -80,19 +80,41 @@ module Pod
|
|
80
80
|
def self.popen3(bin, command, stdout, stderr)
|
81
81
|
require 'open3'
|
82
82
|
Open3.popen3(bin, *command) do |i, o, e, t|
|
83
|
-
|
84
|
-
|
83
|
+
reader(o, stdout)
|
84
|
+
reader(e, stderr)
|
85
85
|
i.close
|
86
|
+
|
86
87
|
status = t.value
|
87
88
|
|
88
89
|
o.flush
|
89
90
|
e.flush
|
90
|
-
sleep(0.
|
91
|
+
sleep(0.01)
|
91
92
|
|
92
93
|
status
|
93
94
|
end
|
94
95
|
end
|
95
96
|
|
97
|
+
def self.reader(input, output)
|
98
|
+
Thread.new do
|
99
|
+
buf = ''
|
100
|
+
begin
|
101
|
+
loop do
|
102
|
+
buf << input.readpartial(4096)
|
103
|
+
loop do
|
104
|
+
string, separator, buf = buf.partition(/[\r\n]/)
|
105
|
+
if separator.empty?
|
106
|
+
buf = string
|
107
|
+
break
|
108
|
+
end
|
109
|
+
output << (string << separator)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
rescue EOFError
|
113
|
+
output << (buf << $/) unless buf.empty?
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
96
118
|
#-------------------------------------------------------------------------#
|
97
119
|
|
98
120
|
# Helper class that allows to write to an {IO} instance taking into account
|
@@ -125,8 +147,7 @@ module Pod
|
|
125
147
|
#
|
126
148
|
def <<(value)
|
127
149
|
super
|
128
|
-
|
129
|
-
@io << "#{ indent }#{ value }" if @io
|
150
|
+
io << "#{ indent }#{ value }" if io
|
130
151
|
end
|
131
152
|
end
|
132
153
|
end
|
@@ -1,24 +1,15 @@
|
|
1
1
|
module Pod
|
2
2
|
module Generator
|
3
3
|
class EmbedFrameworksScript
|
4
|
-
# @return [
|
5
|
-
# used to locate the target-specific build products.
|
6
|
-
#
|
7
|
-
attr_reader :target_definition
|
8
|
-
|
9
|
-
# @return [Hash{String, Array{String}] Multiple lists of frameworks per
|
4
|
+
# @return [Hash{String => Array<String>}] Multiple lists of frameworks per
|
10
5
|
# configuration.
|
11
6
|
#
|
12
7
|
attr_reader :frameworks_by_config
|
13
8
|
|
14
|
-
# @param [
|
15
|
-
# @see #target_definition
|
16
|
-
#
|
17
|
-
# @param [Hash{String, Array{String}] frameworks_by_config
|
9
|
+
# @param [Hash{String => Array<String>] frameworks_by_config
|
18
10
|
# @see #frameworks_by_config
|
19
11
|
#
|
20
|
-
def initialize(
|
21
|
-
@target_definition = target_definition
|
12
|
+
def initialize(frameworks_by_config)
|
22
13
|
@frameworks_by_config = frameworks_by_config
|
23
14
|
end
|
24
15
|
|
@@ -54,7 +45,12 @@ module Pod
|
|
54
45
|
|
55
46
|
install_framework()
|
56
47
|
{
|
57
|
-
|
48
|
+
if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
|
49
|
+
local source="${BUILT_PRODUCTS_DIR}/$1"
|
50
|
+
else
|
51
|
+
local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
|
52
|
+
fi
|
53
|
+
|
58
54
|
local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
59
55
|
|
60
56
|
if [ -L "${source}" ]; then
|
@@ -63,33 +59,32 @@ module Pod
|
|
63
59
|
fi
|
64
60
|
|
65
61
|
# use filter instead of exclude so missing patterns dont' throw errors
|
66
|
-
echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers
|
67
|
-
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers
|
62
|
+
echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" ${source} ${destination}"
|
63
|
+
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
|
64
|
+
|
68
65
|
# Resign the code if required by the build settings to avoid unstable apps
|
69
|
-
|
70
|
-
code_sign "${destination}/$1"
|
71
|
-
fi
|
66
|
+
code_sign_if_enabled "${destination}/$(basename "$1")"
|
72
67
|
|
73
68
|
# Embed linked Swift runtime libraries
|
74
69
|
local basename
|
75
|
-
basename=$(
|
70
|
+
basename=$(basename $1 | sed -E s/\\\\..+// && exit ${PIPESTATUS[0]})
|
76
71
|
local swift_runtime_libs
|
77
|
-
swift_runtime_libs=$(xcrun otool -LX "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/$
|
72
|
+
swift_runtime_libs=$(xcrun otool -LX "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/${basename}.framework/${basename}" | grep --color=never @rpath/libswift | sed -E s/@rpath\\\\/\\(.+dylib\\).*/\\\\1/g | uniq -u && exit ${PIPESTATUS[0]})
|
78
73
|
for lib in $swift_runtime_libs; do
|
79
74
|
echo "rsync -auv \\"${SWIFT_STDLIB_PATH}/${lib}\\" \\"${destination}\\""
|
80
75
|
rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
|
81
|
-
|
82
|
-
code_sign "${destination}/${lib}"
|
83
|
-
fi
|
76
|
+
code_sign_if_enabled "${destination}/${lib}"
|
84
77
|
done
|
85
78
|
}
|
86
79
|
|
87
80
|
# Signs a framework with the provided identity
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
81
|
+
code_sign_if_enabled() {
|
82
|
+
if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
|
83
|
+
# Use the current code_sign_identitiy
|
84
|
+
echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
|
85
|
+
echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements $1"
|
86
|
+
/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1"
|
87
|
+
fi
|
93
88
|
}
|
94
89
|
|
95
90
|
eos
|
@@ -82,7 +82,11 @@ module Pod
|
|
82
82
|
# @return [String]
|
83
83
|
#
|
84
84
|
def generate_platform_import_header
|
85
|
-
|
85
|
+
case platform.name
|
86
|
+
when :ios then "#import <UIKit/UIKit.h>\n"
|
87
|
+
when :osx then "#import <Cocoa/Cocoa.h>\n"
|
88
|
+
else "#import <Foundation/Foundation.h>\n"
|
89
|
+
end
|
86
90
|
end
|
87
91
|
end
|
88
92
|
end
|
@@ -49,26 +49,62 @@ module Pod
|
|
49
49
|
# @return [Xcodeproj::Config]
|
50
50
|
#
|
51
51
|
def generate
|
52
|
-
pod_targets = target.pod_targets_for_build_configuration(@configuration_name)
|
53
52
|
config = {
|
54
53
|
'OTHER_LDFLAGS' => '$(inherited) ' + XCConfigHelper.default_ld_flags(target),
|
55
|
-
'OTHER_LIBTOOLFLAGS' => '$(OTHER_LDFLAGS)',
|
56
54
|
'PODS_ROOT' => target.relative_pods_root,
|
57
55
|
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
|
58
56
|
}
|
57
|
+
@xcconfig = Xcodeproj::Config.new(config)
|
58
|
+
|
59
|
+
@xcconfig.merge!(merged_user_target_xcconfigs)
|
60
|
+
|
61
|
+
generate_settings_to_import_pod_targets
|
62
|
+
|
63
|
+
XCConfigHelper.add_target_specific_settings(target, @xcconfig)
|
64
|
+
|
65
|
+
generate_vendored_build_settings
|
66
|
+
generate_other_ld_flags
|
67
|
+
|
68
|
+
# TODO: Need to decide how we are going to ensure settings like these
|
69
|
+
# are always excluded from the user's project.
|
70
|
+
#
|
71
|
+
# See https://github.com/CocoaPods/CocoaPods/issues/1216
|
72
|
+
@xcconfig.attributes.delete('USE_HEADERMAP')
|
73
|
+
|
74
|
+
generate_ld_runpath_search_paths if target.requires_frameworks?
|
75
|
+
|
76
|
+
@xcconfig
|
77
|
+
end
|
78
|
+
|
79
|
+
#---------------------------------------------------------------------#
|
80
|
+
|
81
|
+
private
|
59
82
|
|
83
|
+
# Add build settings, which ensure that the pod targets can be imported
|
84
|
+
# from the integrating target by all sort of imports, which are:
|
85
|
+
# - `#import <…>`
|
86
|
+
# - `#import "…"`
|
87
|
+
# - `@import …;` / `import …`
|
88
|
+
#
|
89
|
+
def generate_settings_to_import_pod_targets
|
60
90
|
if target.requires_frameworks?
|
61
91
|
# Framework headers are automatically discoverable by `#import <…>`.
|
62
|
-
header_search_paths = pod_targets.map
|
92
|
+
header_search_paths = target.pod_targets.map do |target|
|
93
|
+
if target.scoped?
|
94
|
+
"$PODS_FRAMEWORK_BUILD_PATH/#{target.product_name}/Headers"
|
95
|
+
else
|
96
|
+
"$CONFIGURATION_BUILD_DIR/#{target.product_name}/Headers"
|
97
|
+
end
|
98
|
+
end
|
63
99
|
build_settings = {
|
64
|
-
'PODS_FRAMEWORK_BUILD_PATH' => target.
|
100
|
+
'PODS_FRAMEWORK_BUILD_PATH' => target.scoped_configuration_build_dir,
|
65
101
|
# Make headers discoverable by `import "…"`
|
66
102
|
'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-iquote'),
|
67
103
|
}
|
68
|
-
if target.pod_targets.any?
|
104
|
+
if target.pod_targets.any? { |t| t.should_build? && t.scoped? }
|
69
105
|
build_settings['FRAMEWORK_SEARCH_PATHS'] = '$(inherited) "$PODS_FRAMEWORK_BUILD_PATH"'
|
70
106
|
end
|
71
|
-
|
107
|
+
@xcconfig.merge!(build_settings)
|
72
108
|
else
|
73
109
|
# Make headers discoverable from $PODS_ROOT/Headers directory
|
74
110
|
header_search_paths = target.sandbox.public_headers.search_paths(target.platform)
|
@@ -78,44 +114,50 @@ module Pod
|
|
78
114
|
# by `#import <…>`
|
79
115
|
'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-isystem'),
|
80
116
|
}
|
81
|
-
|
117
|
+
@xcconfig.merge!(build_settings)
|
82
118
|
end
|
119
|
+
end
|
83
120
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
121
|
+
# Add custom build settings and required build settings to link to
|
122
|
+
# vendored libraries and frameworks.
|
123
|
+
#
|
124
|
+
# @note
|
125
|
+
# In case of generated pod targets, which require frameworks, the
|
126
|
+
# vendored frameworks and libraries are already linked statically
|
127
|
+
# into the framework binary and must not be linked again to the
|
128
|
+
# user target.
|
129
|
+
#
|
130
|
+
def generate_vendored_build_settings
|
131
|
+
target.pod_targets.each do |pod_target|
|
89
132
|
unless pod_target.should_build? && pod_target.requires_frameworks?
|
90
|
-
# In case of generated pod targets, which require frameworks, the
|
91
|
-
# vendored frameworks and libraries are already linked statically
|
92
|
-
# into the framework binary and must not be linked again to the
|
93
|
-
# user target.
|
94
133
|
XCConfigHelper.add_settings_for_file_accessors_of_target(pod_target, @xcconfig)
|
95
134
|
end
|
135
|
+
end
|
136
|
+
end
|
96
137
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
138
|
+
# Add pod target to list of frameworks / libraries that are linked
|
139
|
+
# with the user’s project.
|
140
|
+
#
|
141
|
+
def generate_other_ld_flags
|
142
|
+
other_ld_flags = target.pod_targets.select(&:should_build?).map do |pod_target|
|
143
|
+
if pod_target.requires_frameworks?
|
144
|
+
%(-framework "#{pod_target.product_basename}")
|
145
|
+
else
|
146
|
+
%(-l "#{pod_target.product_basename}")
|
105
147
|
end
|
106
148
|
end
|
107
149
|
|
108
|
-
|
109
|
-
# are always excluded from the user's project.
|
110
|
-
#
|
111
|
-
# See https://github.com/CocoaPods/CocoaPods/issues/1216
|
112
|
-
@xcconfig.attributes.delete('USE_HEADERMAP')
|
113
|
-
|
114
|
-
generate_ld_runpath_search_paths if target.requires_frameworks?
|
115
|
-
|
116
|
-
@xcconfig
|
150
|
+
@xcconfig.merge!('OTHER_LDFLAGS' => other_ld_flags.join(' '))
|
117
151
|
end
|
118
152
|
|
153
|
+
# Ensure to add the default linker run path search paths as they could
|
154
|
+
# be not present due to being historically absent in the project or
|
155
|
+
# target template or just being removed by being superficial when
|
156
|
+
# linking third-party dependencies exclusively statically. This is not
|
157
|
+
# something a project needs specifically for the integration with
|
158
|
+
# CocoaPods, but makes sure that it is self-contained for the given
|
159
|
+
# constraints.
|
160
|
+
#
|
119
161
|
def generate_ld_runpath_search_paths
|
120
162
|
ld_runpath_search_paths = ['$(inherited)']
|
121
163
|
if target.platform.symbolic_name == :osx
|
@@ -135,6 +177,70 @@ module Pod
|
|
135
177
|
@xcconfig.merge!('LD_RUNPATH_SEARCH_PATHS' => ld_runpath_search_paths.join(' '))
|
136
178
|
end
|
137
179
|
|
180
|
+
private
|
181
|
+
|
182
|
+
#---------------------------------------------------------------------#
|
183
|
+
|
184
|
+
# !@group Private Helpers
|
185
|
+
|
186
|
+
# Returns the {PodTarget}s which are active for the current
|
187
|
+
# configuration name.
|
188
|
+
#
|
189
|
+
# @return [Array<PodTarget>]
|
190
|
+
#
|
191
|
+
def pod_targets
|
192
|
+
target.pod_targets_for_build_configuration(@configuration_name)
|
193
|
+
end
|
194
|
+
|
195
|
+
# Returns the +user_target_xcconfig+ for all pod targets grouped by keys
|
196
|
+
#
|
197
|
+
# @return [Hash{String,Hash{Target,String}]
|
198
|
+
#
|
199
|
+
def user_target_xcconfig_values_by_target_by_key
|
200
|
+
pod_targets.each_with_object({}) do |target, hash|
|
201
|
+
target.spec_consumers.each do |spec_consumer|
|
202
|
+
spec_consumer.user_target_xcconfig.each do |k, v|
|
203
|
+
(hash[k] ||= {})[target] = v
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# Merges the +user_target_xcconfig+ for all pod targets into the
|
210
|
+
# #xcconfig and warns on conflicting definitions.
|
211
|
+
#
|
212
|
+
# @return [Hash{String, String}]
|
213
|
+
#
|
214
|
+
def merged_user_target_xcconfigs
|
215
|
+
settings = user_target_xcconfig_values_by_target_by_key
|
216
|
+
settings.each_with_object({}) do |(key, values_by_target), xcconfig|
|
217
|
+
uniq_values = values_by_target.values.uniq
|
218
|
+
values_are_bools = uniq_values.all? { |v| v =~ /(yes|no)/i }
|
219
|
+
if values_are_bools
|
220
|
+
# Boolean build settings
|
221
|
+
if uniq_values.count > 1
|
222
|
+
UI.warn 'Can\'t merge user_target_xcconfig for pod targets: ' \
|
223
|
+
"#{values_by_target.keys.map(&:label)}. Boolean build "\
|
224
|
+
"setting #{key} has different values."
|
225
|
+
else
|
226
|
+
xcconfig[key] = uniq_values.first
|
227
|
+
end
|
228
|
+
elsif key =~ /S$/
|
229
|
+
# Plural build settings
|
230
|
+
xcconfig[key] = uniq_values.join(' ')
|
231
|
+
else
|
232
|
+
# Singular build settings
|
233
|
+
if uniq_values.count > 1
|
234
|
+
UI.warn 'Can\'t merge user_target_xcconfig for pod targets: ' \
|
235
|
+
"#{values_by_target.keys.map(&:label)}. Singular build "\
|
236
|
+
"setting #{key} has different values."
|
237
|
+
else
|
238
|
+
xcconfig[key] = uniq_values.first
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
138
244
|
#---------------------------------------------------------------------#
|
139
245
|
end
|
140
246
|
end
|