Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | # __________ __ ___. |
| 3 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | # \/ \/ \/ \/ \/ |
| 8 | # $Id$ |
| 9 | # |
| 10 | # Copyright (c) 2009 Dominik Riebeling |
| 11 | # |
| 12 | # All files in this archive are subject to the GNU General Public License. |
| 13 | # See the file COPYING in the source tree root for full license agreement. |
| 14 | # |
| 15 | # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 16 | # KIND, either express or implied. |
| 17 | # |
| 18 | # |
| 19 | # Automate building releases for deployment. |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 20 | # Run from any folder to build |
| 21 | # - trunk |
| 22 | # - any tag (using the -t option) |
| 23 | # - any local folder (using the -p option) |
| 24 | # Will build a binary archive (tar.bz2 / zip) and source archive. |
| 25 | # The source archive won't be built for local builds. Trunk and |
| 26 | # tag builds will retrieve the sources directly from svn and build |
| 27 | # below the systems temporary folder. |
| 28 | # |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 29 | # If the required Qt installation isn't in PATH use --qmake option. |
| 30 | # Tested on Linux and MinGW / W32 |
| 31 | # |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 32 | # requires pysvn package. |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 33 | # requires upx.exe in PATH on Windows. |
| 34 | # |
| 35 | |
| 36 | import re |
| 37 | import os |
| 38 | import sys |
| 39 | import tarfile |
| 40 | import zipfile |
| 41 | import shutil |
| 42 | import subprocess |
| 43 | import getopt |
Dominik Riebeling | d7b9f99 | 2009-09-20 14:59:29 +0000 | [diff] [blame] | 44 | import time |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 45 | import hashlib |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 46 | import tempfile |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 47 | import string |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 48 | |
Dominik Riebeling | 1121206 | 2009-10-30 21:40:07 +0000 | [diff] [blame] | 49 | # modules that are not part of python itself. |
| 50 | try: |
| 51 | import pysvn |
| 52 | except ImportError: |
| 53 | print "Fatal: This script requires the pysvn package to run." |
| 54 | print " See http://pysvn.tigris.org/." |
| 55 | sys.exit(-5) |
Dominik Riebeling | ee3fc61 | 2010-12-19 20:10:22 +0000 | [diff] [blame] | 56 | cpus = 1 |
| 57 | try: |
| 58 | import multiprocessing |
| 59 | cpus = multiprocessing.cpu_count() |
| 60 | print "Info: %s cores found." % cpus |
| 61 | except ImportError: |
| 62 | print "Warning: multiprocessing module not found. Assuming 1 core." |
Dominik Riebeling | 1121206 | 2009-10-30 21:40:07 +0000 | [diff] [blame] | 63 | |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 64 | # == Global stuff == |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 65 | # DLL files to ignore when searching for required DLL files. |
| 66 | systemdlls = ['advapi32.dll', |
| 67 | 'comdlg32.dll', |
| 68 | 'gdi32.dll', |
| 69 | 'imm32.dll', |
| 70 | 'kernel32.dll', |
| 71 | 'msvcrt.dll', |
| 72 | 'msvcrt.dll', |
| 73 | 'netapi32.dll', |
| 74 | 'ole32.dll', |
| 75 | 'oleaut32.dll', |
| 76 | 'setupapi.dll', |
| 77 | 'shell32.dll', |
| 78 | 'user32.dll', |
| 79 | 'winmm.dll', |
| 80 | 'winspool.drv', |
| 81 | 'ws2_32.dll'] |
| 82 | |
| 83 | |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 84 | # == Functions == |
| 85 | def usage(myself): |
| 86 | print "Usage: %s [options]" % myself |
| 87 | print " -q, --qmake=<qmake> path to qmake" |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 88 | print " -p, --project=<pro> path to .pro file for building with local tree" |
| 89 | print " -t, --tag=<tag> use specified tag from svn" |
Dominik Riebeling | d5529ef | 2009-10-04 21:17:59 +0000 | [diff] [blame] | 90 | print " -a, --add=<file> add file to build folder before building" |
Dominik Riebeling | 6b51e5b | 2009-10-05 18:35:28 +0000 | [diff] [blame] | 91 | print " -s, --source-only only create source archive" |
| 92 | print " -b, --binary-only only create binary archive" |
Dominik Riebeling | 93c81dc | 2010-08-08 20:56:58 +0000 | [diff] [blame] | 93 | if nsisscript != "": |
| 94 | print " -n, --makensis=<file> path to makensis for building Windows setup program." |
Dominik Riebeling | 5f7a846 | 2009-11-29 21:09:21 +0000 | [diff] [blame] | 95 | if sys.platform != "darwin": |
| 96 | print " -d, --dynamic link dynamically instead of static" |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 97 | if sys.platform != "win32": |
| 98 | print " -x, --cross= prefix to cross compile for win32" |
Dominik Riebeling | aae2213 | 2010-03-31 20:52:07 +0000 | [diff] [blame] | 99 | print " -k, --keep-temp keep temporary folder on build failure" |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 100 | print " -h, --help this help" |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 101 | print " If neither a project file nor tag is specified trunk will get downloaded" |
| 102 | print " from svn." |
| 103 | |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 104 | |
Dominik Riebeling | e79fca9 | 2011-08-14 18:57:49 +0000 | [diff] [blame] | 105 | def which(executable): |
| 106 | path = os.environ.get("PATH", "").split(os.pathsep) |
| 107 | for p in path: |
| 108 | fullpath = p + "/" + executable |
| 109 | if os.path.exists(fullpath): |
| 110 | return fullpath |
| 111 | print "which: could not find " + executable |
| 112 | return "" |
| 113 | |
| 114 | |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 115 | def getsources(svnsrv, filelist, dest): |
| 116 | '''Get the files listed in filelist from svnsrv and put it at dest.''' |
| 117 | client = pysvn.Client() |
| 118 | print "Checking out sources from %s, please wait." % svnsrv |
| 119 | |
| 120 | for elem in filelist: |
| 121 | url = re.subn('/$', '', svnsrv + elem)[0] |
| 122 | destpath = re.subn('/$', '', dest + elem)[0] |
Dominik Riebeling | 1717217 | 2009-11-20 21:04:23 +0000 | [diff] [blame] | 123 | # make sure the destination path does exist |
| 124 | d = os.path.dirname(destpath) |
Dominik Riebeling | 1717217 | 2009-11-20 21:04:23 +0000 | [diff] [blame] | 125 | if not os.path.exists(d): |
| 126 | os.makedirs(d) |
| 127 | # get from svn |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 128 | try: |
| 129 | client.export(url, destpath) |
| 130 | except: |
| 131 | print "SVN client error: %s" % sys.exc_value |
Dominik Riebeling | 1717217 | 2009-11-20 21:04:23 +0000 | [diff] [blame] | 132 | print "URL: %s, destination: %s" % (url, destpath) |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 133 | return -1 |
| 134 | print "Checkout finished." |
| 135 | return 0 |
| 136 | |
| 137 | |
Dominik Riebeling | 7d4616e | 2011-05-08 19:34:03 +0000 | [diff] [blame] | 138 | def getfolderrev(svnsrv): |
| 139 | '''Get the most recent revision for svnsrv''' |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 140 | client = pysvn.Client() |
| 141 | entries = client.info2(svnsrv, recurse=False) |
| 142 | return entries[0][1].rev.number |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 143 | |
| 144 | |
| 145 | def findversion(versionfile): |
| 146 | '''figure most recent program version from version.h, |
| 147 | returns version string.''' |
| 148 | h = open(versionfile, "r") |
| 149 | c = h.read() |
| 150 | h.close() |
| 151 | r = re.compile("#define +VERSION +\"(.[0-9\.a-z]+)\"") |
| 152 | m = re.search(r, c) |
| 153 | s = re.compile("\$Revision: +([0-9]+)") |
| 154 | n = re.search(s, c) |
| 155 | if n == None: |
| 156 | print "WARNING: Revision not found!" |
| 157 | return m.group(1) |
| 158 | |
| 159 | |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 160 | def findqt(cross=""): |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 161 | '''Search for Qt4 installation. Return path to qmake.''' |
| 162 | print "Searching for Qt" |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 163 | bins = [cross + "qmake", cross + "qmake-qt4"] |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 164 | for binary in bins: |
Dominik Riebeling | 9e25f04 | 2009-10-03 18:16:41 +0000 | [diff] [blame] | 165 | try: |
Dominik Riebeling | e79fca9 | 2011-08-14 18:57:49 +0000 | [diff] [blame] | 166 | q = which(binary) |
Dominik Riebeling | 9e25f04 | 2009-10-03 18:16:41 +0000 | [diff] [blame] | 167 | if len(q) > 0: |
| 168 | result = checkqt(q) |
| 169 | if not result == "": |
| 170 | return result |
| 171 | except: |
| 172 | print sys.exc_value |
| 173 | |
| 174 | return "" |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 175 | |
| 176 | |
Dominik Riebeling | bbe9d32 | 2009-10-03 17:19:07 +0000 | [diff] [blame] | 177 | def checkqt(qmakebin): |
| 178 | '''Check if given path to qmake exists and is a suitable version.''' |
| 179 | result = "" |
| 180 | # check if binary exists |
| 181 | if not os.path.exists(qmakebin): |
| 182 | print "Specified qmake path does not exist!" |
| 183 | return result |
| 184 | # check version |
| 185 | output = subprocess.Popen([qmakebin, "-version"], stdout=subprocess.PIPE, |
| 186 | stderr=subprocess.PIPE) |
| 187 | cmdout = output.communicate() |
| 188 | # don't check the qmake return code here, Qt3 doesn't return 0 on -version. |
| 189 | for ou in cmdout: |
| 190 | r = re.compile("Qt[^0-9]+([0-9\.]+[a-z]*)") |
| 191 | m = re.search(r, ou) |
| 192 | if not m == None: |
| 193 | print "Qt found: %s" % m.group(1) |
| 194 | s = re.compile("4\..*") |
| 195 | n = re.search(s, m.group(1)) |
| 196 | if not n == None: |
| 197 | result = qmakebin |
| 198 | return result |
| 199 | |
| 200 | |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 201 | def qmake(qmake, projfile, platform=sys.platform, wd=".", static=True, cross=""): |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 202 | print "Running qmake in %s..." % wd |
Dominik Riebeling | 6b51e5b | 2009-10-05 18:35:28 +0000 | [diff] [blame] | 203 | command = [qmake, "-config", "release", "-config", "noccache"] |
| 204 | if static == True: |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 205 | command.extend(["-config", "-static"]) |
| 206 | # special spec required? |
| 207 | if len(qmakespec[platform]) > 0: |
| 208 | command.extend(["-spec", qmakespec[platform]]) |
| 209 | # cross compiling prefix set? |
| 210 | if len(cross) > 0: |
| 211 | command.extend(["-config", "cross"]) |
Dominik Riebeling | 6b51e5b | 2009-10-05 18:35:28 +0000 | [diff] [blame] | 212 | command.append(projfile) |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 213 | output = subprocess.Popen(command, stdout=subprocess.PIPE, cwd=wd) |
Dominik Riebeling | bbe9d32 | 2009-10-03 17:19:07 +0000 | [diff] [blame] | 214 | output.communicate() |
| 215 | if not output.returncode == 0: |
| 216 | print "qmake returned an error!" |
| 217 | return -1 |
| 218 | return 0 |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 219 | |
| 220 | |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 221 | def build(wd=".", platform=sys.platform, cross=""): |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 222 | # make |
| 223 | print "Building ..." |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 224 | # use the current platforms make here, cross compiling uses the native make. |
| 225 | command = [make[sys.platform]] |
Dominik Riebeling | ee3fc61 | 2010-12-19 20:10:22 +0000 | [diff] [blame] | 226 | if cpus > 1: |
| 227 | command.append("-j") |
| 228 | command.append(str(cpus)) |
| 229 | output = subprocess.Popen(command, stdout=subprocess.PIPE, cwd=wd) |
Dominik Riebeling | 07e8647 | 2009-10-22 22:02:56 +0000 | [diff] [blame] | 230 | while True: |
| 231 | c = output.stdout.readline() |
| 232 | sys.stdout.write(".") |
| 233 | sys.stdout.flush() |
| 234 | if not output.poll() == None: |
| 235 | sys.stdout.write("\n") |
| 236 | sys.stdout.flush() |
| 237 | if not output.returncode == 0: |
| 238 | print "Build failed!" |
| 239 | return -1 |
| 240 | break |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 241 | if platform != "darwin": |
Dominik Riebeling | 5f7a846 | 2009-11-29 21:09:21 +0000 | [diff] [blame] | 242 | # strip. OS X handles this via macdeployqt. |
| 243 | print "Stripping binary." |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 244 | output = subprocess.Popen([cross + "strip", progexe[platform]], \ |
| 245 | stdout=subprocess.PIPE, cwd=wd) |
Dominik Riebeling | 5f7a846 | 2009-11-29 21:09:21 +0000 | [diff] [blame] | 246 | output.communicate() |
| 247 | if not output.returncode == 0: |
| 248 | print "Stripping failed!" |
| 249 | return -1 |
Dominik Riebeling | bbe9d32 | 2009-10-03 17:19:07 +0000 | [diff] [blame] | 250 | return 0 |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 251 | |
| 252 | |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 253 | def upxfile(wd=".", platform=sys.platform): |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 254 | # run upx on binary |
| 255 | print "UPX'ing binary ..." |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 256 | output = subprocess.Popen(["upx", progexe[platform]], \ |
| 257 | stdout=subprocess.PIPE, cwd=wd) |
Dominik Riebeling | bbe9d32 | 2009-10-03 17:19:07 +0000 | [diff] [blame] | 258 | output.communicate() |
| 259 | if not output.returncode == 0: |
| 260 | print "UPX'ing failed!" |
| 261 | return -1 |
| 262 | return 0 |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 263 | |
| 264 | |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 265 | def runnsis(versionstring, nsis, script, srcfolder): |
Dominik Riebeling | 93c81dc | 2010-08-08 20:56:58 +0000 | [diff] [blame] | 266 | # run script through nsis to create installer. |
| 267 | print "Running NSIS ..." |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 268 | |
Dominik Riebeling | 93c81dc | 2010-08-08 20:56:58 +0000 | [diff] [blame] | 269 | # Assume the generated installer gets placed in the same folder the nsi |
| 270 | # script lives in. This seems to be a valid assumption unless the nsi |
| 271 | # script specifies a path. NSIS expects files relative to source folder so |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 272 | # copy progexe. Additional files are injected into the nsis script. |
| 273 | |
| 274 | # FIXME: instead of copying binaries around copy the NSI file and inject |
| 275 | # the correct paths. |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 276 | # Only win32 supported as target platform so hard coded. |
| 277 | b = srcfolder + "/" + os.path.dirname(script) + "/" \ |
| 278 | + os.path.dirname(progexe["win32"]) |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 279 | if not os.path.exists(b): |
| 280 | os.mkdir(b) |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 281 | shutil.copy(srcfolder + "/" + progexe["win32"], b) |
| 282 | output = subprocess.Popen([nsis, srcfolder + "/" + script], \ |
| 283 | stdout=subprocess.PIPE) |
Dominik Riebeling | 93c81dc | 2010-08-08 20:56:58 +0000 | [diff] [blame] | 284 | output.communicate() |
| 285 | if not output.returncode == 0: |
| 286 | print "NSIS failed!" |
| 287 | return -1 |
| 288 | setupfile = program + "-" + versionstring + "-setup.exe" |
Dominik Riebeling | 77b6825 | 2010-08-09 17:44:03 +0000 | [diff] [blame] | 289 | # find output filename in nsis script file |
| 290 | nsissetup = "" |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 291 | for line in open(srcfolder + "/" + script): |
Dominik Riebeling | 77b6825 | 2010-08-09 17:44:03 +0000 | [diff] [blame] | 292 | if re.match(r'^[^;]*OutFile\s+', line) != None: |
| 293 | nsissetup = re.sub(r'^[^;]*OutFile\s+"(.+)"', r'\1', line).rstrip() |
| 294 | if nsissetup == "": |
| 295 | print "Could not retrieve output file name!" |
| 296 | return -1 |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 297 | shutil.copy(srcfolder + "/" + os.path.dirname(script) + "/" + nsissetup, \ |
| 298 | setupfile) |
Dominik Riebeling | 93c81dc | 2010-08-08 20:56:58 +0000 | [diff] [blame] | 299 | return 0 |
| 300 | |
| 301 | |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 302 | def nsisfileinject(nsis, outscript, filelist): |
| 303 | '''Inject files in filelist into NSIS script file after the File line |
| 304 | containing the main binary. This assumes that the main binary is present |
| 305 | in the NSIS script and that all additiona files (dlls etc) to get placed |
| 306 | into $INSTDIR.''' |
| 307 | output = open(outscript, "w") |
| 308 | for line in open(nsis, "r"): |
| 309 | output.write(line) |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 310 | # inject files after the progexe binary. |
| 311 | # Match the basename only to avoid path mismatches. |
| 312 | if re.match(r'^\s*File\s*.*' + os.path.basename(progexe["win32"]), \ |
| 313 | line, re.IGNORECASE): |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 314 | for f in filelist: |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 315 | injection = " File /oname=$INSTDIR\\" + os.path.basename(f) \ |
| 316 | + " " + os.path.normcase(f) + "\n" |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 317 | output.write(injection) |
| 318 | output.write(" ; end of injected files\n") |
| 319 | output.close() |
| 320 | |
| 321 | |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 322 | def finddlls(program, extrapaths=[], cross=""): |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 323 | '''Check program for required DLLs. Find all required DLLs except ignored |
| 324 | ones and return a list of DLL filenames (including path).''' |
| 325 | # ask objdump about dependencies. |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 326 | output = subprocess.Popen([cross + "objdump", "-x", program], \ |
| 327 | stdout=subprocess.PIPE) |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 328 | cmdout = output.communicate() |
| 329 | |
| 330 | # create list of used DLLs. Store as lower case as W32 is case-insensitive. |
| 331 | dlls = [] |
| 332 | for line in cmdout[0].split('\n'): |
| 333 | if re.match(r'\s*DLL Name', line) != None: |
Dominik Riebeling | 9dfae97 | 2010-09-23 16:47:23 +0000 | [diff] [blame] | 334 | dll = re.sub(r'^\s*DLL Name:\s+([a-zA-Z_\-0-9\.\+]+).*$', r'\1', line) |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 335 | dlls.append(dll.lower()) |
| 336 | |
| 337 | # find DLLs in extrapaths and PATH environment variable. |
| 338 | dllpaths = [] |
| 339 | for file in dlls: |
| 340 | if file in systemdlls: |
Dominik Riebeling | 4cc2cc4 | 2011-03-06 17:37:27 +0000 | [diff] [blame] | 341 | print "System DLL: " + file |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 342 | continue |
| 343 | dllpath = "" |
| 344 | for path in extrapaths: |
| 345 | if os.path.exists(path + "/" + file): |
| 346 | dllpath = re.sub(r"\\", r"/", path + "/" + file) |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 347 | print file + ": found at " + dllpath |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 348 | dllpaths.append(dllpath) |
| 349 | break |
| 350 | if dllpath == "": |
| 351 | try: |
Dominik Riebeling | e79fca9 | 2011-08-14 18:57:49 +0000 | [diff] [blame] | 352 | dllpath = re.sub(r"\\", r"/", which(file)) |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 353 | print file + ": found at " + dllpath |
| 354 | dllpaths.append(dllpath) |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 355 | except: |
Dominik Riebeling | 4cc2cc4 | 2011-03-06 17:37:27 +0000 | [diff] [blame] | 356 | print "MISSING DLL: " + file |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 357 | return dllpaths |
| 358 | |
| 359 | |
Dominik Riebeling | 4cc2cc4 | 2011-03-06 17:37:27 +0000 | [diff] [blame] | 360 | def zipball(programfiles, versionstring, buildfolder, platform=sys.platform): |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 361 | '''package created binary''' |
| 362 | print "Creating binary zipball." |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 363 | archivebase = program + "-" + versionstring |
| 364 | outfolder = buildfolder + "/" + archivebase |
| 365 | archivename = archivebase + ".zip" |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 366 | # create output folder |
| 367 | os.mkdir(outfolder) |
| 368 | # move program files to output folder |
| 369 | for f in programfiles: |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 370 | if re.match(r'^(/|[a-zA-Z]:)', f) != None: |
| 371 | shutil.copy(f, outfolder) |
| 372 | else: |
| 373 | shutil.copy(buildfolder + "/" + f, outfolder) |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 374 | # create zipball from output folder |
| 375 | zf = zipfile.ZipFile(archivename, mode='w', compression=zipfile.ZIP_DEFLATED) |
| 376 | for root, dirs, files in os.walk(outfolder): |
| 377 | for name in files: |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 378 | physname = os.path.normpath(os.path.join(root, name)) |
| 379 | filename = string.replace(physname, os.path.normpath(buildfolder), "") |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 380 | zf.write(physname, filename) |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 381 | for name in dirs: |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 382 | physname = os.path.normpath(os.path.join(root, name)) |
| 383 | filename = string.replace(physname, os.path.normpath(buildfolder), "") |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 384 | zf.write(physname, filename) |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 385 | zf.close() |
| 386 | # remove output folder |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 387 | shutil.rmtree(outfolder) |
Dominik Riebeling | bbe9d32 | 2009-10-03 17:19:07 +0000 | [diff] [blame] | 388 | return archivename |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 389 | |
| 390 | |
Dominik Riebeling | 4cc2cc4 | 2011-03-06 17:37:27 +0000 | [diff] [blame] | 391 | def tarball(programfiles, versionstring, buildfolder): |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 392 | '''package created binary''' |
| 393 | print "Creating binary tarball." |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 394 | archivebase = program + "-" + versionstring |
| 395 | outfolder = buildfolder + "/" + archivebase |
| 396 | archivename = archivebase + ".tar.bz2" |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 397 | # create output folder |
| 398 | os.mkdir(outfolder) |
| 399 | # move program files to output folder |
| 400 | for f in programfiles: |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 401 | shutil.copy(buildfolder + "/" + f, outfolder) |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 402 | # create tarball from output folder |
| 403 | tf = tarfile.open(archivename, mode='w:bz2') |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 404 | tf.add(outfolder, archivebase) |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 405 | tf.close() |
| 406 | # remove output folder |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 407 | shutil.rmtree(outfolder) |
Dominik Riebeling | bbe9d32 | 2009-10-03 17:19:07 +0000 | [diff] [blame] | 408 | return archivename |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 409 | |
| 410 | |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 411 | def macdeploy(versionstring, buildfolder, platform=sys.platform): |
Dominik Riebeling | 5f7a846 | 2009-11-29 21:09:21 +0000 | [diff] [blame] | 412 | '''package created binary to dmg''' |
| 413 | dmgfile = program + "-" + versionstring + ".dmg" |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 414 | appbundle = buildfolder + "/" + progexe[platform] |
Dominik Riebeling | 5f7a846 | 2009-11-29 21:09:21 +0000 | [diff] [blame] | 415 | |
Dominik Riebeling | a6df932 | 2010-07-10 21:22:22 +0000 | [diff] [blame] | 416 | # workaround to Qt issues when building out-of-tree. Copy files into bundle. |
Dominik Riebeling | 85f8406 | 2010-07-28 21:05:16 +0000 | [diff] [blame] | 417 | sourcebase = buildfolder + re.sub('[^/]+.pro$', '', project) + "/" |
| 418 | print sourcebase |
Dominik Riebeling | a6df932 | 2010-07-10 21:22:22 +0000 | [diff] [blame] | 419 | for src in bundlecopy: |
Dominik Riebeling | 85f8406 | 2010-07-28 21:05:16 +0000 | [diff] [blame] | 420 | shutil.copy(sourcebase + src, appbundle + "/" + bundlecopy[src]) |
Dominik Riebeling | 5f7a846 | 2009-11-29 21:09:21 +0000 | [diff] [blame] | 421 | # end of Qt workaround |
| 422 | |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 423 | output = subprocess.Popen(["macdeployqt", progexe[platform], "-dmg"], \ |
| 424 | stdout=subprocess.PIPE, cwd=buildfolder) |
Dominik Riebeling | 5f7a846 | 2009-11-29 21:09:21 +0000 | [diff] [blame] | 425 | output.communicate() |
| 426 | if not output.returncode == 0: |
| 427 | print "macdeployqt failed!" |
| 428 | return -1 |
| 429 | # copy dmg to output folder |
| 430 | shutil.copy(buildfolder + "/" + program + ".dmg", dmgfile) |
| 431 | return dmgfile |
| 432 | |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 433 | |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 434 | def filehashes(filename): |
| 435 | '''Calculate md5 and sha1 hashes for a given file.''' |
| 436 | if not os.path.exists(filename): |
| 437 | return ["", ""] |
| 438 | m = hashlib.md5() |
| 439 | s = hashlib.sha1() |
| 440 | f = open(filename, 'rb') |
| 441 | while True: |
| 442 | d = f.read(65536) |
| 443 | if d == "": |
| 444 | break |
| 445 | m.update(d) |
| 446 | s.update(d) |
| 447 | return [m.hexdigest(), s.hexdigest()] |
| 448 | |
| 449 | |
| 450 | def filestats(filename): |
| 451 | if not os.path.exists(filename): |
| 452 | return |
| 453 | st = os.stat(filename) |
| 454 | print filename, "\n", "-" * len(filename) |
| 455 | print "Size: %i bytes" % st.st_size |
| 456 | h = filehashes(filename) |
| 457 | print "md5sum: %s" % h[0] |
| 458 | print "sha1sum: %s" % h[1] |
| 459 | print "-" * len(filename), "\n" |
| 460 | |
| 461 | |
Dominik Riebeling | aae2213 | 2010-03-31 20:52:07 +0000 | [diff] [blame] | 462 | def tempclean(workfolder, nopro): |
| 463 | if nopro == True: |
| 464 | print "Cleaning up working folder %s" % workfolder |
| 465 | shutil.rmtree(workfolder) |
| 466 | else: |
| 467 | print "Project file specified or cleanup disabled!" |
| 468 | print "Temporary files kept at %s" % workfolder |
| 469 | |
| 470 | |
Dominik Riebeling | a9acd1f | 2010-07-28 18:37:12 +0000 | [diff] [blame] | 471 | def deploy(): |
Dominik Riebeling | d7b9f99 | 2009-09-20 14:59:29 +0000 | [diff] [blame] | 472 | startup = time.time() |
Dominik Riebeling | a9acd1f | 2010-07-28 18:37:12 +0000 | [diff] [blame] | 473 | |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 474 | try: |
Dominik Riebeling | 6ba552c | 2011-05-05 17:19:00 +0000 | [diff] [blame] | 475 | opts, args = getopt.getopt(sys.argv[1:], "q:p:t:a:n:sbdkx:i:h", |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 476 | ["qmake=", "project=", "tag=", "add=", "makensis=", "source-only", |
Dominik Riebeling | 6ba552c | 2011-05-05 17:19:00 +0000 | [diff] [blame] | 477 | "binary-only", "dynamic", "keep-temp", "cross=", "buildid=", "help"]) |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 478 | except getopt.GetoptError, err: |
| 479 | print str(err) |
| 480 | usage(sys.argv[0]) |
| 481 | sys.exit(1) |
| 482 | qt = "" |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 483 | proj = "" |
| 484 | svnbase = svnserver + "trunk/" |
| 485 | tag = "" |
Dominik Riebeling | d5529ef | 2009-10-04 21:17:59 +0000 | [diff] [blame] | 486 | addfiles = [] |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 487 | cleanup = True |
Dominik Riebeling | 6b51e5b | 2009-10-05 18:35:28 +0000 | [diff] [blame] | 488 | binary = True |
| 489 | source = True |
Dominik Riebeling | aae2213 | 2010-03-31 20:52:07 +0000 | [diff] [blame] | 490 | keeptemp = False |
Dominik Riebeling | 93c81dc | 2010-08-08 20:56:58 +0000 | [diff] [blame] | 491 | makensis = "" |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 492 | cross = "" |
Dominik Riebeling | 6ba552c | 2011-05-05 17:19:00 +0000 | [diff] [blame] | 493 | buildid = None |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 494 | platform = sys.platform |
Dominik Riebeling | 5f7a846 | 2009-11-29 21:09:21 +0000 | [diff] [blame] | 495 | if sys.platform != "darwin": |
| 496 | static = True |
| 497 | else: |
| 498 | static = False |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 499 | for o, a in opts: |
| 500 | if o in ("-q", "--qmake"): |
| 501 | qt = a |
Dominik Riebeling | 2b05ef7 | 2009-10-03 20:42:02 +0000 | [diff] [blame] | 502 | if o in ("-p", "--project"): |
| 503 | proj = a |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 504 | cleanup = False |
| 505 | if o in ("-t", "--tag"): |
| 506 | tag = a |
| 507 | svnbase = svnserver + "tags/" + tag + "/" |
Dominik Riebeling | d5529ef | 2009-10-04 21:17:59 +0000 | [diff] [blame] | 508 | if o in ("-a", "--add"): |
| 509 | addfiles.append(a) |
Dominik Riebeling | 93c81dc | 2010-08-08 20:56:58 +0000 | [diff] [blame] | 510 | if o in ("-n", "--makensis"): |
| 511 | makensis = a |
Dominik Riebeling | 6b51e5b | 2009-10-05 18:35:28 +0000 | [diff] [blame] | 512 | if o in ("-s", "--source-only"): |
| 513 | binary = False |
| 514 | if o in ("-b", "--binary-only"): |
| 515 | source = False |
Dominik Riebeling | 5f7a846 | 2009-11-29 21:09:21 +0000 | [diff] [blame] | 516 | if o in ("-d", "--dynamic") and sys.platform != "darwin": |
Dominik Riebeling | 6b51e5b | 2009-10-05 18:35:28 +0000 | [diff] [blame] | 517 | static = False |
Dominik Riebeling | aae2213 | 2010-03-31 20:52:07 +0000 | [diff] [blame] | 518 | if o in ("-k", "--keep-temp"): |
| 519 | keeptemp = True |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 520 | if o in ("-x", "--cross") and sys.platform != "win32": |
| 521 | cross = a |
| 522 | platform = "win32" |
Dominik Riebeling | 6ba552c | 2011-05-05 17:19:00 +0000 | [diff] [blame] | 523 | if o in ("-i", "--buildid"): |
| 524 | buildid = a |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 525 | if o in ("-h", "--help"): |
| 526 | usage(sys.argv[0]) |
| 527 | sys.exit(0) |
| 528 | |
Dominik Riebeling | 6b51e5b | 2009-10-05 18:35:28 +0000 | [diff] [blame] | 529 | if source == False and binary == False: |
| 530 | print "Building build neither source nor binary means nothing to do. Exiting." |
| 531 | sys.exit(1) |
| 532 | |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 533 | print "Building " + progexe[platform] + " for " + platform |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 534 | # search for qmake |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 535 | if qt == "": |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 536 | qm = findqt(cross) |
Dominik Riebeling | bbe9d32 | 2009-10-03 17:19:07 +0000 | [diff] [blame] | 537 | else: |
| 538 | qm = checkqt(qt) |
| 539 | if qm == "": |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 540 | print "ERROR: No suitable Qt installation found." |
Dominik Riebeling | bbe9d32 | 2009-10-03 17:19:07 +0000 | [diff] [blame] | 541 | sys.exit(1) |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 542 | |
| 543 | # create working folder. Use current directory if -p option used. |
| 544 | if proj == "": |
| 545 | w = tempfile.mkdtemp() |
| 546 | # make sure the path doesn't contain backslashes to prevent issues |
| 547 | # later when running on windows. |
| 548 | workfolder = re.sub(r'\\', '/', w) |
Dominik Riebeling | 7d4616e | 2011-05-08 19:34:03 +0000 | [diff] [blame] | 549 | revision = getfolderrev(svnbase) |
Dominik Riebeling | 6ba552c | 2011-05-05 17:19:00 +0000 | [diff] [blame] | 550 | if buildid == None: |
| 551 | versionextra = "" |
| 552 | else: |
| 553 | versionextra = "-" + buildid |
Dominik Riebeling | 7d4616e | 2011-05-08 19:34:03 +0000 | [diff] [blame] | 554 | if tag != "": |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 555 | sourcefolder = workfolder + "/" + tag + "/" |
Dominik Riebeling | 6ba552c | 2011-05-05 17:19:00 +0000 | [diff] [blame] | 556 | archivename = tag + versionextra + "-src.tar.bz2" |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 557 | # get numeric version part from tag |
| 558 | ver = "v" + re.sub('^[^\d]+', '', tag) |
| 559 | else: |
Dominik Riebeling | 7d4616e | 2011-05-08 19:34:03 +0000 | [diff] [blame] | 560 | sourcefolder = workfolder + "/" + program + "-r" + str(revision) + versionextra + "/" |
| 561 | archivename = program + "-r" + str(revision) + versionextra + "-src.tar.bz2" |
| 562 | ver = "r" + str(revision) |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 563 | os.mkdir(sourcefolder) |
| 564 | else: |
| 565 | workfolder = "." |
| 566 | sourcefolder = "." |
| 567 | archivename = "" |
| 568 | # check if project file explicitly given. If yes, don't get sources from svn |
| 569 | if proj == "": |
| 570 | proj = sourcefolder + project |
| 571 | # get sources and pack source tarball |
| 572 | if not getsources(svnbase, svnpaths, sourcefolder) == 0: |
Dominik Riebeling | aae2213 | 2010-03-31 20:52:07 +0000 | [diff] [blame] | 573 | tempclean(workfolder, cleanup and not keeptemp) |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 574 | sys.exit(1) |
| 575 | |
Dominik Riebeling | 6ba552c | 2011-05-05 17:19:00 +0000 | [diff] [blame] | 576 | # replace version strings. |
| 577 | print "Updating version information in sources" |
| 578 | for f in regreplace: |
| 579 | infile = open(sourcefolder + "/" + f, "r") |
| 580 | incontents = infile.readlines() |
| 581 | infile.close() |
Dominik Riebeling | 2c29776 | 2011-04-06 20:17:29 +0000 | [diff] [blame] | 582 | |
Dominik Riebeling | 6ba552c | 2011-05-05 17:19:00 +0000 | [diff] [blame] | 583 | outfile = open(sourcefolder + "/" + f, "w") |
| 584 | for line in incontents: |
| 585 | newline = line |
| 586 | for r in regreplace[f]: |
Dominik Riebeling | 2c29776 | 2011-04-06 20:17:29 +0000 | [diff] [blame] | 587 | # replacements made on the replacement string: |
| 588 | # %REVISION% is replaced with the revision number |
Dominik Riebeling | 7d4616e | 2011-05-08 19:34:03 +0000 | [diff] [blame] | 589 | replacement = re.sub("%REVISION%", str(revision), r[1]) |
Dominik Riebeling | 6ba552c | 2011-05-05 17:19:00 +0000 | [diff] [blame] | 590 | # %BUILD% is replace with buildid as passed on the command line |
| 591 | if buildid != None: |
| 592 | replacement = re.sub("%BUILDID%", str(buildid), replacement) |
Dominik Riebeling | 7d4616e | 2011-05-08 19:34:03 +0000 | [diff] [blame] | 593 | newline = re.sub(r[0], replacement, newline) |
Dominik Riebeling | 6ba552c | 2011-05-05 17:19:00 +0000 | [diff] [blame] | 594 | outfile.write(newline) |
| 595 | outfile.close() |
Dominik Riebeling | 2c29776 | 2011-04-06 20:17:29 +0000 | [diff] [blame] | 596 | |
Dominik Riebeling | 6b51e5b | 2009-10-05 18:35:28 +0000 | [diff] [blame] | 597 | if source == True: |
Dominik Riebeling | 6ba552c | 2011-05-05 17:19:00 +0000 | [diff] [blame] | 598 | print "Creating source tarball %s\n" % archivename |
Dominik Riebeling | 6b51e5b | 2009-10-05 18:35:28 +0000 | [diff] [blame] | 599 | tf = tarfile.open(archivename, mode='w:bz2') |
| 600 | tf.add(sourcefolder, os.path.basename(re.subn('/$', '', sourcefolder)[0])) |
| 601 | tf.close() |
| 602 | if binary == False: |
| 603 | shutil.rmtree(workfolder) |
| 604 | sys.exit(0) |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 605 | else: |
| 606 | # figure version from sources. Need to take path to project file into account. |
| 607 | versionfile = re.subn('[\w\.]+$', "version.h", proj)[0] |
| 608 | ver = findversion(versionfile) |
Dominik Riebeling | 6ba552c | 2011-05-05 17:19:00 +0000 | [diff] [blame] | 609 | # append buildid if any. |
| 610 | if buildid != None: |
| 611 | ver += "-" + buildid |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 612 | |
Dominik Riebeling | 2b05ef7 | 2009-10-03 20:42:02 +0000 | [diff] [blame] | 613 | # check project file |
| 614 | if not os.path.exists(proj): |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 615 | print "ERROR: path to project file wrong." |
Dominik Riebeling | 2b05ef7 | 2009-10-03 20:42:02 +0000 | [diff] [blame] | 616 | sys.exit(1) |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 617 | |
Dominik Riebeling | d5529ef | 2009-10-04 21:17:59 +0000 | [diff] [blame] | 618 | # copy specified (--add) files to working folder |
| 619 | for f in addfiles: |
| 620 | shutil.copy(f, sourcefolder) |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 621 | buildstart = time.time() |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 622 | header = "Building %s %s" % (program, ver) |
| 623 | print header |
| 624 | print len(header) * "=" |
| 625 | |
| 626 | # build it. |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 627 | if not qmake(qm, proj, platform, sourcefolder, static, cross) == 0: |
Dominik Riebeling | aae2213 | 2010-03-31 20:52:07 +0000 | [diff] [blame] | 628 | tempclean(workfolder, cleanup and not keeptemp) |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 629 | sys.exit(1) |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 630 | if not build(sourcefolder, platform, cross) == 0: |
Dominik Riebeling | aae2213 | 2010-03-31 20:52:07 +0000 | [diff] [blame] | 631 | tempclean(workfolder, cleanup and not keeptemp) |
Dominik Riebeling | bbe9d32 | 2009-10-03 17:19:07 +0000 | [diff] [blame] | 632 | sys.exit(1) |
Dominik Riebeling | 93c81dc | 2010-08-08 20:56:58 +0000 | [diff] [blame] | 633 | buildtime = time.time() - buildstart |
Dominik Riebeling | 4cc2cc4 | 2011-03-06 17:37:27 +0000 | [diff] [blame] | 634 | progfiles = programfiles |
| 635 | progfiles.append(progexe[platform]) |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 636 | if platform == "win32": |
Dominik Riebeling | 1727c99 | 2010-06-11 20:02:59 +0000 | [diff] [blame] | 637 | if useupx == True: |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 638 | if not upxfile(sourcefolder, platform) == 0: |
Dominik Riebeling | 1727c99 | 2010-06-11 20:02:59 +0000 | [diff] [blame] | 639 | tempclean(workfolder, cleanup and not keeptemp) |
| 640 | sys.exit(1) |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 641 | dllfiles = finddlls(sourcefolder + "/" + progexe[platform], \ |
| 642 | [os.path.dirname(qm)], cross) |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 643 | if dllfiles.count > 0: |
Dominik Riebeling | 4cc2cc4 | 2011-03-06 17:37:27 +0000 | [diff] [blame] | 644 | progfiles.extend(dllfiles) |
| 645 | archive = zipball(progfiles, ver, sourcefolder, platform) |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 646 | # only when running native right now. |
| 647 | if nsisscript != "" and makensis != "": |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 648 | nsisfileinject(sourcefolder + "/" + nsisscript, sourcefolder \ |
| 649 | + "/" + nsisscript + ".tmp", dllfiles) |
Dominik Riebeling | 4756a77 | 2010-08-30 17:51:53 +0000 | [diff] [blame] | 650 | runnsis(ver, makensis, nsisscript + ".tmp", sourcefolder) |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 651 | elif platform == "darwin": |
| 652 | archive = macdeploy(ver, sourcefolder, platform) |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 653 | else: |
Dominik Riebeling | 168eba1 | 2010-06-23 20:15:14 +0000 | [diff] [blame] | 654 | if os.uname()[4].endswith("64"): |
| 655 | ver += "-64bit" |
Dominik Riebeling | 4cc2cc4 | 2011-03-06 17:37:27 +0000 | [diff] [blame] | 656 | archive = tarball(progfiles, ver, sourcefolder) |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 657 | |
| 658 | # remove temporary files |
Dominik Riebeling | aae2213 | 2010-03-31 20:52:07 +0000 | [diff] [blame] | 659 | tempclean(workfolder, cleanup) |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 660 | |
| 661 | # display summary |
| 662 | headline = "Build Summary for %s" % program |
| 663 | print "\n", headline, "\n", "=" * len(headline) |
| 664 | if not archivename == "": |
| 665 | filestats(archivename) |
| 666 | filestats(archive) |
Dominik Riebeling | d7b9f99 | 2009-09-20 14:59:29 +0000 | [diff] [blame] | 667 | duration = time.time() - startup |
| 668 | durmins = (int)(duration / 60) |
Dominik Riebeling | bbe9d32 | 2009-10-03 17:19:07 +0000 | [diff] [blame] | 669 | dursecs = (int)(duration % 60) |
Dominik Riebeling | 93c81dc | 2010-08-08 20:56:58 +0000 | [diff] [blame] | 670 | buildmins = (int)(buildtime / 60) |
| 671 | buildsecs = (int)(buildtime % 60) |
Dominik Riebeling | 45c411e | 2009-10-04 16:45:59 +0000 | [diff] [blame] | 672 | print "Overall time %smin %ssec, building took %smin %ssec." % \ |
| 673 | (durmins, dursecs, buildmins, buildsecs) |
Dominik Riebeling | efb9343 | 2009-06-18 22:17:17 +0000 | [diff] [blame] | 674 | |
| 675 | |
| 676 | if __name__ == "__main__": |
Dominik Riebeling | 43a40ca | 2011-03-06 00:04:26 +0000 | [diff] [blame] | 677 | print "You cannot run this module directly!" |
| 678 | print "Set required environment and call deploy()." |