| # Copyright Martin J. Bligh, 2006 |
| # |
| # Class for compiling kernels. Data for the object includes the src files |
| # used to create the kernel, patches applied, config (base + changes), |
| # the build directory itself, and logged output |
| # |
| # Methods: |
| # __init__ Initialize kernel object |
| # patch Apply a list of patches (in order) |
| # config Summon a kernel_config object and set it up |
| # build Build the kernel |
| # build_timed Build the kernel, and time it |
| # clean Do a "make clean" |
| # install Do a "make install" |
| # set_cross_cc Set the cross compiler to the h/w platform |
| # pickle_dump Pickle this object, sans job backreference. |
| # |
| # Data: |
| # job Backpointer to the job object we're part of |
| # autodir Path to the top level autotest dir (/usr/local/autotest) |
| # top_dir Path to the top level dir of this kernel object |
| # src_dir <kernel>/src/ |
| # build_dir <kernel>/patches/ |
| # config_dir <kernel>/config |
| # log_dir <kernel>/log |
| |
| import os,os.path,shutil,urllib,copy,pickle |
| from autotest_utils import * |
| import kernel_config |
| import test |
| |
| class kernel: |
| autodir = '' |
| |
| def __init__(self, job, top_directory, base_tree): |
| self.job = job |
| autodir = job.autodir |
| self.top_dir = top_directory |
| if not self.top_dir.startswith(autodir): |
| raise |
| if os.path.isdir(self.top_dir): |
| system('rm -rf ' + self.top_dir) |
| os.mkdir(self.top_dir) |
| |
| self.build_dir = self.top_dir + '/build' |
| # created by get_kernel_tree |
| self.src_dir = self.top_dir + '/src' |
| self.patch_dir = self.top_dir + '/patches' |
| self.config_dir = self.top_dir + '/config' |
| self.log_dir = self.top_dir + '/log' |
| os.mkdir(self.src_dir) |
| os.mkdir(self.patch_dir) |
| os.mkdir(self.config_dir) |
| os.mkdir(self.log_dir) |
| |
| base_tree = kernelexpand(base_tree) |
| self.get_kernel_tree(base_tree) |
| |
| |
| def patch(self, *patches): |
| self.job.stdout.redirect(self.log_dir+'/stdout') |
| local_patches = self.get_patches(patches) |
| self.apply_patches(local_patches) |
| self.job.stdout.restore() |
| |
| |
| def config(self, config_file, config_list = None): |
| self.job.stdout.redirect(self.log_dir+'/stdout') |
| config = kernel_config.kernel_config(self.build_dir, self.config_dir, config_file, config_list) |
| self.job.stdout.restore() |
| |
| |
| def get_patches(self, patches): |
| local_patches = [] |
| for patch in patches: |
| dest = self.patch_dir + basename(patch) |
| get_file(patch, dest) |
| local_patches.append(dest) |
| |
| |
| def apply_patches(self, patches): |
| builddir = self.build_dir |
| os.chdir(builddir) |
| |
| if not patches: |
| return None |
| for patch in patches: |
| local = patch_dir + basename(patch) |
| get_file(patch, local) |
| print 'Patching from', basename(patch), '...' |
| cat_file_to_cmd(patch, 'patch -p1') |
| |
| |
| def get_kernel_tree(self, base_tree): |
| # Extract base_tree into self.top_dir/build |
| os.chdir(self.top_dir) |
| tarball = 'src/' + basename(base_tree) |
| get_file(base_tree, tarball) |
| |
| print 'Extracting kernel tarball:', tarball, '...' |
| extract_tarball_to_dir(tarball, 'build') |
| |
| |
| def build(self, make_opts = ''): |
| # build the kernel |
| os.chdir(self.build_dir) |
| print self.log_dir+'stdout' |
| self.job.stdout.redirect(self.log_dir+'/stdout') |
| self.job.stderr.redirect(self.log_dir+'/stderr') |
| self.set_cross_cc() |
| # setup_config_file(config_file, config_overrides) |
| |
| # Not needed on 2.6, but hard to tell -- handle failure |
| try: |
| system('make dep') |
| except CmdError: |
| pass |
| threads = 2 * count_cpus() |
| system('make -j %d %s %s' % (threads, make_opts, target)) |
| # eg make bzImage, or make zImage |
| if kernel_config.modules_needed('.config'): |
| system('make modules') |
| |
| self.job.stdout.restore() |
| self.job.stderr.restore() |
| |
| |
| def build_timed(self, threads, timefile = '/dev/null', make_opts = ''): |
| os.chdir(self.build_dir) |
| print "make clean" |
| system('make clean') |
| build_string = "/usr/bin/time make %s -j %s vmlinux > /dev/null 2> %s" % (make_opts, threads, timefile) |
| print build_string |
| system(build_string) |
| if (not os.path.isfile('vmlinux')): |
| raise TestError("no vmlinux found, kernel build failed") |
| |
| |
| def clean(self): |
| os.chdir(self.build_dir) |
| print "make clean" |
| system('make clean') |
| |
| |
| def install(self, dir): |
| # install the kernel |
| os.chdir(self.build_dir) |
| image = 'arch/' + get_target_arch() + '/boot/' + target |
| force_copy(image, '/boot/vmlinuz-autotest') |
| force_copy('System.map', '/boot/System.map-autotest') |
| force_copy('.config', '/boot/config-autotest') |
| |
| if kernel_config.modules_needed('.config'): |
| system('make modules_install') |
| |
| |
| def set_cross_cc(self): |
| target_arch = get_target_arch() |
| global target |
| target = 'bzImage' |
| |
| if target_arch == 'ppc64': |
| install_package('ppc64-cross') |
| os.environ['CROSS_COMPILE']=autodir+'sources/ppc64-cross/bin' |
| target = 'zImage' |
| elif target_arch == 'x86_64': |
| install_package('x86_64-cross') |
| os.environ['ARCH']='x86_64' |
| os.environ['CROSS_COMPILE']=autodir+'sources/x86_64-cross/bin' |
| |
| |
| # we can't pickle the backreference to job (it contains fd's), |
| # nor would we want to |
| def pickle_dump(self, filename): |
| temp = copy.copy(self) |
| temp.job = None |
| pickle.dump(temp, open(filename, 'w')) |
| |