--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/build/buildutils/export.py Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,390 @@
+#
+# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+#
+#! /usr/bin/python
+
+import sys
+import traceback
+import os
+import os.path
+import sys
+#import subprocess
+import shutil
+import re
+import types
+import zipfile
+
+from os.path import abspath
+
+class BuildError(Exception):
+ pass
+
+def main():
+ tmpExtension = ".cpp"
+ try:
+ args = sys.argv[1:]
+
+ # Get macro definitios
+ macros = [a[2:] for a in args if a.startswith("-D")]
+ args = [a for a in args if not a.startswith("-D")]
+
+ opcode = args[0]
+ fileName = args[1]
+
+ exports = readExports(fileName, fileName+tmpExtension, macros)
+ for src, dst in exports:
+ isZipFile = False
+ if src.startswith("___zip___"):
+ isZipFile = True
+ src = src[9:]
+
+ if not os.path.exists(src):
+ print "Exported file "+src+" doesn't exist"
+ else:
+ if opcode.lower() == "clean":
+ if isZipFile:
+ handleZipCommand(src, dst, doClean = True)
+ else:
+ delFile(dst)
+ else:
+ if isZipFile:
+ handleZipCommand(src, dst, doClean = False)
+ else:
+ updateFile(dst, src)
+ except:
+ print "Error during export "
+ traceback.print_exc()
+ sys.exit(-1)
+
+ delFile(fileName+tmpExtension, False)
+
+def readExports(fileName, cppedFile, macros):
+
+ if not os.path.exists(fileName):
+ print "No %s, nothing to export" % fileName
+ return ()
+
+ # Preprocess bld.inf
+
+ args = [
+ '-undef',
+ '-nostdinc']
+
+ if os.name=="nt":
+ args = [
+ '-undef',
+ '-traditional',
+ '-+',
+ '-nostdinc']
+
+ cppFile(
+ fileName,
+ cppedFile,
+ args,
+ macros)
+
+ lines = readFile(cppedFile)
+
+ EXPORTS = {}
+
+ bldInf = {}
+
+ # Keeps track of which inf-file's contents inside the preprocessed
+ # bld.inf-file are being processed
+ infFile = None
+
+ section = None
+
+ # Read in bld.inf contents
+ for line in [l.strip() for l in lines if len(l.strip()) > 0]:
+ if line.startswith("#"):
+ # Comment line indicates which inf-file any subsequent
+ # lines were included from
+
+ # Parse inf-file name
+ infFile = re.search(r'^# \d+ "(.+)"', line).group(1)
+
+ # Translate backslashes to slashes, remove dupes
+ infFile = abspath(re.sub(r"\\+", "/", infFile))
+ elif line.lower().startswith("prj_"):
+ section = line.lower()[4:]
+ else:
+ if not section:
+ raise BuildError, \
+ "Data outside of data section in bld.inf: %s" % line
+
+ # Collect lines by section (prj_exports etc), each entry is a
+ # tuple of the actual data line and the name of the inf-file
+ # where it originated from
+ bldInf.setdefault(
+ section, []).append((line.strip(), infFile))
+
+ # Collect exports to a separate list
+ for export, infFile in bldInf.get("exports", []):
+ isZipFile = False
+ if export.strip().lower().startswith(":zip"):
+ isZipFile = True
+ export = export[5:]
+ try:
+ src, dst = export.split()
+ except:
+ raise BuildError, \
+ 'Malformed line "%s" in %s' % (export, infFile)
+
+ # Map source path through current inf file path
+ if not src.startswith("\\") and not src.startswith("/"):
+ src = os.path.join(os.path.split(infFile)[0], src)
+
+ if dst.startswith("\\") or dst.startswith("/"):
+ # Destination path is absolute, use it as is
+ pass
+ elif dst.startswith("|"):
+ # Destination path is relative to the inf-file it was specified
+ # in
+ dst = os.path.join(os.path.dirname(infFile), dst[1:])
+
+ src, dst = map(abspath, [src, dst])
+ if isZipFile:
+ src = "___zip___"+src
+ EXPORTS[(src, dst)] = None
+
+ return EXPORTS.keys()
+
+def handleZipCommand(zipfl, dirToUnzip, doClean = False):
+ zfobj = zipfile.ZipFile(zipfl)
+ if doClean:
+ print("Deleting files extracted from %s:" % (zipfl))
+ else:
+ print("Extracting files from %s:" % (zipfl))
+ for name in zfobj.namelist():
+ #Not handling cases where zip file contains empty dirs
+ if not name.endswith('/'):
+ print(" " + os.path.join(dirToUnzip,name))
+ destFile = os.path.join(dirToUnzip, name)
+ if doClean:
+ delFile(destFile, doPrint = False)
+ else:
+ makeDirs(destFile, isFile = True)
+ if uptodate(destFile, zipfl):
+ print(" Already extracted...")
+ continue
+ outfile = open(destFile, 'wb')
+ outfile.write(zfobj.read(name))
+ outfile.close()
+
+
+
+def updateFile(dst, src):
+ if not uptodate(dst, src):
+ print("Copying %s to %s" % (src, dst))
+ shutil.copy(src, dst)
+
+def oldestTime(files):
+ oldestTime = None
+ oldestFile = None
+ try:
+ for f in files:
+ fileTime = os.path.getmtime(f)
+ if oldestTime == None or fileTime < oldestTime:
+ oldestTime = fileTime
+ oldestFile = f
+ except:
+ # One or more files don't exist
+ return 0
+
+ #print "oldest file is %s with %d" % (oldestFile, oldestTime)
+ return oldestTime
+
+def newestTime(files):
+ newest = 0
+ newestFile = None
+
+ for f in files:
+ try:
+ fileTime = os.path.getmtime(f)
+ except:
+ print("Expected to find file " + f)
+ else:
+ if fileTime > newest:
+ newestFile = f
+ newest = fileTime
+
+ #print "newest file is %s with %d" % (newestFile, newest)
+ return newest
+
+def uptodate(targets, sources):
+
+ # Make non-list arguments lists
+ if not isinstance(targets, list):
+ targets = [targets]
+ if not isinstance(sources, list):
+ sources = [sources]
+
+ if oldestTime(targets) < newestTime(sources):
+ # One or more target files don't exist or are older than one or
+ # more source files, rebuild is needed
+ result = False
+ else:
+ # Rebuild is not needed
+ result = True
+
+
+ # Create missing directories
+ if result == False:
+ for f in targets:
+ dirName = os.path.dirname(f)
+ if not os.path.exists(dirName):
+ os.makedirs(dirName)
+
+ return result
+
+
+def cppFile(
+ srcFile,
+ dstFile,
+ args,
+ macros = []):
+
+ """ Preprocesses a file with CPP using given arguments.
+
+ By default dstFile is altered only if running CPP would change the file's
+ contents.
+
+ Returns true if dstFile was altered.
+ """
+
+ # Target file doesn't exist or preprocessing was forced
+
+ # Create any missing directories for destination file
+ makeDirs(dstFile, isFile = True)
+
+ for m in macros:
+ if len(m) == 0:
+ raise BuildError, "empty macro definition"
+ if m == "NOKIA_SYMBIAN_BLD":
+ args.extend([
+ "-D__GNUC__=4",
+ "-I " + abspath("\\epoc32\\include\\"),
+ "-imacros " + abspath("\\epoc32\\include\\platform_paths.hrh")])
+
+ cmd = ['cpp'] + \
+ args + \
+ ["-D" + m for m in macros] +\
+ [srcFile, \
+ dstFile]
+
+ print " ".join(cmd)
+
+ execute(cmd, False)
+ return True
+
+
+def makeDirs(directory, isFile = False):
+ """ Creates a directory if it doesn't exist.
+
+ Doesn't do anything if the directory already exists.
+
+ If isFile is True, the last element of the directory path is assumed to be
+ a file and is discarded from the path to be created. """
+
+ if isFile:
+ directory = os.path.dirname(directory)
+
+ try:
+ os.makedirs(directory)
+ except:
+ pass
+
+def readFile(f):
+ """ Reads contents of a file to a list and returns it. """
+
+ f = open(f, 'r')
+ contents = f.readlines()
+ f.close()
+
+ return contents
+
+def delFile(file, doPrint = True):
+ """ Deletes a file.
+
+ Fails if the file appears to be a directory. """
+
+ if os.path.exists(file):
+ if os.path.isfile(file):
+ if doPrint:
+ print("Deleting file " + file)
+ os.remove(file)
+ else:
+ print('Can not delete file "%s", is a directory' % (file))
+
+def execute(
+ cmd,
+ printMsg = True,
+ haltOnError = True,
+ input = None,
+ grabOutput = False,
+ *args,
+ **kwd):
+ """ Executes external command, keeps track of time spent outside.
+
+ Any arguments are passed directly to subprocess.call(). """
+
+
+ if printMsg:
+ # Construct string to be displayed on screen
+ msg = ""
+ if kwd.has_key('cwd'):
+ msg = "[" + kwd['cwd'] + "] "
+ if type(cmd) == types.StringType:
+ msg += cmd
+ elif type(cmd) == types.ListType:
+ msg += " ".join(cmd)
+ else:
+ raise Error, "Invalid type %s for cmd argument" % type(cmd)
+ print msg
+
+ kwd['args'] = cmd
+
+
+ """
+ if input:
+ # Input data for command was specified, pipe it
+ kwd['stdin'] = subprocess.PIPE
+ if grabOutput:
+ # Command output should be grabbed
+ kwd['stdout'] = subprocess.PIPE
+ kwd['stderr'] = subprocess.PIPE
+
+ process = subprocess.Popen(*args, **kwd)
+
+ if input or grabOutput:
+ stdout, stderr = process.communicate(input)
+ else:
+ process.wait()
+
+ result = process.returncode
+ """
+ cmd2 = " ".join(cmd)
+ result = os.system(" ".join(cmd))
+ if not result == 0 and haltOnError == True:
+ print 'Error running external command "' + \
+ (type(cmd) == types.StringType and cmd or ' '.join(cmd)) + \
+ '", return code ' + str(result)
+
+ return result
+
+
+if __name__ == "__main__":
+ main()