custom config checks - close #108
This commit is contained in:
parent
d202e15a57
commit
0ccf43cc96
26
build_tests/configure/custom_config_check.rb
Normal file
26
build_tests/configure/custom_config_check.rb
Normal file
@ -0,0 +1,26 @@
|
||||
configure do
|
||||
custom_check("Checking 'grep' version") do |op|
|
||||
stdout, stderr, status = op.log_and_test_command(%w[grep --version])
|
||||
should_fail = true
|
||||
if status != 0
|
||||
fail_message = "error executing grep"
|
||||
elsif stdout =~ /^grep \(GNU grep\) 1\./
|
||||
fail_message = "too old!"
|
||||
status = 1
|
||||
elsif stdout =~ /^grep \(GNU grep\) 2\./
|
||||
fail_message = "we'll work with it but you should upgrade"
|
||||
status = 1
|
||||
should_fail = false
|
||||
op.store_merge("CPPDEFINES" => "GREP_WORKAROUND")
|
||||
else
|
||||
op.store_append("CPPDEFINES" => "GREP_FULL")
|
||||
end
|
||||
op.complete(status, success_message: "good!", fail_message: fail_message, fail: should_fail)
|
||||
end
|
||||
end
|
||||
|
||||
build do
|
||||
Environment.new do |env|
|
||||
puts env["CPPDEFINES"]
|
||||
end
|
||||
end
|
@ -69,7 +69,7 @@ module Rscons
|
||||
cc = ccc.find do |cc|
|
||||
test_c_compiler(cc)
|
||||
end
|
||||
common_config_checks(cc ? 0 : 1, success_message: cc)
|
||||
complete(cc ? 0 : 1, success_message: cc)
|
||||
end
|
||||
|
||||
# Check for a working C++ compiler.
|
||||
@ -87,7 +87,7 @@ module Rscons
|
||||
cc = ccc.find do |cc|
|
||||
test_cxx_compiler(cc)
|
||||
end
|
||||
common_config_checks(cc ? 0 : 1, success_message: cc)
|
||||
complete(cc ? 0 : 1, success_message: cc)
|
||||
end
|
||||
|
||||
# Check for a working D compiler.
|
||||
@ -105,7 +105,7 @@ module Rscons
|
||||
dc = cdc.find do |dc|
|
||||
test_d_compiler(dc)
|
||||
end
|
||||
common_config_checks(dc ? 0 : 1, success_message: dc)
|
||||
complete(dc ? 0 : 1, success_message: dc)
|
||||
end
|
||||
|
||||
# Check for a package or configure program output.
|
||||
@ -122,7 +122,7 @@ module Rscons
|
||||
if status == 0
|
||||
store_parse(stdout, options)
|
||||
end
|
||||
common_config_checks(status, options)
|
||||
complete(status, options)
|
||||
end
|
||||
|
||||
# Check for a C header.
|
||||
@ -158,7 +158,7 @@ module Rscons
|
||||
break
|
||||
end
|
||||
end
|
||||
common_config_checks(status, options)
|
||||
complete(status, options)
|
||||
end
|
||||
|
||||
# Check for a C++ header.
|
||||
@ -194,7 +194,7 @@ module Rscons
|
||||
break
|
||||
end
|
||||
end
|
||||
common_config_checks(status, options)
|
||||
complete(status, options)
|
||||
end
|
||||
|
||||
# Check for a D import.
|
||||
@ -230,7 +230,7 @@ module Rscons
|
||||
break
|
||||
end
|
||||
end
|
||||
common_config_checks(status, options)
|
||||
complete(status, options)
|
||||
end
|
||||
|
||||
# Check for a library.
|
||||
@ -268,14 +268,113 @@ module Rscons
|
||||
if status == 0
|
||||
store_append({"LIBS" => [lib]}, options)
|
||||
end
|
||||
common_config_checks(status, options)
|
||||
complete(status, options)
|
||||
end
|
||||
|
||||
# Check for a executable program.
|
||||
def check_program(program, options = {})
|
||||
Ansi.write($stdout, "Checking for program '", :cyan, program, :reset, "'... ")
|
||||
path = Util.find_executable(program)
|
||||
common_config_checks(path ? 0 : 1, options.merge(success_message: path))
|
||||
complete(path ? 0 : 1, options.merge(success_message: path))
|
||||
end
|
||||
|
||||
# Execute a test command and log the result.
|
||||
#
|
||||
# @return [String, String, Process::Status]
|
||||
# stdout, stderr, status
|
||||
def log_and_test_command(command)
|
||||
begin
|
||||
@log_fh.puts("Command: #{command.join(" ")}")
|
||||
stdout, stderr, status = Open3.capture3(*command)
|
||||
@log_fh.puts("Exit status: #{status.to_i}")
|
||||
@log_fh.write(stdout)
|
||||
@log_fh.write(stderr)
|
||||
[stdout, stderr, status]
|
||||
rescue Errno::ENOENT
|
||||
["", "", 127]
|
||||
end
|
||||
end
|
||||
|
||||
# Store construction variables for merging into the Cache.
|
||||
#
|
||||
# @param vars [Hash]
|
||||
# Hash containing the variables to merge.
|
||||
# @param options [Hash]
|
||||
# Options.
|
||||
def store_merge(vars, options = {})
|
||||
store_vars = store_common(options)
|
||||
store_vars["merge"] ||= {}
|
||||
vars.each_pair do |key, value|
|
||||
store_vars["merge"][key] = value
|
||||
end
|
||||
end
|
||||
|
||||
# Store construction variables for appending into the Cache.
|
||||
#
|
||||
# @param vars [Hash]
|
||||
# Hash containing the variables to append.
|
||||
# @param options [Hash]
|
||||
# Options.
|
||||
def store_append(vars, options = {})
|
||||
store_vars = store_common(options)
|
||||
store_vars["append"] ||= {}
|
||||
vars.each_pair do |key, value|
|
||||
if store_vars["append"][key].is_a?(Array) and value.is_a?(Array)
|
||||
store_vars["append"][key] += value
|
||||
else
|
||||
store_vars["append"][key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Store flags to be parsed into the Cache.
|
||||
#
|
||||
# @param flags [String]
|
||||
# String containing the flags to parse.
|
||||
# @param options [Hash]
|
||||
# Options.
|
||||
def store_parse(flags, options = {})
|
||||
store_vars = store_common(options)
|
||||
store_vars["parse"] ||= []
|
||||
store_vars["parse"] << flags
|
||||
end
|
||||
|
||||
# Perform processing common to several configure checks.
|
||||
#
|
||||
# @param status [Process::Status, Integer]
|
||||
# Process exit code. 0 for success, non-zero for error.
|
||||
# @param options [Hash]
|
||||
# Common check options.
|
||||
# @option options [Boolean] :fail
|
||||
# Whether to fail configuration if the requested item is not found.
|
||||
# This defaults to true if the :set_define option is not specified,
|
||||
# otherwise defaults to false if :set_define option is specified.
|
||||
# @option options [String] :set_define
|
||||
# A define to set (in CPPDEFINES) if the requested item is found.
|
||||
# @option options [String] :success_message
|
||||
# Message to print on success (default "found").
|
||||
def complete(status, options)
|
||||
success_message = options[:success_message] || "found"
|
||||
fail_message = options[:fail_message] || "not found"
|
||||
if status == 0
|
||||
Ansi.write($stdout, :green, "#{success_message}\n")
|
||||
if options[:set_define]
|
||||
store_append("CPPDEFINES" => [options[:set_define]])
|
||||
end
|
||||
else
|
||||
should_fail =
|
||||
if options.has_key?(:fail)
|
||||
options[:fail]
|
||||
else
|
||||
!options[:set_define]
|
||||
end
|
||||
if should_fail
|
||||
Ansi.write($stdout, :red, "#{fail_message}\n")
|
||||
raise ConfigureFailure.new
|
||||
else
|
||||
Ansi.write($stdout, :yellow, "#{fail_message}\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
@ -381,64 +480,6 @@ module Rscons
|
||||
end
|
||||
end
|
||||
|
||||
# Execute a test command and log the result.
|
||||
def log_and_test_command(command)
|
||||
begin
|
||||
@log_fh.puts("Command: #{command.join(" ")}")
|
||||
stdout, stderr, status = Open3.capture3(*command)
|
||||
@log_fh.puts("Exit status: #{status.to_i}")
|
||||
@log_fh.write(stdout)
|
||||
@log_fh.write(stderr)
|
||||
[stdout, stderr, status]
|
||||
rescue Errno::ENOENT
|
||||
["", "", 127]
|
||||
end
|
||||
end
|
||||
|
||||
# Store construction variables for merging into the Cache.
|
||||
#
|
||||
# @param vars [Hash]
|
||||
# Hash containing the variables to merge.
|
||||
# @param options [Hash]
|
||||
# Options.
|
||||
def store_merge(vars, options = {})
|
||||
store_vars = store_common(options)
|
||||
store_vars["merge"] ||= {}
|
||||
vars.each_pair do |key, value|
|
||||
store_vars["merge"][key] = value
|
||||
end
|
||||
end
|
||||
|
||||
# Store construction variables for appending into the Cache.
|
||||
#
|
||||
# @param vars [Hash]
|
||||
# Hash containing the variables to append.
|
||||
# @param options [Hash]
|
||||
# Options.
|
||||
def store_append(vars, options = {})
|
||||
store_vars = store_common(options)
|
||||
store_vars["append"] ||= {}
|
||||
vars.each_pair do |key, value|
|
||||
if store_vars["append"][key].is_a?(Array) and value.is_a?(Array)
|
||||
store_vars["append"][key] += value
|
||||
else
|
||||
store_vars["append"][key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Store flags to be parsed into the Cache.
|
||||
#
|
||||
# @param flags [String]
|
||||
# String containing the flags to parse.
|
||||
# @param options [Hash]
|
||||
# Options.
|
||||
def store_parse(flags, options = {})
|
||||
store_vars = store_common(options)
|
||||
store_vars["parse"] ||= []
|
||||
store_vars["parse"] << flags
|
||||
end
|
||||
|
||||
# Common functionality for all store methods.
|
||||
#
|
||||
# @param options [Hash]
|
||||
@ -462,42 +503,5 @@ module Rscons
|
||||
end
|
||||
end
|
||||
|
||||
# Perform processing common to several configure checks.
|
||||
#
|
||||
# @param status [Process::Status, Integer]
|
||||
# Process exit code.
|
||||
# @param options [Hash]
|
||||
# Common check options.
|
||||
# @option options [Boolean] :fail
|
||||
# Whether to fail configuration if the requested item is not found.
|
||||
# This defaults to true if the :set_define option is not specified,
|
||||
# otherwise defaults to false if :set_define option is specified.
|
||||
# @option options [String] :set_define
|
||||
# A define to set (in CPPDEFINES) if the requested item is found.
|
||||
# @option options [String] :success_message
|
||||
# Message to print on success (default "found").
|
||||
def common_config_checks(status, options)
|
||||
success_message = options[:success_message] || "found"
|
||||
if status == 0
|
||||
Ansi.write($stdout, :green, "#{success_message}\n")
|
||||
if options[:set_define]
|
||||
store_append("CPPDEFINES" => [options[:set_define]])
|
||||
end
|
||||
else
|
||||
should_fail =
|
||||
if options.has_key?(:fail)
|
||||
options[:fail]
|
||||
else
|
||||
!options[:set_define]
|
||||
end
|
||||
if should_fail
|
||||
Ansi.write($stdout, :red, "not found\n")
|
||||
raise ConfigureFailure.new
|
||||
else
|
||||
Ansi.write($stdout, :yellow, "not found\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
@ -81,6 +81,19 @@ module Rscons
|
||||
@configure_op.__send__(method_name, *args)
|
||||
end
|
||||
end
|
||||
|
||||
# Perform a custom configuration check.
|
||||
#
|
||||
# @param message [String]
|
||||
# Custom configuration check message (e.g. "Checking for foo").
|
||||
# rscons will add "... " to the end of the message.
|
||||
# @yieldparam configure_op [ConfigureOp]
|
||||
# {ConfigureOp} object.
|
||||
# @return [void]
|
||||
def custom_check(message, &block)
|
||||
$stdout.write(message + "... ")
|
||||
block[@configure_op]
|
||||
end
|
||||
end
|
||||
|
||||
# @return [String, nil]
|
||||
|
@ -2086,6 +2086,66 @@ EOF
|
||||
end
|
||||
end
|
||||
|
||||
context "custom_check" do
|
||||
context "when running a test command" do
|
||||
context "when executing the command fails" do
|
||||
context "when failures are fatal" do
|
||||
it "fails configuration with the correct error message" do
|
||||
test_dir "configure"
|
||||
create_exe "grep", "exit 4"
|
||||
result = run_rscons(rsconscript: "custom_config_check.rb", op: "configure")
|
||||
expect(result.stderr).to eq ""
|
||||
expect(result.stdout).to match /Checking 'grep' version\.\.\. error executing grep/
|
||||
expect(result.status).to_not eq 0
|
||||
end
|
||||
end
|
||||
|
||||
context "when the custom logic indicates a failure" do
|
||||
it "fails configuration with the correct error message" do
|
||||
test_dir "configure"
|
||||
create_exe "grep", "echo 'grep (GNU grep) 1.1'"
|
||||
result = run_rscons(rsconscript: "custom_config_check.rb", op: "configure")
|
||||
expect(result.stderr).to eq ""
|
||||
expect(result.stdout).to match /Checking 'grep' version\.\.\. too old!/
|
||||
expect(result.status).to_not eq 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when failures are not fatal" do
|
||||
context "when the custom logic indicates a failure" do
|
||||
it "displays the correct message and does not fail configuration" do
|
||||
test_dir "configure"
|
||||
create_exe "grep", "echo 'grep (GNU grep) 2.1'"
|
||||
result = run_rscons(rsconscript: "custom_config_check.rb", op: "configure")
|
||||
expect(result.stderr).to eq ""
|
||||
expect(result.stdout).to match /Checking 'grep' version\.\.\. we'll work with it but you should upgrade/
|
||||
expect(result.status).to eq 0
|
||||
result = run_rscons(rsconscript: "custom_config_check.rb", op: "build")
|
||||
expect(result.stderr).to eq ""
|
||||
expect(result.stdout).to match /GREP_WORKAROUND/
|
||||
expect(result.status).to eq 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when the custom logic indicates success" do
|
||||
it "passes configuration with the correct message" do
|
||||
test_dir "configure"
|
||||
create_exe "grep", "echo 'grep (GNU grep) 3.0'"
|
||||
result = run_rscons(rsconscript: "custom_config_check.rb", op: "configure")
|
||||
expect(result.stderr).to eq ""
|
||||
expect(result.stdout).to match /Checking 'grep' version\.\.\. good!/
|
||||
expect(result.status).to eq 0
|
||||
result = run_rscons(rsconscript: "custom_config_check.rb", op: "build")
|
||||
expect(result.stderr).to eq ""
|
||||
expect(result.stdout).to match /GREP_FULL/
|
||||
expect(result.status).to eq 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "does everything" do
|
||||
test_dir "configure"
|
||||
create_exe "pkg-config", "echo '-DMYPACKAGE'"
|
||||
|
Loading…
x
Reference in New Issue
Block a user