]> git.saurik.com Git - wxWidgets.git/blobdiff - build/tools/builder.py
Move build tools into the main part of the repository tree
[wxWidgets.git] / build / tools / builder.py
diff --git a/build/tools/builder.py b/build/tools/builder.py
new file mode 100755 (executable)
index 0000000..7c067ae
--- /dev/null
@@ -0,0 +1,235 @@
+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