Use the Imakefile!
				or:
	Some mean tricks to get the stuff compiled!


Traditionally X apps come with an Imakefile to use the old tool available 
for virtually all official X11R6 platforms (and some others). Its use
is recommended in the FAQ. 

	A) A short introduction 
	 ----------------------
	(by Hung-Chi Chu )


			Autoconf vs. Imakefile
			======================

  I would like to share my experience about autoconf and Imakefile.

- autoconf/emx is not perfect, especially on Makefiles generated
  automatically. I don't like to modify any auto-generated files since
  they are "monsters" and the modification will be overwritten when
  the next configure runs.
- autoconf/emx is nearly perfect for generating config.h except that
  occasionally I need to add/modify a few lines in configure.in for 
  searching some special functions in add-on libraries.
- for other auto-generated and non-intermediate files which have
  path definition in them, such as the script 'gtk-config',
  write a new file called *.os2 by substitute the drive letter with
  ${X11ROOT} et al.
- Imakefile is neat for X/2 libraries and programs. It is analogous to
  "Makefile.am" for autoconf.  It is not difficult to write an Imakefile
  from Makefile.am.
  For non-X lib/prog, it is also simple to rewrite a neat Makefile for
  os2 (ex. Makefile.emx) from Makefile.am. 
- The effort of rewriting Imakefile/Makefile.emx is almost at finding
  all DEFINES for gcc. This can be easily done by searching "-D"
  in Makefiles generated by configure.

- Following are the main steps I apply to do port:
  1. use autoconf/emx to generate config.h, Makefile et al.
  2. for the first version:
     2.1 rewrite Imakefile/Makefile.emx from Makefile.am
     2.2 check some auto-generated and non-intermediate files.
          modify and rename them as *.os2 if necessary
     2.3 for dynamic library, make a module definition file *.def
          and a response file *os2.rsp (necessary for Imakefile)
  3. for the following versions:
     3.1 apply the patch of the previous version
     3.2 diff -u previous_version/Makefile.am this_version/Makefile.am
     3.3 modify Imakefile/Makefile.am from the result of 3.1
     3.4 "diff -u" of any other special *.in files and modify
          the corresponding *.os2
     3.5 for dynamic libraries, check *.def and modify it if necessary
  4. for Imakefile: xmkmf; make Makefiles; make
                      or xmkmf -a; make
      for Makefile.emx:
           gmake -f Makefile.emx all
  5. "make install" and make a patch file by "diff -ruN" if all work well
  6. make the zip package. :-)

- I have used these procedures to port many libs/progs,
  including some not-yet-released GNOME-related binaries. :-)



	B) Preliminary steps
	--------------------
The following is meant to overcome some simple, nevertheless annoying problems
and to make things work faster: Quick and simple fixes, some dirty stolen tricks.

1) RTF docs
-----------

- Read the README file!
- Read the INSTALL file!
- Read any additional info files from the program authors. Many problems 
  ocurring under special UN*X flavours have a similar counterpart on OS/2
  (others haven't, but this shall be a simple guide :-)


2) Some additions to /XFree86/lib/X11/config/os2.cf and os2.rules
-----------------------------------------------------------------

a) I tried to make life easier, so I've added some defines to the vendor 
specific imake template file: /XFree86/lib/X11/config/os2.cf.

Reasons for that:
- Never edit generated Makefiles by hand: Far too much work for larger
  projects and errors are to be expected. (But sometimes unavoidable).
- If things work and don't break other projects, they should be mailed to
  the respective lists in order to finally become standard.
- Read the /XFree86/lib/X11/config/README file. The following excerpt may 
  be useful, too:

My proposed changes of /XFree86/lib/X11/config/os2.cf:

#define ManSuffix	1x
#define LibManSuffix	3x
#define FileManSuffix	4x

	instead of

#define ManSuffix	1 [... etc.]
(This helps a lot, if you already installed or will install many man pages.
I'm sure this will happen!! Also this is for good reasons now standard on
most recent UN*X versions.)

	Change 
	
#define CplusplusCmd g++

	to
	
#define CplusplusCmd gcc
#define CplusplusOptions -D__ST_MT_ERRNO__ -Zmtd -Zsysv-signals -O2
(I can't find any reason to call emx gcc by a different name for C++ 
or to use different options here. But there were reports of problems 
with the experimental compilers 'pgcc' aka 'egcs'; you might want to
omit -O2 therefore!)

	Change 

#define ExtraLibraries	-lsocket -lbsd

	to
	
XCOMM (There is now a standard -lz port available on Hobbes)
#define HasZlib  	YES 
#define GzipLibrary -lz

#define ExtraLibraries	-lsocket -lbsd -lwrap
(Shouldn't do any harm, but make smaller executables with OS/2 API calls.)
  Imake.tmpl provides defaults for the following variables:

	HasZlib			boolean for system has libz


b) EMX docs recommend using object module format (-Zomf; link386.exe) for
   better stability, if neither gdb.exe nor fork() shall be used. The 
   following additions to /XFree86/lib/X11/config/os2.rules are meant to
   facilitate the switch in this case; nevertheless you'll have to check 
   dependency lines and rules, if a.out format is still used (and some rules
   for libraries will become obsolete, but not harmful):

XCOMM $XConsortium: os2.rules /main/1 1996/10/31 14:47:27 kaleb $
XCOMM platform:  $XFree86: xc/config/cf/os2.rules,v 3.15 1997/01/05 11:49:39 dawes Exp $

.SUFFIXES: .a .lib .o .obj .c .C .cc .cpp

.c.$O:
	$(CC) $(CFLAGS) -c $*.c

#if HasCplusplus
.$C.$O:
	$(CXX) $(CFLAGS) -c $*.$C
#endif

XCOMM Uncomment if using OMF (emxomf called automatically by gcc)!

XCOMM CC  = gcc -Zomf
XCOMM O   = obj
XCOMM LD  = emxomfld
C   = C XCOMM or .cpp
O   = o
A   = .a

	C) Common initial problems
	--------------------------

Initially I thought imake was a labyrinthic beast, deserving the title
of the Minotaurus among the make tools. But with small and simple fixes
to work around some annoying bugs I was able to tame it a bit, so that
'xmkmf' at least does something useful:

1) 'xmkmf -a' crashes because of 'sh' and 'Rexx' conflicts
----------------------------------------------------------

Usually Imakefiles silently assume they are running on UNIX in a Bourne
'sh' environment, since authors intentionally do not support non UNIX
platforms.

Just try running the following changed Rexx scripts first, to create a
working environment:

		make.cmd

/* REXX */

'@echo off'
PARSE ARG a1 a2 a3 a4 a5 a6 a7 a8 a9 a10


/* x11make.exe 'MAKE=x11make.exe SHELL=d:/os2/cmd.exe' a1 a2 a3 a4 a5
a6 a7 a8 a9 a10 */
'SET SHELL=D:\OS2\CMD.EXE'
'SET X11SHELL=D:\OS2\CMD.EXE'
'set emxshell=D:\OS2\CMD.EXE'
'set CONFIG_SHELL=D:\OS2\CMD.EXE'
'set MAKE_SHELL=D:\OS2\CMD.EXE'

x11make.exe 'MAKE=x11make.exe SHELL= MAKE_SHELL=d:\os2\cmd.exe
CONFIG_SHELL=d:\os2\cmd.exe' a1 a2 a3 a4 a5 a6 a7 a8 a9 a10


	or

		gmake.cmd

/* REXX */

'@echo off'
PARSE ARG a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
'set SHELL=d:/bin/ash.exe'
'SET X11SHELL=D:\OS2\CMD.EXE'
'set emxshell=d:/bin/ash.exe'
'set MAKE_SHELL=d:/bin/ash.exe'

/* x11make.exe 'MAKE=x11make.exe SHELL=' a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
*/

x11make.exe 'MAKE=x11make.exe SHELL=d:/bin/ash.exe
MAKE_SHELL=d:/bin/ash.exe CONFIG_SHELL=d:/bin/ash.exe' a1 a2 a3 a4 a5
a6 a7 a8 a9 a10

==================================

Normally, running make.cmd should be sufficient, since the current OS/2 implementation by H. Veit and others makes extensive use of Rexx, needs cmd.exe as command processor and is incompatible with Bourne shells. Here a number of problems arise with many common Imakefiles. 

Now lets assume xmkmf worked. Theoretically the steps are:

	xmkmf
	make Makefiles
	make depend
	make all (or simply: make)
	.\programname.exe for testing
	make install
	make install.man



2) 'make' crashes because of 'sh' and 'Rexx' conflicts
------------------------------------------------------

Imake is misconfigured on most (commercial) UN*X platforms. Authors normally
compensate this by including many lines of (normally highly complicated) 
Bourne shell code and calling several Bourne shell scripts in the Imakefile. In
this case 'make' won't work. Nor does a sh.exe as make shell work:
The current implementation depends on cmd.exe and Rexx. Finding and rewriting
everything in those immense Imakefiles, helper scripts and Makefiles isn't really
an alternative. Just try alternatively make and gmake (having installed e.g. 
/bin/ash.exe). Now make should simply resume where it has crashed. Just delete
'products' of those crashes (empty script output, truncated object files, core 
dumps, etc.) before resuming the process. This makes using Imake real fun! 



3) Imakefile examples
---------------------

$XFree86: config/README states:
  "The easiest way to write an Imakefile is to find another one that does
  something similar and copy/modify it!"

Here some strongly shortened examples that use Bourne shell code: 
sh -c 'for i in '"$(TEXT) $(SRCS) $(MISC) $(HDRS)"' ; do... etc., etc.


	a) creating a library: NormalLibraryTarget(rw, $(OBJS))
	
--------------------------
# Imakefile for xpaint read/write directory

#include "../version"
#include "../Local.config"
INCLUDES = -I.. $(XPM_INCLUDE) $(TIFF_INCLUDE) $(JPEG_INCLUDE) $(PNG_INCLUDE)

# Nothing to change below here

TIFF_SRC = writeTIFF.c readTIFF.c
#ifdef HaveTIFF
TIFF_OBJ = writeTIFF.$O readTIFF.$O 
TIFF_DEF = -DHAVE_TIFF
#endif
[...]
XPM_SRC = readWriteXPM.c
XPM_OBJ = readWriteXPM.$O 

SGI_SRC = readWriteSGI.c
#ifdef SGIArchitecture
SGI_OBJ = readWriteSGI.$O 
SGI_DEF = -DHAVE_SGI
#endif

DEFINES = $(XPM_DEF) $(TIFF_DEF) $(SGI_DEF) $(JPEG_DEF) $(PNG_DEF) \

SRCS = rwTable.c \
	readWriteXBM.c readWritePNM.c readWriteXWD.c writePS.c \
	readGIF.c writeGIF.c $(XPM_SRC) $(TIFF_SRC) $(SGI_SRC) \
	$(JPEG_SRC) $(PNG_SRC) libpnmrw.c 
OBJS = rwTable.$O \
	readWriteXBM.$O readWritePNM.$O readWriteXWD.$O writePS.$O \
	readGIF.$O writeGIF.$O $(XPM_OBJ) $(TIFF_OBJ) $(SGI_OBJ) \
	$(JPEG_OBJ) $(PNG_OBJ) libpnmrw.$O 

HDRS = libpnmrw.h rwTable.h
MISC = Imakefile

NormalLibraryTarget(rw, $(OBJS))

makelist:
	sh -c 'for i in '"$(TEXT) $(SRCS) $(MISC) $(HDRS)"' ; do \
		echo $(CURRENT_DIR)/$$i >> ../filelist ; done '

rwTable.$O: ../Local.config
----------------------------



	b) creating an executable: ComplexProgramTarget(xart)

------------------------------------
#include "./version"
#include "./Local.config"

DEFINES = $(ARCH_DEFINES) $(EXTRA_DEFINES) $(XPM_INCLUDE) \
	  -DXPAINT_VERSION=\"$(VERSION)\"

# Nothing to change below here
##     unless you've added a file, like e.g. a brush bitmap

XPSRC = [...]
[...]
SRCS = $(XPSRC) $(OPSRC) $(XPWIDSRC)
OBJS = $(XPOBJ) $(OPOBJ) $(XPWIDOBJ)

HDRS =	[...]
[...]
SYS_LIBRARIES = XawClientLibs -lm

#ifdef SGIArchitecture
SGI_LIB = -limage
#endif

DEPLIBS = always xart.man xart.ad
LOCAL_LIBRARIES = LibraryTargetName(rw/librw.a) $(XPM_LIB) $(TIFF_LIB) $(SGI_LIB) $(JPEG_LIB) $(PNG_LIB)

SUBDIRS = rw

ComplexProgramTarget(xart)
InstallAppDefaults(XArt)

NamedMakeSubdirs(always, $(SUBDIRS))
MakefileSubdirs($(SUBDIRS) bitmaps Doc)
CleanSubdirs($(SUBDIRS))

# Other targets...

clean::
	rm -f xart.ad.h DefaultRC.txt.h Help.txt.h PGP.*  xart.man xart.ad

includes:: xart.ad.h DefaultRC.txt.h Help.txt.h

xart.man:	xart.man.in version
	sed -e 'sáXPAINT_VERSIONá$(VERSION)á' < xart.man.in > $@

Colormap.$O: ColormapP.h Colormap.h
[...]
makelist:: 
	-$(RM) filelist
	@touch filelist

makelist:: 
	sh -c 'for i in '"$(TEXT) $(SRCS) $(MISC) $(HDRS)"' ; \
	do echo $(CURRENT_DIR)/$$i >> $(TOP)/filelist ; done '

NamedTargetSubdirs(makelist, $(SUBDIRS) bitmaps Doc, , , makelist)


kit: makelist
	sh -c 'sum="`cat filelist`" ; makekit -oMANIFEST MANIFEST $$sum'

tar: makelist
	sh -c 'cd .. ; rm -f xpaint-$(VERSION).tar.gz; \
	tar czf xpaint-$(VERSION).tar.gz \
	`sed -e "s:^\./::" -e "s:^:xpaint/:" xpaint/filelist`'

TAGS:	$(SRCS) $(HDRS) $(RWSRC)
	etags -t -o ./TAGS $(XPSRC) $(OPSRC) $(XPWIDSRC) $(RWSRC) $(HDRS)

certification:	makelist
	-$(RM) $(CERTIFICATION)	
	certify `cat filelist`
----------------------------------------



	c) Some maybe useful (or useless) defines:

You may want to add parts of it to your Imakefile (or Local.config, etc.) in case of
problems. Use comments, else you'll forget about these hackish def's!! 

Beware: Redefines of functions are debugging headaches: The actual code won't 
	be explicitly in the sources; you will forget, that you redef'd!
	Awful coding style!!


#ifdef OS2Architecture
XCOMM XCOMM #define StrcasecmpDefines -DNEED_STRCASECMP -Dstrcasecmp=stricmp\
XCOMM XCOMM  -Dstrncasecmp=strnicmp -Dstrcmp=stricmp
XCOMM XCOMM #include 


/* OS/2 does not have everything */
XCOMM XCOMM #define lstat stat
XCOMM XCOMM #define S_ISLNK() false
XCOMM XCOMM #define S_ISBLK() false
XCOMM XCOMM #define symlink() (0)
XCOMM XCOMM #define readlink(s,t,l) (strcpy(t,s),strlen(t))
XCOMM XCOMM /* drive letter support needs major rewriting
XCOMM XCOMM  * #define getcwd _getcwd2
XCOMM XCOMM  * #define chdir _chdir2 */
XCOMM XCOMM #define strcasecmp stricmp
XCOMM XCOMM #define strcmp stricmp

ARCH_DEFINES = -DSTDC_HEADERS=1 -DHAVE_STRING_H=1 -DHAVE_STDLIB_H=1\
 -DHAVE_PARAM_H=1 -DHAVE_MEMORY_H=1 -DHAVE_ALLOCA_H=1 -DHAVE_ALLOCA=1\
 -DHAVE_STRERROR=1 -Dlstat=stat -DS_ISLNK=false -DS_ISBLK=false -Dsymlink()=(0)\
 -Dreadlink(s,t,l)=(strcpy(t,s),strlen(t) -D__STDC__ -Dstrcasecmp=stricmp\
 -Dstrncasecmp=strnicmp
#endif