Description
-MG
only reports new dependencies one by one, it would be much better to do so in batches: generating more dependencies per step reduces the amount of RGBASM invocations, which is better.
Some testing with GCC shows that it reports all missing deps, and treats all missing files as empty. (#if
, #ifdef
etc. are evaluated normally.)
This could in theory cause some problems:
Data:
INCBIN "file.bin"
IF @ - Data == 0
FAIL "Wut, the file is empty?"
ENDC
...to which I suggest aborting normally on any fatal error. This would be similar to the current behavior, but probably less common. Note however that GCC honors #error
, still producing the deps, but returning 1 (so the first make
errors out, but further ones work correctly). Maybe this could be better handled by skipping all conditional blocks entirely, still producing fatal errors encountered along the way?
... Overall, this sounds incredibly fragile, and I'm really not confident in this change, but it's largely a necessity if we want
Activity
Rangi42 commentedon Jul 4, 2021
"skipping all conditional blocks entirely" wouldn't allow cases like this:
ISSOtm commentedon Jul 4, 2021
Then how should they be handled? Conditionally evaluating all blocks won't work either for example due to macro arg expansion...
(As a side note, I feel like we're fighting an uphill battle regarding this due to not being able to run
-M
as a preprocessing step...)Rangi42 commentedon Jul 4, 2021
I'm not sure; pret uses a custom
scan_includes
tool that ignores all rgbasm semantics and just scans for lines starting withINCLUDE
/INCBIN
. (Which doesn't even let us do things likeINCLUDE "{VERSION}/foo.inc"
orINCBIN STRCAT("build/", "bar.bin")
.)The initial report sparking this gave this example:
Without
-M -MG
bothincbin
s complain about missing files; with-M -MG
the first is printed as a dependency but the second isn't. (sect_BinaryFile
callsfstk_FindFile
callsprintDep
; thensect_BinaryFile
can't open the file so complains and setsfailedOnMissingInclude = true
; I'm actually not sure why the secondincbin
isn't printed anyway by theif (generatedMissingIncludes) printDep(path);
clause infstk_FindFile
.)ISSOtm commentedon Jul 5, 2021
That's because
failedOnMissingInclude
causesYYACCEPT
in parser.yaaaaaa123456789 commentedon Jul 5, 2021
Dependency listing is one of those things where accurate output is more important than fast output. If a project relies on dependency output in its build system, inaccurate output might cause a file not to be rebuilt, leaving stale code/data in the final binary.
Scanning assembly files for inclusion statements is a trivial task if anyone wants to build a faster but simpler tool. (I once wrote a
scan_includes
equivalent in all of half an hour, testing included. In pure ISO C17.) RGBASM should be as correct as possible in this aspect — projects that want the faster behavior can easily implement it.daid commentedon Jul 5, 2021
Unless you have to deal with rgbds macros and equs.
I currently first run rgbasm and then append the resulting dependency file with a
grep + sed
to add all the extraincbin
statements as well, it's ugly, but it works in the common case.Depends on your definition of "correct". From my perspective, the current behavior is incorrect. I ask a file for it's dependencies, and it does not list all dependencies.
I had earlier questions about
-MP
behavior, and the reply I got back then was "current behavior matches gcc". And for this specific issue, the behavior does not match gcc. With-MG
gcc lists all includes, and process all defines it does have, and if any#error
is encountered it aborts with an error.That sounds like a really bad plan.
ISSOtm commentedon Jul 5, 2021
The counter-argument is "we don't use those, so our tool doesn't account for them". This is valid, as "this specific codebase doesn't use these features" lets you optimize for their lack. However, they introduce additional dependencies (typically Python or a C compiler), so removing their need would be useful.
You are correct, but this is by necessity. C dependency generation is performed by the preprocessor, which only cares about its own syntax:
And in addition, the preproc's syntax is not context-sensitive; that is, a C file can be correctly parsed (by the preproc) even when some of the files to be included are missing. (I believe
#if
etc. blocks cannot "straddle" files, but correct me on that if I'm wrong.)RGBASM is not so lucky due to
EQUS
.The rest of the syntax can largely be handled: treat "required" yet non-existent variables as 0, ignore macros, etc. But the lack of an
EQUS
can (and likely will) introduce parsing errors.Even then, since macros can generate
INCLUDE
s, dependencies can be hidden even when not transitive (a.asm
defines a macroninja
thatINCLUDE "c.inc"
, includesb.inc
which definessamurai EQUS "ninja"
, thena.asm
callssamurai
as if it were a macro. Contrived? Certainly.)The presence or absence of an
INCBIN
can be easily tested for as well, since the file's size is not known, therefore PC must advance by some number. This can further alter the chain in non-obvious ways, more than justFAIL
or trippingassert
s (assert @ - DataStart == $1234, "File does not have expected size"
). How should those be handled?Since it appears that ignoring all
IF
s is wrong, then that should be restricted to allIF
s whose expression generates a syntax error, I guess. Though introducing more behavioral differences between normal parsing and after a dependency turned out to be missing is a can of worms that I'm definitely not opening.All in all, the lack of robustness in RGBASM programs is why the current behavior is what it is: after a failed
INCBIN
, and even moreso a failedINCLUDE
, here be dragons. Only one dependency is currently listed per invocation out of necessity, not laziness. Even reporting syntax errors (gcc -MM -MG
still errors out while printing nothing if the file contains#if defined(kaboom
!) is not reliable, so reportingFAIL
s as well does not sound like a good idea.This could be improved while staying relatively simple and safe: only abort on the first conditional block or fatal error after a missing dep, which would at least account for a chain of
INCBIN
s not followed by strict assertions, and someINCLUDE
chains.aaaaaa123456789 commentedon Jul 5, 2021
A fully accurate mode could be introduced by adding a flag that simply assembles the input into
/dev/null
and outputs the list of files it read. This will obviously be very slow, but also 100% correct (bar any randomness in the input) for any method that needs that, such as @daid's tool.I'm not sure of whether this would be worth it, though.
ISSOtm commentedon Jul 5, 2021
I've just explained that it is not possible to assemble the input without the dependencies in the general case.
To do so in one go, RGBASM would need to be able to invoke the command responsible for generating the file, and proceed once the file has been generated. (This would flip the paradigm from RGBASM telling
make
what it needs to RGBASM invokingmake
itself, though I've proposed this idea long ago and it was shot down by ax6.)daid commentedon Jul 5, 2021
I disagree, as without
-MG
the parsing continues after a missing incbin. So it can continue, but decides not to. For some extreme edge case reasons.ISSOtm commentedon Jul 5, 2021
Parsing continues after a failed
INCBIN
as "current state known to be incorrect, let's try reporting more errors for this batch";-MG
instead tries to avoid being incorrect, so it aborts immediately. Again, I agree this is worth changing, what do you think about the changes I suggested above?28 remaining items