run.c (9943B)
1 /* 2 * Top-level orchestration: install default macros/rules, import command-line, 3 * MAKEFLAGS, and environment macros, read the makefiles, build the child 4 * environment (with the outgoing MAKEFLAGS so recursive make keeps its flags), 5 * then bring the requested targets up to date. This is pdpmake main() minus the 6 * CLI/getopt machinery (now in driver/cmd/make.c). Part of the src/api/make.c 7 * amalgamation. 8 */ 9 #include "make.h" 10 11 static char* mk_slice_dup(MakeCtx* mc, KitSlice s) { 12 char* t = mk_alloc(mc, s.len + 1); 13 if (s.len) memcpy(t, s.s, s.len); 14 t[s.len] = '\0'; 15 return t; 16 } 17 18 /* Look up NAME in the ambient environment; return its value or NULL. */ 19 static const char* mk_getenv(MakeCtx* mc, const char* name) { 20 size_t nlen = strlen(name); 21 const char* const* e; 22 if (!mc->ambient) return NULL; 23 for (e = mc->ambient; *e; ++e) 24 if (strncmp(*e, name, nlen) == 0 && (*e)[nlen] == '=') return *e + nlen + 1; 25 return NULL; 26 } 27 28 /* 29 * If the option flag for a special target isn't set, mark its prerequisites; 30 * if the target had no prerequisites, set the global option flag. 31 */ 32 static void mk_mark_special(MakeCtx* mc, const char* special, uint32_t oflag, 33 uint16_t nflag) { 34 struct name* np; 35 struct rule* rp; 36 struct depend* dp; 37 int marked = FALSE; 38 39 if (!(mc->opts & oflag) && (np = mk_findname(mc, special))) { 40 for (rp = np->n_rule; rp; rp = rp->r_next) { 41 for (dp = rp->r_dep; dp; dp = dp->d_next) { 42 dp->d_name->n_flag |= nflag; 43 marked = TRUE; 44 } 45 } 46 if (!marked) mc->opts |= oflag; 47 } 48 } 49 50 /* Import NAME=VALUE entries from the environment as level-3 macros. */ 51 static void mk_import_env(MakeCtx* mc) { 52 const char* const* e; 53 54 if (!mc->ambient) return; 55 for (e = mc->ambient; *e; ++e) { 56 const char* eq = strchr(*e, '='); 57 char* name; 58 if (!eq || eq == *e) continue; 59 name = mk_strndup(mc, *e, (size_t)(eq - *e)); 60 /* Exceptions for particular environment values (see pdpmake). */ 61 if (strcmp(name, "MAKEFLAGS") == 0 || strcmp(name, "SHELL") == 0) continue; 62 if (strcmp(name, "CURDIR") == 0 && !useenv && !POSIX_2017) continue; 63 mk_setmacro(mc, name, eq + 1, 3 | M_ENVIRON); 64 } 65 } 66 67 /* 68 * Parse the incoming MAKEFLAGS environment variable: whitespace-separated 69 * tokens are either option letters (merged into mc->opts) or NAME=VALUE macro 70 * definitions (level 2). This is how a recursive `make` inherits the flags and 71 * macros of its parent. (Escaped blanks in values are not handled in v1.) 72 */ 73 static void mk_makeflags_in(MakeCtx* mc) { 74 const char* mf = mk_getenv(mc, "MAKEFLAGS"); 75 char* dup; 76 char* q; 77 char* tok; 78 79 if (!mf || !*mf) return; 80 dup = mk_strdup(mc, mf); 81 q = dup; 82 while ((tok = mk_gettok(&q)) != NULL) { 83 char* eq = strchr(tok, '='); 84 if (eq && eq != tok) { 85 *eq = '\0'; 86 mk_setmacro(mc, tok, eq + 1, 2); 87 } else { 88 const char* p = tok; 89 if (*p == '-') ++p; 90 for (; *p; ++p) { 91 switch (*p) { 92 case 'e': mc->opts |= OPT_e; break; 93 case 'i': mc->opts |= OPT_i; break; 94 case 'k': mc->opts |= OPT_k; break; 95 case 'n': mc->opts |= OPT_n; break; 96 case 'q': mc->opts |= OPT_q; break; 97 case 'r': mc->opts |= OPT_r; break; 98 case 's': mc->opts |= OPT_s; break; 99 case 't': mc->opts |= OPT_t; break; 100 default: break; /* ignore unknown (e.g. -j and its digits) */ 101 } 102 } 103 } 104 } 105 } 106 107 /* Backslash-escape blanks and backslashes for embedding in MAKEFLAGS. */ 108 static char* mk_escape_value(MakeCtx* mc, const char* val) { 109 size_t n = 0; 110 size_t i; 111 size_t j = 0; 112 char* out; 113 for (i = 0; val[i]; ++i) 114 n += (val[i] == '\\' || val[i] == ' ' || val[i] == '\t') ? 2 : 1; 115 out = mk_alloc(mc, n + 1); 116 for (i = 0; val[i]; ++i) { 117 if (val[i] == '\\' || val[i] == ' ' || val[i] == '\t') out[j++] = '\\'; 118 out[j++] = val[i]; 119 } 120 out[j] = '\0'; 121 return out; 122 } 123 124 /* 125 * Build the child environment vector used to launch recipes: the ambient 126 * environment (minus MAKEFLAGS), the outgoing MAKEFLAGS (option flags plus 127 * level-1/2 macros), and the command-line (level-1) macros exported as 128 * individual variables. Stored in mc->env. 129 */ 130 static void mk_build_child_env(MakeCtx* mc) { 131 static const struct { 132 uint32_t bit; 133 const char* flag; 134 } fl[] = {{OPT_e, "-e"}, {OPT_i, "-i"}, {OPT_k, "-k"}, {OPT_n, "-n"}, 135 {OPT_q, "-q"}, {OPT_r, "-r"}, {OPT_s, "-s"}, {OPT_t, "-t"}}; 136 char* mf = NULL; 137 int i; 138 size_t k; 139 struct macro* mp; 140 size_t n_ambient = 0; 141 size_t n_export = 0; 142 size_t count = 0; 143 const char* const* e; 144 KitExecKV* env; 145 146 for (k = 0; k < sizeof fl / sizeof fl[0]; ++k) 147 if (mc->opts & fl[k].bit) mf = mk_appendword(mc, mf, fl[k].flag); 148 for (i = 0; i < HTABSIZE; ++i) 149 for (mp = mc->macrohead[i]; mp; mp = mp->m_next) 150 if ((mp->m_level == 1 || mp->m_level == 2) && 151 strcmp(mp->m_name, "MAKEFLAGS") != 0) 152 mf = mk_appendword( 153 mc, mf, 154 mk_concat3(mc, mp->m_name, "=", mk_escape_value(mc, mp->m_val))); 155 if (!mf) mf = mk_strdup(mc, ""); 156 /* Also expose it as the MAKEFLAGS macro so $(MAKEFLAGS) expands. */ 157 mk_setmacro(mc, "MAKEFLAGS", mf, 0); 158 159 if (mc->ambient) 160 for (e = mc->ambient; *e; ++e) 161 if (strncmp(*e, "MAKEFLAGS=", 10) != 0) n_ambient++; 162 for (i = 0; i < HTABSIZE; ++i) 163 for (mp = mc->macrohead[i]; mp; mp = mp->m_next) 164 if (mp->m_level == 1 && strcmp(mp->m_name, "SHELL") != 0 && 165 strcmp(mp->m_name, "MAKEFLAGS") != 0) 166 n_export++; 167 168 env = mk_alloc(mc, (n_ambient + n_export + 1) * sizeof *env); 169 if (mc->ambient) 170 for (e = mc->ambient; *e; ++e) { 171 const char* eq; 172 if (strncmp(*e, "MAKEFLAGS=", 10) == 0) continue; 173 eq = strchr(*e, '='); 174 if (!eq) continue; 175 env[count].key.s = *e; 176 env[count].key.len = (size_t)(eq - *e); 177 env[count].value = kit_slice_cstr(eq + 1); 178 count++; 179 } 180 env[count].key = kit_slice_cstr("MAKEFLAGS"); 181 env[count].value = kit_slice_cstr(mf); 182 count++; 183 for (i = 0; i < HTABSIZE; ++i) 184 for (mp = mc->macrohead[i]; mp; mp = mp->m_next) 185 if (mp->m_level == 1 && strcmp(mp->m_name, "SHELL") != 0 && 186 strcmp(mp->m_name, "MAKEFLAGS") != 0) { 187 env[count].key = kit_slice_cstr(mp->m_name); 188 env[count].value = kit_slice_cstr(mp->m_val); 189 count++; 190 } 191 mc->env = env; 192 mc->nenv = count; 193 } 194 195 /* Read one makefile source into the graph (name is for diagnostics only). */ 196 static void mk_read_source(MakeCtx* mc, const char* name, MakeSource* src) { 197 mc->makefile = name; 198 mk_input(mc, src, 0); 199 mc->makefile = NULL; 200 } 201 202 /* Read a makefile by path (resolved against root) through file_io. */ 203 static int mk_read_path(MakeCtx* mc, const char* path, int required) { 204 const KitFileIO* io = mc->ctx->file_io; 205 KitFileData fd; 206 MakeSource src; 207 208 fd.data = NULL; 209 fd.size = 0; 210 fd.token = NULL; 211 if (!io || io->read_all(io->user, mk_path(mc, path), &fd) != KIT_OK) { 212 if (required) mk_error(mc, "can't open %s", path); 213 return 0; 214 } 215 src.data = (const char*)fd.data; 216 src.len = fd.size; 217 src.pos = 0; 218 mk_read_source(mc, path, &src); 219 if (io->release) io->release(io->user, &fd); 220 return 1; 221 } 222 223 static int mk_run(MakeCtx* mc) { 224 const KitMakeOptions* o = mc->mkopts; 225 MakeSource builtin = {NULL, 0, 0}; 226 struct macro* shell_mp; 227 size_t i; 228 int estat; 229 int found_target; 230 231 mc->myname = "make"; 232 mk_setmacro(mc, "$", "$", 0 | M_VALID); 233 234 /* Macro definitions from the command line (highest precedence, level 1). */ 235 for (i = 0; i < o->nmacros; ++i) { 236 char* name = mk_slice_dup(mc, o->macros[i].name); 237 char* val = mk_slice_dup(mc, o->macros[i].value); 238 mk_setmacro(mc, name, val, 1); 239 } 240 241 /* MAKEFLAGS from the environment: option flags + macros (level 2). */ 242 mk_makeflags_in(mc); 243 244 /* Macro definitions from the environment (level 3). */ 245 mk_import_env(mc); 246 247 /* Built-in rules. */ 248 mk_input(mc, &builtin, 0); 249 250 /* SHELL / MAKE / CURDIR (level 4; a makefile can still override SHELL). */ 251 mk_setmacro(mc, "SHELL", mc->shell ? mc->shell : "/bin/sh", 4); 252 mk_setmacro(mc, "MAKE", "make", 4); 253 if (mc->root && !POSIX_2017) mk_setmacro(mc, "CURDIR", mc->root, 4); 254 255 /* User makefiles (paths resolved against root; no chdir). */ 256 if (o->nmakefiles == 0) { 257 const char* names[3]; 258 int nn = 0; 259 int opened = 0; 260 int k; 261 if (!mc->posix) names[nn++] = "PDPmakefile"; 262 names[nn++] = "makefile"; 263 names[nn++] = "Makefile"; 264 for (k = 0; k < nn && !opened; ++k) opened = mk_read_path(mc, names[k], 0); 265 if (!opened) mk_error(mc, "no makefile found"); 266 } else { 267 for (i = 0; i < o->nmakefiles; ++i) { 268 const char* fn = o->makefiles[i]; 269 if (strcmp(fn, "-") == 0) { 270 MakeSource src; 271 src.data = (const char*)o->stdin_makefile; 272 src.len = o->stdin_makefile_len; 273 src.pos = 0; 274 mk_read_source(mc, "stdin", &src); 275 } else { 276 mk_read_path(mc, fn, TRUE); 277 } 278 } 279 } 280 281 /* Honor a makefile-provided SHELL for recipe execution. */ 282 shell_mp = mk_getmp(mc, "SHELL"); 283 if (shell_mp && shell_mp->m_val[0]) mc->shell = shell_mp->m_val; 284 285 if (print) mk_print_details(mc); 286 287 mk_mark_special(mc, ".SILENT", OPT_s, N_SILENT); 288 mk_mark_special(mc, ".IGNORE", OPT_i, N_IGNORE); 289 mk_mark_special(mc, ".PRECIOUS", OPT_precious, N_PRECIOUS); 290 if (!POSIX_2017) mk_mark_special(mc, ".PHONY", OPT_phony, N_PHONY); 291 292 /* Assemble the recipe environment now that all macros/flags are known. */ 293 mk_build_child_env(mc); 294 295 /* Build the requested targets (or the default goal). */ 296 estat = 0; 297 found_target = FALSE; 298 for (i = 0; i < o->ntargets; ++i) { 299 found_target = TRUE; 300 estat |= mk_make(mc, mk_newname(mc, o->targets[i]), 0); 301 } 302 if (!found_target) { 303 if (!mc->firstname) mk_error(mc, "no targets defined"); 304 estat = mk_make(mc, mc->firstname, 0); 305 } 306 307 return estat & MAKE_FAILURE; 308 }