Class: Rmk

Inherits:
Object
  • Object
show all
Defined in:
lib/rmk/rmk.rb,
lib/rmk/vars.rb,
lib/rmk/version.rb,
lib/rmk/schedule.rb

Defined Under Namespace

Modules: Schedule Classes: Build, MultiVarWriter, Rule, Storage, VDir, VFile, VOutDir, Vars

Constant Summary collapse

VERSION =
"0.1.0"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(srcroot: '', outroot: '') ⇒ Rmk

create Rmk object

Parameters:

  • srcroot (String) (defaults to: '')

    source root dir,can be absolute or relative to output root(start with ..)

  • outroot (String) (defaults to: '')

    output root dir,can be absolute or relative to pwd,default pwd



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/rmk/rmk.rb', line 14

def initialize(srcroot:'', outroot:'')
  @files_mutex = Thread::Mutex.new # files operate mutex


  srcroot = Rmk.normalize_path srcroot
  @outroot = File.join Rmk.normalize_path(File.absolute_path outroot), ''
  @srcroot = File.join File.absolute_path(srcroot, @outroot), ''
  raise "source path '#{@srcroot}' not exist or not directory" unless ::Dir.exist?(@srcroot)
  warn 'in-source build' if @outroot == @srcroot
  @src_relative = srcroot.match?(/^\.\./) && File.join(srcroot, '')
  Dir.mkdir @outroot unless Dir.exist? @outroot
  Dir.chdir @outroot
  Dir.mkdir '.rmk' unless Dir.exist? '.rmk'
  @mid_storage = Rmk::Storage.new '.rmk/mid', {}
  @dep_storage = Rmk::Storage.new '.rmk/dep', {}
  @cml_storage = Rmk::Storage.new '.rmk/cml', {} # command line text storage

  @srcfiles = {}
  @outfiles = {}
  @defaultfiles = []
  @vars = {'srcroot'=>@srcroot[0..-2], 'outroot'=>@outroot[0..-2], 'src_rto_root'=>(@src_relative || @srcroot)[0..-2]}.freeze
  @virtual_root = Rmk::VDir.new self, nil
end

Instance Attribute Details

#cml_storageObject (readonly)

Returns the value of attribute cml_storage.



36
37
38
# File 'lib/rmk/rmk.rb', line 36

def cml_storage
  @cml_storage
end

#dep_storageObject (readonly)

Returns the value of attribute dep_storage.



36
37
38
# File 'lib/rmk/rmk.rb', line 36

def dep_storage
  @dep_storage
end

#mid_storageObject (readonly)

Returns the value of attribute mid_storage.



36
37
38
# File 'lib/rmk/rmk.rb', line 36

def mid_storage
  @mid_storage
end

#outfilesObject (readonly)

Returns the value of attribute outfiles.



35
36
37
# File 'lib/rmk/rmk.rb', line 35

def outfiles
  @outfiles
end

#outrootObject (readonly)

Returns the value of attribute outroot.



35
36
37
# File 'lib/rmk/rmk.rb', line 35

def outroot
  @outroot
end

#srcfilesObject (readonly)

Returns the value of attribute srcfiles.



35
36
37
# File 'lib/rmk/rmk.rb', line 35

def srcfiles
  @srcfiles
end

#srcrootObject (readonly)

Returns the value of attribute srcroot.



35
36
37
# File 'lib/rmk/rmk.rb', line 35

def srcroot
  @srcroot
end

#varsObject (readonly)

Returns the value of attribute vars.



35
36
37
# File 'lib/rmk/rmk.rb', line 35

def vars
  @vars
end

#virtual_rootObject (readonly)

Returns the value of attribute virtual_root.



35
36
37
# File 'lib/rmk/rmk.rb', line 35

def virtual_root
  @virtual_root
end

Class Method Details

.normalize_path(path) ⇒ String

Returns:

  • (String)


9
# File 'lib/rmk/rmk.rb', line 9

def self.normalize_path(path) path.gsub(?\\, ?/).sub(/^[a-z](?=:)/){|ch|ch.upcase} end

Instance Method Details

#add_default(*files) ⇒ Object

add default target



143
# File 'lib/rmk/rmk.rb', line 143

def add_default(*files) @files_mutex.synchronize{@defaultfiles.concat files} end

#add_out_file(path:, vpath: nil) ⇒ Rmk::VFile

register a out file

Parameters:

  • path (String)
  • vpath (String) (defaults to: nil)

Returns:



124
125
126
127
128
129
130
# File 'lib/rmk/rmk.rb', line 124

def add_out_file(path:, vpath:nil)
  @files_mutex.synchronize do
    raise "file '#{path}' has been defined" if @outfiles.include? path
    file = @srcfiles.delete(path).change_to_out! file if @srcfiles.include? path
    @outfiles[path] = VFile.new rmk:self, path:path, vpath:vpath
  end
end

#add_src_file(path:, vpath: nil) ⇒ Rmk::VFile

register a src file

Parameters:

  • path (String)
  • vpath (String) (defaults to: nil)

Returns:



136
137
138
139
140
# File 'lib/rmk/rmk.rb', line 136

def add_src_file(path:, vpath:nil)
  @files_mutex.synchronize do
    @outfiles[path] || (@srcfiles[path] ||= VFile.new(rmk:self, path:path, vpath:vpath, is_src:true))
  end
end

#build(*tgts) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/rmk/rmk.rb', line 157

def build(*tgts)
  puts 'Rmk: build start'
  if tgts.empty?
    files = @defaultfiles
  else
    files = tgts.map do |name|
      file = Rmk.normalize_path name
      file = @outfiles[File.absolute_path file, @outroot] || @srcfiles[File.absolute_path file, @srcroot]
      raise "build target '#{name}' not found" unless file
      file = file.input_ref_builds[0].outfiles[0] if file.src? && file.input_ref_builds.size == 1
      file
    end
  end
  if files.empty?
    @srcfiles.each_value{|file| file.check_for_build}
  else
    checklist = []
    checkproc = proc do |fi|
      next checklist << fi if fi.src?
      fi.output_ref_build.infiles.each &checkproc
      fi.output_ref_build.depfiles.each &checkproc
      fi.output_ref_build.orderfiles.each &checkproc
    end
    files.each &checkproc
    exit puts('found nothing to build') || 0 if checklist.empty?
    checklist.each {|file| file.check_for_build}
  end
  while Thread.list.size > 1
    thr = Thread.list[-1]
    thr.join unless thr == Thread.current
  end
  puts 'Rmk: build end'
  @mid_storage.save
  @dep_storage.data!.each_key {|key| @dep_storage.data!.delete key unless @outfiles.include? key}
  @dep_storage.save
  @cml_storage.data!.each_key {|key| @cml_storage.data!.delete key unless @outfiles.include? key}
  @cml_storage.save
end

#find_inputfiles(pattern, ffile: false) ⇒ Array<VFile, FFile>

find files which can be build’s imput file

Parameters:

  • pattern (String)

    absolute path to find src and out files which can include ‘*’ to match any char at last no dir part

  • ffile (Boolean) (defaults to: false)

    return FFile struct or not

Returns:

  • (Array<VFile, FFile>)

    return array of FFile when ffile, otherwise array of VFile



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/rmk.rb', line 59

def find_inputfiles(pattern, ffile:false)
  pattern = Rmk.normalize_path pattern
  path, regex, postpath = split_path_pattern pattern
  files = []
  if regex
    @files_mutex.synchronize do
      find_outfiles_imp files, path, regex, postpath, ffile:ffile
      range = postpath ? path.size..-1-postpath.size : path.size..-1
      Dir[pattern].each do |fn|
        next if @outfiles.include? fn
        next files << (ffile ? FFile.new(@srcfiles[fn], nil, fn[range][regex, 1]) : @srcfiles[fn]) if @srcfiles.include? fn
        file = (@srcfiles[fn] = VFile.new rmk:self, path:fn, is_src:true,
          vpath:fn.start_with?(@srcroot) && fn[@srcroot.size .. -1])
        files << (ffile ? FFile.new(file, nil, fn[range][regex, 1]) : file)
      end
    end
  else
    @files_mutex.synchronize do
      next files << (ffile ? FFile.new(@outfiles[path]) : @outfiles[path]) if @outfiles.include? path
      next files << (ffile ? FFile.new(@srcfiles[path]) : @srcfiles[path]) if @srcfiles.include? path
      next unless File.exist? path
      file = @srcfiles[path] = VFile.new rmk:self, path:path, is_src:true,
          vpath:path.start_with?(@srcroot) && path[@srcroot.size .. -1]
      files << (ffile ? FFile.new(file) : file)
    end
  end
  files
end

#find_outfiles(pattern) ⇒ Array<Hash>

find files which must be build’s output

Parameters:

  • pattern (String)

    absolute path to find out files which can include ‘*’ to match any char at last no dir part

Returns:

  • (Array<Hash>)

    return Array of file, and Regex when has ‘*’ pattern



91
92
93
94
95
96
97
98
99
# File 'lib/rmk/rmk.rb', line 91

def find_outfiles(pattern)
  path, regex, postpath = split_path_pattern Rmk.normalize_path pattern
  files = []
  @files_mutex.synchronize do
    next (files << @outfiles[path] if @outfiles.include? path) unless regex
    find_outfiles_imp files, path, regex, postpath
  end
  files
end

#join_abs_src_path(path) ⇒ Object



38
# File 'lib/rmk/rmk.rb', line 38

def join_abs_src_path(path) File.join @srcroot, path end

#join_rto_src_path(path) ⇒ Object

join src file path relative to out root, or absolute src path when not relative src



41
# File 'lib/rmk/rmk.rb', line 41

def join_rto_src_path(path) ::File.join @src_relative ? @src_relative : @srcroot, path end

#parseself

parse project

Returns:

  • (self)


147
148
149
150
151
152
153
154
155
# File 'lib/rmk/rmk.rb', line 147

def parse
  puts 'Rmk: parse start'
  @mid_storage.wait_ready
  @dep_storage.wait_ready
  @cml_storage.wait_ready
  @virtual_root.parse
  puts 'Rmk: parse done'
  self
end

#split_path_pattern(pattern) ⇒ Object

split path pattern to dir part and file match regex part when pattern include ‘*’, return [dir part, file(or dir) match regex, post dir part, post file part] ;otherwise return [origin pattern, nil, nil, nil]

Parameters:

  • pattern (String)

    absolute path, can include ‘*’ to match any char at last no dir part



47
48
49
50
51
52
53
# File 'lib/rmk/rmk.rb', line 47

def split_path_pattern(pattern)
  match = /^([a-zA-Z]:\/(?:[^\/*]+\/)*+)([^\/*]*+)(?:\*([^\/*]*+))?(?(3)(\/(?:[^\/*]+\/)*+[^\/*]++)?)$/.match pattern
  raise "file syntax '#{pattern}' error" unless match
  dir, prefix, postfix, postpath = *match[1..5]
  regex = postfix && /#{Regexp.escape prefix}(.*)#{Regexp.escape postfix}$/
  [regex ? dir : pattern, regex, postpath]
end