# Using Rake to compile FreeBASIC code

**URL:** <https://www.ruby-forum.com/t/using-rake-to-compile-freebasic-code/55451>\
**Category:** Ruby\
**Created:** [March 21, 2006, 5:00am UTC](https://www.ruby-forum.com/t/using-rake-to-compile-freebasic-code/55451 "2006-03-21T05:00:38Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [March 21, 2006, 5:00am UTC](https://www.ruby-forum.com/t/using-rake-to-compile-freebasic-code/55451/1 "2006-03-21T05:00:38Z")

</div>

Hello list!,

Maybe the subject sound strange, but FreeBASIC  
([http://www.freebasic.net](http://www.freebasic.net)) offer us native assembly-linked code that we  
currently use to drive a few special purpose dlls on windows.

Folling Rake Tutorial, we tried to recreate it for fb (instead of c).

The problem is related in the way FB set the main module on the compiled  
object (an special param must be passed to make the module as main).

In the later link process, if no module is defined/marked as main, the  
link stop and raise a undefined main routine.

We solved this creating an Array of “MAINS”, when the compile rule find  
the module in the list, add the param for making it main.

The problem is that in our Rakefile we have several projects, and some  
of them use these modules but not as main, so it raises a problem of  
multiple definitions.

There is the code we are using:

MAINS = []  
LIBS = []

rule ‘.o’ =\> ‘.bas’ do |t|  
fbc\_compile t  
end

def fb\_project(executable, main, files, libs=nil)  
obj = FileList.new(files)  
obj.include(main)  
MAINS \<\< main

obj.each { |fn| fn.sub!(/.bas$/, “.o”) }

file executable =\> obj do |t|  
fbc\_link t, libs  
end  
end

def fbc\_compile(task)  
as\_main = “-m #{task.name.chomp(‘.o’)}” if MAINS.include?(task.name)  
sh “fbc -c #{task.source} -o #{task.name} #{as\_main}”  
end

def fbc\_link(task, libs)  
lb = []  
libs.each { |libname| lb \<\< “-l #{libname}” } unless libs.nil?

sh “fbc -x #{task.name}.exe #{task.prerequisites.join(’ ‘)}  
#{lb.join(’ ')}”  
end

fb\_project(“test”, “stub.bas”, ["\*\*/_.bas", '_.rc’], [“user32”])  
task :compile =\> :test

fb\_project(“xx”, “module1.bas”, [“module2.bas”], [“user32”])  
task :compile =\> :xx

If we call test or xx task (or even compile) module1.bas and stub.bas  
both get compiled “as main”, and the link process fail.

Any suggestion or approach to solve this issue?

Thanks in advance,

Luis

---

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [March 21, 2006, 6:32am UTC](https://www.ruby-forum.com/t/using-rake-to-compile-freebasic-code/55451/2 "2006-03-21T06:32:32Z")

</div>

Luis L. wrote:

> Maybe the subject sound strange, but FreeBASIC  
> ([http://www.freebasic.net](http://www.freebasic.net)) offer us native assembly-linked code that we  
> currently use to drive a few special purpose dlls on windows.
> 
> Folling Rake Tutorial, we tried to recreate it for fb (instead of c).

Cool!

> The problem is related in the way FB set the main module on the compiled  
> object (an special param must be passed to make the module as main).
> 
> In the later link process, if no module is defined/marked as main, the  
> link stop and raise a undefined main routine.  
> […]  
> The problem is that in our Rakefile we have several projects, and some  
> of them use these modules but not as main, so it raises a problem of  
> multiple definitions.

Ok, the problem (as I understand it) is that a main module must be  
specially compiled. Only one main module can be in a executable. And  
modules that are main for one program need to be non-main for other  
executables.

Does that sound right?

I approached with the thought that modules that could be main must be  
compiled twice, once normally for use as a library, and once with the  
main flag to be used as the main program.

I setup two rules to handle that. The first rule is similar to the one  
you gave in your Rakefile. It only compiles normal modules.

The second rule is for generating objects in a special directory (e.g.  
“mains”). All object modules in the “mains” directory have been  
compiled for use as a main.

Then all I had to do was have the project method excluded the normal .o  
file that corresponds to the main module and include the specially  
compiled version in the main directory.

Just a couple notes. I don’t have FreeBasic so I couldn’t actually  
compile anything. I just simulated the fbc program with a simple script  
that just touched the output files. This means I may have gotten some  
of the details wrong, especially the flags that are sent to the compile.  
In particular, double check the -m flag. I assume that it wants the  
name of the module without any directory name or file extension.

Here’s my version … let me know of this works for you:

* * *

#!/usr/bin/env ruby

# -_- ruby -_-

require ‘rake/clean’

CLEAN.include ‘\*\*/_.o’, ‘mains’  
CLOBBER.include '_.exe’

LIBS = []

directory ‘mains’

# Rule to build normal objects from source.

rule ‘.o’ =\> ‘.bas’ do |t|  
fbc\_compile t.source, t.name  
end

# Rule to compile main objects from source.

rule %r{^mains/.\*.o$} =\> [  
proc { |fn| File.basename(fn).ext(‘bas’) },  
proc { ‘mains’ }  
] do |t|  
fbc\_main\_compile t, t.source  
end

def fb\_project(executable, main, files, libs=[])  
bas\_files = FileList[\*files.grep(/.bas$/)]  
rc\_files = FileList[\*files.grep(/.rc$/)]  
objs = bas\_files.ext(“o”) + rc\_files  
objs.exclude(main.ext(“o”))  
objs.include(File.join(“mains”, main.ext(“o”)))

task :compile =\> executable  
task executable =\> executable.ext(“exe”)  
file executable.ext(“exe”) =\> objs do |t|  
fbc\_link t.name, t.prerequisites, libs  
end  
end

def fbc\_compile(src, obj)  
sh “fbc -c #{src} -o #{obj}”  
end

def fbc\_main\_compile(task, main\_name)  
sh “fbc -c #{task.source} -o #{task.name} -m #{main\_name.ext}”  
end

def fbc\_link(exec, deps, libs)  
lb = libs.collect { |lib| “-l #{lib}” }.join(’ ‘)  
sh "fbc -x #{exec} #{deps.join(’ ')} #{lb}"  
end

fb\_project(“test”, “stub.bas”, ["\*\*/_.bas", '_.rc’], [“user32”])

fb\_project(“xx”, “module1.bas”, [“module2.bas”], [“user32”])

## task :default =\> :compile

–  
– Jim W.

---

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [March 21, 2006, 8:20am UTC](https://www.ruby-forum.com/t/using-rake-to-compile-freebasic-code/55451/3 "2006-03-21T08:20:46Z")

</div>

Jim W. wrote:

> Luis L. wrote:
> 
> > Maybe the subject sound strange, but FreeBASIC  
> > ([http://www.freebasic.net](http://www.freebasic.net)) offer us native assembly-linked code that we  
> > currently use to drive a few special purpose dlls on windows.
> > 
> > Folling Rake Tutorial, we tried to recreate it for fb (instead of c).
> 
> Cool!

In one of our projects, the business logic is driven by a embedded lua  
interpreter (called and extended from FB), that way we provide simpler  
access to change logic without need of recompiling.

We are using RoR and wanted to take advantage of Rake for our libraries  
too (we are tired of batch files!)

> Ok, the problem (as I understand it) is that a main module must be  
> specially compiled. Only one main module can be in a executable. And  
> modules that are main for one program need to be non-main for other  
> executables.
> 
> Does that sound right?

Yes, that is correct, please excuse my bad grammar (self learned  
english, spanish native speaker).

> I approached with the thought that modules that could be main must be  
> compiled twice, once normally for use as a library, and once with the  
> main flag to be used as the main program.

[snip]

> Just a couple notes. I don’t have FreeBasic so I couldn’t actually  
> compile anything. I just simulated the fbc program with a simple script  
> that just touched the output files. This means I may have gotten some  
> of the details wrong, especially the flags that are sent to the compile.  
> In particular, double check the -m flag. I assume that it wants the  
> name of the module without any directory name or file extension.
> 
> Here’s my version … let me know of this works for you:

I really don’t know HOW you do this (trying to figure out the new rule  
you added) but it works.

Yeah, copy & paste, run it and build everything without problems!

We just used ‘\*\*/\*.bas’ as example to include every module in the list,  
doing that, for the “test” project, stub get compiled twice: one as  
module, one as main.

But that is because we used magic wildcards, when in real-life,  
wouldn’t.

Wanted to thank you for the time you took to answer me, and provide this  
helpful solution.

Still learning ruby (a few months playing with it) but now I want to run  
SWIG on the ruby headers to create compatible FB includes and create  
native access (?) to freebasic (btw, its cross-platform win, linux, dos)

Also we created, unit testing ala UnitTest for FreeBASIC, TDD to the  
max! 😉

Regards and thank you again,

Luis

---

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [March 25, 2006, 7:56pm UTC](https://www.ruby-forum.com/t/using-rake-to-compile-freebasic-code/55451/4 "2006-03-25T19:56:14Z")

</div>

Jim:

After toyed with the rakefile with simple files, moved it to my project.

my folder structure is something like this:

my\_project  
code/  
shared/  
test/  
Rakefile

Inside code is where my main code resides, and shared is a  
junction/symlink to where I store code for md5, blowfish, hash, list,  
etc.

In test, I create a few test to “verify” each one of the units/modules  
of my project.

Well, with the rakefile/rules you created in previous mail, making main  
a module located inside another folder fails, with this error:

rake aborted!  
Don’t know how to build task ‘mains/test/test\_bf.o’

I have inside test a file named test\_bf.bas

The task is named test\_blowfish, so don’t “collide” between tasks

The rule for ‘.o’ =\> ‘.bas’ worked fine, but the one that makes “mains”  
didn’t.

I tried to understand the regex rule, but fail to do so ☹

Any hint or suggestion to what need to tweak?

Regards and thank you for your time,

Luis

Jim W. wrote:

> Luis L. wrote:
> 
> > Maybe the subject sound strange, but FreeBASIC  
> > ([http://www.freebasic.net](http://www.freebasic.net)) offer us native assembly-linked code that we  
> > currently use to drive a few special purpose dlls on windows.
> > 
> > Folling Rake Tutorial, we tried to recreate it for fb (instead of c).
> 
> Cool!
> 
> > The problem is related in the way FB set the main module on the compiled  
> > object (an special param must be passed to make the module as main).
> > 
> > In the later link process, if no module is defined/marked as main, the  
> > link stop and raise a undefined main routine.  
> > […]  
> > The problem is that in our Rakefile we have several projects, and some  
> > of them use these modules but not as main, so it raises a problem of  
> > multiple definitions.
> 
> Ok, the problem (as I understand it) is that a main module must be  
> specially compiled. Only one main module can be in a executable. And  
> modules that are main for one program need to be non-main for other  
> executables.
> 
> Does that sound right?
> 
> I approached with the thought that modules that could be main must be  
> compiled twice, once normally for use as a library, and once with the  
> main flag to be used as the main program.
> 
> I setup two rules to handle that. The first rule is similar to the one  
> you gave in your Rakefile. It only compiles normal modules.
> 
> The second rule is for generating objects in a special directory (e.g.  
> “mains”). All object modules in the “mains” directory have been  
> compiled for use as a main.
> 
> Then all I had to do was have the project method excluded the normal .o  
> file that corresponds to the main module and include the specially  
> compiled version in the main directory.
> 
> Just a couple notes. I don’t have FreeBasic so I couldn’t actually  
> compile anything. I just simulated the fbc program with a simple script  
> that just touched the output files. This means I may have gotten some  
> of the details wrong, especially the flags that are sent to the compile.  
> In particular, double check the -m flag. I assume that it wants the  
> name of the module without any directory name or file extension.
> 
> Here’s my version … let me know of this works for you:
> 
> * * *
> 
> #!/usr/bin/env ruby
> 
> # -_- ruby -_-
> 
> require ‘rake/clean’
> 
> CLEAN.include ‘\*\*/_.o’, ‘mains’  
> CLOBBER.include '_.exe’
> 
> LIBS = []
> 
> directory ‘mains’
> 
> # Rule to build normal objects from source.
> 
> rule ‘.o’ =\> ‘.bas’ do |t|  
> fbc\_compile t.source, t.name  
> end
> 
> # Rule to compile main objects from source.
> 
> rule %r{^mains/.\*.o$} =\> [  
> proc { |fn| File.basename(fn).ext(‘bas’) },  
> proc { ‘mains’ }  
> ] do |t|  
> fbc\_main\_compile t, t.source  
> end
> 
> def fb\_project(executable, main, files, libs=[])  
> bas\_files = FileList[\*files.grep(/.bas$/)]  
> rc\_files = FileList[\*files.grep(/.rc$/)]  
> objs = bas\_files.ext(“o”) + rc\_files  
> objs.exclude(main.ext(“o”))  
> objs.include(File.join(“mains”, main.ext(“o”)))
> 
> task :compile =\> executable  
> task executable =\> executable.ext(“exe”)  
> file executable.ext(“exe”) =\> objs do |t|  
> fbc\_link t.name, t.prerequisites, libs  
> end  
> end
> 
> def fbc\_compile(src, obj)  
> sh “fbc -c #{src} -o #{obj}”  
> end
> 
> def fbc\_main\_compile(task, main\_name)  
> sh “fbc -c #{task.source} -o #{task.name} -m #{main\_name.ext}”  
> end
> 
> def fbc\_link(exec, deps, libs)  
> lb = libs.collect { |lib| “-l #{lib}” }.join(’ ‘)  
> sh "fbc -x #{exec} #{deps.join(’ ')} #{lb}"  
> end
> 
> fb\_project(“test”, “stub.bas”, ["\*\*/_.bas", '_.rc’], [“user32”])
> 
> fb\_project(“xx”, “module1.bas”, [“module2.bas”], [“user32”])
> 
> ## task :default =\> :compile
> 
> –  
> – Jim W.

---

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [March 25, 2006, 11:40pm UTC](https://www.ruby-forum.com/t/using-rake-to-compile-freebasic-code/55451/5 "2006-03-25T23:40:28Z")

</div>

Luis L. wrote:

> Jim:
> 
> After toyed with the rakefile with simple files, moved it to my project.
> 
> my folder structure is something like this:
> 
> my\_project  
> code/  
> shared/  
> test/  
> Rakefile
> 
> Inside code is where my main code resides, and shared is a  
> junction/symlink to where I store code for md5, blowfish, hash, list,  
> etc.
> 
> In test, I create a few test to “verify” each one of the units/modules  
> of my project.
> 
> Well, with the rakefile/rules you created in previous mail, making main  
> a module located inside another folder fails, with this error:
> 
> rake aborted!  
> Don’t know how to build task ‘mains/test/test\_bf.o’

Ok, the rule needs to bridge the gap between test/test\_bf.bas and  
mains/test/test\_bf.o. The regular expression part of the rule (the  
r{^mains/.\*.o$}) is fine, it should match “mains/test/test\_bf.o”. The  
list of procs are probably what’s wrong.

[ proc { |fn| File.basename(fn).ext(‘bas’) },  
proc { ‘mains’ }  
]

will produce the list:

[‘test\_bf.bas’, ‘mains’]

which is wrong. What you want is:

[‘test/test\_bf.bas’, ‘mains/test’]

So, just write two procs to produce that and put that in the rule.

Also, you will probably need to add a line that will describe how to  
make the ‘mains/test’ directory (Just saying “directory ‘mains/test’” is  
adequate).

–  
– Jim W.

---

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [March 26, 2006, 1:41am UTC](https://www.ruby-forum.com/t/using-rake-to-compile-freebasic-code/55451/6 "2006-03-26T01:41:32Z")

</div>

Jim W. wrote:

> Ok, the rule needs to bridge the gap between test/test\_bf.bas and  
> mains/test/test\_bf.o. The regular expression part of the rule (the  
> r{^mains/.\*.o$}) is fine, it should match “mains/test/test\_bf.o”. The  
> list of procs are probably what’s wrong.
> 
> [ proc { |fn| File.basename(fn).ext(‘bas’) },  
> proc { ‘mains’ }  
> ]
> 
> will produce the list:
> 
> [‘test\_bf.bas’, ‘mains’]
> 
> which is wrong. What you want is:
> 
> [‘test/test\_bf.bas’, ‘mains/test’]
> 
> So, just write two procs to produce that and put that in the rule.
> 
> Also, you will probably need to add a line that will describe how to  
> make the ‘mains/test’ directory (Just saying “directory ‘mains/test’” is  
> adequate).

Thank you again Jim, following your indications I solved it (btw, this  
use of proc is just like lamda, right?)

This is the new rule:

# Rule to compile main objects from source.

rule %r{^mains/.\*.o$} =\> [  
proc { |fn| fn.sub(%r{^mains/}, ‘’).ext(‘bas’) },  
proc { |fn| File.dirname(fn) }  
] do |t|  
sh “fbc -c #{t.source} -o #{t.name} -m #{File.basename(t.source).ext}”  
end

Guess could be solved more “elegant”, but it works 🙂

I added a directory task into fb\_project to intelligently add when is  
needed (mains/other or leave just mains)

Thank you for your time (again).

Regards,

Luis
