It Seemed Like a Good Idea at the Time Coding, Mostly

19May/092

Haskell: A Pretty Nice Language

I was going through one of those "every language sucks" periods a few days back, so I decided to do something productive and learn me a Haskell. So far, I'm liking it: the pure functional style isn't as hard as I expected, monads are okay after a bit (though I'm still a little suspicious of them), the strict typing isn't too much of a burden, the polymorphic types are bliss to use, and the pattern matching is simply wonderful.  It also comes with an extensive set of libraries and a central repository, which is nice to find in a non-mainstream language. Overall, I think Haskell is a good language to know.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Filed under: Uncategorized 2 Comments
8May/090

Super-Makefile has levelled up! SuperMakefile became BashBuild!

I had just about reached the limits of what was possible with just a makefile, but I still felt like adding more. So I rewrote the thing today as a shell script. Now, you simply call it as './configure', and it generates the Makefile for you. The script is still configured in much the same manner as the old Makefile, except now you don't have to specify a compiler.

More importantly, the rewrite has allowed a whole bunch of new tricks, including:

  • Command-line specification of the install prefix
  • Now the commands are familiar to anyone who has ever done a "./configure && make && sudo make install" before
  • Out of source builds are now implemented
  • Autodetection of the C compiler

And most importantly:

  • Plenty of room to grow

Unfortunately, the code took a major step backwards in attractiveness. Over the next few days I may tinker around with it in an attempt to make it not look quite so bad, and possibly move more logic out into the configure script.

Other major news of the day: I finally dumped bzr for git, just so I could use GitHub. The new project is named BashBuild.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Filed under: coding No Comments
5May/090

Revenge of the Super-Makefile

So today I found some more things that the old Makefile was lacking. An "install" target, a ".PHONY" target to prevent breakage down the line, and the ability to recursively build subprojects. A few hours later, I have this:

PROJECT=foo
VERSION=0.0.1
SOURCES=bar.c baz.c
SUBPROJECTS=xyzzy fnord
LIBRARY=-lm
INCPATHS=xyzzy fnord
LIBPATHS=fnord
PREFIX=/usr/local
LDFLAGS=
CFLAGS=-c -Wall -g
CC=gcc

# ------------ MAGIC BEGINS HERE -------------

# We want subprojects to use these variables
export CC
export PREFIX

# Automatic generation of some important lists
OBJECTS=$(SOURCES:.c=.o)
INCFLAGS=$(foreach TMP,$(INCPATHS),-I$(TMP))
LIBFLAGS=$(foreach TMP,$(LIBPATHS),-L$(TMP))

# Set up the output file names for the different output types
ifeq "$(LIBRARY)" "shared"
    BINARY=lib$(PROJECT).so
else ifeq "$(LIBRARY)" "static"
    BINARY=lib$(PROJECT).a
else
    BINARY=$(PROJECT)
endif

all: $(SOURCES) $(SUBPROJECTS) $(BINARY)

$(BINARY): $(OBJECTS)
ifdef SOURCES
    # Assemble the object files into the right type of binary
    ifeq "$(LIBRARY)" "static"
        ar rcs $(BINARY) $(OBJECTS)
    else ifeq "$(LIBRARY)" "shared"
        $(CC) -shared $(LIBFLAGS) $(OBJECTS) $(LDFLAGS) -o $@
    else
        $(CC) $(LIBFLAGS) $(OBJECTS) $(LDFLAGS) -o $@
    endif
endif

$(SUBPROJECTS):
        make -e -C $@

.c.o:
        $(CC) $(INCFLAGS) $(CFLAGS) -fPIC $< -o $@

install:
        @ for i in $(SUBPROJECTS); do make -e -C $${i} install; done
ifdef SOURCES
    ifeq "$(LIBRARY)" "static"
        install $(BINARY) $(PREFIX)/lib
    else ifeq "$(LIBRARY)" "shared"
        install $(BINARY) $(PREFIX)/lib
    else
        install $(BINARY) $(PREFIX)/bin
    endif
endif

distclean:
        rm -f $(BINARY) $(OBJECTS)
        @ for i in $(SUBPROJECTS); do make -C $${i} distclean; done

clean:
        rm -f $(OBJECTS)
        @ for i in $(SUBPROJECTS); do make -C $${i} clean; done

.PHONY: all clean distclean install $(SUBPROJECTS)

It's longer, but not by too much, and now I can safely say it has everything I have ever needed in a fancy build system. It would be nice if I could get pretty colourized output, but this Makefile reliably builds, cleans, and installs the projects I have tested it on.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Tagged as: , , No Comments
4May/090

The Super-Makefile

After toying with build systems off and on for months, I concluded today that make is about as advanced as I ever need to get for my projects. In the past, I recall using this gem of a Makefile.  But my needs in a build process have grown a little. First of all, I now prefer C to C++, so that had to be changed. Then I had to go about adding static and shared library abilities to it. Then I added "clean" and "distclean" build targets, and include and library search paths got introduced somewhere along the way.

After good half hour of modification, I had the following Makefile, posted here mainly so I can find it easily from any computer. By modifying the first six variables defined in the Makefile, it can be adapted to almost any C project of reasonable complexity. It has no support for cross-platform library identification, out-of-source builds, or debug and release build toggles. But on the other hand, I can never get those things to work right any way.

Toggling between static library, shared library, and executable build modes is performed by setting the LIBRARY variable to "static", "shared", or anything that isn't those two values.

PROJECT=foo
SOURCES=bar.c baz.c
LIBRARY=nope
INCPATHS=../some_other_project/
LIBPATHS=../yet_another_project/
LDFLAGS=-ldosomething
CFLAGS=-c -Wall
CC=gcc

# ------------ MAGIC BEGINS HERE -------------

# Automatic generation of some important lists
OBJECTS=$(SOURCES:.c=.o)
INCFLAGS=$(foreach TMP,$(INCPATHS),-I$(TMP))
LIBFLAGS=$(foreach TMP,$(LIBPATHS),-L$(TMP))

# Set up the output file names for the different output types
ifeq "$(LIBRARY)" "shared"
    BINARY=lib$(PROJECT).so
    LDFLAGS += -shared
else ifeq "$(LIBRARY)" "static"
    BINARY=lib$(PROJECT).a
else
    BINARY=$(PROJECT)
endif

all: $(SOURCES) $(BINARY)

$(BINARY): $(OBJECTS)
    # Link the object files, or archive into a static library
    ifeq "$(LIBRARY)" "static"
        ar rcs $(BINARY) $(OBJECTS)
    else
        $(CC) $(LIBFLAGS) $(OBJECTS) $(LDFLAGS) -o $@
    endif

.c.o:
        $(CC) $(INCFLAGS) $(CFLAGS) -fPIC $< -o $@

distclean: clean
        rm -f $(BINARY)

clean:
        rm -f $(OBJECTS)
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Tagged as: , , No Comments