kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

make.c (2805B)


      1 /*
      2  * Public POSIX make API and engine amalgamation. See <kit/make.h>.
      3  *
      4  * The engine ported from pdpmake is split across several src/make fragments for
      5  * readability but compiled as ONE translation unit: this file includes each one,
      6  * so every engine function has internal (static) linkage and none of pdpmake's
      7  * generic names escapes into libkit. kit_make_run establishes the setjmp target
      8  * that the engine's fatal-error path (mk_error/mk_exit) longjmps back to, then
      9  * maps the make exit status into KitMakeResult.
     10  */
     11 
     12 #include <kit/make.h>
     13 
     14 #include "make/make.h"
     15 
     16 /* Engine fragments (all `static`; compiled only here). */
     17 #include "make/utils.c"  /* IWYU pragma: keep */
     18 #include "make/macro.c"  /* IWYU pragma: keep */
     19 #include "make/target.c" /* IWYU pragma: keep */
     20 #include "make/modtime.c" /* IWYU pragma: keep */
     21 #include "make/rules.c"  /* IWYU pragma: keep */
     22 #include "make/check.c"  /* IWYU pragma: keep */
     23 #include "make/input.c"  /* IWYU pragma: keep */
     24 #include "make/build.c"  /* IWYU pragma: keep */
     25 #include "make/run.c"    /* IWYU pragma: keep */
     26 
     27 static uint32_t make_opts_from_flags(uint32_t flags) {
     28   uint32_t o = 0;
     29   if (flags & KIT_MAKE_F_ENV_OVERRIDE) o |= OPT_e;
     30   if (flags & KIT_MAKE_F_IGNORE_ERR) o |= OPT_i;
     31   if (flags & KIT_MAKE_F_KEEP_GOING) o |= OPT_k;
     32   if (flags & KIT_MAKE_F_DRY_RUN) o |= OPT_n;
     33   if (flags & KIT_MAKE_F_PRINT_DB) o |= OPT_p;
     34   if (flags & KIT_MAKE_F_QUESTION) o |= OPT_q;
     35   if (flags & KIT_MAKE_F_NO_BUILTINS) o |= OPT_r;
     36   if (flags & KIT_MAKE_F_SILENT) o |= OPT_s;
     37   if (flags & KIT_MAKE_F_TOUCH) o |= OPT_t;
     38   return o;
     39 }
     40 
     41 KitStatus kit_make_run(const KitContext* ctx, const KitMakeHost* host,
     42                        const KitMakeOptions* opts, KitMakeResult* result) {
     43   MakeCtx mc;
     44 
     45   if (!ctx || !ctx->heap || !host || !opts || !result) return KIT_INVALID;
     46   if (!host->mtime || !host->exec || !host->exec->spawn || !host->exec->wait ||
     47       !host->touch || !host->remove_file)
     48     return KIT_INVALID;
     49 
     50   result->exit_code = 2;
     51 
     52   memset(&mc, 0, sizeof mc);
     53   mc.ctx = ctx;
     54   mc.host = host;
     55   mc.mkopts = opts;
     56   mc.out = opts->out;
     57   mc.err = opts->err;
     58   /* mc.env (KitExecKV pairs) is built by mk_build_child_env before recipes run;
     59    * until then it is NULL (from the memset). */
     60   mc.ambient = opts->env;
     61   mc.root = opts->curdir;
     62   mc.shell = opts->shell ? opts->shell : "/bin/sh";
     63   mc.myname = "make";
     64   mc.posix_level = DEFAULT_POSIX_LEVEL;
     65   mc.posix = (opts->flags & KIT_MAKE_F_POSIX) != 0;
     66   mc.opts = make_opts_from_flags(opts->flags);
     67 
     68   arena_init(&mc.arena, (Heap*)ctx->heap, 64u * 1024u);
     69 
     70   /* mc's address is taken (setjmp/&mc), so its fields survive the longjmp. */
     71   if (setjmp(mc.jmpbuf) == 0) mc.exit_code = mk_run(&mc);
     72 
     73   result->exit_code = mc.exit_code;
     74   arena_fini(&mc.arena);
     75   return KIT_OK;
     76 }