bake 0.1.0 → 0.1.1

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.
@@ -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
+