Module: C

Defined in:
lib/rub/c.rb,
lib/rub/r/i/runner.rb

Overview

Core Module

Defined Under Namespace

Classes: Tag, TargetTag

Class Method Summary collapse

Class Method Details

.add_dir(dir) ⇒ Object

Add a directory to the build.

This will run the “dir.rub” file in that directory synchronously. Any values that that directory defines will be available when this call returns.

This function only runs scripts once, if the script has already run this function will return success without running the script, and as the script has already been run the exported values should be available.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/rub/r/i/runner.rb', line 63

def self.add_dir(dir)
  dir = C.path(dir)
  
  if not dir.directory?
    raise "\"#{dir}\" is not a directory!"
  end
  
  dir += 'dir.rub'
  if not dir.exist?
    raise "\"#{dir}\" does not exist!"
  end
  dir = dir.realpath
  
  R::I::Runner.do_file(dir)
end

.chash(o) ⇒ Object

Get a consistant hash of an object.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/rub/c.rb', line 62

def self.chash(o)
  if o.is_a? Array
    return o.map{|i| chash i}.join
  end
  
  # Super hacky, strip out object-ids, because they change every
  # invocation, but use inspect.  It works alright.
  r = o.inspect.gsub(/(?<!:):0x[0-9a-f]*/, '')
  
  # Modules don't print themselfs meaningfully.
  if o.is_a? Module
    r << o.pretty_print_instance_variables.map{|k| [k, o.instance_variable_get(k)] }.inspect
  end

  r  
end

.find_command(cmd) ⇒ Pathname?

Find an executable on the system.

This searches the system for execrable in the appropriate locations (example $PATH on UNIX).

This function caches its result both in memory and between Rub runs. Feel free to call it often.

Examples:

C::find_command 'true'    #=> #<Pathname:/usr/bin/true>
C::find_command 'cc'      #=> #<Pathname:/home/kevincox/.local/bin/cc>
C::find_command 'sl'      #=> #<Pathname:/usr/bin/sl>
C::find_command 'python'  #=> #<Pathname:/usr/bin/python>
C::find_command 'explode' #=> nil

Parameters:

  • cmd (String)

    The name of the command (basename only).

Returns:

  • (Pathname, nil)

    Pathname, or nil if not found.



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/rub/c.rb', line 243

def self.find_command(cmd)
  pn = Pathname.new(cmd)
  if pn.absolute?
    #return pn.executable? ? pn : nil
    return pn
  end
  
  exe = R.spersistant["C.find_command.#{cmd}"]
  
  exe and exe.executable? and return exe
  
  exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
  names = exts.map{|e| cmd+e}
  ENV['PATH'].split(File::PATH_SEPARATOR)
             .map{|d|Pathname.new(d)}
             .each do |d|
    names.each do |n|
      e = d + n
      #p e
      
      if e.executable?
        exe = e
        break
      end
    end
    
    exe and break
  end
  
  R.spersistant["C.find_command.#{cmd}"] = exe
end

.generator(src, cmd, out, desc: nil) ⇒ Array<Pathname>

Add a generator to the build

This function provides a simple api for creating R::TargetGenerator targets. It creates a target that simply runs one or more commands to transform it’s inputs into outputs. This interface handles all build caching and parallelization.

Parameters:

  • src (Array<Pathname,String>, Pathname, String)

    The source file or list of source files.

  • cmd (Array<Array<Pathname,String>>, Array<Pathname,String>)

    The command or list of commands to run. Commands will run in order.

  • out (Array<Pathname,String>, Pathname, String)

    The output files of the command.

  • desc (defaults to: nil)

    The verb for this step in the process. (See R::TargetGenerator#action)

Returns:

  • (Array<Pathname>)

    The output files. This will represent the same values passed in to the out parameter but it will be a new Array and all the values will be Pathnames.



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/rub/c.rb', line 208

def self.generator(src, cmd, out, desc: nil)
  t = R::TargetGenerator.new
  
  desc and t.action = desc
  
  src = R::Tool.make_set_paths(src)
  out = R::Tool.make_set_paths(out)
  cmd[0].is_a?(Array) or cmd = [cmd]
  
  t.input .merge(src)
  t.output.merge(out)
  t.add_cmds cmd
  
  t.register
  
  out
end

.glob(glob) ⇒ Set<Pathname>

Glob pathnames.

Parameters:

  • glob (String)

Returns:

  • (Set<Pathname>)

See Also:

  • Dir.glob


57
58
59
# File 'lib/rub/c.rb', line 57

def self.glob(glob)
  Set.new Dir.glob(glob).map{|e| C.path(e) }
end

.path(p) ⇒ Pathname

Expand a path.

Returns:

  • (Pathname)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/rub/c.rb', line 32

def self.path(p)
  p.is_a? Symbol   and return p
  p.is_a? Pathname and return p.expand_path
  p = p.to_s
  
  #p = case p[0]
  #  when '!'
  #    Pathname.new(p[1..-1])
  #  when '>'
  #    R::Env.out_dir + p[1..-1]
  #  when '<'
  #    R::Env.src_dir + p[1..-1]
  #  else
  #    Pathname.new(p)
  #end
  
  Pathname.new(p).expand_path
end

.tag(t) ⇒ Tag

Get a tag.

If the tag already exists it returns the existing Tag object otherwise it creates and returns a new Tag instance.

Parameters:

  • t (Symbol)

    The tag name.

Returns:

  • (Tag)

    The tag object.



179
180
181
# File 'lib/rub/c.rb', line 179

def self.tag(t)
  R.find_target(t) || Tag.new(t)
end

.unique_path(base, seed) ⇒ Object

Return a probably unique file name.

This file can be used as a build target.

Parameters:

  • base (String)

    The basename of the file.

  • seed (Object)

    A value to use for the folder name, keeping this the same across invocations allows predictable names, preventing unnecessary rebuilds.



100
101
102
# File 'lib/rub/c.rb', line 100

def self.unique_path(base, seed)
  R::Env.out_dir + 'c/unique/' + unique_segment(seed) + base
end

.unique_segment(*seed) ⇒ Object

Create a probably unique path segment.

Creates a string in the form ‘$stuff/’ that will probably be unique.

Parameters:

  • seed (Object)

    A value to use for the folder name, keeping this the same across invocations allows predictable names, preventing unnecessary rebuilds.



86
87
88
89
90
# File 'lib/rub/c.rb', line 86

def self.unique_segment(*seed)
  seed ||= caller_locations(1,1)
  
  return Digest::SHA1.hexdigest(chash(seed))
end