def relocate_pkgconfig(root): # Do trivial rewrites of pkgconfig files. pkg_config = os.path.join(root, 'lib', 'pkgconfig') if os.path.exists(pkg_config): for name in os.listdir(pkg_config): if not name.endswith('.pc'): continue path = os.path.join(pkg_config, name) log.info(path) lines = list(open(path)) for i, line in enumerate(lines): if re.match(r'^prefix=([^\$]+)\s*$', line): lines[i] = 'prefix=%s\n' % root break else: with log.indent(): log.warning('No obvious prefix to replace') continue # As silly as this seems, *.pc files we have seen have their # write flag removed, but we still own them (since we just installed # them). Quickest way to fix: delete them. if not os.access(path, os.W_OK): os.unlink(path) with open(path, 'w') as fh: fh.writelines(lines)
def relocate(root, con, spec=None, dry_run=False, target_cache=None): target_cache = {} if target_cache is None else target_cache flags, include, exclude = _parse_spec(spec, root) if 'linux' in flags and not sys.platform.startswith('linux'): return if 'darwin' in flags and sys.platform != 'darwin': return if not (include or 'auto' in flags): raise ValueError('no libraries to include') # Find everything in include on OS X, since we need to actually find the # individual dependencies. if sys.platform == 'darwin': for path in include: for found in find_shared_libraries(path): log.debug('found %s' % found) for name in name_variants(os.path.basename(found)): target_cache.setdefault(name, []).append(found) for lib_path in find_shared_libraries(root): log.info(lib_path) with log.indent(): if sys.platform == 'darwin': _relocate_darwin_library(lib_path, con, flags, include, exclude, dry_run, target_cache) else: _relocate_linux_library(lib_path, include, dry_run) if 'pkgconfig' in flags: relocate_pkgconfig(root)
def relocate_package(pkg): if pkg.relocate: log.info(style_note('Relocating')) with log.indent(): libs.relocate(pkg.install_path, con=pkg.home.db.connect(), spec=pkg.render_template(pkg.relocate), ) if pkg.set_rpath and sys.platform.startswith('linux'): rpath = pkg.render_template(pkg.set_rpath) log.info(style_note('Setting RPATH to', rpath)) with log.indent(): libs.relocate(pkg.install_path, con=pkg.home.db.connect(), spec=rpath, )
def develop(self): log.info(style_note('source %s' % os.path.basename(self.develop_sh))) pkg = self.package def setenv(name, value): log.info('vee develop setenv %s "%s"' % (name, value)) pkg.environ[name] = value with log.indent(): bash_source(os.path.basename(self.develop_sh), callbacks=dict(vee_develop_setenv=setenv), cwd=os.path.dirname(self.develop_sh))
def call(cmd, **kwargs): # Log the call. kwargs.pop('silent', None) # B/C. VEE = os.environ.get('VEE') cmd_collapsed = [x.replace(VEE, '$VEE') if VEE else x for x in cmd] log.debug( '$ ' + ' '.join(cmd_collapsed), verbosity=2, _frame=kwargs.pop('_frame', 0) + 3 ) check = kwargs.pop('check', True) verbosity = kwargs.pop('verbosity', 0) indent = kwargs.pop('indent', False) if indent: indent = log.indent() indent.__enter__() pty = kwargs.pop('pty', None) stdout = _CallOutput(kwargs.pop('stdout', None), 'stdout', verbosity, pty=pty) stderr = _CallOutput(kwargs.pop('stderr', None), 'stderr', verbosity, pty=pty) proc = subprocess.Popen(cmd, stdout=stdout.slave_fd, stderr=stderr.slave_fd, bufsize=0, **kwargs) stdout.start(proc) stderr.start(proc) proc.wait() stdout.join() stderr.join() if indent: indent.__exit__(None, None, None) if (check or stdout.return_buffer or stderr.return_buffer) and proc.returncode: raise subprocess.CalledProcessError(proc.returncode, cmd) if stdout.return_buffer and stderr.return_buffer: return ''.join(stdout.buffer), ''.join(stderr.buffer) if stdout.return_buffer: return ''.join(stdout.buffer) if stderr.return_buffer: return ''.join(stderr.buffer) return proc.returncode
def install(self): log.info(style_note('source %s' % os.path.basename(self.install_sh))) pkg = self.package pkg._assert_paths(build=True, install=True) env = pkg.fresh_environ() env.update( VEE=pkg.home.root, VEE_BUILD_PATH=pkg.build_path, VEE_INSTALL_NAME=pkg.install_name, VEE_INSTALL_PATH=pkg.install_path, ) cwd = os.path.dirname(self.install_sh) with log.indent(): call([ 'bash', '-c', 'source "%s" "%s"' % (self.install_sh, pkg.install_path) ], env=env, cwd=cwd)
def install(self, names=None, link_env=None, reinstall=False, relink=False, no_deps=False): # I'd love to split this method into an "install" and "link" step, but # then we'd need to reimplement the dependency resolution. That would # be a good idea to do anyways, but... meh. if isinstance(names, str): names = [names] names = list(names if names else self.keys()) for name in names: if name not in self: raise KeyError(name) if not isinstance(reinstall, set): reinstall = set( names if no_deps else self.keys()) if reinstall else set() if not isinstance(relink, set): relink = set( names if no_deps else self.keys()) if relink else set() while names: name = names.pop(0) self._parent_names.setdefault(name, None) parent_chain = [] tip = name while tip and tip not in parent_chain: parent_chain.append(tip) tip = self._parent_names.get(tip) parent_chain = parent_chain[1:] print( '==>', style(name, 'blue'), style('(%s)' % ' < '.join(parent_chain), faint=True) if parent_chain else '') with log.indent(): # Avoid infinite error loops. if name in self._errored: log.warning('Skipping due to previous error.') continue try: self._install_one(names, name, link_env, reinstall, relink, no_deps) except PipelineError as e: self._errored.add(name) log.error(str(e)) continue except Exception as e: self._errored.add(name) print_cli_exc(e, verbose=True) log.exception('Exception while processing %s' % name) continue if self._errored: log.warning('There were errors in: %s' % ', '.join(sorted(self._errored)))
def call(cmd, **kwargs): # Log the call. kwargs.pop('silent', None) # B/C. VEE = os.environ.get('VEE') cmd_collapsed = [x.replace(VEE, '$VEE') if VEE else x for x in cmd] log.debug( '$ ' + ' '.join(cmd_collapsed), verbosity=2, _frame=kwargs.pop('_frame', 0) + 3 ) check = kwargs.pop('check', True) decode = kwargs.pop('decode', False) verbosity = kwargs.pop('verbosity', 0) indent = kwargs.pop('indent', False) if indent: indent = log.indent() indent.__enter__() pty = kwargs.pop('pty', None) stdout = _CallOutput(kwargs.pop('stdout', None), 'stdout', verbosity, pty=pty) stderr = _CallOutput(kwargs.pop('stderr', None), 'stderr', verbosity, pty=pty) if kwargs.pop('vee_in_env', False): vee_src = os.path.abspath(os.path.join(__file__, '..', '..')) env = kwargs.get('env', os.environ).copy() env['PYTHONPATH'] = join_env_path( vee_src, env.get('PYTHONPATH') ) env['PATH'] = join_env_path(os.path.join(vee_src, 'bin'), env.get('PATH')) kwargs['env'] = env proc = subprocess.Popen(cmd, stdout=stdout.slave_fd, stderr=stderr.slave_fd, bufsize=0, **kwargs) stdout.start(proc) stderr.start(proc) proc.wait() stdout.join() stderr.join() if indent: indent.__exit__(None, None, None) if (check or stdout.return_buffer or stderr.return_buffer) and proc.returncode: raise subprocess.CalledProcessError(proc.returncode, cmd) # Decode if requested. if stdout.return_buffer: stdout_res = b''.join(stdout.buffer) if decode: stdout_res = stdout_res.decode() if stderr.return_buffer: stderr_res = b''.join(stderr.buffer) if decode: stderr_res = stderr_res.decode() if stdout.return_buffer and stderr.return_buffer: return stdout_res, stderr_res if stdout.return_buffer: return stdout_res if stderr.return_buffer: return stderr_res return proc.returncode
def link(args): """Link the given requirement or requirements into the given environment, e.g.:: # Install and link a single package. $ vee link [email protected]:vfxetc/sgmock # Install and link multiple packages. $ vee link [email protected]:vfxetc/sgmock [email protected]:vfxetc/sgsession \\ http:/example.org/path/to/tarball.tgz --make-install # Install and link from a requirement set. $ vee link path/to/manifest.txt """ if args.no_install and args.re_install: raise ValueError( 'please use only one of --no-install and --re-install') home = args.assert_home() if sum( int(bool(x)) for x in (args.repo, args.environment, args.directory)) > 1: raise ValueError( 'use only one of --repo, --environment, or --directory') if args.environment: env = Environment(args.environment, home=home) elif args.directory: env = Environment(os.path.abspath(args.directory), home=home) else: repo = home.get_repo(args.repo) env = Environment('%s/%s' % (repo.name, repo.branch_name), home=home) if args.raw: for dir_ in args.requirements: log.info(style_note('Linking', dir_)) env.link_directory(dir_) return manifest = Manifest(args.requirements, home=home) pkg_set = PackageSet(env=env, home=home) # Register the whole set, so that dependencies are pulled from here instead # of weakly resolved from installed packages. pkg_set.resolve_set(manifest) for req in manifest.iter_packages(): # Skip if it wasn't requested. if args.subset and req.name not in args.subset: continue log.info(style('==> %s' % req.name, 'blue')) pkg = pkg_set.resolve(req, check_existing=not args.reinstall) if args.no_install and not pkg.installed: raise CliError('not installed: %s' % req) try: with log.indent(): pkg_set.install(pkg.name, link_env=env, reinstall=args.reinstall, relink=args.force) except AlreadyInstalled: pass except AlreadyLinked as e: log.info(style('Already linked ', 'blue') + str(req), verbosity=1) except Exception as e: print_cli_exc(e, verbose=True) log.exception('Failed to link %s' % req) continue