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