diff --git a/build_tests/configure/on_fail.rb b/build_tests/configure/on_fail.rb new file mode 100644 index 0000000..b685295 --- /dev/null +++ b/build_tests/configure/on_fail.rb @@ -0,0 +1,5 @@ +configure do + check_c_compiler "foo123c", fail: false, on_fail: "Install the foo123 package" + check_d_compiler "foo123d", fail: false + check_cxx_compiler "foo123cxx", on_fail: lambda {puts "Install the foo123cxx package"} +end diff --git a/doc/user_guide.md b/doc/user_guide.md index b56d552..3647d32 100644 --- a/doc/user_guide.md +++ b/doc/user_guide.md @@ -246,6 +246,15 @@ configure do end ``` +Global configuration options may be supplied to the compiler checks as well. +Example: + +```ruby +configure do + check_c_compiler "x86_64-elf-gcc", on_fail: "Install x86_64-elf cross toolchain first!" +end +``` + ###> Checking for a Header File The following methods can be used to check for the presence of a header file: @@ -272,18 +281,6 @@ end Optionally specifies an array of paths to look for the header file in. -##### `:fail` - -If the `:fail` option is set to `false`, then the absence of the header file -will not result in the configure option failing. -The `:fail` option defaults to `true` if the `:set_define` option is not -defined, and defaults to `false` if the `:set_define` option is defined. - -##### `:set_define` - -If set, a build define of the specified String will be added to the -`CPPDEFINES` construction variable array if the requested header is found. - ###> Checking for a D Import The `check_d_import` method can be used to check for the presence of D import. @@ -327,18 +324,6 @@ end Optionally specifies an array of paths to look for the library in. -##### `:fail` - -If the `:fail` option is set to `false`, then the absence of the library -will not result in the configure option failing. -The `:fail` option defaults to `true` if the `:set_define` option is not -defined, and defaults to `false` if the `:set_define` option is defined. - -##### `:set_define` - -If set, a build define of the specified String will be added to the -`CPPDEFINES` construction variable array if the requested library is found. - ##### `:use` If not set, the library will be used by default in all `Environment` objects. @@ -387,18 +372,6 @@ used to look for package configuration flags for the specified package. If the `:program` option is given, the program specified will be used to look for configuration flags. -##### `:fail` - -If the `:fail` option is set to `false`, then the absence of the package or -program requested will not result in the configure option failing. -The `:fail` option defaults to `true` if the `:set_define` option is not -defined, and defaults to `false` if the `:set_define` option is defined. - -##### `:set_define` - -If set, a build define of the specified String will be added to the -`CPPDEFINES` construction variable array if the requested package is found. - ##### `:use` If not set, the library will be used by default in all `Environment` objects. @@ -457,6 +430,46 @@ configure do end ``` +###> Global Configuration Check Options + +#### `:fail` + +If the `:fail` option is set to `false`, then the absence of the package or +program requested will not result in the configure option failing. +The `:fail` option defaults to `true` if the `:set_define` option is not +defined, and defaults to `false` if the `:set_define` option is defined. + +#### `:on_fail` + +The `:on_fail` option can be set to a String or a Proc object. If the +configuration operation fails (or would fail), the given message is printed +or the Proc is called. + +Examples: + +```ruby +configure do + check_c_compiler "special-gcc", on_fail: "First install special gcc!" +end + +configure do + package_hint = lambda do + puts "The following packages must be installed to build this project:" + puts "- libsdl2-dev" + puts "- libsdl2-image-dev" + puts "- libsdl2-net-dev" + end + check_lib "SDL2", on_fail: package_hint + check_lib "SDL2_image", on_fail: package_hint + check_lib "SDL2_net", on_fail: package_hint +end +``` + +#### `:set_define` + +If set, a build define of the specified String will be added to the +`CPPDEFINES` construction variable array if the requested package is found. + ##> Build Operations The `build` block is used to create Environments and register build targets. diff --git a/lib/rscons/configure_op.rb b/lib/rscons/configure_op.rb index 497bf65..8f868bc 100644 --- a/lib/rscons/configure_op.rb +++ b/lib/rscons/configure_op.rb @@ -62,6 +62,10 @@ module Rscons # @return [void] def check_c_compiler(*ccc) $stdout.write("Checking for C compiler... ") + options = {} + if ccc.last.is_a?(Hash) + options = ccc.slice!(-1) + end if ccc.empty? # Default C compiler search array. ccc = %w[gcc clang] @@ -69,7 +73,7 @@ module Rscons cc = ccc.find do |cc| test_c_compiler(cc) end - complete(cc ? 0 : 1, success_message: cc) + complete(cc ? 0 : 1, options.merge(success_message: cc)) end # Check for a working C++ compiler. @@ -80,6 +84,10 @@ module Rscons # @return [void] def check_cxx_compiler(*ccc) $stdout.write("Checking for C++ compiler... ") + options = {} + if ccc.last.is_a?(Hash) + options = ccc.slice!(-1) + end if ccc.empty? # Default C++ compiler search array. ccc = %w[g++ clang++] @@ -87,7 +95,7 @@ module Rscons cc = ccc.find do |cc| test_cxx_compiler(cc) end - complete(cc ? 0 : 1, success_message: cc) + complete(cc ? 0 : 1, options.merge(success_message: cc)) end # Check for a working D compiler. @@ -98,6 +106,10 @@ module Rscons # @return [void] def check_d_compiler(*cdc) $stdout.write("Checking for D compiler... ") + options = {} + if cdc.last.is_a?(Hash) + options = cdc.slice!(-1) + end if cdc.empty? # Default D compiler search array. cdc = %w[gdc ldc2] @@ -105,7 +117,7 @@ module Rscons dc = cdc.find do |dc| test_d_compiler(dc) end - complete(dc ? 0 : 1, success_message: dc) + complete(dc ? 0 : 1, options.merge(success_message: dc)) end # Check for a package or configure program output. @@ -387,11 +399,15 @@ module Rscons else !options[:set_define] end + color = should_fail ? :red : :yellow + Ansi.write($stdout, color, "#{fail_message}\n") + if options[:on_fail].is_a?(String) + $stdout.puts(options[:on_fail]) + elsif options[:on_fail].is_a?(Proc) + options[:on_fail].call + 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 diff --git a/spec/build_tests_spec.rb b/spec/build_tests_spec.rb index 1f432fd..31e6b24 100644 --- a/spec/build_tests_spec.rb +++ b/spec/build_tests_spec.rb @@ -2222,6 +2222,16 @@ EOF end end + context "on_fail option" do + it "prints on_fail messages and calls on_fail procs on failure" do + test_dir "configure" + result = run_rscons(rsconscript: "on_fail.rb", op: %w[configure]) + expect(result.status).to_not eq 0 + expect(result.stdout).to match /Install the foo123 package/ + expect(result.stdout).to match /Install the foo123cxx package/ + end + end + it "does everything" do test_dir "configure" create_exe "pkg-config", "echo '-DMYPACKAGE'"