[Scons-users] Dependency between Command calls
Mats Wichmann
mats at wichmann.us
Sat Apr 12 15:26:30 EDT 2025
On 4/12/25 12:13, Oliver Koch via Scons-users wrote:
> Dear SCons experts,
>
> Thank your for your last supporting comments!
>
> I have developed a small SConstruct file (attached) that implements to
> tool calls via Command().
> However, I have a few questions regarding generalization as given in the
> comments of the SConstruct file.
>
> The required input file (MyDeps.puml) is also attached.
>
> The output of the two subsequent runs of "scons" are given in Run1.out
> and Run2.out.
>
> So, the build is executed as intended, but the toy example is not really
> scalable to a real world tool chain.
>
> Could you answer my questions resp. give me some hints, how to make this
> a "real" build chain?
>
> Thank you!
>
> Oliver
A few comments, out of order.
# This is not executed. Why?
act = env.Action(PlantUML, cmdstr="Building ${TARGET}")
The Action method produces an action object, but you never do anything
with that action object. You have to tell something that act is its
action before anything happens with it. It's fine to pass it to Command,
that works in the same way as passing it an action string (which will
anyway be converted to an action object). So like:
tgt = env.Command(target, source, action=act)
----
from SCons.Script import *
you don't need to do that in an SConstruct/SConscript file, the
execution context causes it to be done for you. Where you need that
import is in files that are run directly and not executed by the
SConscript() function.
----
The classic way to scale when there are many files is to write a
builder. I think we've previously sent you links on that, please check
the earlier messages. But you don't have to. You could also take this:
# I am lloking for something like:
# for svg in SVGs:
# env.Command(svg.basename + '.svgz', svg, SVGZ)
and actually enable it, there's no real reason it wouldn't work
from pathlib import Path
for svg in SVGs:
tgtpath = str(Path(svg).name) + '.svgz'
env.Command(tgtpath, svg, action=SVGZ)
That's a bit "hacky", you should properly let SCons compute the path and
there are facilities for doing so. If you write a real Builder, part of
the plumbing it the knowlede of how to transform source to target names
for the type of files that builder handles.-
There's also a function which can let you find files - read up on Glob
in the manual. The nice thing about Glob() is it "finds" files that
haven't been built yet, as it can compute targets based on the
information in the graph. So you can potentially:
for svg in env.Glob('*.svg'): # these will be Nodes, unless you add a
strings=True arg
----
def PlantUML(target, source, env):
import os
for src in source:
Cmd = 'java.exe' + \
' -jar C:\\Progra~1\\PlantUML\\plantuml.jar' + \
' -tsvg ' + str(src)
print('Calling: ', Cmd)
os.system(Cmd)
# target should not be an input, but is given from Cmd output.
# How to make a list of targets from the just created files?
for tgt in target:
print(' Creating: ', str(tgt))
If you do things this way, you bypass the work SCons does for you. If
you build a command string like Cmd, and include substitutable elements
(like $SOURCE), and pass that to Command (instead of going directly out
via os.system() - and fwiw, using subprocess.run() is preferred if you
*MUST*), then bingo: the return from Command is the list of targets it
computed, and you have your answer to
# How to make a list of targets from the just created files?
More information about the Scons-users
mailing list