Home | History | Annotate | Download | only in OvmfPkg
      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 
     14 import os
     15 import re
     16 import StringIO
     17 import subprocess
     18 import sys
     19 import zipfile
     20 
     21 is_unix = not sys.platform.startswith('win')
     22 
     23 if not is_unix:
     24     print "This script currently only supports unix-like systems"
     25     sys.exit(-1)
     26 
     27 if os.path.exists('OvmfPkgX64.dsc'):
     28     os.chdir('..')
     29 
     30 if not os.path.exists(os.path.join('OvmfPkg', 'OvmfPkgX64.dsc')):
     31     print "OvmfPkg/OvmfPkgX64.dsc doesn't exist"
     32     sys.exit(-1)
     33 
     34 def 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 
     42 gcc_version = run_and_capture_output(args=('gcc', '--version'))
     43 gcc_re = re.compile(r'\s*\S+\s+\([^\)]+?\)\s+(\d+(?:\.\d+)*)(?:\s+.*)?')
     44 mo = gcc_re.match(gcc_version)
     45 if not mo:
     46     print "Unable to find GCC version"
     47     sys.exit(-1)
     48 gcc_version = map(lambda n: int(n), mo.group(1).split('.'))
     49 
     50 if 'TOOLCHAIN' in os.environ:
     51     TOOLCHAIN = os.environ['TOOLCHAIN']
     52 else:
     53     assert(gcc_version[0] == 4)
     54     minor = max(4, min(7, gcc_version[1]))
     55     TOOLCHAIN = 'GCC4' + str(minor)
     56 
     57 def 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 
     74 def 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 
     81 def 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 
     88 def 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 
     94 revision = get_revision()
     95 
     96 newline_re = re.compile(r'(\n|\r\n|\r(?!\n))', re.MULTILINE)
     97 def to_dos_text(str):
     98     return newline_re.sub('\r\n', str)
     99 
    100 def 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 
    122 def read_file(filename):
    123     f = open(filename)
    124     d = f.read()
    125     f.close()
    126     return d
    127 
    128 LICENSE = to_dos_text(
    129 '''This OVMF binary release is built from source code licensed under
    130 the BSD open source license.  The BSD license is documented at
    131 http://opensource.org/licenses/bsd-license.php, and a copy is
    132 shown below.
    133 
    134 One sub-component of the OVMF project is a FAT filesystem driver.  The FAT
    135 filesystem driver code is also BSD licensed, but the code license contains
    136 one additional term.  This license can be found at
    137 https://github.com/tianocore/tianocore.github.io/wiki/Edk2-fat-driver
    138 and a copy is shown below (following the normal BSD license).
    139 
    140 === BSD license: START ===
    141 
    142 ''')
    143 
    144 LICENSE += read_file(os.path.join('MdePkg', 'License.txt'))
    145 
    146 LICENSE += to_dos_text(
    147 '''
    148 === BSD license: END ===
    149 
    150 === FAT filesystem driver license: START ===
    151 
    152 ''')
    153 
    154 LICENSE += read_file(os.path.join('FatBinPkg', 'License.txt'))
    155 
    156 LICENSE += to_dos_text(
    157 '''
    158 === FAT filesystem driver license: END ===
    159 ''')
    160 
    161 def 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 
    180 def 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 
    202 build_info = gen_build_info()
    203 build('IA32')
    204 build('X64')
    205 create_zip('IA32')
    206 create_zip('X64')
    207 
    208 
    209