def run_compiler(self, env, mode, cmd, assumed_family, abs_path = None): try: return VerifyCompiler(env, mode, cmd, assumed_family, abs_path), None except Exception as e: util.con_out(util.ConsoleHeader, 'Compiler {0} for {1} failed: '.format(cmd, mode), util.ConsoleRed, str(e), util.ConsoleNormal) return None, e
def update(self): for entry in self.graph.create: if entry.type == nodetypes.Mkdir: util.con_out(util.ConsoleBlue, '[create] ', util.ConsoleGreen, entry.format(), util.ConsoleNormal) # The path might already exist because we mkdir -p and don't bother # ordering. if not os.path.exists(entry.path): os.makedirs(entry.path) else: raise Exception('Unknown entry type: {0}'.format(entry.type)) if not len(self.leafs): return True tm = TaskMasterParent(self.cx, self, self.leafs, self.max_parallel) success = tm.run() self.commit() if success and len(self.commands) != self.num_completed_tasks: util.con_err( util.ConsoleRed, 'Build marked as completed, but some commands were not executed?!\n', 'Commands:', util.ConsoleNormal) for task in self.commands: if not task: continue util.con_err(util.ConsoleBlue, ' -> ', util.ConsoleRed, '{0}'.format(task.entry.format()), util.ConsoleNormal) return success
def check_upgrade(self): try: query = "select val from vars where key = 'db_version'" cursor = self.cn.execute(query) row = cursor.fetchone() if not row: raise Exception('Database seems to be misconfigured - cannot read version') version = int(row[0]) except: version = 1 latest_version = 4 if version == latest_version: return if version > latest_version: raise Exception('Your database version is too new!') util.con_out( util.ConsoleHeader, 'Note: upgrading database from version {0} to {1}'.format(version, latest_version), util.ConsoleNormal ) if version == 1: version = self.upgrade_to_v2() if version == 2: version = self.upgrade_to_v3() if version == 3: version = self.upgrade_to_v4()
def drop_folder(self, entry): assert entry.type in [ nodetypes.Mkdir, nodetypes.Output, nodetypes.SharedOutput ] assert not os.path.isabs(entry.path) if os.path.exists(entry.path): util.con_out(util.ConsoleHeader, 'Removing old folder: ', util.ConsoleBlue, '{0}'.format(entry.path), util.ConsoleNormal) try: os.rmdir(entry.path) except OSError as exn: if exn.errno != errno.ENOENT: util.con_err(util.ConsoleRed, 'Could not remove folder: ', util.ConsoleBlue, '{0}'.format(entry.path), util.ConsoleNormal, '\n', util.ConsoleRed, '{0}'.format(exn), util.ConsoleNormal) raise cursor = self.cn.execute("select count(*) from nodes where folder = ?", (entry.id, )) amount = cursor.fetchone()[0] if amount > 0: util.con_err( util.ConsoleRed, 'Folder id ', util.ConsoleBlue, '{0} '.format(entry.id), util.ConsoleRed, 'is about to be deleted, but is still in use as a folder!', util.ConsoleNormal) raise Exception('folder still in use!') # If the node transitioned to an entry, don't delete its node. if entry.type == nodetypes.Mkdir: self.drop_entry(entry)
def drop_folder(self, entry): assert entry.type in [nodetypes.Mkdir, nodetypes.Output, nodetypes.SharedOutput] assert not os.path.isabs(entry.path) if os.path.exists(entry.path): util.con_out( util.ConsoleHeader, 'Removing old folder: ', util.ConsoleBlue, '{0}'.format(entry.path), util.ConsoleNormal) try: os.rmdir(entry.path) except OSError as exn: if exn.errno != errno.ENOENT: util.con_err(util.ConsoleRed, 'Could not remove folder: ', util.ConsoleBlue, '{0}'.format(entry.path), util.ConsoleNormal, '\n', util.ConsoleRed, '{0}'.format(exn), util.ConsoleNormal) raise cursor = self.cn.execute("select count(*) from nodes where folder = ?", (entry.id,)) amount = cursor.fetchone()[0] if amount > 0: util.con_err(util.ConsoleRed, 'Folder id ', util.ConsoleBlue, '{0} '.format(entry.id), util.ConsoleRed, 'is about to be deleted, but is still in use as a folder!', util.ConsoleNormal) raise Exception('folder still in use!') # If the node transitioned to an entry, don't delete its node. if entry.type == nodetypes.Mkdir: self.drop_entry(entry)
def spewResult(self, message): if message['ok']: color = util.ConsoleGreen else: color = util.ConsoleRed util.con_out( util.ConsoleBlue, '[{0}]'.format(message['pid']), util.ConsoleNormal, ' ', color, message['cmdline'], util.ConsoleNormal ) sys.stdout.flush() if len(message['stdout']): util.WriteEncodedText(sys.stdout, message['stdout']) if message['stdout'][-1] != '\n': sys.stdout.write('\n') sys.stdout.flush() if len(message['stderr']): util.WriteEncodedText(sys.stderr, message['stderr']) if message['stderr'][-1] != '\n': sys.stderr.write('\n') sys.stderr.flush()
def verify_native(self): self.write_source(False) argv = self.build_link_argv() util.con_out( util.ConsoleHeader, 'Checking {0} compiler (vendor test {1})... '.format( self.mode_, self.family_), util.ConsoleBlue, '{0}'.format(argv), util.ConsoleNormal) p = util.CreateProcess(argv, env=self.env_, no_raise=False) if util.WaitForProcess(p) != 0: raise Exception('Compiler failed with return code {0}'.format( p.returncode)) inclusion_pattern = None if self.family_ == 'msvc': inclusion_pattern = msvc_utils.DetectInclusionPattern(p.stdoutText) lines = self.test_executable() return { 'vendor': lines[0], 'arch': lines[2], 'inclusion_pattern': inclusion_pattern, }
def check_upgrade(self): try: query = "select val from vars where key = 'db_version'" cursor = self.cn.execute(query) row = cursor.fetchone() if not row: raise Exception( 'Database seems to be misconfigured - cannot read version') version = int(row[0]) except: version = 1 latest_version = 3 if version == latest_version: return if version > latest_version: raise Exception('Your database version is too new!') util.con_out( util.ConsoleHeader, 'Note: upgrading database from version {0} to {1}'.format( version, latest_version), util.ConsoleNormal) if version == 1: version = self.upgrade_to_v2() if version == 2: version = self.upgrade_to_v3()
def reconfigure(self): # See if we need to reconfigure. files = [] reconfigure_needed = False self.db.query_scripts(lambda row, path, stamp: files.append( (path, stamp))) for path, stamp in files: if not os.path.exists(path) or os.path.getmtime(path) > stamp: reconfigure_needed = True break if not reconfigure_needed: return True util.con_out(util.ConsoleHeader, 'Reparsing build scripts.', util.ConsoleNormal) # The database should be upgraded here, so we should always have an # API version set. api_version = Version(self.db.query_var('api_version')) assert api_version is not None if api_version >= '2.2': from ambuild2.frontend.v2_2.context_manager import ContextManager elif api_version >= '2.1': from ambuild2.frontend.v2_1.context_manager import ContextManager elif api_version >= '2.0': from ambuild2.frontend.v2_0.context_manager import ContextManager # Backwards compatibility: for an automatic reconfigure on an older build, # just assume the source path is the cwd. If the AMBuildScript suddenly # has decided to depend on originalCwd, then the user may have to manually # run configure.py again, until we remove configure.py entirely. if 'originalCwd' in self.vars: originalCwd = self.vars['originalCwd'] else: originalCwd = self.vars['sourcePath'] cm = ContextManager(sourcePath=self.vars['sourcePath'], buildPath=self.vars['buildPath'], originalCwd=originalCwd, options=self.vars['options'], args=self.vars['args']) cm.db = self.db cm.refactoring = self.options.refactor try: cm.generate('ambuild2') except: traceback.print_exc() util.con_err(util.ConsoleRed, 'Failed to reparse build scripts.', util.ConsoleNormal) return False # We flush the node cache after this, since database.py expects to get # never-before-seen items at the start. We could change this and make # nodes individually import, which might be cleaner. self.db.flush_caches() return True
def TryVerifyCompiler(env, mode, cmd, assumed_family): try: return VerifyCompiler(env, mode, cmd, assumed_family) except Exception as e: util.con_out(util.ConsoleHeader, 'Compiler {0} for {1} failed: '.format(cmd, mode), util.ConsoleRed, str(e), util.ConsoleNormal) return None
def startWorker(self): args = (self.cx.vars, ) child = self.cx.procman.spawn(TaskWorker, args) self.workers_.append(child) util.con_out(util.ConsoleHeader, 'Spawned {0} (pid: {1})'.format('worker', child.proc.pid), util.ConsoleNormal)
def build_internal(self): if self.options.show_graph: self.db.printGraph() return True if self.options.show_changed: dmg_list = damage.ComputeDamageGraph(self.db, only_changed=True) for entry in dmg_list: if not entry.isFile(): continue print(entry.format()) return True dmg_graph = damage.ComputeDamageGraph(self.db) if not dmg_graph: return False # If we get here, we have to compute damage. if self.options.show_damage: dmg_graph.printGraph() return True dmg_graph.filter_commands() if self.options.show_commands: dmg_graph.printGraph() return True builder = Builder(self, dmg_graph) if self.options.show_steps: builder.printSteps() return True status, message = builder.update() if status == TaskMaster.BUILD_FAILED: if message is None: util.con_err(util.ConsoleHeader, 'Build failed.', util.ConsoleNormal) else: util.con_err(util.ConsoleHeader, 'Build failed: {}'.format(message), util.ConsoleNormal) return False if status == TaskMaster.BUILD_INTERRUPTED: util.con_err(util.ConsoleHeader, 'Build cancelled.', util.ConsoleNormal) return False if status == TaskMaster.BUILD_NO_CHANGES: util.con_out(util.ConsoleHeader, 'Build succeeded, no changes.', util.ConsoleNormal) return True assert status == TaskMaster.BUILD_SUCCEEDED util.con_out(util.ConsoleHeader, 'Build succeeded.', util.ConsoleNormal) return True
def postGenerate(self): self.cleanup() self.db.commit() self.db.vacuum() if self.is_bootstrap: self.saveVars() self.db.close() if self.had_symlink_fallback: util.con_out(util.ConsoleHeader, 'Note: filesystem does not support symlinks. Files will be copied instead.', util.ConsoleNormal)
def TryVerifyCompiler(env, mode, cmd, assumed_family): try: return VerifyCompiler(env, mode, cmd, assumed_family) except Exception as e: util.con_out( util.ConsoleHeader, 'Compiler {0} for {1} failed: '.format(cmd, mode), util.ConsoleRed, e.message, util.ConsoleNormal ) return None
def processResults(self, message): if not message['ok']: self.errors_.append(message) self.terminateBuild() return self.spewResult(message) task_id = message['task_id'] updates = message['updates'] if not self.builder.updateGraph(task_id, updates, message): util.con_out(util.ConsoleRed, 'Failed to update node!', util.ConsoleNormal) self.terminateBuild()
def run_compiler(self, mode, cmd, assumed_family, env = None, abs_path = None): self.rules_config_['family'] = assumed_family props = self.rp_.parse(self.rules_config_) flags = props.get('CFLAGS', []) flags += shlex.split(os.environ.get('CFLAGS', '')) if mode == 'CXX': flags.extend(shlex.split(os.environ.get('CXXFLAGS', ''))) try: return self.verify_compiler(flags, mode, cmd, assumed_family, env, abs_path), None except Exception as e: util.con_out(util.ConsoleHeader, 'Compiler {0} for {1} failed: '.format(cmd, mode), util.ConsoleRed, str(e), util.ConsoleNormal) return None, e
def reconfigure(self): # See if we need to reconfigure. files = [] reconfigure_needed = False self.db.query_scripts(lambda row,path,stamp: files.append((path, stamp))) for path, stamp in files: if not os.path.exists(path) or os.path.getmtime(path) > stamp: reconfigure_needed = True break if not reconfigure_needed: return True util.con_out( util.ConsoleHeader, 'Reparsing build scripts.', util.ConsoleNormal ) # The database should be upgraded here, so we should always have an # API version set. api_version = self.db.query_var('api_version') assert api_version is not None if api_version == '2.0': from ambuild2.frontend.v2_0.amb2.gen import Generator elif api_version == '2.1': from ambuild2.frontend.v2_1.amb2 import Generator gen = Generator.FromVars(self.vars, self.db, self.options.refactor) try: gen.generate() except: traceback.print_exc() util.con_err( util.ConsoleRed, 'Failed to reparse build scripts.', util.ConsoleNormal ) return False # We flush the node cache after this, since database.py expects to get # never-before-seen items at the start. We could change this and make # nodes individually import, which might be cleaner. self.db.flush_caches() return True
def build_internal(self): if self.options.show_graph: self.db.printGraph() return True if self.options.show_changed: dmg_list = damage.ComputeDamageGraph(self.db, only_changed=True) for entry in dmg_list: if not entry.isFile(): continue print(entry.format()) return True dmg_graph = damage.ComputeDamageGraph(self.db) if not dmg_graph: return False # If we get here, we have to compute damage. if self.options.show_damage: dmg_graph.printGraph() return True dmg_graph.filter_commands() if self.options.show_commands: dmg_graph.printGraph() return True builder = Builder(self, dmg_graph) if self.options.show_steps: builder.printSteps() return True if not builder.update(): util.con_err( util.ConsoleHeader, 'Build failed.', util.ConsoleNormal ) return False util.con_out( util.ConsoleHeader, 'Build succeeded.', util.ConsoleNormal ) return True
def processResults(self, message): if not message['ok']: self.errors_.append(message) self.terminateBuild() return self.spewResult(message) task_id = message['task_id'] updates = message['updates'] if not self.builder.updateGraph(task_id, updates, message): util.con_out( util.ConsoleRed, 'Failed to update node!', util.ConsoleNormal ) self.terminateBuild()
def reconfigure(self): # See if we need to reconfigure. files = [] reconfigure_needed = False self.db.query_scripts(lambda row, path, stamp: files.append( (path, stamp))) for path, stamp in files: if not os.path.exists(path) or os.path.getmtime(path) > stamp: reconfigure_needed = True break if not reconfigure_needed: return True util.con_out(util.ConsoleHeader, 'Reparsing build scripts.', util.ConsoleNormal) # The database should be upgraded here, so we should always have an # API version set. api_version = self.db.query_var('api_version') assert api_version is not None if api_version == '2.0': from ambuild2.frontend.v2_0.amb2.gen import Generator elif api_version == '2.1': from ambuild2.frontend.v2_1.amb2 import Generator gen = Generator.FromVars(self.vars, self.db, self.options.refactor) try: gen.generate() except: traceback.print_exc() util.con_err(util.ConsoleRed, 'Failed to reparse build scripts.', util.ConsoleNormal) return False # We flush the node cache after this, since database.py expects to get # never-before-seen items at the start. We could change this and make # nodes individually import, which might be cleaner. self.db.flush_caches() return True
def recvTaskComplete(self, worker, message): task = self.pending_[worker.pid] message['pid'] = worker.pid if not message['ok']: self.errors_.append((worker, task, message)) self.terminateBuild(TaskMaster.BUILD_FAILED) return self.spewResult(worker, task, message) del self.pending_[worker.pid] if message['task_id'] != task.id: raise Exception( 'Worker {} returned wrong task id (got {}, expected {})'. format(worker.pid, task_id, task.id)) updates = message['updates'] if not self.builder.updateGraph(task.id, updates, message): util.con_out(util.ConsoleRed, 'Failed to update node!', util.ConsoleNormal) self.terminateBuild(TaskMaster.BUILD_FAILED) # Enqueue any tasks that can be run if this was their last outstanding # dependency. for outgoing in task.outgoing: outgoing.incoming.remove(task) if len(outgoing.incoming) == 0: self.task_graph.append(outgoing) if not len(self.task_graph) and not len(self.pending_): # There are no tasks remaining. self.status_ = TaskMaster.BUILD_SUCCEEDED # Add this process to the idle set. self.idle_.add(worker) # If more stuff was queued, and we have idle processes, use them. while len(self.task_graph) and len(self.idle_): worker = self.idle_.pop() self.issue_next_task(worker)
def spewResult(self, worker, message): if message['ok']: color = util.ConsoleGreen else: color = util.ConsoleRed util.con_out(util.ConsoleBlue, '[{0}]'.format(message['pid']), util.ConsoleNormal, ' ', color, message['cmdline'], util.ConsoleNormal) sys.stdout.flush() if len(message['stdout']): util.WriteEncodedText(sys.stdout, message['stdout']) if message['stdout'][-1] != '\n': sys.stdout.write('\n') sys.stdout.flush() if len(message['stderr']): util.WriteEncodedText(sys.stderr, message['stderr']) if message['stderr'][-1] != '\n': sys.stderr.write('\n') sys.stderr.flush()
def DetectEmscripten(env, var): cmd = env[var] argv = cmd.split() if 'CFLAGS' in env: argv += env.get('CFLAGS', '').split() if var == 'CC': suffix = '.c' elif var == 'CXX': argv += env.get('CXXFLAGS', '').split() suffix = '.cpp' # Run emcc -dM -E on a blank file to get preprocessor definitions. with tempfile.NamedTemporaryFile(suffix = suffix, delete = True) as fp: argv = cmd.split() + ['-dM', '-E', fp.name] output = subprocess.check_output(args = argv) output = output.replace('\r', '') lines = output.split('\n') # Map the definitions into a dictionary. defs = {} for line in lines: m = re.match('#define\s+([A-Za-z_][A-Za-z0-9_]*)\s*(.*)', line) if m is None: continue macro = m.group(1) value = m.group(2) defs[macro] = value if '__EMSCRIPTEN__' not in defs: return None version = '{0}.{1}'.format(defs['__EMSCRIPTEN_major__'], defs['__EMSCRIPTEN_minor__']) v = vendors.Emscripten(cmd, version) util.con_out( util.ConsoleHeader, 'found {0} version {1}'.format('Emscripten', version), util.ConsoleNormal ) return v
def DetectEmscripten(env, var): cmd = env[var] argv = cmd.split() if 'CFLAGS' in env: argv += env.get('CFLAGS', '').split() if var == 'CC': suffix = '.c' elif var == 'CXX': argv += env.get('CXXFLAGS', '').split() suffix = '.cpp' # Run emcc -dM -E on a blank file to get preprocessor definitions. with tempfile.NamedTemporaryFile(suffix=suffix, delete=True) as fp: argv = cmd.split() + ['-dM', '-E', fp.name] output = subprocess.check_output(args=argv) output = output.replace('\r', '') lines = output.split('\n') # Map the definitions into a dictionary. defs = {} for line in lines: m = re.match('#define\s+([A-Za-z_][A-Za-z0-9_]*)\s*(.*)', line) if m is None: continue macro = m.group(1) value = m.group(2) defs[macro] = value if '__EMSCRIPTEN__' not in defs: return None version = '{0}.{1}'.format(defs['__EMSCRIPTEN_major__'], defs['__EMSCRIPTEN_minor__']) v = vendors.Emscripten(cmd, version) util.con_out(util.ConsoleHeader, 'found {0} version {1}'.format('Emscripten', version), util.ConsoleNormal) return v
def verify_compiler(self, flags, mode, cmd, assumed_family, env, abs_path): base_argv = shlex.split(cmd) base_argv.extend(flags) argv = base_argv[:] if abs_path is not None: argv[0] = abs_path verifier = Verifier(family = assumed_family, env = env, argv = argv, mode = mode, cross_compile = self.cross_compile_) info = verifier.verify() vendor, version = info['vendor'].split(' ') if vendor == 'gcc': v = GCC(version) elif vendor == 'emscripten': v = Emscripten(version) elif vendor == 'apple-clang': v = Clang(version, 'apple') elif vendor == 'clang': v = Clang(version) elif vendor == 'msvc': v = MSVC(version) else: raise Exception('Unknown vendor {0}'.format(vendor)) if info['inclusion_pattern'] is not None: v.extra_props['inclusion_pattern'] = info['inclusion_pattern'] util.con_out(util.ConsoleHeader, 'found {0} version {1}, {2}'.format(vendor, version, info['arch']), util.ConsoleNormal) return CommandAndVendor(base_argv, v, info['arch'])
def verify_cross_compile(self): self.write_source(True) argv = self.build_pp_argv() util.con_out( util.ConsoleHeader, 'Checking {0} compiler (vendor test {1})... '.format( self.mode_, self.family_), util.ConsoleBlue, '{0}'.format(argv), util.ConsoleNormal) p = util.CreateProcess(argv, env=self.env_, no_raise=False) if util.WaitForProcess(p) != 0: raise Exception('compiler failed with return code {0}'.format( p.returncode)) lines = self.parse_pp(p.stdoutText) self.verify_lines(lines) # Execute one more time to test linkage. self.write_source(False) argv = self.build_link_argv() p = util.CreateProcess(argv, env=self.env_, no_raise=False) if util.WaitForProcess(p) != 0: raise Exception('compiler failed with return code {}: {}'.format( p.returncode, argv)) inclusion_pattern = None if self.family_ == 'msvc': inclusion_pattern = msvc_utils.DetectInclusionPattern(p.stdoutText) return { 'vendor': lines[0], 'arch': lines[2], 'inclusion_pattern': inclusion_pattern, }
def VerifyCompiler(env, mode, cmd, vendor): args = cmd.split() if 'CFLAGS' in env: args.extend(env['CFLAGS'].split()) if mode == 'CXX' and 'CXXFLAGS' in env: args.extend(env['CXXFLAGS'].split()) if mode == 'CXX': filename = 'test.cpp' else: filename = 'test.c' file = open(filename, 'w') file.write(""" #include <stdio.h> #include <stdlib.h> int main() { #if defined __ICC printf("icc %d\\n", __ICC); #elif defined __clang__ # if defined(__clang_major__) && defined(__clang_minor__) # if defined(__apple_build_version__) printf("apple-clang %d.%d\\n", __clang_major__, __clang_minor__); # else printf("clang %d.%d\\n", __clang_major__, __clang_minor__); # endif # else printf("clang 1.%d\\n", __GNUC_MINOR__); # endif #elif defined __GNUC__ printf("gcc %d.%d\\n", __GNUC__, __GNUC_MINOR__); #elif defined _MSC_VER printf("msvc %d\\n", _MSC_VER); #elif defined __TenDRA__ printf("tendra 0\\n"); #elif defined __SUNPRO_C printf("sun %x\\n", __SUNPRO_C); #elif defined __SUNPRO_CC printf("sun %x\\n", __SUNPRO_CC); #else #error "Unrecognized compiler!" #endif #if defined __cplusplus printf("CXX\\n"); #else printf("CC\\n"); #endif exit(0); } """) file.close() if mode == 'CC': executable = 'test' + util.ExecutableSuffix elif mode == 'CXX': executable = 'testp' + util.ExecutableSuffix # Make sure the exe is gone. if os.path.exists(executable): os.unlink(executable) # Until we can better detect vendors, don't do this. # if vendor == 'gcc' and mode == 'CXX': # args.extend(['-fno-exceptions', '-fno-rtti']) args.extend([filename, '-o', executable]) # For MSVC, we need to detect the inclusion pattern for foreign-language # systems. if vendor == 'msvc': args += ['-nologo', '-showIncludes'] util.con_out( util.ConsoleHeader, 'Checking {0} compiler (vendor test {1})... '.format(mode, vendor), util.ConsoleBlue, '{0}'.format(args), util.ConsoleNormal ) p = util.CreateProcess(args) if p == None: print('not found') return False if util.WaitForProcess(p) != 0: print('failed with return code {0}'.format(p.returncode)) return False inclusion_pattern = None if vendor == 'msvc': inclusion_pattern = DetectMicrosoftInclusionPattern(p.stdoutText) exe = util.MakePath('.', executable) p = util.CreateProcess([executable], executable = exe) if p == None: print('failed to create executable with {0}'.format(cmd)) return False if util.WaitForProcess(p) != 0: print('executable failed with return code {0}'.format(p.returncode)) return False lines = p.stdoutText.splitlines() if len(lines) != 2: print('invalid executable output') return False if lines[1] != mode: print('requested {0} compiler, found {1}'.format(mode, lines[1])) return False vendor, version = lines[0].split(' ') if vendor == 'gcc': v = vendors.GCC(cmd, version) elif vendor == 'apple-clang': v = vendors.Clang('apple-clang', cmd, version) elif vendor == 'clang': v = vendors.Clang('clang', cmd, version) elif vendor == 'msvc': v = vendors.MSVC(cmd, version) elif vendor == 'sun': v = vendors.SunPro(cmd, version) else: print('Unknown vendor {0}'.format(vendor)) return False if inclusion_pattern is not None: v.extra_props['inclusion_pattern'] = inclusion_pattern util.con_out( util.ConsoleHeader, 'found {0} version {1}'.format(vendor, version), util.ConsoleNormal ) return v
def receiveSpawned(self, message): util.con_out( util.ConsoleHeader, 'Spawned {0} (pid: {1})'.format(message['type'], message['pid']), util.ConsoleNormal )
def receiveSpawned(self, message): util.con_out( util.ConsoleHeader, 'Spawned {0} (pid: {1})'.format(message['type'], message['pid']), util.ConsoleNormal)
def VerifyCompiler(env, mode, cmd, vendor): args = cmd.split() if 'CFLAGS' in env: args.extend(env['CFLAGS'].split()) if mode == 'CXX' and 'CXXFLAGS' in env: args.extend(env['CXXFLAGS'].split()) if mode == 'CXX': filename = 'test.cpp' else: filename = 'test.c' file = open(filename, 'w') file.write(""" #include <stdio.h> #include <stdlib.h> int main() { #if defined __ICC printf("icc %d\\n", __ICC); #elif defined __clang__ # if defined(__clang_major__) && defined(__clang_minor__) # if defined(__apple_build_version__) printf("apple-clang %d.%d\\n", __clang_major__, __clang_minor__); # else printf("clang %d.%d\\n", __clang_major__, __clang_minor__); # endif # else printf("clang 1.%d\\n", __GNUC_MINOR__); # endif #elif defined __GNUC__ printf("gcc %d.%d\\n", __GNUC__, __GNUC_MINOR__); #elif defined _MSC_VER printf("msvc %d\\n", _MSC_VER); #elif defined __TenDRA__ printf("tendra 0\\n"); #elif defined __SUNPRO_C printf("sun %x\\n", __SUNPRO_C); #elif defined __SUNPRO_CC printf("sun %x\\n", __SUNPRO_CC); #else #error "Unrecognized compiler!" #endif #if defined __cplusplus printf("CXX\\n"); #else printf("CC\\n"); #endif exit(0); } """) file.close() if mode == 'CC': executable = 'test' + util.ExecutableSuffix elif mode == 'CXX': executable = 'testp' + util.ExecutableSuffix # Make sure the exe is gone. if os.path.exists(executable): os.unlink(executable) # Until we can better detect vendors, don't do this. # if vendor == 'gcc' and mode == 'CXX': # args.extend(['-fno-exceptions', '-fno-rtti']) args.extend([filename, '-o', executable]) # For MSVC, we need to detect the inclusion pattern for foreign-language # systems. if vendor == 'msvc': args += ['-nologo', '-showIncludes'] util.con_out( util.ConsoleHeader, 'Checking {0} compiler (vendor test {1})... '.format(mode, vendor), util.ConsoleBlue, '{0}'.format(args), util.ConsoleNormal) p = util.CreateProcess(args) if p == None: print('not found') return False if util.WaitForProcess(p) != 0: print('failed with return code {0}'.format(p.returncode)) return False inclusion_pattern = None if vendor == 'msvc': inclusion_pattern = DetectMicrosoftInclusionPattern(p.stdoutText) exe = util.MakePath('.', executable) p = util.CreateProcess([executable], executable=exe) if p == None: print('failed to create executable with {0}'.format(cmd)) return False if util.WaitForProcess(p) != 0: print('executable failed with return code {0}'.format(p.returncode)) return False lines = p.stdoutText.splitlines() if len(lines) != 2: print('invalid executable output') return False if lines[1] != mode: print('requested {0} compiler, found {1}'.format(mode, lines[1])) return False vendor, version = lines[0].split(' ') if vendor == 'gcc': v = vendors.GCC(cmd, version) elif vendor == 'apple-clang': v = vendors.Clang('apple-clang', cmd, version) elif vendor == 'clang': v = vendors.Clang('clang', cmd, version) elif vendor == 'msvc': v = vendors.MSVC(cmd, version) elif vendor == 'sun': v = vendors.SunPro(cmd, version) else: print('Unknown vendor {0}'.format(vendor)) return False if inclusion_pattern is not None: v.extra_props['inclusion_pattern'] = inclusion_pattern util.con_out(util.ConsoleHeader, 'found {0} version {1}'.format(vendor, version), util.ConsoleNormal) return v
def VerifyCompiler(env, mode, cmd, assumed_family): base_argv = cmd.split() if 'CFLAGS' in env: base_argv.extend(env['CFLAGS'].split()) if mode == 'CXX' and 'CXXFLAGS' in env: base_argv.extend(env['CXXFLAGS'].split()) argv = base_argv[:] if mode == 'CXX': filename = 'test.cpp' else: filename = 'test.c' file = open(filename, 'w') file.write(""" #include <stdio.h> #include <stdlib.h> int main() { #if defined __ICC printf("icc %d\\n", __ICC); #elif defined(__EMSCRIPTEN__) printf("emscripten %d.%d\\n", __clang_major__, __clang_minor__); #elif defined __clang__ # if defined(__clang_major__) && defined(__clang_minor__) # if defined(__apple_build_version__) printf("apple-clang %d.%d\\n", __clang_major__, __clang_minor__); # else printf("clang %d.%d\\n", __clang_major__, __clang_minor__); # endif # else printf("clang 1.%d\\n", __GNUC_MINOR__); # endif #elif defined __GNUC__ printf("gcc %d.%d\\n", __GNUC__, __GNUC_MINOR__); #elif defined _MSC_VER printf("msvc %d\\n", _MSC_VER); #elif defined __TenDRA__ printf("tendra 0\\n"); #elif defined __SUNPRO_C printf("sun %x\\n", __SUNPRO_C); #elif defined __SUNPRO_CC printf("sun %x\\n", __SUNPRO_CC); #else #error "Unrecognized compiler!" #endif #if defined __cplusplus printf("CXX\\n"); #else printf("CC\\n"); #endif exit(0); } """) file.close() executable = 'test' if mode == 'CXX': executable += 'p' if assumed_family == 'emscripten': executable += '.js' else: executable += util.ExecutableSuffix # Make sure the exe is gone. if os.path.exists(executable): os.unlink(executable) argv.extend([filename, '-o', executable]) # For MSVC, we need to detect the inclusion pattern for foreign-language # systems. if assumed_family == 'msvc': argv += ['-nologo', '-showIncludes'] util.con_out( util.ConsoleHeader, 'Checking {0} compiler (vendor test {1})... '.format( mode, assumed_family), util.ConsoleBlue, '{0}'.format(argv), util.ConsoleNormal) p = util.CreateProcess(argv) if p == None: raise Exception('compiler not found') if util.WaitForProcess(p) != 0: raise Exception('compiler failed with return code {0}'.format( p.returncode)) inclusion_pattern = None if assumed_family == 'msvc': inclusion_pattern = MSVC.DetectInclusionPattern(p.stdoutText) executable_argv = [executable] if assumed_family == 'emscripten': exe = 'node' executable_argv[0:0] = [exe] else: exe = util.MakePath('.', executable) p = util.CreateProcess(executable_argv, executable=exe) if p == None: raise Exception('failed to create executable with {0}'.format(cmd)) if util.WaitForProcess(p) != 0: raise Exception('executable failed with return code {0}'.format( p.returncode)) lines = p.stdoutText.splitlines() if len(lines) != 2: raise Exception('invalid executable output') if lines[1] != mode: raise Exception('requested {0} compiler, found {1}'.format( mode, lines[1])) vendor, version = lines[0].split(' ') if vendor == 'gcc': v = GCC(version) elif vendor == 'emscripten': v = Emscripten(version) elif vendor == 'apple-clang': v = Clang(version, 'apple') elif vendor == 'clang': v = Clang(version) elif vendor == 'msvc': v = MSVC(version) elif vendor == 'sun': v = SunPro(version) else: raise Exception('Unknown vendor {0}'.format(vendor)) if inclusion_pattern is not None: v.extra_props['inclusion_pattern'] = inclusion_pattern util.con_out(util.ConsoleHeader, 'found {0} version {1}'.format(vendor, version), util.ConsoleNormal) return CommandAndVendor(base_argv, v)