bake 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,122 @@
1
+ require 'bake/target'
2
+
3
+ module Bake
4
+ module Plugins
5
+ module Cpp
6
+ class SystemLibrary < Target
7
+ attr_reader :file
8
+
9
+ def initialize(parent, toolset, name, file)
10
+ super(parent, toolset)
11
+ @built = true
12
+ @name = name
13
+ @file = file
14
+ opt(:built? => true)
15
+ end
16
+ end
17
+
18
+ class Library < Target
19
+ def initialize(parent, toolset, name)
20
+ super(parent, toolset)
21
+ @name = name
22
+ default(:libtype => 'static')
23
+ default(:debug_symbols? => false)
24
+ end
25
+
26
+ def add_dep(target)
27
+ return super if !target.is_a?(FileTarget)
28
+ deps << Cpp::Object.new(self, toolset, target)
29
+ end
30
+ end
31
+
32
+ class Executable < Target
33
+ def initialize(parent, toolset, name)
34
+ super(parent, toolset)
35
+ @name = name
36
+ default(:debug_symbols? => false)
37
+ end
38
+
39
+ def add_dep(target)
40
+ return super if !target.is_a?(FileTarget)
41
+ deps << Cpp::Object.new(self, toolset, target)
42
+ end
43
+ end
44
+
45
+ class Object < Target
46
+ def initialize(parent, toolset, file_target)
47
+ super(parent, toolset)
48
+ deps << file_target
49
+ default(:exceptions? => true)
50
+ default(:rtti? => true)
51
+ default(:optimizations? => false)
52
+ default(:multithreaded? => true)
53
+ end
54
+
55
+ def src
56
+ return deps.first.path
57
+ end
58
+
59
+ def includes(recalc = false)
60
+ incfile = "#{get(:outdir)}/#{src}.includes"
61
+ if !@includes || recalc
62
+ if File.exists?(incfile)
63
+ @includes = load_includes(incfile)
64
+ else
65
+ @includes = calc_includes(src, Set.new)
66
+ end
67
+ end
68
+ return @includes
69
+ end
70
+
71
+ private
72
+ def load_includes(incfile)
73
+ includes = Set.new
74
+ file = File.open(incfile)
75
+ while line = file.gets
76
+ line.chomp!
77
+ includes << line if !line.empty?
78
+ end
79
+ file.close
80
+ return includes
81
+ end
82
+
83
+ def calc_includes(filename, include_fns)
84
+ new_include_fns = Set.new
85
+ File.open(filename) do |file|
86
+ incdirs = get(:incdirs)
87
+ while line = file.gets
88
+ if line =~ /\s*#\s*include\s+("|<)([^"]+)("|>)/
89
+ inc = $2
90
+ incdirs.each do |include_dir|
91
+ fn = File.join(include_dir, inc)
92
+ break if include_fns.include?(fn)
93
+ if File.exists?(fn)
94
+ new_include_fns << fn
95
+ include_fns << fn
96
+ break
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ new_include_fns.each do |inc|
104
+ calc_includes(inc, include_fns)
105
+ end
106
+ return include_fns
107
+ end
108
+ end
109
+
110
+ class Runner < Target
111
+ def initialize(parent, toolset, exe)
112
+ super(parent, toolset)
113
+ target = dep(exe)[0]
114
+ if !target.is_a?(Executable)
115
+ raise "target '#{target}' is not an executable"
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+
@@ -0,0 +1,27 @@
1
+ module Bake
2
+ module Plugins
3
+ module Cpp
4
+ class Darwin < GccToolsetBase
5
+ def ar(lib)
6
+ obj_str, lib_str, flags = process_inputs(lib)
7
+
8
+ output = lib_fn(lib)
9
+ if lib[:libtype] == 'dynamic'
10
+ sh("g++ #{flags} -dynamiclib -o #{output} #{obj_str} #{lib_str}")
11
+ else
12
+ sh("ar rcs #{output} #{obj_str}")
13
+ end
14
+ end
15
+
16
+ private
17
+ def lib_fn(lib)
18
+ if lib[:libtype] == 'dynamic'
19
+ return File.join(lib[:outdir], "#{lib.name}.dylib")
20
+ end
21
+ return File.join(lib[:outdir], "lib#{lib.name}.a")
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,9 @@
1
+ module Bake
2
+ module Plugins
3
+ module Cpp
4
+ class Gcc < GccToolsetBase
5
+ end
6
+ end
7
+ end
8
+ end
9
+
@@ -0,0 +1,118 @@
1
+ require 'fileutils'
2
+
3
+ module Bake
4
+ module Plugins
5
+ module Cpp
6
+ class GccToolsetBase < ToolsetBase
7
+ def output(target)
8
+ if target.is_a?(Cpp::Object)
9
+ return obj_fn(target)
10
+ elsif target.is_a?(Cpp::Library)
11
+ return lib_fn(target)
12
+ elsif target.is_a?(Cpp::Executable)
13
+ return exe_fn(target)
14
+ elsif target.is_a?(Cpp::Runner)
15
+ return runner_fn(target)
16
+ end
17
+ return nil
18
+ end
19
+
20
+ def compile(obj)
21
+ src = obj.src
22
+ output = obj_fn(obj)
23
+ flags = build_flags('-I', obj[:incdirs] + obj[:sysincdirs]) +
24
+ build_flags('-D', obj[:defines])
25
+ flags += obj[:cflags].join(' ')
26
+ flags += ' -fno-rtti' if !obj[:rtti?]
27
+ flags += ' -O3' if obj[:optimizations?]
28
+ flags += ' -g' if obj[:debug_symbols?]
29
+ sh("g++ -c -o #{output} #{flags} #{src}")
30
+ end
31
+
32
+ def ar(lib)
33
+ obj_str, lib_str, flags = process_inputs(lib)
34
+
35
+ output = lib_fn(lib)
36
+ if lib[:libtype] == 'dynamic'
37
+ sh("g++ #{flags} -shared -Wl,-soname,#{output} -o #{output} #{obj_str} #{lib_str}")
38
+ if lib.has_prop?(:gcc_lib_path)
39
+ fn = File.join(lib[:gcc_lib_path], output.basename)
40
+ File.symlink(output, fn) if !File.exists?(fn)
41
+ end
42
+ else
43
+ sh("ar rcs #{output} #{obj_str}")
44
+ end
45
+ end
46
+
47
+ def link(exe)
48
+ obj_str, lib_str, flags = process_inputs(exe)
49
+
50
+ output = exe_fn(exe)
51
+ sh("g++ #{flags} -o #{output} #{obj_str} #{lib_str}")
52
+ end
53
+
54
+ def run(runner)
55
+ sh(exe_fn(runner.deps.first))
56
+ FileUtils.touch(runner_fn(runner))
57
+ end
58
+
59
+ private
60
+ def build_flags(flag, args)
61
+ return args.inject('') { |str, arg| str + "#{flag}#{arg} " }
62
+ end
63
+
64
+ def obj_fn(obj)
65
+ src = obj.src
66
+ basename = File.basename(src, File.extname(src)) + '.o'
67
+ return File.join(obj[:outdir], basename)
68
+ end
69
+
70
+ def lib_fn(lib)
71
+ if lib[:libtype] == 'dynamic'
72
+ return File.join(lib[:outdir], "lib#{lib.name}.so")
73
+ end
74
+ return File.join(lib[:outdir], "lib#{lib.name}.a")
75
+ end
76
+
77
+ def exe_fn(exe)
78
+ return File.join(exe[:outdir], exe.name)
79
+ end
80
+
81
+ def runner_fn(runner)
82
+ return "#{exe_fn(runner.deps.first)}.success"
83
+ end
84
+
85
+ def process_inputs(target)
86
+ output = output(target)
87
+ obj_str = ''
88
+ lib_str = ''
89
+ libdirs = []
90
+ rtdirs = []
91
+ target.deps.each do |input|
92
+ if input.is_a?(Cpp::Object)
93
+ fn = obj_fn(input)
94
+ obj_str += fn + ' '
95
+ elsif input.is_a?(Cpp::SystemLibrary)
96
+ lib_str += '-l' + input.file + ' '
97
+ elsif input.is_a?(Cpp::Library)
98
+ fn = lib_fn(input)
99
+ if input[:libtype] == 'dynamic'
100
+ obj_str += fn + ' '
101
+ rtdirs << File.dirname(fn)
102
+ else
103
+ lib_str += '-l' + input.name + ' '
104
+ libdir = File.dirname(fn)
105
+ libdirs << libdir if !libdirs.include?(libdir)
106
+ end
107
+ end
108
+ end
109
+
110
+ libdirs.concat(target[:libdirs])
111
+ flags = build_flags('-L', libdirs)
112
+ return [ obj_str, lib_str, flags ]
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+
@@ -0,0 +1,124 @@
1
+ require 'fileutils'
2
+
3
+ module Bake
4
+ module Plugins
5
+ module Cpp
6
+ class Msvc < ToolsetBase
7
+ def output(target)
8
+ if target.is_a?(Object)
9
+ return obj_fn(target)
10
+ elsif target.is_a?(Library)
11
+ return lib_fn(target)
12
+ elsif target.is_a?(Executable)
13
+ return exe_fn(target)
14
+ end
15
+ return nil
16
+ end
17
+
18
+ def compile(obj)
19
+ src = obj.src
20
+ output = obj_fn(obj)
21
+ flags = build_flags('/I', obj[:incdirs] + obj[:sysincdirs]) +
22
+ build_flags('/D', obj[:defines])
23
+ flags += obj[:cflags].join(' ')
24
+ flags += ' /MD'
25
+ flags += ' /EHsc' if obj[:exceptions?]
26
+ flags += ' /GR' if obj[:rtti?]
27
+ flags += obj[:optimizations?] ? ' /O2' : ' /Od'
28
+ flags += ' /Z7' if obj[:debug_symbols?]
29
+ sh("cl /nologo #{flags} /c /Fo#{output} /Tp#{src}")
30
+ end
31
+
32
+ def ar(lib)
33
+ obj_str, flags = process_inputs(lib)
34
+
35
+ output = lib_fn(lib)
36
+ if lib[:libtype] == 'dynamic'
37
+ flags += ' /debug' if lib[:debug_symbols?]
38
+ sh("link /nologo /dll #{flags} /out:#{output[1]} #{obj_str}")
39
+ else
40
+ sh("lib /nologo /out:#{output} #{obj_str}")
41
+ end
42
+ end
43
+
44
+ def link(exe)
45
+ obj_str, flags = process_inputs(exe)
46
+
47
+ output = exe_fn(exe)
48
+ flags += ' /debug' if exe[:debug_symbols?]
49
+ sh("link /nologo /subsystem:console #{flags} /out:#{output} #{obj_str}")
50
+ end
51
+
52
+ def run(runner)
53
+ sh(exe_fn(runner.deps.first))
54
+ FileUtils.touch(runner_fn(runner))
55
+ end
56
+
57
+ private
58
+ def build_flags(flag, args)
59
+ return args.inject('') { |str, arg| str + "#{flag}#{arg} " }
60
+ end
61
+
62
+ def obj_fn(obj)
63
+ src = obj.src
64
+ basename = File.basename(src, File.extname(src)) + '.obj'
65
+ return File.join(obj[:outdir], basename)
66
+ end
67
+
68
+ def lib_fn(lib)
69
+ if lib[:libtype] == 'dynamic'
70
+ return [File.join(lib[:outdir], "#{lib.name}.lib"),
71
+ File.join(lib[:outdir], "#{lib.name}.dll"),
72
+ File.join(lib[:outdir], "#{lib.name}.exp")]
73
+ end
74
+ return File.join(lib[:outdir], "#{lib.name}.lib")
75
+ end
76
+
77
+ def exe_fn(exe)
78
+ return File.join(exe[:outdir], exe.name + '.exe')
79
+ end
80
+
81
+ def runner_fn(runner)
82
+ return "#{exe_fn(runner.deps.first)}.success"
83
+ end
84
+
85
+ def process_inputs(target)
86
+ output = output(target)
87
+ obj_str = ''
88
+ libdirs = []
89
+ static_lib = target.is_a?(Library) && target[:libtype] == 'static'
90
+ target.deps.each do |input|
91
+ if input.is_a?(Object)
92
+ fn = obj_fn(input)
93
+ obj_str += fn + ' '
94
+ elsif input.is_a?(SystemLibrary)
95
+ if !static_lib
96
+ obj_str += input.file + '.lib '
97
+ end
98
+ elsif input.is_a?(Library)
99
+ if !static_lib
100
+ if input[:libtype] == 'dynamic'
101
+ fn = lib_fn(input)[0]
102
+ else
103
+ fn = lib_fn(input)
104
+ end
105
+ libdir = File.dirname(fn)
106
+ libdirs << libdir if !libdirs.include?(libdir)
107
+ obj_str += File.basename(fn) + ' '
108
+ end
109
+ end
110
+ end
111
+
112
+ if !static_lib
113
+ target[:libs].each { |lib| obj_str += lib + '.lib ' }
114
+ end
115
+ libdirs.concat(target[:libdirs])
116
+ flags = build_flags('/LIBPATH:', libdirs)
117
+
118
+ return [ obj_str, flags ]
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+
@@ -0,0 +1,50 @@
1
+ require 'bake/toolset'
2
+ require 'fileutils'
3
+
4
+ module Bake
5
+ module Plugins
6
+ module Cpp
7
+ module Qt
8
+ class Moc
9
+ include Toolset
10
+
11
+ def build(target)
12
+ raise "unknown target '#{target}'" if !target.is_a?(MocFile)
13
+ return if !stale?(target)
14
+ src = target.src
15
+ sh("moc -o #{target.output} #{target.src}")
16
+ end
17
+
18
+ def clean(target)
19
+ FileUtils.rm_f(target.output)
20
+ end
21
+
22
+ def stale?(target)
23
+ return true if !File.exists?(target.output)
24
+ return File.mtime(target.src) > File.mtime(target.output)
25
+ end
26
+
27
+ def sh(*args)
28
+ cmd = args.join(' ')
29
+ puts cmd
30
+ system(*args)
31
+ raise "error: #{cmd}" if !$? || !$?.success?
32
+ end
33
+ end
34
+
35
+ class MocFile < Bake::Target
36
+ attr_reader :output
37
+ attr_accessor :src
38
+
39
+ def initialize(parent, src)
40
+ super(parent)
41
+ ext = File.extname(src)
42
+ @output = File.basename(src, ext) + '.moc' + ext
43
+ @src = src
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+