bake-toolkit 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile.rb +3 -0
- data/bin/bake +86 -0
- data/bin/bakery +234 -0
- data/lib/alias/loader.rb +56 -0
- data/lib/alias/model/language.rb +22 -0
- data/lib/alias/model/metamodel.rb +29 -0
- data/lib/bake/cache.rb +142 -0
- data/lib/bake/loader.rb +92 -0
- data/lib/bake/model/language.rb +46 -0
- data/lib/bake/model/metamodel.rb +226 -0
- data/lib/bake/model/metamodel_ext.rb +15 -0
- data/lib/bake/options.rb +288 -0
- data/lib/bake/subst.rb +90 -0
- data/lib/bake/util.rb +98 -0
- data/lib/bake/version.rb +30 -0
- data/lib/bakery/loader.rb +57 -0
- data/lib/bakery/model/language.rb +22 -0
- data/lib/bakery/model/metamodel.rb +44 -0
- data/lib/bakery/options.rb +98 -0
- data/lib/option/parser.rb +66 -0
- data/lib/tocxx.rb +883 -0
- data/license.txt +64 -0
- metadata +109 -0
data/lib/bake/subst.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
module Cxxproject
|
2
|
+
|
3
|
+
class Subst
|
4
|
+
|
5
|
+
def self.itute(config, projName, options)
|
6
|
+
|
7
|
+
@@configName = config.name
|
8
|
+
@@projName = projName
|
9
|
+
@@options = options
|
10
|
+
@@mainProjectName = File::basename(options.main_dir)
|
11
|
+
|
12
|
+
@@artifactName = ""
|
13
|
+
if Metamodel::ExecutableConfig === config
|
14
|
+
if not config.artifactName.nil?
|
15
|
+
@@artifactName = config.artifactName.name
|
16
|
+
elsif config.defaultToolchain != nil
|
17
|
+
basedOnToolchain = Cxxproject::Toolchain::Provider[config.defaultToolchain.basedOn]
|
18
|
+
if basedOnToolchain != nil
|
19
|
+
@@artifactName = projName+basedOnToolchain[:LINKER][:OUTPUT_ENDING]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
subst(config)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.subst(elem)
|
28
|
+
elem.class.ecore.eAllAttributes_derived.each do |a|
|
29
|
+
next if a.name == "file_name" or a.name == "line_number"
|
30
|
+
next if a.eType.name != "EString"
|
31
|
+
str = elem.getGeneric(a.name)
|
32
|
+
|
33
|
+
posSubst = 0
|
34
|
+
substStr = ""
|
35
|
+
while (true)
|
36
|
+
posStart = str.index("$(", posSubst)
|
37
|
+
break if posStart.nil?
|
38
|
+
posEnd = str.index(")", posStart)
|
39
|
+
break if posEnd.nil?
|
40
|
+
substStr << str[posSubst..posStart-1] if posStart>0
|
41
|
+
|
42
|
+
var = str[posStart+2..posEnd-1]
|
43
|
+
|
44
|
+
if var == "MainConfigName"
|
45
|
+
substStr << @@options.build_config
|
46
|
+
elsif var == "MainProjectName"
|
47
|
+
substStr << @@mainProjectName
|
48
|
+
elsif var == "ConfigName"
|
49
|
+
substStr << @@configName
|
50
|
+
elsif var == "ProjectName"
|
51
|
+
substStr << @@projName
|
52
|
+
elsif var == "OutputDir"
|
53
|
+
if @@projName == @@mainProjectName
|
54
|
+
substStr << @@options.build_config
|
55
|
+
else
|
56
|
+
substStr << (@@options.build_config + "_" + @@mainProjectName)
|
57
|
+
end
|
58
|
+
elsif var == "Time"
|
59
|
+
substStr << Time.now.to_s
|
60
|
+
elsif var == "Hostname"
|
61
|
+
substStr << Socket.gethostname
|
62
|
+
elsif var == "ArtifactName"
|
63
|
+
substStr << @@artifactName
|
64
|
+
elsif var == "ArtifactNameBase"
|
65
|
+
substStr << @@artifactName.chomp(File.extname(@@artifactName))
|
66
|
+
elsif ENV[var]
|
67
|
+
substStr << ENV[var]
|
68
|
+
elsif var == "PATH_TO_CYGWIN" # allowed to be not set
|
69
|
+
substStr << ""
|
70
|
+
else
|
71
|
+
Printer.printError "Error: #{elem.file_name}(#{elem.line_number}): unknown substitution variable '$(#{var})'"
|
72
|
+
ExitHelper.exit(1)
|
73
|
+
end
|
74
|
+
|
75
|
+
posSubst = posEnd + 1
|
76
|
+
end
|
77
|
+
substStr << str[posSubst..-1]
|
78
|
+
|
79
|
+
elem.setGeneric(a.name, substStr)
|
80
|
+
end
|
81
|
+
|
82
|
+
childsRefs = elem.class.ecore.eAllReferences.select{|r| r.containment}
|
83
|
+
childsRefs.each do |c|
|
84
|
+
elem.getGenericAsArray(c.name).each { |child| subst(child) }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
data/lib/bake/util.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'bake/model/metamodel_ext'
|
2
|
+
require 'bake/model/metamodel'
|
3
|
+
require 'set'
|
4
|
+
require 'cxxproject/utils/printer'
|
5
|
+
require 'cxxproject/utils/exit_helper'
|
6
|
+
require 'cxxproject/utils/utils'
|
7
|
+
|
8
|
+
def adjustFlags(orgStr, flags)
|
9
|
+
orgSplitted = Cxxproject::Utils::flagSplit(orgStr)
|
10
|
+
|
11
|
+
flags.each do |f|
|
12
|
+
if f.overwrite != ""
|
13
|
+
orgSplitted = Cxxproject::Utils::flagSplit(f.overwrite)
|
14
|
+
end
|
15
|
+
|
16
|
+
if f.remove != ""
|
17
|
+
rmSplitted = Cxxproject::Utils::flagSplit(f.remove)
|
18
|
+
orgSplitted.delete_if {|o| rmSplitted.any? { |r|
|
19
|
+
begin
|
20
|
+
o.match("\\A"+r+"\\Z")
|
21
|
+
rescue Exception => e
|
22
|
+
Cxxproject::Printer.printError "Error: #{f.file_name}(#{f.line_number}): " + e.message
|
23
|
+
Cxxproject::ExitHelper.exit(1)
|
24
|
+
end
|
25
|
+
}}
|
26
|
+
end
|
27
|
+
|
28
|
+
if f.add != ""
|
29
|
+
Cxxproject::Utils::flagSplit(f.add).each do |a|
|
30
|
+
orgSplitted << a unless orgSplitted.any? { |o| o==a }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
orgSplitted.join(" ")
|
37
|
+
end
|
38
|
+
|
39
|
+
def integrateToolchain(tcs, toolchain)
|
40
|
+
return tcs unless toolchain
|
41
|
+
|
42
|
+
integrateLinker(tcs, toolchain.linker) if toolchain.respond_to?"linker"
|
43
|
+
integrateArchiver(tcs, toolchain.archiver)
|
44
|
+
toolchain.compiler.each do |c|
|
45
|
+
integrateCompiler(tcs, c, c.ctype)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def integrateLinker(tcs, linker)
|
51
|
+
return tcs unless linker
|
52
|
+
tcs[:LINKER][:COMMAND] = linker.command if linker.command != ""
|
53
|
+
tcs[:LINKER][:FLAGS] = adjustFlags(tcs[:LINKER][:FLAGS], linker.flags)
|
54
|
+
tcs[:LINKER][:LIB_PREFIX_FLAGS] = adjustFlags(tcs[:LINKER][:LIB_PREFIX_FLAGS], linker.libprefixflags)
|
55
|
+
tcs[:LINKER][:LIB_POSTFIX_FLAGS] = adjustFlags(tcs[:LINKER][:LIB_POSTFIX_FLAGS], linker.libpostfixflags)
|
56
|
+
end
|
57
|
+
|
58
|
+
def integrateArchiver(tcs, archiver)
|
59
|
+
return tcs unless archiver
|
60
|
+
tcs[:ARCHIVER][:COMMAND] = archiver.command if archiver.command != ""
|
61
|
+
tcs[:ARCHIVER][:FLAGS] = adjustFlags(tcs[:ARCHIVER][:FLAGS], archiver.flags)
|
62
|
+
end
|
63
|
+
|
64
|
+
def integrateCompiler(tcs, compiler, type)
|
65
|
+
return tcs unless compiler
|
66
|
+
if compiler.respond_to?"command"
|
67
|
+
tcs[:COMPILER][type][:COMMAND] = compiler.command if compiler.command != ""
|
68
|
+
end
|
69
|
+
tcs[:COMPILER][type][:FLAGS] = adjustFlags(tcs[:COMPILER][type][:FLAGS], compiler.flags)
|
70
|
+
compiler.define.each do |d|
|
71
|
+
tcs[:COMPILER][type][:DEFINES] << d.str
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def integrateCompilerFile(tcs, compiler)
|
76
|
+
[:CPP, :C, :ASM].each do |t|
|
77
|
+
integrateCompiler(tcs, compiler, t)
|
78
|
+
end
|
79
|
+
return tcs
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def sanitize_filename(filename)
|
84
|
+
filename.strip do |name|
|
85
|
+
# NOTE: File.basename doesn't work right with Windows paths on Unix
|
86
|
+
# get only the filename, not the whole path
|
87
|
+
name.gsub! /^.*(\\|\/)/, ''
|
88
|
+
|
89
|
+
# Finally, replace all non alphanumeric, underscore
|
90
|
+
# or periods with underscore
|
91
|
+
# name.gsub! /[^\w\.\-]/, '_'
|
92
|
+
# Basically strip out the non-ascii alphabets too
|
93
|
+
# and replace with x.
|
94
|
+
# You don't want all _ :)
|
95
|
+
name.gsub!(/[^0-9A-Za-z.\-]/, 'x')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
data/lib/bake/version.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module Cxxproject
|
2
|
+
class Version
|
3
|
+
def self.bake
|
4
|
+
"1.0.1"
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
expectedCxx = "0.5.59"
|
9
|
+
expectedRGen = "0.6.0"
|
10
|
+
expectedRText = "0.2.0"
|
11
|
+
|
12
|
+
begin
|
13
|
+
gem "cxxproject", "=#{expectedCxx}"
|
14
|
+
rescue Exception => e
|
15
|
+
puts "Warning: Failed to load cxxproject #{expectedCxx}, using latest version"
|
16
|
+
end
|
17
|
+
|
18
|
+
begin
|
19
|
+
gem "rgen", "=#{expectedRGen}"
|
20
|
+
rescue Exception => e
|
21
|
+
puts "Warning: Failed to load rgen #{expectedRGen}, using latest version"
|
22
|
+
end
|
23
|
+
|
24
|
+
begin
|
25
|
+
gem "rtext", "=#{expectedRText}"
|
26
|
+
rescue Exception => e
|
27
|
+
puts "Warning: Failed to load rtext #{expectedRText}, using latest version"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'bakery/model/metamodel'
|
2
|
+
require 'bakery/model/language'
|
3
|
+
require 'bake/version'
|
4
|
+
|
5
|
+
require 'rgen/environment'
|
6
|
+
require 'rgen/fragment/fragmented_model'
|
7
|
+
|
8
|
+
require 'rtext/default_loader'
|
9
|
+
|
10
|
+
require 'cxxproject/utils/exit_helper'
|
11
|
+
require 'cxxproject/utils/printer'
|
12
|
+
|
13
|
+
module Cxxproject
|
14
|
+
|
15
|
+
class BakeryLoader
|
16
|
+
|
17
|
+
attr_reader :model
|
18
|
+
|
19
|
+
def initialize(options)
|
20
|
+
@env = RGen::Environment.new
|
21
|
+
@options = options
|
22
|
+
@model = RGen::Fragment::FragmentedModel.new(:env => @env)
|
23
|
+
end
|
24
|
+
|
25
|
+
def load(filename)
|
26
|
+
|
27
|
+
sumErrors = 0
|
28
|
+
|
29
|
+
if not File.exists?filename
|
30
|
+
Printer.printError "Error: #{filename} does not exist"
|
31
|
+
ExitHelper.exit(1)
|
32
|
+
end
|
33
|
+
|
34
|
+
loader = RText::DefaultLoader.new(
|
35
|
+
Cxxproject::BakeryLanguage,
|
36
|
+
@model,
|
37
|
+
:file_provider => proc { [filename] },
|
38
|
+
:cache => @DumpFileCache)
|
39
|
+
loader.load()
|
40
|
+
|
41
|
+
f = @model.fragments[0]
|
42
|
+
|
43
|
+
f.data[:problems].each do |p|
|
44
|
+
Printer.printError "Error: "+p.file+"("+p.line.to_s+"): "+p.message
|
45
|
+
end
|
46
|
+
|
47
|
+
if f.data[:problems].length > 0
|
48
|
+
ExitHelper.exit(1)
|
49
|
+
end
|
50
|
+
|
51
|
+
return @env
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'bake/model/metamodel'
|
2
|
+
require 'rtext/language'
|
3
|
+
|
4
|
+
module Cxxproject
|
5
|
+
|
6
|
+
BakeryLanguage =
|
7
|
+
RText::Language.new(BakeryModel.ecore,
|
8
|
+
:feature_provider => proc {|c|
|
9
|
+
RGen::Serializer::OppositeReferenceFilter.call(c.eAllStructuralFeatures).reject {|f|
|
10
|
+
f.eAnnotations.any? {|a|
|
11
|
+
a.details.any? {|d| d.key == 'internal' && d.value == 'true'}
|
12
|
+
}
|
13
|
+
}
|
14
|
+
},
|
15
|
+
:unlabled_arguments => proc {|c|
|
16
|
+
["name"]
|
17
|
+
},
|
18
|
+
:line_number_attribute => "line_number",
|
19
|
+
:file_name_attribute => "file_name"
|
20
|
+
)
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rgen/metamodel_builder'
|
2
|
+
require 'rgen/metamodel_builder/data_types'
|
3
|
+
|
4
|
+
module Cxxproject
|
5
|
+
|
6
|
+
module BakeryModel
|
7
|
+
extend RGen::MetamodelBuilder::ModuleExtension
|
8
|
+
|
9
|
+
class ModelElement < RGen::MetamodelBuilder::MMBase
|
10
|
+
abstract
|
11
|
+
has_attr 'line_number', Integer do
|
12
|
+
annotation :details => {'internal' => 'true'}
|
13
|
+
end
|
14
|
+
has_attr 'file_name', String do
|
15
|
+
annotation :details => {'internal' => 'true'}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Project < ModelElement
|
20
|
+
has_attr 'name', String, :defaultValueLiteral => ""
|
21
|
+
has_attr 'config', String, :defaultValueLiteral => ""
|
22
|
+
end
|
23
|
+
class Exclude < ModelElement
|
24
|
+
has_attr 'name', String, :defaultValueLiteral => ""
|
25
|
+
has_attr 'config', String, :defaultValueLiteral => ""
|
26
|
+
end
|
27
|
+
class Collection < ModelElement
|
28
|
+
has_attr 'name', String, :defaultValueLiteral => ""
|
29
|
+
contains_many 'project', Project, 'collection'
|
30
|
+
contains_many 'exclude', Exclude, 'collection'
|
31
|
+
end
|
32
|
+
|
33
|
+
module Project::ClassModule
|
34
|
+
def isFound
|
35
|
+
@isFound ||= false
|
36
|
+
end
|
37
|
+
def found
|
38
|
+
@isFound = true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'cxxproject/utils/printer'
|
2
|
+
require "cxxproject/toolchain/colorizing_formatter"
|
3
|
+
require "option/parser"
|
4
|
+
|
5
|
+
module Cxxproject
|
6
|
+
|
7
|
+
class BakeryOptions < Parser
|
8
|
+
attr_reader :collection_name, :collection_dir # String
|
9
|
+
attr_reader :roots # String List
|
10
|
+
attr_reader :color, :error # Boolean
|
11
|
+
attr_reader :socket # Fixnum
|
12
|
+
|
13
|
+
def initialize(argv)
|
14
|
+
super(argv)
|
15
|
+
|
16
|
+
@collection_name = nil
|
17
|
+
@collection_dir = nil
|
18
|
+
@color = nil
|
19
|
+
@error = false
|
20
|
+
@roots = []
|
21
|
+
@socket = 0
|
22
|
+
@def_root = nil
|
23
|
+
|
24
|
+
add_option(Option.new("-b",true) { |x| set_collection_name(x) })
|
25
|
+
add_option(Option.new("-m",true) { |x| set_collection_dir(x) })
|
26
|
+
add_option(Option.new("-r",false) { set_error })
|
27
|
+
add_option(Option.new("-a",true) { |x| set_color(x) })
|
28
|
+
add_option(Option.new("-w",true) { |x| set_root(x) })
|
29
|
+
add_option(Option.new("--socket",true) { |x| set_socket(x) })
|
30
|
+
add_option(Option.new("-h",false) { usage; ExitHelper.exit(0) })
|
31
|
+
end
|
32
|
+
|
33
|
+
def usage
|
34
|
+
puts "\nUsage: bake [options]"
|
35
|
+
puts " -b <name> Name of the collection to build."
|
36
|
+
puts " -m <dir> Directory containing the collection file (default is current directory)."
|
37
|
+
puts " -r Stop on first error."
|
38
|
+
puts " -a <scheme> Use ansi color sequences (console must support it). Possible values are 'white' and 'black'."
|
39
|
+
puts " -h Print this help."
|
40
|
+
puts " -w <root> Add a workspace root (can be used multiple times)."
|
41
|
+
puts " If no root is specified, the parent directory of Collection.meta is added automatically."
|
42
|
+
puts " --socket <num> Set socket for sending errors, receiving commands, etc. - used by e.g. Eclipse."
|
43
|
+
puts "Note: all parameters except -b, -p and -h will be passed to bake - see bake help for more options."
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse_options()
|
47
|
+
parse_internal(true)
|
48
|
+
set_collection_dir(Dir.pwd) if @collection_dir.nil?
|
49
|
+
@roots << @def_root if @roots.length == 0
|
50
|
+
end
|
51
|
+
|
52
|
+
def check_valid_dir(dir)
|
53
|
+
if not File.exists?(dir)
|
54
|
+
Printer.printError "Error: Directory #{dir} does not exist"
|
55
|
+
ExitHelper.exit(1)
|
56
|
+
end
|
57
|
+
if not File.directory?(dir)
|
58
|
+
Printer.printError "Error: #{dir} is not a directory"
|
59
|
+
ExitHelper.exit(1)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def set_collection_name(collection_name)
|
64
|
+
@collection_name = collection_name
|
65
|
+
end
|
66
|
+
|
67
|
+
def set_collection_dir(dir)
|
68
|
+
check_valid_dir(dir)
|
69
|
+
@collection_dir = File.expand_path(dir.gsub(/[\\]/,'/'))
|
70
|
+
@def_root = File.dirname(@collection_dir)
|
71
|
+
end
|
72
|
+
|
73
|
+
def set_color(x)
|
74
|
+
if (x != "black" and x != "white")
|
75
|
+
Printer.printError "Error: color scheme must be 'black' or 'white'"
|
76
|
+
ExitHelper.exit(1)
|
77
|
+
end
|
78
|
+
@color = x
|
79
|
+
ColorizingFormatter.enabled = true
|
80
|
+
ColorizingFormatter::setColorScheme(x.to_sym)
|
81
|
+
end
|
82
|
+
def set_error()
|
83
|
+
@error = true
|
84
|
+
end
|
85
|
+
|
86
|
+
def set_root(dir)
|
87
|
+
check_valid_dir(dir)
|
88
|
+
r = File.expand_path(dir.gsub(/[\\]/,'/'))
|
89
|
+
@roots << r if not @roots.include?r
|
90
|
+
end
|
91
|
+
|
92
|
+
def set_socket(num)
|
93
|
+
@socket = String === num ? num.to_i : num
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|