add Application class; update CLI and Script for new architecture

This commit is contained in:
Josh Holtrop 2018-10-21 01:03:40 -04:00
parent ea6ae1be10
commit ac89a122d8
8 changed files with 199 additions and 164 deletions

View File

@ -1,4 +1,5 @@
require_relative "rscons/ansi" require_relative "rscons/ansi"
require_relative "rscons/application"
require_relative "rscons/build_target" require_relative "rscons/build_target"
require_relative "rscons/builder" require_relative "rscons/builder"
require_relative "rscons/cache" require_relative "rscons/cache"
@ -48,18 +49,13 @@ module Rscons
class << self class << self
# @return [Integer] # Access the Application singleton.
# The number of threads to use when scheduling subprocesses. #
attr_accessor :n_threads # @return [Application]
# The Application singleton.
# @return [Boolean] def application
# Whether to output ANSI color escape sequences. @application ||= Application.new
attr_accessor :do_ansi_color end
# @since 1.16.0
# @return [VarSet]
# Access any variables set on the rscons command-line.
attr_reader :vars
# Remove all generated files. # Remove all generated files.
# #
@ -200,46 +196,8 @@ module Rscons
end.sort end.sort
end end
private
# Determine the number of threads to use by default.
#
# @return [Integer]
# The number of threads to use by default.
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 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/
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
end
@n_threads = determine_n_threads
@vars = VarSet.new
end end
# Unbuffer $stdout # Unbuffer $stdout

View File

@ -12,7 +12,7 @@ module Rscons
# #
# @return [void] # @return [void]
def write(io, *message) def write(io, *message)
do_color = Rscons.do_ansi_color do_color = Rscons.application.do_ansi_color
if do_color.nil? if do_color.nil?
do_color = do_ansi?(io) do_color = do_ansi?(io)
end end

72
lib/rscons/application.rb Normal file
View File

@ -0,0 +1,72 @@
module Rscons
# Functionality for an instance of the rscons application invocation.
class Application
# @return [Boolean]
# Whether to output ANSI color escape sequences.
attr_accessor :do_ansi_color
# @return [Integer]
# The number of threads to use when scheduling subprocesses.
attr_accessor :n_threads
# @return [VarSet]
# Access any variables set on the rscons command-line.
attr_reader :vars
def initialize
@vars = VarSet.new
@n_threads = determine_n_threads
end
# Run the specified operation.
#
# @param operation [String]
# The operation to perform (e.g. "clean", "configure", "build", etc...)
#
# @return [Integer]
# Process exit code (0 on success).
def run(operation)
# TODO
0
end
private
# Determine the number of threads to use by default.
#
# @return [Integer]
# The number of threads to use by default.
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/
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
end
end

View File

@ -22,7 +22,7 @@ Configure options:
--prefix=PREFIX Set installation prefix (default: /usr/local) --prefix=PREFIX Set installation prefix (default: /usr/local)
Build options: Build options:
-j N, --nthreads=N Set number of threads (local default: #{Rscons.n_threads}) -j N, --nthreads=N Set number of threads (local default: #{Rscons.application.n_threads})
EOF EOF
@ -44,56 +44,45 @@ module Rscons
def run(argv) def run(argv)
argv = argv.dup argv = argv.dup
rsconsfile = nil rsconsfile = nil
do_help = false
OptionParser.new do |opts| OptionParser.new do |opts|
opts.banner = "Usage: #{$0} [options]" opts.banner = "Usage: #{$0} [options]"
opts.on("-f FILE", "Execute FILE (default Rsconsfile)") do |f| opts.on("-f FILE") do |f|
rsconsfile = f rsconsfile = f
end end
opts.on("-j NTHREADS", "Use NTHREADS parallel jobs (local default #{Rscons.n_threads})") do |n_threads| opts.on("-j NTHREADS") do |n_threads|
Rscons.n_threads = n_threads.to_i Rscons.application.n_threads = n_threads.to_i
end end
opts.on("-r", "--color MODE", "Set color mode (off, auto, force)") do |color_mode| opts.on("-r", "--color MODE") do |color_mode|
case color_mode case color_mode
when "off" when "off"
Rscons.do_ansi_color = false Rscons.application.do_ansi_color = false
when "force" when "force"
Rscons.do_ansi_color = true Rscons.application.do_ansi_color = true
end end
end end
opts.on("--version", "Show version") do opts.on("--version") do
puts "Rscons version #{Rscons::VERSION}" puts "Rscons version #{Rscons::VERSION}"
exit 0 exit 0
end end
opts.on("-h", "--help", "Show this help.") do opts.on("-h", "--help") do
puts USAGE do_help = true
exit 0
end end
end.order!(argv) end.order!(argv)
if argv.empty? # Retrieve the operation, or default to build.
puts USAGE operation = argv.shift || "build"
exit 0
end
case argv.first
when "clean"
Rscons.clean
exit 0
when "configure"
# TODO
exit 0
end
argv.each do |arg| argv.each do |arg|
if arg =~ /^([^=]+)=(.*)$/ if arg =~ /^([^=]+)=(.*)$/
Rscons.vars[$1] = $2 Rscons.application.vars[$1] = $2
end end
end end
@ -113,13 +102,15 @@ module Rscons
end end
end end
begin script = Script.new
load rsconsfile script.load(rsconsfile)
rescue Rscons::BuildError => e
exit 1
end
if do_help
puts USAGE
exit 0 exit 0
else
exit Rscons.application.run(operation)
end
end end
end end

View File

@ -19,7 +19,8 @@ module Rscons
# @return [Integer] # @return [Integer]
# The number of threads to use for this Environment. If nil (the # The number of threads to use for this Environment. If nil (the
# default), the global Rscons.n_threads default value will be used. # default), the global Rscons.application.n_threads default value will be
# used.
attr_writer :n_threads attr_writer :n_threads
# Set the build root. # Set the build root.
@ -871,7 +872,7 @@ module Rscons
# @return [Integer] # @return [Integer]
# Number of threads to use for parallelized builds in this Environment. # Number of threads to use for parallelized builds in this Environment.
def n_threads def n_threads
@n_threads || Rscons.n_threads @n_threads || Rscons.application.n_threads
end end
# Print the builder run message, depending on the Environment's echo mode. # Print the builder run message, depending on the Environment's echo mode.

View File

@ -4,22 +4,30 @@ module Rscons
# the DSL for the build script to use. # the DSL for the build script to use.
class Script class Script
class << self # @return [String, nil]
# Project name.
attr_accessor :project_name
# @return [Boolean]
# Whether to autoconfigure if the user does not explicitly perform a
# configure operation before building (default: true).
attr_accessor :autoconf
# Construct a Script.
def initialize
@project_name = nil
@autoconf = true
end
# Load a script from the specified file. # Load a script from the specified file.
# #
# @param path [String] # @param path [String]
# File name of the rscons script to load. # File name of the rscons script to load.
# #
# @return [Script] # @return [void]
# The loaded script state.
def load(path) def load(path)
script_contents = File.read(path, mode: "rb") script_contents = File.read(path, mode: "rb")
script = Script.new self.instance_eval(script_contents, path, 1)
script.instance_eval(script_contents, path, 1)
script
end
end end
end end

View File

@ -0,0 +1,71 @@
module Rscons
describe Application do
describe ".determine_n_threads" do
context "when specified by environment variable" do
before(:each) do
expect(ENV).to receive(:[]).with("RSCONS_NTHREADS").and_return("3")
end
it "returns the user-specified number of threads to use" do
expect(Rscons.application.__send__(:determine_n_threads)).to eq(3)
end
end
context "when not specified by environment variable" do
before(:each) do
expect(ENV).to receive(:[]).with("RSCONS_NTHREADS").and_return(nil)
end
context "on Linux" do
before(:each) do
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return("linux")
end
it "returns the number of processors from /proc/cpuinfo" do
expect(File).to receive(:read).with("/proc/cpuinfo").and_return(<<EOF)
processor : 0
processor : 1
EOF
expect(Rscons.application.__send__(:determine_n_threads)).to eq(2)
end
end
context "on Windows" do
before(:each) do
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return("mingw")
end
it "returns the number of logical processors that wmic reports" do
expect(Rscons).to receive(:`).with("wmic cpu get NumberOfLogicalProcessors /value").and_return("NumberOfLogicalProcessors=7")
expect(Rscons.application.__send__(:determine_n_threads)).to eq(7)
end
end
context "on Darwin" do
before(:each) do
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return("darwin")
end
it "returns the number of threads that sysctl reports" do
expect(Rscons).to receive(:`).with("sysctl -n hw.ncpu").and_return("6")
expect(Rscons.application.__send__(:determine_n_threads)).to eq(6)
end
end
context "on an unknown platform" do
before(:each) do
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return("other")
end
it "returns 1" do
expect(Rscons.application.__send__(:determine_n_threads)).to eq(1)
end
end
context "when an error occurs" do
it "returns 1" do
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_raise("foo")
expect(Rscons.application.__send__(:determine_n_threads)).to eq(1)
end
end
end
end
end
end

View File

@ -150,70 +150,4 @@ describe Rscons do
end end
end end
end end
describe ".determine_n_threads" do
context "when specified by environment variable" do
before(:each) do
expect(ENV).to receive(:[]).with("RSCONS_NTHREADS").and_return("3")
end
it "returns the user-specified number of threads to use" do
expect(Rscons.__send__(:determine_n_threads)).to eq(3)
end
end
context "when not specified by environment variable" do
before(:each) do
expect(ENV).to receive(:[]).with("RSCONS_NTHREADS").and_return(nil)
end
context "on Linux" do
before(:each) do
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return("linux")
end
it "returns the number of processors from /proc/cpuinfo" do
expect(File).to receive(:read).with("/proc/cpuinfo").and_return(<<EOF)
processor : 0
processor : 1
EOF
expect(Rscons.__send__(:determine_n_threads)).to eq(2)
end
end
context "on Windows" do
before(:each) do
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return("mingw")
end
it "returns the number of logical processors that wmic reports" do
expect(Rscons).to receive(:`).with("wmic cpu get NumberOfLogicalProcessors /value").and_return("NumberOfLogicalProcessors=7")
expect(Rscons.__send__(:determine_n_threads)).to eq(7)
end
end
context "on Darwin" do
before(:each) do
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return("darwin")
end
it "returns the number of threads that sysctl reports" do
expect(Rscons).to receive(:`).with("sysctl -n hw.ncpu").and_return("6")
expect(Rscons.__send__(:determine_n_threads)).to eq(6)
end
end
context "on an unknown platform" do
before(:each) do
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return("other")
end
it "returns 1" do
expect(Rscons.__send__(:determine_n_threads)).to eq(1)
end
end
context "when an error occurs" do
it "returns 1" do
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_raise("foo")
expect(Rscons.__send__(:determine_n_threads)).to eq(1)
end
end
end
end
end end