delphivm 0.8.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/Thorfile.thor +2 -2
  3. data/delphivm.gemspec +1 -1
  4. data/delphivm.sublime-project +8 -0
  5. data/delphivm.sublime-workspace +453 -0
  6. data/lib/build_target.rb +84 -0
  7. data/lib/delphivm.rb +77 -137
  8. data/lib/delphivm/generator.rb +123 -0
  9. data/lib/delphivm/ide_services.rb +8 -3
  10. data/lib/delphivm/runner.rb +5 -8
  11. data/lib/delphivm/version.rb +3 -4
  12. data/lib/dvm/gen/app.thor +84 -0
  13. data/lib/dvm/ide.thor +3 -2
  14. data/lib/dvm/project.thor +1 -1
  15. data/lib/extensions.rb +1 -1
  16. data/templates/delphi/app.tt/.gitignore.tt +18 -0
  17. data/templates/delphi/app.tt/BDS.bat.tt +9 -0
  18. data/templates/delphi/app.tt/BUILD.bat.tt +19 -0
  19. data/templates/delphi/app.tt/README.md.tt +16 -0
  20. data/templates/delphi/app.tt/VERSION +1 -0
  21. data/templates/delphi/app.tt/license.txt +61 -0
  22. data/templates/delphi/app.tt/src/@D170/%{app_name}App.groupproj +45 -0
  23. data/templates/delphi/app.tt/src/source.optset +18 -0
  24. data/templates/delphi/dproj/sample.tt/samples/@D170/%{name}.dpr +12 -0
  25. data/templates/delphi/dproj/sample.tt/samples/@D170/%{name}.dproj +146 -0
  26. data/templates/delphi/dproj/src.tt/src/@D170/%{app_name}.dpr +12 -0
  27. data/templates/delphi/dproj/src.tt/src/@D170/%{app_name}.dproj +174 -0
  28. data/templates/delphi/dproj/test.tt/tests/@D170/%{name}.dpr +24 -0
  29. data/templates/delphi/dproj/test.tt/tests/@D170/%{name}.dproj +146 -0
  30. data/templates/delphi/samples.tt/samples/@D170/%{app_name}Samples.groupproj +44 -0
  31. data/templates/delphi/samples.tt/samples/samples.optset +19 -0
  32. data/templates/delphi/tests.tt/tests/@D170/%{app_name}Tests.groupproj +44 -0
  33. data/templates/delphi/tests.tt/tests/tests.optset +35 -0
  34. metadata +26 -2
@@ -0,0 +1,84 @@
1
+ class BuildTarget < Thor
2
+ attr_accessor :idetag
3
+ attr_accessor :config
4
+
5
+ INCL_BUILD = /(_|\/|\A)build(_|\/|\Z)/ # REX for recognize a build subpath
6
+
7
+ include Thor::Actions
8
+
9
+ def self.inherited(klass)
10
+ klass.source_root(ROOT)
11
+ klass.publish
12
+ end
13
+
14
+ def method_missing(name, *args, &block)
15
+ if name.to_s.match(/(\w+)_path$/)
16
+ convert_to_path $1
17
+ else
18
+ super
19
+ end
20
+ end
21
+
22
+ protected
23
+ def self.depends(*task_names)
24
+ @depends ||=[]
25
+ @depends.push(*task_names)
26
+ @depends
27
+ end
28
+
29
+ def clear_products
30
+ @products = []
31
+ end
32
+
33
+ def catch_products
34
+ @catch_products = true
35
+ yield
36
+ ensure
37
+ @catch_products = false
38
+ end
39
+
40
+ def catch_product(*prods)
41
+ @products.push(*prods)
42
+ yield *prods unless @catch_products
43
+ end
44
+
45
+ def do_clean(idetag, cfg)
46
+ catch_products do
47
+ do_make(idetag, cfg)
48
+ end
49
+ @products.each do |p|
50
+ remove_file(p)
51
+ end
52
+ end
53
+
54
+ def do_make(idetag, cfg)
55
+ end
56
+
57
+ def do_build(idetag, cfg)
58
+ invoke :clean
59
+ invoke :make
60
+ end
61
+
62
+ def self.publish
63
+ [:clean, :make, :build].each do |mth|
64
+ desc "#{mth}", "#{mth} #{self.namespace} products"
65
+ method_option :params, type: :hash, aliases: '-p', default: {:Config => 'Debug'}, desc: "more MSBuild params. See MSBuild help"
66
+ define_method mth do
67
+ msbuild_params = options[:params]
68
+ IDEServices.ideused.each do |idetag|
69
+ self.idetag = idetag
70
+ self.config = msbuild_params
71
+ self.clear_products
72
+ self.class.depends.each { |task| self.invoke "#{task}:#{mth}" }
73
+ send("do_#{mth}", idetag, msbuild_params)
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ def convert_to_path(under_scored='')
80
+ buildpath_as_str = (Pathname('out') + self.idetag + self.config[:Config]).to_s
81
+ ROOT + under_scored.to_s.split('_').join('/').gsub(INCL_BUILD, '\1' + buildpath_as_str + '\2')
82
+ end
83
+
84
+ end
data/lib/delphivm.rb CHANGED
@@ -1,137 +1,77 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'thor'
4
- require 'pathname'
5
-
6
- Delphivm = Thor
7
- class Delphivm
8
- ROOT = ::Pathname.getwd
9
- end
10
-
11
- require 'zip/zip'
12
-
13
- require 'open3'
14
- require 'nokogiri'
15
-
16
- require 'win32/registry.rb'
17
-
18
- require 'version_info'
19
- require 'open-uri'
20
- require 'net/http'
21
- require 'ruby-progressbar'
22
-
23
- require 'extensions'
24
- require 'delphivm/version'
25
- require 'delphivm/ide_services'
26
- require 'delphivm/dsl'
27
-
28
- require 'delphivm/runner'
29
-
30
- if Delphivm::ROOT == Pathname(__FILE__).dirname.parent
31
- TARGET = Object.const_get('Delphivm')
32
- else
33
- VersionInfo.file_format = :text
34
- target = Module.new
35
- target.module_exec do
36
- include VersionInfo
37
- self.VERSION.file_name = Delphivm::ROOT + 'VERSION'
38
- end
39
- Object.const_set(Delphivm::ROOT.basename.to_s.snake_case.camelize, target)
40
- target.freeze
41
- VersionInfo.install_tasks(:target => target)
42
-
43
- TARGET = Object.const_get(target.name)
44
- end
45
-
46
- module Thor::Util #:nodoc:
47
- SEARCH_ROOT = File.dirname(__FILE__)
48
- # redefine to search tasks only for this app
49
- def self.globs_for(path)
50
- ["#{SEARCH_ROOT}/dvm/*.thor", "#{Delphivm::ROOT}/dvm/*.thor"]
51
- end
52
- end
53
-
54
- class BuildTarget < Thor
55
- attr_accessor :idetag
56
- attr_accessor :config
57
-
58
- INCL_BUILD = /(_|\/|\A)build(_|\/|\Z)/ # REX for recognize a build subpath
59
-
60
- include Thor::Actions
61
-
62
- def self.inherited(klass)
63
- klass.source_root(ROOT)
64
- klass.publish
65
- end
66
-
67
- def method_missing(name, *args, &block)
68
- if name.to_s.match(/(\w+)_path$/)
69
- convert_to_path $1
70
- else
71
- super
72
- end
73
- end
74
-
75
- protected
76
- def self.depends(*task_names)
77
- @depends ||=[]
78
- @depends.push(*task_names)
79
- @depends
80
- end
81
-
82
- def clear_products
83
- @products = []
84
- end
85
-
86
- def catch_products
87
- @catch_products = true
88
- yield
89
- ensure
90
- @catch_products = false
91
- end
92
-
93
- def catch_product(*prods)
94
- @products.push(*prods)
95
- yield *prods unless @catch_products
96
- end
97
-
98
- def do_clean(idetag, cfg)
99
- catch_products do
100
- do_make(idetag, cfg)
101
- end
102
- @products.each do |p|
103
- remove_file(p)
104
- end
105
- end
106
-
107
- def do_make(idetag, cfg)
108
- end
109
-
110
- def do_build(idetag, cfg)
111
- invoke :clean
112
- invoke :make
113
- end
114
-
115
- def self.publish
116
- [:clean, :make, :build].each do |mth|
117
- desc "#{mth}", "#{mth} #{self.namespace} products"
118
- method_option :params, type: :hash, aliases: '-p', default: {:Config => 'Debug'}, desc: "more MSBuild params. See MSBuild help"
119
- define_method mth do
120
- msbuild_params = options[:params]
121
- IDEServices.ideused.each do |idetag|
122
- self.idetag = idetag
123
- self.config = msbuild_params
124
- self.clear_products
125
- self.class.depends.each { |task| self.invoke "#{task}:#{mth}" }
126
- send("do_#{mth}", idetag, msbuild_params)
127
- end
128
- end
129
- end
130
- end
131
-
132
- def convert_to_path(under_scored='')
133
- buildpath_as_str = (Pathname('out') + self.idetag + self.config[:Config]).to_s
134
- ROOT + under_scored.to_s.split('_').join('/').gsub(INCL_BUILD, '\1' + buildpath_as_str + '\2')
135
- end
136
-
137
- end
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'thor'
4
+ require 'pathname'
5
+
6
+ require 'zip/zip'
7
+
8
+ require 'open3'
9
+ require 'nokogiri'
10
+
11
+ require 'win32/registry.rb'
12
+
13
+ require 'version_info'
14
+ require 'open-uri'
15
+ require 'net/http'
16
+ require 'ruby-progressbar'
17
+
18
+ require 'extensions'
19
+
20
+ require 'build_target'
21
+
22
+ Delphivm = Thor # sure, we are hacking Thor !
23
+
24
+ class Delphivm
25
+ include(VersionInfo)
26
+
27
+ ROOT = ::Pathname.getwd
28
+ GEM_ROOT = Pathname(__FILE__).dirname.parent
29
+ EXE_NAME = File.basename($0, '.rb')
30
+
31
+ PATH_TO_VENDOR = ROOT + 'vendor'
32
+ PATH_TO_VENDOR_CACHE = PATH_TO_VENDOR + 'cache'
33
+ PATH_TO_VENDOR_IMPORTS = PATH_TO_VENDOR + 'imports'
34
+ DVM_IMPORTS_FILE = PATH_TO_VENDOR + 'imports.dvm'
35
+
36
+ module Util #:nodoc:
37
+ # redefine Thor to search tasks only for this app
38
+ def self.globs_for(path)
39
+ ["#{GEM_ROOT}/lib/dvm/**/*.thor", "#{Delphivm::ROOT}/dvm/**/*.thor"]
40
+ end
41
+ end
42
+
43
+ class Gen < Thor
44
+ namespace :gen
45
+ # used only as thor namesapce for generators
46
+ # defined here because we need ensure class Gen exist when generator tasks are loaded
47
+ desc "echo", "prueba de echo"
48
+ def echo
49
+ end
50
+ end
51
+
52
+ private
53
+ def self.create_app_module
54
+ @app_module = ::Module.new do
55
+ include VersionInfo
56
+ self.VERSION.file_name = ROOT + 'VERSION'
57
+ end
58
+ Object.const_set(ROOT.basename.to_s.snake_case.camelize, @app_module)
59
+ @app_module.freeze # force to fix then module name
60
+ end
61
+
62
+ def self.app_module
63
+ return @app_module if @app_module
64
+ if ROOT.basename.to_s.casecmp(EXE_NAME) == 0
65
+ @app_module = Delphivm
66
+ else
67
+ create_app_module
68
+ end
69
+ VersionInfo.install_tasks(:target => @app_module)
70
+ @app_module
71
+ end
72
+ public
73
+ APPMODULE = self.app_module
74
+ end
75
+
76
+ # Runner must be loaded after Delphivm setup, i.e., after Thor is hacked
77
+ require 'delphivm/runner'
@@ -0,0 +1,123 @@
1
+ class Delphivm
2
+
3
+ module Generator
4
+ TEMPLATE_ROOT = GEM_ROOT + Pathname('templates/delphi')
5
+
6
+ def self.included(base) #:nodoc:
7
+ base.send :include, Thor::Actions
8
+ base.add_runtime_options!
9
+ base.extend ClassMethods
10
+ end
11
+
12
+ module ClassMethods
13
+ def subtemplate
14
+ @subtemplate
15
+ end
16
+
17
+ def subtemplate=(value)
18
+ @subtemplate = value
19
+ end
20
+
21
+ def get_app_name
22
+ @app_name = output_folder.basename.to_s.camelize
23
+ end
24
+
25
+ def desc(*msg)
26
+ if msg.size==1
27
+ command = name.split(':')[-1].downcase
28
+ args = self.arguments.map {|arg| arg.usage }.join(' ')
29
+ # # hide from thor standard list
30
+ group(' ')
31
+ Gen.register(self, command, command + ' ' + args, *msg)
32
+ end
33
+ super *msg
34
+ end
35
+
36
+ def template_subfolder
37
+ subpath = (subtemplate.to_s.empty? ? '' : '/' + subtemplate.to_s)
38
+ @template_subfolder = self.name.split('::')[-1].snake_case + subpath + '.tt'
39
+ end
40
+
41
+ def output_folder
42
+ @output_folder ||= ROOT
43
+ end
44
+
45
+ def output_folder=(value)
46
+ @output_folder = Pathname(value.to_s)
47
+ end
48
+
49
+ def source_root
50
+ TEMPLATE_ROOT + self.template_subfolder
51
+ end
52
+ end
53
+
54
+ def method_missing(name, *args, &block)
55
+ binding_params.has_key?(name) ? binding_params[name] : super
56
+ end
57
+
58
+ def do_folder_template(folder)
59
+ empty_directory folder
60
+ end
61
+
62
+ def do_file_template(source, target)
63
+ template(source, target.dirname + target.basename('.tt'))
64
+ rescue Exception => e
65
+ say "task #{self.class.namespace} proccessing template #{source}", :red
66
+ say "ERROR: #{e.message}", :red
67
+ say "avaiable params:\n", :red
68
+ print_table(binding_params.inject({}){|r,p| r[":#{p[0]} => "] = p[1];r}.to_a)
69
+ raise ""
70
+ end
71
+
72
+ def skip_template_item?(item, directory)
73
+ if directory && item.to_s =~ /@(.+)/
74
+ ($1 != binding_params[:idever])
75
+ else
76
+ false
77
+ end
78
+ end
79
+
80
+ def do_execute
81
+ self.class.source_root.glob('**/*') do |f|
82
+ source = f.relative_path_from(self.class.source_root)
83
+ target = self.class.output_folder + source
84
+
85
+ next if skip_template_item?(source, f.directory?)
86
+
87
+ target = Pathname(target.to_s.gsub('@','') % binding_params)
88
+ if f.directory?
89
+ do_folder_template target
90
+ else
91
+ do_file_template(source, target)
92
+ end
93
+ end
94
+ end
95
+
96
+ def binding_params
97
+ return @binding_params if @binding_params
98
+ @binding_params = {app_name: self.class.get_app_name}
99
+ options.each do |k, v|
100
+ @binding_params[k.to_sym] = v
101
+ end
102
+ self.class.arguments.each do |arg|
103
+ @binding_params[arg.name.to_sym] = self.send(arg.name)
104
+ end
105
+ @binding_params
106
+ end
107
+
108
+ def do_invoke(*names, &block)
109
+ propagate_thor_runtime_options(*names)
110
+ klass = names[0]
111
+ klass.output_folder = self.class.output_folder
112
+ invoke(*names, &block)
113
+ end
114
+
115
+ def propagate_thor_runtime_options(*names)
116
+ names[2] ||= {} # ensure we have options hash
117
+ %w(force pretend quiet skip).each do |rt_opt|
118
+ names[2][rt_opt] = options[rt_opt] if options.has_key?(rt_opt)
119
+ end
120
+ end
121
+ end
122
+
123
+ end
@@ -21,7 +21,8 @@ class Delphivm
21
21
  'D100' => {regkey: 'Software\Borland\BDS\4.0', name: '2006', desc: 'Borland Developer Stuido 4.0'},
22
22
  'D150' => {regkey: 'Software\Embarcadero\BDS\8.0', name: 'XE', desc: 'Embarcadero RAD Stuido XE'},
23
23
  'D160' => {regkey: 'Software\Embarcadero\BDS\9.0', name: 'XE2', desc: 'Embarcadero RAD Stuido XE2'},
24
- 'D170' => {regkey: 'Software\Embarcadero\BDS\10.0', name: 'XE3', desc: 'Embarcadero RAD Stuido XE3'}
24
+ 'D170' => {regkey: 'Software\Embarcadero\BDS\10.0', name: 'XE3', desc: 'Embarcadero RAD Stuido XE3'},
25
+ 'D180' => {regkey: 'Software\Embarcadero\BDS\11.0', name: 'XE4', desc: 'Embarcadero RAD Stuido XE4'}
25
26
  }
26
27
 
27
28
  def self.idelist
@@ -30,6 +31,10 @@ class Delphivm
30
31
  result.sort.reverse
31
32
  end
32
33
 
34
+ def self.default_ide
35
+ self.idelist.first
36
+ end
37
+
33
38
  def self.ideused
34
39
  #TODO ensure we return only ides listed at IDEInfos
35
40
  ROOT.glob("{src,samples}/**/*.{#{GROUP_FILE_EXT.join(',')}}").map {|f| f.dirname.basename.to_s.split('-')[0]}.uniq.sort
@@ -44,7 +49,7 @@ class Delphivm
44
49
  new_path = ide_paths(ide_tag.upcase).map{ |p| p + 'bin' }.first
45
50
  path.unshift new_path
46
51
  path = path.join(';')
47
- self.winpath= path
52
+ self.winpath = path
48
53
  return new_path
49
54
  end
50
55
 
@@ -59,7 +64,7 @@ class Delphivm
59
64
  end
60
65
 
61
66
  def set_env
62
- ENV["PATH"] = '$(BDSCOMMONDIR)\bpl;' + ENV["PATH"]
67
+ ENV["PATH"] = '$(BDSCOMMONDIR)\bpl;' + ENV["PATH"]
63
68
  ENV["PATH"] = self['RootDir'] + 'bin;' + ENV["PATH"]
64
69
  ENV["BDSPROJECTGROUPDIR"] = workdir.win
65
70
  ENV["IDEVERSION"] = idever