kit

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

make.h (11712B)


      1 #ifndef KIT_MAKE_INTERNAL_H
      2 #define KIT_MAKE_INTERNAL_H
      3 
      4 /*
      5  * Internal header for the make engine ported from the public-domain pdpmake
      6  * (rmyorston/pdpmake).
      7  *
      8  * Amalgamation. The engine is compiled as ONE translation unit: src/api/make.c
      9  * includes each engine fragment (src/make/<part>.c) after this header. Every
     10  * engine function is `static`, so none of pdpmake's generic names (error,
     11  * input, make, target, ...) escapes into libkit's symbol space.
     12  *
     13  * No global state. Every pdpmake global now lives in MakeCtx, which is threaded
     14  * as the first parameter `mc` of every engine function that touches shared
     15  * state. The read-only option predicates below (dryrun, silent, ...) are the
     16  * one sanctioned convenience macro family; they read mc->opts and therefore
     17  * require `mc` to be in scope (it always is -- it is the first parameter).
     18  *
     19  * No libc/OS calls. Memory comes from an arena (mk_alloc et al.); makefile and
     20  * archive bytes are read through KitContext.file_io; recipe execution, file
     21  * modification times, touch, and remove arrive through the KitMakeHost vtable;
     22  * output goes to KitWriter sinks; a fatal error longjmps back to kit_make_run
     23  * instead of calling exit().
     24  */
     25 
     26 #include <kit/core.h>
     27 #include <kit/make.h>
     28 
     29 #include <ctype.h>
     30 #include <limits.h>
     31 #include <setjmp.h>
     32 #include <stdarg.h>
     33 #include <stdbool.h>
     34 #include <stddef.h>
     35 #include <stdint.h>
     36 #include <stdio.h>
     37 #include <string.h>
     38 
     39 #include "core/arena.h"
     40 
     41 /* pdpmake feature selection: extensions + POSIX-2024 both on (its defaults). */
     42 #define ENABLE_FEATURE_MAKE_EXTENSIONS 1
     43 #define ENABLE_FEATURE_MAKE_POSIX_2024 1
     44 #define IF_FEATURE_MAKE_EXTENSIONS(...) __VA_ARGS__
     45 #define IF_NOT_FEATURE_MAKE_EXTENSIONS(...)
     46 #define IF_FEATURE_MAKE_POSIX_2024(...) __VA_ARGS__
     47 #define IF_NOT_FEATURE_MAKE_POSIX_2024(...)
     48 
     49 #define STD_POSIX_2017 0
     50 #define STD_POSIX_2024 1
     51 #define DEFAULT_POSIX_LEVEL STD_POSIX_2024
     52 
     53 #ifndef TRUE
     54 #define TRUE (1)
     55 #define FALSE (0)
     56 #endif
     57 #define MAX(a, b) ((a) > (b) ? (a) : (b))
     58 
     59 #define HTABSIZE 199
     60 
     61 /* ---- data structures (verbatim from pdpmake, layout preserved) ----------- */
     62 
     63 /* A file, either to be made or pre-existing. A timespec models the mtime; the
     64  * host reports mtime in ns, which mk_modtime splits into sec/nsec. */
     65 struct mk_timespec {
     66   int64_t tv_sec;
     67   int64_t tv_nsec;
     68 };
     69 
     70 struct name {
     71   struct name* n_next; /* next in hash chain */
     72   char* n_name;
     73   struct rule* n_rule; /* rules to build this */
     74   struct mk_timespec n_tim;
     75   uint16_t n_flag;
     76 };
     77 
     78 #define N_DOING 0x01     /* being built */
     79 #define N_DONE 0x02      /* looked at */
     80 #define N_TARGET 0x04    /* is a target */
     81 #define N_PRECIOUS 0x08  /* precious */
     82 #define N_DOUBLE 0x10    /* double-colon target */
     83 #define N_SILENT 0x20    /* build silently */
     84 #define N_IGNORE 0x40    /* ignore build errors */
     85 #define N_SPECIAL 0x80   /* special target */
     86 #define N_MARK 0x100     /* mark for deduplication */
     87 #define N_PHONY 0x200    /* phony target */
     88 #define N_INFERENCE 0x400 /* inference rule */
     89 
     90 struct rule {
     91   struct rule* r_next;
     92   struct depend* r_dep; /* prerequisites */
     93   struct cmd* r_cmd;    /* commands */
     94 };
     95 
     96 struct depend {
     97   struct depend* d_next;
     98   struct name* d_name;
     99   int d_refcnt;
    100 };
    101 
    102 struct cmd {
    103   struct cmd* c_next;
    104   char* c_cmd;
    105   int c_refcnt;
    106   const char* c_makefile;
    107   int c_dispno;
    108 };
    109 
    110 struct macro {
    111   struct macro* m_next;
    112   char* m_name;
    113   char* m_val;
    114   bool m_immediate; /* set with ::= */
    115   bool m_flag;      /* infinite-loop guard */
    116   uint8_t m_level;  /* level at which created */
    117 };
    118 
    119 /* Flags to mk_setmacro (packed into the level argument). */
    120 #define M_IMMEDIATE 0x08
    121 #define M_VALID 0x10
    122 #define M_ENVIRON 0x20
    123 
    124 /* .PRAGMA bits. Order must match p_name[] in target.c. */
    125 enum {
    126   BIT_MACRO_NAME = 0,
    127   BIT_TARGET_NAME,
    128   BIT_COMMAND_COMMENT,
    129   BIT_EMPTY_SUFFIX,
    130   BIT_POSIX_2017,
    131   BIT_POSIX_2024,
    132   BIT_POSIX_202X,
    133 
    134   P_MACRO_NAME = (1 << BIT_MACRO_NAME),
    135   P_TARGET_NAME = (1 << BIT_TARGET_NAME),
    136   P_COMMAND_COMMENT = (1 << BIT_COMMAND_COMMENT),
    137   P_EMPTY_SUFFIX = (1 << BIT_EMPTY_SUFFIX)
    138 };
    139 
    140 /* Option bits (mc->opts). The public KIT_MAKE_F_* flags map onto these in
    141  * run.c; the extra bits (precious/phony/include/make) are engine-internal. */
    142 enum {
    143   OPTBIT_e = 0,
    144   OPTBIT_i,
    145   OPTBIT_k,
    146   OPTBIT_n,
    147   OPTBIT_q,
    148   OPTBIT_r,
    149   OPTBIT_s,
    150   OPTBIT_t,
    151   OPTBIT_p,
    152   OPTBIT_precious,
    153   OPTBIT_phony,
    154   OPTBIT_include,
    155   OPTBIT_make,
    156 
    157   OPT_e = (1 << OPTBIT_e),
    158   OPT_i = (1 << OPTBIT_i),
    159   OPT_k = (1 << OPTBIT_k),
    160   OPT_n = (1 << OPTBIT_n),
    161   OPT_q = (1 << OPTBIT_q),
    162   OPT_r = (1 << OPTBIT_r),
    163   OPT_s = (1 << OPTBIT_s),
    164   OPT_t = (1 << OPTBIT_t),
    165   OPT_p = (1 << OPTBIT_p),
    166   OPT_precious = (1 << OPTBIT_precious),
    167   OPT_phony = (1 << OPTBIT_phony),
    168   OPT_include = (1 << OPTBIT_include),
    169   OPT_make = (1 << OPTBIT_make)
    170 };
    171 
    172 /* make() return status. */
    173 #define MAKE_FAILURE 0x01
    174 #define MAKE_DIDSOMETHING 0x02
    175 
    176 /* Conditional-directive nesting (ifdef/ifeq...). */
    177 #define MK_IF_MAX 10
    178 
    179 /* An input source for the parser: either an in-memory makefile buffer (data !=
    180  * NULL, read line by line from pos) or, when data == NULL, the built-in rules
    181  * generated by mk_getrules. */
    182 typedef struct MakeSource {
    183   const char* data;
    184   size_t len;
    185   size_t pos;
    186 } MakeSource;
    187 
    188 /* The engine context: every former pdpmake global, plus the injected host. */
    189 typedef struct MakeCtx {
    190   /* injected substrate */
    191   const KitContext* ctx;   /* heap / file_io / diag / now (borrowed) */
    192   const KitMakeHost* host; /* mtime / run_recipe / capture / touch / remove */
    193   const KitMakeOptions* mkopts; /* makefiles / targets / macros / flags */
    194   Arena arena;             /* all engine allocations */
    195   KitWriter* out;          /* stdout: recipe echo, -p, -n */
    196   KitWriter* err;          /* stderr: make diagnostics */
    197 
    198   /* error handling: mk_error/mk_exit longjmp here; kit_make_run reads code */
    199   jmp_buf jmpbuf;
    200   int exit_code;
    201 
    202   /* recipe launch context */
    203   const KitExecKV* env; /* child env for recipes (KitExecKV pairs, run.c) */
    204   size_t nenv;
    205   const char* const* ambient; /* borrowed ambient NAME=VALUE (from options) */
    206   const char* root;  /* absolute working dir: path root, recipe cwd, $(CURDIR) */
    207   const char* shell; /* recipe shell (SHELL macro, default /bin/sh) */
    208 
    209   /* former globals */
    210   struct name* namehead[HTABSIZE];
    211   struct macro* macrohead[HTABSIZE];
    212   struct name* firstname; /* default goal */
    213   struct name* target;    /* target currently being built (for remove) */
    214   uint32_t opts;
    215   int lineno;
    216   int dispno;
    217   struct cmd* curr_cmd;
    218   const char* makefile; /* current makefile name (diagnostics) */
    219   const char* myname;   /* "make" */
    220   bool posix;
    221   bool seen_first;
    222   unsigned char pragma;
    223   unsigned char posix_level;
    224 
    225   /* conditional-directive state (was file statics in input.c) */
    226   uint8_t clevel;
    227   uint8_t cstate[MK_IF_MAX + 1];
    228 
    229   /* built-in rules generator state (was function statics in rules.c) */
    230   const char* rulepos;
    231   int rule_idx;
    232 } MakeCtx;
    233 
    234 /* Read-only option predicates. Require `mc` in scope (always the first
    235  * parameter of an engine function). */
    236 #define useenv (mc->opts & OPT_e)
    237 #define ignore (mc->opts & OPT_i)
    238 #define errcont (mc->opts & OPT_k)
    239 #define dryrun (mc->opts & OPT_n)
    240 #define print (mc->opts & OPT_p)
    241 #define quest (mc->opts & OPT_q)
    242 #define norules (mc->opts & OPT_r)
    243 #define silent (mc->opts & OPT_s)
    244 #define dotouch (mc->opts & OPT_t)
    245 #define precious (mc->opts & OPT_precious)
    246 #define doinclude (mc->opts & OPT_include)
    247 #define domake (mc->opts & OPT_make)
    248 
    249 #define POSIX_2017 (mc->posix && mc->posix_level == STD_POSIX_2017)
    250 
    251 /* Character-class predicates for names. */
    252 #define ispname(c) (isalpha(c) || isdigit(c) || (c) == '.' || (c) == '_')
    253 #define isfname(c) (ispname(c) || (c) == '-')
    254 
    255 /* ---- memory + diagnostics + output helpers (utils.c) --------------------- */
    256 
    257 static void* mk_alloc(MakeCtx* mc, size_t n);
    258 static void* mk_realloc(MakeCtx* mc, void* p, size_t oldn, size_t newn);
    259 static char* mk_strdup(MakeCtx* mc, const char* s);
    260 static char* mk_strndup(MakeCtx* mc, const char* s, size_t n);
    261 static char* mk_concat3(MakeCtx* mc, const char* a, const char* b,
    262                         const char* c);
    263 static char* mk_appendword(MakeCtx* mc, const char* str, const char* word);
    264 
    265 #define MK_NORETURN __attribute__((noreturn))
    266 static void mk_exit(MakeCtx* mc, int code) MK_NORETURN; /* longjmp, no message */
    267 static void mk_error(MakeCtx* mc, const char* fmt, ...)
    268     MK_NORETURN; /* message + mk_exit(2) */
    269 static void mk_warning(MakeCtx* mc, const char* fmt, ...);
    270 static void mk_diagnostic(MakeCtx* mc, const char* fmt, ...);
    271 static void mk_error_unexpected(MakeCtx* mc, const char* s) MK_NORETURN;
    272 static void mk_error_in_inference_rule(MakeCtx* mc, const char* s) MK_NORETURN;
    273 static void mk_error_not_allowed(MakeCtx* mc, const char* s, const char* t)
    274     MK_NORETURN;
    275 
    276 static void mk_out(MakeCtx* mc, const char* s);            /* to mc->out */
    277 static void mk_out_bytes(MakeCtx* mc, const char* p, size_t n);
    278 static void mk_outc(MakeCtx* mc, char c);
    279 static void mk_outf(MakeCtx* mc, const char* fmt, ...);    /* to mc->out */
    280 
    281 static unsigned mk_getbucket(const char* name);
    282 
    283 /* Resolve `name` against mc->root (a relative name gets joined to root; an
    284  * absolute name or a NULL root is returned unchanged). Used for every path the
    285  * engine hands to a host file op, so make never chdir()s. */
    286 static const char* mk_path(MakeCtx* mc, const char* name);
    287 
    288 /* ---- macro.c ------------------------------------------------------------- */
    289 static struct macro* mk_getmp(MakeCtx* mc, const char* name);
    290 static void mk_setmacro(MakeCtx* mc, const char* name, const char* val,
    291                         int level);
    292 
    293 /* ---- target.c ------------------------------------------------------------ */
    294 static struct depend* mk_newdep(MakeCtx* mc, struct name* np,
    295                                 struct depend* dphead);
    296 static struct cmd* mk_newcmd(MakeCtx* mc, char* str, struct cmd* cphead);
    297 static struct name* mk_findname(MakeCtx* mc, const char* name);
    298 static struct name* mk_newname(MakeCtx* mc, const char* name);
    299 static struct cmd* mk_getcmd(struct name* np);
    300 static void mk_freerules(struct rule* rp);
    301 static int mk_is_valid_target(MakeCtx* mc, const char* name);
    302 static void mk_set_pragma(MakeCtx* mc, const char* name);
    303 static void mk_addrule(MakeCtx* mc, struct name* np, struct depend* dp,
    304                        struct cmd* cp, int flag);
    305 
    306 /* ---- check.c ------------------------------------------------------------- */
    307 static void mk_print_details(MakeCtx* mc);
    308 
    309 /* ---- rules.c ------------------------------------------------------------- */
    310 static char* mk_suffix(const char* name);
    311 static char* mk_has_suffix(MakeCtx* mc, const char* name, const char* suffix);
    312 static struct name* mk_dyndep(MakeCtx* mc, struct name* np,
    313                               struct rule* infrule, const char** ptsuff);
    314 static char* mk_getrules(MakeCtx* mc, char* s, int size);
    315 
    316 /* ---- input.c ------------------------------------------------------------- */
    317 static char* mk_expand_macros(MakeCtx* mc, const char* str, int except_dollar);
    318 static const char* mk_is_suffix(MakeCtx* mc, const char* s);
    319 static void mk_input(MakeCtx* mc, MakeSource* src, int ilevel);
    320 
    321 /* ---- modtime.c ----------------------------------------------------------- */
    322 static char* mk_splitlib(MakeCtx* mc, const char* name, char** member);
    323 static void mk_modtime(MakeCtx* mc, struct name* np);
    324 
    325 /* ---- build.c ------------------------------------------------------------- */
    326 static void mk_remove_target(MakeCtx* mc);
    327 static int mk_make(MakeCtx* mc, struct name* np, int level);
    328 
    329 /* ---- run.c --------------------------------------------------------------- */
    330 static int mk_run(MakeCtx* mc);
    331 
    332 #endif