wxWidgets/build/tools/builder.py
2010-06-25 20:53:39 +00:00

236 lines
6.8 KiB
Python
Executable File

import os
import string
import subprocess
import sys
import time
class BuildError(Exception):
def __init__(self, value):
self.value = value
def __repr__(self):
return repr(self.value)
def runInDir(command, dir=None, verbose=True):
if dir:
olddir = os.getcwd()
os.chdir(dir)
commandStr = " ".join(command)
if verbose:
print commandStr
result = os.system(commandStr)
if dir:
os.chdir(olddir)
return result
class Builder:
"""
Base class exposing the Builder interface.
"""
def __init__(self, formatName="", commandName="", programDir=None):
"""
formatName = human readable name for project format (should correspond with Bakefile names)
commandName = name of command line program used to invoke builder
programDir = directory program is located in, if not on the path
"""
self.dir = dir
self.name = commandName
self.formatName = formatName
self.programDir = programDir
self.doSetup()
def doSetup(self):
"""
Do anything special needed to configure the environment to build with this builder.
"""
pass
def isAvailable(self):
"""
Run sanity checks before attempting to build with this format
"""
# Make sure the builder program exists
programPath = self.getProgramPath()
if os.path.exists(programPath):
return True
else:
# check the PATH for the program
# TODO: How do we check if we're in Cygwin?
if sys.platform.startswith("win"):
result = os.system(self.name)
if result == 0:
return True
dirs = os.environ["PATH"].split(":")
for dir in dirs:
if os.path.isfile(os.path.join(dir, self.name)):
return True
else:
result = os.system("which %s" % self.name)
if result == 0:
return True
return False
def getProgramPath(self):
if self.programDir:
path = os.path.join(self.programDir, self.name)
if sys.platform.startswith("win"):
path = '"%s"' % path
return path
return self.name
def clean(self, dir=None, projectFile=None):
"""
dir = the directory containing the project file
projectFile = Some formats need to explicitly specify the project file's name
"""
args = [self.getProgramPath(), "clean"]
if dir:
args.append(dir)
if self.isAvailable():
result = runInDir(args)
return result
return False
def configure(self, options=None):
# if we don't have configure, just report success
return True
def build(self, dir=None, projectFile=None, targets=None, options=None):
if self.isAvailable():
if options:
optionList = list(options)
else:
optionList = []
optionList.insert(0, self.getProgramPath())
result = runInDir(optionList, dir)
return result
return 1
def install(self, dir=None, options=None):
if self.isAvailable():
args = ["make", "install"]
if options:
args.extend(options)
result = runInDir(args, dir)
return result
return 1
# Concrete subclasses of abstract Builder interface
class GNUMakeBuilder(Builder):
def __init__(self, commandName="make", formatName="GNUMake"):
Builder.__init__(self, commandName=commandName, formatName=formatName)
class XCodeBuilder(Builder):
def __init__(self, commandName="xcodebuild", formatName="XCode"):
Builder.__init__(self, commandName=commandName, formatName=formatName)
class AutoconfBuilder(GNUMakeBuilder):
def __init__(self, formatName="autoconf"):
GNUMakeBuilder.__init__(self, formatName=formatName)
def configure(self, dir=None, options=None):
#olddir = os.getcwd()
#os.chdir(dir)
configdir = dir
if not dir:
configdir = os.getcwd()
configure_cmd = ""
while os.path.exists(configdir):
config_cmd = os.path.join(configdir, "configure")
if not os.path.exists(config_cmd):
parentdir = os.path.abspath(os.path.join(configdir, ".."))
if configdir == parentdir:
break
configdir = parentdir
else:
configure_cmd = config_cmd
break
if not configure_cmd:
sys.stderr.write("Could not find configure script at %r. Have you run autoconf?\n" % dir)
return 1
optionsStr = string.join(options, " ") if options else ""
command = "%s %s" % (configure_cmd, optionsStr)
print command
result = os.system(command)
#os.chdir(olddir)
return result
class MSVCBuilder(Builder):
def __init__(self):
Builder.__init__(self, commandName="nmake.exe", formatName="msvc")
def isAvailable(self):
PATH = os.environ['PATH'].split(os.path.pathsep)
for p in PATH:
if os.path.exists(os.path.join(p, self.name)):
return True
return False
class MSVCProjectBuilder(Builder):
def __init__(self):
Builder.__init__(self, commandName="VCExpress.exe", formatName="msvcProject")
for key in ["VS90COMNTOOLS", "VC80COMNTOOLS", "VC71COMNTOOLS"]:
if os.environ.has_key(key):
self.prgoramDir = os.path.join(os.environ[key], "..", "IDE")
if self.programDir == None:
for version in ["9.0", "8", ".NET 2003"]:
msvcDir = "C:\\Program Files\\Microsoft Visual Studio %s\\Common7\\IDE" % version
if os.path.exists(msvcDir):
self.programDir = msvcDir
def isAvailable(self):
if self.programDir:
path = os.path.join(self.programDir, self.name)
if os.path.exists(path):
return True
else:
# I don't have commercial versions of MSVC so I can't test this
name = "devenv.com"
path = os.path.join(self.programDir, name)
if os.path.exists(path):
self.name = "devenv.com"
return True
return False
builders = [GNUMakeBuilder, XCodeBuilder, AutoconfBuilder, MSVCBuilder, MSVCProjectBuilder]
def getAvailableBuilders():
availableBuilders = {}
for symbol in builders:
thisBuilder = symbol()
if thisBuilder.isAvailable():
availableBuilders[thisBuilder.formatName] = symbol
return availableBuilders