#! /usr/bin/env python
# 
# $Id: statisize.py,v 4.0 2003/04/28 14:40:07 hut66au Exp $
#
# This file takes a linking command line as input (as in c++ -o imview etc),
# finds out all the -L library dependencies and uses static library whereever
# possible, by creating a subdirectory `static' with links to the .a files, then changes
# the compilation line by replacing the -lsomething with static/libsomething.a
#
# This is the only portable way I've found to make an executable as static as possible.
# On some machines (notably DECs and Suns) creating a pure static executable is impossible 
# as some .a are missing. 
#

import os, errno, sys, string

# set to one if you need debug messages
debug = 0
# list of libraries to exclude from this process
excludelib = ["c", "m", "X11", "Xext", "pthread", "socket", "nsl", "dpstk", "dps", "Xt", "SM", "ICE", "dl", "mp"]
includepath = ["/usr/lib"]
atend = [] # for silent libraries that need to be appended

# returns a copy of the input list with items unique
def uniq(strlist):
    strlist.sort()
    cpl = strlist[:] # make a copy
    l = len(strlist)
    for item in range(l-1):
        index = l - item -1
        if (strlist[index] == strlist[index-1]):
            cpl.pop(index) # remove from the end
    return cpl

# process arguments for this script
def processOwnArgs(arglist):
    global debug
    while arglist[0][0] == "-":
        if debug:
            print "argument ", arglist[arg][1:]
        if arglist[0][1:] == "debug":
            debug = 1
            arglist.pop(0) # get rid of this argument
        if arglist[0][1:] == "append":
            if debug:
                print "Will append ", arglist[1], " at the end of compilation stanza"
            atend.append(arglist[1])
            arglist.pop(0) # get rid of two arguments
            arglist.pop(0)
        if arglist[0][1:] == "-": # end of arguments
            arglist.pop(0)
            break;
        

# main part of the script

words = sys.argv[1:]
processOwnArgs(words)
nbwords = len(words)

if debug:
    print "*** Debug information"

# finds the -Lsomething
libpath = []
for row in range(nbwords):
    if words[row][0:2] == "-L":
        libpath.append(words[row][2:])

# append the automatically included libs
libpath = libpath + includepath
if debug:
    print "Lib path: ", libpath

# finds the -lsomething
libraries = []
for row in range(nbwords):
    if words[row][0:2] == "-l":
        libraries.append(words[row][2:])


# print out the somethings
libpath = uniq(libpath)
if debug:
    print "Libpath =", libpath
libraries = uniq(libraries)
if debug:
    print "Libraries =", libraries




# walk the library tree, creates symbolic links, remember them
assoc = {}
for lib in libraries:
    for dir in libpath:
        if (excludelib.count(lib) != 0):
            if debug:
                print "Excluding ", lib
            break;
        libname = "lib" + lib + ".a"
        pathlib = dir + "/" + libname
        if os.access(pathlib, os.R_OK) == 1:
            if debug:
                print "Found static version of ", lib, " as: ", pathlib
            assoc[lib] = pathlib
            break

if debug:
    print assoc

# now re-creates a compilation line with -l changed to direct library calls
# change the -l<lib> into blabla/lib<lib>.a
for index in (range(nbwords)):
    if words[index][0:2] == "-l":
        try:
            remainder = words[index][2:]
            words[index] = assoc[remainder]
        except KeyError:
            if debug:
                print "library ", remainder, " was unchanged"

# print the new command
cmd = ""
for index in (range(nbwords)):
    cmd = cmd + words[index] + " "
# add the extra stuff
for stuff in atend:
    cmd = cmd + stuff + " "
    words.append(stuff)

if debug:
    print "Words contains: ", words
    print "*** End of debug information"
    
print cmd

# execute it
os.execvp(words[0], words)
