def compile_module(module,specification,include_path=[]): spec_file = 'testtmp_%s.pip' % module code_file = 'testtmp_%s.cpp' % module extra = [] if sys.platform == 'darwin': extra.append('/usr/lib/libstdc++.6.dylib') ext = distutils.core.Extension(module,sources=[code_file],extra_objects=extra,extra_link_args=['-g'],extra_compile_args=['-g']) dist = distutils.dist.Distribution(dict(ext_modules=[ext])) bin_file = None try: os.mkdir('build') except: pass try: f=file(spec_file,"w") f.write(specification) f.close() pip.generate(module,spec_file,code_file,include_path) dist.get_option_dict('build_ext')['inplace']=('script',True) dist.get_option_dict('build_ext')['verbose']=('script',True) dist.run_command('build_ext') bin_file=dist.get_command_obj('build_ext').get_ext_filename(module) return imp.load_dynamic(module,bin_file) finally: if bin_file is not None: safe_remove(bin_file) dist.run_command('clean') safe_remove(spec_file) safe_remove(code_file)
def _compiler_type(): """ Gets the compiler type from distutils. On Windows with MSVC it will be "msvc". On macOS and linux it is "unix". Borrowed from https://github.com/pyca/cryptography/blob\ /05b34433fccdc2fec0bb014c3668068169d769fd/src/_cffi_src/utils.py#L78 """ dist = distutils.dist.Distribution() dist.parse_config_files() cmd = dist.get_command_obj('build') cmd.ensure_finalized() compiler = distutils.ccompiler.new_compiler(compiler=cmd.compiler) return compiler.compiler_type
def run_setup_command(prj: spec.BigflowProjectSpec, command, options=None): """Execute distutils command in the scope of same python process.""" attrs = projectspec_to_setuppy_kwargs(prj) logger.debug("Create tmp Distribution with attrs %r", attrs) dist = BigflowDistribution(attrs) if options: logger.debug("Update command options with %s", options) dist.get_option_dict(command).update(options) cmd_obj = dist.get_command_obj(command) logger.debug("Command object is %s", cmd_obj) cmd_obj.ensure_finalized() logger.info("Run command %s with options %s", command, options) cmd_obj.run()
def compile_module(module, specification, include_path=[]): spec_file = 'testtmp_%s.pip' % module code_file = 'testtmp_%s.cpp' % module extra = [] if sys.platform == 'darwin': extra.append('/usr/lib/libstdc++.6.dylib') ext = distutils.core.Extension(module, sources=[code_file], extra_objects=extra, extra_link_args=['-g'], extra_compile_args=['-g']) dist = distutils.dist.Distribution(dict(ext_modules=[ext])) bin_file = None try: os.mkdir('build') except: pass try: f = file(spec_file, "w") f.write(specification) f.close() pip.generate(module, spec_file, code_file, include_path) dist.get_option_dict('build_ext')['inplace'] = ('script', True) dist.get_option_dict('build_ext')['verbose'] = ('script', True) dist.run_command('build_ext') bin_file = dist.get_command_obj('build_ext').get_ext_filename(module) return imp.load_dynamic(module, bin_file) finally: if bin_file is not None: safe_remove(bin_file) dist.run_command('clean') safe_remove(spec_file) safe_remove(code_file)
def build_charm_extension(package_set): """ Builds Chimi's built-in Charm extension, if necessary, and sets up the Python search path so we can find it. """ charm = package_set.packages['charm'] charm_build = charm.builds[0] extension_dir = os.path.join(package_set.directory, 'chimi-tmp', 'ext') extension_path = os.path.join(extension_dir, 'charm.so') if not os.path.exists(extension_path): if not os.path.isdir(extension_dir): os.makedirs(extension_dir) import pkg_resources charm_source_string = pkg_resources.resource_string(__name__, 'data/ext/charm.cc') charm_source_path = os.path.join(extension_dir, 'charm.cc') # Fetch and transform the `CmiNumCores` source. src = file(os.path.join(charm.directory, 'src', 'conv-core', 'cputopology.C'), 'r').read() match = re.search(r'CmiNumCores[\s\n]*\((?:[\s\n]*void[\s\n]*|[\s\n]*)?\)[\s\n]*{', src, re.DOTALL) score = 1 idx = match.end() + 1 braces = re.compile(r'[{}]') while score > 0: m = braces.search(src, idx) score += 1 if m.group() == '{' else -1 idx = m.end() + 1 func_source = src[match.end()-1:idx+1] retre = re.compile(r'\breturn[\s\n]+([^\s\n]+)[\s\n]*;') py_cmi_num_cores_code = \ 'static PyObject*\n' + \ 'PyCmiNumCores()'+retre.subn(r'return PyInt_FromLong(\1);', func_source)[0] file(charm_source_path, 'w').write(charm_source_string.replace('PY_CMI_NUM_CORES_CODE', py_cmi_num_cores_code)) # Prepare the extension for compilation. import distutils.core import distutils.dist import distutils.command.build_ext ext = distutils.core.Extension('charm', sources=['charm.cc'], include_dirs=[os.path.join(charm_build.directory, 'include')], extra_compile_args=['--no-warnings'], language='c++' ) dist = distutils.dist.Distribution({'ext_modules': [ext], 'script_args': ['build_ext', '--inplace']}) cmd = dist.get_command_obj('build_ext') dist._set_command_options(cmd, {'inplace': (None, True)}) # distutils or python-config (...or something) decides to pass # '-Wstrict-prototypes' (a C-language option) to the compiler, which of # course complains because we're compiling C++ sources. (And *of # course* the '--no-warnings' compile flag [or any similar flag] has no # effect because of the order in which distutils combines compiler # flags. Grrrrr!) # # I don't like being told that I did something wrong when it's not my # fault, so we redirect standard error to /dev/null. (Compile errors? # *What* compile errors?) stderr = os.dup(sys.stderr.fileno()) devnull = os.open(os.devnull, os.O_RDWR) os.dup2(devnull, sys.stderr.fileno()) # Change directory into the extension dir, build the extension, and # restore the previous working directory. oldcwd = os.getcwd() error = None try: os.chdir(extension_dir) dist.run_command('build_ext') except distutils.errors.CompileError as err: error = err finally: os.chdir(oldcwd) os.dup2(stderr, sys.stderr.fileno()) if error: print(error) if not extension_dir in sys.path: sys.path.append(extension_dir)