Module: Rscons::Util

Defined in:
lib/rscons/util.rb

Overview

A collection of stand-alone utility methods.

Class Method Summary collapse

Class Method Details

.absolute_path(path) ⇒ String, ...

Return the absolute path for a given target if not a phony target.

Parameters:

  • path (String, Symbol, nil)

    Given target name.

Returns:

  • (String, Symbol, nil)

    Absolute path of given target.



26
27
28
29
30
31
32
# File 'lib/rscons/util.rb', line 26

def absolute_path(path)
  if path.is_a?(String)
    File.expand_path(path)
  else
    path
  end
end

.absolute_path?(path) ⇒ Boolean

Return whether the given path is an absolute filesystem path.

Parameters:

  • path (String)

    the path to examine.

Returns:

  • (Boolean)

    Whether the given path is an absolute filesystem path.



11
12
13
14
15
16
17
# File 'lib/rscons/util.rb', line 11

def absolute_path?(path)
  if RUBY_PLATFORM =~ /mingw|msys/
    path =~ %r{^(?:\w:)?[\\/]}
  else
    path.start_with?("/")
  end
end

.clean_d_precompile_path(pc_path, import_path) ⇒ void

This method returns an undefined value.

Remove any stale .di files from the precompile path.

Parameters:

  • pc_path (String)

    Path to precompile build directory containing .di generated interface files.

  • import_path (String)

    D import path containing .d source files.



43
44
45
46
47
48
49
50
51
# File 'lib/rscons/util.rb', line 43

def clean_d_precompile_path(pc_path, import_path)
  glob("#{pc_path}/**/*.di").each do |di_path|
    end_path = di_path[(pc_path.size+1)..]
    path = "#{import_path}/#{end_path}".sub(/\.di$/, ".d")
    unless File.exist?(path)
      FileUtils.rm_f(di_path)
    end
  end
end

.colorize_markup(message) ⇒ Array

Colorize a builder run message.

Parameters:

  • message (String)

    Builder run message.

Returns:

  • (Array)

    Colorized message with color codes for Ansi module.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/rscons/util.rb', line 60

def colorize_markup(message)
  if message =~ /^(.*?)(<[^>]+>)(.*)$/
    prefix, code, suffix = $1, $2, $3
    case code
    when "<target>"
      code = :magenta
    when "<source>"
      code = :cyan
    when "<reset>"
      code = :reset
    end
    [prefix, code, *colorize_markup(suffix)].delete_if {|v| v == ""}
  else
    [message]
  end
end

.command_to_execute_meObject

Command that can be run to execute this instance of rscons from the current working directory.



348
349
350
351
352
# File 'lib/rscons/util.rb', line 348

def command_to_execute_me
  command = Pathname.new(File.expand_path($0)).relative_path_from(Dir.pwd).to_s
  command = "./#{command}" unless command["/"]
  command
end

.command_to_s(command) ⇒ String

Return a string representation of a command.

Parameters:

  • command (Array<String>)

    The command.

Returns:

  • (String)

    The string representation of the command.



84
85
86
# File 'lib/rscons/util.rb', line 84

def command_to_s(command)
  command.map { |c| c[" "] ? "'#{c.gsub("'", "'\\\\''")}'" : c }.join(" ")
end

.determine_n_threadsInteger

Determine the number of threads to use by default.

Returns:

  • (Integer)

    The number of threads to use by default.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/rscons/util.rb', line 92

def determine_n_threads
  # If the user specifies the number of threads in the environment, then
  # respect that.
  if ENV["RSCONS_NTHREADS"] =~ /^(\d+)$/
    return $1.to_i
  end

  # Otherwise try to figure out how many threads are available on the
  # host hardware.
  begin
    case RbConfig::CONFIG["host_os"]
    when /linux/
      return File.read("/proc/cpuinfo").scan(/^processor\s*:/).size
    when /mswin|mingw|msys/
      if `wmic cpu get NumberOfLogicalProcessors -value` =~ /NumberOfLogicalProcessors=(\d+)/
        return $1.to_i
      end
    when /darwin/
      if `sysctl -n hw.ncpu` =~ /(\d+)/
        return $1.to_i
      end
    end
  rescue
  end

  # If we can't figure it out, default to 1.
  1
end

.find_executable(name) ⇒ String?

Look for an executable.

Returns:

  • (String, nil)

    Executable path, if found.



142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/rscons/util.rb', line 142

def find_executable(name)
  if name["/"] or name["\\"]
    if File.file?(name) and File.executable?(name)
      return name
    end
  else
    path_entries = ENV["PATH"].split(File::PATH_SEPARATOR)
    path_entries.find do |path_entry|
      if path = test_path_for_executable(path_entry, name)
        return path
      end
    end
  end
end

.find_import_path_for_d_source(import_paths, source, module_name) ⇒ String?

Find the D import path that will be used to import the given module.

Parameters:

  • import_paths (Array<String>)

    Import paths.

  • source (String)

    Source file name.

  • module_name (String)

    Module name.

Returns:

  • (String, nil)

    Import path used to import the given module.



168
169
170
171
172
173
174
175
176
177
178
# File 'lib/rscons/util.rb', line 168

def find_import_path_for_d_source(import_paths, source, module_name)
  source = source.gsub("\\", "/")
  module_path = module_name.gsub(".", "/") + ".d"
  import_paths.each do |import_path|
    path = "#{import_path}/#{module_path}".gsub("\\", "/")
    if path == source
      return import_path
    end
  end
  nil
end

.format_elapsed_time(elapsed) ⇒ String

Format an elapsed time in human-readable format.

Returns:

  • (String)

    Elapsed time in human-readable format.



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/rscons/util.rb', line 184

def format_elapsed_time(elapsed)
  hours = (elapsed / (60 * 60)).to_i
  elapsed -= hours * 60 * 60
  minutes = (elapsed / 60).to_i
  elapsed -= minutes * 60
  seconds = elapsed.ceil
  result = ""
  if hours > 0
    result += "#{hours}h "
  end
  if hours > 0 || minutes > 0
    result += "#{minutes}m "
  end
  result += "#{seconds}s"
  result
end

.get_module_name(source_path) ⇒ String?

Get the module name for a D source file.

Parameters:

  • source_path (String)

    D source file.

Returns:

  • (String, nil)

    Module name.



208
209
210
211
212
213
214
215
216
217
218
# File 'lib/rscons/util.rb', line 208

def get_module_name(source_path)
  if File.exist?(source_path)
    if File.binread(source_path) =~ /^\s*module\s(\S*);/
      return $1
    end
    name = File.basename(source_path).sub(/\.d$/, "")
    if name =~ /^\w+$/
      return name
    end
  end
end

.glob(*patterns) ⇒ Array<String>

Return a list of paths matching the specified pattern(s).

A pattern can contain a “/**” component to recurse through directories. If the pattern ends with “/**” then only the recursive list of directories will be returned.

Examples:

  • “src/**”: return all directories under “src”, recursively (including “src” itself).

  • “src/*/”: return all files and directories recursively under the src directory.

  • “src/*/.c”: return all .c files recursively under the src directory.

  • “dir/*/”: return all directories in dir, but no files.

Returns:

  • (Array<String>)

    Paths matching the specified pattern(s).



235
236
237
238
239
240
241
242
243
244
245
# File 'lib/rscons/util.rb', line 235

def glob(*patterns)
  require "pathname"
  patterns.reduce([]) do |result, pattern|
    if pattern.end_with?("/**")
      pattern += "/"
    end
    result += Dir.glob(pattern).map do |path|
      Pathname.new(path.gsub("\\", "/")).cleanpath.to_s
    end
  end.sort
end

.make_relative_path(path) ⇒ String

Make a relative path corresponding to a possibly absolute one.

Parameters:

  • path (String)

    Input path that is possibly absolute.

Returns:

  • (String)

    Relative path.



254
255
256
257
258
259
260
261
262
263
264
# File 'lib/rscons/util.rb', line 254

def make_relative_path(path)
  if absolute_path?(path)
    if path =~ %r{^(\w):(.*)$}
      "_#{$1}#{$2}"
    else
      "_#{path}"
    end
  else
    path
  end
end

.parse_dependency_file(mf_fname) ⇒ Array<String>

Parse dependencies from a Makefile or ldc2 dependency file.

This method is used internally by Rscons builders.

Parameters:

  • mf_fname (String)

    File name of the Makefile to read.

Returns:

  • (Array<String>)

    Paths of dependency files.



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/rscons/util.rb', line 275

def parse_dependency_file(mf_fname)
  deps = []
  buildup = ''
  File.read(mf_fname).each_line do |line|
    if line =~ /^(.*)\\\s*$/
      buildup += ' ' + $1
    else
      buildup += ' ' + line
      if buildup =~ /^[^:]+\(\S+\)\s*:.*?:[^:]+\((\S+)\)/
        # ldc2-style dependency line
        deps << $1
      elsif buildup =~ /^.*: (.*)$/
        # Makefile-style dependency line
        mf_deps = $1
        deps += mf_deps.split(' ').map(&:strip)
      end
      buildup = ''
    end
  end
  deps
end

.short_format_paths(paths) ⇒ String

Return a string showing the path specified, or if more than one, then the first path with a “(+D)” afterward, where D is the number of remaining paths.

Parameters:

  • paths (Array<String>)

    Paths.

Returns:

  • (String)

    Condensed path readout.



130
131
132
133
134
135
136
# File 'lib/rscons/util.rb', line 130

def short_format_paths(paths)
  if paths.size == 1
    paths.first
  else
    "#{paths.first} (+#{paths.size - 1})"
  end
end

.task(name, options = {}, &block) ⇒ Task

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Create or modify a task.

Returns:

  • (Task)

    Created task.



303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/rscons/util.rb', line 303

def task(name, options = {}, &block)
  if name == "configure"
    Rscons.application.silent_configure = false
  end
  if task = Task.tasks[name]
    task.modify(options, &block)
  else
    task = Task.new(name, options, &block)
  end
  if name == "configure"
    if configuration_params = Cache.instance["configuration_data"]["params"]
      task.param_values.merge!(configuration_params)
    end
  end
  task
end

.wait_for_thread(*threads) ⇒ Thread

Wait for any of a number of threads to complete.

Parameters:

  • threads (Array<Thread>)

    Threads to wait for.

Returns:

  • (Thread)

    The Thread that completed.



327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/rscons/util.rb', line 327

def wait_for_thread(*threads)
  if threads.empty?
    raise "No threads to wait for"
  end
  queue = Queue.new
  threads.each do |thread|
    # Create a wait thread for each thread we're waiting for.
    Thread.new do
      begin
        thread.join
      ensure
        queue.push(thread)
      end
    end
  end
  # Wait for any thread to complete.
  queue.pop
end