[Scons-users] Scanners

Carnë Draug carandraug+dev at gmail.com
Wed Jan 20 10:05:32 EST 2016


On 20 January 2016 at 11:22, Tom Tanner (BLOOMBERG/ LONDON)
<ttanner2 at bloomberg.net> wrote:
> Is there any way to tell the Scanner class to sort the list of scanned
> dependencies? I have a hand written scanner and it has to sort the
> dependencies it returns so as not to get unexpected rebuilds depending on
> the vagaries of todays choice of filing system and how python has decided to
> order dictionaries today.
>
> But even that isn't always enough as the scanner is recursive so it can
> possibly build multiple lists which are individually sorted but the total
> result isn't.
>
> But at least specifically in my case, and possibly in others, the order of
> the dependencies isn't important.

I had the same issue before.  But I could just sort the list myself to
solve the problem.  It was also recursive, but I used a set and merged
sets together to avoid duplicates.

Is this helpful?

    def perl5_scanner(node, env, path):
      perl_args = ["perl", "-MModule::ScanDeps"] + ["-I" + inc for inc
in env['PERL5LIB']]

      ## We handle the recursion ourselves instead of using the recursion
      ## option from Module::ScanDeps because that will descend deep into
      ## the whole system libraries and our dependencies (from the project)
      ## are likely to be much smaller.
      our_deps = set()
      cwd = os.path.realpath(os.getcwd())
      def scan_deps(fpaths):
        my_deps = set()
        for fpath in fpaths:
          ## Order of keys in perl is random for security, so we need to
          ## sort them, otherwise the order of dependencies will change
          ## causing a rebuild everytime.
          code = """
            $deps = scan_deps (files => ['%s'], recurse => 0);
            foreach (sort keys %%{$deps})
              { print $deps->{$_}->{file} . "\\n"; }
          """ % str(fpath)
          deps = subprocess.check_output(perl_args + ["-e", code],
env=env['ENV'])
          for dep in deps.splitlines():
            dep = os.path.realpath(dep)
            if dep.startswith(cwd) and dep not in our_deps:
              my_deps.add(dep)

        old_len = len(our_deps)
        my_deps.difference_update(our_deps)
        our_deps.update(my_deps)
        if len(our_deps) != old_len:
          scan_deps(my_deps)

      scan_deps([node])
      return env.File(list(our_deps))


    scanner = SCons.Script.Scanner(perl5_scanner, skeys=['.pl', '.pm'])
    env.Append(SCANNERS=scanner)

Carnë


More information about the Scons-users mailing list