Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
C
cocoapods
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gengmeiios
cocoapods
Commits
cc958fde
Commit
cc958fde
authored
Oct 24, 2012
by
Fabio Pelosin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[UserProjectIntegrator] Clean up.
parent
2421ef03
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
170 additions
and
101 deletions
+170
-101
user_project_integrator.rb
lib/cocoapods/installer/user_project_integrator.rb
+164
-82
user_project_integrator_spec.rb
spec/functional/user_project_integrator_spec.rb
+6
-19
No files found.
lib/cocoapods/installer/user_project_integrator.rb
View file @
cc958fde
...
@@ -6,69 +6,101 @@ require 'active_support/core_ext/array/conversions'
...
@@ -6,69 +6,101 @@ require 'active_support/core_ext/array/conversions'
module
Pod
module
Pod
class
Installer
class
Installer
# The {UserProjectIntegrator} integrates the libraries generated by
# TargetDefinitions of the {Podfile} with their correspondent user project.
#
class
UserProjectIntegrator
class
UserProjectIntegrator
include
Pod
::
Config
::
Mixin
include
Pod
::
Config
::
Mixin
# @return [Podfile] the podfile that should be integrated with the user
# projects.
#
attr_reader
:podfile
# @param [Podfile] podfile @see #podfile.
#
def
initialize
(
podfile
)
def
initialize
(
podfile
)
@podfile
=
podfile
@podfile
=
podfile
end
end
# Integrates the user projects associated with the {TargetDefinitions}
# with the Pods project and its products.
#
# @return [void]
#
def
integrate!
def
integrate!
create_workspace!
create_workspace!
# Only need to write out the user's project if any of the target
# integrators actually did some work.
target_integrators
.
map
(
&
:integrate!
)
target_integrators
.
map
(
&
:integrate!
)
end
end
# creates the workspace containing the Pods project and the user projects
# should be saved.
#
# @return [void]
#
def
create_workspace!
workspace
=
Xcodeproj
::
Workspace
.
new_from_xcworkspace
(
workspace_path
)
[
pods_project_path
,
*
user_project_paths
].
each
do
|
project_path
|
project_path
=
project_path
.
relative_path_from
(
config
.
project_root
).
to_s
workspace
<<
project_path
unless
workspace
.
include?
(
project_path
)
end
workspace
.
save_as
(
workspace_path
)
UI
.
notice
"From now on use `
#{
workspace_path
.
basename
}
'."
unless
workspace_path
.
exist?
end
# @return [Pathname] the path where the workspace containing the Pods
# project and the user projects should be saved.
#
def
workspace_path
def
workspace_path
@
podfile
.
workspace
||
raise
(
Informative
,
"Could not automatically select an Xcode workspace. "
\
podfile
.
workspace
||
raise
(
Informative
,
"Could not automatically select an Xcode workspace. "
\
"Specify one in your Podfile."
)
"Specify one in your Podfile."
)
end
end
# @return [Pathname] the path of the Pods project.
#
def
pods_project_path
def
pods_project_path
config
.
project_root
+
"Pods/Pods.xcodeproj"
config
.
project_root
+
"Pods/Pods.xcodeproj"
end
end
# @return [Array<TargetIntegrator>] the target integrators for the non
# empty target definitions.
#
def
target_integrators
def
target_integrators
@target_integrators
||=
@podfile
.
target_definitions
.
values
.
map
do
|
definition
|
@target_integrators
||=
@podfile
.
target_definitions
.
values
.
map
do
|
definition
|
TargetIntegrator
.
new
(
definition
)
unless
definition
.
empty?
TargetIntegrator
.
new
(
definition
)
unless
definition
.
empty?
end
.
compact
end
.
compact
end
end
# @return [Array<Pathname>] the paths of all the user projects referenced
# by the target definitons.
#
def
user_project_paths
def
user_project_paths
@podfile
.
target_definitions
.
values
.
map
do
|
td
|
@podfile
.
target_definitions
.
values
.
map
do
|
td
|
next
if
td
.
empty?
next
if
td
.
empty?
td
.
user_project
.
path
#|| raise(Informative, "Could not resolve the Xcode project in which the " \
td
.
user_project
.
path
# "`#{td.name}' target should be integrated.")
end
.
compact
.
uniq
end
.
compact
end
end
def
create_workspace!
#-------------------------------------------------------------------------#
workspace
=
Xcodeproj
::
Workspace
.
new_from_xcworkspace
(
workspace_path
)
[
pods_project_path
,
*
user_project_paths
].
each
do
|
project_path
|
project_path
=
project_path
.
relative_path_from
(
config
.
project_root
).
to_s
workspace
<<
project_path
unless
workspace
.
include?
(
project_path
)
end
unless
workspace_path
.
exist?
||
config
.
silent?
UI
.
notice
"From now on use `
#{
workspace_path
.
basename
}
'."
end
workspace
.
save_as
(
workspace_path
)
end
# This class is responsible for integrating the library generated by a
# {TargetDefinition} with its destination project.
#
class
TargetIntegrator
class
TargetIntegrator
include
Pod
::
Config
::
Mixin
include
Pod
::
Config
::
Mixin
# @return [TargetDefinition]
# the target definition whose library should be integrated.
#
attr_reader
:target_definition
attr_reader
:target_definition
# @param [TargetDefinition] target_definition @see #target_definition
#
def
initialize
(
target_definition
)
def
initialize
(
target_definition
)
@target_definition
=
target_definition
@target_definition
=
target_definition
end
end
def
inspect
"#<
#{
self
.
class
}
for target `
#{
@target_definition
.
label
}
'>"
end
# Integrates the user project targets. Only the targets that do **not**
# Integrates the user project targets. Only the targets that do **not**
# already have the Pods library in their frameworks build phase are
# already have the Pods library in their frameworks build phase are
# processed.
# processed.
...
@@ -77,113 +109,163 @@ module Pod
...
@@ -77,113 +109,163 @@ module Pod
#
#
def
integrate!
def
integrate!
return
if
targets
.
empty?
return
if
targets
.
empty?
message
=
"Integrating `
#{
target_definition
.
lib_name
}
' into "
\
UI
.
section
(
"Integrating `
#{
@target_definition
.
lib_name
}
' into
#{
'target'
.
pluralize
(
targets
.
size
)
}
"
\
"
#{
'target'
.
pluralize
(
targets
.
size
)
}
`
#{
targets
.
map
(
&
:name
).
to_sentence
}
' "
\
"`
#{
targets
.
map
(
&
:name
).
to_sentence
}
' of Xcode project
#{
UI
.
path
user_project_path
}
."
)
do
"of project
#{
UI
.
path
user_project_path
}
."
UI
.
section
(
message
)
do
add_xcconfig_base_configuration
add_xcconfig_base_configuration
add_pods_library
add_pods_library
add_copy_resources_script_phase
add_copy_resources_script_phase
user_project
.
save_as
(
@
target_definition
.
user_project
.
path
)
user_project
.
save_as
(
target_definition
.
user_project
.
path
)
end
end
end
end
# @return [Pathname] the path of the user project.
# @return [Xcodeproj::Project]
# the project that will be integrated.
#
#
# @raises If the path doesn't exits.
def
user_project
@user_project
||=
Xcodeproj
::
Project
.
new
(
user_project_path
)
end
# Returns the path of the user project that the {TargetDefinition}
# should integrate.
#
#
# @raises If the project is implicit and there are multiple projects.
# @raises If the project is implicit and there are multiple projects.
#
#
# @raises If the path doesn't exits.
#
# @return [Pathname] the path of the user project.
#
def
user_project_path
def
user_project_path
if
path
=
@target_definition
.
user_project
.
path
path
=
target_definition
.
user_project
.
path
unless
path
.
exist?
raise
Informative
,
"The Xcode project `
#{
path
}
' does not exist."
unless
path
end
path
else
raise
Informative
,
"Could not automatically select an Xcode project.
\n
"
\
raise
Informative
,
"Could not automatically select an Xcode project.
\n
"
\
"Specify one in your Podfile like so:
\n\n
"
\
"Specify one in your Podfile like so:
\n\n
xcodeproj 'path/to/NAME.xcodeproj'"
" xcodeproj 'path/to/XcodeProject'"
end
end
end
# @return [Xcodeproj::Project] Returns the project of the user.
unless
path
.
exist?
#
raise
Informative
,
"The Xcode project `
#{
path
}
' does not exist."
def
user_project
end
@user_project
||=
Xcodeproj
::
Project
.
new
(
user_project_path
)
path
end
end
# This returns a list of the targets from the user’s project to which
# Returns a list of the targets from the project of {TargetDefinition}
# this Pods static library should be linked. If no explicit target was
# that needs to be integrated.
# specified, then the first encountered target is assumed.
#
# The method first looks if there is a target specified with the
# `link_with` option of the {TargetDefinition}. Otherwise it looks for
# the target that has the same name of the target definition.
# Finally if no target was found the first encountered target is
# returned (it is assumed to be the one to integrate in simple
# projects).
#
#
# In addition this will only return targets that do **not** already
# In addition this will only return targets that do **not** already
# have the Pods library in their frameworks build phase.
# have the Pods library in their frameworks build phase.
#
#
# @return [Array<PBXNativeTarget>] Returns the list of targets that
# @return [Array<PBXNativeTarget>]
# the Pods lib should be linked with.
# the list of targets that the Pods lib should be linked with.
#
def
targets
def
targets
@targets
||=
begin
unless
@targets
if
link_with
=
@target_definition
.
link_with
if
link_with
=
target_definition
.
link_with
# Find explicitly linked targets.
targets
=
user_project
.
targets
.
select
{
|
t
|
link_with
.
include?
t
.
name
}
user_project
.
targets
.
select
do
|
target
|
raise
Informative
,
"Unable to find a target named `
#{
link_with
.
to_sentence
}
` to link with target definition `
#{
target_definition
.
name
}
`"
if
targets
.
empty?
link_with
.
include?
target
.
name
elsif
target_definition
.
name
!=
:default
target
=
user_project
.
targets
.
find
{
|
t
|
t
.
name
==
target_definition
.
name
.
to_s
}
targets
=
[
target
]
raise
Informative
,
"Unable to find a target named `
#{
target_definition
.
name
.
to_s
}
`"
unless
target
else
targets
=
[
user_project
.
targets
.
first
]
raise
Informative
,
"Unable to find a target"
if
targets
.
empty?
end
@targets
=
targets
.
reject
do
|
target
|
target
.
frameworks_build_phase
.
files
.
any?
{
|
bf
|
bf
.
file_ref
.
name
==
target_definition
.
lib_name
}
end
end
elsif
@target_definition
.
name
!=
:default
# Find the target with the matching name.
target
=
user_project
.
targets
.
find
{
|
target
|
target
.
name
==
@target_definition
.
name
.
to_s
}
raise
Informative
,
"Unable to find a target named `
#{
@target_definition
.
name
.
to_s
}
'"
unless
target
[
target
]
else
# Default to the first, which in a simple project is probably an app target.
[
user_project
.
targets
.
first
]
end
.
reject
do
|
target
|
# Reject any target that already has this Pods library in one of its frameworks build phases
target
.
frameworks_build_phase
.
files
.
any?
{
|
build_file
|
build_file
.
file_ref
.
name
==
@target_definition
.
lib_name
}
end
end
end
@targets
end
end
#@!group Integration
# Adds the `xcconfig` configurations files generated for the current
# {TargetDefinition} to the build configurations of the targets that
# should be integrated.
#
# It also checks if any build setting of the build configurations
# overrides the `xcconfig` file and warns the user.
#
# TODO: If the xcconfig is already set don't override it and inform the
# user.
#
# @return [void]
#
def
add_xcconfig_base_configuration
def
add_xcconfig_base_configuration
xcconfig
=
user_project
.
new_file
(
@
target_definition
.
xcconfig_relative_path
)
xcconfig
_ref
=
user_project
.
new_file
(
target_definition
.
xcconfig_relative_path
)
targets
.
each
do
|
target
|
targets
.
each
do
|
target
|
c
onfig_build_names_by_overriden_key
=
{}
c
heck_overridden_build_settings
(
target_definition
.
xcconfig
,
target
)
target
.
build_configurations
.
each
do
|
config
|
target
.
build_configurations
.
each
do
|
config
|
config_name
=
config
.
name
config
.
base_configuration_reference
=
xcconfig_ref
if
@target_definition
.
xcconfig
end
@target_definition
.
xcconfig
.
attributes
.
each
do
|
key
,
value
|
end
target_value
=
config
.
build_settings
[
key
]
end
if
target_value
&&
!
target_value
.
include?
(
'$(inherited)'
)
config_build_names_by_overriden_key
[
key
]
||=
[]
config_build_names_by_overriden_key
[
key
]
<<
config_name
end
end
end
config
.
base_configuration_reference
=
xcconfig
# Informs the user about any build setting of the target which might
# override the given xcconfig file.
#
# @return [void]
#
def
check_overridden_build_settings
(
xcconfig
,
target
)
return
unless
xcconfig
configs_by_overridden_key
=
{}
target
.
build_configurations
.
each
do
|
config
|
xcconfig
.
attributes
.
keys
.
each
do
|
key
|
configs_by_overridden_key
[
key
]
||=
[]
target_value
=
config
.
build_settings
[
key
]
if
target_value
&&
!
target_value
.
include?
(
'$(inherited)'
)
configs_by_overridden_key
[
key
]
<<
config
.
name
end
end
end
config
_build_names_by_overriden_key
.
each
do
|
key
,
config_build
_names
|
config
s_by_overridden_key
.
each
do
|
key
,
config
_names
|
name
=
"
#{
target
.
name
}
[
#{
config_
build_
names
.
join
(
' - '
)
}
]"
name
=
"
#{
target
.
name
}
[
#{
config_names
.
join
(
' - '
)
}
]"
actions
=
[
"Use the `$(inherited)' flag, or"
,
"Remove the build settings from the target."
]
actions
=
[
"Use the `$(inherited)' flag, or"
,
"Remove the build settings from the target."
]
UI
.
warn
(
"The target `
#{
name
}
' overrides the `
#{
key
}
' build setting defined in `
#{
@
target_definition
.
xcconfig_relative_path
}
'."
,
actions
)
UI
.
warn
(
"The target `
#{
name
}
' overrides the `
#{
key
}
' build setting defined in `
#{
target_definition
.
xcconfig_relative_path
}
'."
,
actions
)
end
end
end
end
end
end
# Adds a file reference to the library of the {TargetDefinition} and
# adds it to the frameworks build phase of the targets.
#
# @return [void]
#
def
add_pods_library
def
add_pods_library
frameworks
=
user_project
.
frameworks_group
frameworks
=
user_project
.
frameworks_group
pods_library
=
frameworks
.
new_static_library
(
@
target_definition
.
label
)
pods_library
=
frameworks
.
new_static_library
(
target_definition
.
label
)
targets
.
each
do
|
target
|
targets
.
each
do
|
target
|
target
.
frameworks_build_phase
.
add_file_reference
(
pods_library
)
target
.
frameworks_build_phase
.
add_file_reference
(
pods_library
)
end
end
end
end
# Adds a shell script build phase responsible to copy the resources
# generated by the TargetDefinition to the bundle of the product of the
# targets.
#
# @return [void]
#
def
add_copy_resources_script_phase
def
add_copy_resources_script_phase
targets
.
each
do
|
target
|
targets
.
each
do
|
target
|
phase
=
target
.
new_shell_script_build_phase
(
'Copy Pods Resources'
)
phase
=
target
.
new_shell_script_build_phase
(
'Copy Pods Resources'
)
phase
.
shell_script
=
%{"#{
@
target_definition.copy_resources_script_relative_path}"\n}
phase
.
shell_script
=
%{"#{target_definition.copy_resources_script_relative_path}"\n}
end
end
end
end
def
inspect
"#<
#{
self
.
class
}
for target `
#{
target_definition
.
label
}
'>"
end
end
end
end
end
end
end
...
...
spec/functional/user_project_integrator_spec.rb
View file @
cc958fde
...
@@ -3,24 +3,13 @@ require File.expand_path('../../spec_helper', __FILE__)
...
@@ -3,24 +3,13 @@ require File.expand_path('../../spec_helper', __FILE__)
describe
Pod
::
Installer
::
UserProjectIntegrator
do
describe
Pod
::
Installer
::
UserProjectIntegrator
do
extend
SpecHelper
::
TemporaryDirectory
extend
SpecHelper
::
TemporaryDirectory
def
integrate!
@integrator
=
Pod
::
Installer
::
UserProjectIntegrator
.
new
(
@podfile
)
@integrator
.
integrate!
@sample_project
=
Xcodeproj
::
Project
.
new
(
@sample_project_path
)
end
before
do
before
do
config
.
silent
=
true
sample_project_path
=
SpecHelper
.
create_sample_app_copy_from_fixture
(
'SampleProject'
)
@sample_project_path
=
SpecHelper
.
create_sample_app_copy_from_fixture
(
'SampleProject'
)
config
.
project_root
=
sample_project_path
.
dirname
config
.
project_root
=
@sample_project_path
.
dirname
sample_project_path
=
@sample_project_path
@podfile
=
Pod
::
Podfile
.
new
do
@podfile
=
Pod
::
Podfile
.
new
do
platform
:ios
platform
:ios
xcodeproj
sample_project_path
,
'Test'
=>
:debug
xcodeproj
sample_project_path
,
'Test'
=>
:debug
link_with
'SampleProject'
# this is an app target!
link_with
'SampleProject'
# this is an app target!
pod
'JSONKit'
pod
'JSONKit'
target
:test_runner
,
:exclusive
=>
true
do
target
:test_runner
,
:exclusive
=>
true
do
...
@@ -28,12 +17,10 @@ describe Pod::Installer::UserProjectIntegrator do
...
@@ -28,12 +17,10 @@ describe Pod::Installer::UserProjectIntegrator do
pod
'Kiwi'
pod
'Kiwi'
end
end
end
end
@sample_project_path
=
sample_project_path
@sample_project
=
Xcodeproj
::
Project
.
new
(
@sample_project_path
)
@integrator
=
Pod
::
Installer
::
UserProjectIntegrator
.
new
(
@podfile
)
end
@integrator
.
integrate!
@sample_project
=
Xcodeproj
::
Project
.
new
(
sample_project_path
)
before
do
integrate!
end
end
it
'adds references to the Pods static libraries to the Frameworks group'
do
it
'adds references to the Pods static libraries to the Frameworks group'
do
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment