bake-toolkit 2.13.1 → 2.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/documentation/_build/html/_sources/changelog.txt +7 -0
  3. data/documentation/_build/html/_sources/index.txt +1 -1
  4. data/documentation/_build/html/_sources/syntax/adapt_configs.txt +143 -0
  5. data/documentation/_build/html/_sources/syntax/derive_configs.txt +48 -60
  6. data/documentation/_build/html/_sources/syntax/syntax.txt +1 -0
  7. data/documentation/_build/html/_static/syntax.html +9 -6
  8. data/documentation/_build/html/changelog.html +14 -4
  9. data/documentation/_build/html/commandline/commandline.html +6 -6
  10. data/documentation/_build/html/concepts/build_hierarchy.html +4 -4
  11. data/documentation/_build/html/concepts/concepts.html +4 -4
  12. data/documentation/_build/html/concepts/the_main_project.html +4 -4
  13. data/documentation/_build/html/concepts/the_project_meta_file.html +4 -4
  14. data/documentation/_build/html/genindex.html +4 -4
  15. data/documentation/_build/html/ide/eclipse/eclipse.html +4 -4
  16. data/documentation/_build/html/ide/eclipse/how_to_convert_existing_cdt_workspace.html +4 -4
  17. data/documentation/_build/html/ide/eclipse/how_to_create_a_new_project_in_eclipse.html +4 -4
  18. data/documentation/_build/html/ide/eclipse/how_to_create_a_workspace_in_eclipse.html +4 -4
  19. data/documentation/_build/html/ide/eclipse/how_to_install_eclipse_plugin.html +4 -4
  20. data/documentation/_build/html/ide/eclipse/how_to_use_bake_in_eclipse.html +4 -4
  21. data/documentation/_build/html/ide/ide_integrations.html +4 -4
  22. data/documentation/_build/html/ide/vs/how_to_create_vs_projects.html +4 -4
  23. data/documentation/_build/html/ide/vs/how_to_debug_in_vs.html +4 -4
  24. data/documentation/_build/html/ide/vs/how_to_used_bake_in_vs.html +4 -4
  25. data/documentation/_build/html/ide/vs/vs.html +4 -4
  26. data/documentation/_build/html/ide/vs/vs_install.html +4 -4
  27. data/documentation/_build/html/index.html +8 -7
  28. data/documentation/_build/html/install/install_bake.html +4 -4
  29. data/documentation/_build/html/internal.html +4 -4
  30. data/documentation/_build/html/known_issues.html +4 -4
  31. data/documentation/_build/html/license.html +4 -4
  32. data/documentation/_build/html/performance/performance.html +4 -4
  33. data/documentation/_build/html/quickstart/quickstart.html +4 -4
  34. data/documentation/_build/html/search.html +4 -4
  35. data/documentation/_build/html/searchindex.js +1 -1
  36. data/documentation/_build/html/syntax/adapt_configs.html +287 -0
  37. data/documentation/_build/html/syntax/derive_configs.html +57 -116
  38. data/documentation/_build/html/syntax/project_meta_syntax.html +13 -10
  39. data/documentation/_build/html/syntax/syntax.html +11 -4
  40. data/documentation/_build/html/syntax/variable_substitutions.html +4 -4
  41. data/documentation/_build/html/tips_and_tricks/how_to_use_bake_with_cygwin.html +4 -4
  42. data/documentation/_build/html/tips_and_tricks/static_code_analysis.html +4 -4
  43. data/documentation/_build/html/tips_and_tricks/the_bakery.html +4 -4
  44. data/documentation/_build/html/tips_and_tricks/the_clang.html +4 -4
  45. data/documentation/_build/html/tips_and_tricks/tips_and_tricks.html +4 -4
  46. data/documentation/_build/html/why_bake/why_bake.html +6 -6
  47. data/lib/adapt/config/loader.rb +111 -0
  48. data/lib/bake/cache.rb +25 -1
  49. data/lib/bake/config/checks.rb +61 -0
  50. data/lib/bake/config/loader.rb +41 -40
  51. data/lib/bake/libElement.rb +54 -55
  52. data/lib/bake/mergeConfig.rb +170 -154
  53. data/lib/bake/model/language.rb +2 -4
  54. data/lib/bake/model/metamodel.rb +31 -19
  55. data/lib/bake/model/metamodel_ext.rb +4 -1
  56. data/lib/bake/options/options.rb +12 -3
  57. data/lib/bake/options/usage.rb +1 -0
  58. data/lib/blocks/block.rb +0 -4
  59. data/lib/blocks/blockBase.rb +2 -1
  60. data/lib/blocks/compile.rb +5 -5
  61. data/lib/blocks/makefile.rb +1 -1
  62. data/lib/blocks/showIncludes.rb +13 -2
  63. data/lib/common/version.rb +3 -3
  64. data/lib/tocxx.rb +7 -2
  65. metadata +10 -6
data/lib/bake/cache.rb CHANGED
@@ -2,6 +2,7 @@ require 'common/exit_helper'
2
2
  require 'bake/toolchain/colorizing_formatter'
3
3
  require 'common/options/parser'
4
4
  require 'common/version'
5
+ require 'adapt/config/loader'
5
6
 
6
7
  module Bake
7
8
 
@@ -15,6 +16,7 @@ module Bake
15
16
  attr_accessor :exclude_filter
16
17
  attr_accessor :no_autodir
17
18
  attr_accessor :build_config
19
+ attr_accessor :adapt_filenames
18
20
  end
19
21
 
20
22
  class CacheAccess
@@ -83,6 +85,23 @@ module Bake
83
85
  end
84
86
  end
85
87
  end
88
+
89
+ if (cache != nil)
90
+ if (not AdaptConfig.filenames.eql?(cache.adapt_filenames))
91
+ Bake.formatter.printInfo("Info: adapt config filenames have been changed, reloading meta information")
92
+ cache = nil
93
+ end
94
+ end
95
+
96
+ if (cache != nil and not AdaptConfig.filenames.empty?)
97
+ AdaptConfig.filenames.each do |f|
98
+ adaptTime = File.mtime(f)
99
+ if adaptTime > cacheTime + 1
100
+ Bake.formatter.printInfo("Info: #{f} has been changed, reloading meta information")
101
+ cache = nil
102
+ end
103
+ end
104
+ end
86
105
 
87
106
  if cache != nil
88
107
  if cache.workspace_roots.length == Bake.options.roots.length
@@ -115,8 +134,12 @@ module Bake
115
134
  else
116
135
  Bake.formatter.printInfo("Info: cache not found, reloading meta information")
117
136
  end
118
- rescue Exception
137
+ rescue Exception => e
119
138
  Bake.formatter.printWarning("Warning: cache file corrupt, reloading meta information (cache might be written by an older bake version)")
139
+ if Bake.options.debug
140
+ puts e.message
141
+ puts e.backtrace
142
+ end
120
143
  cache = nil
121
144
  end
122
145
 
@@ -140,6 +163,7 @@ module Bake
140
163
  cache.exclude_filter = Bake.options.exclude_filter
141
164
  cache.workspace_roots = Bake.options.roots
142
165
  cache.build_config = Bake.options.build_config
166
+ cache.adapt_filenames = AdaptConfig.filenames
143
167
  bbdump = Marshal.dump(cache)
144
168
  begin
145
169
  File.delete(@cacheFilename)
@@ -0,0 +1,61 @@
1
+ module Bake
2
+ module Configs
3
+
4
+ class Checks
5
+
6
+ def self.symlinkCheck(filename)
7
+ dirOfProjMeta = File.dirname(filename)
8
+ Dir.chdir(dirOfProjMeta) do
9
+ if Dir.pwd != dirOfProjMeta and File.dirname(Dir.pwd) != File.dirname(dirOfProjMeta)
10
+ isSym = false
11
+ begin
12
+ isSym = File.symlink?(dirOfProjMeta)
13
+ rescue
14
+ end
15
+ if isSym
16
+ Bake.formatter.printError("Symlinks only allowed with the same parent dir as the target: #{dirOfProjMeta} --> #{Dir.pwd}", filename)
17
+ ExitHelper.exit(1)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ def self.commonMetamodelCheck(configs, filename)
24
+
25
+ if configs.length == 0
26
+ Bake.formatter.printError("No config found", filename)
27
+ ExitHelper.exit(1)
28
+ end
29
+
30
+ configs.each do |config|
31
+ if config.respond_to?("toolchain") and config.toolchain
32
+ config.toolchain.compiler.each do |c|
33
+ if not c.internalDefines.nil? and c.internalDefines != ""
34
+ Bake.formatter.printError("InternalDefines only allowed in DefaultToolchain", c.internalDefines)
35
+ ExitHelper.exit(1)
36
+ end
37
+ end
38
+ end
39
+
40
+ config.includeDir.each do |inc|
41
+ if not ["front", "back", ""].include?inc.inject
42
+ Bake.formatter.printError("inject of IncludeDir must be 'front' or 'back'", inc)
43
+ ExitHelper.exit(1)
44
+ end
45
+ if not ["front", "back", ""].include?inc.infix
46
+ Bake.formatter.printError("infix of IncludeDir must be 'front' or 'back'", inc)
47
+ ExitHelper.exit(1)
48
+ end
49
+ if (inc.infix != "" and inc.inject != "")
50
+ Bake.formatter.printError("IncludeDir must have inject OR infix (deprecated)", inc)
51
+ ExitHelper.exit(1)
52
+ end
53
+ end if config.respond_to?("includeDir")
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+ end
@@ -1,11 +1,12 @@
1
1
  require 'bake/model/loader'
2
+ require 'bake/config/checks'
2
3
 
3
4
  module Bake
4
5
 
5
6
  class Config
6
7
  attr_reader :referencedConfigs
7
8
 
8
- def getFullProject(configs, configname) # note: configs is never empty
9
+ def getFullProjectInternal(configs, configname, isMain) # note: configs is never empty
9
10
 
10
11
  if (configname == "")
11
12
  if configs[0].parent.default != ""
@@ -33,8 +34,24 @@ module Bake
33
34
  end
34
35
 
35
36
  if config.extends != ""
36
- parent,parentConfigName = getFullProject(configs, config.extends)
37
- MergeConfig.new(config, parent).merge()
37
+ parent,parentConfigName = getFullProjectInternal(configs, config.extends, isMain)
38
+ MergeConfig.new(config, parent).merge(:merge)
39
+ end
40
+
41
+ [config, configname]
42
+ end
43
+
44
+ def getFullProject(configs, configname, isMain)
45
+ config, configname = getFullProjectInternal(configs, configname, isMain)
46
+
47
+
48
+ # check if config has to be manipulated
49
+ @adaptConfigs.each do |c|
50
+ if c.project == config.parent.name or (isMain and c.project == "__MAIN__") or c.project == "__ALL__"
51
+ if c.name == config.name or (isMain and c.name == "__MAIN__") or c.name == "__ALL__"
52
+ MergeConfig.new(c, config).merge(c.type.to_sym)
53
+ end
54
+ end
38
55
  end
39
56
 
40
57
  [config, configname]
@@ -98,7 +115,7 @@ module Bake
98
115
 
99
116
  def loadProjMeta(filename)
100
117
 
101
- symlinkCheck(filename)
118
+ Bake::Configs::Checks.symlinkCheck(filename)
102
119
 
103
120
  @project_files << filename
104
121
  f = @loader.load(filename)
@@ -109,43 +126,25 @@ module Bake
109
126
  Bake.formatter.printError("Config file must have exactly one 'Project' element as root element", filename)
110
127
  ExitHelper.exit(1)
111
128
  end
112
-
113
- reqVersion = f.root_elements[0].getRequiredBakeVersion
129
+ proj = f.root_elements[0]
114
130
 
131
+ reqVersion = proj.getRequiredBakeVersion
115
132
  checkVer(reqVersion)
116
133
 
117
- configs = f.root_elements[0].getConfig
134
+ configs = proj.getConfig
135
+ Bake::Configs::Checks::commonMetamodelCheck(configs, filename)
118
136
 
119
- if configs.length == 0
120
- Bake.formatter.printError("No config found", filename)
121
- ExitHelper.exit(1)
122
- end
123
-
124
- configs.each do |config|
125
- if config.respond_to?("toolchain") and config.toolchain
126
- config.toolchain.compiler.each do |c|
127
- if not c.internalDefines.nil? and c.internalDefines != ""
128
- Bake.formatter.printError("InternalDefines only allowed in DefaultToolchain", c.internalDefines)
129
- ExitHelper.exit(1)
130
- end
131
- end
137
+ configs.each do |c|
138
+ if not c.project.empty?
139
+ Bake.formatter.printError("Attribute 'project' must only be used in adapt config.",c)
140
+ ExitHelper.exit(1)
141
+ end
142
+ if not c.type.empty?
143
+ Bake.formatter.printError("Attribute 'type' must only be used in adapt config.",c)
144
+ ExitHelper.exit(1)
132
145
  end
133
-
134
- config.includeDir.each do |inc|
135
- if not ["front", "back", ""].include?inc.inject
136
- Bake.formatter.printError("inject of IncludeDir must be 'front' or 'back'", inc)
137
- ExitHelper.exit(1)
138
- end
139
- if not ["front", "back", ""].include?inc.infix
140
- Bake.formatter.printError("infix of IncludeDir must be 'front' or 'back'", inc)
141
- ExitHelper.exit(1)
142
- end
143
- if (inc.infix != "" and inc.inject != "")
144
- Bake.formatter.printError("IncludeDir must have inject OR infix (deprecated)", inc)
145
- ExitHelper.exit(1)
146
- end
147
- end if config.respond_to?("includeDir")
148
146
  end
147
+
149
148
  configs
150
149
  end
151
150
 
@@ -204,7 +203,7 @@ module Bake
204
203
  end
205
204
 
206
205
  # get config
207
- config, dep.config = getFullProject(@loadedConfigs[dep_name], dep.config)
206
+ config, dep.config = getFullProject(@loadedConfigs[dep_name], dep.config, false)
208
207
  dep.name = dep_name
209
208
 
210
209
  # config not referenced yet
@@ -237,7 +236,7 @@ module Bake
237
236
  ConfigNames.print(configs, nil, mainMeta)
238
237
  end
239
238
 
240
- config, Bake.options.build_config = getFullProject(configs,Bake.options.build_config)
239
+ config, Bake.options.build_config = getFullProject(configs,Bake.options.build_config, true)
241
240
  @referencedConfigs = {}
242
241
  @referencedConfigs[Bake.options.main_project_name] = [config]
243
242
 
@@ -257,10 +256,10 @@ module Bake
257
256
  r = r + Bake.options.main_project_name # glob would not work otherwise on windows (ruby bug?)
258
257
  end
259
258
  r = r+"/**{,/*/**}/Project.meta"
260
- @potentialProjs.concat(Dir.glob(r))
259
+ @potentialProjs.concat(Dir.glob(r).sort)
261
260
  end
262
261
 
263
- @potentialProjs = @potentialProjs.uniq.sort
262
+ @potentialProjs = @potentialProjs.uniq
264
263
  end
265
264
 
266
265
 
@@ -297,7 +296,9 @@ module Bake
297
296
  end
298
297
  end
299
298
 
300
- def load()
299
+ def load(adaptConfigs)
300
+ @adaptConfigs = adaptConfigs
301
+
301
302
  @loader = Loader.new
302
303
  cache = CacheAccess.new()
303
304
  @referencedConfigs = cache.load_cache unless Bake.options.nocache
@@ -59,30 +59,28 @@ module Bake
59
59
  end
60
60
  end
61
61
 
62
- block.lib_elements.each_key.sort.each do |line_num|
63
- block.lib_elements[line_num].each do |elem|
62
+ block.lib_elements.each do |elem|
64
63
 
65
- case elem.type
66
- when LibElement::LIB
67
- @@linker_libs_array << "#{@@linker[:LIB_FLAG]}#{elem.value}"
68
- when LibElement::USERLIB
69
- @@linker_libs_array << "#{@@linker[:USER_LIB_FLAG]}#{elem.value}"
70
- when LibElement::LIB_WITH_PATH
71
- adaptedPath, prefix = adaptPath(elem.value, block, prefix)
72
- @@linker_libs_array << adaptedPath
73
- when LibElement::SEARCH_PATH
74
- adaptedPath, prefix = adaptPath(elem.value, block, prefix)
75
- if not @@lib_path_set.include?adaptedPath
76
- @@lib_path_set << adaptedPath
77
- @@linker_libs_array << "#{@@linker[:LIB_PATH_FLAG]}#{adaptedPath}" if @@linker[:LIST_MODE] == false
78
- end
79
- when LibElement::DEPENDENCY
80
- if Blocks::ALL_BLOCKS.include?elem.value
81
- bb = Blocks::ALL_BLOCKS[elem.value]
82
- collect_recursive(bb)
83
- else
84
- # TODO: warning or error?
85
- end
64
+ case elem.type
65
+ when LibElement::LIB
66
+ @@linker_libs_array << "#{@@linker[:LIB_FLAG]}#{elem.value}"
67
+ when LibElement::USERLIB
68
+ @@linker_libs_array << "#{@@linker[:USER_LIB_FLAG]}#{elem.value}"
69
+ when LibElement::LIB_WITH_PATH
70
+ adaptedPath, prefix = adaptPath(elem.value, block, prefix)
71
+ @@linker_libs_array << adaptedPath
72
+ when LibElement::SEARCH_PATH
73
+ adaptedPath, prefix = adaptPath(elem.value, block, prefix)
74
+ if not @@lib_path_set.include?adaptedPath
75
+ @@lib_path_set << adaptedPath
76
+ @@linker_libs_array << "#{@@linker[:LIB_PATH_FLAG]}#{adaptedPath}" if @@linker[:LIST_MODE] == false
77
+ end
78
+ when LibElement::DEPENDENCY
79
+ if Blocks::ALL_BLOCKS.include?elem.value
80
+ bb = Blocks::ALL_BLOCKS[elem.value]
81
+ collect_recursive(bb)
82
+ else
83
+ # TODO: warning or error?
86
84
  end
87
85
  end
88
86
  end
@@ -92,42 +90,43 @@ module Bake
92
90
 
93
91
 
94
92
  def self.calcLibElements(block)
95
- lib_elements = {} # key = line number, value = array pairs [type, name/path string]
96
-
97
- block.config.userLibrary.each do |l|
98
- ln = l.lib
99
- ls = nil
100
- if l.lib.include?("/")
101
- pos = l.lib.rindex("/")
102
- ls = block.convPath(l.lib[0..pos-1], l)
103
- ln = l.lib[pos+1..-1]
104
- end
105
- lib_elements[l.line_number] = ls.nil? ? [] : [LibElement.new(LibElement::SEARCH_PATH, ls)]
106
- lib_elements[l.line_number] << LibElement.new(LibElement::USERLIB, ln)
107
- end
93
+ lib_elements = [] # value = array pairs [type, name/path string]
108
94
 
109
- block.config.exLib.each do |exLib|
110
- ln = exLib.name
111
- ls = nil
112
- if exLib.name.include?("/")
113
- pos = exLib.name.rindex("/")
114
- ls = block.convPath(exLib.name[0..pos-1], exLib)
115
- ln = exLib.name[pos+1..-1]
116
- end
117
- if exLib.search
118
- lib_elements[exLib.line_number] = ls.nil? ? [] : [LibElement.new(LibElement::SEARCH_PATH, ls)]
119
- lib_elements[exLib.line_number] << LibElement.new(LibElement::LIB, ln)
120
- else
121
- ln = ls + "/" + ln unless ls.nil?
122
- lib_elements[exLib.line_number] = [LibElement.new(LibElement::LIB_WITH_PATH, ln)]
95
+ block.config.libStuff.each do |l|
96
+
97
+ if (Metamodel::UserLibrary === l)
98
+ ln = l.name
99
+ ls = nil
100
+ if l.name.include?("/")
101
+ pos = l.name.rindex("/")
102
+ ls = block.convPath(l.name[0..pos-1], l)
103
+ ln = l.name[pos+1..-1]
104
+ end
105
+ lib_elements << LibElement.new(LibElement::SEARCH_PATH, ls) if !ls.nil?
106
+ lib_elements << LibElement.new(LibElement::USERLIB, ln)
107
+ elsif (Metamodel::ExternalLibrarySearchPath === l)
108
+ lib_elements << LibElement.new(LibElement::SEARCH_PATH, block.convPath(l))
109
+ elsif (Metamodel::ExternalLibrary === l)
110
+ ln = l.name
111
+ ls = nil
112
+ if l.name.include?("/")
113
+ pos = l.name.rindex("/")
114
+ ls = block.convPath(l.name[0..pos-1], l)
115
+ ln = l.name[pos+1..-1]
116
+ end
117
+ if l.search
118
+ lib_elements << LibElement.new(LibElement::SEARCH_PATH, ls) if !ls.nil?
119
+ lib_elements << LibElement.new(LibElement::LIB, ln)
120
+ else
121
+ ln = ls + "/" + ln unless ls.nil?
122
+ lib_elements << LibElement.new(LibElement::LIB_WITH_PATH, ln)
123
+ end
124
+ elsif (Metamodel::Dependency === l)
125
+ lib_elements << LibElement.new(LibElement::DEPENDENCY, l.name+","+l.config)
123
126
  end
124
- end
125
-
126
- block.config.exLibSearchPath.each do |exLibSP|
127
- lib_elements[exLibSP.line_number] = [LibElement.new(LibElement::SEARCH_PATH, block.convPath(exLibSP))]
127
+
128
128
  end
129
129
 
130
- block.config.dependency.each { |dep| lib_elements[dep.line_number] = [LibElement.new(LibElement::DEPENDENCY, dep.name+","+dep.config)]}
131
130
  return lib_elements
132
131
  end
133
132
 
@@ -1,3 +1,5 @@
1
+ require 'rtext/serializer'
2
+
1
3
  module Bake
2
4
 
3
5
  class MergeConfig
@@ -7,181 +9,195 @@ module Bake
7
9
  @parent = parent
8
10
  end
9
11
 
10
- def mergeToolchain(pt,ct, isDefault)
11
- pt.compiler.each do |pc|
12
- found = false
13
- ct.compiler.each do |cc|
14
- if cc.ctype == pc.ctype
15
- found = true
16
- cc.setFlags(clone(pc.flags) + cc.flags)
17
- cc.setDefine(clone(pc.define) + cc.define)
18
- if cc.internalDefines.nil? and not pc.internalDefines.nil?
19
- cc.setInternalDefines(clone(pc.internalDefines))
20
- end
21
- if cc.command == "" and pc.command != ""
22
- cc.setCommand(clone(pc.command))
23
- end
24
- end
25
- end
26
- ct.addCompiler(pc) if not found
12
+ def clone(obj)
13
+ if obj.is_a?(Metamodel::ModelElement)
14
+ cloneModelElement(obj)
15
+ elsif Array === obj
16
+ obj.map { |o| clone(o) }
17
+ else
18
+ obj # no clone, should not happen
27
19
  end
28
-
29
- if not pt.archiver.nil?
30
- if (ct.archiver.nil?)
31
- ct.setArchiver(clone(pt.archiver))
32
- else
33
- if ct.archiver.command == "" and pt.archiver.command != ""
34
- ct.archiver.setCommand(clone(pt.archiver.command))
35
- end
36
- ct.archiver.setFlags(clone(pt.archiver.flags) + ct.archiver.flags)
37
- end
38
- end
39
-
40
- if not pt.linker.nil?
41
- if (ct.linker.nil?)
42
- ct.setLinker(clone(pt.linker))
43
- else
44
- if ct.linker.command == "" and pt.linker.command != ""
45
- ct.linker.setCommand(clone(pt.linker.command))
20
+ end
21
+
22
+ def cloneModelElement(obj)
23
+ cpy = obj.class.new
24
+ cpy.file_name = obj.file_name
25
+ obj.class.ecore.eAllStructuralFeatures.each do |f|
26
+ value = obj.getGeneric(f.name)
27
+ if f.is_a?(RGen::ECore::EReference) && f.containment
28
+ if value.is_a?(Array)
29
+ cpy.setGeneric(f.name, value.collect{|v| clone(v)})
30
+ elsif !value.nil?
31
+ cpy.setGeneric(f.name, clone(value))
46
32
  end
47
- ct.linker.setFlags(clone(pt.linker.flags) + ct.linker.flags)
48
- ct.linker.setLibprefixflags(clone(pt.linker.libprefixflags) + ct.linker.libprefixflags)
49
- ct.linker.setLibpostfixflags(clone(pt.linker.libpostfixflags) + ct.linker.libpostfixflags)
33
+ elsif f.is_a?(RGen::ECore::EAttribute)
34
+ cpy.setGeneric(f.name, value) if obj.eIsSet(f.name)
50
35
  end
51
- end
52
-
53
- if ct.outputDir == "" and pt.outputDir != ""
54
- ct.setOutputDir(clone(pt.outputDir))
55
36
  end
56
-
57
- if ct.docu.nil? and not pt.docu.nil?
58
- ct.setDocu(clone(pt.docu))
59
- end
60
-
61
- ct.setLintPolicy(clone(pt.lintPolicy) + ct.lintPolicy)
62
-
63
- if (isDefault)
64
- if ct.basedOn == "" and pt.basedOn != ""
65
- ct.setBasedOn(clone(pt.basedOn))
66
- end
67
- if pt.eclipseOrder # is that a good idea?
68
- ct.setEclipseOrder(clone(pt.eclipseOrder))
37
+ cpy
38
+ end
39
+
40
+
41
+ def replace()
42
+ @child.class.ecore.eAllReferences.each do |f|
43
+ next unless @parent.class.ecore.eAllReferences.include?f
44
+ next unless f.containment
45
+ childData = @child.getGeneric(f.name)
46
+ if Metamodel::ModelElement === childData
47
+ @parent.setGeneric(f.name,childData) if !childData.nil?
48
+ elsif Array === childData
49
+ if !childData.empty?
50
+ parentData = @parent.getGeneric(f.name)
51
+ cclasses = childData.map { |c| c.class }.uniq
52
+ parentData.delete_if { |p| cclasses.include?p.class }
53
+ parentData += childData
54
+ @parent.setGeneric(f.name,parentData)
55
+ end
69
56
  end
70
- if ct.internalIncludes.nil? and not pt.internalIncludes.nil?
71
- ct.setInternalIncludes(clone(pt.internalIncludes))
72
- end
73
57
  end
74
-
75
58
  end
76
59
 
77
- def manipulateLineNumbers(ar)
78
- ar.each { |l| l.line_number -= 100000 }
60
+ def hasSubNodes(elem)
61
+ elem.class.ecore.eAllReferences.each do |f|
62
+ next unless f.containment
63
+ elemData = elem.getGeneric(f.name)
64
+ return true if (Array === elemData && !elemData.empty?)
65
+ return true if (Metamodel::ModelElement === elemData)
66
+ end
67
+ false
79
68
  end
80
-
81
- def clone(obj)
82
- return obj.map {|o| o.dup} if Array === obj
83
- return obj.dup
69
+
70
+ def sameAttr(childData, parentData)
71
+ childData.class.ecore.eAllAttributes.all? { |a|
72
+ a.eAnnotations.each do |x| x.details.each do |y|
73
+ return true if (y.key == :internal and y.value == true)
74
+ end; end
75
+ a.name == "line_number" || (not childData.eIsSet(a.name)) || (childData.getGeneric(a.name) == parentData.getGeneric(a.name))
76
+ }
84
77
  end
85
78
 
86
- def merge()
87
-
88
- # Valid for all config types
89
-
90
- deps = clone(@parent.dependency)
91
- @child.dependency.each do |cd|
92
- deps << cd if deps.none? {|pd| pd.name == cd.name and pd.config == cd.config }
93
- end
94
- @child.setDependency(deps)
95
-
96
- @child.setSet(clone(@parent.set) + @child.set)
97
-
98
- cExLib = clone(@parent.exLib)
99
- cExLibSearchPath = clone(@parent.exLibSearchPath)
100
- cUserLibrary = clone(@parent.userLibrary)
101
- manipulateLineNumbers(cExLib)
102
- manipulateLineNumbers(cExLibSearchPath)
103
- manipulateLineNumbers(cUserLibrary)
104
-
105
- @child.setExLib(cExLib + @child.exLib)
106
- @child.setExLibSearchPath(cExLibSearchPath + @child.exLibSearchPath)
107
- @child.setUserLibrary(cUserLibrary + @child.userLibrary)
108
-
109
- if not @parent.startupSteps.nil?
110
- if (@child.startupSteps.nil?)
111
- @child.setStartupSteps(clone(@parent.startupSteps))
112
- else
113
- @child.startupSteps.setStep(clone(@parent.startupSteps.step) + @child.startupSteps.step)
114
- end
115
- end
116
-
117
- if not @parent.preSteps.nil?
118
- if (@child.preSteps.nil?)
119
- @child.setPreSteps(clone(@parent.preSteps))
120
- else
121
- @child.preSteps.setStep(clone(@parent.preSteps.step) + @child.preSteps.step)
122
- end
123
- end
79
+ def removeChilds(childElem, parentElem)
80
+ return if childElem.nil? or parentElem.nil?
124
81
 
125
- if not @parent.postSteps.nil?
126
- if (@child.postSteps.nil?)
127
- @child.setPostSteps(clone(@parent.postSteps))
128
- else
129
- @child.postSteps.setStep(clone(@parent.postSteps.step) + @child.postSteps.step)
130
- end
131
- end
132
-
133
- if not @parent.exitSteps.nil?
134
- if (@child.exitSteps.nil?)
135
- @child.setExitSteps(clone(@parent.exitSteps))
136
- else
137
- @child.exitSteps.setStep(clone(@parent.exitSteps.step) + @child.exitSteps.step)
82
+ childElem.class.ecore.eAllReferences.each do |f|
83
+ next unless f.containment
84
+ childData = childElem.getGeneric(f.name)
85
+ parentData = parentElem.getGeneric(f.name)
86
+ next if childData.nil? or parentData.nil?
87
+ if (Array === childData)
88
+ if !parentData.empty? && !childData.empty?
89
+ childData.each do |c|
90
+ cN = hasSubNodes(c)
91
+ toRemove = []
92
+ parentData.each do |p|
93
+ next if p.class != c.class
94
+ if (not cN)
95
+ if sameAttr(c, p)
96
+ toRemove << p
97
+ end
98
+ else
99
+ removeChilds(c, p);
100
+ end
101
+ end
102
+ toRemove.each do |r|
103
+ parentElem.removeGeneric(f.name, r)
104
+ end
105
+ end
106
+ end
107
+ elsif Metamodel::ModelElement === childData
108
+ if parentData.class == childData.class && sameAttr(childData, parentData)
109
+ cN = hasSubNodes(childData)
110
+ if (not cN)
111
+ parentElem.setGeneric(f.name, nil)
112
+ else
113
+ removeChilds(childData, parentData)
114
+ end
115
+ end # otherwise not equal, will not be deleted
138
116
  end
139
117
  end
140
-
141
- pt = @parent.defaultToolchain
142
- ct = @child.defaultToolchain
118
+ end
119
+
120
+ def extendAttributes(childData, parentData)
121
+ parentData.class.ecore.eAllAttributes.each do |a|
122
+ childData.setGeneric(a.name, parentData.getGeneric(a.name)) if !childData.eIsSet(a.name) && parentData.eIsSet(a.name)
123
+ end
124
+ end
125
+
126
+ def extend(child, parent)
127
+ (parent.class.ecore.eAllReferences & child.class.ecore.eAllReferences).each do |f|
128
+ next unless f.containment
129
+ parentData = parent.getGeneric(f.name)
130
+ next if parentData.nil? or (Array === parentData && parentData.empty?)
131
+ childData = child.getGeneric(f.name)
132
+
133
+ if Array === parentData
134
+ if f.name == "compiler"
135
+ extendedParentData = []
136
+ parentData.each do |p|
137
+ c = childData.find { |c| p.ctype == c.ctype }
138
+ if c
139
+ extendAttributes(c, p)
140
+ extend(c, p)
141
+ extendedParentData << c
142
+ else
143
+ extendedParentData << p
144
+ end
145
+ end
146
+ restOfChildData = childData.find_all { |c| parentData.find {|p| p.ctype != c.ctype } }
147
+ child.setGeneric(f.name, extendedParentData + restOfChildData)
148
+ else
149
+ child.setGeneric(f.name, parentData + childData)
150
+ end
151
+ elsif Metamodel::ModelElement === parentData
152
+ if childData.nil? || childData.class != parentData.class
153
+ child.setGeneric(f.name, parentData)
154
+ else
155
+ extendAttributes(childData, parentData)
156
+ extend(childData, parentData)
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ def copyChildToParent(c, p)
163
+ (p.class.ecore.eAllReferences & c.class.ecore.eAllReferences).each do |f|
164
+ next unless f.containment
165
+ childData = c.getGeneric(f.name)
166
+ next if childData.nil? || (Array === childData && childData.empty?)
167
+ p.setGeneric(f.name, childData)
168
+ end
169
+ end
170
+
171
+ def merge(type)
172
+ #s = StringIO.new
173
+ #ser = RText::Serializer.new(Language)
143
174
 
144
- if not pt.nil?
145
- if (ct.nil?)
146
- @child.setDefaultToolchain(clone(pt))
147
- else
148
- mergeToolchain(pt,ct,true)
149
- end
150
- end
151
-
152
- pt = @parent.toolchain
153
- ct = @child.toolchain
154
-
155
- if not pt.nil?
156
- if (ct.nil?)
157
- @child.setToolchain(clone(pt))
158
- else
159
- mergeToolchain(pt,ct,false)
160
- end
175
+ if Bake.options.debug
176
+ #s.puts "\n>>>> child <<<<"
177
+ #ser.serialize(@child, s)
178
+ #s.puts "\n>>>> parent <<<<"
179
+ #ser.serialize(@parent, s)
161
180
  end
162
-
163
- # Valid for custom config
164
181
 
165
- if (Metamodel::CustomConfig === @child && Metamodel::CustomConfig === @parent)
166
- @child.setStep(clone(@parent.step)) if @child.step.nil? and not @parent.step.nil?
182
+ if (type == :remove)
183
+ removeChilds(@child, @parent)
184
+ elsif (type == :replace)
185
+ replace
186
+ elsif (type == :extend)
187
+ c = clone(@child)
188
+ extend(c, @parent)
189
+ copyChildToParent(c, @parent)
190
+ elsif (type == :merge)
191
+ extend(@child, clone(@parent))
167
192
  end
168
193
 
169
- # Valid for library and exe config
170
-
171
- if ((Metamodel::LibraryConfig === @child || Metamodel::ExecutableConfig === @child) && (Metamodel::LibraryConfig === @parent || Metamodel::ExecutableConfig === @parent))
172
- @child.setFiles(clone(@parent.files) + @child.files)
173
- @child.setExcludeFiles(clone(@parent.excludeFiles) + @child.excludeFiles)
174
- @child.setIncludeDir(clone(@parent.includeDir) + @child.includeDir)
194
+ if Bake.options.debug
195
+ #s.puts "\n>>>> #{type.to_s} <<<<"
196
+ #ser.serialize(type == :merge ? @child : @parent, s)
197
+ #puts "#{s.string}"
175
198
  end
176
199
 
177
- # Valid for exe config
178
-
179
- if (Metamodel::ExecutableConfig === @child && Metamodel::ExecutableConfig === @parent)
180
- @child.setLinkerScript(clone(@parent.linkerScript)) if @child.linkerScript.nil? and not @parent.linkerScript.nil?
181
- @child.setArtifactName(clone(@parent.artifactName)) if @child.artifactName.nil? and not @parent.artifactName.nil?
182
- @child.setMapFile(clone(@parent.mapFile)) if @child.mapFile.nil? and not @parent.mapFile.nil?
183
- end
184
-
200
+
185
201
  end
186
202
 
187
203
  end