bake 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,42 +5,45 @@ module Bake
5
5
  module Plugins
6
6
  module Cpp
7
7
  module Qt
8
- class Moc
9
- include Toolset
8
+ class Moc < Toolset
9
+ def initialize(sys)
10
+ super
11
+ command(:moc)
12
+ end
10
13
 
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}")
14
+ def moc(context, *srcs)
15
+ return srcs.collect do |src|
16
+ file_target = FileTarget.new(
17
+ context.current, toolset, src)
18
+ MocFile.new(context.current, self, file_target)
19
+ end
16
20
  end
17
21
 
18
- def clean(target)
19
- FileUtils.rm_f(target.output)
22
+ def build(target)
23
+ if !target.is_a?(MocFile)
24
+ raise "unknown target '#{target}'"
25
+ end
26
+ src = target.src
27
+ sys.sh("moc -o #{target.path} #{target.src}")
20
28
  end
29
+ end
21
30
 
22
- def stale?(target)
23
- return true if !File.exists?(target.output)
24
- return File.mtime(target.src) > File.mtime(target.output)
31
+ class MocFile < Source
32
+ def src
33
+ return @source.path
25
34
  end
26
35
 
27
- def sh(*args)
28
- cmd = args.join(' ')
29
- puts cmd
30
- system(*args)
31
- raise "error: #{cmd}" if !$? || !$?.success?
36
+ def path
37
+ src = @source.path
38
+ ext = File.extname(src)
39
+ basename = File.basename(src, ext) + '.moc' + ext
40
+ return File.join(get(:outdir), basename)
32
41
  end
33
- end
34
42
 
35
- class MocFile < Bake::Target
36
- attr_reader :output
37
- attr_accessor :src
43
+ alias :products :path
38
44
 
39
- def initialize(parent, src)
40
- super(parent)
41
- ext = File.extname(src)
42
- @output = File.basename(src, ext) + '.moc' + ext
43
- @src = src
45
+ def build
46
+ toolset.build(self)
44
47
  end
45
48
  end
46
49
  end
@@ -5,76 +5,41 @@ require 'set'
5
5
  module Bake
6
6
  module Plugins
7
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
8
+ class ToolsetBase < Toolset
9
+ module Object
10
+ def products
11
+ return toolset.obj_fn(self)
12
+ end
16
13
  end
17
14
 
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
15
+ module Library
16
+ def products
17
+ return toolset.lib_fn(self)
38
18
  end
39
19
  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
20
+
21
+ module Executable
22
+ def products
23
+ return toolset.exe_fn(self)
69
24
  end
70
- return false
71
25
  end
72
-
73
- def clean(target)
74
- output_files(target).each { |file| FileUtils.rm_f(file) }
26
+
27
+ def initialize(sys)
28
+ super
29
+ constructor :syslib, Cpp::SystemLibrary
30
+ constructor :lib, Cpp::Library
31
+ constructor :exe, Cpp::Executable
32
+ end
33
+
34
+ def build(target)
75
35
  if target.is_a?(Cpp::Object)
76
- filename = "#{target[:outdir]}/#{target.src.basename}.includes"
77
- FileUtils.rm_f(filename)
36
+ compile(target)
37
+ elsif target.is_a?(Cpp::Library)
38
+ ar(target)
39
+ elsif target.is_a?(Cpp::Executable)
40
+ link(target)
41
+ else
42
+ raise "unknown Cpp target of class '#{target.class}"
78
43
  end
79
44
  end
80
45
 
@@ -84,13 +49,6 @@ module Bake
84
49
  return out.to_a if out.respond_to?(:to_a)
85
50
  return [ out ]
86
51
  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
52
  end
95
53
  end
96
54
  end
@@ -0,0 +1,40 @@
1
+ require 'bake/target'
2
+ require 'fileutils'
3
+
4
+ module Bake
5
+ module Plugins
6
+ class Runner < Target
7
+ def post_initialize(exe)
8
+ @exe = nil
9
+ dep(exe)
10
+ end
11
+
12
+ def add_dep(target)
13
+ @exe = target if !@exe
14
+ deps << target
15
+ end
16
+
17
+ def path
18
+ return @exe.path if @exe.is_a?(FileTarget)
19
+ return @exe.run_command
20
+ end
21
+
22
+ alias :id :path
23
+
24
+ def build
25
+ toolset.sys.sh(path)
26
+ toolset.sys.touch(products)
27
+ end
28
+
29
+ def products
30
+ return File.join(get(:outdir), output_basename)
31
+ end
32
+
33
+ private
34
+ def output_basename
35
+ return path.basename + '.success'
36
+ end
37
+ end
38
+ end
39
+ end
40
+
@@ -1,18 +1,18 @@
1
- require 'bake/addon'
1
+ require 'bake/toolset'
2
2
 
3
3
  module Bake
4
4
  module Plugins
5
- class System
6
- include Addon
7
-
8
- def initialize
5
+ class System < Toolset
6
+ def initialize(sys)
7
+ super
9
8
  command(:glob)
9
+ constructor(:run, Plugins::Runner)
10
10
  end
11
11
 
12
12
  def glob(context, *args)
13
13
  has_options = args.last.respond_to?(:to_hash)
14
14
  options = has_options ? args.pop.to_hash : {}
15
- exclude = array_opt(options, :exclude)
15
+ exclude = options[:exclude].make_array
16
16
  files = []
17
17
  args.each do |pat|
18
18
  matches = Dir[pat]
@@ -22,24 +22,8 @@ module Bake
22
22
  end
23
23
  end
24
24
  end
25
- if block_given?
26
- for i in 0...files.size
27
- yield(files[i])
28
- end
29
- end
30
25
  return files
31
26
  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
27
  end
44
28
  end
45
29
  end
@@ -2,11 +2,11 @@ require 'bake/target'
2
2
 
3
3
  module Bake
4
4
  class Project < Target
5
- attr_accessor :loader
5
+ attr_reader :loader
6
6
 
7
- def initialize(parent, loader)
8
- super(parent, nil)
7
+ def post_initialize(loader)
9
8
  @loader = loader
9
+ @mappings = {}
10
10
  end
11
11
 
12
12
  def current_project
@@ -24,26 +24,67 @@ module Bake
24
24
  return child || loader.load_project(self, name)
25
25
  end
26
26
 
27
+ def map(mappings)
28
+ @mappings.merge!(mappings)
29
+ end
30
+
31
+ # Returns the target found at +path+ relative to this project.
32
+ # Raises a +RuntimeError+ if no such target is found.
33
+ #
34
+ # The +path+ argument is of the form:
35
+ # <dir>:<name> | <name> | <dir>
27
36
  def resolve(path)
37
+ search_projects = ([ self ] + get(:search_projects))
28
38
  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
39
+ if index
40
+ # search for a fully qualified target given by dir:name
41
+ dir = path.slice(0, index)
42
+ name = path.slice(index + 1, path.length - index - 1)
43
+ else
44
+ if !path.index('/') && path != '.' && path != '..'
45
+ # search for target named by path in search_projects
46
+ target = nil
47
+ search_projects.each do |proj|
48
+ target = proj.find_target(path)
49
+ return target if target
50
+ end
42
51
  end
52
+ # search for a project at given path
53
+ dir = path
54
+ name = nil
43
55
  end
44
- target = proj.children.find { |child| child.name == name }
45
- raise "invalid target path '#{path}'" if !target
46
- return target
56
+
57
+ # iterate the search_projects looking for target given by dir:name
58
+ search_projects.each do |proj|
59
+ dir.split('/').each do |el|
60
+ if el == '.'
61
+ next
62
+ elsif el == '..'
63
+ proj = proj.parent_project
64
+ break if !proj
65
+ else
66
+ begin
67
+ proj = proj.child_project(el)
68
+ rescue ProjectLoadError
69
+ proj = nil
70
+ break
71
+ end
72
+ end
73
+ end
74
+ # found a project at dir, find a child named name
75
+ if proj
76
+ return proj if !name
77
+ target = proj.find_target(name)
78
+ return target if target
79
+ end
80
+ end
81
+ raise "invalid target path '#{path}'"
82
+ end
83
+
84
+ protected
85
+ def find_target(name)
86
+ return resolve(@mappings[name]) if @mappings.has_key?(name)
87
+ return children.find { |child| child.name == name }
47
88
  end
48
89
  end
49
90
  end
@@ -2,6 +2,8 @@ require 'bake/target'
2
2
  require 'bake/project'
3
3
 
4
4
  module Bake
5
+ class ProjectLoadError < RuntimeError; end
6
+
5
7
  class ProjectLoader
6
8
  attr_reader :invok_project
7
9
 
@@ -11,10 +13,17 @@ module Bake
11
13
  load_invok_project
12
14
  end
13
15
 
16
+ # Loads a child project of the project given by +parent+. It does this
17
+ # by searching for directory called +name+ in +parent+'s +:cwdir+.
18
+ # Raises a +ProjectLoadError+ if no such directory exists. If the
19
+ # directory contains a bakefile, it will be processed in this
20
+ # +ProjectLoader+'s context.
14
21
  def load_project(parent, name)
15
22
  dir = File.join(parent[:cwdir], name)
16
- raise "no such directory '#{dir}'" if !File.directory?(dir)
17
- proj = Project.new(parent, self)
23
+ if !File.directory?(dir)
24
+ raise ProjectLoadError, "no such directory '#{dir}'"
25
+ end
26
+ proj = Project.new(parent, @context.default_toolset, self)
18
27
  proj.name = name
19
28
  proj.opt(:projname => name)
20
29
  proj.opt(:cwdir => dir)
@@ -30,8 +39,8 @@ module Bake
30
39
  while true
31
40
  bakefile = File.join(dir, 'root.bake')
32
41
  if File.exists?(bakefile)
33
- project = Project.new(nil, self)
34
- project.req(:rootdir => dir)
42
+ project = Project.new(nil, @context.default_toolset, self)
43
+ project.opt(:rootdir => dir)
35
44
  project.opt(:projname => 'root')
36
45
  project.opt(:cwdir => dir)
37
46
  project.opt(:outdir => '${cwdir}')
@@ -0,0 +1,42 @@
1
+ require 'fileutils'
2
+
3
+ module Bake
4
+ class SystemUtils
5
+ def initialize(options = {})
6
+ @options = options
7
+ if options[:dry_run]
8
+ @file_utils = FileUtils::DryRun
9
+ elsif options[:verbose]
10
+ @file_utils = FileUtils::Verbose
11
+ else
12
+ @file_utils = FileUtils
13
+ end
14
+ end
15
+
16
+ def dry_run?
17
+ return @options[:dry_run]
18
+ end
19
+
20
+ def verbose?
21
+ return @options[:dry_run] || @options[:verbose]
22
+ end
23
+
24
+ def sh(*args)
25
+ cmd = args.join(' ')
26
+ puts cmd if verbose?
27
+ if !dry_run?
28
+ system(*args)
29
+ raise "error: #{cmd}" if !$? || !$?.success?
30
+ end
31
+ end
32
+
33
+ def fwrite(file, contents)
34
+ puts "writing '#{file}'" if verbose?
35
+ File.open(file, "w") { |f| f.puts(contents) } if !dry_run?
36
+ end
37
+
38
+ def method_missing(name, *args)
39
+ @file_utils.send(name, *args)
40
+ end
41
+ end
42
+ end