Permalink
Browse files

Fix preprocessor defines and add find_executable

git-svn-id: http://mkrf.rubyforge.org/svn/trunk@46 6e48df83-f314-0410-b1e7-e69642b30866
  • Loading branch information...
1 parent 47a001e commit ff555c6b8aa8a653591479775fb7ce9146df4205 kevinclark committed Oct 19, 2006
View
@@ -1,4 +1,7 @@
= svn
+* [CLEAN-UP] Preprocessor define handling moved to Availability from Generator.
+* [NEW] find_executable method added to Availability.
+* [FIXED] include_header and has_header? now properly set preprocessor defines.
* [FIXED] Defaults on Generator work again. [44]
= 0.1.2 10/4/06
View
@@ -41,7 +41,7 @@ namespace :test do
BASE_DIR = File.dirname(__FILE__) + '/test/sample_files'
SAMPLE_DIRS = {
- :trivial => BASE_DIR + '/libtrivial/',
+ :trivial => BASE_DIR + '/libtrivial/ext/',
:syck => BASE_DIR + '/syck-0.55/ext/ruby/ext/syck/',
:libxml => BASE_DIR + '/libxml-ruby-0.3.8/ext/xml/'
}
View
16 TODO
@@ -1,19 +1,5 @@
* install task for output Rakefile
-* command-line configuration options
+* command-line configuration options (--with, --without, --enable, --disable)
BUGS
-
-From Tim Hunter:
-
-I'm trying to write a Rakefile for RMagick with mkrf. The first thing I miss is the equivalent of autoconf's AC_CHECK_PROGS. I think this is the find_executable method in mkmf
-
-It would also be nice to have some kind of automatic option processing for --with-THING, --without-THING, --enable-THING, --disable-THING options.
-
-Two more things.
-
-1) How do I add arbitrary strings to the gcc options such as the values of LDFLAGS, CPPFLAGS, and CFLAGS?
-
-A) For now, users may modify them directly via the objs and cflags accessors.
-
-2) RMagick uses about 100 feature test symbols (HAVE_xxx, etc.), too many to specify on the command line. It must be possible to create a configuration header file from a template, like the file created by AC_CONFIG_HEADERS.
View
@@ -16,7 +16,7 @@ class Availability
TEMP_SOURCE_FILE = "temp_source.c"
TEMP_EXECUTABLE = "temp_executable"
- attr_reader :headers, :loaded_libs, :includes, :logger
+ attr_reader :headers, :loaded_libs, :includes, :logger, :defines
# Create a new Availability instance.
#
@@ -33,6 +33,7 @@ def initialize(options = {})
@compiler = options[:compiler] || Config::CONFIG["CC"]
@includes = (options[:includes] || DEFAULT_INCLUDES).to_a
@logger = Logger.new('mkrf.log')
+ @defines = []
end
# Include a library in the list of available libs. Returns +false+ if the
@@ -46,7 +47,9 @@ def include_library(library, function = "main")
end
# Include a header in the list of availiable headers. Returns +false+ if the
- # header is not available. Returns non-false otherwise.
+ # header is not available. Returns non-false otherwise. If the header is
+ # found, the preprocessor constant HAVE_BLAH is defined where BLAH is the name
+ # of the header in uppercase without the file extension.
#
# Params:
# * <tt>header</tt> -- the name of the header to be included as a string.
@@ -68,14 +71,20 @@ def has_library?(library, function = "main")
end
# Returns +true+ if the header is found in the default search path or in
- # optional paths passed as an argument, +false+ otherwise.
+ # optional paths passed as an argument, +false+ otherwise. If the header is
+ # found, the preprocessor constant HAVE_BLAH is defined where BLAH is the name
+ # of the header in uppercase without the file extension.
#
# Params:
# * <tt>header</tt> -- the header to be searched for
# * <tt>paths</tt> -- an optional list of search paths if the header is not found in the default paths
def has_header?(header, *paths)
- return true if header_already_loaded?(header) || header_can_link?(header) ||
+ if header_already_loaded?(header) || header_can_link?(header) ||
header_found_in_paths?(header, paths)
+ defines << format("HAVE_%s", header.tr("a-z./\055", "A-Z___"))
+ return true
+ end
+
logger.warn "Header not found: #{header}"
return false
end
@@ -129,6 +138,18 @@ def includes_compile_string
@includes.collect {|i| "-I#{i}"}.join(' ')
end
+ # Takes the name of an executable and an optional set of paths to search.
+ # If no paths are given, the environmental path is used by default.
+ # Returns the absolute path to an executable, or nil if not found.
+ def find_executable(bin, *paths)
+ paths = ENV['PATH'].split(File::PATH_SEPARATOR) if paths.empty?
+ paths.each do |path|
+ file = File.join(path, bin)
+ return file if File.executable?(file)
+ end
+ return nil
+ end
+
private
def found_library?(library, function)
View
@@ -86,13 +86,13 @@ def sources
# Add a define to the compile string. Example:
#
# Mkrf::Generator.new('my_library') do |g|
- # g.add_define(HAVE_PTHREADS)
+ # g.add_define('HAVE_PTHREADS')
# end
#
# Params:
# * +defn+ -- string to add to compile time defines
def add_define(defn)
- @defines.push(defn)
+ @available.defines << defn
end
# Include a library in the compile. Returns +false+ if the
@@ -138,10 +138,7 @@ def write_rakefile(filename = "Rakefile") # :nodoc:
end
def defines_compile_string # :nodoc:
- (@defines.collect {|define| "-D#{define}" } +
- @available.headers.collect { |header|
- format("-DHAVE_%s", header.tr("a-z./\055", "A-Z___"))
- }).join(' ')
+ @available.defines.collect {|define| "-D#{define}"}.join(' ')
end
def rakefile_contents # :nodoc:
View
Binary file not shown.
@@ -4,7 +4,7 @@ class TestSampleProjects < Test::Unit::TestCase
SAMPLES_DIR = File.dirname(__FILE__) + '/../sample_files'
SAMPLE_LIBS = {
- :trivial => "/libtrivial/libtrivial.#{Config::CONFIG['DLEXT']}",
+ :trivial => "/libtrivial/ext/libtrivial.#{Config::CONFIG['DLEXT']}",
:syck => "/syck-0.55/ext/ruby/ext/syck/syck.#{Config::CONFIG['DLEXT']}",
:libxml => "/libxml-ruby-0.3.8/ext/xml/libxml_so.#{Config::CONFIG['DLEXT']}"
}
@@ -0,0 +1,3 @@
+require File.dirname(__FILE__) + '/../../../../lib/mkrf'
+
+Mkrf::Generator.new('libtrivial')
@@ -1,3 +0,0 @@
-require File.dirname(__FILE__) + '/../../../lib/mkrf'
-
-Mkrf::Generator.new('libtrivial')
@@ -3,7 +3,8 @@
class TestAvailability < Test::Unit::TestCase
def setup
- @avail = Mkrf::Availability.new(:includes => File.join(File.dirname(__FILE__), '..', 'fixtures'))
+ @fixture_path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'fixtures'))
+ @avail = Mkrf::Availability.new(:includes => @fixture_path)
end
def teardown
@@ -46,7 +47,13 @@ def test_has_header_should_work_with_basic_headers
def test_has_header_should_check_many_paths
assert !@avail.has_header?('header_down_a_directory.h')
- assert @avail.has_header?('header_down_a_directory.h', File.join(File.dirname(__FILE__), '..', 'fixtures', 'down_a_directory'))
+ assert @avail.has_header?('header_down_a_directory.h',
+ File.join(@fixture_path, 'down_a_directory'))
+ end
+
+ def test_has_header_should_add_define_with_valid_header
+ assert @avail.has_header?('stdmkrf.h')
+ assert @avail.defines.include?('HAVE_STDMKRF_H'), "Defines: #{@avail.defines.inspect}"
end
def test_include_header
@@ -69,6 +76,24 @@ def test_method_missing_should_go_down_chain_when_not_catching_stackable_attribu
assert_raises(NoMethodError) { @avail.with_not_a_stackable_attribute }
end
+ def test_find_executable_should_return_nil_when_not_found
+ assert_nil @avail.find_executable('fake_executable')
+ end
+
+ def test_find_executable_should_default_to_search_env_path
+ old_path = ENV['PATH']
+ ENV['PATH'] = @fixture_path
+ expected = File.join(@fixture_path, 'some_binary')
+ assert_equal expected, @avail.find_executable('some_binary')
+ ensure
+ ENV['PATH'] = old_path
+ end
+
+ def test_find_executable_should_search_given_paths_if_supplied
+ expected = File.join(@fixture_path, 'some_binary')
+ assert_equal expected, @avail.find_executable('some_binary', @fixture_path)
+ end
+
def test_logging
@avail.logger.level = Logger::INFO
assert @avail.include_library('z')
@@ -83,6 +83,15 @@ def test_cflags
assert_match Regexp.new("CFLAGS = .*#{cflags}.*"), generator.rakefile_contents
end
+ def test_defines_compile_string
+ generator = Mkrf::Generator.new('testlib') do |g|
+ g.add_define 'HAVE_UNIX'
+ g.include_header 'stdio.h'
+ end
+ assert_match(/HAVE_UNIX/, generator.defines_compile_string)
+ assert_match(/HAVE_STDIO_H/, generator.defines_compile_string)
+ end
+
protected
def spec_code

0 comments on commit ff555c6

Please sign in to comment.