Skip to content

Commit b1aa2dd

Browse files
committed
Updated dependencies
1 parent be4ba57 commit b1aa2dd

File tree

534 files changed

+18137
-82
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

534 files changed

+18137
-82
lines changed

FileExtractor/README.md

+13-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ The information include the list of files containing the Swift source code that
1111
## Usage
1212

1313
```bash
14-
$ file-extractor -projectrootpath <path-to-xcode-project> -filesjson <path-to-output-file>
14+
$ file-extractor -projectrootpath <path-to-xcode-project> [-filesjson <path-to-output-file>] [-projectfile <path-to-xcodeproj>]
1515
```
1616

1717
where
@@ -20,6 +20,8 @@ where
2020

2121
`<path-to-output-file>` is a path to the file that the extraced data will be written to. If it's an optional parameter. If ommited, tool will print out to the standard output.
2222

23+
`<path-to-xcodeproj>` is a path to the Xcode project file. It's an optional parameter and should be provided only when the tool fails to automatically identify which project to parse.
24+
2325
## Data formats
2426

2527
The input data format is defined by the Xcode project file structure and best described [here](http://www.monobjc.net/xcode-project-file-format.html). The user should not need to ever work with it outside of Xcode.
@@ -42,13 +44,14 @@ The output data format is called `Files.json` and presented below:
4244
},
4345
"sourceFiles": [ <string> ],
4446
"layoutFiles": [ <string> ],
45-
"systemLinkedFrameworks": [<string>],
47+
"implicitlyLinkedFrameworks": [ <string> ],
4648
"explicitlyLinkedFrameworks": [
4749
{
4850
"name": <string>,
4951
"path": <string>
5052
}
51-
]
53+
],
54+
"frameworkSearchPaths": [ <string> ]
5255
}
5356
```
5457
`project` is an object that contains the path to the project root directory and path to the actual xcodeproj or xcworkspace file. This directory will be copied by the Renamer to provide place for writing the obfuscated Swift source files to.
@@ -61,10 +64,12 @@ The output data format is called `Files.json` and presented below:
6164

6265
`layoutFiles` is an array of paths to storyboard / xib files containing the layouts that the tool should obfuscate.
6366

64-
`systemLinkedFrameworks` contains the list of names of frameworks that are imported in the source code (with various form of Swift `import` statement), but not included in the Xcode project. Since Xcode autolinks the system frameworks by default (see `CLANG_MODULES_AUTOLINK` flag), these frameworks should be automatically found by the compiler, which uses the SDK path for this purpose. They are used to identify the module that the symbol is part of.
67+
`implicitlyLinkedFrameworks` contains the list of names of frameworks that are imported in the source code (with various form of Swift `import` statement), but not included in the Xcode project. There are two types of such frameworks. One is system frameworks. Since Xcode autolinks the system frameworks by default (see `CLANG_MODULES_AUTOLINK` flag), these frameworks should be automatically found by the compiler, which uses the SDK path for this purpose. Second one is frameworks with paths added to search paths, but not explicitely stated as dependencies. They are used to identify the module that the symbol is part of.
6568

6669
`explicitlyLinkedFrameworks` contains the list of framework objects with name and path. These are taken from the Xcode project, which must contain the names and paths to frameworks that are not automatically linked. They are required for the Swift compiler to perform the analysis and also used to identify which module is the symbol part of.
6770

71+
`frameworkSearchPaths` contains the list of paths to search for non-system frameworks. It's especially useful when working with Cocoapods projects, since they dont specify the framework dependencies explicitely, but set the paths.
72+
6873
Sample `Files.json` file might look like that:
6974

7075
```javascript
@@ -95,8 +100,11 @@ Sample `Files.json` file might look like that:
95100
"path":"/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.0.sdk/System/Library/Frameworks/"
96101
}
97102
],
98-
"systemLinkedFrameworks":[
103+
"implicitlyLinkedFrameworks":[
99104
"UIKit"
105+
],
106+
"frameworkSearchPaths": [
107+
"/Users/siejkowski/Polidea/SwiftObfuscator/TestProjects/Dropnote/Pods/Crashlytics/iOS"
100108
]
101109
}
102110
```

FileExtractor/lib/file-extractor/command.rb

+37-10
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ module FileExtractor
33
require 'claide'
44

55
require 'file-extractor/arguments_decorator'
6-
require 'file-extractor/xcodeproj_determiner'
76
require 'file-extractor/data_extractor'
7+
require 'file-extractor/dependency_builder'
8+
require 'file-extractor/xcodefiles_determiner'
9+
require 'file-extractor/xcworkspace_extractor'
810

911
class Command < CLAide::Command
1012

@@ -13,13 +15,17 @@ class Command < CLAide::Command
1315

1416
PROJECTROOTPATH_KEY = "projectrootpath"
1517
FILESJSON_KEY = "filesjson"
18+
PROJECTFILEPATH_KEY = "projectfile"
1619

1720
@file_extractor_options = [
1821
["-#{PROJECTROOTPATH_KEY}", "Path to Xcode project root folder. "\
1922
"It\'s the folder that contains both the Xcode project file (.xcodeproj or .xcworkspace) "\
2023
"and the source files."\
2124
"It\'s a required parameter."],
22-
["-#{FILESJSON_KEY}", "Path to output files.json. It\'s an optional parameter."]
25+
["-#{FILESJSON_KEY}", "Path to output files.json. It\'s an optional parameter."],
26+
["-#{PROJECTFILEPATH_KEY}", "is a path to the Xcode project file. "\
27+
"It\'s an optional parameter and should be provided only "\
28+
"when the tool fails to automatically identify which project to parse."]
2329
]
2430

2531
def self.options
@@ -31,7 +37,9 @@ def self.options
3137
CLAide::Argument.new("-#{PROJECTROOTPATH_KEY}", true),
3238
CLAide::Argument.new("PROJECTROOT", true),
3339
CLAide::Argument.new("-#{FILESJSON_KEY}", false),
34-
CLAide::Argument.new("FILESJSON", false)
40+
CLAide::Argument.new("FILESJSON", false),
41+
CLAide::Argument.new("-#{PROJECTFILEPATH_KEY}", false),
42+
CLAide::Argument.new("PROJECTFILE", false)
3543
]
3644

3745
def extract_option(argv, key)
@@ -46,6 +54,7 @@ def extract_option(argv, key)
4654
def initialize(argv)
4755
@project_root_path = extract_option(argv, PROJECTROOTPATH_KEY)
4856
@files_path = extract_option(argv, FILESJSON_KEY)
57+
@project_file_path = extract_option(argv, PROJECTFILEPATH_KEY)
4958
super
5059
end
5160

@@ -57,24 +66,42 @@ def self.run(argv = [])
5766
def run
5867
puts "Path to root:"
5968
puts @project_root_path
60-
project_paths = FileExtractor::XcodeprojDeterminer.find_xcode_files(@project_root_path)
61-
if project_paths.empty?
69+
xcodeprojs, xcworkspaces = FileExtractor::XcodefilesDeterminer.find_xcode_files(@project_root_path)
70+
projects, schemes = FileExtractor::XcworkspaceExtractor.extract_projects_and_dependency_schemes(xcworkspaces, xcodeprojs)
71+
if projects.empty?
6272
puts "\n\nNo Xcode project document found in the project root directory"
63-
elsif project_paths.count == 1
73+
elsif projects.count == 1
6474
puts "Path to Xcode project:"
65-
puts project_paths.first
75+
puts xcodeprojs.first
6676
puts "Path to files:"
6777
puts @files_path
6878

69-
json, output_string = FileExtractor::DataExtractor.extract_data(@project_root_path, project_paths.first, @files_path)
79+
json, output_string, build_dir = FileExtractor::DataExtractor.extract_data(@project_root_path, xcodeprojs.first, @files_path)
7080
puts "\nFound data:\n#{json}"
7181
puts "\n#{output_string}"
72-
else
82+
83+
FileExtractor::DependencyBuilder.build_dependencies(schemes, build_dir)
84+
elsif !@project_file_path.nil?
85+
puts "Path to Xcode project:"
86+
puts @project_file_path
87+
puts "Path to files:"
88+
puts @files_path
89+
90+
json, output_string, build_dir = FileExtractor::DataExtractor.extract_data(@project_root_path, xcodeprojs.first, @files_path)
91+
puts "\nFound data:\n#{json}"
92+
puts "\n#{output_string}"
93+
94+
if projects.include? @project_file_path
95+
FileExtractor::DependencyBuilder.build_dependencies(schemes, build_dir)
96+
end
97+
else
7398
puts "\n\nFound multiple possible Xcode project files:\n"
74-
project_paths.each do |path|
99+
projects.each do |path|
75100
puts path
76101
end
102+
puts "\nPlease specify which one to use with -#{PROJECTFILEPATH_KEY} flag\n"
77103
end
78104
end
105+
79106
end
80107
end

FileExtractor/lib/file-extractor/data_extractor.rb

+6-9
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,28 @@ module FileExtractor
33
require 'file-extractor/files_json_struct'
44
require 'file-extractor/xcodeproj_extractor'
55
require 'file-extractor/modules_extractor'
6-
require 'file-extractor/sdk_resolver'
76
require 'file-extractor/data_integrity_checker'
87

98
class DataExtractor
109

1110
def self.extract_data(root_path, project_path, files_path)
12-
data = extract_data_from_all_sources(root_path, project_path)
11+
data, build_dir = extract_data_from_all_sources(root_path, project_path)
1312
data_is_ok, error_message = FileExtractor::DataIntegrityChecker.verify_data_integrity(data)
1413
json = JSON.pretty_generate(data)
1514
if data_is_ok
16-
return json, write_json_to_file(json, files_path)
15+
return json, write_json_to_file(json, files_path), build_dir
1716
else
18-
return json, error_message
17+
return json, error_message, build_dir
1918
end
2019
end
2120

2221
private
2322

2423
def self.extract_data_from_all_sources(root_path, project_path)
2524
data_extractor = FileExtractor::XcodeprojExtractor.new(root_path, project_path)
26-
data = data_extractor.extract_data
27-
data.systemLinkedFrameworks = FileExtractor::ModulesExtractor.system_linked_frameworks(data)
28-
data.sdk.path = FileExtractor::SdkResolver.sdk_path(data)
29-
data.explicitlyLinkedFrameworks = FileExtractor::SdkResolver.update_frameworks_paths(data)
30-
data
25+
data, build_dir = data_extractor.extract_data_and_build_directory
26+
data.implicitlyLinkedFrameworks = FileExtractor::ModulesExtractor.system_linked_frameworks(data)
27+
return data, build_dir
3128
end
3229

3330
def self.write_json_to_file(json, files_path)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
module FileExtractor
2+
3+
require 'open3'
4+
5+
class DependencyBuilder
6+
7+
def self.build_dependencies(schemes, build_dir)
8+
schemes.each do |scheme|
9+
puts "\nBuilding dependencies using command:\n"
10+
build_dir = clean_build_directory(build_dir)
11+
clean_command = "xcodebuild -workspace \"#{scheme[:workspace]}\" -scheme \"#{scheme[:scheme]}\" -derivedDataPath \"#{build_dir}\" clean"
12+
build_command = "xcodebuild -workspace \"#{scheme[:workspace]}\" -scheme \"#{scheme[:scheme]}\" -derivedDataPath \"#{build_dir}\""
13+
puts clean_command
14+
puts build_command
15+
Open3.capture3(clean_command)
16+
stdout, stderr, status = Open3.capture3(build_command)
17+
if status.success?
18+
puts "\nBuilding dependencies finished successfully\n"
19+
else
20+
puts "\nError while building dependencies, here come the logs\n\n"
21+
puts "\nstdout:\n\n"
22+
puts stdout
23+
puts "\nstderr:\n\n"
24+
puts stderr
25+
end
26+
end
27+
end
28+
29+
def self.clean_build_directory(build_dir)
30+
# TODO: should we pass the configuration names from build settings here instead of "Debug" and "Release"?
31+
paths_to_remove = ["Build", "Products", "Debug", "Release"]
32+
dirs = build_dir.split(File::SEPARATOR)
33+
while dirs.last.start_with?(*paths_to_remove)
34+
dirs.pop
35+
end
36+
File.expand_path(dirs.join(File::SEPARATOR))
37+
end
38+
39+
end
40+
41+
end

FileExtractor/lib/file-extractor/files_json_struct.rb

+8-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@ def to_json(options = {})
2424
include StructSerialization
2525
end
2626

27-
FilesJson = Struct.new(:project, :module, :sdk, :sourceFiles, :layoutFiles, :explicitlyLinkedFrameworks, :systemLinkedFrameworks) do
27+
FilesJson = Struct.new(:project,
28+
:module,
29+
:sdk,
30+
:sourceFiles,
31+
:layoutFiles,
32+
:explicitlyLinkedFrameworks,
33+
:implicitlyLinkedFrameworks,
34+
:frameworkSearchPaths) do
2835
include StructSerialization
2936

3037
def to_h
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
module FileExtractor
2+
3+
require 'find'
4+
5+
class XcodefilesDeterminer
6+
7+
XCODE_PROJECT_FORMAT = ".xcodeproj"
8+
XCWORKSPACE_FORMAT = ".xcworkspace"
9+
XCODE_FILE_FORMATS = [XCODE_PROJECT_FORMAT, XCWORKSPACE_FORMAT]
10+
11+
def self.find_xcode_files(path)
12+
xcodeprojs = find_xcode_files_of_type(path, XCODE_PROJECT_FORMAT)
13+
xcworkspaces = find_xcode_files_of_type(path, XCWORKSPACE_FORMAT)
14+
return xcodeprojs, xcworkspaces
15+
end
16+
17+
private
18+
19+
def self.find_xcode_files_of_type(path, type)
20+
Find.find(path).select do |path|
21+
check_if_path_has_extension(path, type)
22+
end.each do |path|
23+
File.expand_path(path)
24+
end
25+
end
26+
27+
def self.check_if_path_has_extension(path, extension)
28+
extension == File.extname(path) && check_if_is_not_subfile(path)
29+
end
30+
31+
def self.check_if_is_not_subfile(file)
32+
XCODE_FILE_FORMATS.select do |extension|
33+
File.dirname(file).include?(extension)
34+
end.empty?
35+
end
36+
37+
end
38+
39+
end

FileExtractor/lib/file-extractor/xcodeproj_extractor.rb

+41-13
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,32 @@ def initialize(root_path, project_path)
1515
@main_build_settings = build_settings(@main_target)
1616
end
1717

18-
def extract_data
19-
FileExtractor::FilesJson.new(
18+
def extract_data_and_build_directory
19+
dir = @main_build_settings["BUILT_PRODUCTS_DIR"]
20+
return FileExtractor::FilesJson.new(
2021
FileExtractor::Project.new(@root_path, @project.path.to_s),
21-
FileExtractor::Module.new(module_name(@main_target), triple(@main_build_settings)),
22-
FileExtractor::Sdk.new(sdk(@main_target), nil),
22+
FileExtractor::Module.new(module_name(@main_build_settings), triple(@main_build_settings)),
23+
FileExtractor::Sdk.new(sdk_name(@main_build_settings), sdk_path(@main_build_settings)),
2324
source_files(@main_target),
2425
layout_files(@main_target),
25-
explicitly_linked_frameworks(@main_target),
26-
nil
27-
)
26+
update_frameworks_paths(explicitly_linked_frameworks(@main_target), @main_build_settings),
27+
nil,
28+
framework_search_paths(@main_build_settings)
29+
), dir
2830
end
2931

3032
private
3133

32-
def module_name(target)
33-
target.name
34+
def module_name(build_settings)
35+
build_settings["PRODUCT_MODULE_NAME"]
3436
end
3537

36-
def sdk(target)
37-
target.sdk
38+
def sdk_name(build_settings)
39+
build_settings["SDK_NAME"]
40+
end
41+
42+
def sdk_path(build_settings)
43+
build_settings["SDKROOT"]
3844
end
3945

4046
def source_files(target)
@@ -65,14 +71,36 @@ def filepaths(file_references, *extensions)
6571

6672
def explicitly_linked_frameworks(target)
6773
target.frameworks_build_phase.files.map do |framework|
68-
name = framework.file_ref.name
74+
name = framework.display_name
6975
path = framework.file_ref.real_path.to_s
7076
FileExtractor::ExplicitlyLinkedFramework.new(name.sub(".framework", ""), path.sub(name, ""))
7177
end
7278
end
7379

80+
def update_frameworks_paths(frameworks, build_settings)
81+
frameworks.map do |framework|
82+
framework.path = framework.path.sub("${SDKROOT}", build_settings["SDKROOT"])
83+
framework.path = framework.path.sub("${BUILT_PRODUCTS_DIR}", build_settings["BUILT_PRODUCTS_DIR"])
84+
framework
85+
end
86+
end
87+
88+
def framework_search_paths(build_settings)
89+
search_paths = build_settings["FRAMEWORK_SEARCH_PATHS"]
90+
framework_search_paths = []
91+
if !search_paths.nil?
92+
framework_search_paths = search_paths.split("\" ").map do |path_to_clean|
93+
path_to_clean.sub(/^\"/, '')
94+
end
95+
end
96+
framework_search_paths
97+
end
98+
7499
def triple(build_settings)
75-
architecture = build_settings["CURRENT_ARCH"]
100+
architecture = build_settings["PLATFORM_PREFERRED_ARCH"]
101+
if architecture.nil?
102+
architecture = build_settings["CURRENT_ARCH"]
103+
end
76104
sdk = case build_settings["PLATFORM_NAME"]
77105
when "iphoneos"
78106
build_settings["SDK_NAME"].gsub("iphoneos", "ios")

0 commit comments

Comments
 (0)