Example #1
0
    def prepare(self):
        assert self.target.dolock.owned == state.LOCK_EX
        self.target.build_starting()
        self.before_t = _try_stat(self.target.name)

        newstamp = self.target.read_stamp()
        if self.target.is_generated and newstamp != self.target.stamp:
            if state.is_missing(newstamp):
                # was marked generated, but is now deleted
                debug3('oldstamp=%r newstamp=%r\n', self.target.stamp, newstamp)
                self.target.forget()
                self.target.refresh()
            elif vars.OVERWRITE:
                warn('%s: you modified it; overwrite\n', self.target.printable_name())
            else:
                warn('%s: you modified it; skipping\n', self.target.printable_name())
                return 0
        if self.target.exists_not_dir() and not self.target.is_generated:
            # an existing source file that was not generated by us.
            # This step is mentioned by djb in his notes.
            # For example, a rule called default.c.do could be used to try
            # to produce hello.c, but we don't want that to happen if
            # hello.c was created in advance by the end user.
            if vars.OVERWRITE:
                warn('%s: exists and not marked as generated; overwrite.\n',
                     self.target.printable_name())
            else:
                warn('%s: exists and not marked as generated; not redoing.\n',
                     self.target.printable_name())
                debug2('-- static (%r)\n', self.target.name)
                return 0

        (self.dodir, self.dofile, self.dobasedir, self.dobasename, self.doext) = _find_do_file(self.target)
        if not self.dofile:
            if state.is_missing(newstamp):
                err('no rule to make %r\n', self.target.name)
                return 1
            else:
                self.target.forget()
                debug2('-- forget (%r)\n', self.target.name)
                return 0  # no longer a generated target, but exists, so ok

        self.outdir = self._mkoutdir()
        # name connected to stdout
        self.tmpname_sout = self.target.tmpfilename('out.tmp')
        # name provided as $3
        self.tmpname_arg3 = os.path.join(self.outdir, self.target.basename())
        # name for the log file
        unlink(self.tmpname_sout)
        unlink(self.tmpname_arg3)
        self.tmpname_log, self.log_fd = logger.open_log(self.target, truncate=True)
        self.tmp_sout_fd = os.open(self.tmpname_sout, os.O_CREAT|os.O_RDWR|os.O_EXCL, 0666)
        close_on_exec(self.tmp_sout_fd, True)
        self.tmp_sout_f = os.fdopen(self.tmp_sout_fd, 'w+')

        return None
Example #2
0
def isdirty(f, depth, expect_stamp, max_runid):
    debug('%s?%s\n', depth, f.name)

    if not f.is_generated and not expect_stamp and f.exists():
        debug('%s-- CLEAN (static)\n', depth)
        return CLEAN
    if f.exitcode:
        debug('%s-- DIRTY (failed last time)\n', depth)
        return DIRTY
    if not state.is_missing(expect_stamp) and state.is_missing(f.stamp):
        debug('%s-- DIRTY (never built)\n', depth)
        return DIRTY
    if f.stamp_mtime > max_runid:
        debug('%s-- DIRTY (built)\n', depth)
        return DIRTY
    if not f.stamp:
        debug('%s-- DIRTY (no stamp)\n', depth)
        return DIRTY

    newstamp = f.read_stamp()

    debug3('%sexpect: %s\n', depth, expect_stamp)
    debug3('%sold:    %s\n', depth, f.stamp)
    debug3('%snew:    %s\n', depth, newstamp)
    if f.csum: debug3('%scsum:   %s\n', depth, f.csum)

    if f.is_generated and newstamp != f.stamp and not state.is_missing(newstamp):
        if vars.OVERWRITE:
            debug('%s-- DIRTY (override)\n', depth)
            return DIRTY
        else:
            debug('%s-- CLEAN (override)\n', depth)
            return CLEAN

    if newstamp != f.stamp:
        if state.is_missing(newstamp):
            debug('%s-- DIRTY (missing)\n', depth)
        else:
            debug('%s-- DIRTY (mtime)\n', depth)
        return [f] if f.csum else DIRTY

    must_build = []
    for stamp2, f2 in f.deps:
        dirty = CLEAN

        if f2 == state.ALWAYS:
            if f.stamp_mtime >= vars.RUNID:
                # has already been checked during this session
                debug('%s-- CLEAN (always, checked)\n', depth)
            else:
                debug('%s-- DIRTY (always)\n', depth)
                dirty = DIRTY
        else:
            f2 = state.File(f2, f.dir)
            sub = isdirty(f2, depth = depth + '  ',
                          expect_stamp = stamp2,
                          max_runid = max(f.stamp_mtime, vars.RUNID))
            if sub:
                debug('%s-- DIRTY (sub)\n', depth)
                dirty = sub

        if not f.csum:
            # f is a "normal" target: dirty f2 means f is instantly dirty
            if dirty:
                # if dirty==DIRTY, this means f is definitely dirty.
                # if dirty==[...], it's a list of the uncertain children.
                return dirty
        else:
            # f is "checksummable": dirty f2 means f needs to redo,
            # but f might turn out to be clean after that (ie. our parent
            # might not be dirty).
            if dirty == DIRTY:
                # f2 is definitely dirty, so f definitely needs to
                # redo.  However, after that, f might turn out to be
                # unchanged.
                return [f]
            elif isinstance(dirty, list):
                # our child f2 might be dirty, but it's not sure yet.  It's
                # given us a list of targets we have to redo in order to
                # be sure.
                must_build += dirty

    if must_build:
        # f is *maybe* dirty because at least one of its children is maybe
        # dirty.  must_build has accumulated a list of "topmost" uncertain
        # objects in the tree.  If we build all those, we can then
        # redo-ifchange f and it won't have any uncertainty next time.
        return must_build

    if expect_stamp != (f.csum or f.stamp):
        # This must be after we checked the children. Before, we didn't knew
        # if the current target was dirty or not
        debug('%s-- DIRTY (parent)\n', depth)
        return DIRTY

    # if we get here, it's because the target is clean
    debug2('%s-- CLEAN (dropped off)\n', depth)
    return CLEAN