Reputation: 9469
I'm trying to understand why Sphinx
builder for SCons doesn't work. The essential part of the code that I want to debug boils down to this:
SCons.Action.Action('$SPHINXCOM', '$SPHINXCOMSTR')
I know that in theory, $SPHINXCOM
should expand to $SPHINXBUILD $_SPHINXOPTIONS ${SOURCE.attributes.root} ${TARGET.attributes.root}
, but since SCons never seems to run this action, I can never trace what was it thinking it should run.
Trying to navigate SCons' own code is a road to hell... it's completely opaque, with dozens of delegations and guesswork and so on... After hours of trying, I still cannot find the code that is supposed to run when this action is evaluated, or whatever the correct term is... but at some point the methods of the action start returning empty string, at which point it seems to stop.
By reading through the --help
options, I cannot see anything that would increase verbosity or print any more diagnostic messages than what is already printed (there isn't really any logging in the code anyway, so there seems to be nothing to print anyway). I would be happy to find the code that executes the action, so that I would know at which point the action does have to have to produce any non-null values in its methods... I'd be grateful if anyone could point me to that code.
Just to give you a taste of what is going on with this Action
thing. My findings so far are as follows:
Action
calls two helper methods conditioned on the type of arguments, which in my case seems to delegate the work to ActionBase
class.ActionBase
, after inspecting the types of arguments (all of which are passed through **kw
, i.e. anonymously) seems to then delegate the work to ActionAction
class.ActionAction
class then inspects the arguments, which have now been altered by the previous inspections, and calls CommandAction
class to deal with the input.CommandAction
now again delegates to Action
.Action
now received the same basic info in the arguments, but it's formatted differently: instead of the second argument being a string, it is a dict with a single key in it.Action
now delegates to _Action
...Somewhere around that point the methods of "action" object start returning empty string where a I'd expect to see the generated command. Given the overall structure and smell of the code, I think I only scratched the surface of this devious delegation scheme, but I don't have enough of inside knowledge to cut through all of it to the place, where "action" methods are really accessed. If I knew where that happens, I'd be able to find a way to structure the arguments to Action
in such a way that they make it in one piece to that place.
Upvotes: 1
Views: 1017
Reputation: 4052
Note that SCons runs in two phases: a "parse" phase, and a "build" phase. The call trace that you describe above is from the "parse" phase. This is where the SConstructs get read and digested. In this phase, SCons simply keeps track of which source and target nodes are required (get defined) by the different Builder calls like "env.PDF("test.ltx")
". For a target node, like "test.pdf
" in this example, it also registers the Environment to be used ("env
" here). In Builder::_execute
an instance of the class Executor
gets registered with each target, keeping track of which Builder actions have to get triggered.
But it doesn't execute the required single Actions right away! This will only happen later, in the "build" phase, when SCons detects that the target "test.pdf
" is indeed not up-to-date.
Then, Task::execute
(in Taskmaster.py) gets called, which invokes the Node::build()
method of the target node. There the registered Executor gets called and expands the Actions in Executor::execute_action_list()
.
Remark: Take into account that the string '$SPHINXCOM'
gets substituted with the variables as being set for the current Environment. So, you don't have to manipulate the arguments given to the Action
constructor, but the variables in the used Environment for getting the output you need.
I hope this helps you further. ;)
Upvotes: 1