framework-generate 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|