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
ce3b4a30
Commit
ce3b4a30
authored
Nov 06, 2013
by
Per Eckerdal
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for Xcode subprojects to podspecs
parent
fd0682e5
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
416 additions
and
7 deletions
+416
-7
installer.rb
lib/cocoapods/installer.rb
+32
-7
linked_dependencies_installer.rb
lib/cocoapods/installer/linked_dependencies_installer.rb
+191
-0
pod_source_installer.rb
lib/cocoapods/installer/pod_source_installer.rb
+6
-0
linked_dependencies_installer_spec.rb
spec/unit/installer/linked_dependencies_installer_spec.rb
+159
-0
pod_source_installer_spec.rb
spec/unit/installer/pod_source_installer_spec.rb
+8
-0
installer_spec.rb
spec/unit/installer_spec.rb
+20
-0
No files found.
lib/cocoapods/installer.rb
View file @
ce3b4a30
...
@@ -28,13 +28,14 @@ module Pod
...
@@ -28,13 +28,14 @@ module Pod
#
#
class
Installer
class
Installer
autoload
:Analyzer
,
'cocoapods/installer/analyzer'
autoload
:Analyzer
,
'cocoapods/installer/analyzer'
autoload
:FileReferencesInstaller
,
'cocoapods/installer/file_references_installer'
autoload
:FileReferencesInstaller
,
'cocoapods/installer/file_references_installer'
autoload
:PodSourceInstaller
,
'cocoapods/installer/pod_source_installer'
autoload
:PodSourceInstaller
,
'cocoapods/installer/pod_source_installer'
autoload
:TargetInstaller
,
'cocoapods/installer/target_installer'
autoload
:TargetInstaller
,
'cocoapods/installer/target_installer'
autoload
:AggregateTargetInstaller
,
'cocoapods/installer/target_installer/aggregate_target_installer'
autoload
:AggregateTargetInstaller
,
'cocoapods/installer/target_installer/aggregate_target_installer'
autoload
:PodTargetInstaller
,
'cocoapods/installer/target_installer/pod_target_installer'
autoload
:PodTargetInstaller
,
'cocoapods/installer/target_installer/pod_target_installer'
autoload
:UserProjectIntegrator
,
'cocoapods/installer/user_project_integrator'
autoload
:UserProjectIntegrator
,
'cocoapods/installer/user_project_integrator'
autoload
:LinkedDependenciesInstaller
,
'cocoapods/installer/linked_dependencies_installer'
include
Config
::
Mixin
include
Config
::
Mixin
...
@@ -112,6 +113,7 @@ module Pod
...
@@ -112,6 +113,7 @@ module Pod
install_file_references
install_file_references
install_libraries
install_libraries
set_target_dependencies
set_target_dependencies
link_linked_dependencies
link_aggregate_target
link_aggregate_target
run_post_install_hooks
run_post_install_hooks
write_pod_project
write_pod_project
...
@@ -392,6 +394,19 @@ module Pod
...
@@ -392,6 +394,19 @@ module Pod
end
end
end
end
# Adds the linked dependencies to the pod targets.
#
# @return [void]
#
def
link_linked_dependencies
pod_targets
.
each
do
|
pod_target
|
pod_root
=
pod_for_target
(
pod_target
).
root
installer
=
LinkedDependenciesInstaller
.
new
(
pods_project
,
pod_root
,
pod_target
)
installer
.
install!
end
end
# Writes the Pods project to the disk.
# Writes the Pods project to the disk.
#
#
# @return [void]
# @return [void]
...
@@ -648,6 +663,16 @@ module Pod
...
@@ -648,6 +663,16 @@ module Pod
analysis_result
.
sandbox_state
analysis_result
.
sandbox_state
end
end
# Finds the PodRepresentation object for a given Target.
#
# @param [Target] The target for which the representation should be found.
#
# @return [PodRepresentation] The pod for a given target.
#
def
pod_for_target
(
pod_target
)
pod_reps
.
find
{
|
pod_rep
|
pod_rep
.
name
==
pod_target
.
root_spec
.
name
}
end
#-------------------------------------------------------------------------#
#-------------------------------------------------------------------------#
end
end
...
...
lib/cocoapods/installer/linked_dependencies_installer.rb
0 → 100644
View file @
ce3b4a30
module
Pod
class
Installer
# This class is responsible for adding linked Xcode dependencies as
# subprojects in the correct groups and link the Xcode subproject
# library targets to the respective pod targets.
#
class
LinkedDependenciesInstaller
# @return [Project] The Pods project.
#
attr_reader
:pods_project
# @return [Pathname] The root path of the pod.
#
attr_reader
:pod_root
# @return [PodTarget] The pod target to process.
#
attr_reader
:pod_target
# @param [Project] pods_project @see pods_project
# @param [Pathname] pod_root @see pod_root
# @param [PodTarget] pod_target @see pod_target
#
def
initialize
(
pods_project
,
pod_root
,
pod_target
)
@pods_project
=
pods_project
@pod_root
=
pod_root
@pod_target
=
pod_target
end
# Installs the linked projects for a given pod target.
#
# @return [void]
#
def
install!
add_linked_projects
add_libraries_to_target
end
#-----------------------------------------------------------------------#
private
# @!group Installation Steps
# Add the Xcode projects that specs refer to as subprojects to the Pods
# Xcode project, in the appropriate groups.
#
# @return [void]
#
def
add_linked_projects
linked_project_specs
.
each
do
|
path
,
specs
|
specs
.
each
do
|
spec
|
group
=
pods_project
.
group_for_spec
(
spec
.
name
)
pods_project
.
add_file_reference
(
path
,
group
)
end
end
end
# Add the linked project targets to the pod target.
#
# @return [void]
#
def
add_libraries_to_target
pod_target
.
spec_consumers
.
each
do
|
consumer
|
xcodeproj
=
consumer
.
xcodeproj
next
unless
xcodeproj
[
'project'
]
linked_project
=
open_linked_xcode_project
(
xcodeproj
[
'project'
])
# Hide the schemes that would be autogenerated for the subproject's targets.
linked_project
.
recreate_user_schemes
(
false
)
link_targets_with_target
(
linked_project
,
xcodeproj
[
'library_targets'
]
||
[])
end
end
#-----------------------------------------------------------------------#
private
# @!group Private Helpers
# Open an Xcode project refered to by a specific pod. Raises an
# Informative error if it fails to open the Xcode project file.
#
# @param [String] The filename of the Xcode project, relative to
# the pod's root.
#
# @return [Xcodeproj::Project] The opened Xcode project file
#
def
open_linked_xcode_project
(
project_filename
)
linked_project
=
begin
Xcodeproj
::
Project
.
open
(
pod_root
+
project_filename
)
rescue
RuntimeError
=>
e
raise
Informative
,
"Could not open project
#{
project_filename
}
, specified in
#{
spec_file
}
:
#{
e
.
message
}
"
end
linked_project
end
# Link a number of targets within a subproject to a pod target.
#
# @param [Xcodeproj::Project] linked_project The Xcode subproject that
# contains the library targets.
# @param [Array<String>] library_target_names The names of the targets
# that should be linked against.
#
# @return [void]
#
def
link_targets_with_target
(
linked_project
,
library_target_names
)
library_target_names
.
each
do
|
library_target_name
|
library_target
=
find_named_native_target_in_project
(
linked_project
,
library_target_name
)
link_target_with_target
(
pod_target
.
target
,
library_target
)
end
end
# Make sure a target is linked with another target.
#
# @param [PBXNativeTarget] main_target The target that should link against
# another target.
# @param [PBXNativeTarget] library_target The target that should be linked
# against.
#
# @return [void]
#
def
link_target_with_target
(
main_target
,
library_target
)
frameworks
=
main_target
.
project
.
frameworks_group
lib_name
=
library_target
.
product_reference
.
path
.
sub
(
/^lib/
,
''
).
sub
(
/\.a$/
,
''
)
library_ref
=
frameworks
.
new_product_ref_for_target
(
lib_name
,
:static_library
)
main_target
.
add_dependency
(
library_target
)
main_target
.
frameworks_build_phase
.
add_file_reference
(
library_ref
)
end
# @return [Hash<Pathname => Array<Specification>>] A hash of the Xcode
# project paths to the specifications that refer to it.
#
def
linked_project_specs
specs_by_path
=
{}
pod_target
.
spec_consumers
.
each
do
|
consumer
|
proj
=
consumer
.
xcodeproj
next
unless
proj
.
present?
absolute_path
=
pod_root
+
proj
[
'project'
]
specs_by_path
[
absolute_path
]
||=
[]
specs_by_path
[
absolute_path
]
<<
consumer
.
spec
end
specs_by_path
end
# Finds the native target in an Xcode project with a given name.
# Raises an Informative error if the native target can't be found.
#
# @param [Project] project The project to search in
# @param [String] target_name The name of the target that we're
# looking for
#
# @return [PBXNativeTarget] The native target with the given name
#
def
find_named_native_target_in_project
(
project
,
target_name
)
target
=
project
.
targets
.
find
do
|
target
|
target_name
==
target
.
name
&&
target
.
isa
==
'PBXNativeTarget'
end
if
target
.
nil?
raise
Informative
,
"Could not find native target
#{
target_name
}
in project
#{
project
.
path
}
, specified in
#{
spec_file
}
"
end
target
end
# @return [String] the path where the pod target's specification is
# defined, if loaded from a file. (May be nil)
#
def
spec_file
pod_target
.
root_spec
.
defined_in_file
end
#-----------------------------------------------------------------------#
end
end
end
lib/cocoapods/installer/pod_source_installer.rb
View file @
ce3b4a30
...
@@ -231,6 +231,12 @@ module Pod
...
@@ -231,6 +231,12 @@ module Pod
# @return [Array<Strings>] The paths that can be deleted.
# @return [Array<Strings>] The paths that can be deleted.
#
#
def
clean_paths
def
clean_paths
has_xcodeproj
=
specs_by_platform
.
any?
do
|
platform
,
specs
|
specs
.
any?
{
|
spec
|
spec
.
consumer
(
platform
).
xcodeproj
.
present?
}
end
return
[]
if
has_xcodeproj
cached_used
=
used_files
cached_used
=
used_files
glob_options
=
File
::
FNM_DOTMATCH
|
File
::
FNM_CASEFOLD
glob_options
=
File
::
FNM_DOTMATCH
|
File
::
FNM_CASEFOLD
files
=
Pathname
.
glob
(
root
+
"**/*"
,
glob_options
).
map
(
&
:to_s
)
files
=
Pathname
.
glob
(
root
+
"**/*"
,
glob_options
).
map
(
&
:to_s
)
...
...
spec/unit/installer/linked_dependencies_installer_spec.rb
0 → 100644
View file @
ce3b4a30
require
File
.
expand_path
(
'../../../spec_helper'
,
__FILE__
)
module
Pod
describe
Installer
::
LinkedDependenciesInstaller
do
before
do
@target_definition
=
Podfile
::
TargetDefinition
.
new
(
'Pods'
,
nil
)
@file_accessor
=
fixture_file_accessor
(
'banana-lib/BananaLib.podspec'
)
@project
=
Project
.
new
(
config
.
sandbox
.
project_path
)
@project
.
add_pod_group
(
'BananaLib'
,
fixture
(
'banana-lib'
))
@pod_target
=
PodTarget
.
new
([
@file_accessor
.
spec
],
@target_definition
,
config
.
sandbox
)
@pod_target
.
file_accessors
=
[
@file_accessor
]
@pod_target
.
target
=
@project
.
new_target
(
:static_library
,
'Pod-BananaLib'
,
:ios
)
@installer
=
Installer
::
LinkedDependenciesInstaller
.
new
(
@project
,
@file_accessor
.
root
,
@pod_target
)
end
#-------------------------------------------------------------------------#
describe
"Installation"
do
describe
"#install!"
do
it
"adds libraries to target when installing"
do
@installer
.
expects
(
:add_libraries_to_target
)
@installer
.
stubs
(
:add_linked_projects
)
@installer
.
install!
end
it
"adds linked projects when installing"
do
@installer
.
expects
(
:add_linked_projects
)
@installer
.
stubs
(
:add_libraries_to_target
)
@installer
.
install!
end
end
it
"adds subproject libraries to targets"
do
spec
=
@file_accessor
.
spec
spec
.
xcodeproj
=
{
:project
=>
'../SampleProject/Sample Lib/Sample Lib.xcodeproj'
,
:library_targets
=>
[
'Sample Lib'
]
}
@pod_target
.
stubs
(
:spec_consumers
).
returns
([
spec
.
consumer
(
:ios
)
])
# Add the linked project to the pods project, otherwise add_libraries_to_target will fail
path
=
SpecHelper
::
Fixture
.
fixture
(
'SampleProject/Sample Lib/Sample Lib.xcodeproj'
)
@project
.
add_file_reference
(
path
,
@project
.
main_group
)
# Check that the schemes are hidden
Xcodeproj
::
Project
.
any_instance
.
expects
(
:recreate_user_schemes
).
with
(
false
)
@installer
.
send
(
:add_libraries_to_target
)
@pod_target
.
target
.
frameworks_build_phase
.
files_references
.
map
(
&
:path
).
should
.
include
(
'libSample Lib.a'
)
end
it
"adds linked projects"
do
path
=
SpecHelper
::
Fixture
.
fixture
(
'SampleProject/Sample Lib/Sample Lib.xcodeproj'
)
@installer
.
stubs
(
:linked_project_specs
).
returns
({
path
=>
[
@file_accessor
.
spec
]
})
@installer
.
send
(
:add_linked_projects
)
@project
.
reference_for_path
(
path
).
isa
.
should
.
be
==
'PBXFileReference'
end
end
#-------------------------------------------------------------------------#
describe
"Private Helpers"
do
it
"opens a linked xcode project by path"
do
@installer
.
send
(
:open_linked_xcode_project
,
"../SampleProject/SampleProject.xcodeproj"
).
path
.
basename
.
to_s
.
should
==
'SampleProject.xcodeproj'
end
it
"does not open a linked xcode project if the path is incorrect"
do
should
.
raise
Informative
do
@installer
.
send
(
:open_linked_xcode_project
,
"hello"
)
end
.
message
.
should
.
match
/Could not open project/
end
it
"links targets by name with the pod target"
do
lib_project
=
Xcodeproj
::
Project
.
open
(
SpecHelper
::
Fixture
.
fixture
(
'SampleProject/Sample Lib/Sample Lib.xcodeproj'
))
@project
.
add_file_reference
(
lib_project
.
path
,
@project
.
main_group
)
@installer
.
send
(
:link_targets_with_target
,
lib_project
,
[
'Sample Lib'
])
@pod_target
.
target
.
frameworks_build_phase
.
files_references
.
map
(
&
:path
).
should
.
include
(
'libSample Lib.a'
)
end
it
"links a target with another target"
do
sample_project
=
Xcodeproj
::
Project
.
open
(
SpecHelper
::
Fixture
.
fixture
(
'SampleProject/SampleProject.xcodeproj'
))
lib_project
=
Xcodeproj
::
Project
.
open
(
SpecHelper
::
Fixture
.
fixture
(
'SampleProject/Sample Lib/Sample Lib.xcodeproj'
))
sample_project
.
main_group
.
new_file
(
lib_project
.
path
)
app_target
=
@installer
.
send
(
:find_named_native_target_in_project
,
sample_project
,
'TestRunner'
)
lib_target
=
@installer
.
send
(
:find_named_native_target_in_project
,
lib_project
,
'Sample Lib'
)
# Change the name of the lib_target product in order to test that we link
# against that and not just the target name.
lib_target
.
product_reference
.
path
=
'libLib.a'
@installer
.
send
(
:link_target_with_target
,
app_target
,
lib_target
)
app_target
.
dependencies
.
map
(
&
:target
).
should
.
include
(
lib_target
)
app_target
.
frameworks_build_phase
.
files_references
.
map
(
&
:path
).
should
.
include
(
'libLib.a'
)
end
it
"finds that no specs specifies linked projects"
do
@pod_target
.
stubs
(
:spec_consumers
).
returns
([
@file_accessor
.
spec
.
consumer
(
:ios
)
])
@installer
.
send
(
:linked_project_specs
).
should
.
be
==
{}
end
it
"finds specs that specify linked projects"
do
spec
=
@file_accessor
.
spec
spec
.
xcodeproj
=
{
:project
=>
'hello'
}
@pod_target
.
stubs
(
:spec_consumers
).
returns
([
spec
.
consumer
(
:ios
)
])
@installer
.
send
(
:linked_project_specs
).
should
.
be
==
{
(
@file_accessor
.
root
+
'hello'
)
=>
[
spec
]
}
end
it
"finds a native target in a project"
do
project
=
Xcodeproj
::
Project
.
open
(
SpecHelper
::
Fixture
.
fixture
(
'SampleProject/SampleProject.xcodeproj'
))
@installer
.
send
(
:find_named_native_target_in_project
,
project
,
'SampleProject'
).
isa
.
should
==
'PBXNativeTarget'
end
it
"does not find a nonexistent native target in a project"
do
project
=
Xcodeproj
::
Project
.
open
(
SpecHelper
::
Fixture
.
fixture
(
'SampleProject/SampleProject.xcodeproj'
))
should
.
raise
Informative
do
@installer
.
send
(
:find_named_native_target_in_project
,
project
,
'SampleProject_nonexistent'
)
end
.
message
.
should
.
match
/Could not find native target/
end
it
"finds the spec file path correctly"
do
@installer
.
send
(
:spec_file
).
should
.
be
==
@file_accessor
.
spec
.
defined_in_file
end
end
#-------------------------------------------------------------------------#
end
end
spec/unit/installer/pod_source_installer_spec.rb
View file @
ce3b4a30
...
@@ -152,6 +152,14 @@ module Pod
...
@@ -152,6 +152,14 @@ module Pod
]
]
end
end
it
"returns no clean paths for specs that have linked projects"
do
spec
=
fixture_spec
(
'banana-lib/BananaLib.podspec'
)
spec
.
xcodeproj
=
{
:project
=>
'hello'
}
specs_by_platform
=
{
:ios
=>
[
spec
]
}
@installer
=
Installer
::
PodSourceInstaller
.
new
(
config
.
sandbox
,
specs_by_platform
)
@installer
.
send
(
:clean_paths
).
should
.
be
==
[]
end
it
"returns the used files"
do
it
"returns the used files"
do
@installer
.
send
(
:download_source
)
@installer
.
send
(
:download_source
)
paths
=
@installer
.
send
(
:used_files
)
paths
=
@installer
.
send
(
:used_files
)
...
...
spec/unit/installer_spec.rb
View file @
ce3b4a30
...
@@ -63,6 +63,7 @@ module Pod
...
@@ -63,6 +63,7 @@ module Pod
@installer
.
stubs
(
:install_file_references
)
@installer
.
stubs
(
:install_file_references
)
@installer
.
stubs
(
:install_libraries
)
@installer
.
stubs
(
:install_libraries
)
@installer
.
stubs
(
:link_aggregate_target
)
@installer
.
stubs
(
:link_aggregate_target
)
@installer
.
stubs
(
:link_linked_dependencies
)
@installer
.
stubs
(
:write_lockfiles
)
@installer
.
stubs
(
:write_lockfiles
)
@installer
.
stubs
(
:aggregate_targets
).
returns
([])
@installer
.
stubs
(
:aggregate_targets
).
returns
([])
@installer
.
unstub
(
:generate_pods_project
)
@installer
.
unstub
(
:generate_pods_project
)
...
@@ -515,6 +516,25 @@ module Pod
...
@@ -515,6 +516,25 @@ module Pod
end
end
#-------------------------------------------------------------------------#
describe
"Private helpers"
do
before
do
@installer
.
send
(
:analyze
)
@specs
=
@installer
.
pod_targets
.
map
(
&
:specs
).
flatten
@spec
=
@specs
.
find
{
|
spec
|
spec
&&
spec
.
name
==
'JSONKit'
}
end
it
"finds a pod from a given pod target"
do
pod_target
=
@installer
.
pod_targets
.
find
{
|
x
|
x
.
specs
.
first
.
root
.
name
==
'JSONKit'
}
@installer
.
send
(
:pod_for_target
,
pod_target
).
name
.
should
==
'JSONKit'
end
end
#-------------------------------------------------------------------------#
end
end
end
end
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