[Toybox] Debugging "infrastructure" breakage, an example.

Rob Landley rob at landley.net
Tue Jul 16 22:06:54 PDT 2013


I'm adding a new command, timeout, cloned from sleep.c instead of  
hello.c.
(Somebody did a bug report on the busybox list about timeout, and I went
"there's a timeout command now?" Hey, means I can yank more/timeout.sh  
in
Aboriginal Linux, I'm all for it.)

Initially I tried to do it as an OLDTOY() alias of sleep (to re-use the
seconds/minutes/hours/days fractional parsing logic), but wound
up factoring common code out into lib/ instead, and making timeout its
own command with its own toys/other/timeout.c file.

The build broke, even after doing "make defconfig", and that usually  
means I'm
missing a semicolon after a function I added to lib/lib.h or something.
And _when_ the toybox build breaks in the generated/* shared  
infrastructure,
you get pages of nonsense.

Here's how you fix it. The trick is:

   make 2>&1 | less

And then look at the _first_ break. Due to the "gcc lib/*.c toys/*/*.c"  
nature
of the build, it's going to give pages and pages and pages of errors  
for anything
wrong in the infrastructure, losing its marbles in the middle of  
parsing large
tables and deciding everything after that is out to get it.

But the first failure is the one confusing it. The rest is just flying  
shrapnel.
In this case,

   Compile toybox...
   In file included from toys.h:65:0,
                    from main.c:6:
   generated/newtoys.h:113:1: warning: return type defaults to 'int'

"This is just a warning," you say? But it's pointing out where we went  
wrong.

In generated/newtoys.h line 113 we have:

   USE_TIMEOUT(NEWTOY(timeout, "<2k:s: ", TOYFLAG_BIN))

This macro is expanded in several different places to mean several
different things. In the warning we got there through toys.h line 65,
which is the first include in:

   // Get list of function prototypes for all enabled command_main()  
functions.

   #define NEWTOY(name, opts, flags) void name##_main(void);
   #define OLDTOY(name, oldname, opts, flags)
   #include "generated/newtoys.h"
   #include "generated/globals.h"

A prototype should _not_ be giving us a warning, which that implies  
that the
USE_TIMEOUT() macro isn't converting into a prototype, most likely  
because
the macro isn't actually being defined (so the compiler thinks it's a  
function
call, and warns us we didn't prototype that function call).

A grep of generated/config.h confirms this: USE_TIMEOUT is not there.

The macro is generated from the config symbol, and _that_ means I  
probably
typoed the config symbol name. Which I did: I still have it as  
SLEEP_TIMEOUT
from when it was an alias of sleep. I used USE_TIMEOUT in the NEWTOY  
line
but no config symbol is providing USE_TIMEOUT, hence it thinks there's a
function call in the middle of the function prototype list for all the
command_main() prototypes, and hilarity ensues.

(Note that for a standlone file the top config symbol has to match the  
name
of the C file we're building so the makefile can select which source  
files
out of toys to build, and so what NEWTOY() and such are defining line  
up.
Since the config doesn't contain a TIMEOUT=y, it won't include  
toys/*/timeout.c
in the gcc command line, and thus the link would fail with no  
timeout_main()
assumign we could get that far. But we don't get that far because the  
macro
doesn't resolve, so the build breaks way earlier.)

The fix is to rename the config symbol to what it should be, and upon  
fixing that:

Compile toybox...
toys/posix/sleep.c: In function 'sleep_main':
toys/posix/sleep.c:34:3: warning: passing argument 2 of 'xparsetime'  
makes integer from pointer without a cast [enabled by default]
./lib/lib.h:123:6: note: expected 'long int' but argument is of type  
'long int *'
toys/posix/sleep.c:34:3: error: too few arguments to function  
'xparsetime'
./lib/lib.h:123:6: note: declared here
toys/other/timeout.c: In function 'timeout_main':
toys/other/timeout.c:36:23: warning: unused variable 'vcr'  
[-Wunused-variable]
toys/other/timeout.c:36:19: warning: unused variable 'tv'  
[-Wunused-variable]

Errors, but normal "unfinished C code, a bit of damage from splitting  
code out
of sleep, and some rough edges in the lib code I added". Not the pages  
of
hysterical infrastructure messages from a badly confused gcc.

Rob
 1374037614.0


More information about the Toybox mailing list