def _create_binary(self, binary_tgt, results_dir): """Create a .pex file for the specified binary target.""" # Note that we rebuild a chroot from scratch, instead of using the REQUIREMENTS_PEX # and PYTHON_SOURCES products, because those products are already-built pexes, and there's # no easy way to merge them into a single pex file (for example, they each have a __main__.py, # metadata, and so on, which the merging code would have to handle specially). interpreter = self.context.products.get_data(PythonInterpreter) with temporary_dir() as tmpdir: # Create the pex_info for the binary. run_info_dict = self.context.run_tracker.run_info.get_as_dict() build_properties = PexInfo.make_build_properties() build_properties.update(run_info_dict) pex_info = binary_tgt.pexinfo.copy() pex_info.build_properties = build_properties builder = PEXBuilder(path=tmpdir, interpreter=interpreter, pex_info=pex_info, copy=True) if binary_tgt.shebang: self.context.log.info( 'Found Python binary target {} with customized shebang, using it: {}' .format(binary_tgt.name, binary_tgt.shebang)) builder.set_shebang(binary_tgt.shebang) else: self.context.log.debug( 'No customized shebang found for {}'.format( binary_tgt.name)) # Find which targets provide sources and which specify requirements. source_tgts = [] req_tgts = [] for tgt in binary_tgt.closure(exclude_scopes=Scopes.COMPILE): if has_python_sources(tgt) or has_resources(tgt): source_tgts.append(tgt) # Add target's interpreter compatibility constraints to pex info. if has_python_sources(tgt): for constraint in tgt.compatibility: builder.add_interpreter_constraint(constraint) elif has_python_requirements(tgt): req_tgts.append(tgt) # Dump everything into the builder's chroot. for tgt in source_tgts: dump_sources(builder, tgt, self.context.log) dump_requirements(builder, interpreter, req_tgts, self.context.log, binary_tgt.platforms) # Build the .pex file. pex_path = os.path.join(results_dir, '{}.pex'.format(binary_tgt.name)) builder.build(pex_path) return pex_path
def bootstrap_conan(self): pex_info = PexInfo.default() pex_info.entry_point = 'conans.conan' conan_bootstrap_dir = os.path.join(get_pants_cachedir(), 'conan_support') conan_pex_path = os.path.join(conan_bootstrap_dir, 'conan_binary') interpreter = PythonInterpreter.get() if not os.path.exists(conan_pex_path): with safe_concurrent_creation(conan_pex_path) as safe_path: builder = PEXBuilder(safe_path, interpreter, pex_info=pex_info) reqs = [PythonRequirement(req) for req in self.get_options().conan_requirements] dump_requirements(builder, interpreter, reqs, logger) builder.freeze() conan_binary = PEX(conan_pex_path, interpreter) return self.ConanBinary(pex=conan_binary)
def resolve_requirement_strings(self, interpreter, requirement_strings): """Resolve a list of pip-style requirement strings.""" requirement_strings = sorted(requirement_strings) if len(requirement_strings) == 0: req_strings_id = 'no_requirements' elif len(requirement_strings) == 1: req_strings_id = requirement_strings[0] else: req_strings_id = hash_all(requirement_strings) path = os.path.realpath(os.path.join(self.workdir, str(interpreter.identity), req_strings_id)) if not os.path.isdir(path): reqs = [PythonRequirement(req_str) for req_str in requirement_strings] with safe_concurrent_creation(path) as safe_path: builder = PEXBuilder(path=safe_path, interpreter=interpreter, copy=True) dump_requirements(builder, interpreter, reqs, self.context.log) builder.freeze() return PEX(path, interpreter=interpreter)
def bootstrap_conan(self): pex_info = PexInfo.default() pex_info.entry_point = 'conans.conan' conan_bootstrap_dir = os.path.join(get_pants_cachedir(), 'conan_support') conan_pex_path = os.path.join(conan_bootstrap_dir, 'conan_binary') interpreter = PythonInterpreter.get() if not os.path.exists(conan_pex_path): with safe_concurrent_creation(conan_pex_path) as safe_path: builder = PEXBuilder(safe_path, interpreter, pex_info=pex_info) reqs = [ PythonRequirement(req) for req in self.get_options().conan_requirements ] dump_requirements(builder, interpreter, reqs, logger) builder.freeze() conan_binary = PEX(conan_pex_path, interpreter) return self.ConanBinary(pex=conan_binary)
def bootstrap(self, interpreter, pex_file_path, extra_reqs=None): # Caching is done just by checking if the file at the specified path is already executable. if not is_executable(pex_file_path): pex_info = PexInfo.default(interpreter=interpreter) if self.entry_point is not None: pex_info.entry_point = self.entry_point with safe_concurrent_creation(pex_file_path) as safe_path: builder = PEXBuilder(interpreter=interpreter, pex_info=pex_info) all_reqs = list(self.base_requirements) + list(extra_reqs or []) dump_requirements(builder, interpreter, all_reqs, logger, platforms=['current']) builder.build(safe_path) return PEX(pex_file_path, interpreter)
def _build_requirements_pex(self, interpreter, path, req_libs): builder = PEXBuilder(path=path, interpreter=interpreter, copy=True) dump_requirements(builder, interpreter, req_libs, self.context.log) builder.freeze()