1#!/usr/bin/python 2# 3# Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR> 4# 5# This program and the accompanying materials 6# are licensed and made available under the terms and conditions of the BSD License 7# which accompanies this distribution. The full text of the license may be found at 8# http://opensource.org/licenses/bsd-license.php 9# 10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12# 13 14import os 15import re 16import StringIO 17import subprocess 18import sys 19import zipfile 20 21is_unix = not sys.platform.startswith('win') 22 23if not is_unix: 24 print "This script currently only supports unix-like systems" 25 sys.exit(-1) 26 27if os.path.exists('OvmfPkgX64.dsc'): 28 os.chdir('..') 29 30if not os.path.exists(os.path.join('OvmfPkg', 'OvmfPkgX64.dsc')): 31 print "OvmfPkg/OvmfPkgX64.dsc doesn't exist" 32 sys.exit(-1) 33 34def run_and_capture_output(args, checkExitCode = True): 35 p = subprocess.Popen(args=args, stdout=subprocess.PIPE) 36 stdout = p.stdout.read() 37 ret_code = p.wait() 38 if checkExitCode: 39 assert ret_code == 0 40 return stdout 41 42gcc_version = run_and_capture_output(args=('gcc', '--version')) 43gcc_re = re.compile(r'\s*\S+\s+\([^\)]+?\)\s+(\d+(?:\.\d+)*)(?:\s+.*)?') 44mo = gcc_re.match(gcc_version) 45if not mo: 46 print "Unable to find GCC version" 47 sys.exit(-1) 48gcc_version = map(lambda n: int(n), mo.group(1).split('.')) 49 50if 'TOOLCHAIN' in os.environ: 51 TOOLCHAIN = os.environ['TOOLCHAIN'] 52else: 53 assert(gcc_version[0] == 4) 54 minor = max(4, min(7, gcc_version[1])) 55 TOOLCHAIN = 'GCC4' + str(minor) 56 57def git_based_version(): 58 dir = os.getcwd() 59 if not os.path.exists('.git'): 60 os.chdir('OvmfPkg') 61 stdout = run_and_capture_output(args=('git', 'log', 62 '-n', '1', 63 '--abbrev-commit')) 64 regex = re.compile(r'^\s*git-svn-id:\s+\S+@(\d+)\s+[0-9a-f\-]+$', 65 re.MULTILINE) 66 mo = regex.search(stdout) 67 if mo: 68 version = 'r' + mo.group(1) 69 else: 70 version = stdout.split(None, 3)[1] 71 os.chdir(dir) 72 return version 73 74def svn_info(): 75 dir = os.getcwd() 76 os.chdir('OvmfPkg') 77 stdout = run_and_capture_output(args=('svn', 'info')) 78 os.chdir(dir) 79 return stdout 80 81def svn_based_version(): 82 buf = svn_info() 83 revision_re = re.compile('^Revision\:\s*([\da-f]+)$', re.MULTILINE) 84 mo = revision_re.search(buf) 85 assert(mo is not None) 86 return 'r' + mo.group(1) 87 88def get_revision(): 89 if os.path.exists(os.path.join('OvmfPkg', '.svn')): 90 return svn_based_version() 91 else: 92 return git_based_version() 93 94revision = get_revision() 95 96newline_re = re.compile(r'(\n|\r\n|\r(?!\n))', re.MULTILINE) 97def to_dos_text(str): 98 return newline_re.sub('\r\n', str) 99 100def gen_build_info(): 101 distro = run_and_capture_output(args=('lsb_release', '-sd')).strip() 102 103 machine = run_and_capture_output(args=('uname', '-m')).strip() 104 105 gcc_version_str = '.'.join(map(lambda v: str(v), gcc_version)) 106 107 ld_version = run_and_capture_output(args=('ld', '--version')) 108 ld_version = ld_version.split('\n')[0].split()[-1] 109 110 iasl_version = run_and_capture_output(args=('iasl'), checkExitCode=False) 111 iasl_version = filter(lambda s: s.find(' version ') >= 0, iasl_version.split('\n'))[0] 112 iasl_version = iasl_version.split(' version ')[1].strip() 113 114 sb = StringIO.StringIO() 115 print >> sb, 'edk2: ', revision 116 print >> sb, 'compiler: GCC', gcc_version_str, '(' + TOOLCHAIN + ')' 117 print >> sb, 'binutils:', ld_version 118 print >> sb, 'iasl: ', iasl_version 119 print >> sb, 'system: ', distro, machine.replace('_', '-') 120 return to_dos_text(sb.getvalue()) 121 122def read_file(filename): 123 f = open(filename) 124 d = f.read() 125 f.close() 126 return d 127 128LICENSE = to_dos_text( 129'''This OVMF binary release is built from source code licensed under 130the BSD open source license. The BSD license is documented at 131http://opensource.org/licenses/bsd-license.php, and a copy is 132shown below. 133 134One sub-component of the OVMF project is a FAT filesystem driver. The FAT 135filesystem driver code is also BSD licensed, but the code license contains 136one additional term. This license can be found at 137https://github.com/tianocore/tianocore.github.io/wiki/Edk2-fat-driver 138and a copy is shown below (following the normal BSD license). 139 140=== BSD license: START === 141 142''') 143 144LICENSE += read_file(os.path.join('MdePkg', 'License.txt')) 145 146LICENSE += to_dos_text( 147''' 148=== BSD license: END === 149 150=== FAT filesystem driver license: START === 151 152''') 153 154LICENSE += read_file(os.path.join('FatBinPkg', 'License.txt')) 155 156LICENSE += to_dos_text( 157''' 158=== FAT filesystem driver license: END === 159''') 160 161def build(arch): 162 args = ( 163 'OvmfPkg/build.sh', 164 '-t', TOOLCHAIN, 165 '-a', arch, 166 '-b', 'RELEASE' 167 ) 168 logname = 'build-%s.log' % arch 169 build_log = open(logname, 'w') 170 print 'Building OVMF for', arch, '(%s)' % logname, '...', 171 sys.stdout.flush() 172 p = subprocess.Popen(args=args, stdout=build_log, stderr=build_log) 173 ret_code = p.wait() 174 if ret_code == 0: 175 print '[done]' 176 else: 177 print '[error 0x%x]' % ret_code 178 return ret_code 179 180def create_zip(arch): 181 global build_info 182 filename = 'OVMF-%s-%s.zip' % (arch, revision) 183 print 'Creating', filename, '...', 184 sys.stdout.flush() 185 if os.path.exists(filename): 186 os.remove(filename) 187 zipf = zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED) 188 189 zipf.writestr('BUILD_INFO', build_info) 190 zipf.writestr('LICENSE', LICENSE) 191 zipf.write(os.path.join('OvmfPkg', 'README'), 'README') 192 FV_DIR = os.path.join( 193 'Build', 194 'Ovmf' + arch.title(), 195 'RELEASE_' + TOOLCHAIN, 196 'FV' 197 ) 198 zipf.write(os.path.join(FV_DIR, 'OVMF.fd'), 'OVMF.fd') 199 zipf.close() 200 print '[done]' 201 202build_info = gen_build_info() 203build('IA32') 204build('X64') 205create_zip('IA32') 206create_zip('X64') 207 208 209