def check_compiler(self, compiler_cmd, compiler_args): """Checks a compiler command its arguments for compatibility with this target configuration. Checks that the given compiler matches at least one, **but possibly more**, of the compilers used in the target. Also performs any special checkes for invalid compiler arguments, e.g. -mmic is only for native KNC. If the given compiler command and arguments are compatible with this target then information about matching compiler installations is returned as a list of n :any:`InstalledCompiler` instances. Args: compiler_cmd (str): The compiler command as passed by the user. compiler_args (list): Compiler command line arguments. Returns: list: Information about matching installed compilers as :any:`Compiler` instances. Raises: ConfigurationError: The compiler or command line arguments are incompatible with this target. """ if '-mmic' in compiler_args and self['host_arch'] != str(INTEL_KNC): raise ConfigurationError("Host architecture of target '%s' is '%s'" " but the '-mmic' compiler argument requires '%s'" % (self['name'], self['host_arch'], INTEL_KNC), "Select a different target", "Create a new target with host architecture '%s'" % INTEL_KNC) compiler_ctrl = Compiler.controller(self.storage) absolute_path = util.which(compiler_cmd) compiler_cmd = os.path.basename(compiler_cmd) found = [] known_compilers = [comp for comp in self.compilers().itervalues()] for info in Knowledgebase.find_compiler(command=compiler_cmd): try: compiler_record = self.populate(info.role.keyword) except KeyError: # Target was not configured with a compiler in this role continue compiler_path = compiler_record['path'] if (absolute_path and (compiler_path == absolute_path) or (not absolute_path and (os.path.basename(compiler_path) == compiler_cmd))): found.append(compiler_record) else: # Target was configured with a wrapper compiler so check if that wrapper wraps this compiler while 'wrapped' in compiler_record: compiler_record = compiler_ctrl.one(compiler_record['wrapped']) known_compilers.append(compiler_record.installation()) compiler_path = compiler_record['path'] if (absolute_path and (compiler_path == absolute_path) or (not absolute_path and (os.path.basename(compiler_path) == compiler_cmd))): found.append(compiler_record) break if not found: parts = ["No compiler in target '%s' matches '%s'." % (self['name'], absolute_path or compiler_cmd), "The known compiler commands are:"] parts.extend(' %s (%s)' % (comp.absolute_path, comp.info.short_descr) for comp in known_compilers) hints = ("Try one of the valid compiler commands", "Create and select a new target configuration that uses the '%s' compiler" % (absolute_path or compiler_cmd), "Check loaded modules and the PATH environment variable") raise ConfigurationError('\n'.join(parts), *hints) return found
def _compiler_info(self): command = os.path.basename(self['path']) role = Knowledgebase.find_role(self['role']) family = role.kbase.families[self['family']] info_list = Knowledgebase.find_compiler(command, family, role) if len(info_list) != 1: raise InternalError("Zero or more than one known compilers match '%s'" % self) return info_list[0]
def _parse_tau_makefile(self, args): # Parsing a TAU Makefile is a really hairy operation, so let's lift the limits # pylint: disable=too-many-statements,too-many-locals makefile = args.forced_makefile if not util.path_accessible(makefile): self.parser.error("Invalid TAU makefile: %s" % makefile) tau_arch_name = os.path.basename( os.path.dirname(os.path.dirname(makefile))) matches = [ arch for arch in TauMagic.all() if arch.name == tau_arch_name ] if len(matches) == 1: tau_arch = matches[0] elif not matches: raise ConfigurationError( "TAU Makefile '%s' targets an unrecognized TAU architecture: %s" % (makefile, tau_arch_name)) else: for arch in matches: if arch.architecture == HOST_ARCH and arch.operating_system == HOST_OS: tau_arch = arch break else: parts = [ "TAU Makefile '%s' targets an ambiguous TAU architecture: %s" % (makefile, tau_arch_name), "It could be any of these:" ] parts.extend([ " - %s on %s" % (arch.operating_system.name, arch.architecture.name) for arch in matches ]) raise ConfigurationError("\n".join(parts)) self.logger.info( "Parsing TAU Makefile '%s' to populate command line arguments:", makefile) args.host_arch = tau_arch.architecture.name self.logger.info(" --host-arch='%s'", args.host_arch) args.host_os = tau_arch.operating_system.name self.logger.info(" --host-os='%s'", args.host_os) args.tau_source = os.path.abspath( os.path.join(os.path.dirname(makefile), '..', '..')) self.logger.info(" --taucmdr='%s'", args.tau_source) with open(makefile, 'r') as fin: compiler_parts = ("FULL_CC", "FULL_CXX", "TAU_F90") package_parts = { "BFDINCLUDE": ("binutils_source", lambda x: os.path.dirname(shlex.split(x)[0].lstrip("-I"))), "UNWIND_INC": ("libunwind_source", lambda x: os.path.dirname(x.lstrip("-I"))), "PAPIDIR": ("papi_source", os.path.abspath), "PDTDIR": ("pdt_source", os.path.abspath), "SCOREPDIR": ("scorep_source", os.path.abspath) } tau_r = '' for line in fin: if line.startswith('#'): continue try: key, val = [x.strip() for x in line.split('=', 1)] except ValueError: continue if key == 'TAU_R': tau_r = val.split()[0] elif key in compiler_parts: path = util.which(val.strip().split()[0].replace( '$(TAU_R)', tau_r)) if not path: self.logger.warning( "Failed to parse %s in TAU Makefile '%s'", key, makefile) continue matching_info = Knowledgebase.find_compiler( os.path.basename(path)) if matching_info: if len(matching_info) > 1: self.logger.warning( "Ambiguous compiler '%s' in TAU Makefile '%s'", path, makefile) comp = InstalledCompiler(path, matching_info[0]) attr = comp.info.role.keyword setattr(args, attr, comp.absolute_path) self.logger.info(" --%s='%s'", attr.lower().replace("_", "-"), comp.absolute_path) while comp.wrapped: comp = comp.wrapped attr = comp.info.role.keyword setattr(args, attr, comp.absolute_path) self.logger.info(" --%s='%s'", attr.lower().replace("_", "-"), comp.absolute_path) elif key in package_parts: attr, operator = package_parts[key] path = val.strip() if not path: path = None else: path = operator(path) if not os.path.exists(path): self.logger.warning( "'%s' referenced by TAU Makefile '%s' doesn't exist", path, makefile) continue setattr(args, attr, path) self.logger.info(" --%s='%s'", attr.replace("_source", ""), path)
def check_compiler(self, compiler_cmd, compiler_args): """Checks a compiler command its arguments for compatibility with this target configuration. Checks that the given compiler matches at least one, **but possibly more**, of the compilers used in the target. Also performs any special checkes for invalid compiler arguments, e.g. -mmic is only for native KNC. If the given compiler command and arguments are compatible with this target then information about matching compiler installations is returned as a list of n :any:`InstalledCompiler` instances. Args: compiler_cmd (str): The compiler command as passed by the user. compiler_args (list): Compiler command line arguments. Returns: list: Information about matching installed compilers as :any:`Compiler` instances. Raises: ConfigurationError: The compiler or command line arguments are incompatible with this target. """ if '-mmic' in compiler_args and self['host_arch'] != str(INTEL_KNC): raise ConfigurationError( "Host architecture of target '%s' is '%s'" " but the '-mmic' compiler argument requires '%s'" % (self['name'], self['host_arch'], INTEL_KNC), "Select a different target", "Create a new target with host architecture '%s'" % INTEL_KNC) compiler_ctrl = Compiler.controller(self.storage) absolute_path = util.which(compiler_cmd) compiler_cmd = os.path.basename(compiler_cmd) found = [] known_compilers = [comp for comp in self.compilers().itervalues()] for info in Knowledgebase.find_compiler(command=compiler_cmd): try: compiler_record = self.populate(info.role.keyword) except KeyError: # Target was not configured with a compiler in this role continue compiler_path = compiler_record['path'] if (absolute_path and (compiler_path == absolute_path) or (not absolute_path and (os.path.basename(compiler_path) == compiler_cmd))): found.append(compiler_record) else: # Target was configured with a wrapper compiler so check if that wrapper wraps this compiler while 'wrapped' in compiler_record: compiler_record = compiler_ctrl.one( compiler_record['wrapped']) known_compilers.append(compiler_record.installation()) compiler_path = compiler_record['path'] if (absolute_path and (compiler_path == absolute_path) or (not absolute_path and (os.path.basename(compiler_path) == compiler_cmd))): found.append(compiler_record) break if not found: parts = [ "No compiler in target '%s' matches '%s'." % (self['name'], absolute_path or compiler_cmd), "The known compiler commands are:" ] parts.extend(' %s (%s)' % (comp.absolute_path, comp.info.short_descr) for comp in known_compilers) hints = ( "Try one of the valid compiler commands", "Create and select a new target configuration that uses the '%s' compiler" % (absolute_path or compiler_cmd), "Check loaded modules and the PATH environment variable") raise ConfigurationError('\n'.join(parts), *hints) return found
def _parse_tau_makefile(self, args): # Parsing a TAU Makefile is a really hairy operation, so let's lift the limits # pylint: disable=too-many-statements,too-many-locals makefile = args.forced_makefile if not util.path_accessible(makefile): self.parser.error("Invalid TAU makefile: %s" % makefile) tau_arch_name = os.path.basename(os.path.dirname(os.path.dirname(makefile))) matches = [arch for arch in TauMagic.all() if arch.name == tau_arch_name] if len(matches) == 1: tau_arch = matches[0] elif len(matches) == 0: raise ConfigurationError("TAU Makefile '%s' targets an unrecognized TAU architecture: %s" % (makefile, tau_arch_name)) else: for arch in matches: if arch.architecture == HOST_ARCH and arch.operating_system == HOST_OS: tau_arch = arch break else: parts = ["TAU Makefile '%s' targets an ambiguous TAU architecture: %s" % (makefile, tau_arch_name), "It could be any of these:"] parts.extend([" - %s on %s" % (arch.operating_system.name, arch.architecture.name) for arch in matches]) raise ConfigurationError("\n".join(parts)) self.logger.info("Parsing TAU Makefile '%s' to populate command line arguments:", makefile) args.host_arch = tau_arch.architecture.name self.logger.info(" --host-arch='%s'", args.host_arch) args.host_os = tau_arch.operating_system.name self.logger.info(" --host-os='%s'", args.host_os) args.tau_source = os.path.abspath(os.path.join(os.path.dirname(makefile), '..', '..')) self.logger.info(" --taucmdr='%s'", args.tau_source) with open(makefile, 'r') as fin: compiler_parts = ("FULL_CC", "FULL_CXX", "TAU_F90") package_parts = {"BFDINCLUDE": ("binutils_source", lambda x: os.path.dirname(x.lstrip("-I"))), "UNWIND_INC": ("libunwind_source", lambda x: os.path.dirname(x.lstrip("-I"))), "PAPIDIR": ("papi_source", os.path.abspath), "PDTDIR": ("pdt_source", os.path.abspath), "SCOREPDIR": ("scorep_source", os.path.abspath)} tau_r = '' for line in fin: if line.startswith('#'): continue try: key, val = [x.strip() for x in line.split('=', 1)] except ValueError: continue if key == 'TAU_R': tau_r = val.split()[0] elif key in compiler_parts: path = util.which(val.strip().split()[0].replace('$(TAU_R)', tau_r)) if not path: self.logger.warning("Failed to parse %s in TAU Makefile '%s'", key, makefile) continue matching_info = Knowledgebase.find_compiler(os.path.basename(path)) if matching_info: if len(matching_info) > 1: self.logger.warning("Ambiguous compiler '%s' in TAU Makefile '%s'", path, makefile) comp = InstalledCompiler(path, matching_info[0]) attr = comp.info.role.keyword setattr(args, attr, comp.absolute_path) self.logger.info(" --%s='%s'", attr.lower().replace("_", "-"), comp.absolute_path) while comp.wrapped: comp = comp.wrapped attr = comp.info.role.keyword setattr(args, attr, comp.absolute_path) self.logger.info(" --%s='%s'", attr.lower().replace("_", "-"), comp.absolute_path) elif key in package_parts: attr, operator = package_parts[key] path = val.strip() if not path: path = None else: path = operator(path) if not os.path.exists(path): self.logger.warning("'%s' referenced by TAU Makefile '%s' doesn't exist", path, makefile) continue setattr(args, attr, path) self.logger.info(" --%s='%s'", attr.replace("_source", ""), path)