HOWTOlabs Linux
Code Development

unless otherwise noted the following material has been gleaned from the use of redhat 5.X/6.0 Linux distributions

Contents
More on Linux

Miscellanious Links

Stripping Line Feeds
Linefeeds are bad in Unix. Just say no to linefeeds :-)
Seriously, the only solution is to remove the linefeeds. The easy way to do this is:
tr -d "\015" < original > tmp.f
mv tmp.f original

So maybe you have a shell command called rmlf [file] that will strip LF's from a single file. Maybe you'd like a whole source tree to be cleaned in a single command. Here's a hint ...
find . -name "*.h" -exec echo "echo filename: {}" \;


make - getting stderr to dump to a file
Make follows conventions and writes its errors to standard error output which is different from the standard output. Using `bash' or `sh' the way to re-direct standard error to a file is:
make 2>error.out
If you want to re-direct standard error to standard out, so that the errors are intermingled with the output, the command is:
make 2>&1
This is all documented in the man page for `sh', just type:
man sh
thanks to Don at Intel for this elucidation


Mixing C and C++
If a C++ file is to call a function in a C file, there is a good chance the hidden function name mangling most compilers use with C++ will get it wrong and cause a link error.

The work around is to make sure the C++ file uses prototypes with the magical extern "C" keyword. For instance ...

extern "C" char *foo(char *a, int b);

Now this work around needs a bit more finesse to keep classic C compilers from choking. Most C++ compilers #define __cplusplus only when compiling a C++ file. To keep your prototypes C compatible try something like this ...

#ifdef __cplusplus
extern "C" {
#endif
void func1(typea a, typeb b);
void func2(typea a, typeb b);
...
void funcN(typea a, typeb b);
#ifdef __cplusplus
}
#endif


Sample makefile I
Say you have an application that has a couple source files in the default directory, but would also like to compile in some shared source files from other directories and have all the object files created during compiling sent to a common objects directory. Let's just say I found this to be non-trivial to write a makefile for. So here is a sample makefile that should do the trick ...
# testapp makefile
#
# common files
#  |-include
#  |  |-base
#  |  |-graphics
#  |  `-io
#  |-src
#  |  |-base
#  |  |-gfx
#  |  `-io
#  `-apps
#    `-testapp
#       `-objects

TARGET = testapp

CPP = g++
CPP_PROJ = -c -gstabs+
INCLUDE = -I../../include -I../../include/base -I../../include/graphics -I../../include/io
LDFLAGS =
LIBS = -lMesaGL -lMesaGLU -L/usr/X11R6/lib -lX11 -lXext -lXmu -lXt -lXi -lSM -lICE -lm

OBJDIR = objects

OBJS_IO = \
        $(OBJDIR)/io1.o \
        $(OBJDIR)/io2.o \
        $(OBJDIR)/io3.o

OBJS_GFX= \
        $(OBJDIR)/gfx1.o \
        $(OBJDIR)/gfx2.o

OBJS_BASE= \
        $(OBJDIR)/base1.o \
        $(OBJDIR)/base2.o \
        $(OBJDIR)/base3.o \
        $(OBJDIR)/base4.o

$(TARGET): $(OBJDIR)/$(TARGET).o $(OBJS_BASE) $(OBJS_IO) $(OBJS_GFX)
        $(CPP) -gstabs+ -o $@ $< $(OBJS_BASE) $(OBJS_IO) $(OBJS_GFX) $(LIBS)

$(OBJS_BASE): $(wildcard ../../src/base/*.cpp)
        $(CPP) $(CPP_PROJ) $(INCLUDE) -o $@ ../../src/base/$(*F).cpp

$(OBJS_IO): $(wildcard ../../src/io/*.cpp)
        $(CPP) $(CPP_PROJ) $(INCLUDE) -o $@ ../../irc/io/$(*F).cpp

$(OBJS_GFX): $(wildcard ../../src/gfx/*.cpp)
        $(CPP) $(CPP_PROJ) $(INCLUDE) -o $@ ../../src/gfx/$(*F).cpp

$(OBJDIR)/$(TARGET).o: $(TARGET).cpp
        $(CPP) $(CPP_PROJ) $(INCLUDE) -o $@ $<

clean:
        rm -f $(OBJDIR)/*.o
	rm -f $(TARGET)
  

Sample Makefile II
# ismogl*.a - DISM OpenGL static library
# changes:
#   Jan 11, 2000 - replaced ismwinapp.o with x11app.o

TARGET =         ismogld.a
INC_CORE =       ../../inc
DIR_CORE =       ../../ismsrc/core
DIR_OGL =        ../../ismsrc/ogl
DIR_PLUGINS =    ../../ismsrc/plugins
OBJDIR =         objects
LIBDIR =         ../../libs/linux

CPP = g++
CPP_PROJ = -c -gstabs+ -DFREDWINOFF -DDISMBAD_BYPASS_OFF -DX11_LINUX
#CXXFLAGS =  -D_DEBUG -DISM_NOTHREAD -DISM_NOTEX -DISM_OGL
CXXFLAGS =  -D_DEBUG -DISM_NOTHREAD -DISM_OGL
INCLUDE = -I$(INC_CORE) -I$(INC_CORE)/plugins -I$(INC_CORE)/ogl

OBJS_OGL = \
        $(OBJDIR)/appgl.o \
        $(OBJDIR)/surfgl.o \
        $(OBJDIR)/lightgl.o \
        $(OBJDIR)/meshgl.o \
        $(OBJDIR)/glprim.o \
        $(OBJDIR)/imagegl.o \
        $(OBJDIR)/newscene.o \
        $(OBJDIR)/camgl.o

OBJS_PLUGINS = \
        $(OBJDIR)/bb.o \
        $(OBJDIR)/imageswitch.o \
        $(OBJDIR)/keyframe.o \
        $(OBJDIR)/lod.o \
        $(OBJDIR)/pathplay.o \
        $(OBJDIR)/portal.o \
        $(OBJDIR)/room.o \
        $(OBJDIR)/roomgroup.o \
        $(OBJDIR)/sprite.o \
        $(OBJDIR)/switch.o \
        $(OBJDIR)/switcher.o \
        $(OBJDIR)/texswitcher.o \
        $(OBJDIR)/wall.o \
        $(OBJDIR)/xformer.o

OBJS_CORE = \
        $(OBJDIR)/appearbase.o \
        $(OBJDIR)/array.o \
        $(OBJDIR)/box.o \
        $(OBJDIR)/cam.o \
        $(OBJDIR)/engine.o \
        $(OBJDIR)/fog.o \
        $(OBJDIR)/geodraw.o \
        $(OBJDIR)/geonorm.o \
        $(OBJDIR)/geoutil.o \
        $(OBJDIR)/geomesh.o \
        $(OBJDIR)/group.o \
        $(OBJDIR)/image.o \
        $(OBJDIR)/ismapp.o \
        $(OBJDIR)/ismpool.o \
        $(OBJDIR)/ismbufpool.o \
        $(OBJDIR)/ismprim.o \
        $(OBJDIR)/x11app.o \
        $(OBJDIR)/light.o \
        $(OBJDIR)/lightdev.o \
        $(OBJDIR)/loadq.o \
        $(OBJDIR)/mat.o \
        $(OBJDIR)/cmatrix.o \
        $(OBJDIR)/model.o \
        $(OBJDIR)/multitex.o \
        $(OBJDIR)/obj.o \
        $(OBJDIR)/quat.o \
        $(OBJDIR)/scene.o \
        $(OBJDIR)/scenethread.o \
        $(OBJDIR)/shape.o \
        $(OBJDIR)/sphere3.o \
        $(OBJDIR)/memstream.o \
        $(OBJDIR)/stream.o \
        $(OBJDIR)/string.o \
        $(OBJDIR)/surf.o \
        $(OBJDIR)/trimesh.o \
        $(OBJDIR)/vtxaos.o \
        $(OBJDIR)/vtxbase.o


# collect all the object files into a library archive
$(LIBDIR)/$(TARGET): $(LIBDIR) $(OBJDIR) $(OBJS_CORE) $(OBJS_PLUGINS) $(OBJS_OGL)
        ar -rs $@ $(OBJS_CORE) $(OBJS_PLUGINS) $(OBJS_OGL)

# compile DISM OpenGL files
$(OBJDIR)/%.o: $(DIR_OGL)/%.cpp
        $(CPP) $(CPP_PROJ) $(CXXFLAGS) $(INCLUDE) -o $@ $<

# compile DISM plugin files
$(OBJDIR)/%.o: $(DIR_PLUGINS)/%.cpp
        $(CPP) $(CPP_PROJ) $(CXXFLAGS) $(INCLUDE) -o $@ $<

# compile the core DISM common files
$(OBJDIR)/%.o: $(DIR_CORE)/%.cpp
        $(CPP) $(CPP_PROJ) $(CXXFLAGS) $(INCLUDE) -o $@ $<

#$(OBJDIR)/%.o: %.cpp
#       $(CPP) $(CPP_PROJ) $(CXXFLAGS) $(INCLUDE) -o $@ $<

$(OBJDIR)/%.o: %.c
        $(CPP) $(CPP_PROJ) $(CXXFLAGS) $(INCLUDE) -o $@ $<


$(LIBDIR):
        @mkdir -p $(LIBDIR)

$(OBJDIR):
        @mkdir -p $(OBJDIR)

clean:
        rm -fR $(OBJDIR)
        rm -f *.o
        rm -f $(LIBDIR)/$(TARGET)

ogl:
        rm -fR $(OBJS_OGL)


Building Shared Libraries

ELF shared libraries

To build libfoo.so as a shared library, the basic steps look like this: 
   $ gcc -fPIC -c *.c
   $ gcc -shared -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0 *.o
   $ ln -s libfoo.so.1.0 libfoo.so.1
   $ ln -s libfoo.so.1 libfoo.so
   $ LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH ; export LD_LIBRARY_PATH

This will generate a shared library called libfoo.so.1.0, and the
appropriate links for ld (libfoo.so) and the dynamic loader
(libfoo.so.1) to find it. To test, we add the current directory to
LD_LIBRARY_PATH 

tip thanks to Richard Schaal - Intel


Gnu Debugger
Make sure the -gstabs+ option is enabled for both compile and link commands. After compile use the gdb command thusly:
gdb [executable file]


Setup for OpenGL & Motif/Lesstif Development
tested with RedHat 6.1

Get Mesa3.1
  make linux ...
  cp *.so ...
  ld config
offset will run
  cp -R include/GL /usr/include
offset will build
  cp -R widgets-mesa/include/GL /usr/include

Get GLUT 3.6
  build *.so
  cp *.so ...
  ldconfig
glpng/test will run
  cp include/glut.h
glpng/test will build

Get Lesstf-0.89.9
  cd lib
  make ...
  cp *.so
  ldconfig
glw & molview will run
  cp include/Xm
glw & molview will build

Note: may need to replace references of ...
  GLwMDrawA.h -> GLwDrawA.h
  glwMDrawingAreaWidgetClass -> glwDrawingAreaWidgetClass


GBM Library
This is a nice library that can be used to read all those nasty proprietary image formats that are not covered by more standardzed image libraies for PNG or JPEG . Precompiled binaries for Linux available online seem to have hard coded reference to mysterious foreign libraries. The source is also available onlin, but compiling it for Linux will generate a gbm.a library with mysterious referecnes to tell and spr_rhdr that wil prevent it from linking with application code.

Its times like this that you need the time tested tool: a distgusting hack.
Get the source code

The Linux makefile should already be in the main directory.  To be
sure though
    cp unix/* .

edit gbm.c

find the text that looks like this ...
	iax_qft, iax_rhdr, iax_rpal, iax_rdata, iax_w, iax_err,
	xbm_qft, xbm_rhdr, xbm_rpal, xbm_rdata, xbm_w, xbm_err,
/*	spr_qft, spr_rhdr, spr_rpal, spr_rdata, spr_w, spr_err,  */
	psg_qft, psg_rhdr, psg_rpal, psg_rdata, psg_w, psg_err,
	gem_qft, gem_rhdr, gem_rpal, gem_rdata, gem_w, gem_err,
... and insure a comment is made as shown.

now edit makefile

locate the first reference to gbmspr.o delete it

now make should build a gbm.a and the other command line utilities
without complaint.  I suspect that some sprite file format support
is gutted by this hack.  Hopefully a better online binary and source will
make this hack obsolete.


Renaming mixed case filenames to contain only lowercase
At some point you may run into a situation where an application that runs both on MS Windows and Linux needs to read the same files. The following are a script and source for making a new command, mlv, that can be used to rename filenames so that they only use lowercase characters. Here is a script that uses the mlv command to generate an appropriate mv command.
$ cat makelc
# renaming $1 with all lowercase
mlv $1 > $1.junk
chmod 700 ./$1.junk
./$1.junk
rm -f ./$1.junk

$ ls Test
test1.BMP  test2.BMP  test3.BMP  

$find -name "*.BMP" -exec ./makelc {} \;
mv ./Test/test3.BMP ./Test/test3.bmp
mv ./Test/test2.BMP ./Test/test2.bmp
mv ./Test/test1.BMP ./Test/test1.bmp

Here's the source code for mlv. Once the mlv executable is created, placing it in /usr/local/bin makes it easy to run from anywhere.
/*  mlv - generate script output to rename mixed case filenames to all lowercase
/*
/*  $ cc mlv.c -o mlv
/*
/*  Note: filenames that include whitespace will freak
*/

int main(int argc, char *argv[]) {
	int i, j, k;

	if (argc < 2) {
		printf("echo mlv [file to rename in all lowercase]\n");
		return;
		}
	printf("mv ");
	printf("%s", argv[1]);
	k = strlen(argv[1]);
	i = 0;
	for (j = 0; j < k; j++) {
		if (argv[1][j] == '/')
			i++;
		}
	for (j = 0; j < k; j++) {
		if (argv[1][j] == '/')
			i--;
		if (i == 0)
			argv[1][j] = tolower(argv[1][j]);
			/* replace with isupper() if uppercase is what you want  */
		}
	printf(" %s\n", argv[1]);
	}


boot: 'nosmp' will force multi-CPU system to use single CPU kernal