Here's the Makefile I came up after endless trials and errors.
Hope you'll find it useful. - yotam (yotam_med...@tmai.com)
-------------------------------- Makefile --------------------------------
# $Id: Makefile,v 1.1 1995/06/29 06:46:35 yotam Exp yotam $
################################################################
# By Yotam Medini / yo...@netcom.com, yotam_med...@tmai.com #
# May 95 #
################################################################
#
# I try to do the following:
# * Install Tcl/Tk with shared library. Also install tclsh/wish
# using these libtcl/libtk libraries.
# * Make all installation, without editing any file.
# * Put all the installation setting in this single Makefile
# * Try to use common rule-tricks for both tcl-tk.
# * Avoid being root as possible.
#
# Because I don't know how to install shared libraries in arbitrray
# directory that can used by any tool, the step for installing
# the shared libraries must be done by root.
# Thus the installation consist of the following:
#
# * Arrange the following three files:
# This Makefile
# tcl$(VERSION).tar.gz
# tk$(VERSION).tar.gz
# * Edit this Makefile, or append make call consistently.
# Specific make-variables that one may likely want to change are:
# prefix, SLDIR.
# * Issue the following 6 make-calls. All from this Makefile's directory.
# In parenthesis (user)/(root) refering who should issue the call.
# (user)% make tcl-pre-root
# (root)# make Tcl-install-shared-lib
# (user)% make tcl-post-root
# (user)% make tk-pre-root
# (root)# make tk-install-shared-lib
# (user)% make tk-post-root
#
#
# I did not make any effort to ensure smart dependencies. This may be
# non-trivial task, since the objects need to be compiled more than once
# to produce the static library, the jump table and the shared library.
# Also, this Makefile is supposed to serve installation rather than
# development.
#
################################################################
# Here is a quote from the tsx-11.mit.edu distribution.
# (InfoMagic - Disc 3 of the March 95).
# darkstar:70>cd /cdrom/tsx-11/packages/GCC/src
# darkstar:71>ls -ldg tools-2.17.tar.gz
# -r--r--r-- 1 root bin 161297 Feb 25 23:34 tools-2.17.tar.gz
# darkstar:72>gzip -cd tools-2.17.tar.gz | tar tvf - | grep table_description
# -rw-r--r-- eric/other 10465 Feb 4 12:49 1995
# tools-2.17/doc/table_description
#
# # This is the database of all registered Linux(TM) libraries. The format of
# # this file is as follows. - Mitch Sep `93
# #
# ...
# Library: libtcl.so
# Description: Tool control library
# Maintainer: Jay Carlson
# Email: n...@theory.cs.mankato.msus.edu
# Start: 0x60c00000
# End: 0x60cfffff
#
# Library: libtk.so
# Maintainer: Jay Carlson
# Email: n...@theory.cs.mankato.msus.edu
# Description: Tool control library
# Start: 0x60d00000
# End: 0x60dfffff
#
prefix = /home/local
# unfortunately, ld.so wants it in pre-configured places
SLDIR = /usr/local/lib
INSTALL = /usr/bin/install -c
INSTALL_PROGRAM = $(INSTALL) -s
INSTALL_DATA = $(INSTALL) -m 644
########################################################################
########################################################################
######################## TCL ########################
TCLVER = 7.4b4
TCLDIR = tcl$(TCLVER)
TCLTGZ = $(TCLDIR).tar.gz
tcl-extract:
gzip -cd $(TCLTGZ) | tar xvf -
tcl-config:
(cd $(TCLDIR); ./configure --prefix=$(prefix))
tcl-compile:
(cd $(TCLDIR); make -w)
########################################################################
# The following inspired from:
# "A Method for Building Shared Libraries" / Eric Kasten
# Linux Journal April 1995.
#
# Values are taken from Makefile of sunsite.unc.edu Linux archive
# in which README.linux is signed by David Engel da...@ods.com
#
# LIBGCC = /usr/lib/gcc-lib/i486-linux/2.6.3/libgcc.a
LIBGCC := $(shell $(CC) -print-libgcc-file-name)
GCCJUMPAS = gcc -B/usr/bin/jump
SL_PATH = $(prefix)/lib
TCL_SL_VERSION = 7.4.0
TCL_SL_LOAD_ADDRESS = 0x60c00000
TCL_SL_JUMP_TABLE_SIZE = 0x4000
TCL_SL_GOT_SIZE = 4096
TCL_SL_IMPORT = /usr/lib/libc.sa
TCL_SL_EXTRA_LIBS = $(LIBGCC) -lm -lc
TCL_SHPARMS = \
-l $(SL_PATH)/libtcl \
-v $(TCL_SL_VERSION) \
-a $(TCL_SL_LOAD_ADDRESS) \
-j $(TCL_SL_JUMP_TABLE_SIZE) \
-g $(TCL_SL_GOT_SIZE)
TCL_VERIFYPARMS = -llibtcl.so.$(TCL_SL_VERSION) -- libtcl.sa
TCL_JUMPDIR = $(TCLDIR)/jump
$(TCL_JUMPDIR):
mkdir -p $(TCL_JUMPDIR)
$(TCL_JUMPDIR)/jump.import: $(TCL_JUMPDIR)
make \
JUMPIMPORT=$(TCL_JUMPDIR)/jump.import \
SL_IMPORT=$(TCL_SL_IMPORT) \
shlib-import
tcl-shlib-import: $(TCL_JUMPDIR)/jump.import
# Generate dummy .c files
$(TCLDIR)/dummyMain.c:
(echo '#include "tcl.h"'; \
echo 'int main(int ac, char **av)'; \
echo '{ Tcl_Main(ac, av, (Tcl_AppInitProc*)0); return 0;}') > $@
$(TCLDIR)/dummyInit.c:
(echo '#include "tcl.h"'; \
echo 'int Tcl_AppInit(Tcl_Interp *interp)'; \
echo '{return TCL_ERROR;}') > $@
# tcl - shared object
# Note, the sub-make call use stdin as Makefile, (adding objs target)
# so it will only compile library objects.
TCLDUMSRC = $(TCLDIR)/dummyMain.c $(TCLDIR)/dummyInit.c
tcl-shobjs: $(TCL_JUMPDIR)/jump.import $(TCLDUMSRC)
(cd $(TCLDIR); \
/bin/rm -f jump/jump.log *.o; \
make dummyMain.o ; \
JUMP_LIB=libtcl; export JUMP_LIB; \
JUMP_DIR=`pwd`/jump; export JUMP_DIR; \
(cat Makefile; echo objs: '$$(OBJS)') | \
make -f - dummyInit.o objs CC="$(GCCJUMPAS)")
$(TCL_JUMPDIR)/jump.log: tcl-shobjs
tclvarsfuncs: $(TCL_JUMPDIR)/jump.log
(cd $(TCL_JUMPDIR); \
JUMP_DIR=`pwd`; export JUMP_DIR; \
getvars; getfuncs; /bin/rm -f jump.log)
# Generate list of tcl.h - declared exported functions
# We add:
# matherr(), since tclAppInit.c needs it.
# panic(), TclOpen(), TclRead(), TclWaitpid(), TclWrite() since Tk uses it.
tclexpflist: $(TCLDIR)/tcl.h
echo matherr > $@
echo panic >> $@
echo TclOpen >> $@
echo TclRead >> $@
echo TclWaitpid >> $@
echo TclWrite >> $@
(cd $(TCLDIR); \
grep EXTERN tcl.h | grep Tcl_ | grep _ANSI_ARGS_ | \
sed 's/.*Tcl_\(.*\) _ANSI.*/Tcl_\1/') >> $@
# split $(TCLDIR)/jump/jumps.func into jump.func.new + jump.fignore
tclfignore: tclexpflist
cp $(TCLDIR)/jump/jump.funcs jump.fignore
/bin/rm -f jump.funcs.new
for ef in `cat tclexpflist`; \
do \
grep "T _$$ef " jump.fignore >> jump.funcs.new; \
grep -v "T _$$ef " jump.fignore > jump.fignore.new; \
mv jump.fignore.new jump.fignore; \
done
# split $(TCLDIR)/jump/jumps.vars into jump.vars.new + jump.vignore
# The list is limited, so we hard code it
# rather then making an analog tclexpvlist
tclvignore:
cp $(TCLDIR)/jump/jump.vars jump.vignore
/bin/rm -f jump.vars.new
for ev in tcl_AsyncReady tcl_FileCloseProc tcl_RcFileName; \
do \
grep "D _$$ev " jump.vignore >> jump.vars.new; \
grep -v "D _$$ev " jump.vignore > jump.vignore.new; \
mv jump.vignore.new jump.vignore; \
done
tcl-ignore: tclvarsfuncs tclfignore tclvignore
cat jump.fignore jump.vignore > $(TCLDIR)/jump/jump.ignore
cp jump.funcs.new $(TCLDIR)/jump/jump.funcs
cp jump.vars.new $(TCLDIR)/jump/jump.vars
/bin/rm -f jump.fignore jump.vignore jump.funcs.new jump.vars.new
# After the jump.vars, jump.funcs, jump.ignore were made
# getsize requires re-compilation of the shared objects!!
# So call 'make tcl-shobjs' again.
tcl-varsize:
$(MAKE) TDIR=$(TCLDIR) varsize
tclolist:
(cd $(TCLDIR); \
(cat Makefile; echo -ne "echoobjs:\n\t@echo"; echo ' $$(OBJS)') | \
make -f - --no-print-directory echoobjs) > $@
tcl-shlib: tclolist
(cd $(TCLDIR); \
JUMP_LIB=libtcl; export JUMP_LIB; \
JUMP_DIR=`pwd`/jump; export JUMP_DIR; \
mkimage $(TCL_SHPARMS) -- \
dummyInit.o `cat ../tclolist` $(TCL_SL_EXTRA_LIBS); \
mkstubs $(TCL_SHPARMS) -- libtcl; \
ar rs libtcl.sa dummyMain.o; \
verify-shlib $(TCL_VERIFYPARMS))
# instead of a script
tcl-pre-root:
/bin/rm -rf $(TCLDIR) jump.* tclexpflist tclolist
$(MAKE) tcl-extract tcl-config tcl-compile
(cd $(TCLDIR); mv libtcl.a libtcl.a.SAVE)
$(MAKE) tcl-ignore
$(MAKE) tcl-shobjs
$(MAKE) tcl-varsize
$(MAKE) tcl-shlib
# By root only
tcl-install-shared-lib:
make -w PKGDIR=$(TCLDIR) LIB=libtcl JUMPVER=$(TCL_SL_VERSION) \
install-shared-lib
# echo -ne "\t\$${CC} \$${LDFLAGS_SWITCHES} \$${CC_SWITCHES} ";
tclsh:
(cd $(TCLDIR); \
/bin/rm -f tclsh tclAppInit.o; \
(cat Makefile; echo tclsh.so: tclAppInit.o; \
echo -ne "\tgcc \$${LDFLAGS_SWITCHES} "; \
echo "tclAppInit.o -L/usr/local/lib -ltcl \$${MATH_LIBS} -o tclsh") \
| make -w -f - tclsh.so)
# Install the static libtcl.a and the dynimically linked tclsh.
# Do touches so nothing will re-compile.
tcl-install: tclsh
(cd $(TCLDIR); \
mv libtcl.a.SAVE libtcl.a; \
touch libtcl.a; touch tclsh; \
make -w install)
tcl-install-link:
$(MAKE) TDIR=$(TCLDIR) LIB=libtcl TOOL=tclsh install-link
tcl-post-root: tcl-install tcl-install-link
######################## end of TCL ########################
########################################################################
########################################################################
########################################################################
########################################################################
######################## TK ########################
TKVER = 4.0b4
TKDIR = tk$(TKVER)
TKTGZ = $(TKDIR).tar.gz
tk-extract:
mkdir -p $(TKDIR)
chmod -R +w $(TKDIR)
/bin/rm -rf $(TKDIR)
gzip -cd $(TKTGZ) | tar xvf -
tk-config:
(cd $(TKDIR); ./configure --prefix=$(prefix))
tk-compile:
(cd $(TKDIR); make -w)
TK_SL_VERSION = 4.0.0
TK_SL_LOAD_ADDRESS = 0x60d00000
TK_SL_JUMP_TABLE_SIZE = 0x4000
TK_SL_GOT_SIZE = 4096
TK_SL_IMPORT = /usr/lib/libc.sa
TK_SL_EXTRA_LIBS = -ltcl -lX11 $(LIBGCC) -lm -lc
TK_SHPARMS = \
-l $(SL_PATH)/libtk \
-v $(TK_SL_VERSION) \
-a $(TK_SL_LOAD_ADDRESS) \
-j $(TK_SL_JUMP_TABLE_SIZE) \
-g $(TK_SL_GOT_SIZE)
TK_VERIFYPARMS = -llibtk.so.$(TK_SL_VERSION) -- libtk.sa
TK_JUMPDIR = $(TKDIR)/jump
$(TK_JUMPDIR):
mkdir -p $(TK_JUMPDIR)
$(TK_JUMPDIR)/jump.import: $(TK_JUMPDIR)
make \
JUMPIMPORT=$(TK_JUMPDIR)/jump.import \
SL_IMPORT=$(TK_SL_IMPORT) \
shlib-import
tk-shlib-import: $(TK_JUMPDIR)/jump.import
# Generate dummy .c files
$(TKDIR)/dummyMain.c:
(echo '#include "tk.h"'; \
echo 'int main(int ac, char **av)'; \
echo '{ Tk_Main(ac, av, (Tcl_AppInitProc*)0); return 0;}') > $@
# $(TKDIR)/dummyInit.c:
# (echo '#include "tk.h"'; \
# echo 'int Tk_Init(Tcl_Interp *interp)'; \
# echo '{return TCL_ERROR;}') > $@
# tk - shared object
# Note, the sub-make call use stdin as Makefile, (adding objs target)
# so it will only compile library objects.
TKDUMSRC = $(TKDIR)/dummyMain.c
tk-shobjs: $(TK_JUMPDIR)/jump.import $(TKDUMSRC)
(cd $(TKDIR); \
/bin/rm -f jump/jump.log *.o; \
make dummyMain.o ; \
JUMP_LIB=libtk; export JUMP_LIB; \
JUMP_DIR=`pwd`/jump; export JUMP_DIR; \
(cat Makefile; echo objs: '$$(OBJS)') | \
make -f - objs CC="$(GCCJUMPAS)")
$(TK_JUMPDIR)/jump.log: tk-shobjs
tkvarsfuncs: $(TK_JUMPDIR)/jump.log
(cd $(TK_JUMPDIR); \
JUMP_DIR=`pwd`; export JUMP_DIR; \
getvars; getfuncs; ls -l jump; /bin/rm -f jump.log)
# Generate list of tk.h - declared exported functions
tkexpflist: $(TKDIR)/tk.h
echo matherr > $@
(cd $(TKDIR); \
grep EXTERN tk.h | grep Tk_ | grep _ANSI_ARGS_ | \
sed 's/.*Tk_\(.*\) _ANSI.*/Tk_\1/') >> $@
# split $(TKDIR)/jump/jumps.func into jump.func.new + jump.fignore
tkfignore: tkexpflist
cp $(TKDIR)/jump/jump.funcs jump.fignore
/bin/rm -f jump.funcs.new
for ef in `cat tkexpflist`; \
do \
grep "T _$$ef " jump.fignore >> jump.funcs.new; \
grep -v "T _$$ef " jump.fignore > jump.fignore.new; \
mv jump.fignore.new jump.fignore; \
done
# split $(TKDIR)/jump/jumps.vars into jump.vars.new + jump.vignore
tkvignore:
$(MAKE) \
JUMPDIR=$(TKDIR)/jump \
VLIST='tk_CanvasTagsOption tk_NumMainWindows' \
vignore
tk-ignore: tkvarsfuncs tkfignore tkvignore
cat jump.fignore jump.vignore > $(TKDIR)/jump/jump.ignore
cp jump.funcs.new $(TKDIR)/jump/jump.funcs
cp jump.vars.new $(TKDIR)/jump/jump.vars
/bin/rm -f jump.fignore jump.vignore jump.funcs.new jump.vars.new
# After the jump.vars, jump.funcs, jump.ignore were made
# getsize requires re-compilation of the shared objects!!
# So call 'make tk-shobjs' again.
tk-varsize:
$(MAKE) TDIR=$(TKDIR) varsize
tkolist:
(cd $(TKDIR); \
(cat Makefile; echo -ne "echoobjs:\n\t@echo"; echo ' $$(OBJS)') | \
make -f - --no-print-directory echoobjs) > $@
tk-shlib: tkolist
(cd $(TKDIR); \
JUMP_LIB=libtk; export JUMP_LIB; \
JUMP_DIR=`pwd`/jump; export JUMP_DIR; \
mkimage $(TK_SHPARMS) -- \
`cat ../tkolist` $(TK_SL_EXTRA_LIBS); \
mkstubs $(TK_SHPARMS) -- libtk; \
ar rs libtk.sa dummyMain.o; \
verify-shlib $(TK_VERIFYPARMS))
# instead of a script
tk-pre-root:
/bin/rm -rf $(TKDIR) jump.* tkexpflist tkolist
$(MAKE) tk-extract tk-config tk-compile
(cd $(TKDIR); mv libtk.a libtk.a.SAVE)
$(MAKE) tk-ignore
$(MAKE) tk-shobjs
$(MAKE) tk-varsize
$(MAKE) tk-shlib
# By root only
tk-install-shared-lib:
make -w PKGDIR=$(TKDIR) LIB=libtk JUMPVER=$(TK_SL_VERSION) \
install-shared-lib
wish:
(cd $(TKDIR); \
/bin/rm -f wish tkAppInit.o; \
(cat Makefile; echo wish.so: tkAppInit.o; \
echo -ne "\tgcc \$${LDFLAGS_SWITCHES} tkAppInit.o "; \
echo -ne "-L/usr/local/lib -ltk -ltcl \$${X11_LIB_SWITCHES} "; \
echo "-lm -o wish") \
| make -w -f - wish.so)
tk-install: wish
(cd $(TKDIR); \
mv libtk.a.SAVE libtk.a; \
make -w libtk.a; \
mv tkAppInit.o.SAVE tkAppInit.o; \
touch libtk.a; touch wish; \
make -w install)
tk-install-link:
$(MAKE) TDIR=$(TKDIR) LIB=libtk TOOL=wish install-link
tk-post-root: tk-install tk-install-link
######################## end of TK ########################
########################################################################
########################################################################
########################################################################
# Tcl/Tk - common rules, targets, etc.
# split $(JUMPDIR)/jumps.vars into jump.vars.new + jump.vignore
# The list is limited, so we don't use fancy grep as for [foo]expflist
# rather then making an analog tkexpvlist
vignore:
cp $(JUMPDIR)/jump.vars jump.vignore; \
/bin/rm -f jump.vars.new; \
for ev in $(VLIST); \
do \
egrep "[CD] _$$ev " jump.vignore >> jump.vars.new; \
egrep -v "[CD] _$$ev " jump.vignore > jump.vignore.new; \
mv jump.vignore.new jump.vignore; \
done
shlib-import:
echo -n > $(JUMPIMPORT)
for lib in $(SL_IMPORT); \
do nm --no-cplus -o $$lib | grep '__GOT__' | sed 's/__GOT__/_/' \
>> $(JUMPIMPORT); \
done
varsize:
(cd $(TDIR)/jump; \
JUMP_DIR=`pwd`; export JUMP_DIR; \
getsize > jump.vars-new; \
mv jump.vars jump.vars-old; \
mv jump.vars-new jump.vars)
# By root only!
# $(INSTALL_PROGRAM) $(LIB).so.$(JUMPVER) $(SLDIR) )
install-shared-lib:
(cd $(SLDIR); rm -f $(LIB).so.* $(LIB).sa)
(cd $(PKGDIR); \
$(INSTALL_DATA) $(LIB).sa $(SLDIR); \
$(INSTALL) $(LIB).so.$(JUMPVER) $(SLDIR) )
/sbin/ldconfig -vn $(SLDIR)
install-link:
(VERSION=`grep VERSION $(TDIR)/Makefile \
| head -1 | cut -d= -f2 | tr -d " "`;\
(cd $(prefix)/lib; \
/bin/rm -f $(LIB).a; \
ln -s $(LIB)$$VERSION.a $(LIB).a); \
(cd $(prefix)/bin; \
/bin/rm -f $(TOOL); \
ln -s $(TOOL)$$VERSION $(TOOL)))
# convinient date; target; date
dtd:
date
$(MAKE) $(TARGET)
date