コード例 #1
0
    def compile(self,
                src: fbuild.db.SRC,
                dst=None,
                *,
                flags=[],
                **kwargs) -> fbuild.db.DST:
        """Compile a c file and cache the results."""
        # Generate the dependencies while we compile the file.
        with tempfile() as dep:
            obj = self.uncached_compile(src,
                                        dst,
                                        flags=list(
                                            chain(('-MMD', '-MF', dep),
                                                  flags)),
                                        **kwargs)

            with open(dep, 'rb') as f:
                # Parse the output and return the module dependencies.
                stdout = f.read().replace(b'\\\n', b'')

        # Parse the output and return the module dependencies.
        m = re.match(b'\s*\S+:(?: (.*))?$', stdout)
        if not m:
            raise fbuild.ExecutionError('unable to understand %r' % stdout)

        s = m.group(1)
        if s is not None:
            deps = s.decode().split()
            self.ctx.db.add_external_dependencies_to_call(srcs=deps)

        return obj
コード例 #2
0
ファイル: __init__.py プロジェクト: rjeschmi/fbuild
    def modules(self, src:fbuild.db.SRC, *,
            preprocessor=None,
            flags=()):
        """Calculate the modules this ocaml file depends on."""
        src = Path(src)

        cmd = [self.exe]
        cmd.extend(self.pre_flags)
        cmd.append('-modules')

        if preprocessor is not None:
            cmd.extend(('-pp', preprocessor))

        cmd.extend(self.flags)
        cmd.extend(flags)
        cmd.append(src)

        # Now, run ocamldep
        stdout, stderr = self.ctx.execute(cmd, str(self), src,
            color='yellow',
            stdout_quieter=1)

        # Parse the output and return the module dependencies.
        m = re.match(b'\S+:(?: (.*))?$', stdout.strip())
        if not m:
            raise fbuild.ExecutionError('unable to understand %r' % stdout)

        s = m.group(1)
        if s is None:
            return ()
        else:
            return tuple(s.decode().split())
コード例 #3
0
ファイル: context.py プロジェクト: refi64/fbuild
    def execute(self, cmd, msg1=None, msg2=None, *,
            arch=None,
            color=None,
            quieter=0,
            stdout_quieter=None,
            stderr_quieter=None,
            input=None,
            stdin=None,
            stdout=fbuild.subprocess.PIPE,
            stderr=fbuild.subprocess.PIPE,
            timeout=None,
            env=None,
            runtime_libpaths=None,
            **kwargs):
        """Execute the command and return the output."""

        if isinstance(cmd, str):
            cmd_string = cmd
        else:
            cmd_parts = []
            # Wrap any space separated parts in quotes.
            for c in cmd:
                if ' ' in c:
                    c = "'{}'".format(c.replace("'", "\\'"))
                cmd_parts.append(c)
            cmd_string = ' '.join(cmd_parts)

        if stdout_quieter is None:
            stdout_quieter = quieter

        if stderr_quieter is None:
            stderr_quieter = quieter

        # Windows needs something in the environment, so for the moment we'll
        # just make sure everything is passed on to the executable.
        if env is None:
            env = dict(os.environ)
        else:
            env = dict(os.environ, **env)

        # Add in the runtime library search paths.
        if runtime_libpaths:
            # Look up the current architecture
            runtime_env_libpath = \
                fbuild.builders.platform.runtime_env_libpath(self)

            runtime_libpaths = os.pathsep.join(runtime_libpaths)
            try:
                libpaths = env[runtime_env_libpath]
            except KeyError:
                libpaths = runtime_libpaths
            else:
                libpaths += os.pathsep + runtime_libpaths

            env[runtime_env_libpath] = libpaths

            # Add the runtime libpaths to the command string.
            cmd_string = '{}={} {}'.format(
                runtime_env_libpath,
                libpaths,
                cmd_string)

        self.logger.write('%-10s: starting %r\n' %
            (threading.current_thread().name, cmd_string),
            verbose=4,
            buffer=False)

        if msg1:
            if msg2:
                self.logger.check(' * ' + str(msg1), str(msg2),
                    color=color,
                    verbose=quieter)
            else:
                self.logger.check(' * ' + str(msg1),
                    color=color,
                    verbose=quieter)

        # Define a function that gets called if execution times out. We will
        # raise an exception if the timeout occurs.
        if timeout:
            timed_out = False
            def timeout_function(p):
                nonlocal timed_out
                timed_out = True
                p.kill(group=True)

            # Set the timer to None for now to make sure it's defined.
            timer = None

        starttime = time.time()
        try:
            p = fbuild.subprocess.killableprocess.Popen(cmd,
                stdin=fbuild.subprocess.PIPE if input else stdin,
                stdout=stdout,
                stderr=stderr,
                env=env,
                **kwargs)

            try:
                if timeout:
                    timer = threading.Timer(timeout, timeout_function, (p,))
                    timer.start()

                stdout, stderr = p.communicate(input)
                returncode = p.wait()
            except KeyboardInterrupt:
                # Make sure if we get a keyboard interrupt to kill the process.
                p.kill(group=True)
                raise
            else:
                # Detect Ctrl-C in subprocess.
                if returncode == -signal.SIGINT:
                    raise KeyboardInterrupt
        except OSError as e:
            # flush the logger
            self.logger.log('command failed: ' + cmd_string, color='red')
            raise e from e
        finally:
            if timeout and timer is not None:
                timer.cancel()
        endtime = time.time()

        if returncode:
            self.logger.log(' + ' + cmd_string, verbose=quieter)
        else:
            self.logger.log(' + ' + cmd_string, verbose=1)

        if stdout:
            try:
                self.logger.log(stdout.rstrip().decode(),
                    verbose=stdout_quieter)
            except UnicodeDecodeError:
                self.logger.log(repr(stdout.rstrip()), verbose=stdout_quieter)

        if stderr:
            try:
                self.logger.log(stderr.rstrip().decode(),
                    verbose=stderr_quieter)
            except UnicodeDecodeError:
                self.logger.log(repr(stderr.rstrip()), verbose=stderr_quieter)

        self.logger.log(
            ' - exit %d, %.2f sec' % (returncode, endtime - starttime),
            verbose=2)

        if timeout and timed_out:
            raise fbuild.ExecutionTimedOut(cmd, stdout, stderr, returncode)
        elif returncode:
            raise fbuild.ExecutionError(cmd, stdout, stderr, returncode)

        return stdout, stderr