Wednesday, November 21, 2007

New toy..

Managed to get some nice time off today, read some of the library books, watched Tron, Ghost Busters I, and Spaced Invaders, but most of all got to relax. I've also placed my VIMRC file into a cvs repository on my OpenBSD box, that should make syncing changes with my Desktop/Laptop easier, plus allow me to see what I've changed hehe.

Had an interesting idea and started playing with some Ruby today also.

Normally when I start a new program I make a new directory in ~/code/Lang/src/ and copy a template makefile over from ../../makefiles/ and edit it to my needs. In one of the library books, I found a GNU Makefile that essentially automates building a C/C++ program where by all C/C++ source files (subject to make handling the dependencies) are compiled into corresponding files and get linked together into the binary, nice little thing when you look at it. With a little tinkering it could probably be made semi-language independent but I don't really have time to dig into GNU Make's syntax and features to do that.

I've basically written makefiles in the past that should work with just about any ol'make program. For much the same reason I write shell scripts that should run on most any /bin/sh, because I don't want to edit the freaking thing if I ever meet a Unix like OS it won't run on lool.

The idea I had was a enlazynating program that by knowing a fair bit about a given languages normal build process (such as C, C++, and Java), it could then automate the process of building it without having to generate a makefile, kind of like a 'smart-makefile' of sorts. I've got a alias set in my shell so that gcc is called on the command line with my usual settings. I also tend to include a few more once the things done.

It's probably a stupid idea to do this, a decent BSD or GNU Makefile would likely serve much better (and be worth the learning of each ones extensions to make). But I rather like to be able to just 'have fun' playing with and testing stuff.

Right now, it seems to be able to handle a simple compile/link of files in one directory but needs some work to properly link files in subdir's, lots of other stuff to do. But working on it has been a good way to pass the time.

Currently I classify this as a toy rather then a program for serious usage. But if I ever finish it, I might use it just for the sake of keeping a fairly fast build/test cycle.

If I could, I would've made a machine to manage VHS-Tape/DVD-Disk changing but hey, I'm not an inventor when it comes to to building some thing out of thin air...

Here is what I've done over the past couple hours, it's not very good but it's a starting point for later play.

#!/usr/local/bin/ruby -w
# usage: make [opt] project [dir]
#   rdoc...
#   handle header files and linking properly in C
#   support more then C
#   implement a way to set lang opts/debug/profiler stuff correctly
#   reduce usage of $globals
#   clean up code... looks like sludge

require 'getoptlong'
require 'rdoc/usage'


def main()

  opts =
    [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
    [ '--lang', '-l', GetoptLong::REQUIRED_ARGUMENT ],
    [ '--lang-opts', '-o', GetoptLong::REQUIRED_ARGUMENT ],
    [ '--debug', '-d', GetoptLong::OPTIONAL_ARGUMENT ],
    [ '--prof', '-p', GetoptLong::OPTIONAL_ARGUMENT ],
    [ '--clean', '-c', GetoptLong::NO_ARGUMENT ],
    [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ]

    opts.each do |opt, arg|
      case opt
        when '--help'
        when '--lang'
          proc_lang( arg )
        when '--lang-opts'
          puts "#{arg} -> --lang-opts not implemented!"
        when '--debug'
          $debug = true
        when '--prof'
          $profiler = arg
        when '--verbose'

    if ARGV[0]
      $project = ARGV[0]
    if ARGV[1]
      $startdir = ARGV[1]
    puts ARGV #debug
    puts "\n\n"

    unless $lang
      $stderr.puts( 'WARNING: --lang not set!, defaulting to ISO C99' )
    # call usage() on *any* error and print the problem
    rescue StandardError 
      puts( $! )



def proc_lang( str )

  case str
    when 'c','C'
      # set up for C
    when 'c++','cpp','C++','C++','cc','CC','cxx','CXX'
      # set up for C++
    when 'java','Java'
      # set up for Java
    when 'Perl','pl', 'plx'
      # Setup for Perl
    when 'Python','py'
      # Setup for Python
    when 'Ruby','rb'
      # set up for Ruby ;-)

class Lang

  def make()

  def each( startdir, &block )
    dp = do |dir|
      dir.each do |node|
        if node == '.' or node == '..' 
        p = File.expand_path( node, startdir )
        yield( p )
        if p )
          self.each( p, &block )

end # !class Lang

class LangC < Lang

  @@compiler  =   'gcc'
  @@cflags    =   "-Wall -Wpointer-arith -Wcast-qual -Wcast-align " +
                  "-Wconversion -Waggregate-return -Wstrict-prototypes " +
                  "-Wmissing-prototypes -Wmissing-declarations " +
                  "-Wredundant-decls -Winline -Wnested-externs " +
                  "-std=c99 -march=i686 -pipe "
  @@ldfags    =   nil
  @@debug     =   '-g'
  @@prof      =   nil
  @filelist =

  # The very bloody boring constructor which serves only to override the
  # defaults for our static class variables.
  def initialize( compiler=false, cflags=false, ldflags=false, 
                  debug=false, prof=false )

    if compiler then @@compiler = compiler end
    if cflags then @@cflags = cflags end
    if ldflags then @@ldfags = ldflags end
    if debug then @@debug = debug end
    if prof then @@prof = prof end


  # Assemble project
  def make()

    @filelist =


  # Walk the directory tree and compile all .c files into .o
  def compile()

    $stdout.puts '------- COMPILING -------' if $verbose

    self.each( $startdir ) do |file|
      if file =~ /.*\.c$/ 
        p = file.to_s.gsub( File.extname(file),".o" )
        @filelist.push( p )
        # Don't compile unless the source is newer then the object files
        if File.exists?( p )
          next unless timecheck(file,p)
        system( "#{@@compiler} #{@@cflags} #{@@debug} #{@@prof} " +
                      "#{file} -c -o #{p}" )

  # Walk the directory tree and link all object files
  def link()

    $stdout.puts '------- LINKING -------' if $verbose

    @filelist.each do |obj|
      system( "#{@@compiler} #{@@cflags} #{@@ldflags} #{@@debug} " +
                    "#{@@prof} #{obj} -o #{$startdir}/#{$project}" )

  # Return true if first filename has a newer time stamp then the second
  def timecheck( f1, f2 )
    File.mtime( f1 ) > File.mtime( f2 ) ? true : false


if __FILE__ == $0

No comments:

Post a Comment