def add_support(self, module, path=None, auto=False, appname=None): if not auto: if path: self._epicssupportdict[module] = path else: self._epicssupportdict[module] = \ self.dep.get_install_path(module) return if not utils.in_code_tree(): return if appname is None: appname = self._appname pth = self.dep.get_dep_path(module) dep = Dependency() dep.add_package(module, pth) libs = dep.get_libs(mapped=True) tgt = [] # remove 'module' as the that is added explicitly above for lib, libdir in libs: name = lib # Namespace these so there are no conflicts, # e.g. berkley 'db' and epcis internal 'db' name = 'ASKAPDEP_' + lib # For some reason we have to add the directories to the # RELEASE file and then use the variables? # Explicit paths in the Makefile won't work. if libdir: if lib not in [i[1] for i in self._implicit_deps]: self._epicssupportdict[name] = libdir tgt.append((name, lib, appname)) else: if lib not in [i[1] for i in self._implicit_deps]: tgt.append((name, lib, appname)) self._implicit_deps += tgt
def _doc(self): self._add_slice_options() slicefiles = glob.glob('*.ice') slicefiles = ' '.join(slicefiles) if utils.in_code_tree(): utils.run('%s %s %s' % (self._bcom, self._opts, slicefiles), self.nowarnings)
def _install(self): self._add_ant_options() if not utils.in_code_tree(): self.add_option('-Dprefix=%s' % self._prefix) utils.run("%s %s install" % (self._icom, self._opts), self.nowarnings) if self._run_script: self._create_run_script()
def _test(self): if not utils.in_code_tree(): return if os.path.exists("tests"): self._testtgt("tests") else: print "error: Cannot run tests as the tests subdirectory is missing: %s" % os.path.join(self._bdir, "tests")
def add_support(self, module, path=None, auto=False, appname=None): if not auto: if path: self._epicssupportdict[module] = path else: self._epicssupportdict[module] = \ self.dep.get_install_path(module) return if not utils.in_code_tree(): return if appname is None: appname = self._appname pth = self.dep.get_dep_path(module) dep = Dependency() dep.add_package(module, pth) libs = dep.get_libs(mapped=True) tgt = [] # remove 'module' as the that is added explicitly above for lib, libdir in libs: name = lib # Namespace these so there are no conflicts, # e.g. berkley 'db' and epcis internal 'db' name = 'ASKAPDEP_'+lib # For some reason we have to add the directories to the # RELEASE file and then use the variables? # Explicit paths in the Makefile won't work. if libdir: if lib not in [ i[1] for i in self._implicit_deps ]: self._epicssupportdict[name] = libdir tgt.append((name, lib, appname)) else: if lib not in [ i[1] for i in self._implicit_deps ]: tgt.append((name, lib, appname)) self._implicit_deps += tgt
def _test(self): if not utils.in_code_tree(): return if os.path.exists("tests"): self._testtgt("tests") else: print "error: Cannot run tests as the tests subdirectory is missing: %s" % os.path.join(self._bdir, "tests")
def _doc(self): self._add_slice_options() slicefiles = glob.glob('*.ice') slicefiles = ' '.join(slicefiles) if utils.in_code_tree(): utils.run('%s %s %s' % (self._bcom, self._opts, slicefiles), self.nowarnings)
def _functest(self): if not utils.in_code_tree(): return if os.path.exists("functests"): self._testtgt("functests") else: print "error: missing functests subdirectory in %s" % \ os.path.relpath(self._bdir, self._askaproot)
def _install(self): self._add_ant_options() if not utils.in_code_tree(): self.add_option('-Dprefix=%s' % self._prefix) utils.run("%s %s install" % (self._icom, self._opts), self.nowarnings) if self._run_script: self._create_run_script()
def _functest(self): if not utils.in_code_tree(): return if os.path.exists("functests"): self._testtgt("functests") else: print "error: missing functests subdirectory in %s" % \ os.path.relpath(self._bdir, self._askaproot)
def _add_ant_options(self): if utils.in_code_tree(): self.add_option("-Daskap_version='%s'" % utils.get_release_version()) self.add_option('-Dclasspath=%s' % self.dep.get_classpath()) self.add_option('-Dinstall.dir=%s' % self.installdir) # Add dependencies' directories for ant for kv in self.dep.get_rootdirs(mapped=True): self.add_option('-Ddep_%s=%s' % kv)
def _add_ant_options(self): if utils.in_code_tree(): self.add_option("-Daskap_version='%s'" % utils.get_release_version()) self.add_option('-Dclasspath=%s' % self.dep.get_classpath()) self.add_option('-Dinstall.dir=%s' % self.installdir) # Add dependencies' directories for ant for kv in self.dep.get_rootdirs(mapped=True): self.add_option('-Ddep_%s=%s' % kv)
def _clean(self): if utils.in_code_tree() and os.path.exists('setup.py'): utils.run("python setup.py clean") # Bug #2803 # An ASKAP/EPICS application (pkgname == '.') usually has a configure # directory in the root directory # as opposed to EPICS base and some support modules where the tarball # gets expanded in the pkgname directory. # This feature affects the way the package gets cleaned in order to # support idempotent cleaning command. # In case of ASKAP/EPICS applications, we need to check whether EPICS # base configure directory exists, otherwise # we cannot execute 'make clean' command. If epics base configure # directory exists, a RELEASE.<architecture> file # must exist in the configure directory in order to locate epics base # configure directory for the make command # to work correctly. if self._package == '.': if self._epicsbase_configure_exists(): # RELEASE.<arch> must exists in order to run make clean. # This prevents an error when running clean when the package # has already been cleaned. self._create_releasefile() if not os.path.exists(self._deps_file): open(self._deps_file, 'w').write("") shutil.copy(self._releasefile, os.path.join(self._package, "configure")) if self._oldreleasefile is not None: shutil.copy( self._releasefile, os.path.join(self._package, "configure", self._oldreleasefile)) curdir = os.path.abspath(os.curdir) # Enter the untarred package directory os.chdir(self._package) utils.run("make clean uninstall") os.chdir(curdir) else: utils.q_print( "WARNING: EPICS base configure directory does " "not exists (required by 'make clean'). " "Some temporary files inside the package will not" "be removed. Build EPICS base and re-run clean " "target or delete temporary files manually.") # Execute base class method, which removes install directory and # additional clean targets Builder._clean(self)
def _fetch_remote(self): if utils.in_code_tree(): return if self.remote_archive is None: return uitem = urllib2.urlparse.urlsplit(self.remote_archive) outfile = os.path.split(uitem.path)[-1] if (os.path.isfile(outfile)): return fullpath = self.remote_archive if not uitem.scheme: root = os.environ["RBUILD_REMOTE_ARCHIVE"] fullpath = os.path.sep.join((root, self.remote_archive)) remote = urllib2.urlopen(fullpath) utils.q_print("info: Fetching '{}'...".format(fullpath)) with open(outfile, "wb") as of: of.write(remote.read()) remote.close()
def _clean(self): if utils.in_code_tree() and os.path.exists('setup.py'): utils.run("python setup.py clean") # Bug #2803 # An ASKAP/EPICS application (pkgname == '.') usually has a configure # directory in the root directory # as opposed to EPICS base and some support modules where the tarball # gets expanded in the pkgname directory. # This feature affects the way the package gets cleaned in order to # support idempotent cleaning command. # In case of ASKAP/EPICS applications, we need to check whether EPICS # base configure directory exists, otherwise # we cannot execute 'make clean' command. If epics base configure # directory exists, a RELEASE.<architecture> file # must exist in the configure directory in order to locate epics base # configure directory for the make command # to work correctly. if self._package == '.': if self._epicsbase_configure_exists(): # RELEASE.<arch> must exists in order to run make clean. # This prevents an error when running clean when the package # has already been cleaned. self._create_releasefile() if not os.path.exists(self._deps_file): open(self._deps_file, 'w').write("") shutil.copy(self._releasefile, os.path.join(self._package, "configure")) if self._oldreleasefile is not None: shutil.copy(self._releasefile, os.path.join(self._package, "configure", self._oldreleasefile)) curdir = os.path.abspath(os.curdir) # Enter the untarred package directory os.chdir(self._package) utils.run("make clean uninstall") os.chdir(curdir) else: utils.q_print("WARNING: EPICS base configure directory does not ""exists (required by 'make clean'). Some temporary files inside the package will not be removed. Build EPICS base and re-run clean target or delete temporary files manually.") # Execute base class method, which removes install directory and # additional clean targets Builder._clean(self)
def _clean(self): cpaths = list(self._clean_targets) + \ [self._pkgsig, self._installdir, ".sconsign.dblite"] if os.path.exists(self._infofile): with open(self._infofile, "r") as fh: if fh.readline().find("# Auto-generated by build.py") >= 0: cpaths.append(self._infofile) if not utils.in_code_tree(): cpaths += [self._package] if os.path.exists(self._clean_file): with open(self._clean_file, "r") as fh: for line in fh: cpaths.append(line.strip()) cpaths.append(self._clean_file) for path in cpaths: if os.path.exists(path): utils.rmtree(path) return True
def add_ioc_config(self, envfile=None, hostfile=None, iocname=None): """Add deployment configuration files for tunning the ioc. These are two csv files (<iocname>_env.csv and <iocname>_host.csv) containing individual ioc environment and which IOCs to run on which host. These get installed into install/ioc-config""" if not utils.in_code_tree(): utils.q_print("warn: 'add_ioc_config' only works in Code tree") return if iocname is None: if self._appname.startswith("ioc"): iocname = self._appname else: iocname = "ioc"+self._appname if envfile is None: envfile = os.path.join("files", iocname+"_env.csv") if not os.path.exists(envfile): raise IOError("'%s' doesn't exist" % envfile) if hostfile is None: hostfile = os.path.join("files", iocname+"_host.csv") if not os.path.exists(hostfile): raise IOError("'%s' doesn't exist" % hostfile) self._csv_files.append((envfile, hostfile, iocname))
def add_ioc_config(self, envfile=None, hostfile=None, iocname=None): """Add deployment configuration files for tunning the ioc. These are two csv files (<iocname>_env.csv and <iocname>_host.csv) containing individual ioc environment and which IOCs to run on which host. These get installed into install/ioc-config""" if not utils.in_code_tree(): utils.q_print("warn: 'add_ioc_config' only works in Code tree") return if iocname is None: if self._appname.startswith("ioc"): iocname = self._appname else: iocname = "ioc" + self._appname if envfile is None: envfile = os.path.join("files", iocname + "_env.csv") if not os.path.exists(envfile): raise IOError("'%s' doesn't exist" % envfile) if hostfile is None: hostfile = os.path.join("files", iocname + "_host.csv") if not os.path.exists(hostfile): raise IOError("'%s' doesn't exist" % hostfile) self._csv_files.append((envfile, hostfile, iocname))
def _test(self): self._add_ant_options() if utils.in_code_tree(): utils.run("%s %s test" % (self._icom, self._opts))
def _clean(self): if utils.in_code_tree(): utils.run("%s %s clean" % (self._icom, self._opts)) Builder._clean(self)
def _doc(self): if not utils.in_code_tree() and not utils.in_dev_tree(): return env = self._get_env() cmd = "%s %s setup.py doc" % (env, self._pycmd) utils.run("%s" % cmd, self.nowarnings)
def _doc(self): if utils.in_code_tree() and os.path.exists('setup.py'): env = self._get_env() cmd = "%s python setup.py doc" % (env, ) utils.run("%s" % cmd, self.nowarnings)
def build(self): ''' Run the complete build process. XXX rbuild script only allows single build targets to be specified but 'python build.py <targets>' allows for multiple targets to be specified. ''' # get tar file name in case of a remote archive self._determine_tarfile() if "bclean" in self._comopts: self._build_clean() if "clean" in self._comopts: self._clean() # will remove .packagesig if "depends" in self._comopts: pass # handled by rbuild but for completeness list here. if "install" in self._comopts: if self.is_up_to_date(): return # Run clean before building to get rid of possible old artifacts # in installdir. # The do_clean flag should only be set False for second builders. # In Code just remove the installdir rather than running _clean() # so rebuilds will be fast and handled by underlying build # system e.g. scons if self.do_clean: if utils.in_code_tree(): if os.path.exists(self._installdir): utils.q_print("info: pre-build removal of %s dir." % self._installdir) utils.rmtree(self._installdir) else: utils.q_print("info: pre-build clean.") self._clean() self._get_system_opts() self._fetch_remote() self._unpack() self._copy(self._files, self._package) self._patch() self._replace() self._precommand() os.chdir(self._builddir) self._configure() self._build() self._install() os.chdir(self._bdir) self._copy_to_install() self._lib64_symlink() self._create_info() self._create_init() self._postcommand() self._signature() self._save_clean_targets() if "test" in self._comopts and utils.in_code_tree(): os.chdir(self._package) self._test() os.chdir(self._bdir) if "functest" in self._comopts and utils.in_code_tree(): os.chdir(self._package) self._functest() os.chdir(self._bdir) if "signature" in self._comopts: self._signature() if "stage" in self._comopts: self._stage() if "release" in self._comopts: self._release() if "deploy" in self._comopts: self._deploy() if "format" in self._comopts: if utils.in_code_tree(): utils.format_src_code() else: utils.q_print("warn: format only applies in the Code tree.") if "doc" in self._comopts: os.chdir(self._package) self._doc() os.chdir(self._bdir)
def _doc(self): self._add_ant_options() if utils.in_code_tree(): utils.run("%s %s doc" % (self._icom, self._opts))
def _clean(self): if utils.in_code_tree(): utils.run("%s %s clean" % (self._icom, self._opts)) Builder._clean(self)
def _test(self): self._add_ant_options() if utils.in_code_tree(): utils.run("%s %s test" % (self._icom, self._opts))
def _doc(self): if utils.in_code_tree() and os.path.exists('setup.py'): env = self._get_env() cmd = "%s python setup.py doc" % (env,) utils.run("%s" % cmd, self.nowarnings)
def _doc(self): self._add_ant_options() if utils.in_code_tree(): utils.run("%s %s doc" % (self._icom, self._opts))
def _doc(self): if not utils.in_code_tree() and not utils.in_dev_tree(): return env = self._get_env() cmd = "%s %s setup.py doc" % (env, self._pycmd) utils.run("%s" % cmd, self.nowarnings)
def __init__(self, pkgname=None, archivename=None, extractdir=None, buildsubdir=None, buildcommand=None, buildtargets=[], confcommand=None, installcommand=None, options=sys.argv[1:]): ''' The constructor sets up a package build "environment" :param pkgname: The (optional) name of the package directory. By default the current directory name is used. :param archivename: The (optional) archive name minus suffix. The default is based on package name. :param extractdir: The (optional) directory into which the archive is extracted. It is created if it does not exist. :param buildsubdir: The (optional) directory in which to start the build. :param buildtargets: The (optional) additional build targets. :param buildcommand: The (optional) build command. The default is 'None'. :param installcommand: The (optional) install command. The default is 'None'. :param confcommand: The command to configure the package. the default is 'None'. Otherwise the default is None. :param installcommand: The command to install the package. The default is 'None'. :param options: The default is 'sys.argv[1:]'. ''' self._bdir = os.path.abspath(os.curdir) self._package = pkgname or os.path.basename(self._bdir) self._tarname = None self._archive_name = archivename self._extractdir = extractdir if buildsubdir: self._builddir = os.path.join(self._package, buildsubdir) else: self._builddir = self._package self._bcom = buildcommand self._btargets = buildtargets self._ccom = confcommand self._icom = installcommand self._patches = [] self._replacement_list = [] self._askaproot = os.getenv('ASKAP_ROOT') self._infofile = 'package.info' self._installdir = "install" self._pkgsig = '.packagesig' self._prefix = os.path.join(self._bdir, self._installdir) self.parallel = True # filter out general builder options if "-noparallel" in options: options.remove("-noparallel") self.parallel = False # XXX stage_dir and release name is set in rbuild but define here # to allow for testing using: # python build.py [stage, release] self._releasename = 'release-%s' % utils.get_svn_revision() self._stagedir = os.path.join(self._askaproot, 'tmp', self._releasename) # Iterate backwards because we are changing options list. for i in range(len(options) - 1, -1, -1): if options[i].startswith('stage_dir'): self._stagedir = options[i].split('=')[1] options.pop(i) elif options[i].startswith('release_name'): self._releasename = options[i].split('=')[1] options.pop(i) self.create_signature = True self.version_string = "" self.remote_archive = None if utils.in_code_tree(): self.create_signature = False self.version_string = utils.get_release_version() self._comopts = options self._opts = "" self._precallback = None self._postcallback = None self._files = [] self._install_files = [] self._clean_file = os.path.abspath(".clean_targets") self._clean_targets = self._load_clean_targets() self._buildfile = "build.py" # XXX could be setup.py self.nowarnings = False # enable or disable printing of warnings self._add_patches() self._platform = utils.get_platform() self._arch = self._platform['architecture'] self._system = self._platform['system'].lower() self._hostname = self._platform['hostname'].lower() self._initscript_name = "init_package_env.sh" self.no_initscript = False self.add_extra_clean_targets(self._initscript_name) self.do_clean = True # default is to clean before building. siglist = [self._buildfile] + utils.get_svn_files_list() self._siglist = list(set(siglist)) self._init_dependencies()