C ext best practices

rubyists-

i’m wrapped a little libary that already has a full on gnu autotools
installation, call it

libfoobar-0.0.0.tgz

obviously, this unpacks like

libfoobar-0.0.0/
libfoobar-0.0.0/README
libfoobar-0.0.0/configure
libfoobar-0.0.0/foobar.c

if i were to wrap this package for ruby, i’d like to be able to

require ‘foobar’

what is the preferred means to make an extenstion like this?

  • foobar.c defines ruby bindings and extconf.rb must be called with
    ‘–with-foobar-dir’ pointing to an install of libfoobar?

  • _foobar.c defines ruby bindings and all libfoobar source files are simply
    dropped in same directory such that

    ruby extconf.rb
    make

    results in a foobar.so containing all required stuff?

thoughts?

-a

···

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
URL :: Solar-Terrestrial Physics Data | NCEI
TRY :: for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done
===============================================================================

Well, I won’t argue that it’s “best practices” but here’s what RMagick
does. RMagick assumes that the ImageMagick library, libMagick, has already
been installed in a separate step.

RMagick uses the standard GNU ./configure, make, make install sequence.
The configure script (built by autoconf) handles any
non-Ruby configuration - such as finding libMagick - and builds a custom
Makefile, extconf.rb, and a metaconfig file for install.rb. The Makefile’s
all: target runs install.rb’s config and setup steps. The Makefile’s
install: target runs install.rb’s install step.

Here’s RMagick’s Makefile.in. This will probably make it clearer than my
prose description. (The ./configure script also accepts a number of
options, like --with-std-ruby, that it passes on to install.rb via
@RUBY_CONFIG_OPTS@.)

Path to ruby interpreter

RUBY=@RUBY@

Any extra options from configure script to pass to ‘install.rb config’

RUBY_CONFIG_OPTS=@RUBY_CONFIG_OPTS@

all: config.save
$(RUBY) install.rb setup

install:
$(RUBY) install.rb install

clean: config.save
$(RUBY) install.rb clean

distclean: config.save
$(RUBY) install.rb clean
rm -f Makefile ext/RMagick/extconf.rb metaconfig
rm -f config.status Makefile config.cache config.log
rm -rf autom4te.cache

uninstall: config.save
$(RUBY) uninstall.rb $(RUBY_CONFIG_OPTS)

config.save: metaconfig
$(RUBY) install.rb config $(RUBY_CONFIG_OPTS)

···

On Tue, 20 Apr 2004 13:43:34 -0600, Ara.T.Howard wrote:

rubyists-

i’m wrapped a little libary that already has a full on gnu autotools
installation, call it

libfoobar-0.0.0.tgz

obviously, this unpacks like

libfoobar-0.0.0/
libfoobar-0.0.0/README
libfoobar-0.0.0/configure
libfoobar-0.0.0/foobar.c

if i were to wrap this package for ruby, i’d like to be able to

require ‘foobar’

what is the preferred means to make an extenstion like this?

  • foobar.c defines ruby bindings and extconf.rb must be called with
    ‘–with-foobar-dir’ pointing to an install of libfoobar?

  • _foobar.c defines ruby bindings and all libfoobar source files are
    simply
    dropped in same directory such that

    ruby extconf.rb
    make

    results in a foobar.so containing all required stuff?

thoughts?

-a

very nice.

i guess i’m thinking more along the lines of smallish packages, and would like
avoid having site_ruby/1.8/i686/foobar.so depend on
/usr/local/lib/libfoobar.so… (i just had a bad experience supporting some
software that required LD_RUN_PATH to manage dependancies). it would be ideal
if

foobar.so

was the result of compiling

foobar.c # original C source
_foobar.c # ruby binding to it

obviously this wouldn’t apply to packages likely to be updated independently
(like ImageMagick) but might be o.k. for smallish things like cdb, lockfile
utils, etc.

thoughts?

-a

···

On Tue, 20 Apr 2004, Tim Hunter wrote:

Well, I won’t argue that it’s “best practices” but here’s what RMagick
does. RMagick assumes that the ImageMagick library, libMagick, has already
been installed in a separate step.

RMagick uses the standard GNU ./configure, make, make install sequence.
The configure script (built by autoconf) handles any
non-Ruby configuration - such as finding libMagick - and builds a custom
Makefile, extconf.rb, and a metaconfig file for install.rb. The Makefile’s
all: target runs install.rb’s config and setup steps. The Makefile’s
install: target runs install.rb’s install step.

Here’s RMagick’s Makefile.in. This will probably make it clearer than my
prose description. (The ./configure script also accepts a number of
options, like --with-std-ruby, that it passes on to install.rb via
@RUBY_CONFIG_OPTS@.)

Path to ruby interpreter

RUBY=@RUBY@

Any extra options from configure script to pass to ‘install.rb config’

RUBY_CONFIG_OPTS=@RUBY_CONFIG_OPTS@

all: config.save
$(RUBY) install.rb setup

install:
$(RUBY) install.rb install

clean: config.save
$(RUBY) install.rb clean

distclean: config.save
$(RUBY) install.rb clean
rm -f Makefile ext/RMagick/extconf.rb metaconfig
rm -f config.status Makefile config.cache config.log
rm -rf autom4te.cache

uninstall: config.save
$(RUBY) uninstall.rb $(RUBY_CONFIG_OPTS)

config.save: metaconfig
$(RUBY) install.rb config $(RUBY_CONFIG_OPTS)

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
URL :: Solar-Terrestrial Physics Data | NCEI
TRY :: for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done
===============================================================================

Hi,

At Wed, 21 Apr 2004 23:04:11 +0900,
Ara.T.Howard wrote in [ruby-talk:97854]:

i guess i’m thinking more along the lines of smallish packages, and would like
avoid having site_ruby/1.8/i686/foobar.so depend on
/usr/local/lib/libfoobar.so… (i just had a bad experience supporting some
software that required LD_RUN_PATH to manage dependancies). it would be ideal
if

foobar.so

was the result of compiling

foobar.c # original C source
_foobar.c # ruby binding to it

obviously this wouldn’t apply to packages likely to be updated independently
(like ImageMagick) but might be o.k. for smallish things like cdb, lockfile
utils, etc.

Though, makefile created by configure and one created by
extconf.rb, could conflict. I think you would have to separate
the directories.

One thought (but not tested),

---------- depend:
$(DLLIB): src/foobar.$(LIBEXT)

src/foobar.$(LIBEXT):
$(RUBY) -C “$(@D)” -e “exec *ARGV” $(MAKE) $(MFLAGS) $(@F)

---------- extconf.rb:
topdir = Dir.pwd
IO.foreach(File.join($srcdir, “depend”)) do |line|
/$(DLLLIB):\s*(.*.$(LIBEXT))/ =~ line or next
lib = $1
subdir = File.dirname(lib)
Dir.mkdir(subdir) rescue nil
Dir.chdir(subdir) do
srcdir = $srcdir
unless File.expand_path(srcdir, topdir) == File.expand_path(srcdir)
srcdir = File.join(“…”, srcdir)
end
system(File.join(srcdir, “configure”), *ARGV) or exit
end
$LOCAL_LIBS << " " + lib
end
create_makefile(“foobar”)

···


Nobu Nakada