rake-delphi 0.0.9 → 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 (48) hide show
  1. data/2 +336 -0
  2. data/Gemfile +2 -1
  3. data/lib/rake/common/logger.rb +1 -1
  4. data/lib/rake/delphi/androidmanifest.rb +57 -0
  5. data/lib/rake/delphi/dcc32.rb +58 -59
  6. data/lib/rake/delphi/dcc32tool.rb +51 -0
  7. data/lib/rake/delphi/dccaarmtool.rb +29 -0
  8. data/lib/rake/delphi/envvariables.rb +19 -22
  9. data/lib/rake/delphi/paclient.rb +251 -0
  10. data/lib/rake/delphi/paclienttool.rb +20 -0
  11. data/lib/rake/delphi/project.rb +4 -2
  12. data/lib/rake/delphi/projectinfo.rb +73 -1
  13. data/lib/rake/delphi/resources.rb +1 -1
  14. data/lib/rake/delphi/tool.rb +8 -1
  15. data/lib/rake/delphi/version.rb +1 -1
  16. data/lib/rake/helpers/gemversion.rb +11 -0
  17. data/lib/rake/helpers/raketask.rb +16 -0
  18. data/lib/rake/helpers/string.rb +13 -0
  19. data/rake-delphi-cygwin.env.cmd +11 -0
  20. data/rake-delphi-cygwin.env.sh +12 -0
  21. data/rake-delphi.gemspec +4 -1
  22. data/test/helpers/consts.rb +6 -1
  23. data/test/helpers/verinfo.rb +22 -3
  24. data/test/resources/testproject-android/AndroidManifest.erb +35 -0
  25. data/test/resources/testproject-android/AndroidManifest.xml +35 -0
  26. data/test/resources/testproject-android/Rakefile.rb +55 -0
  27. data/test/resources/testproject-android/TestProject.cfg +4 -0
  28. data/test/resources/testproject-android/TestProject.dpr +15 -0
  29. data/test/resources/testproject-android/TestProject.rc +62 -0
  30. data/test/resources/testproject-android/TestProject.res +0 -0
  31. data/test/resources/testproject-android/TestProject.xe5.dproj +373 -0
  32. data/test/resources/testproject-android/fmTest.fmx +26 -0
  33. data/test/resources/testproject-android/fmTest.pas +31 -0
  34. data/test/resources/testproject-android/local.resources.txt +1 -0
  35. data/test/resources/testproject-android/release.dcc.cfg +1 -0
  36. data/test/resources/testproject-android/resources.rc +1 -0
  37. data/test/resources/testproject-android/resources.res +0 -0
  38. data/test/resources/testproject/Rakefile.rb +1 -1
  39. data/test/test-delphi-android.rb +192 -0
  40. data/test/test-delphi.rb +3 -11
  41. data/test/test-envvariables.rb +7 -0
  42. data/test/test-gemversion.rb +11 -0
  43. data/test/test-projectinfo-android.rb +81 -0
  44. data/test/test-projectinfo.rb +0 -11
  45. data/test/test-string.rb +41 -0
  46. metadata +92 -6
  47. data/test/resources/testproject/testproject.cfg.1 +0 -8
  48. data/test/resources/testproject/testproject.drc +0 -210
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rake/common/logger'
4
+ require 'rake/delphi/tool'
5
+
6
+ module Rake
7
+ module Delphi
8
+ class Dcc32Tool < CustomDelphiTool
9
+ attr_reader :env
10
+
11
+ def self.toolName
12
+ 'bin/dcc32.exe'
13
+ end
14
+
15
+ def delphidir
16
+ @@delphidir
17
+ end
18
+
19
+ def delphilib
20
+ ENV['BDSLIB']
21
+ end
22
+
23
+ def init_env
24
+ @env ||= EnvVariables.new(self.class.rootForVersion(self.version) + '\Environment Variables', self.delphidir)
25
+ end
26
+
27
+ def readLibraryPaths(platform, platform_stripped)
28
+ Logger.trace(Logger::TRACE, 'Reading library paths for platform: ' + platform.to_s)
29
+ warn "WARNING! You are using Delphi XE or above but no platform defined!" if ENV['DELPHI_VERSION'].to_i >= 14 && ! platform
30
+
31
+ platform = platform.to_s != '' ? '\\' + platform : ''
32
+ # platform not used for old Delphis 'SearchPath'
33
+ libpaths = self.class.readUserOption('Library' + platform, 'Search Path', self.version).split(';') \
34
+ | self.class.readUserOption('Library', 'SearchPath', self.version).split(';')
35
+ Logger.trace(Logger::TRACE, 'Library paths read:')
36
+ Logger.trace(Logger::TRACE, libpaths)
37
+ dev = init_env
38
+ dev['PLATFORM'] = platform_stripped if platform_stripped
39
+ libpaths.map! do |lp|
40
+ unless lp.to_s.empty?
41
+ lp = dev.expand(lp)
42
+ end
43
+ lp
44
+ end
45
+ Logger.trace(Logger::TRACE, 'Library paths expanded:')
46
+ Logger.trace(Logger::TRACE, libpaths)
47
+ return libpaths
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,29 @@
1
+ # vim: set shiftwidth=2 tabstop=2 expandtab:
2
+ # encoding: utf-8
3
+
4
+ require 'rake/delphi/dcc32tool'
5
+
6
+ module Rake
7
+ module Delphi
8
+ class DccARMTool < Dcc32Tool
9
+ def self.toolName
10
+ 'bin/dccaarm.exe'
11
+ end
12
+
13
+ def options
14
+ opts = []
15
+ linker_path = ENV['DELPHI_ANDROID_SDK_LINKER']
16
+ warn "Please, define DELPHI_ANDROID_SDK_LINKER environment variable.\n Otherwise you may get 'File not found: ldandroid.exe' error" unless linker_path
17
+ lib_path = ENV['DELPHI_ANDROID_SDK_LIBPATH']
18
+ warn 'Please, define DELPHI_ANDROID_SDK_LIBPATH environment variable' unless lib_path
19
+ linker_option = ENV['DELPHI_ANDROID_SDK_LINKER_OPTION']
20
+ warn 'Please, define DELPHI_ANDROID_SDK_LINKER_OPTION environment variable' unless linker_option
21
+ opts << '-TX.so'
22
+ opts << "--linker:\"#{linker_path}\""
23
+ opts << "--libpath:\"#{lib_path}\""
24
+ opts << "--linker-option:\"#{linker_option}\""
25
+ return opts
26
+ end
27
+ end
28
+ end
29
+ end
@@ -8,6 +8,22 @@ module Rake
8
8
  ENV['DELPHI_VERSION']
9
9
  end
10
10
 
11
+ def initialize(regpath, delphidir)
12
+ readreg(regpath)
13
+ _dir = delphidir.gsub(/\/$/, '')
14
+ add('DELPHI', _dir)
15
+ add('BDS', _dir)
16
+ add('BDSLIB', _dir + '/Lib')
17
+ expand_vars
18
+ Logger.trace(Logger::TRACE, self)
19
+ end
20
+
21
+ def expand(value)
22
+ value = expand_value(value, self)
23
+ value = expand_value(value, ENV)
24
+ end
25
+
26
+ private
11
27
  def readreg(regpath)
12
28
  return unless regpath
13
29
  begin
@@ -29,34 +45,15 @@ module Rake
29
45
  end
30
46
  end
31
47
 
32
- def initialize(regpath, delphidir)
33
- readreg(regpath)
34
- _dir = delphidir.gsub(/\/$/, '')
35
- add('DELPHI', _dir)
36
- add('BDS', _dir)
37
- add('BDSLIB', _dir + '/Lib')
38
- expand_vars
39
- Logger.trace(Logger::TRACE, self)
40
- end
41
-
42
48
  def add(var, value)
43
49
  self[var] = value
44
50
  end
45
51
 
46
- def expand_global(value)
47
- value.gsub!(/\$\((?'env_name'\w+)\)/) do |match|
52
+ def expand_value(value, values)
53
+ value.gsub(/\$\((?'env_name'\w+)\)/) do |match|
48
54
  name = Regexp.last_match[:env_name].upcase
49
- ENV[name] || match
50
- end
51
- value
52
- end
53
-
54
- def expand(value)
55
- self.each do |name, val|
56
- value.gsub!("$(#{name})", val)
57
- value = expand_global(value)
55
+ values[name] || match
58
56
  end
59
- value
60
57
  end
61
58
 
62
59
  def expand_vars
@@ -0,0 +1,251 @@
1
+ # vim: set shiftwidth=2 tabstop=2 expandtab:
2
+ # encoding: utf-8
3
+
4
+ require 'fileutils'
5
+ require 'tempfile'
6
+ require 'rake'
7
+ require 'rake/helpers/rake'
8
+ require 'rake/helpers/raketask'
9
+ require 'rake/helpers/string'
10
+ require 'rake/common/chdirtask'
11
+ require 'rake/delphi/paclienttool'
12
+ require 'rake/delphi/androidmanifest'
13
+
14
+ module Rake
15
+ module Delphi
16
+ class PAClientTask < Rake::Task
17
+ public
18
+ attr_reader :dccTask
19
+ attr_accessor :suffix
20
+ attr_reader :deploymentfiles
21
+ attr_accessor :noclean # for debugging
22
+
23
+ def initialize(name, application)
24
+ super
25
+ @last_put_arg_index = 0
26
+ @suffix = 'AndroidPackage'
27
+ @manifest = application.define_task(AndroidManifestTask, shortname + ':manifest')
28
+ enhance([@manifest])
29
+ self.needed = false
30
+ dccTaskName = name.gsub(/:post$/, '')
31
+ @dccTask = application[dccTaskName]
32
+ @deploymentfiles = nil
33
+ end
34
+
35
+ def needed=(value)
36
+ super
37
+ @manifest.needed = value
38
+ end
39
+
40
+ private
41
+ def expand_vars(deploymentfiles)
42
+ @dccTask.dccTool.init_env
43
+ deploymentfiles.collect! do |value|
44
+ file, dfile = [value.keys.first, value.values.first]
45
+ if file.kind_of?(String)
46
+ file = @dccTask.dccTool.env.expand(file)
47
+ end
48
+ # return expanded path
49
+ { file => dfile }
50
+ end
51
+ return deploymentfiles
52
+ end
53
+
54
+ def put_args
55
+ @deploymentfiles ||= @dccTask.createVersionInfo.deploymentfiles('Android')
56
+ r = expand_vars(@deploymentfiles)
57
+ @manifest_hash ||= { :manifest => ['.\\', '1'] }
58
+ # add unless already added before
59
+ r << @manifest_hash unless r.include?(@manifest_hash)
60
+ return r
61
+ end
62
+
63
+ def steps
64
+ r = [:Clean]
65
+ # add appropriate 'put' commands count
66
+ put_args.each do |arg|
67
+ r << :put
68
+ end
69
+ r << [:stripdebug, :aaptpackage, :jarsign, :zipalign]
70
+ r.flatten!
71
+ return r
72
+ end
73
+
74
+ def get_Clean_arg(paclientTool)
75
+ return '' if @noclean
76
+ tempfile = Tempfile.new('paclient')
77
+ tempfile.close
78
+ tempfile = File.expand_path2(tempfile.path)
79
+ tempfile.double_delimiters!
80
+ output = @dccTask.exeoutput
81
+ output += '\\' + @suffix
82
+ output.double_delimiters!
83
+ output = Rake.quotepath('', output)
84
+ return [output, tempfile].join(',')
85
+ end
86
+
87
+ def get_put_arg(paclientTool)
88
+ output = @dccTask.exeoutput
89
+ next_put_arg = put_args[@last_put_arg_index]
90
+ if next_put_arg.kind_of?(Hash)
91
+ src, out = next_put_arg.to_a.first
92
+ out = out.dup
93
+ if src == :project_so
94
+ src = out.last
95
+ src = output + '\\' + src
96
+ elsif src.kind_of?(Symbol)
97
+ src = self.send(src)
98
+ out << src
99
+ end
100
+ out = output + '\\' + @suffix + '\\' + out.join(',')
101
+ arg = src + ',' + out
102
+ else
103
+ arg = next_put_arg
104
+ end
105
+ arg.double_delimiters!
106
+ arg = Rake.quotepath('', arg)
107
+ @last_put_arg_index += 1
108
+ return arg
109
+ end
110
+
111
+ def find_project_so(deploymentfiles)
112
+ deploymentfiles.each do |file|
113
+ return file[:project_so] if file[:project_so]
114
+ end
115
+ fail 'Cannot find :project_so in files'
116
+ end
117
+
118
+ def get_stripdebug_arg(paclientTool)
119
+ stripdebug_path = ENV['DELPHI_ANDROID_SDK_STRIPDEBUG']
120
+ warn 'Please, set DELPHI_ANDROID_SDK_STRIPDEBUG to path where arm-linux-androideabi-strip.exe is located' unless stripdebug_path
121
+ stripdebug_path = Rake.quotepath('', stripdebug_path.to_s)
122
+ output_dest = find_project_so(@deploymentfiles).dup
123
+ output = @dccTask.exeoutput + '\\' + output_dest.last
124
+ # remove '1' string
125
+ output_dest.delete_at(1)
126
+ output_dest.unshift @dccTask.exeoutput + '\\' + @suffix + '\\'
127
+ args = [stripdebug_path.double_delimiters, output.double_delimiters, output_dest.join.double_delimiters]
128
+ return args.join(',')
129
+ end
130
+
131
+ def aapt_args
132
+ r = ['library', 'classes', 'res', 'assets', :manifest, :jar, :output]
133
+ return r
134
+ end
135
+
136
+ def manifest
137
+ 'AndroidManifest.xml'
138
+ end
139
+
140
+ def unsigned_path(full = false)
141
+ r = @dccTask.dpr.pathmap('%n-unsigned.apk')
142
+ r = @dccTask.exeoutput + '/' + @suffix + '/' + r if full
143
+ return r
144
+ end
145
+
146
+ def get_aaptpackage_arg(paclientTool)
147
+ output = @dccTask.exeoutput
148
+ output_platform = File.expand_path2(output, '-u')
149
+ apt_path = ENV['DELPHI_ANDROID_SDK_BUILD_TOOLS_PATH']
150
+ warn 'Please, set DELPHI_ANDROID_SDK_BUILD_TOOLS_PATH to path where aapt.exe is located' unless apt_path
151
+ apt_path = apt_path.to_s + '\\aapt.exe'
152
+ apt_path = Rake.quotepath('', apt_path)
153
+ args = [apt_path.double_delimiters]
154
+ args += aapt_args.map do |a|
155
+ to_mkdir = false
156
+ out = true
157
+ if a == :output
158
+ a = unsigned_path
159
+ elsif a == :jar
160
+ platform = ENV['DELPHI_ANDROID_SDK_PLATFORM_PATH']
161
+ warn 'Please, set DELPHI_ANDROID_SDK_PLATFORM_PATH to the path where android.jar is located' unless platform
162
+ a = platform.to_s + '\\android.jar'
163
+ a = Rake.quotepath('', a)
164
+ out = false
165
+ else
166
+ if a.kind_of?(Symbol)
167
+ a = self.send(a)
168
+ else
169
+ # mkdir dirs represented by strings
170
+ to_mkdir = true
171
+ end
172
+ end
173
+ if out
174
+ a = '/' + @suffix + '/' + a
175
+ a_platform = output_platform + a
176
+ a = output + a
177
+ if to_mkdir
178
+ mkdir a_platform unless File.exists?(a_platform)
179
+ end
180
+ end
181
+ a.gsub!('/', '\\')
182
+ a.double_delimiters!
183
+ a
184
+ end
185
+ return args.join(',')
186
+ end
187
+
188
+ def get_jarsign_arg(paclientTool)
189
+ jdk_path = ENV['JAVA_SDK_PATH']
190
+ warn 'Please, set JAVA_SDK_PATH to the path where jarsigner.exe is located' unless jdk_path
191
+ args = [Rake.quotepath('', jdk_path.to_s + '\\jarsigner.exe')]
192
+ args << unsigned_path(true).double_delimiters
193
+ key_store = ENV['DELPHI_ANDROID_KEYSTORE']
194
+ warn 'Please, set DELPHI_ANDROID_KEYSTORE to the path where keystore (to sign application) located' unless key_store
195
+ key_store = Rake.quotepath('', key_store.double_delimiters)
196
+ key_store_params = ENV['DELPHI_ANDROID_KEYSTORE_PARAMS']
197
+ warn 'Please, set DELPHI_ANDROID_KEYSTORE_PARAMS to alias,method,keystore_password,key_password' unless key_store_params
198
+ key_alias, key_params = key_store_params.split(',', 2)
199
+ args << key_alias << key_store << key_params
200
+ return args.join(',')
201
+ end
202
+
203
+ def get_zipalign_arg(paclientTool)
204
+ zip_align = ENV['DELPHI_ANDROID_SDK_PLATFORM_TOOLS']
205
+ warn 'Please, set DELPHI_ANDROID_SDK_PLATFORM_TOOLS to the path where zipalign.exe is located' unless zip_align
206
+ args = [Rake.quotepath('', zip_align.to_s + '\\zipalign.exe')]
207
+ args << unsigned_path(true).double_delimiters
208
+ zip_aligned_out = @dccTask.exeoutput + '\\' + @suffix + '\\' + @dccTask.dpr.pathmap('%n.apk')
209
+ zip_aligned_out_platform = File.expand_path2(zip_aligned_out, '-u')
210
+ FileUtils.rm zip_aligned_out_platform if File.exists?(zip_aligned_out_platform)
211
+ zip_aligned_out.double_delimiters!
212
+ args << zip_aligned_out
213
+ args << '4'
214
+ return args.join(',')
215
+ end
216
+
217
+ def build_args(paclientTool, step)
218
+ r = ['']
219
+ arg = ''
220
+ if step.kind_of?(Symbol)
221
+ arg = self.send("get_#{step.to_s}_arg", paclientTool)
222
+ else
223
+ arg = ''
224
+ end
225
+ r << "--#{step.to_s}=#{arg}"
226
+ return r
227
+ end
228
+
229
+ public
230
+ def execute(args = nil)
231
+ super
232
+ paclientTool = PAClientTool.new
233
+ paclientTool.class.checkToolFailure(paclientTool.toolpath)
234
+ exe_cmd = Rake.quotepath('', paclientTool.toolpath)
235
+ _source = @dccTask.dpr
236
+ ChDir.new(self, File.dirname(_source)) do |dir|
237
+ RakeFileUtils.verbose(Logger.debug?) do
238
+ @last_put_arg_index = 0
239
+ steps.each do |step|
240
+ args = build_args(paclientTool, step)
241
+ args.compact!
242
+ sh exe_cmd + args.join(' ')
243
+ end
244
+ output_platform = File.expand_path2(@dccTask.exeoutput, '-u')
245
+ mv output_platform.pathmap('%p%s') + @suffix + _source.pathmap('%s%n.apk'), output_platform
246
+ end
247
+ end
248
+ end
249
+ end # class PAClientTask
250
+ end
251
+ end
@@ -0,0 +1,20 @@
1
+ # vim: set shiftwidth=2 tabstop=2 expandtab:
2
+ # encoding: utf-8
3
+
4
+ require 'rake/common/logger'
5
+ require 'rake/delphi/tool'
6
+
7
+ module Rake
8
+ module Delphi
9
+ class PAClientTool < CustomDelphiTool
10
+ def initialize(checkExistance = false)
11
+ self.class.reinit
12
+ super
13
+ end
14
+
15
+ def self.toolName
16
+ 'bin/paclient.exe'
17
+ end
18
+ end
19
+ end
20
+ end
@@ -4,6 +4,7 @@ require 'rake'
4
4
  require 'rake/common/classes'
5
5
  require 'rake/common/libstask'
6
6
  require 'rake/delphi/dcc32'
7
+ require 'rake/delphi/paclient'
7
8
  require 'rake/helpers/file'
8
9
  require 'rake/helpers/raketask'
9
10
  require 'rake/helpers/string'
@@ -17,9 +18,10 @@ module Rake
17
18
  super
18
19
  initvars
19
20
  @dcc = application.define_task(Dcc32Task, shortname + ':dcc32')
20
- @libs = LibsTask.define('all-delphi-libs', application)
21
+ @libs = LibsTask.define(name + ':all-delphi-libs', application)
22
+ @post = application.define_task(PAClientTask, @dcc.shortname + ':post')
21
23
  @level = 1
22
- enhance([@libs, @dcc])
24
+ enhance([@libs, @dcc, @post])
23
25
  end
24
26
 
25
27
  def initvars
@@ -68,7 +68,7 @@ module Rake
68
68
  @content = XmlSimple.xml_in(@file, :ForceArray => false)
69
69
  else
70
70
  warn "WARNING! Version info file #{@file} does not exists"
71
- @content = nil
71
+ super
72
72
  end
73
73
  end
74
74
 
@@ -96,6 +96,78 @@ module Rake
96
96
  end
97
97
 
98
98
  class XEVersionInfo < RAD2010VersionInfo
99
+ private
100
+ def read_file_class(platform, node, hash, key)
101
+ platforms = node['Platform']
102
+ unless platforms.kind_of?(Array)
103
+ platforms = [platforms]
104
+ end
105
+ platforms.each do |plat|
106
+ if plat['Name'].casecmp(platform) == 0
107
+ # take filename from hash by key
108
+ value = node.delete(key)
109
+ # delete Name (it is a filtered platform)
110
+ plat.delete('Name')
111
+ # update Platform
112
+ node['Platform'] = plat
113
+ node.delete('Platform') if plat.empty?
114
+ hash.merge!({ value => node })
115
+ end
116
+ end
117
+ end
118
+
119
+ def read_files_and_classes(deployment_content, platform)
120
+ files = {}
121
+ classes = {}
122
+ deployment_content.each do |k, v|
123
+ if k == 'DeployFile'
124
+ v.each do |file|
125
+ read_file_class(platform, file, files, 'LocalName')
126
+ end
127
+ elsif k == 'DeployClass'
128
+ v.each do |_class|
129
+ read_file_class(platform, _class, classes, 'Name')
130
+ end
131
+ end
132
+ end
133
+ return files, classes
134
+ end
135
+
136
+ def make_deployment(files, classes)
137
+ r = []
138
+ files.each do |file, value|
139
+ value_class = value['Class']
140
+ _class = classes[value_class]
141
+ next if ['AndroidGDBServer', 'ProjectAndroidManifest'].include?(value_class)
142
+ if value_class == 'AndroidClassesDexFile'
143
+ # dirty hack for 'classes.dex'
144
+ # usually .dproj has full path to it
145
+ # but we may have another path
146
+ # so remove 'first' part
147
+ file = file.gsub(/^.+(\\lib\\android\\)/, '$(BDS)\1')
148
+ end
149
+ remote_name = value['Platform'] ? value['Platform']['RemoteName'] : file.pathmap('%f')
150
+ if value_class == 'ProjectOutput'
151
+ file = :project_so
152
+ end
153
+ r << { file => [_class['Platform']['RemoteDir'] + '\\', '1', remote_name] }
154
+ end
155
+ return r
156
+ end
157
+
158
+ public
159
+ def deploymentfiles(platform)
160
+ deployment = @content
161
+ raise 'There is no deployment info! Cannot continue.' unless deployment
162
+ ['ProjectExtensions', 'BorlandProject', 'Deployment'].each do |section|
163
+ deployment = deployment[section]
164
+ break unless deployment
165
+ end
166
+ warn "#{@file} have no deployment info" unless deployment
167
+ files, classes = read_files_and_classes(deployment, platform)
168
+ r = make_deployment(files, classes)
169
+ return r
170
+ end
99
171
  end
100
172
 
101
173
  end