Class: Rmk::Build

Inherits:
Object
  • Object
show all
Defined in:
lib/rmk/build.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dir, rule, vars, input, implicit_input, order_only_input, output, implicit_output, collection) ⇒ Build

create Build

Parameters:

  • dir (Rmk::VDir)

    build’s dir

  • rule (Rmk::Rule)

    build’s rule

  • vars (Rmk::Vars)

    upstream vars

  • input (Array<Rmk::VFile>)

    input files

  • implicit_input (String, nil)

    implicit input raw string

  • order_only_input (String, nil)

    order-only input raw string

  • output (String, nil)

    output raw string

  • implicit_output (String, nil)

    implicit output raw string

  • collection (String, nil)

    collection name



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/rmk/build.rb', line 21

def initialize(dir, rule, vars, input, implicit_input, order_only_input, output, implicit_output, collection)
	@mutex = Thread::Mutex.new
	@updatedcnt = 0		# input file updated count
	@runed = false			# build has been runed
	@input_modified = false	# input file has modified

	@dir = dir
	@command = rule.command
	@vars = vars.downstream_new clone_rmk:true
	rmk_vars = @vars.rmk
	@infiles = input

	if @infiles.size == 1
		if FFile === @infiles[0]
			vname = @infiles[0].vname
			if vname
				match = /^((?:[^\/]+\/)*)([^\/]*)$/.match vname
				rmk_vars['in_dir'], rmk_vars['in_nodir'] = match[1], match[2]
				match = /^(.*)\.(.*)$/.match match[2]
				rmk_vars['in_base'], rmk_vars['in_ext'] = match[1], match[2]
				rmk_vars['in_noext'] = rmk_vars['in_dir'] + rmk_vars['in_base']
			end
			rmk_vars['stem'] = @infiles[0].stem if @infiles[0].stem
			@infiles[0] = @infiles[0].vfile
		end
	end
	rmk_vars['in'] = @infiles.map do |file|
		file.input_ref_builds << self
		next file.vpath || file.path unless file.src?
		file.vpath ? @dir.rmk.join_rto_src_path(file.vpath) : file.path
	end.join ' '

	@vars.split_str(implicit_input).each do |fn|
		files = @dir.find_inputfiles fn
		raise "pattern '#{fn}' not match any file" if files.empty?
		files.each{|f| f.input_ref_builds << self}
	end if implicit_input

	@orderfiles = []
	@vars.split_str(order_only_input).each do |fn|
		files = @dir.find_inputfiles fn
		raise "pattern '#{fn}' not match any file" if files.empty?
		files.each{|f| f.order_ref_builds << self}
	end if order_only_input
	raise 'no found any input file' if @infiles.empty? && @orderfiles.empty?

	@outfiles = []
	regout = proc do |fn|
		file = @dir.add_out_file fn
		file.output_ref_build = self
		@outfiles << file
	end
	output = rule['out'] || raise('must have output') unless output
	@vars.split_str(output).each &regout
	collection.each{|col| col.concat @outfiles} if collection
	rmk_vars['out'] = @outfiles.map {|file| file.vpath || file.path}.join ' '
	rmk_vars['out_noext'] = rmk_vars['out'][/^(.*)\..*$/, 1] if @outfiles.size == 1
	rule.apply_to @vars	# interpolate rule's vars to self
	@vars.split_str(implicit_output).each &regout if implicit_output
	rmk_vars.freeze
	@depfiles = []
	@outfiles.each do |file|
		next unless (fns = @dir.rmk.dep_storage.data![file.path])
		fns.each {|fn| @dir.rmk.find_inputfiles(fn).each {|f| f.input_ref_builds << self; @depfiles << f}}
	end
end

Instance Attribute Details

#depfilesObject (readonly)

Returns the value of attribute depfiles.



9
10
11
# File 'lib/rmk/build.rb', line 9

def depfiles
  @depfiles
end

#dirObject (readonly)

Returns the value of attribute dir.



8
9
10
# File 'lib/rmk/build.rb', line 8

def dir
  @dir
end

#infilesObject (readonly)

Returns the value of attribute infiles.



9
10
11
# File 'lib/rmk/build.rb', line 9

def infiles
  @infiles
end

#orderfilesObject (readonly)

Returns the value of attribute orderfiles.



9
10
11
# File 'lib/rmk/build.rb', line 9

def orderfiles
  @orderfiles
end

#outfilesObject (readonly)

Returns the value of attribute outfiles.



9
10
11
# File 'lib/rmk/build.rb', line 9

def outfiles
  @outfiles
end

#varsObject (readonly)

Returns the value of attribute vars.



8
9
10
# File 'lib/rmk/build.rb', line 8

def vars
  @vars
end

Instance Method Details

#input_updated!(modified, order: false) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
# File 'lib/rmk/build.rb', line 88

def input_updated!(modified, order:false)
	Rmk::Schedule.new_thread! &method(:run) if @mutex.synchronize do
		next @runed = :checkskip if @runed == :force
		next if @runed
		@updatedcnt += 1
		@input_modified ||= order ? modified == :create : modified
		needrun = @updatedcnt >= @infiles.size + @depfiles.size + @orderfiles.size
		@runed = true if needrun
		needrun
	end
end

#order_updated!(modified) ⇒ Object



100
# File 'lib/rmk/build.rb', line 100

def order_updated!(modified) input_updated! modified, order:true end

#parse_make_depfile(path) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/rmk/build.rb', line 207

def parse_make_depfile(path)
	lines = IO.readlines path
	line, lid = lines[0], 0
	_, _, line = line.partition /(?<!\\)(?:\\\\)*\K:\s+/
	return unless line
	files = []
	while lid < lines.size
		joinline = line.sub! /(?<!\\)(?:\\\\)*\K\\\n\z/,''
		parms = line.split /(?<!\\)(?:\\\\)*\K\s+/
		unless parms.empty?
			parms.delete_at 0 if parms[0].empty?
			parms.map!{|parm| File.absolute_path parm.gsub(/\\(.)/, '\1')}
			files.concat parms
		end
		break unless joinline
		lid += 1
		line = lines[lid]
	end
	files
end

#parser_force_run!Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/rmk/build.rb', line 127

def parser_force_run!
	return if @runed
	@runed = :force
	exec = nil
	@outfiles.each{|file| file.state = File.exist?(file.path) ? :exist : (exec = :create)}
	@command, changed = get_command
	unless changed || exec
		inproc = proc do |file|
			next file.check_for_parse if file.src?
			state = file.state
			raise 'output file not updated when ref as config file build input' unless state
			state != :exist
		end
		exec = @infiles.any? &inproc
		exec ||= @depfiles.any? &inproc
		return unless @orderfiles.any? do |file|
			next if file.src?
			state = file.state
			raise 'output file not updated when ref as config file build input' unless state
			state == :create
		end unless exec
	end
	raise 'config file build fail' unless raw_exec @command
	@outfiles.each{|file| file.state = :update if file.state == :exist}
end