bake 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +16 -0
- data/CONCEPTS +52 -0
- data/TUTORIAL +12 -23
- data/lib/bake.rb +7 -34
- data/lib/bake/addon.rb +20 -0
- data/lib/bake/context.rb +40 -60
- data/lib/bake/file_target.rb +14 -0
- data/lib/bake/plugin.rb +72 -0
- data/lib/bake/plugins/cpp.rb +122 -0
- data/lib/bake/plugins/cpp/darwin.rb +27 -0
- data/lib/bake/plugins/cpp/gcc.rb +9 -0
- data/lib/bake/plugins/cpp/gcc_toolset_base.rb +118 -0
- data/lib/bake/plugins/cpp/msvc.rb +124 -0
- data/lib/bake/plugins/cpp/qt.rb +50 -0
- data/lib/bake/plugins/cpp/toolset_base.rb +98 -0
- data/lib/bake/plugins/macro.rb +18 -0
- data/lib/bake/plugins/system.rb +46 -0
- data/lib/bake/project.rb +50 -0
- data/lib/bake/project_loader.rb +11 -15
- data/lib/bake/string_utils.rb +4 -0
- data/lib/bake/target.rb +43 -80
- data/lib/bake/toolset.rb +13 -6
- data/lib/bake_version.rb +1 -1
- metadata +19 -7
- data/lib/bake/common_scheme.rb +0 -42
- data/lib/bake/cpp_scheme.rb +0 -460
- data/lib/bake/qt_scheme.rb +0 -62
- data/lib/bake/scheme.rb +0 -104
- data/lib/bake/scheme_loader.rb +0 -28
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'bake/toolset'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Bake
|
6
|
+
module Plugins
|
7
|
+
module Cpp
|
8
|
+
class ToolsetBase
|
9
|
+
include Toolset
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
constructor :syslib, SystemLibrary
|
13
|
+
constructor :lib, Library
|
14
|
+
constructor :exe, Executable
|
15
|
+
constructor :run, Runner
|
16
|
+
end
|
17
|
+
|
18
|
+
def build(target)
|
19
|
+
if stale?(target)
|
20
|
+
FileUtils.mkdir_p(target[:outdir])
|
21
|
+
if target.is_a?(Cpp::Object)
|
22
|
+
compile(target)
|
23
|
+
# refresh the .includes file
|
24
|
+
includes = target.includes
|
25
|
+
filename = "#{target[:outdir]}/#{target.src.basename}.includes"
|
26
|
+
File.open(filename, "w") do |file|
|
27
|
+
includes.each { |inc| file.puts(inc) }
|
28
|
+
end
|
29
|
+
elsif target.is_a?(Cpp::Library)
|
30
|
+
ar(target)
|
31
|
+
elsif target.is_a?(Cpp::Executable)
|
32
|
+
link(target)
|
33
|
+
elsif target.is_a?(Cpp::Runner)
|
34
|
+
run(target)
|
35
|
+
else
|
36
|
+
raise "unknown Cpp target of class '#{target.class}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def stale?(target)
|
42
|
+
t = Time.now
|
43
|
+
output_files(target).each do |out|
|
44
|
+
return true if !File.exists?(out)
|
45
|
+
out_time = File.mtime(out)
|
46
|
+
t = out_time if out_time < t
|
47
|
+
end
|
48
|
+
if target.is_a?(Cpp::Object)
|
49
|
+
return true if File.mtime(target.src) > t
|
50
|
+
target.includes.each { |file| return true if File.mtime(file) > t }
|
51
|
+
elsif target.is_a?(Cpp::Runner)
|
52
|
+
return File.mtime(output_files(target.deps[0])[0]) > t
|
53
|
+
else
|
54
|
+
is_linked = target.is_a?(Cpp::Executable) ||
|
55
|
+
(target.is_a?(Cpp::Library) && target[:libtype] == 'dynamic')
|
56
|
+
target.children.each do |child|
|
57
|
+
output_files(child).each do |file|
|
58
|
+
return true if File.mtime(file) > t
|
59
|
+
end
|
60
|
+
end
|
61
|
+
target.deps.each do |dep|
|
62
|
+
if is_linked && dep.is_a?(Cpp::Library) &&
|
63
|
+
dep[:libtype] != 'dynamic'
|
64
|
+
output_files(dep).each do |file|
|
65
|
+
return true if File.mtime(file) > t
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
return false
|
71
|
+
end
|
72
|
+
|
73
|
+
def clean(target)
|
74
|
+
output_files(target).each { |file| FileUtils.rm_f(file) }
|
75
|
+
if target.is_a?(Cpp::Object)
|
76
|
+
filename = "#{target[:outdir]}/#{target.src.basename}.includes"
|
77
|
+
FileUtils.rm_f(filename)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def output_files(target)
|
82
|
+
out = output(target)
|
83
|
+
return [] if !out
|
84
|
+
return out.to_a if out.respond_to?(:to_a)
|
85
|
+
return [ out ]
|
86
|
+
end
|
87
|
+
|
88
|
+
def sh(*args)
|
89
|
+
cmd = args.join(' ')
|
90
|
+
puts cmd
|
91
|
+
system(*args)
|
92
|
+
raise "error: #{cmd}" if !$? || !$?.success?
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'bake/addon'
|
2
|
+
|
3
|
+
module Bake
|
4
|
+
module Plugins
|
5
|
+
class System
|
6
|
+
include Addon
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
command(:glob)
|
10
|
+
end
|
11
|
+
|
12
|
+
def glob(context, *args)
|
13
|
+
has_options = args.last.respond_to?(:to_hash)
|
14
|
+
options = has_options ? args.pop.to_hash : {}
|
15
|
+
exclude = array_opt(options, :exclude)
|
16
|
+
files = []
|
17
|
+
args.each do |pat|
|
18
|
+
matches = Dir[pat]
|
19
|
+
matches.each do |file|
|
20
|
+
if !exclude.find { |exc| File.fnmatch(exc, file) }
|
21
|
+
files.push(file)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
if block_given?
|
26
|
+
for i in 0...files.size
|
27
|
+
yield(files[i])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
return files
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def array_opt(options, name)
|
35
|
+
opt = options[name]
|
36
|
+
return [] if !opt
|
37
|
+
if opt.respond_to?(:to_ary)
|
38
|
+
opt = opt.to_ary
|
39
|
+
else
|
40
|
+
opt = [ opt ]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
data/lib/bake/project.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'bake/target'
|
2
|
+
|
3
|
+
module Bake
|
4
|
+
class Project < Target
|
5
|
+
attr_accessor :loader
|
6
|
+
|
7
|
+
def initialize(parent, loader)
|
8
|
+
super(parent, nil)
|
9
|
+
@loader = loader
|
10
|
+
end
|
11
|
+
|
12
|
+
def current_project
|
13
|
+
return self
|
14
|
+
end
|
15
|
+
|
16
|
+
def parent_project
|
17
|
+
return parent ? parent.current_project : nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def child_project(name)
|
21
|
+
child = children.find do |child|
|
22
|
+
child.name == name && child.is_a?(Project)
|
23
|
+
end
|
24
|
+
return child || loader.load_project(self, name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def resolve(path)
|
28
|
+
index = path.index(':')
|
29
|
+
raise "invalid path '#{path}'" if !index
|
30
|
+
dir = path.slice(0, index)
|
31
|
+
name = path.slice(index + 1, path.length - index - 1)
|
32
|
+
proj = self
|
33
|
+
dir.split('/').each do |el|
|
34
|
+
if el == '.'
|
35
|
+
next
|
36
|
+
elsif el == '..'
|
37
|
+
proj = proj.parent_project
|
38
|
+
raise "invalid target path '#{path}'" if !proj
|
39
|
+
else
|
40
|
+
proj = proj.child_project(el)
|
41
|
+
raise "invalid target path '#{path}'" if !proj
|
42
|
+
end
|
43
|
+
end
|
44
|
+
target = proj.children.find { |child| child.name == name }
|
45
|
+
raise "invalid target path '#{path}'" if !target
|
46
|
+
return target
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
data/lib/bake/project_loader.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'bake/target'
|
2
|
+
require 'bake/project'
|
2
3
|
|
3
4
|
module Bake
|
4
5
|
class ProjectLoader
|
@@ -10,18 +11,14 @@ module Bake
|
|
10
11
|
load_invok_project
|
11
12
|
end
|
12
13
|
|
13
|
-
def load_project(
|
14
|
-
|
15
|
-
if !
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
proj.opt(:projname => name)
|
22
|
-
proj.opt(:cwdir => dir)
|
23
|
-
process(proj)
|
24
|
-
end
|
14
|
+
def load_project(parent, name)
|
15
|
+
dir = File.join(parent[:cwdir], name)
|
16
|
+
raise "no such directory '#{dir}'" if !File.directory?(dir)
|
17
|
+
proj = Project.new(parent, self)
|
18
|
+
proj.name = name
|
19
|
+
proj.opt(:projname => name)
|
20
|
+
proj.opt(:cwdir => dir)
|
21
|
+
process(proj)
|
25
22
|
return proj
|
26
23
|
end
|
27
24
|
|
@@ -33,8 +30,7 @@ module Bake
|
|
33
30
|
while true
|
34
31
|
bakefile = File.join(dir, 'root.bake')
|
35
32
|
if File.exists?(bakefile)
|
36
|
-
project = Project.new(nil)
|
37
|
-
project.loader = self
|
33
|
+
project = Project.new(nil, self)
|
38
34
|
project.req(:rootdir => dir)
|
39
35
|
project.opt(:projname => 'root')
|
40
36
|
project.opt(:cwdir => dir)
|
@@ -56,7 +52,7 @@ module Bake
|
|
56
52
|
def load_invok_project
|
57
53
|
project = @root_project
|
58
54
|
@invok_path.reverse_each do |name|
|
59
|
-
project = load_project(
|
55
|
+
project = load_project(project, name)
|
60
56
|
end
|
61
57
|
@invok_project = project
|
62
58
|
return project
|
data/lib/bake/string_utils.rb
CHANGED
data/lib/bake/target.rb
CHANGED
@@ -1,115 +1,78 @@
|
|
1
1
|
require 'bake/configuration'
|
2
|
+
require 'bake/string_utils'
|
2
3
|
|
3
4
|
module Bake
|
4
5
|
class Target
|
5
6
|
include Configuration
|
6
7
|
|
7
|
-
attr_reader :parent, :children, :deps
|
8
|
+
attr_reader :parent, :children, :deps, :toolset
|
8
9
|
attr_accessor :name
|
9
10
|
|
10
|
-
def initialize(parent)
|
11
|
+
def initialize(parent, toolset)
|
11
12
|
@parent = parent
|
13
|
+
@toolset = toolset
|
12
14
|
@children = []
|
13
15
|
@deps = []
|
14
16
|
parent.children << self if parent
|
15
|
-
opt(:built? => false)
|
16
|
-
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
if toolset
|
19
|
+
mixin_name = self.class.name.split('::').last
|
20
|
+
toolset.class
|
21
|
+
if toolset.class.const_defined?(mixin_name)
|
22
|
+
extend(toolset.class.const_get(mixin_name))
|
22
23
|
end
|
23
24
|
end
|
24
|
-
|
25
|
+
post_initialize if respond_to?(:post_initialize)
|
25
26
|
end
|
26
27
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
def dep(*targets)
|
36
|
-
ret = []
|
37
|
-
targets.each do |target|
|
38
|
-
if !target.is_a?(Target)
|
39
|
-
real_target = parent.find(target) if parent
|
40
|
-
raise "uknown target '#{target}'" if !real_target
|
41
|
-
target = real_target
|
28
|
+
def build
|
29
|
+
return if @built
|
30
|
+
deps.each { |dep| dep.build }
|
31
|
+
children.each { |child| child.build }
|
32
|
+
if toolset
|
33
|
+
Dir.chdir(get(:cwdir)) do
|
34
|
+
toolset.build(self)
|
42
35
|
end
|
43
|
-
deps << target
|
44
|
-
ret << target
|
45
36
|
end
|
46
|
-
|
37
|
+
@built = true
|
47
38
|
end
|
48
39
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
52
|
-
if !deps.empty?
|
53
|
-
str += ' => '
|
54
|
-
deps.each do |target|
|
55
|
-
str += target.name + ' (' + target.class.name + ') '
|
56
|
-
end
|
57
|
-
end
|
58
|
-
str += "\n"
|
59
|
-
if !children.empty?
|
60
|
-
children.each { |target| str += target.to_s(level + 1) }
|
61
|
-
end
|
62
|
-
return str
|
40
|
+
def clean
|
41
|
+
children.each { |child| child.clean }
|
42
|
+
toolset.clean(self) if toolset
|
63
43
|
end
|
64
|
-
end
|
65
44
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
45
|
+
def dep(*targets)
|
46
|
+
targets = normalize_targets(*targets)
|
47
|
+
targets.each { |target| add_dep(target) }
|
48
|
+
end
|
70
49
|
|
71
|
-
def
|
72
|
-
|
73
|
-
@mappings = {}
|
50
|
+
def add_dep(target)
|
51
|
+
deps << target
|
74
52
|
end
|
75
53
|
|
76
|
-
def
|
77
|
-
|
78
|
-
raise "target '#{name}' already mapped" if @mappings[name]
|
79
|
-
@mappings[name] = loc
|
80
|
-
end
|
54
|
+
def current_project
|
55
|
+
return parent.current_project
|
81
56
|
end
|
82
57
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
if
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
58
|
+
private
|
59
|
+
def normalize_targets(*targets)
|
60
|
+
normalized_targets = []
|
61
|
+
targets.flatten.each do |target|
|
62
|
+
if !target.is_a?(Target)
|
63
|
+
if File.exists?(target)
|
64
|
+
target = FileTarget.new(self, target)
|
65
|
+
else
|
66
|
+
target = current_project.resolve(target)
|
92
67
|
end
|
93
|
-
target = proj.child(name)
|
94
|
-
@mappings[name] = target
|
95
|
-
raise "invalid mapping #{@mappings[name]}" if !target
|
96
|
-
elsif mapping.is_a?(Target)
|
97
|
-
target = mapping
|
98
|
-
else
|
99
|
-
raise "mapping has invalid class '#{mapping.class.name}'"
|
100
68
|
end
|
69
|
+
normalized_targets << target
|
101
70
|
end
|
102
|
-
return
|
103
|
-
end
|
104
|
-
|
105
|
-
def find(name)
|
106
|
-
target = mapping(name)
|
107
|
-
target ||= children.find do |child|
|
108
|
-
!child.is_a?(Project) && child.name == name
|
109
|
-
end
|
110
|
-
target ||= parent.find(name) if parent
|
111
|
-
return target
|
71
|
+
return normalized_targets
|
112
72
|
end
|
113
73
|
end
|
114
74
|
end
|
115
75
|
|
76
|
+
require 'bake/file_target'
|
77
|
+
require 'bake/project'
|
78
|
+
|
data/lib/bake/toolset.rb
CHANGED
@@ -1,10 +1,17 @@
|
|
1
|
+
require 'bake/plugin'
|
2
|
+
|
1
3
|
module Bake
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
module Toolset
|
5
|
+
include Addon
|
6
|
+
|
7
|
+
def constructor(name, target_class)
|
8
|
+
toolset = self
|
9
|
+
command(name) do |*args|
|
10
|
+
block = args.last.is_a?(Proc) ? args.pop : nil
|
11
|
+
target = target_class.new(current, toolset, *args)
|
12
|
+
context_eval(target, &block) if block
|
13
|
+
return target
|
14
|
+
end
|
8
15
|
end
|
9
16
|
end
|
10
17
|
end
|