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
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
163 additions
and
94 deletions
+163
-94
user_project_integrator.rb
lib/cocoapods/installer/user_project_integrator.rb
+157
-75
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'
module
Pod
class
Installer
# The {UserProjectIntegrator} integrates the libraries generated by
# TargetDefinitions of the {Podfile} with their correspondent user project.
#
class
UserProjectIntegrator
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
)
@podfile
=
podfile
end
# Integrates the user projects associated with the {TargetDefinitions}
# with the Pods project and its products.
#
# @return [void]
#
def
integrate!
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!
)
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
@
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."
)
end
# @return [Pathname] the path of the Pods project.
#
def
pods_project_path
config
.
project_root
+
"Pods/Pods.xcodeproj"
end
# @return [Array<TargetIntegrator>] the target integrators for the non
# empty target definitions.
#
def
target_integrators
@target_integrators
||=
@podfile
.
target_definitions
.
values
.
map
do
|
definition
|
TargetIntegrator
.
new
(
definition
)
unless
definition
.
empty?
end
.
compact
end
# @return [Array<Pathname>] the paths of all the user projects referenced
# by the target definitons.
#
def
user_project_paths
@podfile
.
target_definitions
.
values
.
map
do
|
td
|
next
if
td
.
empty?
td
.
user_project
.
path
#|| raise(Informative, "Could not resolve the Xcode project in which the " \
# "`#{td.name}' target should be integrated.")
end
.
compact
td
.
user_project
.
path
end
.
compact
.
uniq
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
include
Pod
::
Config
::
Mixin
# @return [TargetDefinition]
# the target definition whose library should be integrated.
#
attr_reader
:target_definition
# @param [TargetDefinition] target_definition @see #target_definition
#
def
initialize
(
target_definition
)
@target_definition
=
target_definition
end
def
inspect
"#<
#{
self
.
class
}
for target `
#{
@target_definition
.
label
}
'>"
end
# Integrates the user project targets. Only the targets that do **not**
# already have the Pods library in their frameworks build phase are
# processed.
...
...
@@ -77,112 +109,162 @@ module Pod
#
def
integrate!
return
if
targets
.
empty?
UI
.
section
(
"Integrating `
#{
@target_definition
.
lib_name
}
' into
#{
'target'
.
pluralize
(
targets
.
size
)
}
"
\
"`
#{
targets
.
map
(
&
:name
).
to_sentence
}
' of Xcode project
#{
UI
.
path
user_project_path
}
."
)
do
message
=
"Integrating `
#{
target_definition
.
lib_name
}
' into "
\
"
#{
'target'
.
pluralize
(
targets
.
size
)
}
`
#{
targets
.
map
(
&
:name
).
to_sentence
}
' "
\
"of project
#{
UI
.
path
user_project_path
}
."
UI
.
section
(
message
)
do
add_xcconfig_base_configuration
add_pods_library
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
# @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 path doesn't exits.
#
# @return [Pathname] the path of the user project.
#
def
user_project_path
if
path
=
@target_definition
.
user_project
.
path
path
=
target_definition
.
user_project
.
path
unless
path
raise
Informative
,
"Could not automatically select an Xcode project.
\n
"
\
"Specify one in your Podfile like so:
\n\n
xcodeproj 'path/to/NAME.xcodeproj'"
end
unless
path
.
exist?
raise
Informative
,
"The Xcode project `
#{
path
}
' does not exist."
end
path
else
raise
Informative
,
"Could not automatically select an Xcode project.
\n
"
\
"Specify one in your Podfile like so:
\n\n
"
\
" xcodeproj 'path/to/XcodeProject'"
end
end
# @return [Xcodeproj::Project] Returns the project of the user.
# Returns a list of the targets from the project of {TargetDefinition}
# that needs to be integrated.
#
def
user_project
@user_project
||=
Xcodeproj
::
Project
.
new
(
user_project_path
)
end
# This returns a list of the targets from the user’s project to which
# this Pods static library should be linked. If no explicit target was
# 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
# have the Pods library in their frameworks build phase.
#
# @return [Array<PBXNativeTarget>] Returns the list of targets that
# the Pods lib should be linked with.
# @return [Array<PBXNativeTarget>]
# the list of targets that the Pods lib should be linked with.
#
def
targets
@targets
||=
begin
if
link_with
=
@target_definition
.
link_with
# Find explicitly linked targets.
user_project
.
targets
.
select
do
|
target
|
link_with
.
include?
target
.
name
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
]
unless
@targets
if
link_with
=
target_definition
.
link_with
targets
=
user_project
.
targets
.
select
{
|
t
|
link_with
.
include?
t
.
name
}
raise
Informative
,
"Unable to find a target named `
#{
link_with
.
to_sentence
}
` to link with target definition `
#{
target_definition
.
name
}
`"
if
targets
.
empty?
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
# 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
}
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
@targets
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
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
|
c
onfig_build_names_by_overriden_key
=
{}
c
heck_overridden_build_settings
(
target_definition
.
xcconfig
,
target
)
target
.
build_configurations
.
each
do
|
config
|
config_name
=
config
.
name
if
@target_definition
.
xcconfig
@target_definition
.
xcconfig
.
attributes
.
each
do
|
key
,
value
|
target_value
=
config
.
build_settings
[
key
]
if
target_value
&&
!
target_value
.
include?
(
'$(inherited)'
)
config_build_names_by_overriden_key
[
key
]
||=
[]
config_build_names_by_overriden_key
[
key
]
<<
config_name
config
.
base_configuration_reference
=
xcconfig_ref
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
config
_build_names_by_overriden_key
.
each
do
|
key
,
config_build
_names
|
name
=
"
#{
target
.
name
}
[
#{
config_
build_
names
.
join
(
' - '
)
}
]"
config
s_by_overridden_key
.
each
do
|
key
,
config
_names
|
name
=
"
#{
target
.
name
}
[
#{
config_names
.
join
(
' - '
)
}
]"
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
# 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
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
|
target
.
frameworks_build_phase
.
add_file_reference
(
pods_library
)
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
targets
.
each
do
|
target
|
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
def
inspect
"#<
#{
self
.
class
}
for target `
#{
target_definition
.
label
}
'>"
end
end
end
...
...
spec/functional/user_project_integrator_spec.rb
View file @
cc958fde
...
...
@@ -3,24 +3,13 @@ require File.expand_path('../../spec_helper', __FILE__)
describe
Pod
::
Installer
::
UserProjectIntegrator
do
extend
SpecHelper
::
TemporaryDirectory
def
integrate!
@integrator
=
Pod
::
Installer
::
UserProjectIntegrator
.
new
(
@podfile
)
@integrator
.
integrate!
@sample_project
=
Xcodeproj
::
Project
.
new
(
@sample_project_path
)
end
before
do
config
.
silent
=
true
@sample_project_path
=
SpecHelper
.
create_sample_app_copy_from_fixture
(
'SampleProject'
)
config
.
project_root
=
@sample_project_path
.
dirname
sample_project_path
=
@sample_project_path
sample_project_path
=
SpecHelper
.
create_sample_app_copy_from_fixture
(
'SampleProject'
)
config
.
project_root
=
sample_project_path
.
dirname
@podfile
=
Pod
::
Podfile
.
new
do
platform
:ios
xcodeproj
sample_project_path
,
'Test'
=>
:debug
link_with
'SampleProject'
# this is an app target!
pod
'JSONKit'
target
:test_runner
,
:exclusive
=>
true
do
...
...
@@ -28,12 +17,10 @@ describe Pod::Installer::UserProjectIntegrator do
pod
'Kiwi'
end
end
@sample_project
=
Xcodeproj
::
Project
.
new
(
@sample_project_path
)
end
before
do
integrate!
@sample_project_path
=
sample_project_path
@integrator
=
Pod
::
Installer
::
UserProjectIntegrator
.
new
(
@podfile
)
@integrator
.
integrate!
@sample_project
=
Xcodeproj
::
Project
.
new
(
sample_project_path
)
end
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