# Compiling multiple C source files into a single library

**URL:** <https://www.ruby-forum.com/t/compiling-multiple-c-source-files-into-a-single-library/182270>\
**Category:** Ruby\
**Created:** [January 25, 2010, 8:52pm UTC](https://www.ruby-forum.com/t/compiling-multiple-c-source-files-into-a-single-library/182270 "2010-01-25T20:52:41Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [January 25, 2010, 8:52pm UTC](https://www.ruby-forum.com/t/compiling-multiple-c-source-files-into-a-single-library/182270/1 "2010-01-25T20:52:41Z")

</div>

Hi,

In the past I’ve always put all my code into a single source file and  
built it that way. However, I’d like to split out my C source files  
into a “one class per file” arrangement for a particular project, but  
I’m not sure how to do it. I’m using rake-compiler on Snow Leopard,  
btw.

Here’s the layout I have:

my\_project  
Rakefile  
ext/  
foo/  
extconf.rb  
foo.c  
bar.c

foo.c and bar.c are pretty basic C source files:

// foo.c  
#include \<ruby.h\>

void Init\_foo(){  
VALUE cFoo = rb\_define\_class(“Foo”, rb\_cObject);  
rb\_define\_const(cFoo, “VERSION”, rb\_str\_new2(“0.0.1”));  
}

// bar.c  
#include \<ruby.h\>

// I also tried Init\_foo here, but that lead to a compiler error  
void Init\_bar(){  
VALUE cBar = rb\_define\_class(“Bar”, rb\_cObject);  
rb\_define\_const(cBar, “VERSION”, rb\_str\_new2(“0.0.1”));  
}

The extconf.rb file is just “require ‘mkmf’; create\_makefile(‘foo’)”.

The Rake task is simply “Rake::ExtensionTask.new(‘foo’)”.

Running “rake compile:stuff” builds like so:

gcc -I. -I/opt/ree/lib/ruby/1.8/i686-darwin10.2.0 -I/opt/ree/lib/ruby/  
1.8/i686-darwin10.2.0 -I…/…/…/…/ext/foo -D\_XOPEN\_SOURCE -  
D\_DARWIN\_C\_SOURCE -fno-common -g -Os -fno-strict-aliasing -pipe -  
fno-common -c …/…/…/…/ext/foo/bar.c  
gcc -I. -I/opt/ree/lib/ruby/1.8/i686-darwin10.2.0 -I/opt/ree/lib/ruby/  
1.8/i686-darwin10.2.0 -I…/…/…/…/ext/foo -D\_XOPEN\_SOURCE -  
D\_DARWIN\_C\_SOURCE -fno-common -g -Os -fno-strict-aliasing -pipe -  
fno-common -c …/…/…/…/ext/foo/foo.c  
cc -dynamic -bundle -undefined suppress -flat\_namespace -o foo.bundle  
bar.o foo.o -L. -L/opt/ree/lib -L. -ldl -lobjc  
cd -  
cp tmp/i686-darwin10.2.0/foo/1.8.7/foo.bundle lib/foo.bundle

But, if I run the following test.rb program it fails:

$:.unshift ‘lib’  
require ‘stuff’ # ok  
p Foo::VERSION # ok  
p Bar::VERSION # fail, uninitialized constant Bar

Why isn’t Bar visible? What’s the right way to do what I’m attempting?

Regards,

Dan

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [January 25, 2010, 9:00pm UTC](https://www.ruby-forum.com/t/compiling-multiple-c-source-files-into-a-single-library/182270/2 "2010-01-25T21:00:54Z")

</div>

On Tue, Jan 26, 2010 at 04:46:37AM +0900, Daniel B. wrote:

> my\_project  
> #include \<ruby.h\>
> 
> void Init\_foo(){  
> VALUE cFoo = rb\_define\_class(“Foo”, rb\_cObject);  
> rb\_define\_const(cFoo, “VERSION”, rb\_str\_new2(“0.0.1”));  
> }

Call Init\_bar() from Init\_foo(). Ruby will only call one function when  
your extension loads. The “Init\_\*” function maps to the name of the  
shared object you build. So if you build “foo.bundle”, ruby will call  
“Init\_foo”, and only “Init\_foo”. Other initialization is up to you.

> // bar.c  
> #include \<ruby.h\>
> 
> // I also tried Init\_foo here, but that lead to a compiler error  
> void Init\_bar(){  
> VALUE cBar = rb\_define\_class(“Bar”, rb\_cObject);  
> rb\_define\_const(cBar, “VERSION”, rb\_str\_new2(“0.0.1”));  
> }
> 
> The extconf.rb file is just “require ‘mkmf’; create\_makefile(‘foo’)”.

The create\_makefile() call determines the name of the shared object  
built. Since you’re building “foo.bundle”, _only_ Init\_foo will be  
called.

> D\_DARWIN\_C\_SOURCE -fno-common -g -Os -fno-strict-aliasing -pipe -  
> p Foo::VERSION # ok  
> p Bar::VERSION # fail, uninitialized constant Bar
> 
> Why isn’t Bar visible? What’s the right way to do what I’m attempting?

Just call Init\_bar() from inside Init\_foo().

Hope that helps!

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [January 25, 2010, 11:20pm UTC](https://www.ruby-forum.com/t/compiling-multiple-c-source-files-into-a-single-library/182270/3 "2010-01-25T23:20:51Z")

</div>

On Jan 25, 12:59 pm, Aaron P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > // foo.c  
> > “Init\_foo”, and only “Init\_foo”. Other initialization is up to you.  
> > The extconf.rb file is just “require ‘mkmf’; create\_makefile(‘foo’)”.
> 
> > cd -
> 
> Just call Init\_bar() from inside Init\_foo().
> 
> Hope that helps!

Aha, thanks!

Dan
