bake-toolkit 2.13.1 → 2.14.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.
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