dev: cache the compiler build and drop unused headers

Every run rebuilt fec from scratch inside DOS, about 14 seconds, even when no
source had changed. Key a cache on the hash of fec/src plus build-dos.bat and
restore FEC.EXE when it matches; the toolchain itself is pinned by
dosboxx.lock.json so it cannot drift under a hit. Only a passing build is
cached, and the batch skips BUILD.BAT on a hit because it would delete and
rebuild the executable it was just given.

Generated C included stdio.h unconditionally, but only the M4 writer runtime
reaches it. A 26-line unit was pulling in roughly 1900 lines of headers, paid
once per compile check. Emit it only when the runtime is emitted.

--only m6, 57 passed, over three changes:

    31s   before
    17s   core=dynamic
     2s   warm compiler cache

Cold runs still pay the build once.
This commit is contained in:
2026-08-17 01:17:40 +09:00
parent aaf31302d5
commit 044c0f0e98
3 changed files with 41 additions and 4 deletions
+6 -1
View File
@@ -1487,7 +1487,12 @@ void fe_emit_c_program(FeEmitter *e)
need_m4=node_uses_m4(e->check->ast->root);
for (type=e->check->types.types; type; type=type->next)
if (strcmp(type->name,"io.Writer")==0) need_m4=1;
fputs("/* generated by fec M4 */\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\ntypedef char fe_assert_u8[(sizeof(unsigned char)==1) ? 1 : -1];\ntypedef char fe_assert_u16[(sizeof(unsigned short)==2) ? 1 : -1];\ntypedef char fe_assert_u32[(sizeof(unsigned long)==4) ? 1 : -1];\n", e->out);
/* stdio is only reached by the M4 writer runtime (fwrite/stdout/stderr).
Parsing it costs far more than the generated body -- a 26-line unit pulls
in about 1900 lines of headers -- so leave it out when nothing uses it. */
fputs("/* generated by fec M4 */\n#include <stddef.h>\n#include <stdlib.h>\n#include <string.h>\n", e->out);
if (need_m4) fputs("#include <stdio.h>\n", e->out);
fputs("typedef char fe_assert_u8[(sizeof(unsigned char)==1) ? 1 : -1];\ntypedef char fe_assert_u16[(sizeof(unsigned short)==2) ? 1 : -1];\ntypedef char fe_assert_u32[(sizeof(unsigned long)==4) ? 1 : -1];\n", e->out);
if (e->pointer_bits==16)
fputs("typedef char fe_assert_usize[(sizeof(unsigned short)==2) ? 1 : -1];\n",e->out);
else
+4 -1
View File
@@ -1327,7 +1327,10 @@ void fe_emit_c_program(FeEmitter *e)
need_m4=node_uses_m4(e->check->ast->root);
for (type=e->check->types.types;type;type=type->next)
if (strcmp(type->name,"io.Writer")==0) need_m4=1;
fputs("/* generated by fec M7 */\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\ntypedef char fe_assert_u8[(sizeof(unsigned char)==1) ? 1 : -1];\ntypedef char fe_assert_u16[(sizeof(unsigned short)==2) ? 1 : -1];\ntypedef char fe_assert_u32[(sizeof(unsigned long)==4) ? 1 : -1];\n",e->out);
/* See emit_c.c: stdio only comes in with the M4 writer runtime. */
fputs("/* generated by fec M7 */\n#include <stddef.h>\n#include <stdlib.h>\n#include <string.h>\n",e->out);
if (need_m4) fputs("#include <stdio.h>\n",e->out);
fputs("typedef char fe_assert_u8[(sizeof(unsigned char)==1) ? 1 : -1];\ntypedef char fe_assert_u16[(sizeof(unsigned short)==2) ? 1 : -1];\ntypedef char fe_assert_u32[(sizeof(unsigned long)==4) ? 1 : -1];\n",e->out);
if (e->pointer_bits==16)
fputs("typedef char fe_assert_usize[(sizeof(unsigned short)==2) ? 1 : -1];\n",e->out);
else