import sys import os.path from PackageUtils import PackageUtils from Logger import Logger from ToolChainUtils import ToolChainUtils from CommandUtils import CommandUtils from constants import constants from SpecData import SPECS from StringUtils import StringUtils from Sandbox import Chroot, Container class PackageBuilder(object): def __init__(self, mapPackageToCycles, sandboxType): # will be initialized in buildPackageFunction() self.logName = None self.logPath = None self.logger = None self.package = None self.version = None self.doneList = None self.sandboxType = sandboxType self.sandbox = None self.mapPackageToCycles = mapPackageToCycles self.listNodepsPackages = ["glibc", "gmp", "zlib", "file", "binutils", "mpfr", "mpc", "gcc", "ncurses", "util-linux", "groff", "perl", "texinfo", "rpm", "openssl", "go"] def build(self, pkg, doneList): packageName, packageVersion = StringUtils.splitPackageNameAndVersion(pkg) #do not build if RPM is already built #test only if the package is in the testForceRPMS with rpmCheck #build only if the package is not in the testForceRPMS with rpmCheck if not (constants.rpmCheck or packageName in constants.testForceRPMS): if self._checkIfPackageIsAlreadyBuilt(packageName, packageVersion, doneList): return self._buildPackagePrepareFunction(packageName, packageVersion, doneList) try: self._buildPackage() except Exception as e: # TODO: self.logger might be None self.logger.exception(e) raise e def _buildPackage(self): try: self.sandbox.create(self.package + "-" + self.version) tUtils = ToolChainUtils(self.logName, self.logPath) if self.sandbox.hasToolchain(): tUtils.installExtraToolchainRPMS(self.sandbox, self.package, self.version) else: tUtils.installToolchainRPMS(self.sandbox, self.package, self.version, availablePackages=self.doneList) listDependentPackages, listTestPackages, listInstalledPackages, listInstalledRPMs = ( self._findDependentPackagesAndInstalledRPM(self.sandbox)) pkgUtils = PackageUtils(self.logName, self.logPath) if listDependentPackages: self.logger.debug("Installing the build time dependent packages......") for pkg in listDependentPackages: packageName, packageVersion = StringUtils.splitPackageNameAndVersion(pkg) self._installPackage(pkgUtils, packageName, packageVersion, self.sandbox, self.logPath,listInstalledPackages, listInstalledRPMs) for pkg in listTestPackages: flag = False packageName, packageVersion = StringUtils.splitPackageNameAndVersion(pkg) for depPkg in listDependentPackages: depPackageName, depPackageVersion = StringUtils.splitPackageNameAndVersion(depPkg) if depPackageName == packageName: flag = True break; if flag == False: self._installPackage(pkgUtils, packageName,packageVersion, self.sandbox, self.logPath,listInstalledPackages, listInstalledRPMs) pkgUtils.installRPMSInOneShot(self.sandbox) self.logger.debug("Finished installing the build time dependent packages....") pkgUtils.adjustGCCSpecs(self.sandbox, self.package, self.version) pkgUtils.buildRPMSForGivenPackage(self.sandbox, self.package, self.version, self.logPath) self.logger.debug("Successfully built the package: " + self.package) except Exception as e: self.logger.error("Failed while building package: " + self.package) self.logger.debug("Sandbox: " + self.sandbox.getID() + " not deleted for debugging.") logFileName = os.path.join(self.logPath, self.package + ".log") fileLog = os.popen('tail -n 100 ' + logFileName).read() self.logger.info(fileLog) raise e if self.sandbox: self.sandbox.destroy() def _buildPackagePrepareFunction(self, package, version, doneList): self.package = package self.version = version self.logName = "build-" + package + "-" + version self.logPath = constants.logPath + "/" + package + "-" + version if not os.path.isdir(self.logPath): cmdUtils = CommandUtils() cmdUtils.runCommandInShell("mkdir -p " + self.logPath) self.logger = Logger.getLogger(self.logName, self.logPath, constants.logLevel) self.doneList = doneList if self.sandboxType == "chroot": sandbox = Chroot(self.logger) elif self.sandboxType == "container": sandbox = Container(self.logger) else: raise Exception("Unknown sandbox type: " + sandboxType) self.sandbox = sandbox def _findPackageNameAndVersionFromRPMFile(self, rpmfile): rpmfile = os.path.basename(rpmfile) releaseindex = rpmfile.rfind("-") if releaseindex == -1: self.logger.error("Invalid rpm file:" + rpmfile) return None pkg = rpmfile[0:releaseindex] return pkg def _findInstalledPackages(self, sandbox): pkgUtils = PackageUtils(self.logName, self.logPath) listInstalledRPMs = pkgUtils.findInstalledRPMPackages(sandbox) listInstalledPackages = [] for installedRPM in listInstalledRPMs: pkg = self._findPackageNameAndVersionFromRPMFile(installedRPM) if pkg is not None: listInstalledPackages.append(pkg) return listInstalledPackages, listInstalledRPMs def _checkIfPackageIsAlreadyBuilt(self, package, version, doneList): basePkg = SPECS.getData().getSpecName(package) + "-" + version return basePkg in doneList def _findRunTimeRequiredRPMPackages(self, rpmPackage, version): return SPECS.getData().getRequiresForPackage(rpmPackage, version) def _findBuildTimeRequiredPackages(self): return SPECS.getData().getBuildRequiresForPackage(self.package, self.version) def _findBuildTimeCheckRequiredPackages(self): return SPECS.getData().getCheckBuildRequiresForPackage(self.package, self.version) def _installPackage(self, pkgUtils, package, packageVersion, sandbox, destLogPath, listInstalledPackages, listInstalledRPMs): rpmfile = pkgUtils.findRPMFile(package,packageVersion); if rpmfile is None: self.logger.error("No rpm file found for package: " + package + "-" + packageVersion) raise Exception("Missing rpm file") specificRPM = os.path.basename(rpmfile.replace(".rpm", "")) pkg = package+"-"+packageVersion if pkg in listInstalledPackages: return # mark it as installed - to avoid cyclic recursion listInstalledPackages.append(pkg) listInstalledRPMs.append(specificRPM) self._installDependentRunTimePackages(pkgUtils, package, packageVersion, sandbox, destLogPath, listInstalledPackages, listInstalledRPMs) noDeps = False if (package in self.mapPackageToCycles or package in self.listNodepsPackages or package in constants.noDepsPackageList): noDeps = True pkgUtils.prepRPMforInstall(package,packageVersion, noDeps, destLogPath) def _installDependentRunTimePackages(self, pkgUtils, package, packageVersion, sandbox, destLogPath, listInstalledPackages, listInstalledRPMs): listRunTimeDependentPackages = self._findRunTimeRequiredRPMPackages(package, packageVersion) if listRunTimeDependentPackages: for pkg in listRunTimeDependentPackages: if pkg in self.mapPackageToCycles: continue packageName, packageVersion = StringUtils.splitPackageNameAndVersion(pkg) rpmfile = pkgUtils.findRPMFile(packageName, packageVersion) if rpmfile is None: self.logger.error("No rpm file found for package: " + packageName + "-" + packageVersion) raise Exception("Missing rpm file") latestPkgRPM = os.path.basename(rpmfile).replace(".rpm", "") if pkg in listInstalledPackages and latestPkgRPM in listInstalledRPMs: continue self._installPackage(pkgUtils, packageName,packageVersion, sandbox, destLogPath,listInstalledPackages, listInstalledRPMs) def _findDependentPackagesAndInstalledRPM(self, sandbox): listInstalledPackages, listInstalledRPMs = self._findInstalledPackages(sandbox) self.logger.debug(listInstalledPackages) listDependentPackages = self._findBuildTimeRequiredPackages() listTestPackages=[] if constants.rpmCheck and self.package in constants.testForceRPMS: # One time optimization if constants.listMakeCheckRPMPkgWithVersionstoInstall is None: constants.listMakeCheckRPMPkgWithVersionstoInstall=[] for package in constants.listMakeCheckRPMPkgtoInstall: version = SPECS.getData().getHighestVersion(package) constants.listMakeCheckRPMPkgWithVersionstoInstall.append(package+"-"+version) listDependentPackages.extend(self._findBuildTimeCheckRequiredPackages()) testPackages = (set(constants.listMakeCheckRPMPkgWithVersionstoInstall) - set(listInstalledPackages) - set([self.package+"-"+self.version])) listTestPackages=list(set(testPackages)) listDependentPackages = list(set(listDependentPackages)) return listDependentPackages, listTestPackages, listInstalledPackages, listInstalledRPMs