bake 0.1.1 → 0.1.2

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