How to Package and Publish an Open Source Project

autoconf

For packaging source code, the standard Unix practice today is to use autoconf. It is a set of extensible M4 macros that produce shell scripts. These scripts can adapt the packages to many different UNIX systems without manual user intervention.

This is how to build a simple autoconf setup, with a minimal set of features. I start with an empty directory, bring in the source code as stelnet.c, and create an empty install.sh file (autoconf complains without it).

$ mkdir stelnet && cd stelnet
$ touch install.sh

The next step is to create a configure.ac file with the following content:

AC_PREREQ([2.68])
AC_INIT(simpletelnet, 0.9, netblue30@yahoo.com, , http://simpletelnet.sourceforge.net)
AC_CONFIG_SRCDIR([stelnet.c])
#AC_CONFIG_HEADERS([config.h])

AC_PROG_CC
AC_PROG_CXX
AC_PROG_INSTALL
AC_PROG_RANLIB

# checking pthread library
AC_CHECK_LIB([pthread], [main], [], AC_MSG_ERROR([*** POSIX thread support not installed ***]))
AC_CHECK_HEADER(pthread.h,,AC_MSG_ERROR([*** POSIX thread support not installed ***]))

AC_OUTPUT(Makefile)

These are the commands used in the file:

  • AC_INIT – project data.
  • AC_PROG_C, AC_PROG_CXX – detect the C/C++ compilers.
  • AC_PROG_RANLIB – needed if any libraries are built in the package.
  • AC_CHECK_LIB, AC_CHECK_HEADER – checking for a required library.
  • AC_OUTPUT – generate a Makefile based on Makefile.in template.

This setup requires a template file, Makefile.in. It is basically a regular Makefile that will compile and install the project, with a number of macros generated by autoconf scripts. As such, I have added support to get the package name, version number and install prefix from autoconf. The prefix is used during software installation (make install), the version and package name are used during source package build (make dist).

all: stelnet

PREFIX=@prefix@
VERSION=@PACKAGE_VERSION@
NAME=@PACKAGE_NAME@

H_FILE_LIST       = $(wildcard *.[h])
C_FILE_LIST       = $(wildcard *.c)
OBJS = $(C_FILE_LIST:.c=.o)
BINOBJS =  $(foreach file, $(OBJS), $file)
CFLAGS += -ggdb

%.o : %.c $(H_FILE_LIST)
	$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@

stelnet: $(OBJS)
	$(CXX)  $(LDFLAGS) -o $@ $(OBJS) $(LIBS)

clean:; rm -f *.o stelnet

distclean: clean
	rm -fr Makefile autom4te.cache config.log config.status config.h

install: all
	strip stelnet
	mkdir -p $(PREFIX)/bin
	mkdir -p $(PREFIX)/share/doc/stelnet
	install -c -m 0755 stelnet $(PREFIX)/bin/.
	install -c -m 0644 COPYING $(PREFIX)/share/doc/stelnet/.
	install -c -m 0644 README $(PREFIX)/share/doc/stelnet/.
	install -c -m 0644 RELNOTES $(PREFIX)/share/doc/stelnet/.

uninstall:;
	rm -f $(PREFIX)/bin/stelnet
	rm -fr $(PREFIX)/share/doc/stelnet

dist:
	mkdir $(NAME)-$(VERSION)
	cd $(NAME)-$(VERSION); cp -a ../* .; rm -fr $(NAME)-$(VERSION); make distclean; cd ..
	tar -cjvf $(NAME)-$(VERSION).tar.bz2 $(NAME)-$(VERSION)
	rm -fr $(NAME)-$(VERSION)

The last three files needed are COPYING, README and RELNOTES. These files are treated as documentation. With all the files in place, I run autoconf command to create the configuration script:

$ autoconf
$ ls 
configure     COPYING     Makefile.in  RELNOTES
configure.ac  install.sh  README       stelnet.c

Building the project

I start by testing the configuration script. Running the script, it should create a Makefile.

$ ./configure
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for g++... g++
checking whether we are using the GNU C++ compiler... yes
checking whether g++ accepts -g... yes
checking for a BSD-compatible install... /usr/bin/install -c
checking for ranlib... ranlib
checking for main in -lpthread... yes
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking pthread.h usability... yes
checking pthread.h presence... yes
checking for pthread.h... yes
configure: creating ./config.status
config.status: creating Makefile

The Makefile is basically our template with the macros replaced by project name, version and install prefix. Time to build and install the project:

$ make && sudo make install

I run make dist in order to build the software package:

$ make dist
$ ls *.tar.bz2
simpletelnet-0.9.tar.bz2
About these ads

One thought on “How to Package and Publish an Open Source Project

  1. Pingback: Hallow Demon

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s