cocoapods-util 0.0.11

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.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/Gemfile +13 -0
  4. data/LICENSE +21 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +54 -0
  7. data/Rakefile +13 -0
  8. data/cocoapods-util.gemspec +25 -0
  9. data/lib/cocoapods-util/CocoapodsUtilHook.rb +18 -0
  10. data/lib/cocoapods-util/cocoapods-extend/extend.rb +2 -0
  11. data/lib/cocoapods-util/cocoapods-extend/install/list.rb +140 -0
  12. data/lib/cocoapods-util/cocoapods-extend/install.rb +15 -0
  13. data/lib/cocoapods-util/cocoapods-extend/repo/push.rb +40 -0
  14. data/lib/cocoapods-util/cocoapods-extend/repo/push_helper.rb +36 -0
  15. data/lib/cocoapods-util/cocoapods-extend/repo.rb +15 -0
  16. data/lib/cocoapods-util/command/util.rb +28 -0
  17. data/lib/cocoapods-util/command.rb +1 -0
  18. data/lib/cocoapods-util/gem_version.rb +3 -0
  19. data/lib/cocoapods-util/hooks/installer.rb +4 -0
  20. data/lib/cocoapods-util/libsource/source.rb +81 -0
  21. data/lib/cocoapods-util/libsource/source_linker.rb +184 -0
  22. data/lib/cocoapods-util/package/helper/builder.rb +194 -0
  23. data/lib/cocoapods-util/package/helper/framework.rb +61 -0
  24. data/lib/cocoapods-util/package/helper/framework_builder.rb +147 -0
  25. data/lib/cocoapods-util/package/helper/library_builder.rb +47 -0
  26. data/lib/cocoapods-util/package/helper/pod_utils.rb +126 -0
  27. data/lib/cocoapods-util/package/package.rb +177 -0
  28. data/lib/cocoapods-util/user_interface/build_failed_report.rb +15 -0
  29. data/lib/cocoapods-util/xcframework/xcframework.rb +66 -0
  30. data/lib/cocoapods-util/xcframework/xcramework_build.rb +133 -0
  31. data/lib/cocoapods-util.rb +1 -0
  32. data/lib/cocoapods_plugin.rb +3 -0
  33. data/spec/command/util_spec.rb +12 -0
  34. data/spec/spec_helper.rb +50 -0
  35. metadata +126 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6eea54c237d8b750af8a47c4059889c3f65a87d49f11ce2f5bcccdc5157a06cf
4
+ data.tar.gz: 946c608fa0bc0a460867a39f6226ebaf69e6c48a6415434517b09c75fde1aca5
5
+ SHA512:
6
+ metadata.gz: db56865fb1fd147b1b4ef94d6b411edceebdb6d608c28d9936cc1c127a0bf6bf7b0861ee02b112fc32b0a8a0f5ed945f96a214e913bc79931b2ec7bd5fe3c80b
7
+ data.tar.gz: e20471e128e640c5e632f6aa88a1e6a0bd38da2deb022989632ba93e0fdab17aab093e9b0cd00677bcae2dc1be1739f5ff05cd8ec43679a23b0773b33ae4f613
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ pkg
3
+ .idea/
4
+ .vscode/
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cocoapods-util.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'cocoapods'
8
+
9
+ gem 'mocha'
10
+ gem 'bacon'
11
+ gem 'mocha-on-bacon'
12
+ gem 'prettybacon'
13
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Cary
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/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2022 guojiashuang <guojiashuang@58.com>
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # cocoapods-util
2
+
3
+ cocoapods-util是一个pod插件集合,支持package、生成xcframework、linksource、repo push等功能。
4
+
5
+ ## Installation
6
+
7
+ $ gem install cocoapods-util
8
+
9
+ ## Usage
10
+
11
+ $ pod util --help
12
+
13
+ ## 功能
14
+
15
+ ### package
16
+
17
+ $ pod util package --help
18
+
19
+ 通过podspec文件生成library、framework、xcframework。
20
+
21
+ - [x] 支持swift
22
+ - [x] 支持自定义配置dependency
23
+ - [x] 支持排除模拟器
24
+ - [x] 支持多平台(ios、osx、watchos、tvos)
25
+ - [x] 支持自定义设置工程的build settings(如:排除ios模拟器64位架构、设置支持的架构等)
26
+
27
+
28
+ ###  xcframework
29
+
30
+ $ pod util xcframework --help
31
+
32
+ 可以把现有的framework生成xcframework。
33
+
34
+ - 内部可以判断是某个平台的framework(如ios、osx、watchos),直接在framework同级目录生成xcframework。
35
+
36
+ ### linksource
37
+
38
+ $ pod util linksource --help
39
+
40
+ 源码二进制链接功能
41
+
42
+ ### repo push
43
+
44
+ $ pod util repo push --help
45
+
46
+ 推送私有pods仓库的命令
47
+
48
+ - 可以通过添加--skip-validate的选项跳过验证步骤。
49
+
50
+ ### install list
51
+
52
+ $ pod util install list --help
53
+
54
+ 列出安装的pod库
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ def specs(dir)
4
+ FileList["spec/#{dir}/*_spec.rb"].shuffle.join(' ')
5
+ end
6
+
7
+ desc 'Runs all the specs'
8
+ task :specs do
9
+ sh "bundle exec bacon #{specs('**')}"
10
+ end
11
+
12
+ task :default => :specs
13
+
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cocoapods-util/gem_version.rb'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'cocoapods-util'
8
+ spec.version = CocoapodsUtil::VERSION
9
+ spec.authors = ['guojiashuang']
10
+ spec.email = ['guojiashuang@live.com']
11
+ spec.description = %q{cocoapods-util是一个cocoapods插件,解决日常ios开发中遇到的一些问题。支持打包(编译)静态库、framework生成xcframework、二进制link源码、推送私有库跳过验证等功能。}
12
+ spec.summary = %q{一个常用插件功能的集合,致力于解决日常开发中遇到的一些问题。}
13
+ spec.homepage = 'https://github.com/CaryGo/cocoapods-util'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency "cocoapods", ">= 1.5.0", "< 2.0"
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.3'
24
+ spec.add_development_dependency 'rake'
25
+ end
@@ -0,0 +1,18 @@
1
+ module CocoapodsUtilHook
2
+ Pod::HooksManager.register('cocoapods-util', :pre_install) do |context, _|
3
+ puts "pre_install"
4
+ end
5
+ Pod::HooksManager.register('cocoapods-util', :pre_integrate) do |context, _|
6
+ puts "pre_integrate"
7
+ end
8
+ Pod::HooksManager.register('cocoapods-util', :post_install) do |context, _|
9
+ puts "post_install"
10
+ end
11
+ Pod::HooksManager.register('cocoapods-util', :post_integrate) do |context, _|
12
+ puts "post_integrate"
13
+ end
14
+ Pod::HooksManager.register('cocoapods-util', :source_provider) do |context, _|
15
+ puts "source_provider"
16
+ end
17
+ end
18
+
@@ -0,0 +1,2 @@
1
+ require 'cocoapods-util/cocoapods-extend/repo'
2
+ require File.expand_path('../install.rb', __FILE__)
@@ -0,0 +1,140 @@
1
+ require 'cocoapods/config'
2
+
3
+ module Pod
4
+ class Command
5
+ class Util < Command
6
+ class Install < Util
7
+ class List < Install
8
+ self.summary = '列出pod install安装的组件信息,Podfile.lock不传则在当前目录查找'
9
+ self.command = 'list'
10
+ self.arguments = [
11
+ CLAide::Argument.new('Podfile.lock', false)
12
+ ]
13
+ def self.options
14
+ [
15
+ ['--all', 'list all component.'],
16
+ ['--name', 'componment name.'],
17
+ ['--showmore', 'show more information.']
18
+ ]
19
+ end
20
+
21
+ def initialize(argv)
22
+ @lockfile_path = argv.shift_argument
23
+ @name = argv.option('name')
24
+ @all_componment = argv.flag?('all', true) && (@name.nil? || @name.empty?)
25
+ @showmore = argv.flag?('showmore', false) || @name
26
+ super
27
+ end
28
+
29
+ def validate!
30
+ super
31
+ end
32
+
33
+ def run
34
+ if @lockfile_path.nil?
35
+ @lockfile = Pod::Config.instance.lockfile
36
+ else
37
+ @lockfile = Lockfile.from_file(Pathname.new(@lockfile_path))
38
+ end
39
+ help! '没有查找到Podfile.lock文件,你需要在Podfile所在目录执行或传入Podfile.lock文件路径。' unless @lockfile
40
+
41
+ if @all_componment
42
+ check_all_componment
43
+ else
44
+ installed = pod_installed
45
+ help! "没有找到#{@name}组件的相关信息,请检查输入的组件名称" unless installed.include?(@name)
46
+ check_componment_with_name(@name)
47
+ end
48
+ end
49
+
50
+ private
51
+ def check_all_componment
52
+ installed = pod_installed
53
+ installed.each_index do |index|
54
+ name = installed[index]
55
+ check_componment_with_name(name, index+1)
56
+ end
57
+ end
58
+
59
+ def check_componment_with_name(name, index=1)
60
+ tags_info = pod_tags_info
61
+ UI.puts "#{index}).".red " #{name} ".green "#{tags_info[name]}".yellow
62
+
63
+ # repo spec
64
+ repo_name = pod_spec_repos[name]
65
+ UI.puts " - SPEC REPO: ".yellow "#{repo_name}".green unless repo_name.nil?
66
+
67
+ # external sources
68
+ external = @lockfile.internal_data['EXTERNAL SOURCES'][name]
69
+ external.each { |key, value| UI.puts " - #{key}: ".yellow "#{value}".green } unless external.nil?
70
+
71
+ # subspecs、dependencies
72
+ show_moreinfo(name) if @showmore
73
+ end
74
+
75
+ def show_moreinfo(name)
76
+ subspecs = Array.new
77
+ dependencies = Array.new
78
+ @lockfile.internal_data["PODS"].each { |item|
79
+ info = item.keys.first if item.is_a?(Hash) && item.count == 1
80
+ info = item if item.is_a?(String)
81
+ if info =~ /^#{name}.*$/
82
+ subspecs.push(info.match(/^[^\s]*/)) if info =~ /^#{name}\/.*$/
83
+ if item.is_a?(Hash)
84
+ item.each_value do |value|
85
+ value.each {|dependency| dependencies.push(dependency.to_s) unless dependency =~ /^#{name}/ }
86
+ end
87
+ elsif item.is_a?(String)
88
+ dependencies.push(item.to_s) unless item =~ /^#{name}/
89
+ end
90
+ end
91
+ }
92
+ subspecs.uniq!
93
+ dependencies.uniq!
94
+ UI.puts " - SUBSPEC: ".yellow "#{subspecs.join('、')}".green unless subspecs.empty?
95
+ UI.puts " - DEPENDENCIES: ".yellow "#{dependencies.join('、')}".green unless dependencies.empty?
96
+ end
97
+
98
+ def pod_tags_info
99
+ if @tags_info
100
+ return @tags_info
101
+ end
102
+ @tags_info = Hash.new
103
+ @lockfile.internal_data["PODS"].each do |item|
104
+ info = item.keys.first if item.is_a?(Hash) && item.count == 1
105
+ info = item if item.is_a?(String)
106
+ if info =~ /^[^\/]*$/
107
+ name = info.match(/^[^\/\s]*/)
108
+ tag = info.match(/\(.*\)/) || ''
109
+ @tags_info[name.to_s] = tag.to_s
110
+ end
111
+ end
112
+ @tags_info
113
+ end
114
+
115
+ def pod_installed
116
+ if @installed
117
+ return @installed
118
+ end
119
+ @installed = Array.new
120
+ @lockfile.internal_data["SPEC CHECKSUMS"].each_key do |item|
121
+ @installed.push(item)
122
+ end
123
+ @installed
124
+ end
125
+
126
+ def pod_spec_repos
127
+ if @spec_repos
128
+ return @spec_repos
129
+ end
130
+ @spec_repos = Hash.new
131
+ @lockfile.internal_data["SPEC REPOS"].each do |key, value|
132
+ value.each {|item| @spec_repos[item] = key } if value.is_a?(Array)
133
+ end
134
+ @spec_repos
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,15 @@
1
+ require 'cocoapods-util/cocoapods-extend/install/list'
2
+ module Pod
3
+ class Command
4
+ class Util < Command
5
+ class Install < Util
6
+ self.summary = 'cocoapods install的扩展功能'
7
+ self.description = <<-DESC
8
+ 使用`pod util install list`查看pod安装的组件
9
+ DESC
10
+ self.command == 'install'
11
+ self.abstract_command = true
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,40 @@
1
+ module Pod
2
+ class Command
3
+ class Util < Command
4
+ class Repo < Util
5
+ class Push < Repo
6
+ self.summary = '`pod repo push`扩展功能,解决私有仓库验证不过无法推送的问题'
7
+ self.description = <<-DESC
8
+ 和`pod repo push`命令使用步骤完全一致,可以设置参数`--skip-validate`跳过验证直接推送到私有仓库,不设置时调用原`push`的命令,不影响原功能。
9
+ DESC
10
+ self.arguments = Pod::Command::Repo::Push.arguments
11
+ def self.options
12
+ require 'cocoapods-util/cocoapods-extend/repo/push_helper'
13
+ Pod::Command::Repo::Push.options
14
+ end
15
+
16
+ def initialize(argv)
17
+ @skip_validate = argv.flag?('skip-validate', false)
18
+ super
19
+ @argvs = argv.remainder!
20
+
21
+ @repo = @argvs.first
22
+ end
23
+
24
+ def validate!
25
+ help! 'A spec-repo name or url is required.' unless @repo
26
+ end
27
+
28
+ def run
29
+ require 'cocoapods-util/cocoapods-extend/repo/push_helper'
30
+
31
+ @target = Pod::Command::Repo::Push.new(CLAide::ARGV.new(@argvs))
32
+ @target.validate!
33
+ @target.skip_validate = @skip_validate
34
+ @target.run
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ class Module
2
+ def strong_alias(to, from)
3
+ # https://tieba.baidu.com/p/5535445605?red_tag=0735709674 贴吧大神给出的方案
4
+ # 类方法可以看做singleton class(单例类)的实例方法,下面两个方法都可以,上面这个方式也适用于早起的ruby版本
5
+ (class << self;self;end).send(:alias_method, to, from)
6
+ # self.singleton_class.send(:alias_method, to, from)
7
+ end
8
+ end
9
+
10
+ module Pod
11
+ class Command
12
+ class Repo < Command
13
+ class Push < Repo
14
+ attr_accessor :skip_validate
15
+
16
+ self.strong_alias(:old_options, :options)
17
+ def self.options
18
+ [
19
+ ['--skip-validate', '跳过验证,不验证推送的podspec文件,默认为验证']
20
+ ].concat(self.old_options)
21
+ end
22
+
23
+ # 调用原方法的两种方式
24
+ old_validate_podspec_files = instance_method(:validate_podspec_files)
25
+ define_method(:validate_podspec_files) do
26
+ old_validate_podspec_files.bind(self).() unless @skip_validate
27
+ end
28
+
29
+ alias_method :old_check_repo_status, :check_repo_status
30
+ def check_repo_status
31
+ old_check_repo_status unless @skip_validate
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,15 @@
1
+ require 'cocoapods-util/cocoapods-extend/repo/push'
2
+ module Pod
3
+ class Command
4
+ class Util < Command
5
+ class Repo < Util
6
+ self.summary = 'cocoapods repo命令的扩展功能'
7
+ self.description = <<-DESC
8
+ 操作cocoapods的私有repo。如`pod util repo push`推送到私有仓库(可以设置参数跳过验证)
9
+ DESC
10
+ self.command == 'repo'
11
+ self.abstract_command = true
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ require 'cocoapods-util/package/package'
2
+ require 'cocoapods-util/xcframework/xcframework'
3
+ require 'cocoapods-util/libsource/source'
4
+
5
+ require 'cocoapods-util/cocoapods-extend/extend'
6
+
7
+ module Pod
8
+ class Command
9
+ class Util < Command
10
+ self.summary = '一个CocoaPods常用插件功能的集合'
11
+ self.description = <<-DESC
12
+ 一个CocoaPods常用插件功能的集合,解决日常开发中遇到的一些问题。
13
+ DESC
14
+ self.command == 'util'
15
+ self.abstract_command = true
16
+ def initialize(argv)
17
+ super
18
+ end
19
+
20
+ def validate!
21
+ super
22
+ end
23
+
24
+ def run
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1 @@
1
+ require 'cocoapods-util/command/util'
@@ -0,0 +1,3 @@
1
+ module CocoapodsUtil
2
+ VERSION = "0.0.11"
3
+ end
@@ -0,0 +1,4 @@
1
+ module Pod
2
+ class Installer < Command
3
+ end
4
+ end
@@ -0,0 +1,81 @@
1
+ require 'cocoapods-util/libsource/source_linker.rb'
2
+
3
+ module Pod
4
+ class Command
5
+ class Util < Command
6
+ class Source < Util
7
+ self.summary = '根据传入library、framework或xcframework,添加源码软链接'
8
+ self.description = <<-DESC
9
+ 需要注意参数中的`link、unlink、checklinked和checkcompile`是互斥的,只需要传入一个参数
10
+ DESC
11
+ self.command = 'linksource'
12
+ self.arguments = [
13
+ CLAide::Argument.new('NAME', true),
14
+ ]
15
+
16
+ def self.options
17
+ [
18
+ ['--link', '链接源码'],
19
+ ['--unlink', '删除源码链接'],
20
+ ['--checklinked', '检查源码链接'],
21
+ ['--checkcompile', '输出二进制文件的编译信息,编译的工程路径,编译的源码路径等'],
22
+
23
+ ['--force', 'link时覆盖已经添加的软链接'],
24
+ ['--source-path', '需要链接的源码的路径'],
25
+ ['--compile-path', '特殊情况获取的编译路径和真实源码编译的路径可能不一致,可自定义设置编译路径']
26
+ ]
27
+ end
28
+
29
+ def initialize(argv)
30
+ link = argv.flag?('link')
31
+ @link_type = if argv.flag?('link')
32
+ :link
33
+ elsif argv.flag?('unlink')
34
+ :unlink
35
+ elsif argv.flag?('checklinked')
36
+ :checklinked
37
+ elsif argv.flag?('checkcompile')
38
+ :checkcompile
39
+ else
40
+ :link
41
+ end
42
+
43
+ @file_path = argv.shift_argument
44
+ @force = argv.flag?('force')
45
+ @source_path = argv.option('source-path', nil)
46
+ @compile_path = argv.option('compile-path', nil)
47
+ super
48
+ end
49
+
50
+ def validate!
51
+ super
52
+ help! '必须传入需链接的library、framework或xcframework路径或名称.' unless @file_path
53
+ end
54
+
55
+ def run
56
+ # 获取真实路径,~ 为进程所有者的主目录
57
+ @file_path = File.expand_path(@file_path)
58
+ if (File.exist? @file_path) == false || !(@file_path =~ /\.(a|framework|xcframework)$/)
59
+ help! "路径不存在或传入的路径不是.a、.framework、.xcframework文件"
60
+ return
61
+ end
62
+
63
+ source_dir, basename = File.split(@file_path)
64
+ file_name, file_type = basename.split('.')
65
+
66
+ linker = SourceLinker.new(
67
+ file_name,
68
+ file_type,
69
+ source_dir,
70
+ @link_type,
71
+ @force
72
+ )
73
+ linker.allow_ask_source_path = true
74
+ linker.source_path = @source_path
75
+ linker.compile_path = @compile_path
76
+ linker.execute
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end