framework-generate 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +32 -0
- data/bin/framework-generate +5 -0
- data/lib/framework-generate/copy-carthage-frameworks.sh +24 -0
- data/lib/framework-generate/language.rb +16 -0
- data/lib/framework-generate/platform.rb +66 -0
- data/lib/framework-generate/project.rb +174 -0
- data/lib/framework-generate/script.rb +17 -0
- data/lib/framework-generate/target.rb +243 -0
- data/lib/framework-generate.rb +24 -0
- metadata +75 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b6a1985258384b624b703aac6457212dcf99228a
|
4
|
+
data.tar.gz: 12eb8e3deaa3ab2fb726fa71762624581bfebb31
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f8b2d24cedfa67541e1ab606fa703e35eeb38c53e37d81d6994c178bf10246092896f1f390a9e8a837abad7b476c550c0959059d250a3dd33eebbc577e6ad53a
|
7
|
+
data.tar.gz: 2d39715193e553131c6c40262f5b2152ae3a6f079b9d0f8e4c43feb13ddd77f435fa2169be7bb6528d62c21b72d0c6da89d8fe13cbe2fbcc66c8b3c98bf96abb
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017 Pierre-Marc Airoldi
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# framework-generate
|
2
|
+
Simple tool to help generate a [multiplatform, single-scheme Xcode project](http://promisekit.org/news/2016/08/Multiplatform-Single-Scheme-Xcode-Projects/).
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line to your Gemfile:
|
7
|
+
|
8
|
+
```rb
|
9
|
+
gem 'framework-generate'
|
10
|
+
```
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
Once installed you can run the generate command from the command line as follows
|
15
|
+
|
16
|
+
```bash
|
17
|
+
framework-generate
|
18
|
+
```
|
19
|
+
|
20
|
+
`framework-generate` will look for a `FrameworkSpec` file in the current folder to generate your Xcode project. An example of a `FrameworkSpec` can be found in the [`docs`](docs/FrameworkSpec) folder of this repoisitory.
|
21
|
+
|
22
|
+
To view the full `FrameworkSpec` documentation see the [`docs`](docs/FrameworkSpec.md) folder.
|
23
|
+
|
24
|
+
## Todo
|
25
|
+
|
26
|
+
- [X] Add documentation
|
27
|
+
- [ ] Add tests
|
28
|
+
- [ ] Release 1.0
|
29
|
+
|
30
|
+
## License
|
31
|
+
|
32
|
+
This project is licensed under the terms of the MIT license. See the [LICENSE](LICENSE) file.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
case "$PLATFORM_NAME" in
|
4
|
+
macosx) plat=Mac;;
|
5
|
+
iphone*) plat=iOS;;
|
6
|
+
watch*) plat=watchOS;;
|
7
|
+
appletv*) plat=tvOS;;
|
8
|
+
*) echo "error: Unknown PLATFORM_NAME: $PLATFORM_NAME"; exit 1;;
|
9
|
+
esac
|
10
|
+
|
11
|
+
for (( n = 0; n < SCRIPT_INPUT_FILE_COUNT; n++ )); do
|
12
|
+
VAR=SCRIPT_INPUT_FILE_$n
|
13
|
+
framework=$(basename "${!VAR}")
|
14
|
+
export SCRIPT_INPUT_FILE_$n="$SRCROOT"/Carthage/Build/$plat/"$framework"
|
15
|
+
done
|
16
|
+
|
17
|
+
/usr/local/bin/carthage copy-frameworks || exit
|
18
|
+
|
19
|
+
for (( n = 0; n < SCRIPT_INPUT_FILE_COUNT; n++ )); do
|
20
|
+
VAR=SCRIPT_INPUT_FILE_$n
|
21
|
+
source=${!VAR}.dSYM
|
22
|
+
dest=${BUILT_PRODUCTS_DIR}/$(basename "$source")
|
23
|
+
ditto "$source" "$dest" || exit
|
24
|
+
done
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module FrameworkGenerate
|
2
|
+
class Language
|
3
|
+
attr_accessor :type, :version
|
4
|
+
|
5
|
+
def initialize(type = nil, version = nil)
|
6
|
+
@type = type
|
7
|
+
@version = version
|
8
|
+
|
9
|
+
yield(self) if block_given?
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
"Language<#{type}, #{version}>"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module FrameworkGenerate
|
2
|
+
class Platform
|
3
|
+
attr_accessor :type, :minimum_version, :search_paths
|
4
|
+
|
5
|
+
def initialize(type = nil, minimum_version = nil, search_paths = nil)
|
6
|
+
@type = type
|
7
|
+
@minimum_version = minimum_version
|
8
|
+
@search_paths = search_paths == nil ? default_search_paths : search_paths
|
9
|
+
|
10
|
+
yield(self) if block_given?
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
"Platform<#{type}, #{minimum_version}, #{search_paths}>"
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.supported_platforms(platforms, is_test_target = false)
|
18
|
+
platforms
|
19
|
+
.reject { |platform| is_test_target && platform.type == :watchos }
|
20
|
+
.map { |platform| platform.raw_values }
|
21
|
+
.join(' ')
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.find_platform(platforms, type)
|
25
|
+
platforms.find { |platform| platform.type == type }
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.deployment_target(platforms, type)
|
29
|
+
find_platform(platforms, type).minimum_version
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.search_paths(platforms, type)
|
33
|
+
find_platform(platforms, type).search_paths
|
34
|
+
end
|
35
|
+
|
36
|
+
def raw_values
|
37
|
+
case @type
|
38
|
+
when :macos
|
39
|
+
'macosx'
|
40
|
+
when :ios
|
41
|
+
'iphoneos iphonesimulator'
|
42
|
+
when :tvos
|
43
|
+
'appletvos appletvsimulator'
|
44
|
+
when :watchos
|
45
|
+
'watchos watchsimulator'
|
46
|
+
else
|
47
|
+
abort 'platform not supported!'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def default_search_paths
|
52
|
+
case @type
|
53
|
+
when :macos
|
54
|
+
'$(SRCROOT)/Carthage/Build/Mac/ $(inherited)'
|
55
|
+
when :ios
|
56
|
+
'$(SRCROOT)/Carthage/Build/iOS/ $(inherited)'
|
57
|
+
when :tvos
|
58
|
+
'$(SRCROOT)/Carthage/Build/tvOS/ $(inherited)'
|
59
|
+
when :watchos
|
60
|
+
'$(SRCROOT)/Carthage/Build/watchOS/ $(inherited)'
|
61
|
+
else
|
62
|
+
abort 'platform not supported!'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'xcodeproj'
|
2
|
+
|
3
|
+
module FrameworkGenerate
|
4
|
+
class Project
|
5
|
+
attr_accessor :name, :platforms, :language, :targets
|
6
|
+
|
7
|
+
def initialize(name = nil, platforms = nil, language = nil, targets = nil)
|
8
|
+
@name = name
|
9
|
+
@platforms = platforms
|
10
|
+
@language = language
|
11
|
+
@targets = targets
|
12
|
+
|
13
|
+
yield(self) if block_given?
|
14
|
+
end
|
15
|
+
|
16
|
+
def project
|
17
|
+
yield(self) if block_given?
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"Project<#{name}, #{platforms}, #{language}, #{targets}>"
|
23
|
+
end
|
24
|
+
|
25
|
+
# DSL
|
26
|
+
def new_target(&block)
|
27
|
+
Target.new do |target|
|
28
|
+
block.call(target)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def new_platform(&block)
|
33
|
+
Platform.new do |platform|
|
34
|
+
block.call(platform)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def new_language(&block)
|
39
|
+
Language.new do |language|
|
40
|
+
block.call(language)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def new_script(&block)
|
45
|
+
Script.new do |script|
|
46
|
+
block.call(script)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# sugar
|
51
|
+
def macos(version, search_paths = nil)
|
52
|
+
Platform.new(:macos, version, search_paths)
|
53
|
+
end
|
54
|
+
|
55
|
+
def ios(version, search_paths = nil)
|
56
|
+
Platform.new(:ios, version, search_paths)
|
57
|
+
end
|
58
|
+
|
59
|
+
def tvos(version, search_paths = nil)
|
60
|
+
Platform.new(:tvos, version, search_paths)
|
61
|
+
end
|
62
|
+
|
63
|
+
def watchos(version, search_paths = nil)
|
64
|
+
Platform.new(:watchos, version, search_paths)
|
65
|
+
end
|
66
|
+
|
67
|
+
def swift(version)
|
68
|
+
Language.new(:swift, version)
|
69
|
+
end
|
70
|
+
|
71
|
+
def objc
|
72
|
+
Language.new(:objc, nil)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Interface
|
76
|
+
def project_path
|
77
|
+
if File.extname(@name) == '.xcodeproj'
|
78
|
+
return @name
|
79
|
+
end
|
80
|
+
|
81
|
+
"#{@name}.xcodeproj"
|
82
|
+
end
|
83
|
+
|
84
|
+
def general_build_settings(settings)
|
85
|
+
settings['SDKROOT'] = 'macosx'
|
86
|
+
settings['SUPPORTED_PLATFORMS'] = FrameworkGenerate::Platform::supported_platforms(@platforms)
|
87
|
+
settings['TARGETED_DEVICE_FAMILY'] = '1,2,3,4'
|
88
|
+
settings['MACOSX_DEPLOYMENT_TARGET'] = FrameworkGenerate::Platform::deployment_target(@platforms, :macos)
|
89
|
+
settings['IPHONEOS_DEPLOYMENT_TARGET'] = FrameworkGenerate::Platform::deployment_target(@platforms, :ios)
|
90
|
+
settings['TVOS_DEPLOYMENT_TARGET'] = FrameworkGenerate::Platform::deployment_target(@platforms, :tvos)
|
91
|
+
settings['WATCHOS_DEPLOYMENT_TARGET'] = FrameworkGenerate::Platform::deployment_target(@platforms, :watchos)
|
92
|
+
settings['CODE_SIGN_IDENTITY'] = ''
|
93
|
+
settings['COMBINE_HIDPI_IMAGES'] = 'YES'
|
94
|
+
settings['FRAMEWORK_SEARCH_PATHS[sdk=macosx*]'] = FrameworkGenerate::Platform::search_paths(@platforms, :macos)
|
95
|
+
settings['FRAMEWORK_SEARCH_PATHS[sdk=iphone*]'] = FrameworkGenerate::Platform::search_paths(@platforms, :ios)
|
96
|
+
settings['FRAMEWORK_SEARCH_PATHS[sdk=appletv*]'] = FrameworkGenerate::Platform::search_paths(@platforms, :tvos)
|
97
|
+
settings['FRAMEWORK_SEARCH_PATHS[sdk=watch*]'] = FrameworkGenerate::Platform::search_paths(@platforms, :watchos)
|
98
|
+
settings['SWIFT_VERSION'] = @language.version
|
99
|
+
settings['SWIFT_OPTIMIZATION_LEVEL'] = '-Owholemodule'
|
100
|
+
settings['CLANG_WARN_INFINITE_RECURSION'] = 'YES'
|
101
|
+
settings['CLANG_WARN_SUSPICIOUS_MOVE'] = 'YES'
|
102
|
+
settings['ENABLE_STRICT_OBJC_MSGSEND'] = 'YES'
|
103
|
+
settings['GCC_NO_COMMON_BLOCKS'] = 'YES'
|
104
|
+
|
105
|
+
settings
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_build_settings(settings)
|
109
|
+
settings['SUPPORTED_PLATFORMS'] = FrameworkGenerate::Platform::supported_platforms(@platforms, true)
|
110
|
+
|
111
|
+
settings['LD_RUNPATH_SEARCH_PATHS'] = '$(inherited) @executable_path/Frameworks @loader_path/Frameworks'
|
112
|
+
settings['LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]'] = '$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks'
|
113
|
+
|
114
|
+
settings
|
115
|
+
end
|
116
|
+
|
117
|
+
def generate
|
118
|
+
|
119
|
+
project = Xcodeproj::Project.new(project_path)
|
120
|
+
|
121
|
+
schemes_dir = Xcodeproj::XCScheme.user_data_dir(project.path)
|
122
|
+
FileUtils.rm_rf(schemes_dir)
|
123
|
+
FileUtils.mkdir_p(schemes_dir)
|
124
|
+
|
125
|
+
xcschememanagement = {}
|
126
|
+
xcschememanagement['SchemeUserState'] = {}
|
127
|
+
xcschememanagement['SuppressBuildableAutocreation'] = {}
|
128
|
+
|
129
|
+
project.build_configurations.each do |configuration|
|
130
|
+
general_build_settings(configuration.build_settings)
|
131
|
+
end
|
132
|
+
|
133
|
+
@targets.each do |target|
|
134
|
+
|
135
|
+
scheme = Xcodeproj::XCScheme.new
|
136
|
+
|
137
|
+
created_target = target.create(project, language)
|
138
|
+
|
139
|
+
scheme.add_build_target(created_target)
|
140
|
+
|
141
|
+
if created_target.test_target_type?
|
142
|
+
scheme.add_test_target(created_target)
|
143
|
+
end
|
144
|
+
|
145
|
+
if target.test_target != nil
|
146
|
+
created_test_target = target.test_target.create(project, language)
|
147
|
+
created_test_target.add_dependency(created_target)
|
148
|
+
|
149
|
+
scheme.add_test_target(created_test_target)
|
150
|
+
end
|
151
|
+
|
152
|
+
scheme.save_as(project.path, target.name, true)
|
153
|
+
xcschememanagement['SchemeUserState']["#{target.name}.xcscheme"] = {}
|
154
|
+
xcschememanagement['SchemeUserState']["#{target.name}.xcscheme"]['isShown'] = true
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
project.native_targets.each do |target|
|
159
|
+
next unless target.test_target_type?
|
160
|
+
target.build_configurations.each do |configuration|
|
161
|
+
test_build_settings(configuration.build_settings)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
xcschememanagement_path = schemes_dir + 'xcschememanagement.plist'
|
166
|
+
Xcodeproj::Plist.write_to_path(xcschememanagement, xcschememanagement_path)
|
167
|
+
|
168
|
+
project.save
|
169
|
+
|
170
|
+
puts "Successfully generated #{project_path}"
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module FrameworkGenerate
|
2
|
+
class Script
|
3
|
+
attr_accessor :name, :script, :inputs
|
4
|
+
|
5
|
+
def initialize(name = nil, script = nil, inputs = nil)
|
6
|
+
@name = name
|
7
|
+
@script = script
|
8
|
+
@inputs = inputs
|
9
|
+
|
10
|
+
yield(self) if block_given?
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
"Script<#{name}, #{script}, #{inputs}>"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
require 'xcodeproj'
|
2
|
+
|
3
|
+
module FrameworkGenerate
|
4
|
+
class Target
|
5
|
+
attr_accessor :name, :info_plist, :bundle_id, :header, :include_files, :exclude_files, :resource_files, :dependencies, :type, :pre_build_scripts, :post_build_scripts, :test_target, :is_safe_for_extensions
|
6
|
+
|
7
|
+
def initialize(name = nil, info_plist = nil, bundle_id = nil, header = nil, include_files = nil, exclude_files = nil, resource_files = nil, dependencies = nil, type = :framework, pre_build_scripts = nil, post_build_scripts = nil, test_target = nil, is_safe_for_extensions = false)
|
8
|
+
@name = name
|
9
|
+
@info_plist = info_plist
|
10
|
+
@bundle_id = bundle_id
|
11
|
+
@header = header
|
12
|
+
@include_files = include_files
|
13
|
+
@exclude_files = exclude_files
|
14
|
+
@resource_files = resource_files
|
15
|
+
@dependencies = dependencies
|
16
|
+
@type = type
|
17
|
+
@pre_build_scripts = pre_build_scripts
|
18
|
+
@post_build_scripts = post_build_scripts
|
19
|
+
@test_target = test_target
|
20
|
+
@is_safe_for_extensions = is_safe_for_extensions
|
21
|
+
|
22
|
+
yield(self) if block_given?
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
"Target<#{name}, #{info_plist}, #{bundle_id}, #{header}, #{include_files}, #{exclude_files}, #{dependencies}, #{type}, #{test_target}, #{is_safe_for_extensions}>"
|
27
|
+
end
|
28
|
+
|
29
|
+
def target_build_settings(settings)
|
30
|
+
settings.delete('CODE_SIGN_IDENTITY')
|
31
|
+
|
32
|
+
settings['INFOPLIST_FILE'] = @info_plist
|
33
|
+
settings['PRODUCT_BUNDLE_IDENTIFIER'] = @bundle_id
|
34
|
+
settings['APPLICATION_EXTENSION_API_ONLY'] = @is_safe_for_extensions ? 'YES' : 'NO';
|
35
|
+
|
36
|
+
settings
|
37
|
+
end
|
38
|
+
|
39
|
+
def find_group(project, path)
|
40
|
+
folder_path = File.dirname(path)
|
41
|
+
project.main_group.find_subpath(folder_path, true)
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_framework_header(project, target)
|
45
|
+
return unless @header != nil
|
46
|
+
header_path = @header
|
47
|
+
header_file_group = find_group(project, header_path)
|
48
|
+
header_file = header_file_group.new_reference(header_path)
|
49
|
+
header_build_file = target.headers_build_phase.add_file_reference(header_file, true)
|
50
|
+
header_build_file.settings ||= {}
|
51
|
+
header_build_file.settings['ATTRIBUTES'] = ['Public']
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_info_plist(project)
|
55
|
+
info_plist_path = @info_plist
|
56
|
+
info_plist_group = find_group(project, info_plist_path)
|
57
|
+
has_info_plist = info_plist_group.find_file_by_path(info_plist_path)
|
58
|
+
|
59
|
+
info_plist_group.new_reference(@info_plist) unless has_info_plist
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_supporting_files(project, target)
|
63
|
+
add_info_plist(project)
|
64
|
+
return if target.test_target_type?
|
65
|
+
add_framework_header(project, target)
|
66
|
+
end
|
67
|
+
|
68
|
+
def reject_excluded_files(exclude_files, path)
|
69
|
+
exclude_files.each do |files_to_exclude|
|
70
|
+
files_to_exclude.each do |file_to_exclude|
|
71
|
+
return true if File.fnmatch(file_to_exclude, path)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
false
|
76
|
+
end
|
77
|
+
|
78
|
+
def add_source_files(project, target)
|
79
|
+
exclude_files = @exclude_files.map do |files|
|
80
|
+
Dir[files]
|
81
|
+
end
|
82
|
+
|
83
|
+
source_files = @include_files.map do |files|
|
84
|
+
Dir[files].reject do |path|
|
85
|
+
reject_excluded_files(exclude_files, path)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
source_files.each do |file_directory|
|
90
|
+
file_directory.each do |path|
|
91
|
+
source_file_group = find_group(project, path)
|
92
|
+
has_source_file = source_file_group.find_file_by_path(path)
|
93
|
+
unless has_source_file
|
94
|
+
source_file = source_file_group.new_reference(path)
|
95
|
+
target.source_build_phase.add_file_reference(source_file, true)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def append_framework_extension(framework)
|
102
|
+
if File.extname(framework) == '.framework'
|
103
|
+
return framework
|
104
|
+
end
|
105
|
+
|
106
|
+
"#{framework}.framework"
|
107
|
+
end
|
108
|
+
|
109
|
+
def add_dependencies(project, target)
|
110
|
+
return unless @dependencies != nil
|
111
|
+
|
112
|
+
dependency_names = @dependencies.map do |dependency|
|
113
|
+
append_framework_extension(dependency)
|
114
|
+
end
|
115
|
+
|
116
|
+
frameworks = dependency_names.reject do |name|
|
117
|
+
!project.products.any? { |x| x.path == name }
|
118
|
+
end
|
119
|
+
|
120
|
+
frameworks = frameworks.map do |name|
|
121
|
+
project.products.find { |x| x.path == name }
|
122
|
+
end
|
123
|
+
|
124
|
+
frameworks.each do |path|
|
125
|
+
target.frameworks_build_phase.add_file_reference(path, true)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def copy_carthage_frameworks(project, build_phase)
|
130
|
+
script_file_path = File.join(File.dirname(__FILE__), 'copy-carthage-frameworks.sh')
|
131
|
+
|
132
|
+
script_file = File.open(script_file_path)
|
133
|
+
|
134
|
+
build_phase.shell_script = script_file.read
|
135
|
+
|
136
|
+
script_file.close
|
137
|
+
|
138
|
+
add_framework_to_copy_phase(project, build_phase)
|
139
|
+
end
|
140
|
+
|
141
|
+
def add_framework_to_copy_phase(project, build_phase)
|
142
|
+
return unless @dependencies != nil
|
143
|
+
|
144
|
+
dependency_names = @dependencies.map do |dependency|
|
145
|
+
append_framework_extension(dependency)
|
146
|
+
end
|
147
|
+
|
148
|
+
frameworks = dependency_names.reject do |name|
|
149
|
+
project.products.any? { |x| x.path == name }
|
150
|
+
end
|
151
|
+
|
152
|
+
frameworks.each do |path|
|
153
|
+
build_phase.input_paths << path
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def add_resource_files(project, target)
|
158
|
+
return unless @resource_files != nil
|
159
|
+
|
160
|
+
files = @resource_files.map do |files|
|
161
|
+
Dir[files]
|
162
|
+
end
|
163
|
+
|
164
|
+
files.each do |file_directory|
|
165
|
+
file_directory.each do |path|
|
166
|
+
file_group = find_group(project, path)
|
167
|
+
has_file = file_group.find_file_by_path(path)
|
168
|
+
unless has_file
|
169
|
+
file = file_group.new_reference(path)
|
170
|
+
target.resources_build_phase.add_file_reference(file, true)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def add_build_scripts(target, scripts)
|
177
|
+
return unless scripts != nil
|
178
|
+
|
179
|
+
scripts.each do |script|
|
180
|
+
build_phase = target.new_shell_script_build_phase(script.name)
|
181
|
+
build_phase.shell_script = script.script
|
182
|
+
build_phase.input_paths = script.inputs
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def add_pre_build_scripts(target)
|
187
|
+
add_build_scripts(target, @pre_build_scripts)
|
188
|
+
end
|
189
|
+
|
190
|
+
def add_post_build_scripts(target)
|
191
|
+
add_build_scripts(target, @post_build_scripts)
|
192
|
+
end
|
193
|
+
|
194
|
+
def create(project, language)
|
195
|
+
name = @name
|
196
|
+
type = @type
|
197
|
+
|
198
|
+
# Target
|
199
|
+
target = project.new(Xcodeproj::Project::Object::PBXNativeTarget)
|
200
|
+
project.targets << target
|
201
|
+
target.name = name
|
202
|
+
target.product_name = name
|
203
|
+
target.product_type = Xcodeproj::Constants::PRODUCT_TYPE_UTI[type]
|
204
|
+
target.build_configuration_list = Xcodeproj::Project::ProjectHelper.configuration_list(project, :osx, nil, type, language.type)
|
205
|
+
|
206
|
+
# Pre build script
|
207
|
+
add_pre_build_scripts(target)
|
208
|
+
|
209
|
+
add_supporting_files(project, target)
|
210
|
+
add_source_files(project, target)
|
211
|
+
|
212
|
+
target.build_configurations.each do |configuration|
|
213
|
+
target_build_settings(configuration.build_settings)
|
214
|
+
end
|
215
|
+
|
216
|
+
# Product
|
217
|
+
product = project.products_group.new_product_ref_for_target(name, type)
|
218
|
+
target.product_reference = product
|
219
|
+
|
220
|
+
# Build phases
|
221
|
+
|
222
|
+
target.build_phases << project.new(Xcodeproj::Project::Object::PBXResourcesBuildPhase)
|
223
|
+
target.build_phases << project.new(Xcodeproj::Project::Object::PBXFrameworksBuildPhase)
|
224
|
+
|
225
|
+
# Post build script
|
226
|
+
add_post_build_scripts(target)
|
227
|
+
|
228
|
+
# Dependencies
|
229
|
+
add_dependencies(project, target)
|
230
|
+
|
231
|
+
# Resource files
|
232
|
+
add_resource_files(project, target)
|
233
|
+
|
234
|
+
# Copy frameworks to test target
|
235
|
+
if target.test_target_type?
|
236
|
+
build_phase = target.new_shell_script_build_phase('Copy Carthage Frameworks')
|
237
|
+
copy_carthage_frameworks(project, build_phase)
|
238
|
+
end
|
239
|
+
|
240
|
+
target
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module FrameworkGenerate
|
2
|
+
class Runner
|
3
|
+
def self.generate
|
4
|
+
file_path = "#{Dir.pwd}/FrameworkSpec"
|
5
|
+
|
6
|
+
unless File.exist?(file_path)
|
7
|
+
abort "Couldn't find FrameworkSpec"
|
8
|
+
end
|
9
|
+
|
10
|
+
file_contents = File.read(file_path)
|
11
|
+
|
12
|
+
project = FrameworkGenerate::Project.new
|
13
|
+
project.instance_eval(file_contents, file_path)
|
14
|
+
|
15
|
+
project.generate
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
autoload :Project, 'framework-generate/project'
|
20
|
+
autoload :Language, 'framework-generate/language'
|
21
|
+
autoload :Platform, 'framework-generate/platform'
|
22
|
+
autoload :Target, 'framework-generate/target'
|
23
|
+
autoload :Script, 'framework-generate/script'
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: framework-generate
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pierre-Marc Airoldi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: xcodeproj
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.4.0
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.0.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.4.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.0.0
|
33
|
+
description: Simple tool to help generate a multiplatform, single-scheme Xcode project
|
34
|
+
email:
|
35
|
+
- pierremarcairoldi@gmail.com
|
36
|
+
executables:
|
37
|
+
- framework-generate
|
38
|
+
extensions: []
|
39
|
+
extra_rdoc_files: []
|
40
|
+
files:
|
41
|
+
- LICENSE
|
42
|
+
- README.md
|
43
|
+
- bin/framework-generate
|
44
|
+
- lib/framework-generate.rb
|
45
|
+
- lib/framework-generate/copy-carthage-frameworks.sh
|
46
|
+
- lib/framework-generate/language.rb
|
47
|
+
- lib/framework-generate/platform.rb
|
48
|
+
- lib/framework-generate/project.rb
|
49
|
+
- lib/framework-generate/script.rb
|
50
|
+
- lib/framework-generate/target.rb
|
51
|
+
homepage: https://pierremarcairoldi.com
|
52
|
+
licenses:
|
53
|
+
- MIT
|
54
|
+
metadata: {}
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 2.0.0
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 2.5.1
|
72
|
+
signing_key:
|
73
|
+
specification_version: 4
|
74
|
+
summary: Tool to generate an Xcode framework project
|
75
|
+
test_files: []
|